<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>@yield('title', 'Admin') — {{ config('cms.name') }}</title>
    @php $adminLogo = \App\Models\Setting::get('logo'); @endphp
    @if($adminLogo)
        <link rel="icon" href="{{ route('site.favicon') }}" type="image/png" sizes="64x64">
    @endif
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: { 50: '#f0fdf4', 100: '#dcfce7', 500: '#22c55e', 600: '#16a34a', 700: '#15803d' }
                    }
                }
            }
        }
    </script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cropperjs@1.6.2/dist/cropper.min.css">
    <style>
        body { font-family: 'Plus Jakarta Sans', system-ui, sans-serif; }
        #image-crop-modal .cropper-view-box, #image-crop-modal .cropper-face { border-radius: 0; }
        #image-crop-modal .cropper-container { max-height: 70vh; }
        #admin-sidebar.open { transform: translateX(0); }
        @media (min-width: 1024px) {
            #admin-sidebar-overlay { display: none !important; }
        }
    </style>
    @stack('head')
</head>
<body class="bg-slate-100 min-h-screen">
    @php
        $adminPrimary = \App\Models\Setting::get('primary_color', '#0ea5e9');
        $adminSecondary = \App\Models\Setting::get('secondary_color', '#6366f1');
    @endphp
    <div class="flex min-h-screen">
        <div id="admin-sidebar-overlay" class="fixed inset-0 bg-black/40 z-40 hidden lg:hidden" onclick="document.getElementById('admin-sidebar').classList.remove('open'); this.classList.add('hidden'); document.body.style.overflow='';" aria-hidden="true"></div>
        <aside id="admin-sidebar" class="fixed lg:relative inset-y-0 left-0 z-50 w-64 h-full max-h-screen bg-white flex flex-col shrink-0 shadow-xl lg:shadow-sm transform -translate-x-full lg:translate-x-0 transition-transform duration-300 ease-out overflow-hidden">
            <div class="p-4 lg:p-6 flex items-center justify-between lg:block shrink-0">
                <a href="{{ route('admin.dashboard') }}" class="flex items-center gap-3 group">
                    @if($adminLogo)
                        <img src="{{ asset('storage/'.$adminLogo) }}" alt="Logo" class="w-10 h-10 rounded-xl object-contain">
                    @else
                        <img src="{{ route('branding.logo') }}" alt="{{ config('cms.name') }}" class="w-10 h-10 rounded-xl object-contain bg-slate-900 p-1.5 shadow-md">
                    @endif
                    <div>
                        <span class="font-bold text-slate-800 block tracking-tight">{{ config('cms.name') }}</span>
                        <span class="text-xs text-slate-400 mt-0.5">Propulsé par GdevStudio</span>
                    </div>
                </a>
                <button type="button" class="lg:hidden p-2 -mr-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg" onclick="document.getElementById('admin-sidebar').classList.remove('open'); document.getElementById('admin-sidebar-overlay').classList.add('hidden'); document.body.style.overflow='';" aria-label="Fermer le menu">
                    <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
                </button>
            </div>
            <nav class="px-3 flex-1 min-h-0 overflow-y-auto space-y-1">
                <a href="{{ route('admin.dashboard') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.dashboard') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.dashboard')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.dashboard') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"/></svg>
                    Tableau de bord
                </a>
                <a href="{{ route('admin.pages.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.pages.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.pages.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.pages.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>
                    Pages
                </a>
                <a href="{{ route('admin.media.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.media.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.media.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.media.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
                    Médias
                </a>
                <a href="{{ route('admin.contact-messages.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.contact-messages.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.contact-messages.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.contact-messages.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>
                    Messages
                </a>
                @if(\App\Models\MarketplacePurchase::hasPurchased('plugin', 'forum'))
                <a href="{{ route('admin.forum.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.forum.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.forum.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.forum.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/></svg>
                    Forum
                </a>
                @endif
                @if(\App\Models\MarketplacePurchase::hasPurchased('plugin', 'ecommerce'))
                <a href="{{ route('admin.ecommerce.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.ecommerce.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.ecommerce.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.ecommerce.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/></svg>
                    E-commerce
                </a>
                @endif
                @if(\App\Models\MarketplacePurchase::hasPurchased('plugin', 'reservation'))
                <a href="{{ route('admin.reservation.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.reservation.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.reservation.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.reservation.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
                    Réservation
                </a>
                @endif
                @if(\App\Models\MarketplacePurchase::hasPurchased('plugin', 'newsletter'))
                <a href="{{ route('admin.newsletter.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.newsletter.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.newsletter.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.newsletter.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>
                    Newsletter
                </a>
                @endif
                @if(\App\Models\MarketplacePurchase::hasPurchased('plugin', 'banners'))
                <a href="{{ route('admin.banners.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.banners.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.banners.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.banners.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 4v16M17 4v16M3 8h4m10 0h4M3 12h18M3 16h4m10 0h4M4 20h16a1 1 0 001-1V5a1 1 0 00-1-1H4a1 1 0 00-1 1v14a1 1 0 001 1z"/></svg>
                    Bannières
                </a>
                @endif
                @if(\App\Models\MarketplacePurchase::hasPurchased('plugin', 'multilang'))
                <a href="{{ route('admin.multilang.settings') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.multilang.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.multilang.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.multilang.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129"/></svg>
                    Multilingue
                </a>
                @endif
                @if(\App\Models\MarketplacePurchase::hasPurchased('plugin', 'captcha-protection'))
                <a href="{{ route('admin.captcha-protection.settings') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.captcha-protection.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.captcha-protection.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.captcha-protection.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/></svg>
                    CAPTCHA
                </a>
                @endif
                <a href="{{ route('admin.appearance.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.appearance.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.appearance.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.appearance.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"/></svg>
                    Apparence
                </a>
                @if(auth()->user()->canManageUsers())
                <a href="{{ route('admin.users.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.users.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.users.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.users.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"/></svg>
                    Utilisateurs
                </a>
                <a href="{{ route('admin.settings.email') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.settings.email*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.settings.email*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.settings.email*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>
                    Email / SMTP
                </a>
                <a href="{{ route('admin.settings.legal-popup') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.settings.legal-popup*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.settings.legal-popup*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.settings.legal-popup*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/></svg>
                    RGPD / Popup légal
                </a>
                <a href="{{ route('admin.settings.analytics') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.settings.analytics*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.settings.analytics*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.settings.analytics*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/></svg>
                    Google Analytics
                </a>
                <a href="{{ route('admin.marketplace.index') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.marketplace.*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.marketplace.*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.marketplace.*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/></svg>
                    Marketplace
                </a>
                <a href="{{ route('admin.settings.gcms-update') }}" class="flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 {{ request()->routeIs('admin.settings.gcms-update*') ? 'text-white font-semibold shadow-sm' : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900' }}" @if(request()->routeIs('admin.settings.gcms-update*')) style="background: linear-gradient(135deg, {{ $adminPrimary }}, {{ $adminSecondary }});" @endif>
                    <svg class="w-5 h-5 shrink-0 {{ request()->routeIs('admin.settings.gcms-update*') ? 'opacity-100' : 'opacity-70' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
                    Mise à jour GCMS
                </a>
                @endif
            </nav>
            <div class="p-3 border-t border-slate-100 space-y-1 shrink-0">
                <a href="{{ url('/') }}" target="_blank" class="flex items-center gap-3 px-3 py-2.5 rounded-xl text-slate-600 hover:bg-slate-100 hover:text-slate-900 transition-all duration-200 text-sm">
                    <svg class="w-5 h-5 shrink-0 opacity-70" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg>
                    Voir le site
                </a>
                <form method="POST" action="{{ url('/admin/logout') }}">
                    @csrf
                    <button type="submit" class="w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-slate-500 hover:text-red-600 hover:bg-red-50 transition-all duration-200 text-left">
                        <svg class="w-5 h-5 shrink-0 opacity-70" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/></svg>
                        Déconnexion
                    </button>
                </form>
            </div>
        </aside>
        <main class="flex-1 min-w-0 min-h-screen flex flex-col">
            <header class="sticky top-0 z-30 bg-white/95 backdrop-blur-md border-b border-slate-200/80 px-4 sm:px-6 lg:px-8 py-3 sm:py-4 shadow-sm">
                <div class="flex items-center gap-3">
                    <button type="button" class="lg:hidden p-2 -ml-2 text-slate-600 hover:text-slate-800 hover:bg-slate-100 rounded-lg" onclick="document.getElementById('admin-sidebar').classList.add('open'); document.getElementById('admin-sidebar-overlay').classList.remove('hidden'); document.body.style.overflow='hidden';" aria-label="Ouvrir le menu">
                        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
                    </button>
                    <h1 class="text-lg sm:text-xl font-semibold text-slate-800 truncate">@yield('header', 'Administration')</h1>
                </div>
            </header>
            <div class="flex-1 p-4 sm:p-6 lg:p-8 overflow-x-auto min-w-0">
                @if(auth()->user()?->canManageUsers() && ($gcmsUpdateBanner ?? null) && !empty($gcmsUpdateBanner['update_available']))
                    <div class="mb-6 p-4 bg-amber-50 border border-amber-200 rounded-xl flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
                        <p class="text-amber-900 text-sm font-medium">
                            Une nouvelle version de GCMS est disponible : <strong>{{ $gcmsUpdateBanner['latest_version'] }}</strong>
                        </p>
                        <a href="{{ route('admin.settings.gcms-update') }}" class="shrink-0 inline-flex items-center justify-center px-4 py-2 bg-amber-600 text-white rounded-lg text-sm font-medium hover:bg-amber-700 transition">
                            Voir la mise à jour
                        </a>
                    </div>
                @endif
                @if(session('success'))
                    <div class="mb-6 p-4 bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-xl flex items-center gap-3">
                        <svg class="w-5 h-5 text-emerald-500 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
                        {{ session('success') }}
                    </div>
                @endif
                @if(session('error'))
                    <div class="mb-6 p-4 bg-red-50 border border-red-200 text-red-800 rounded-xl flex items-center gap-3">
                        <svg class="w-5 h-5 text-red-500 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
                        {{ session('error') }}
                    </div>
                @endif
                @yield('content')
            </div>
        </main>
    </div>

    {{-- Modal import image : conserver telle quelle ou recadrer --}}
    <div id="image-crop-modal" class="fixed inset-0 z-[100] hidden items-center justify-center bg-black/60 p-4" role="dialog" aria-modal="true" aria-labelledby="crop-modal-title">
        <div class="bg-white rounded-2xl shadow-xl max-w-2xl w-full max-h-[90vh] overflow-hidden flex flex-col">
            <div class="p-4 border-b border-slate-200 flex items-center justify-between">
                <h2 id="crop-modal-title" class="font-semibold text-slate-800">Importer une image</h2>
                <button type="button" id="crop-modal-close" class="p-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg transition" aria-label="Fermer">
                    <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
                </button>
            </div>
            <div class="flex-1 overflow-y-auto min-h-0">
                <div id="crop-modal-step-choice" class="p-6">
                    <p class="text-sm text-slate-600 mb-4">Souhaitez-vous envoyer l’image <strong>telle quelle</strong> (recommandé pour les logos PNG avec transparence ou les visuels déjà au bon format), ou la <strong>recadrer</strong> avant envoi&nbsp;?</p>
                    <p class="text-xs text-slate-500 mb-4">Le recadrage exporte en JPEG, PNG ou WebP selon le fichier d’origine — les PNG transparents restent en PNG si vous recadrez.</p>
                    <div class="flex flex-col sm:flex-row gap-3 justify-end">
                        <button type="button" id="crop-modal-use-original" class="px-4 py-2 border border-slate-200 rounded-xl text-slate-800 hover:bg-slate-50 transition font-medium order-2 sm:order-1">Conserver telle quelle</button>
                        <button type="button" id="crop-modal-use-crop" class="px-4 py-2 bg-primary-500 text-white rounded-xl hover:bg-primary-600 transition font-medium order-1 sm:order-2">Recadrer</button>
                    </div>
                </div>
                <div id="crop-modal-step-crop" class="hidden p-4">
                    <div class="w-full h-[50vh] min-h-[300px] bg-slate-100">
                        <img id="crop-image" src="" alt="" class="max-w-full max-h-full block">
                    </div>
                    <div class="mt-4 flex gap-2 flex-wrap">
                        <label class="flex items-center gap-2 text-sm text-slate-600">
                            <input type="radio" name="crop-aspect" value="free" checked class="rounded border-slate-300 text-primary-500"> Libre
                        </label>
                        <label class="flex items-center gap-2 text-sm text-slate-600">
                            <input type="radio" name="crop-aspect" value="1" class="rounded border-slate-300 text-primary-500"> 1:1 (carré)
                        </label>
                        <label class="flex items-center gap-2 text-sm text-slate-600">
                            <input type="radio" name="crop-aspect" value="4/3" class="rounded border-slate-300 text-primary-500"> 4:3
                        </label>
                        <label class="flex items-center gap-2 text-sm text-slate-600">
                            <input type="radio" name="crop-aspect" value="16/9" class="rounded border-slate-300 text-primary-500"> 16:9
                        </label>
                    </div>
                </div>
            </div>
            <div class="p-4 border-t border-slate-200 flex gap-3 justify-end flex-wrap">
                <button type="button" id="crop-modal-back" class="hidden px-4 py-2 border border-slate-200 rounded-xl text-slate-700 hover:bg-slate-50 transition">← Retour</button>
                <button type="button" id="crop-modal-cancel" class="px-4 py-2 border border-slate-200 rounded-xl text-slate-700 hover:bg-slate-50 transition">Annuler</button>
                <button type="button" id="crop-modal-confirm" class="hidden px-4 py-2 bg-primary-500 text-white rounded-xl hover:bg-primary-600 transition font-medium">Valider le recadrage</button>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/cropperjs@1.6.2/dist/cropper.min.js"></script>
    @stack('scripts')
    <script>
    (function() {
        var cropModal = document.getElementById('image-crop-modal');
        var cropImage = document.getElementById('crop-image');
        var cropTitle = document.getElementById('crop-modal-title');
        var cropConfirm = document.getElementById('crop-modal-confirm');
        var cropBack = document.getElementById('crop-modal-back');
        var cropCancel = document.getElementById('crop-modal-close');
        var cropModalCancel = document.getElementById('crop-modal-cancel');
        var stepChoice = document.getElementById('crop-modal-step-choice');
        var stepCrop = document.getElementById('crop-modal-step-crop');
        var btnUseOriginal = document.getElementById('crop-modal-use-original');
        var btnUseCrop = document.getElementById('crop-modal-use-crop');
        var cropper = null;
        var pendingUpload = null;
        var cropObjectUrl = null;

        function getCsrfToken() {
            return document.querySelector('meta[name="csrf-token"]')?.content || document.querySelector('input[name="_token"]')?.value;
        }

        /**
         * Réduit image dans le navigateur (évite 413 Request Entity Too Large côté nginx/PHP avant Laravel).
         * Cible ~1,8 Mo max, bord max 2560 px, sortie JPEG sauf GIF (inchangé).
         */
        function gcmsCompressImageFile(file) {
            var maxEdge = 2560;
            var maxBytes = 1800000;
            var skipBelow = 1950000;
            return new Promise(function(resolve) {
                if (!file || !file.type || file.type.indexOf('image/') !== 0 || file.type === 'image/gif') {
                    resolve(file);
                    return;
                }
                if (file.size <= skipBelow) {
                    resolve(file);
                    return;
                }
                var objectUrl = URL.createObjectURL(file);
                var img = new Image();
                img.onload = function() {
                    URL.revokeObjectURL(objectUrl);
                    var w = img.naturalWidth;
                    var h = img.naturalHeight;
                    if (w < 1 || h < 1) {
                        resolve(file);
                        return;
                    }
                    var baseName = (file.name || 'image').replace(/\.[^.]+$/, '');
                    function attempt(scale, quality) {
                        var tw = Math.max(1, Math.round(w * scale));
                        var th = Math.max(1, Math.round(h * scale));
                        if (tw > maxEdge || th > maxEdge) {
                            var r = maxEdge / Math.max(tw, th);
                            tw = Math.max(1, Math.round(tw * r));
                            th = Math.max(1, Math.round(th * r));
                        }
                        var canvas = document.createElement('canvas');
                        canvas.width = tw;
                        canvas.height = th;
                        var ctx = canvas.getContext('2d');
                        if (!ctx) {
                            resolve(file);
                            return;
                        }
                        ctx.drawImage(img, 0, 0, tw, th);
                        canvas.toBlob(function(blob) {
                            if (!blob) {
                                resolve(file);
                                return;
                            }
                            if (blob.size > maxBytes && quality > 0.52) {
                                attempt(scale, quality - 0.07);
                                return;
                            }
                            if (blob.size > maxBytes && scale > 0.38) {
                                attempt(scale * 0.82, 0.86);
                                return;
                            }
                            resolve(new File([blob], baseName + '.jpg', { type: 'image/jpeg', lastModified: Date.now() }));
                        }, 'image/jpeg', quality);
                    }
                    var s0 = 1;
                    if (w > maxEdge || h > maxEdge) {
                        s0 = maxEdge / Math.max(w, h);
                    }
                    attempt(s0, 0.88);
                };
                img.onerror = function() {
                    URL.revokeObjectURL(objectUrl);
                    resolve(file);
                };
                img.src = objectUrl;
            });
        }

        window.gcmsCompressImageFile = gcmsCompressImageFile;

        function uploadMediaFile(file, textInput, btn, done) {
            gcmsCompressImageFile(file).then(function(compressed) {
                var formData = new FormData();
                formData.append('file', compressed);
                formData.append('_token', getCsrfToken());
                if (btn) btn.classList.add('opacity-50', 'pointer-events-none');
                fetch('{{ route("admin.media.upload") }}', { method: 'POST', body: formData, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } })
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        if (data.path && textInput) {
                            textInput.value = data.path;
                            textInput.dispatchEvent(new Event('input', { bubbles: true }));
                        }
                    })
                    .catch(function() { alert('Erreur lors de l\'upload.'); })
                    .finally(function() {
                        if (btn) btn.classList.remove('opacity-50', 'pointer-events-none');
                        if (typeof done === 'function') done();
                    });
            });
        }

        function showChoiceStep() {
            stepChoice.classList.remove('hidden');
            stepCrop.classList.add('hidden');
            cropConfirm.classList.add('hidden');
            cropBack.classList.add('hidden');
            cropTitle.textContent = 'Importer une image';
            if (cropper) {
                cropper.destroy();
                cropper = null;
            }
            cropImage.src = '';
            if (cropObjectUrl) {
                URL.revokeObjectURL(cropObjectUrl);
                cropObjectUrl = null;
            }
        }

        function showCropStep() {
            stepChoice.classList.add('hidden');
            stepCrop.classList.remove('hidden');
            cropConfirm.classList.remove('hidden');
            cropBack.classList.remove('hidden');
            cropTitle.textContent = 'Recadrer l\'image';
        }

        function openImageChoiceModal(file, textInput, btn) {
            if (!file || !file.type.startsWith('image/')) return;
            pendingUpload = { file: file, textInput: textInput, btn: btn };
            showChoiceStep();
            cropModal.classList.remove('hidden');
            cropModal.classList.add('flex');
            document.body.style.overflow = 'hidden';
        }

        function initCropperFromFile() {
            if (!pendingUpload || !pendingUpload.file) return;
            if (cropObjectUrl) {
                URL.revokeObjectURL(cropObjectUrl);
                cropObjectUrl = null;
            }
            cropObjectUrl = URL.createObjectURL(pendingUpload.file);
            cropImage.src = '';
            cropImage.onload = function() {
                if (cropper) cropper.destroy();
                cropper = new Cropper(cropImage, {
                    aspectRatio: NaN,
                    viewMode: 1,
                    dragMode: 'move',
                    autoCropArea: 0.8,
                    restore: false,
                    guides: true,
                    center: true,
                    highlight: false,
                    cropBoxMovable: true,
                    cropBoxResizable: true,
                    toggleDragModeOnDblclick: false,
                });
                cropper.setAspectRatio(getAspectRatio());
            };
            cropImage.src = cropObjectUrl;
        }

        function closeCropModal() {
            cropModal.classList.add('hidden');
            cropModal.classList.remove('flex');
            document.body.style.overflow = '';
            if (cropper) {
                cropper.destroy();
                cropper = null;
            }
            cropImage.src = '';
            if (cropObjectUrl) {
                URL.revokeObjectURL(cropObjectUrl);
                cropObjectUrl = null;
            }
            pendingUpload = null;
            showChoiceStep();
        }

        function getAspectRatio() {
            var radio = document.querySelector('input[name="crop-aspect"]:checked');
            if (!radio || radio.value === 'free') return NaN;
            if (radio.value === '1') return 1;
            if (radio.value === '4/3') return 4/3;
            if (radio.value === '16/9') return 16/9;
            return NaN;
        }

        document.querySelectorAll('input[name="crop-aspect"]').forEach(function(r) {
            r.addEventListener('change', function() {
                if (cropper) cropper.setAspectRatio(getAspectRatio());
            });
        });

        btnUseOriginal.addEventListener('click', function() {
            if (!pendingUpload) return;
            var f = pendingUpload.file;
            var ti = pendingUpload.textInput;
            var b = pendingUpload.btn;
            uploadMediaFile(f, ti, b, closeCropModal);
        });

        btnUseCrop.addEventListener('click', function() {
            if (!pendingUpload) return;
            document.querySelector('input[name="crop-aspect"][value="free"]').checked = true;
            showCropStep();
            initCropperFromFile();
        });

        cropBack.addEventListener('click', function() {
            if (cropper) {
                cropper.destroy();
                cropper = null;
            }
            cropImage.src = '';
            if (cropObjectUrl) {
                URL.revokeObjectURL(cropObjectUrl);
                cropObjectUrl = null;
            }
            showChoiceStep();
        });

        cropConfirm.addEventListener('click', function() {
            if (!cropper || !pendingUpload) return;
            var canvas = cropper.getCroppedCanvas({ maxWidth: 1920, maxHeight: 1920, imageSmoothingEnabled: true, imageSmoothingQuality: 'high' });
            if (!canvas) {
                alert('Erreur lors du recadrage.');
                return;
            }
            var srcFile = pendingUpload.file;
            var mime = 'image/jpeg';
            var quality = 0.92;
            var ext = 'jpg';
            if (srcFile.type === 'image/png') {
                mime = 'image/png';
                ext = 'png';
            } else if (srcFile.type === 'image/webp') {
                mime = 'image/webp';
                ext = 'webp';
            } else if (srcFile.type === 'image/gif') {
                mime = 'image/png';
                ext = 'png';
            }
            function afterCroppedBlob(blob) {
                if (!blob || !pendingUpload) return;
                var formData = new FormData();
                formData.append('file', blob, 'image.' + ext);
                formData.append('_token', getCsrfToken());
                if (pendingUpload.btn) pendingUpload.btn.classList.add('opacity-50', 'pointer-events-none');
                fetch('{{ route("admin.media.upload") }}', { method: 'POST', body: formData, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } })
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        if (data.path && pendingUpload && pendingUpload.textInput) {
                            pendingUpload.textInput.value = data.path;
                            pendingUpload.textInput.dispatchEvent(new Event('input', { bubbles: true }));
                        }
                    })
                    .catch(function() { alert('Erreur lors de l\'upload.'); })
                    .finally(function() {
                        if (pendingUpload && pendingUpload.btn) pendingUpload.btn.classList.remove('opacity-50', 'pointer-events-none');
                        closeCropModal();
                    });
            }
            if (mime === 'image/png') {
                canvas.toBlob(afterCroppedBlob, mime);
            } else {
                canvas.toBlob(afterCroppedBlob, mime, quality);
            }
        });

        cropCancel.addEventListener('click', closeCropModal);
        cropModalCancel.addEventListener('click', closeCropModal);
        cropModal.addEventListener('click', function(e) {
            if (e.target === cropModal) closeCropModal();
        });

        document.getElementById('admin-sidebar')?.addEventListener('click', function(e) {
            if (e.target.closest('a') && window.innerWidth < 1024) {
                document.getElementById('admin-sidebar-overlay')?.classList.add('hidden');
                document.getElementById('admin-sidebar')?.classList.remove('open');
                document.body.style.overflow = '';
            }
        });

        document.addEventListener('change', function(e) {
            var compressTarget = e.target;
            if (compressTarget.matches && compressTarget.matches('input[type=file][data-admin-compress-image][data-admin-compress-submit-form]')) {
                var f = compressTarget.files[0];
                if (!f) return;
                compressTarget.disabled = true;
                gcmsCompressImageFile(f).then(function(out) {
                    var dt = new DataTransfer();
                    dt.items.add(out);
                    compressTarget.files = dt.files;
                    compressTarget.disabled = false;
                    var frm = compressTarget.closest('form');
                    if (frm) frm.submit();
                }).catch(function() {
                    compressTarget.disabled = false;
                });
                return;
            }
            if (!e.target.matches || !e.target.matches('input[data-image-upload]')) return;
            var file = e.target.files[0];
            if (!file) return;
            var group = e.target.closest('.image-input-group');
            var textInput = group ? group.querySelector('input[data-image-text-input]') : null;
            if (!textInput) return;
            var btn = e.target.closest('label');
            if (typeof Cropper !== 'undefined') {
                openImageChoiceModal(file, textInput, btn);
            } else {
                uploadMediaFile(file, textInput, btn, function() {});
            }
            e.target.value = '';
        });

        document.addEventListener('submit', function(ev) {
            var form = ev.target;
            if (!form || form.tagName !== 'FORM') return;
            if (form.dataset.gcmsImageCompressPass === '1') {
                delete form.dataset.gcmsImageCompressPass;
                return;
            }
            var inputs = form.querySelectorAll('input[type=file][data-admin-compress-image]');
            var work = [];
            inputs.forEach(function(inp) {
                if (inp.hasAttribute('data-admin-compress-submit-form')) return;
                var list = Array.from(inp.files || []).filter(function(f) { return f && f.size > 600000; });
                if (!list.length) return;
                work.push({ inp: inp, list: Array.from(inp.files || []) });
            });
            if (!work.length) return;
            ev.preventDefault();
            ev.stopPropagation();
            Promise.all(work.map(function(w) {
                return Promise.all(w.list.map(gcmsCompressImageFile)).then(function(outs) {
                    var dt = new DataTransfer();
                    outs.forEach(function(x) { dt.items.add(x); });
                    w.inp.files = dt.files;
                });
            })).then(function() {
                form.dataset.gcmsImageCompressPass = '1';
                if (typeof form.requestSubmit === 'function') {
                    form.requestSubmit();
                } else {
                    form.submit();
                }
            }).catch(function() {
                alert('Impossible de préparer les images. Réessayez ou choisissez des fichiers plus petits.');
            });
        }, true);

        function syncImageInputPreview(textInput) {
            if (!textInput || !textInput.matches || !textInput.matches('input[data-image-text-input]')) return;
            var group = textInput.closest('.image-input-group');
            if (!group) return;
            var img = group.querySelector('[data-image-preview]');
            if (!img) return;
            var base = (group.getAttribute('data-storage-base') || '').replace(/\/$/, '');
            var v = (textInput.value || '').trim();
            if (!v) {
                img.classList.add('hidden');
                img.removeAttribute('src');
                return;
            }
            var src = (v.indexOf('http') === 0 || v.indexOf('/') === 0) ? v : base + '/' + v.replace(/^\//, '');
            img.onerror = function() { img.classList.add('hidden'); };
            img.onload = function() { img.classList.remove('hidden'); };
            img.src = src;
        }

        document.addEventListener('input', function(e) {
            if (e.target.matches && e.target.matches('input[data-image-text-input]')) {
                syncImageInputPreview(e.target);
            }
        });

        document.addEventListener('DOMContentLoaded', function() {
            document.querySelectorAll('input[data-image-text-input]').forEach(syncImageInputPreview);
        });

        window.GCMSAdminSyncImagePreview = syncImageInputPreview;
    })();
    </script>
</body>
</html>
