﻿<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link rel="icon" type="image/png" href="{{ asset('kiyohr.png') }}">
    <link rel="shortcut icon" href="{{ asset('kiyohr.png') }}">
    <link rel="stylesheet" href="{{ asset('vendor/select2/select2.min.css') }}">
    <link rel="stylesheet" href="{{ asset('vendor/fonts/manrope.css') }}">
    <link rel="stylesheet" href="{{ asset('css/style.css') }}">
    <link rel="stylesheet" href="{{ asset('css/icon-colors.css') }}">
    <title>{{ config('app.name') }} - @yield('title', 'Dashboard')</title>
    <script src="{{ asset('vendor/tailwindcss/tailwindcss.js') }}"></script>
    <script src="{{ asset('vendor/jquery/jquery-3.7.1.min.js') }}"></script>
    <script src="{{ asset('vendor/select2/select2.full.min.js') }}"></script>
    <script>
        var spacingScale = 0.9;
        var spacingSteps = {
            0: 0, 0.5: 0.125, 1: 0.25, 1.5: 0.375, 2: 0.5, 2.5: 0.625,
            3: 0.75, 3.5: 0.875, 4: 1, 5: 1.25, 6: 1.5, 7: 1.75, 8: 2,
            9: 2.25, 10: 2.5, 11: 2.75, 12: 3, 14: 3.5, 16: 4, 20: 5,
            24: 6, 28: 7, 32: 8, 36: 9, 40: 10, 44: 11, 48: 12, 52: 13,
            56: 14, 60: 15, 64: 16, 72: 18, 80: 20, 96: 24
        };
        var spacing = { px: '1px' };
        Object.keys(spacingSteps).forEach(function (key) {
            spacing[key] = (spacingSteps[key] * spacingScale) + 'rem';
        });

        tailwind.config = {
            theme: {
                spacing: spacing,
                extend: {
                    fontFamily: { sans: ['Inter', 'system-ui', 'sans-serif'] },
                    borderRadius: {
                        // Mild corners app-wide (inputs, buttons, cards)
                        DEFAULT: '0.375rem',
                        sm: '0.25rem',
                        md: '0.375rem',
                        lg: '0.375rem',
                        xl: '0.5rem',
                        '2xl': '0.75rem',
                    },
                    colors: {
                        primary: { DEFAULT: '#0c6e6d', hover: '#0a5c5b', light: '#e6f5f5' },
                        secondary: { DEFAULT: '#ff9307', hover: '#e68406', light: '#fff4e6' }
                    }
                }
            }
        }

        window.initSelect2 = function (root) {
            if (!window.jQuery || !window.jQuery.fn || !window.jQuery.fn.select2) {
                console.warn('Select2 could not initialize because jQuery or Select2 failed to load.');
                return;
            }

            window.jQuery(root || document).find('.js-select2').each(function () {
                var $select = window.jQuery(this);
                if ($select.data('select2')) return;

                var inlineWidth = $select[0].style.width;
                var inlineMinWidth = $select[0].style.minWidth;
                var dropdownParentSelector = $select.attr('data-dropdown-parent');
                var $dropdownParent = dropdownParentSelector ? $select.closest(dropdownParentSelector) : null;

                $select.select2({
                    width: inlineWidth ? 'style' : '100%',
                    minimumResultsForSearch: $select.hasClass('js-select2-search') ? 0 : Infinity,
                    dropdownCssClass: 'site-select2-dropdown',
                    dropdownParent: ($dropdownParent && $dropdownParent.length) ? $dropdownParent : undefined,
                    templateResult: function (data) {
                        if (data.element && data.element.hidden) return null;
                        return data.text;
                    }
                });

                // Keep Alpine x-model (and native change handlers) in sync with Select2.
                $select.on('select2:select select2:clear change', function () {
                    this.dispatchEvent(new Event('input', { bubbles: true }));
                    this.dispatchEvent(new Event('change', { bubbles: true }));
                });

                var $container = $select.next('.select2-container');
                $container.addClass('site-select2');

                if ($dropdownParent && $dropdownParent.length) {
                    $select.on('select2:open', function () {
                        var fieldWidth = $container.outerWidth();
                        if (!fieldWidth) return;
                        $dropdownParent.children('.select2-dropdown').css({
                            width: fieldWidth + 'px',
                            minWidth: fieldWidth + 'px',
                            maxWidth: fieldWidth + 'px'
                        });
                    });
                }

                if ($select.hasClass('text-xs')) {
                    $container.addClass('site-select2-xs');
                }
                if (inlineWidth) {
                    $container.css('width', inlineWidth);
                }
                if (inlineMinWidth) {
                    $container.css('min-width', inlineMinWidth);
                }
            });
        };

        document.addEventListener('DOMContentLoaded', function () {
            window.initSelect2(document);
        });
    </script>
    {{-- Alpine for header menus/toasts. Skip if Livewire is present (it ships its own Alpine). --}}
    @if(! class_exists(\Livewire\Livewire::class))
        <script defer src="{{ asset('vendor/alpinejs/cdn.min.js') }}"></script>
    @endif
    <script src="{{ asset('vendor/chartjs/chart.min.js') }}"></script>
    @if(class_exists(\Livewire\Livewire::class))
        @livewireStyles
    @endif
    <style>
        [x-cloak] { display: none !important; }
        button,
        [type="button"],
        [type="submit"],
        [type="reset"],
        .btn {
            border-radius: 0.5rem;
        }
        :root {
            --color-primary: #0c6e6d;
            --color-primary-hover: #0a5c5b;
            --color-primary-light: #e6f5f5;
            --color-secondary: #ff9307;
            --color-secondary-hover: #e68406;
            --color-secondary-light: #fff4e6;
            --admin-control-font-size: 0.875rem;
            --admin-control-height: 34px;
        }
        html { font-size: 16px; }
        body { font-size: 0.875rem; line-height: 1.4; background-color: #F5F8FA; }
        .bg-primary { background-color: var(--color-primary) !important; }
        .bg-primary:hover { background-color: var(--color-primary-hover) !important; }
        .text-primary { color: var(--color-primary) !important; }
        .bg-primary-light { background-color: var(--color-primary-light) !important; }
        .bg-secondary { background-color: var(--color-secondary) !important; }
        .text-secondary { color: var(--color-secondary) !important; }
        .bg-secondary-light { background-color: var(--color-secondary-light) !important; }
        .ring-primary { --tw-ring-color: var(--color-primary) !important; }

        
        /* .sidebar-scroll {
            scrollbar-width: thin;
        } */
        .sidebar-scroll::-webkit-scrollbar {
            width: 2px;
        }
        .sidebar-scroll::-webkit-scrollbar-button {
            display: none;
            height: 0;
            width: 0;
        }
        .hide-scrollbar {
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        .hide-scrollbar::-webkit-scrollbar {
            width: 0;
            height: 0;
        }

    </style>
    @stack('styles')
</head>
<body class="text-slate-800 antialiased overflow-x-hidden"
      x-data="{
          sidebarOpen: true,
            init() {
                var storedSidebarOpen = localStorage.getItem('sidebarOpen');
                this.sidebarOpen = storedSidebarOpen === null ? true : storedSidebarOpen === 'true';
            },
      }"
      x-init="init()"
>
    <div class="flex min-h-screen">
        {{-- Sidebar --}}
        <aside id="main-aside" class="fixed left-0 top-0 z-40 h-screen w-[100px] flex flex-col bg-white border-r border-slate-200">
            <div class="flex h-14 items-center justify-between border-b border-slate-200 px-4">
                <a href="{{ (auth()->user()->is_superadmin ?? false) ? route('superadmin.dashboard') : route('dashboard') }}" class="flex items-center gap-2 overflow-hidden min-w-0">
                    @if(!empty(auth()->user()->company?->logo))
                        <img src="{{ \Illuminate\Support\Facades\Storage::url(auth()->user()->company->logo) }}" alt="Company logo" class="h-8 w-auto object-contain">
                    @elseif(file_exists(public_path('kiyohr.png')))
                        <img src="{{ asset('kiyohr.png') }}" alt="{{ config('app.vendor') }}" class="h-8 w-auto object-contain" />
                    @else
                        <span class="text-xl font-semibold truncate" x-show="sidebarOpen" x-cloak style="color: var(--color-primary)">{{ config('app.name') }}</span>
                    @endif
                </a>
            </div>
            <nav class="sidebar-scroll flex-1 overflow-y-auto">
                @include('layouts.partials.sidebar')
            </nav>
            <div class="border-t border-slate-200 px-4 py-3 text-center text-xs text-slate-500" x-cloak>
                {{-- <div>© {{ date('Y') }} {{ config('app.vendor') }}</div> --}}
                <div class="mt-0.5">v{{ config('app.version') }}</div>
            </div>
        </aside>

        <div class="ml-[100px] flex min-h-screen flex-1 flex-col transition-all duration-200 max-w-full">
            {{-- Top Navbar --}}
            <header class="fixed top-0 left-[100px] right-0 z-30 flex min-h-14 flex-nowrap items-center justify-between gap-3 border-b border-slate-200 bg-white px-2 md:px-6 md:py-3 py-1 md:h-14 md:flex-nowrap md:py-0">
                <div class="flex items-center gap-4">
                    <h1 class="text-lg font-semibold text-slate-800 pl-2 md:pl-2 hidden md:block">@yield('heading', 'Dashboard')</h1>
                </div>
                <div class="flex flex-nowrap items-center justify-end md:gap-2 gap-1">
                    @if($showSelfAttendanceTopbar ?? false)
                        @include('layouts.partials.topbar-self-attendance')
                    @else
                        @yield('topbar_actions')
                    @endif
                    {{-- Notifications --}}
                    <div
                        x-data="{
                            open: false,
                            items: [],
                            unreadCount: 0,
                            seenIds: [],
                            async loadNotifications() {
                                try {
                                    const response = await fetch('{{ route('notifications.feed') }}', {
                                        headers: { 'Accept': 'application/json' }
                                    });
                                    if (!response.ok) return;
                                    const data = await response.json();
                                    const incoming = Array.isArray(data.items) ? data.items : [];
                                    this.unreadCount = data.count ?? incoming.length;
                                    this.items = incoming;

                                    if ('Notification' in window && Notification.permission === 'default') {
                                        Notification.requestPermission();
                                    }

                                    incoming.forEach((item) => {
                                        if (this.seenIds.includes(item.id)) return;
                                        this.seenIds.push(item.id);
                                        if ('Notification' in window && Notification.permission === 'granted') {
                                            const browserNote = new Notification('KiyoHRMS Notification', {
                                                body: item.message || 'New notification',
                                            });
                                            browserNote.onclick = () => {
                                                if (item.url) {
                                                    window.location.href = item.url;
                                                }
                                            };
                                        }
                                    });
                                } catch (error) {
                                    // Keep silent; UI fallback still works.
                                }
                            },
                            async markAllRead() {
                                try {
                                    await fetch('{{ route('notifications.mark-all-read') }}', {
                                        method: 'POST',
                                        headers: {
                                            'Content-Type': 'application/json',
                                            'X-CSRF-TOKEN': document.querySelector('meta[name=\'csrf-token\']').getAttribute('content'),
                                            'Accept': 'application/json'
                                        }
                                    });
                                    this.unreadCount = 0;
                                    this.items = [];
                                } catch (error) {
                                    // no-op
                                }
                            },
                            init() {
                                this.loadNotifications();
                                setInterval(() => this.loadNotifications(), 20000);
                            }
                        }"
                        class="relative"
                    >
                        <button type="button" @click.stop="open = !open" class="relative rounded-lg p-2 hover:bg-secondary-light">
                            <svg class="h-5 w-5 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/>
                            </svg>
                            <span x-show="unreadCount > 0" x-cloak class="absolute -right-1 -top-1 min-w-4 rounded-full bg-secondary px-1 text-center text-[10px] font-semibold text-white" x-text="unreadCount > 9 ? '9+' : unreadCount"></span>
                        </button>
                        <div x-show="open" x-cloak @click.outside="open = false"
                             class="absolute right-0 mt-2 w-72 rounded-xl border border-slate-200 bg-white py-2 shadow-lg">
                            <div class="flex items-center justify-between border-b border-slate-100 px-4 py-2 text-sm font-medium text-slate-500">
                                <span>Notifications</span>
                                <button type="button" class="text-xs text-primary hover:underline" @click="markAllRead()">Mark all read</button>
                            </div>
                            <div class="max-h-64 overflow-y-auto">
                                <template x-if="items.length === 0">
                                    <span class="block px-4 py-3 text-sm text-slate-500">No new notifications</span>
                                </template>
                                <template x-for="item in items" :key="item.id">
                                    <a :href="item.url || '#'" class="block px-4 py-3 text-sm hover:bg-slate-50">
                                        <div class="font-medium text-slate-700" x-text="item.message"></div>
                                        <div class="mt-1 text-xs text-slate-400" x-text="item.created_at"></div>
                                    </a>
                                </template>
                            </div>
                        </div>
                    </div>
                    {{-- User dropdown --}}
                    <div x-data="{ open: false }" class="relative">
                        <button type="button" @click.stop="open = !open" class="flex items-center gap-2 rounded-lg px-2 py-1.5 hover:bg-slate-100">
                            <div class="h-8 w-8 rounded-full bg-primary-light flex items-center justify-center text-sm font-medium text-primary">
                                {{ strtoupper(substr(auth()->user()->name ?? 'U', 0, 1)) }}
                            </div>
                            {{-- <span class="hidden text-sm font-medium sm:block">{{ auth()->user()->name ?? 'User' }}</span> --}}
                            <svg class="h-4 w-4 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
                            </svg>
                        </button>
                        <div x-show="open" x-cloak @click.outside="open = false"
                             class="absolute right-0 mt-2 w-48 rounded-xl border border-slate-200 bg-white py-2 shadow-lg">
                            @if((auth()->user()->is_superadmin ?? false) || auth()->user()->isCompanyAccountAdmin() || auth()->user()->hasPermission('manage_settings'))
                            <a href="{{ (auth()->user()->is_superadmin ?? false) ? route('superadmin.settings.index') : route('settings.home') }}" class="flex items-center gap-2.5 px-4 py-2 text-sm text-slate-700 hover:bg-slate-50">
                                <i class="bi bi-gear text-base text-slate-500"></i>
                                Settings
                            </a>
                            @endif
                            <a href="{{ (auth()->user()->is_superadmin ?? false) ? route('superadmin.settings.profile') : route('settings.profile') }}" class="flex items-center gap-2.5 px-4 py-2 text-sm text-slate-700 hover:bg-slate-50">
                                <i class="bi bi-person text-base text-slate-500"></i>
                                Profile
                            </a>
                            @if(!(auth()->user()->is_superadmin ?? false) && auth()->user()->company_id && (auth()->user()->isCompanyAccountAdmin() || auth()->user()->hasPermission('manage_settings')))
                            <a href="{{ route('subscription.request') }}" class="flex items-center gap-2.5 px-4 py-2 text-sm text-slate-700 hover:bg-slate-50">
                                <i class="bi bi-credit-card text-base text-slate-500"></i>
                                My subscription
                            </a>
                            @endif
                            <form method="POST" action="{{ route('logout') }}" class="block">
                                @csrf
                                <button type="submit" class="flex w-full items-center gap-2.5 px-4 py-2 text-left text-sm text-slate-700 hover:bg-slate-50">
                                    <i class="bi bi-box-arrow-right text-base text-slate-500"></i>
                                    Logout
                                </button>
                            </form>
                        </div>
                    </div>
                </div>
            </header>

            {{-- Main content --}}
            <main id="app-main" class="flex-1 p-3 pl-4 pt-16 md:p-6 md:pl-8 md:pt-16" style="width: 100%">
                @php
                    $layoutToasts = [];
                    $toastId = 1;
                    $subscriptionBanner = null;

                    $bannerUser = auth()->user();
                    $canManageSubscription = $bannerUser
                        && ! ($bannerUser->is_superadmin ?? false)
                        && $bannerUser->company_id
                        && ($bannerUser->isCompanyAccountAdmin() || $bannerUser->hasPermission('manage_settings'));

                    if ($canManageSubscription) {
                        $onSubscriptionPage = request()->routeIs('subscription.*');
                        $bannerCompany = \App\Models\Company::with('subscriptionPlan')->find($bannerUser->company_id);
                        if (! $onSubscriptionPage && $bannerCompany && $bannerCompany->isInExpiryWarningWindow()) {
                            $daysLeft = $bannerCompany->daysUntilLicenceExpiry();
                            if ($daysLeft !== null && $daysLeft < 0) {
                                $msg = 'Your licence expired on '.$bannerCompany->licence_expire_on?->format('d M Y').'. Renew to avoid suspension.';
                            } elseif ($daysLeft === 0) {
                                $msg = 'Your subscription licence expires today. Renew now.';
                            } else {
                                $msg = 'Your subscription expires in '.$daysLeft.' day'.($daysLeft === 1 ? '' : 's').' ('.$bannerCompany->licence_expire_on?->format('d M Y').').';
                            }
                            $subscriptionBanner = $msg;
                            $layoutToasts[] = [
                                'id' => $toastId++,
                                'type' => 'info',
                                'title' => 'Subscription',
                                'message' => $msg,
                                'duration' => 12000,
                            ];
                        }
                    }

                    if (session('success')) {
                        $layoutToasts[] = [
                            'id' => $toastId++,
                            'type' => 'success',
                            'title' => 'Success',
                            'message' => (string) session('success'),
                            'duration' => 4500,
                        ];
                    }
                    if (session('info')) {
                        $layoutToasts[] = [
                            'id' => $toastId++,
                            'type' => 'info',
                            'title' => 'Info',
                            'message' => (string) session('info'),
                            'duration' => 5000,
                        ];
                    }
                    if (session('error')) {
                        $layoutToasts[] = [
                            'id' => $toastId++,
                            'type' => 'error',
                            'title' => 'Error',
                            'message' => (string) session('error'),
                            'duration' => 8000,
                        ];
                    }
                    if ($errors->any()) {
                        $allErrors = $errors->all();
                        $firstError = (string) ($allErrors[0] ?? 'Please check your input.');
                        $extraCount = max(count($allErrors) - 1, 0);
                        $layoutToasts[] = [
                            'id' => $toastId++,
                            'type' => 'error',
                            'title' => $extraCount > 0 ? 'Validation Error (+' . $extraCount . ')' : 'Validation Error',
                            'message' => $firstError,
                            'duration' => 9000,
                        ];
                    }
                @endphp

                @if(!empty($subscriptionBanner))
                    <div class="mb-4 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900">
                        {{ $subscriptionBanner }}
                        <a href="{{ route('subscription.request') }}" class="ml-2 font-semibold underline">Manage subscription</a>
                    </div>
                @endif

                @if(!empty($layoutToasts))
                    <div
                        x-data="{
                            toasts: @js($layoutToasts),
                            hide(id) { this.toasts = this.toasts.filter((t) => t.id !== id) },
                            init() {
                                this.toasts.forEach((toast) => {
                                    window.setTimeout(() => this.hide(toast.id), toast.duration ?? 4000);
                                });
                            }
                        }"
                        class="pointer-events-none fixed right-4 top-20 z-[1050] flex w-full max-w-sm flex-col gap-3"
                    >
                        <template x-for="toast in toasts" :key="toast.id">
                            <div
                                x-show="true"
                                x-transition:enter="transform transition ease-out duration-250"
                                x-transition:enter-start="translate-y-2 opacity-0"
                                x-transition:enter-end="translate-y-0 opacity-100"
                                x-transition:leave="transform transition ease-in duration-200"
                                x-transition:leave-start="translate-y-0 opacity-100"
                                x-transition:leave-end="translate-y-2 opacity-0"
                                class="pointer-events-auto rounded-xl border bg-white p-4 shadow-lg"
                                :class="toast.type === 'success'
                                    ? 'border-emerald-200'
                                    : toast.type === 'info'
                                        ? 'border-sky-200'
                                        : 'border-red-200'"
                            >
                                <div class="flex items-start gap-3">
                                    <div
                                        class="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full"
                                        :class="toast.type === 'success'
                                            ? 'bg-emerald-100 text-emerald-700'
                                            : toast.type === 'info'
                                                ? 'bg-sky-100 text-sky-700'
                                                : 'bg-red-100 text-red-700'"
                                    >
                                        <svg x-show="toast.type === 'success'" class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
                                        </svg>
                                        <svg x-show="toast.type === 'info'" class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                                        </svg>
                                        <svg x-show="toast.type === 'error'" class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M10.29 3.86l-7.2 12.47A2 2 0 004.82 19h14.36a2 2 0 001.73-3.01l-7.2-12.47a2 2 0 00-3.46 0z" />
                                        </svg>
                                    </div>
                                    <div class="min-w-0 flex-1">
                                        <p class="text-sm font-semibold text-slate-900" x-text="toast.title"></p>
                                        <p class="mt-1 text-sm text-slate-600" x-text="toast.message"></p>
                                    </div>
                                    <button type="button" @click="hide(toast.id)" class="rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600">
                                        <svg class="h-4 w-4" 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>
                        </template>
                    </div>
                @endif
                @yield('content')
            </main>
        </div>
    </div>
    @if(class_exists(\Livewire\Livewire::class))
        @livewireScripts
    @endif
    @stack('scripts')
    <script id="app-tab-nav">
        (function () {
            var navSeq = 0;

            function samePage(url) {
                return url.pathname === window.location.pathname && url.search === window.location.search;
            }

            function destroyCharts() {
                if (!window.Chart || !window.Chart.instances) return;
                Object.values(window.Chart.instances).forEach(function (chart) {
                    if (chart && typeof chart.destroy === 'function') chart.destroy();
                });
            }

            function runPageScripts(doc) {
                document.querySelectorAll('script[data-page-script]').forEach(function (node) {
                    node.remove();
                });

                var seen = new Set();
                var nodes = Array.from(doc.querySelectorAll('#app-main script, body script'));
                nodes.forEach(function (oldScript) {
                    if (oldScript.id === 'app-tab-nav' || oldScript.src) return;
                    var code = oldScript.textContent || '';
                    if (!code.trim() || seen.has(code)) return;
                    seen.add(code);

                    var patched = code.replace(
                        /document\.addEventListener\(\s*(['"])DOMContentLoaded\1\s*,\s*/g,
                        '(function (fn) { if (document.readyState !== "loading") { fn(); } else { document.addEventListener("DOMContentLoaded", fn); } })('
                    );
                    var script = document.createElement('script');
                    script.setAttribute('data-page-script', '1');
                    script.textContent = patched;
                    document.body.appendChild(script);
                });
            }

            async function loadTab(url) {
                var main = document.getElementById('app-main');
                if (!main) {
                    window.location.href = url;
                    return;
                }

                var seq = ++navSeq;

                try {
                    var response = await fetch(url, {
                        credentials: 'same-origin',
                        headers: {
                            'X-Requested-With': 'XMLHttpRequest',
                            'Accept': 'text/html'
                        }
                    });

                    if (seq !== navSeq) return;

                    if (!response.ok) {
                        window.location.href = url;
                        return;
                    }

                    var html = await response.text();
                    if (seq !== navSeq) return;

                    var doc = new DOMParser().parseFromString(html, 'text/html');
                    var next = doc.querySelector('#app-main');
                    if (!next) {
                        window.location.href = url;
                        return;
                    }

                    destroyCharts();
                    main.innerHTML = next.innerHTML;
                    document.title = doc.title;
                    history.pushState({}, '', url);
                    window.scrollTo(0, 0);

                    if (window.initSelect2) window.initSelect2(main);
                    if (window.Alpine && typeof window.Alpine.initTree === 'function') {
                        window.Alpine.initTree(main);
                    }
                    runPageScripts(doc);
                } catch (error) {
                    if (seq === navSeq) window.location.href = url;
                }
            }

            document.addEventListener('click', function (event) {
                var link = event.target.closest('.top-submenu a');
                if (!link) return;
                if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) return;
                if (link.target === '_blank' || link.hasAttribute('download')) return;

                var url;
                try {
                    url = new URL(link.href, window.location.origin);
                } catch (error) {
                    return;
                }
                if (url.origin !== window.location.origin) return;
                if (samePage(url)) {
                    event.preventDefault();
                    return;
                }

                event.preventDefault();
                loadTab(link.href);
            });

            window.addEventListener('popstate', function () {
                window.location.reload();
            });
        })();
    </script>
</body>
</html>
