<?php
use App\Core\Auth;
use App\Core\Database;
use App\Core\Config;
$u = Auth::user();
$base = rtrim(Config::baseUrl(), '/'); // Conservé pour compat, mais utiliser route_url()/base_url() ci-dessous
$brandName = Config::get('app_name', 'NOVALINK');

$logoConfigured = Config::get('branding_logo', '/storage/uploads/logo.png');
$faviconConfigured = Config::get('branding_favicon', '/storage/uploads/favicon.ico');

// Convertir chemins relatifs branding/* en chemins publics complets
foreach ([&$logoConfigured, &$faviconConfigured] as &$p) {
  if ($p && !str_starts_with($p, '/')) {
    $p = '/storage/uploads/' . ltrim($p, '/');
  }
}
unset($p);

$publicRoot = Config::publicPath();
$uploadLogoFs = $publicRoot . DIRECTORY_SEPARATOR . ltrim(str_replace('/', DIRECTORY_SEPARATOR, $logoConfigured), DIRECTORY_SEPARATOR);
$uploadFaviconFs = $publicRoot . DIRECTORY_SEPARATOR . ltrim(str_replace('/', DIRECTORY_SEPARATOR, $faviconConfigured), DIRECTORY_SEPARATOR);

$brandLogo = (file_exists($uploadLogoFs) ? $base . $logoConfigured : $base . '/assets/logo-default.svg');
$favicon = (file_exists($uploadFaviconFs) ? $base . $faviconConfigured : $base . '/assets/favicon.svg');

$currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?: '';
$isMaintenanceFtthSection = str_contains($currentPath, '/maintenance-ftth');
$bodyClasses = ['hold-transition', 'sidebar-mini', 'layout-fixed', 'accent-primary'];
if ($u && !$isMaintenanceFtthSection) {
  $bodyClasses[] = 'erp-modern-standard';
}
?>
<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title><?= htmlspecialchars($title ?? $brandName) ?></title>
  
  <!-- Assets locaux (offline-first) -->
  <link rel="stylesheet" href="<?= htmlspecialchars($base) ?>/assets/vendor/bootstrap/bootstrap.min.css">
  <link rel="stylesheet" href="<?= htmlspecialchars($base) ?>/assets/vendor/adminlte/adminlte.min.css">
  <link rel="stylesheet" href="<?= htmlspecialchars($base) ?>/assets/vendor/fontawesome/css/all.min.css">
  <!-- Fallback CDN si les fichiers locaux sont manquants -->
  <script>
    (function(){
      function ensureCssLoaded(selector, cdnHref){
        var test = document.createElement('span');
        test.className = selector;
        test.style.position = 'absolute'; test.style.left = '-9999px';
        document.body.appendChild(test);
        var hasStyle = window.getComputedStyle(test).fontFamily || window.getComputedStyle(test).display;
        document.body.removeChild(test);
        if (!hasStyle) {
          var link = document.createElement('link'); link.rel='stylesheet'; link.href=cdnHref; document.head.appendChild(link);
        }
      }
      document.addEventListener('DOMContentLoaded', function(){
        // Bootstrap fallback
        ensureCssLoaded('btn btn-primary','https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css');
        // AdminLTE fallback (teste une classe adminlte)
        ensureCssLoaded('card','https://cdn.jsdelivr.net/npm/admin-lte@4.0.0/dist/css/adminlte.min.css');
        // FontAwesome fallback
        var fa = document.createElement('i'); fa.className='fas fa-check'; fa.style.left='-9999px'; document.body.appendChild(fa);
        var faLoaded = window.getComputedStyle(fa).fontFamily && window.getComputedStyle(fa).fontFamily.toLowerCase().includes('fontawesome');
        document.body.removeChild(fa);
        if (!faLoaded) {
          var faLink = document.createElement('link'); faLink.rel='stylesheet'; faLink.href='https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css'; document.head.appendChild(faLink);
        }
        // Bootstrap Icons fallback
        ensureCssLoaded('bi','https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css');
      });
    })();
  </script>
  <!-- JS Bootstrap (defer) avant le DOMContentLoaded pour assurer disponibilité) -->
  <script src="<?= htmlspecialchars($base) ?>/assets/vendor/bootstrap/bootstrap.bundle.min.js" defer></script>
  <script>
    // Fallback CDN si le local ne charge pas correctement avant DOMContentLoaded
    document.addEventListener('DOMContentLoaded', function(){
      if (!window.bootstrap) {
        var s=document.createElement('script');
        s.src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js';
        s.defer=true; document.head.appendChild(s);
      }
    });
  </script>
  <!-- Favicon -->
  <link rel="icon" href="<?= htmlspecialchars($favicon) ?>">
  <!-- Fallback local si les CDN sont inaccessibles -->
  <noscript><link rel="stylesheet" href="<?= htmlspecialchars($base) ?>/assets/css/fallback.css"></noscript>
  
  <style>
    :root {
      --primary-color: #0d6efd;
      --secondary-color: #6c757d;
      --success-color: #198754;
      --danger-color: #dc3545;
      --warning-color: #ffc107;
      --info-color: #0dcaf0;
    }
    
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
      background-color: #f4f6f9;
    }
    
    .wrapper {
      display: flex;
      flex-direction: column;
      min-height: 100vh;
    }
    
    .layout-fixed .wrapper {
      display: grid;
      grid-template-columns: 296px 1fr;
      grid-template-rows: auto 1fr auto;
      min-height: 100vh;
    }
    
    .layout-fixed .navbar {
      grid-column: 1 / -1;
      position: sticky;
      top: 0;
      z-index: 1030;
    }
    
    .layout-fixed .main-sidebar {
      grid-row: 2 / 4;
      grid-column: 1;
    }

    .layout-fixed .content-wrapper {
      grid-row: 2;
      grid-column: 2;
      overflow-y: auto;
      min-width: 0;
    }

    .layout-fixed .main-footer {
      grid-row: 3;
      grid-column: 2;
    }
    
    /* Flex fallback pour pages sans sidebar */
    .wrapper:not(.layout-fixed .wrapper) {
      min-height: 100vh;
      display: flex;
      flex-direction: column;
    }
    
    .navbar {
      background:
        radial-gradient(circle at left top, rgba(59,130,246,.24), transparent 26%),
        linear-gradient(92deg, #10233d 0%, #14325f 48%, #1d4c86 100%);
      box-shadow: 0 1rem 2rem rgba(15,23,42,.12);
      padding: 0.65rem 0 !important;
      border-bottom: 1px solid rgba(148,163,184,.18);
    }

    .topbar-shell {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      width: 100%;
    }

    .topbar-left,
    .topbar-right {
      display: flex;
      align-items: center;
      gap: .85rem;
      min-width: 0;
    }

    .topbar-menu-btn {
      width: 44px;
      height: 44px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: 1rem;
      color: #e2e8f0 !important;
      background: rgba(15,23,42,.26);
      border: 1px solid rgba(148,163,184,.18);
    }

    .topbar-menu-btn:hover {
      background: rgba(59,130,246,.18);
      color: #ffffff !important;
    }

    .navbar-brand {
      color: #fff !important;
      font-weight: 700;
      font-size: 1rem;
      display: flex;
      align-items: center;
      gap: 0.85rem;
      min-width: 0;
      margin-right: 0;
    }

    .navbar-brand img {
      height: 34px;
      width: auto;
      object-fit: contain;
      display: block;
      filter: drop-shadow(0 .35rem .55rem rgba(15,23,42,.18));
    }

    .topbar-brand-copy {
      display: flex;
      flex-direction: column;
      min-width: 0;
      line-height: 1.1;
    }

    .topbar-brand-title {
      color: #f8fafc;
      font-size: .98rem;
      font-weight: 800;
      letter-spacing: .02em;
    }

    .topbar-brand-subtitle {
      color: rgba(191,219,254,.86);
      font-size: .73rem;
      font-weight: 600;
      letter-spacing: .04em;
      text-transform: uppercase;
    }

    .topbar-context {
      display: flex;
      align-items: center;
      gap: .55rem;
      padding: .55rem .85rem;
      border-radius: 1rem;
      background: rgba(15,23,42,.24);
      border: 1px solid rgba(148,163,184,.14);
      color: #e2e8f0;
      min-width: 0;
    }

    .topbar-context i {
      color: #7dd3fc;
    }

    .topbar-context-copy {
      display: flex;
      flex-direction: column;
      min-width: 0;
    }

    .topbar-context-label {
      color: rgba(191,219,254,.7);
      font-size: .65rem;
      font-weight: 700;
      letter-spacing: .08em;
      text-transform: uppercase;
    }

    .topbar-context-value {
      color: #f8fafc;
      font-size: .84rem;
      font-weight: 700;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      max-width: 260px;
    }

    .topbar-chip {
      display: inline-flex;
      align-items: center;
      gap: .45rem;
      min-height: 40px;
      padding: .45rem .8rem;
      border-radius: .95rem;
      background: rgba(255,255,255,.08);
      border: 1px solid rgba(191,219,254,.15);
      color: #e2e8f0;
      font-size: .75rem;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
    }

    .topbar-chip i {
      color: #93c5fd;
    }

    .topbar-tools {
      display: flex;
      align-items: center;
      gap: .45rem;
    }

    .topbar-tools .nav-link,
    .topbar-user-toggle {
      width: 42px;
      height: 42px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: .95rem;
      color: #e2e8f0 !important;
      background: rgba(15,23,42,.24);
      border: 1px solid rgba(148,163,184,.14);
      transition: background .2s ease, transform .2s ease, border-color .2s ease;
    }

    .topbar-tools .nav-link:hover,
    .topbar-user-toggle:hover {
      background: rgba(59,130,246,.18);
      border-color: rgba(147,197,253,.22);
      transform: translateY(-1px);
      color: #ffffff !important;
    }

    .topbar-user-toggle {
      width: auto;
      gap: .55rem;
      padding: 0 .85rem;
      text-decoration: none;
    }

    .topbar-user-name {
      color: #f8fafc;
      font-size: .85rem;
      font-weight: 700;
    }

    .navbar-light .navbar-toggler {
      border: none;
      color: #fff !important;
    }

    .navbar-light .navbar-toggler:focus {
      box-shadow: none;
    }

    .navbar-light .navbar-nav .nav-link {
      color: rgba(255,255,255,0.8);
    }

    .navbar-light .navbar-nav .nav-link:hover {
      color: #fff;
    }
    
    .sidebar {
      padding: 0.8rem 0 1.1rem;
      overflow-x: hidden;
    }

    .main-sidebar,
    .main-sidebar * {
      box-sizing: border-box;
    }



    .sidebar-workspace {
      margin: 0 .9rem .9rem;
      padding: .95rem 1rem;
      border-radius: 1rem;
      background: linear-gradient(180deg, rgba(255,255,255,.08) 0%, rgba(255,255,255,.03) 100%);
      border: 1px solid rgba(148,163,184,.14);
      box-shadow: 0 .75rem 1.5rem rgba(15, 23, 42, .08);
      overflow: hidden;
    }

    .sidebar-workspace-label {
      display: inline-flex;
      align-items: center;
      gap: .4rem;
      margin-bottom: .7rem;
      color: #64748b;
      font-size: .68rem;
      font-weight: 800;
      letter-spacing: .08em;
      text-transform: uppercase;
    }

    .sidebar-user-card {
      display: block;
      margin: 0;
      padding: 0;
      border: 0;
      border-radius: 0;
      background: transparent;
      box-shadow: none;
      min-width: 0;
    }

    .sidebar-user-card .info {
      min-width: 0;
    }

    .sidebar-user-top {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: .8rem;
      align-items: center;
      margin-bottom: .85rem;
      min-width: 0;
    }

    .sidebar-user-avatar {
      width: 46px;
      height: 46px;
      border-radius: 1rem;
      background: linear-gradient(135deg, #0d6efd 0%, #38bdf8 100%) !important;
      box-shadow: 0 .9rem 1.4rem rgba(13,110,253,.2);
    }

    .sidebar-user-title {
      font-size: 1rem;
      font-weight: 700;
      color: #0f172a;
      margin: 0 0 .2rem;
    }

    .sidebar-user-subtitle {
      margin: 0;
      color: #64748b;
      font-size: .78rem;
      font-weight: 600;
      overflow-wrap: anywhere;
    }

    .sidebar-user-badges {
      display: flex;
      flex-wrap: wrap;
      gap: .5rem;
      align-items: center;
      margin-bottom: .8rem;
    }

    .sidebar-role-badge,
    .sidebar-sub-badge,
    .sidebar-status-badge {
      display: inline-flex;
      align-items: center;
      min-height: 25px;
      padding: .12rem .68rem;
      border-radius: 999px;
      font-size: .69rem;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
    }

    .sidebar-role-badge {
      background: rgba(13,110,253,.1);
      color: #0f5fd6;
      border: 1px solid rgba(13,110,253,.12);
    }

    .sidebar-sub-badge {
      background: rgba(22,163,74,.1);
      color: #15803d;
      border: 1px solid rgba(22,163,74,.12);
    }

    .sidebar-status-badge {
      background: rgba(249,115,22,.1);
      color: #c2410c;
      border: 1px solid rgba(249,115,22,.15);
    }

    .sidebar-user-stats {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: .6rem;
      margin-top: .8rem;
    }

    .sidebar-stat-card {
      padding: .75rem .8rem;
      border-radius: .9rem;
      background: rgba(248,250,252,.88);
      border: 1px solid rgba(203,213,225,.7);
    }

    .sidebar-stat-label {
      display: block;
      margin-bottom: .18rem;
      color: #64748b;
      font-size: .68rem;
      font-weight: 800;
      letter-spacing: .08em;
      text-transform: uppercase;
    }

    .sidebar-stat-value {
      display: block;
      color: #0f172a;
      font-size: .82rem;
      font-weight: 700;
      line-height: 1.25;
    }

    .sidebar-quick-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: .55rem;
      margin: 0 .9rem .95rem;
      min-width: 0;
    }

    .sidebar-quick-link {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: .35rem;
      min-height: 68px;
      padding: .65rem .5rem;
      border-radius: 1rem;
      text-decoration: none;
      background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
      border: 1px solid rgba(203,213,225,.9);
      box-shadow: 0 .55rem 1rem rgba(15, 23, 42, .05);
      transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
    }

    .sidebar-quick-link:hover {
      transform: translateY(-2px);
      border-color: rgba(13,110,253,.26);
      box-shadow: 0 .8rem 1.35rem rgba(13,110,253,.08);
    }

    .sidebar-quick-link.active {
      border-color: rgba(13,110,253,.24);
      background: linear-gradient(180deg, #eff6ff 0%, #ffffff 100%);
      box-shadow: 0 .85rem 1.4rem rgba(13,110,253,.1);
    }

    .sidebar-quick-link i {
      width: 32px;
      height: 32px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: .75rem;
      background: rgba(13,110,253,.1);
      color: #0d6efd;
      font-size: .88rem;
    }

    .sidebar-quick-link span {
      color: #0f172a;
      font-size: .72rem;
      font-weight: 700;
      text-align: center;
      white-space: nowrap;
    }

    .sidebar-search-shell {
      display: grid;
      grid-template-columns: 1fr auto;
      gap: .55rem;
      padding: .45rem;
      border-radius: 1rem;
      background: #ffffff;
      border: 1px solid rgba(203,213,225,.9);
      box-shadow: 0 .55rem 1rem rgba(15, 23, 42, .05);
      overflow: hidden;
    }

    .sidebar-search-input {
      min-height: 42px;
      border-radius: .85rem;
    }

    .sidebar-search-btn {
      min-width: 42px;
      border-radius: .85rem;
    }
    
    .sidebar .nav-link {
      color: #495057;
      transition: all 0.3s ease;
      padding: 0.75rem 1rem;
      border-left: 3px solid transparent;
    }
    
    .sidebar .nav-link:hover {
      color: #0d6efd;
      background-color: rgba(13, 110, 253, 0.08);
      border-left-color: #0d6efd;
    }
    
    .sidebar .nav-link.active {
      color: #0d6efd;
      background-color: rgba(13, 110, 253, 0.15);
      border-left-color: #0d6efd;
      font-weight: 600;
    }
    
    .sidebar .nav-link i {
      margin-right: 0.75rem;
      width: 20px;
      text-align: center;
    }
    
    .sidebar .nav-link .right {
      margin-left: auto;
    }
    
    .sidebar .nav-treeview {
      padding-left: 1rem;
    }
    
    .sidebar .nav-treeview .nav-link {
      padding: 0.5rem 1rem;
      font-size: 0.9rem;
    }
    
    .main-sidebar {
      position: sticky;
      top: var(--navbar-h, 62px);
      height: calc(100vh - var(--navbar-h, 62px));
      overflow-y: auto;
      overflow-x: hidden;
    }
    
    .content-wrapper {
      background:
        radial-gradient(circle at top right, rgba(59,130,246,.08), transparent 22%),
        linear-gradient(180deg, #f4f7fb 0%, #edf3f9 100%);
      padding: 1.35rem 0 2rem;
    }

    .content-header {
      margin: 0 2rem 1.35rem;
      padding: 1.15rem 1.35rem;
      border-radius: 1.25rem;
      background: linear-gradient(180deg, rgba(255,255,255,.95) 0%, rgba(248,250,252,.98) 100%);
      border: 1px solid rgba(203,213,225,.9);
      box-shadow: 0 .95rem 1.8rem rgba(15,23,42,.05);
    }

    .content-header .container-fluid {
      padding: 0;
    }

    .content-header h1 {
      font-size: 1.7rem;
      font-weight: 800;
      color: #0f172a;
      margin-bottom: .28rem;
    }

    .content-header-kicker {
      display: inline-flex;
      align-items: center;
      gap: .45rem;
      color: #64748b;
      font-size: .72rem;
      font-weight: 800;
      letter-spacing: .08em;
      text-transform: uppercase;
    }

    .content-header-kicker i {
      color: #0d6efd;
    }

    .content-header-subtitle {
      color: #64748b;
      font-size: .92rem;
      font-weight: 500;
      margin: 0;
    }

    .content-header-actions {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      gap: .65rem;
      flex-wrap: wrap;
    }

    .content-header-chip {
      display: inline-flex;
      align-items: center;
      gap: .45rem;
      min-height: 38px;
      padding: .42rem .8rem;
      border-radius: .9rem;
      background: rgba(13,110,253,.07);
      border: 1px solid rgba(13,110,253,.1);
      color: #0f172a;
      font-size: .74rem;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
    }

    .content-header-chip i {
      color: #0d6efd;
    }

    .breadcrumb {
      gap: .45rem;
      padding: .4rem .5rem;
      margin: 0;
      border-radius: .85rem;
      background: rgba(248,250,252,.9);
      border: 1px solid rgba(203,213,225,.8);
    }

    .breadcrumb-item,
    .breadcrumb-item a {
      color: #64748b;
      font-size: .82rem;
      font-weight: 600;
      text-decoration: none;
    }

    .breadcrumb-item.active {
      color: #0f172a;
      font-weight: 700;
    }

    .breadcrumb-item + .breadcrumb-item::before {
      color: #94a3b8;
    }
    
    .content {
      padding: 0 2rem;
    }
    
    .card {
      border: none;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
      border-radius: 0.5rem;
      margin-bottom: 1rem;
    }
    
    .card-header {
      background-color: #f8f9fa;
      border-bottom: 1px solid #e9ecef;
      font-weight: 600;
      padding: 1rem;
    }
    
    .card-header h5 {
      margin: 0;
      font-size: 1rem;
    }
    
    .badge {
      padding: 0.375rem 0.75rem;
      font-weight: 500;
    }
    
    .user-panel {
      padding: 1rem;
      margin-bottom: 1rem;
      border-bottom: 1px solid #e9ecef;
      display: flex;
      align-items: center;
      gap: 1rem;
    }
    
    .user-panel .image {
      flex-shrink: 0;
    }
    
    .user-panel .info {
      flex-grow: 1;
    }
    
    .user-panel .info p {
      margin: 0;
      font-weight: 600;
      color: #212529;
    }
    
    .user-panel .info small {
      color: #6c757d;
    }
    
    .main-footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      background: #fff;
      border-top: 1px solid #e2e8f0;
      padding: .6rem 2rem;
      font-size: .78rem;
      color: #94a3b8;
    }

    .footer-meta {
      display: flex;
      align-items: center;
      gap: .65rem;
    }

    .footer-badge {
      display: inline-flex;
      align-items: center;
      gap: .35rem;
      padding: .2rem .55rem;
      border-radius: .4rem;
      background: #f1f5f9;
      color: #475569;
      font-size: .7rem;
      font-weight: 700;
      letter-spacing: .04em;
    }
    
    .form-control, .form-select {
      border: 1px solid #d1d5db;
      border-radius: 0.375rem;
    }
    
    .form-control:focus, .form-select:focus {
      border-color: #0d6efd;
      box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
    }
    
    .btn {
      border-radius: 0.375rem;
      font-weight: 600;
      transition: all 0.3s ease;
    }
    
    .btn-primary {
      background-color: #0d6efd;
      border-color: #0d6efd;
    }
    
    .btn-primary:hover {
      background-color: #0a58ca;
      border-color: #0a58ca;
    }

    body.erp-modern-standard .content .card,
    body.erp-modern-standard .content .small-box,
    body.erp-modern-standard .content .info-box {
      border: 1px solid rgba(203,213,225,.9);
      border-radius: 1.15rem;
      box-shadow: 0 1rem 1.8rem rgba(15,23,42,.06);
      overflow: hidden;
      backdrop-filter: blur(8px);
      transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
    }

    body.erp-modern-standard .content .card:hover,
    body.erp-modern-standard .content .small-box:hover,
    body.erp-modern-standard .content .info-box:hover {
      transform: translateY(-2px);
      box-shadow: 0 1.2rem 2rem rgba(15,23,42,.08);
      border-color: rgba(96,165,250,.28);
    }

    body.erp-modern-standard .content .card {
      background: linear-gradient(180deg, rgba(255,255,255,.98) 0%, rgba(248,250,252,.98) 100%);
    }

    body.erp-modern-standard .content .card-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: .85rem;
      padding: 1rem 1.15rem;
      background: linear-gradient(180deg, rgba(248,250,252,.98) 0%, rgba(241,245,249,.96) 100%);
      border-bottom: 1px solid rgba(203,213,225,.85);
    }

    body.erp-modern-standard .content .card-header .card-title,
    body.erp-modern-standard .content .card-header h3,
    body.erp-modern-standard .content .card-header h5,
    body.erp-modern-standard .content .card-header h6 {
      margin: 0;
      color: #0f172a;
      font-weight: 800;
      letter-spacing: -.01em;
    }

    body.erp-modern-standard .content .card-body {
      padding: 1.15rem;
    }

    body.erp-modern-standard .content .table-responsive {
      border-radius: 1rem;
      border: 1px solid rgba(226,232,240,.95);
      background: rgba(255,255,255,.78);
    }

    body.erp-modern-standard .content .table {
      margin-bottom: 0;
      color: #1e293b;
      --bs-table-bg: transparent;
    }

    body.erp-modern-standard .content .table thead th {
      padding: .92rem .95rem;
      border-bottom: 1px solid rgba(203,213,225,.9);
      background: rgba(241,245,249,.85);
      color: #64748b;
      font-size: .73rem;
      font-weight: 800;
      letter-spacing: .07em;
      text-transform: uppercase;
      white-space: nowrap;
    }

    body.erp-modern-standard .content .table tbody td {
      padding: .95rem;
      border-color: rgba(226,232,240,.78);
      vertical-align: middle;
    }

    body.erp-modern-standard .content .table tbody tr:hover {
      background: rgba(239,246,255,.8);
    }

    body.erp-modern-standard .content .btn {
      border-radius: .9rem;
      font-weight: 700;
      letter-spacing: .01em;
      box-shadow: none;
    }

    body.erp-modern-standard .content .btn-sm {
      min-height: 36px;
      padding: .48rem .82rem;
      border-radius: .82rem;
    }

    body.erp-modern-standard .content .btn-lg {
      border-radius: 1rem;
    }

    body.erp-modern-standard .content .btn-primary,
    body.erp-modern-standard .content .btn-success,
    body.erp-modern-standard .content .btn-warning,
    body.erp-modern-standard .content .btn-danger,
    body.erp-modern-standard .content .btn-info {
      box-shadow: 0 .8rem 1.3rem rgba(15,23,42,.08);
    }

    body.erp-modern-standard .content .btn-outline-primary,
    body.erp-modern-standard .content .btn-outline-secondary,
    body.erp-modern-standard .content .btn-outline-success,
    body.erp-modern-standard .content .btn-outline-warning,
    body.erp-modern-standard .content .btn-outline-danger,
    body.erp-modern-standard .content .btn-outline-info {
      background: rgba(255,255,255,.78);
      border-width: 1px;
    }

    body.erp-modern-standard .content .form-control,
    body.erp-modern-standard .content .form-select {
      min-height: 46px;
      border-radius: .92rem;
      border-color: rgba(203,213,225,.95);
      background: rgba(255,255,255,.96);
      box-shadow: inset 0 1px 0 rgba(255,255,255,.75);
    }

    body.erp-modern-standard .content textarea.form-control {
      min-height: 110px;
    }

    body.erp-modern-standard .content .form-label,
    body.erp-modern-standard .content label {
      color: #475569;
      font-weight: 700;
      letter-spacing: .01em;
    }

    body.erp-modern-standard .content .badge {
      border-radius: 999px;
      font-weight: 700;
      letter-spacing: .02em;
    }

    body.erp-modern-standard .content .alert {
      border: 1px solid rgba(191,219,254,.9);
      border-radius: 1rem;
      box-shadow: 0 .85rem 1.4rem rgba(15,23,42,.05);
    }

    body.erp-modern-standard .content .small-box {
      border-radius: 1.15rem;
      overflow: hidden;
    }

    body.erp-modern-standard .content .small-box .inner,
    body.erp-modern-standard .content .small-box .icon {
      position: relative;
      z-index: 1;
    }

    body.erp-modern-standard .content .small-box::after {
      content: '';
      position: absolute;
      inset: 0;
      background: linear-gradient(135deg, rgba(255,255,255,.14), transparent 55%);
      pointer-events: none;
    }

    body.erp-modern-standard .content .kpi-card .card-body,
    body.erp-modern-standard .content .section-card .card-body {
      background-image: radial-gradient(circle at top right, rgba(255,255,255,.35), transparent 32%);
    }

    body.erp-modern-standard .content .nav-pills .nav-link {
      border-radius: .9rem;
      font-weight: 700;
    }

    body.erp-modern-standard .content .dropdown-menu {
      border-radius: 1rem;
      border-color: rgba(203,213,225,.9);
      box-shadow: 0 1rem 1.8rem rgba(15,23,42,.12);
    }
    
    /* Tablette + mobile : sidebar en mode "drawer", layout pleine largeur */
    @media (max-width: 991.98px) {
      .layout-fixed .wrapper {
        grid-template-columns: 1fr;
      }

      .layout-fixed .content-wrapper {
        grid-column: 1;
      }

      .layout-fixed .main-sidebar {
        position: fixed;
        left: 0;
        top: var(--navbar-h, 62px);
        bottom: 0;
        width: 296px;
        z-index: 1050;
        transform: translateX(-100%);
        transition: transform .3s ease-in-out;
        box-shadow: 2px 0 8px rgba(0,0,0,0.15);
      }

      /* Overlay sombre derrière la sidebar */
      body::after {
        content: '';
        position: fixed;
        top: var(--navbar-h, 62px);
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, 0.5);
        z-index: 1040;
        opacity: 0;
        visibility: hidden;
        transition: opacity .3s ease-in-out, visibility .3s ease-in-out;
      }
    }

    /* Quand le body a .sidebar-open, afficher la sidebar et l'overlay */
    @media (max-width: 991.98px) {
      body.sidebar-open .main-sidebar {
        transform: translateX(0);
      }

      body.sidebar-open::after {
        opacity: 1;
        visibility: visible;
      }
    }

    /* Mobile seulement : ajustements topbar et content-header */
    @media (max-width: 768px) {
      .topbar-shell {
        gap: .65rem;
      }

      .topbar-context,
      .topbar-chip {
        display: none;
      }

      .topbar-user-name {
        display: none;
      }

      .content-header {
        margin: 0 1rem 1rem;
        padding: 1rem;
      }

      .content-header-actions {
        justify-content: flex-start;
        margin-top: .85rem;
      }
    }
    /* Sidebar style Bootstrap */
    :root {
      --sidebar-bg: #edf2f7;
      --sidebar-link: #1e293b;
      --sidebar-link-hover-bg: rgba(13,110,253,.08);
      --sidebar-link-active-bg: rgba(13,110,253,.14);
      --sidebar-border: #d8e1ea;
      --sidebar-header: #64748b;
      --sidebar-input-bg: #ffffff;
      --sidebar-input-border: #d0d7de;
      --sidebar-input-text: #212529;
      --sidebar-input-placeholder: #6c757d;
    }
    .main-sidebar.sidebar-dark-primary {
      background:
        linear-gradient(180deg, #f5f7fb 0%, #ebf1f7 48%, #e4ebf4 100%) !important;
      border-right: 1px solid var(--sidebar-border);
      box-shadow: 0 0 0 1px rgba(255,255,255,.65), 0 1rem 2rem rgba(15, 23, 42, .08);
    }
    .sidebar-dark-primary .brand-link {
      border-bottom: 1px solid rgba(148,163,184,.14);
    }
    .sidebar-dark-primary .brand-link .brand-text strong { color: #ffffff !important; }
    .sidebar-dark-primary .brand-link .brand-text small { color: rgba(226,232,240,.78) !important; }
    .sidebar-dark-primary .nav-sidebar .nav-link {
      color: var(--sidebar-link);
      border-radius: .95rem;
      border: 1px solid transparent;
      background: rgba(255,255,255,.64);
    }
    .sidebar-dark-primary .nav-sidebar .nav-link .nav-icon {
      margin-right: .65rem;
      width: 1.9rem;
      text-align: center;
      color: #0d6efd;
      opacity: .92;
    }
    .sidebar-dark-primary .nav-sidebar .nav-link:hover {
      background-color: var(--sidebar-link-hover-bg);
      color: #0d6efd;
      border-color: rgba(13,110,253,.12);
    }
    .sidebar-dark-primary .nav-sidebar .nav-link.active {
      background: linear-gradient(90deg, rgba(13,110,253,.16) 0%, rgba(13,110,253,.06) 100%);
      color: #0d6efd;
      border-color: rgba(13,110,253,.18);
      box-shadow: 0 .5rem 1rem rgba(13,110,253,.08);
    }
    .sidebar-dark-primary .nav-header { color: var(--sidebar-header); font-size: .69rem; letter-spacing: .08em; padding: .35rem .9rem .1rem; text-transform: uppercase; }
    .nav-sidebar>.nav-item .right { transition: transform .2s ease; }
    .menu-open>.nav-link .right { transform: rotate(-90deg); }
    /* Amélioration visuelle du menu */
    .nav-sidebar .nav-item { margin-bottom: 0.38rem; }
    .nav-sidebar .nav-link { 
      display: flex;
      align-items: center;
      min-height: 46px;
      padding: 0.76rem 1rem; 
      transition: all 0.2s ease-in-out;
    }
    .nav-sidebar .nav-link:hover {
      transform: translateX(3px);
      box-shadow: 0 .5rem 1rem rgba(13,110,253,.08);
    }
    .nav-sidebar .nav-link.active {
      border-left: 0;
      background: linear-gradient(90deg, var(--sidebar-link-active-bg) 0%, rgba(13,110,253,.05) 100%);
    }
    .nav-icon-sm { font-size: 0.7rem; opacity: 0.6; }
    .nav-header {
      position: relative;
      margin: 1rem .9rem .45rem;
      padding: .6rem .85rem .52rem 1rem !important;
      background: linear-gradient(180deg, rgba(255,255,255,.82) 0%, rgba(248,250,252,.96) 100%);
      border: 1px solid var(--sidebar-border);
      border-radius: .9rem;
      box-shadow: inset 0 1px 0 rgba(255,255,255,.75);
    }
    .nav-header::before {
      content: '';
      position: absolute;
      left: .7rem;
      top: 50%;
      width: 4px;
      height: 56%;
      transform: translateY(-50%);
      background: linear-gradient(180deg, #0d6efd 0%, #38bdf8 100%);
      border-radius: 999px;
    }
    /* Sidebar search controls in dark theme */
    .sidebar-dark-primary .form-control { background-color: var(--sidebar-input-bg); border-color: var(--sidebar-input-border); color: var(--sidebar-input-text); }
    .sidebar-dark-primary .form-control::placeholder { color: var(--sidebar-input-placeholder); }
    .sidebar-dark-primary .btn.btn-secondary { background-color: #0d6efd; border-color: #0d6efd; color: #fff; }
    .sidebar-dark-primary .btn.btn-secondary:hover { background-color: #0b5ed7; border-color: #0b5ed7; color: #fff; }
    .sidebar-search-shell {
      background: #ffffff;
      border: 1px solid var(--sidebar-border);
      box-shadow: 0 .5rem 1rem rgba(15, 23, 42, .04);
    }
    .sidebar-search-input {
      border-color: transparent !important;
      box-shadow: none !important;
      background: transparent !important;
    }
    .sidebar-search-btn {
      box-shadow: none !important;
    }
    .sidebar-menu-shell {
      margin: 0 .9rem;
      padding: .45rem;
      border-radius: 1.15rem;
      background: linear-gradient(180deg, rgba(255,255,255,.58) 0%, rgba(248,250,252,.92) 100%);
      border: 1px solid rgba(203,213,225,.9);
      box-shadow: 0 .85rem 1.4rem rgba(15, 23, 42, .05);
      overflow-x: hidden;
    }

    .sidebar .nav-link p,
    .admin-mega-list .nav-link p,
    .brand-text,
    .sidebar-user-title {
      min-width: 0;
      overflow-wrap: anywhere;
      word-break: break-word;
    }
    .sidebar .nav-header {
      margin: .7rem .35rem .45rem;
    }
    .admin-treeview {
      margin-top: .45rem;
      padding: .25rem .3rem .35rem .95rem;
      border-left: 1px dashed rgba(13,110,253,.16);
    }
    .admin-mega-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: .7rem;
      margin: .2rem 0 0;
    }
    .admin-mega-card {
      padding: .78rem;
      border-radius: 1rem;
      border: 1px solid rgba(13,110,253,.1);
      background: linear-gradient(180deg, #ffffff 0%, #f7fbff 100%);
      box-shadow: 0 .5rem 1rem rgba(15, 23, 42, .05);
    }
    .admin-mega-title {
      display: flex;
      align-items: center;
      gap: .55rem;
      margin-bottom: .6rem;
      color: #0f172a;
      font-size: .78rem;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
    }
    .admin-mega-title i {
      width: 28px;
      height: 28px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: .7rem;
      background: rgba(13,110,253,.1);
      color: #0d6efd;
    }
    .admin-mega-list .nav-link {
      min-height: 40px;
      padding: .62rem .8rem;
      border-radius: .85rem;
    }
    .admin-mega-list .nav-link p {
      font-size: .84rem;
      font-weight: 600;
    }
    @media (max-width: 768px) {
      .sidebar-quick-grid {
        grid-template-columns: 1fr;
      }

      .sidebar-user-stats {
        grid-template-columns: 1fr;
      }
    }
    .admin-mega-list {
      display: grid;
      gap: .4rem;
    }
    .admin-mega-list .nav-item {
      margin: 0;
    }
    .admin-mega-list .nav-link {
      min-height: 42px;
      padding: .55rem .75rem;
      border-radius: .85rem;
      background: rgba(248,249,250,.9);
      border: 1px solid rgba(13,110,253,.08);
    }
    .admin-mega-list .nav-link p {
      font-size: .89rem;
      line-height: 1.2;
      white-space: normal;
    }
    @media (max-width: 991.98px) {
      .admin-mega-grid {
        grid-template-columns: 1fr;
      }
    }
    .admin-tree-group-label {
      display: flex;
      align-items: center;
      gap: .5rem;
      margin: .65rem .55rem .35rem;
      padding: .35rem .75rem;
      border-radius: .75rem;
      background: rgba(13,110,253,.06);
      color: #6c757d;
      font-size: .72rem;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
    }
    .admin-tree-group-label i {
      color: #0d6efd;
    }
    .admin-treeview .nav-link {
      background: transparent;
      border-color: transparent;
      box-shadow: none;
    }
  </style>
</head>
<body class="<?= htmlspecialchars(implode(' ', $bodyClasses)) ?>">
  <div class="wrapper">
    
    <!-- Navbar -->
    <nav class="main-header navbar navbar-expand navbar-dark navbar-primary">
      <div class="container-fluid">
        <div class="topbar-shell">
          <div class="topbar-left">
            <a class="nav-link topbar-menu-btn" data-lte-toggle="sidebar" href="#" role="button"><i class="fas fa-bars"></i></a>

            <a class="navbar-brand" href="<?= htmlspecialchars(route_url('/dashboard')) ?>">
              <img src="<?= htmlspecialchars($brandLogo) ?>" onerror="this.style.display='none'" alt="Logo">
              <span class="topbar-brand-copy">
                <span class="topbar-brand-title"><?= htmlspecialchars($brandName) ?></span>
                <span class="topbar-brand-subtitle">Centre de pilotage</span>
              </span>
            </a>

            <div class="topbar-context">
              <i class="fas fa-diagram-project"></i>
              <span class="topbar-context-copy">
                <span class="topbar-context-label">Module actif</span>
                <span class="topbar-context-value"><?= htmlspecialchars($title ?? 'Console métier') ?></span>
              </span>
            </div>
          </div>

          <div class="topbar-right">
            <?php if ($u): ?>
              <span class="topbar-chip"><i class="fas fa-signal"></i> exploitation</span>
            <?php endif; ?>

            <div class="topbar-tools">
            <?php if ($u): ?>
              <?php 
                try {
                  $pdo = Database::pdo();
                  // Récupérer takeover_at de l'utilisateur courant
                  $tk = $pdo->prepare('SELECT takeover_at FROM users WHERE id=?');
                  $tk->execute([(int)($u['id'] ?? 0)]);
                  $takeoverAt = $tk->fetchColumn();
                  $st = $pdo->prepare('SELECT COUNT(*) FROM notifications WHERE user_id=? AND is_read=0');
                  $st->execute([(int)($u['id'] ?? 0)]);
                  $unreadCount = (int)$st->fetchColumn();
                  $lst = $pdo->prepare('SELECT * FROM notifications WHERE user_id=? ORDER BY created_at DESC LIMIT 10');
                  $lst->execute([(int)($u['id'] ?? 0)]);
                  $notifRows = $lst->fetchAll() ?: [];
                } catch (\Throwable $e) {
                  $unreadCount = 0; $notifRows = []; $takeoverAt = null;
                }
              ?>

              <div class="nav-item dropdown me-1">
                <a class="nav-link position-relative" href="#" id="notifDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false" title="Notifications">
                  <i class="far fa-bell"></i>
                  <span id="notifBadge" class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger" <?= $unreadCount > 0 ? '' : 'hidden' ?>><?= $unreadCount ?></span>
                </a>
                <ul id="notifDropdownMenu" class="dropdown-menu dropdown-menu-end p-0 overflow-auto" aria-labelledby="notifDropdown" style="min-width: 200px; max-width: 60vw; max-height: 420px;">
                  <li class="px-3 py-2 border-bottom d-flex justify-content-between align-items-center">
                    <strong>Notifications</strong>
                    <form id="notifReadAllForm" method="post" action="<?= htmlspecialchars(route_url('/notifications/read-all')) ?>" class="m-0">
                      <button id="notifReadAllButton" class="btn btn-sm btn-link">Tout marquer comme lu</button>
                    </form>
                  </li>
                  <div id="notifDropdownBody">
                    <?php if (empty($notifRows)): ?>
                      <div class="px-3 py-3 text-muted">Aucune notification</div>
                    <?php else: ?>
                      <?php
                        $displayLimit = 3;
                        $isMentionNotif = function(array $n): bool {
                          $t = strtolower((string)($n['title'] ?? ''));
                          $b = strtolower((string)($n['body'] ?? ''));
                          if (str_contains($t, 'mention')) { return true; }
                          if (str_contains($b, 'mention')) { return true; }
                          return (bool)preg_match('/@\[[^\]]+\]|@[a-z0-9_\.-]+/i', (string)($n['body'] ?? ''));
                        };

                        $mentionRows = array_values(array_filter($notifRows, $isMentionNotif));
                        $otherRows = array_values(array_filter($notifRows, fn($n)=>!$isMentionNotif($n)));
                        $displayRows = array_slice(array_merge($mentionRows, $otherRows), 0, $displayLimit);
                      ?>
                      <?php foreach ($displayRows as $n): ?>
                        <li>
                          <div class="dropdown-item small notification-entry <?= ((int)$n['is_read']===0?'fw-semibold':'') ?>" data-notification-id="<?= (int)($n['id'] ?? 0) ?>">
                            <div class="d-flex align-items-start gap-2">
                              <i class="fas fa-circle<?= ((int)$n['is_read']===0?' text-primary':' text-secondary') ?> notification-entry-dot" style="font-size:.5rem; margin-top:.45rem;"></i>
                              <div class="flex-grow-1 min-w-0">
                                <a class="text-decoration-none d-block notification-entry-link" href="<?= htmlspecialchars($n['url'] ?: route_url('/notifications')) ?>" data-notification-id="<?= (int)($n['id'] ?? 0) ?>">
                                  <div>
                                    <?= htmlspecialchars($n['title']) ?>
                                    <?php if ($isMentionNotif($n)): ?>
                                      <span class="badge text-bg-warning ms-1">Mention</span>
                                    <?php endif; ?>
                                  </div>
                                  <?php if (!empty($n['body'])): ?><div class="text-muted"><?= htmlspecialchars($n['body']) ?></div><?php endif; ?>
                                  <div class="text-muted"><?= date('d/m H:i', strtotime($n['created_at'])) ?></div>
                                </a>
                              </div>
                              <?php if ((int)($n['is_read'] ?? 0) === 0): ?>
                                <button type="button" class="btn btn-sm btn-link p-0 text-nowrap notification-mark-read" data-notification-id="<?= (int)($n['id'] ?? 0) ?>">Marquer comme lu</button>
                              <?php endif; ?>
                            </div>
                          </div>
                        </li>
                      <?php endforeach; ?>
                      <li><hr class="dropdown-divider"></li>
                      <li><a class="dropdown-item text-center" href="<?= htmlspecialchars(route_url('/notifications')) ?>">Voir plus</a></li>
                    <?php endif; ?>
                  </div>
                </ul>
              </div>
            <?php endif; ?>

            <div class="nav-item">
              <a class="nav-link" href="#" data-lte-toggle="control-sidebar" data-lte-target="#control-sidebar" role="button" title="Panneau rapide">
                <i class="fas fa-sliders-h"></i>
              </a>
            </div>

            <?php if ($u): ?>
              <div class="nav-item dropdown">
                <a class="nav-link dropdown-toggle topbar-user-toggle" href="#" id="userDropdown" role="button" data-bs-toggle="dropdown">
                  <i class="far fa-user-circle"></i>
                  <span class="topbar-user-name"><?= htmlspecialchars($u['name'] ?? ($u['email'] ?? 'User')) ?></span>
                </a>
                <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
                  <li><a class="dropdown-item" href="<?= htmlspecialchars(route_url('/users/profile')) ?>"><i class="fas fa-id-badge"></i> Profil</a></li>
                  <li><a class="dropdown-item" href="<?= htmlspecialchars(route_url('/settings')) ?>"><i class="fas fa-gear"></i> Paramètres</a></li>
                  <li><hr class="dropdown-divider"></li>
                  <li><a class="dropdown-item" href="<?= htmlspecialchars(route_url('/logout')) ?>"><i class="fas fa-right-from-bracket"></i> Déconnexion</a></li>
                </ul>
              </div>
            <?php else: ?>
              <a class="btn btn-light" href="<?= htmlspecialchars(route_url('/login')) ?>">Connexion</a>
            <?php endif; ?>
            </div>
          </div>
        </div>
      </div>
    </nav>
    <!-- /.navbar -->
    
    <?php if ($u): ?>
    <!-- Sidebar -->
    <aside class="main-sidebar sidebar-dark-primary elevation-4">
      <div class="sidebar">

        <section class="sidebar-workspace">
          <div class="sidebar-workspace-label"><i class="fas fa-briefcase"></i> Poste opérateur</div>

          <div class="sidebar-user-card">
            <div class="sidebar-user-top">
              <div class="image">
                <div class="text-white d-flex align-items-center justify-content-center sidebar-user-avatar">
                  <i class="fas fa-user" style="font-size:1.1rem;"></i>
                </div>
              </div>
              <div class="info">
                <p class="sidebar-user-title"><?= htmlspecialchars($u['name'] ?? 'User') ?></p>
                <p class="sidebar-user-subtitle" style="font-size:.72rem;"><?= htmlspecialchars($u['email'] ?? '') ?></p>
              </div>
            </div>

            <div class="sidebar-user-badges">
              <span class="sidebar-role-badge"><?= htmlspecialchars(ucfirst($u['role_key'] ?? 'guest')) ?></span>
              <span class="sidebar-status-badge" style="display:inline-flex;align-items:center;gap:.3rem;">
                <span style="width:5px;height:5px;border-radius:50%;background:#f97316;display:inline-block;"></span>
                Session active
              </span>
            </div>
          </div>
        </section>

        <div class="sidebar-quick-grid">
          <a href="<?= htmlspecialchars(route_url('/dashboard')) ?>" class="sidebar-quick-link <?= str_contains($currentPath, '/dashboard') ? 'active' : '' ?>">
            <i class="fas fa-chart-pie"></i>
            <span>Dashboard</span>
          </a>
          <a href="<?= htmlspecialchars(route_url('/incidents')) ?>" class="sidebar-quick-link <?= str_contains($currentPath, '/incidents') ? 'active' : '' ?>">
            <i class="fas fa-triangle-exclamation"></i>
            <span>Incidents</span>
          </a>
          <a href="<?= htmlspecialchars(route_url('/planning')) ?>" class="sidebar-quick-link <?= str_contains($currentPath, '/planning') ? 'active' : '' ?>">
            <i class="fas fa-calendar-check"></i>
            <span>Planning</span>
          </a>
        </div>

        <!-- Sidebar Search -->
        <div class="form-inline px-3 mb-2">
          <div class="sidebar-search-shell">
            <input class="form-control sidebar-search-input" type="search" placeholder="Rechercher un ticket, un client..." aria-label="Search" onkeydown="if(event.key==='Enter'){window.location='<?= htmlspecialchars(route_url('/incidents')) ?>?query='+encodeURIComponent(this.value)}">
            <button class="btn btn-secondary sidebar-search-btn" onclick="const i=this.previousElementSibling; window.location='<?= htmlspecialchars(route_url('/incidents')) ?>?query='+encodeURIComponent(i.value)"><i class="fas fa-search"></i></button>
          </div>
        </div>

        <!-- Sidebar Menu -->
        <div class="sidebar-menu-shell">
        <nav>
          <ul class="nav nav-pills nav-sidebar nav-flat flex-column nav-child-indent" data-lte-toggle="treeview" role="menu" data-accordion="false">
            
            <!-- Dashboard -->
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/dashboard')) ?>" class="nav-link <?= (str_ends_with($currentPath, '/dashboard') || str_contains($currentPath, '/dashboard')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-chart-line text-info"></i>
                <p>Tableau de bord</p>
              </a>
            </li>

            <!-- Opérations Section -->
            <li class="nav-header text-uppercase" style="font-size: 0.7rem; font-weight: 600; letter-spacing: 0.5px; margin-top: 1rem;">Opérations</li>
            
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/incidents')) ?>" class="nav-link <?= (str_contains($currentPath, '/incidents')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-exclamation-circle text-danger"></i>
                <p>Incidents</p>
                <?php 
                // Optionnel: Badge compteur d'incidents ouverts
                $openCount = 0; // À remplacer par vraie donnée si disponible
                if ($openCount > 0): 
                ?>
                <span class="badge badge-danger right"><?= $openCount ?></span>
                <?php endif; ?>
              </a>
            </li>

            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/clients')) ?>" class="nav-link <?= (str_contains($currentPath, '/clients')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-building text-info"></i>
                <p>Clients</p>
              </a>
            </li>

            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/planning')) ?>" class="nav-link <?= (str_contains($currentPath, '/planning')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-calendar-alt text-primary"></i>
                <p>Planning</p>
              </a>
            </li>

            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/maintenance-ftth')) ?>" class="nav-link <?= (str_contains($currentPath, '/maintenance-ftth')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-network-wired text-primary"></i>
                <p>Maintenance FTTH B2B</p>
              </a>
            </li>

            <?php $showRaccordementModule = \App\Core\ModuleManager::isVisible(\App\Core\Database::pdo(), 'raccordement_clients'); ?>
            <?php if ($showRaccordementModule): ?>
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/raccordement-clients')) ?>" class="nav-link <?= (str_contains($currentPath, '/raccordement-clients')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-plug-circle-bolt text-primary"></i>
                <p>Raccordement Clients</p>
              </a>
            </li>
            <?php endif; ?>

            <?php $showProspectModule = \App\Core\ModuleManager::isVisible(\App\Core\Database::pdo(), 'prospect_clients'); ?>
            <?php if ($showProspectModule && in_array($u['role_key'] ?? '', ['admin', 'agent', 'manager', 'superviseur', 'supervisor'], true)): ?>
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/prospect-clients')) ?>" class="nav-link <?= (str_contains($currentPath, '/prospect-clients')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-users-viewfinder text-success"></i>
                <p>Prospects & Clients</p>
              </a>
            </li>
            <?php endif; ?>

            <?php $showOtbModule = \App\Core\ModuleManager::isVisible(\App\Core\Database::pdo(), 'otb_management'); ?>
            <?php if ($showOtbModule && in_array($u['role_key'] ?? '', ['admin', 'manager', 'superviseur', 'supervisor'], true)): ?>
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/otb-management')) ?>" class="nav-link <?= (str_contains($currentPath, '/otb-management')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-boxes-packing text-success"></i>
                <p>Gestion des boîtiers OTB</p>
              </a>
            </li>
            <?php endif; ?>

            <?php if (in_array($u['role_key'] ?? '', ['admin', 'agent', 'manager', 'superviseur', 'supervisor'])): ?>
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/quotes')) ?>" class="nav-link <?= (str_contains($currentPath, '/quotes')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-file-invoice-dollar text-success"></i>
                <p>Devis</p>
              </a>
            </li>
            <?php endif; ?>

            <?php if (in_array($u['role_key'] ?? '', ['admin', 'manager', 'superviseur', 'supervisor'], true)): ?>
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/cartographie')) ?>" class="nav-link <?= (str_contains($currentPath, '/cartographie')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-map-marked-alt text-warning"></i>
                <p>Cartographie</p>
              </a>
            </li>
            <?php endif; ?>

            <!-- Section Superviseur -->
            <?php if (in_array($u['role_key'] ?? '', ['admin', 'manager', 'superviseur', 'supervisor'])): ?>
            <li class="nav-header text-uppercase" style="font-size: 0.7rem; font-weight: 600; letter-spacing: 0.5px; margin-top: 1.25rem;">Supervision</li>
            
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/supervisor/dashboard')) ?>" class="nav-link <?= (str_contains($currentPath, '/supervisor/dashboard')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-user-tie text-info"></i>
                <p>Dashboard Superviseur</p>
              </a>
            </li>
            
            <li class="nav-item">
              <a href="<?= htmlspecialchars(route_url('/supervisor/technicians')) ?>" class="nav-link <?= (str_contains($currentPath, '/supervisor/technicians')) ? 'active' : '' ?>">
                <i class="nav-icon fas fa-users-cog text-primary"></i>
                <p>Gestion Techniciens</p>
              </a>
            </li>
            <?php endif; ?>

            <!-- Administration Section (Admin only) -->
            <?php if (($u['role_key'] ?? '') === 'admin'): ?>
            <li class="nav-header text-uppercase" style="font-size: 0.7rem; font-weight: 600; letter-spacing: 0.5px; margin-top: 1.25rem;">Administration</li>
            
            <li class="nav-item <?= (preg_match('#/(settings|users|roles|catalog|sla|referentials|mobile-licenses)#', $currentPath) ? 'menu-open' : '') ?>">
              <a href="#" class="nav-link <?= (preg_match('#/(settings|users|roles|catalog|sla|referentials|mobile-licenses)#', $currentPath) ? 'active' : '') ?>">
                <i class="nav-icon fas fa-sliders-h text-secondary"></i>
                <p>
                  Centre d'administration
                  <i class="right fas fa-angle-left"></i>
                </p>
              </a>
              <ul class="nav nav-treeview admin-treeview">
                <li class="w-100">
                  <div class="admin-mega-grid">
                    <section class="admin-mega-card">
                      <div class="admin-mega-title"><i class="fas fa-gauge-high"></i><span>Pilotage</span></div>
                      <ul class="nav admin-mega-list">
                        <li class="nav-item">
                          <a href="<?= htmlspecialchars(route_url('/settings')) ?>" class="nav-link <?= (str_contains($currentPath, '/settings')) ? 'active' : '' ?>">
                            <i class="nav-icon fas fa-sliders nav-icon-sm text-primary"></i>
                            <p>Paramètres généraux</p>
                          </a>
                        </li>
                        <li class="nav-item">
                          <a href="<?= htmlspecialchars(route_url('/sla')) ?>" class="nav-link <?= (str_contains($currentPath, '/sla')) ? 'active' : '' ?>">
                            <i class="nav-icon fas fa-stopwatch nav-icon-sm text-warning"></i>
                            <p>SLA & niveaux de service</p>
                          </a>
                        </li>
                        <li class="nav-item">
                          <a href="<?= htmlspecialchars(route_url('/referentials')) ?>" class="nav-link <?= (str_contains($currentPath, '/referentials')) ? 'active' : '' ?>">
                            <i class="nav-icon fas fa-diagram-project nav-icon-sm text-info"></i>
                            <p>Référentiels métier</p>
                          </a>
                        </li>
                      </ul>
                    </section>

                    <section class="admin-mega-card">
                      <div class="admin-mega-title"><i class="fas fa-shield-halved"></i><span>Accès</span></div>
                      <ul class="nav admin-mega-list">
                        <li class="nav-item">
                          <a href="<?= htmlspecialchars(route_url('/users')) ?>" class="nav-link <?= (str_contains($currentPath, '/users')) ? 'active' : '' ?>">
                            <i class="nav-icon fas fa-users nav-icon-sm text-success"></i>
                            <p>Utilisateurs</p>
                          </a>
                        </li>
                        <li class="nav-item">
                          <a href="<?= htmlspecialchars(route_url('/mobile-licenses')) ?>" class="nav-link <?= (str_contains($currentPath, '/mobile-licenses')) ? 'active' : '' ?>">
                            <i class="nav-icon fas fa-mobile-screen-button nav-icon-sm text-info"></i>
                            <p>Licences mobiles</p>
                          </a>
                        </li>
                        <li class="nav-item">
                          <a href="<?= htmlspecialchars(route_url('/roles')) ?>" class="nav-link <?= (str_contains($currentPath, '/roles')) ? 'active' : '' ?>">
                            <i class="nav-icon fas fa-user-lock nav-icon-sm text-danger"></i>
                            <p>Rôles & permissions</p>
                          </a>
                        </li>
                      </ul>
                    </section>

                    <section class="admin-mega-card">
                      <div class="admin-mega-title"><i class="fas fa-boxes-stacked"></i><span>Offre</span></div>
                      <ul class="nav admin-mega-list">
                        <li class="nav-item">
                          <a href="<?= htmlspecialchars(route_url('/catalog')) ?>" class="nav-link <?= (str_contains($currentPath, '/catalog')) ? 'active' : '' ?>">
                            <i class="nav-icon fas fa-box-open nav-icon-sm text-secondary"></i>
                            <p>Catalogue & ressources</p>
                          </a>
                        </li>
                      </ul>
                    </section>
                  </div>
                </li>
              </ul>
            </li>
            <?php endif; ?>

          </ul>
        </nav>
        </div>
        <!-- /.sidebar-menu -->
        
      </div>
      <!-- /.sidebar -->
    </aside>
    <!-- /.main-sidebar -->
    
    <!-- Content Wrapper -->
    <div class="content-wrapper">
      <div class="content-header">
        <div class="container-fluid">
          <div class="row g-3 align-items-center">
            <div class="col-lg-7">
              <span class="content-header-kicker"><i class="fas fa-layer-group"></i> cockpit métier</span>
              <h1 class="m-0"><?= htmlspecialchars($pageTitle ?? $title ?? $brandName) ?></h1>
              <p class="content-header-subtitle">Pilotage opérationnel, supervision et accès rapide aux modules de production.</p>
            </div>
            <div class="col-lg-5">
              <div class="content-header-actions">
                <span class="content-header-chip"><i class="fas fa-calendar-day"></i> <?= date('d/m/Y') ?></span>
                <span class="content-header-chip"><i class="fas fa-wave-square"></i> session en ligne</span>
                <ol class="breadcrumb mb-0">
                <li class="breadcrumb-item"><a href="<?= htmlspecialchars(route_url('/dashboard')) ?>">Accueil</a></li>
                <li class="breadcrumb-item active" aria-current="page"><?= htmlspecialchars($pageTitle ?? $title ?? 'Tableau de bord') ?></li>
                </ol>
              </div>
            </div>
          </div>
        </div>
      </div>
      
      <div class="content">
        <div class="container-fluid">
          <?= $content ?? '' ?>
        </div>
      </div>
    </div>
    <!-- /.content-wrapper -->
    
    <?php else: ?>
    
    <!-- Guest Content (no sidebar) -->
    <div class="content-wrapper" style="background-color: #fff; min-height: 100vh;">
      <div class="content">
        <div class="container py-5">
          <?= $content ?? '' ?>
        </div>
      </div>
    </div>
    
    <?php endif; ?>
    
    
    
    <!-- Footer -->
    <footer class="main-footer">
      <span><?= htmlspecialchars($brandName) ?> &copy; <?= date('Y') ?> — Tous droits réservés.</span>
      <div class="footer-meta">
        <span class="footer-badge"><i class="fas fa-code-branch"></i> v1.0.0</span>
        <span class="footer-badge"><i class="fas fa-circle" style="font-size:.45rem;color:#22c55e;"></i> En ligne</span>
      </div>
    </footer>
    
  </div>
  <!-- /.wrapper -->
  
  <!-- Scripts -->
  <!-- JS locaux avec fallback CDN -->
  <script>
    (function(){
      function addScript(src){ var s=document.createElement('script'); s.src=src; s.defer=true; document.body.appendChild(s); }
      // Tente d’inclure JS local (AdminLTE uniquement ici; Bootstrap déjà chargé en <head>)
      addScript('<?= htmlspecialchars($base) ?>/assets/vendor/adminlte/adminlte.min.js');
      // Vérifie après un court délai si AdminLTE a initialisé quelque chose; sinon charge CDN
      setTimeout(function(){
        if (!window.AdminLTE) {
          addScript('https://cdn.jsdelivr.net/npm/admin-lte@4.0.0/dist/js/adminlte.min.js');
        }
      }, 300);
    })();
  </script>
  <script>
    // Injecte un CSS de secours si Bootstrap n'est pas chargé (ex: pas d'accès internet)
    (function() {
      function hasBootstrapCSS() {
        try {
          var el = document.createElement('button');
          el.className = 'btn btn-primary';
          el.style.position = 'absolute';
          el.style.left = '-9999px';
          document.body.appendChild(el);
          var bg = window.getComputedStyle(el).backgroundColor;
          document.body.removeChild(el);
          // Si pas de CSS, backgroundColor est généralement 'rgba(0, 0, 0, 0)' ou 'transparent'
          return bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent';
        } catch (e) { return false; }
      }
      function injectFallback() {
        var id = 'fallback-css-local';
        if (document.getElementById(id)) return;
        var link = document.createElement('link');
        link.id = id;
        link.rel = 'stylesheet';
        link.href = '<?= htmlspecialchars($base) ?>/assets/css/fallback.css';
        document.head.appendChild(link);
      }
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function(){ if (!hasBootstrapCSS()) injectFallback(); });
      } else {
        if (!hasBootstrapCSS()) injectFallback();
      }
    })();
  </script>
  
  <script>
    /* Sync --navbar-h CSS variable so sidebar sticky offset is exact */
    (function(){
      var nav=document.querySelector('.main-header.navbar');
      if(!nav)return;
      function set(){document.documentElement.style.setProperty('--navbar-h',nav.offsetHeight+'px');}
      set();
      window.addEventListener('resize',set);
    })();
  </script>
  <script>
    // Encapsuler tout le code JavaScript pour éviter les conflits de scope
    (function() {
      // Aucun JS custom requis pour le treeview: AdminLTE gère l'ouverture via data-lte-toggle
      var notifDropdown = document.getElementById('notifDropdown');
      var notifBadge = document.getElementById('notifBadge');
      var notifDropdownBody = document.getElementById('notifDropdownBody');
      var notifReadAllForm = document.getElementById('notifReadAllForm');
      var notificationsFeedUrl = '<?= htmlspecialchars(route_url('/notifications/feed')) ?>';
      var notificationsReadUrl = '<?= htmlspecialchars(route_url('/notifications/read')) ?>';
      var notificationsReadAllUrl = '<?= htmlspecialchars(route_url('/notifications/read-all')) ?>';
      var notificationsIndexUrl = '<?= htmlspecialchars(route_url('/notifications')) ?>';
      var notificationsPollingMs = 30000;
      var currentNotifications = [];
      var notificationPollTimer = null;
      var notificationAudioContext = null;
      var notificationStorageKey = 'insuite:web:lastNotifSeenId:<?= (int)($u['id'] ?? 0) ?>';

      function getToastContainer() {
        var container = document.getElementById('mentionToastContainer');
        if (container) return container;
        container = document.createElement('div');
        container.id = 'mentionToastContainer';
        container.className = 'toast-container position-fixed top-0 end-0 p-3';
        container.style.zIndex = '1080';
        document.body.appendChild(container);
        return container;
      }

      function escapeHtml(value) {
        return String(value || '')
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
          .replace(/'/g, '&#039;');
      }

      function formatNotifDate(value) {
        if (!value) return '';
        var parsed = new Date(String(value).replace(' ', 'T'));
        if (Number.isNaN(parsed.getTime())) return String(value).slice(0, 16);
        return parsed.toLocaleString('fr-FR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
      }

      function ensureNotificationAudioContext() {
        var AudioContextCtor = window.AudioContext || window.webkitAudioContext;
        if (!AudioContextCtor) return null;
        if (!notificationAudioContext) {
          notificationAudioContext = new AudioContextCtor();
        }
        return notificationAudioContext;
      }

      function armNotificationAudio() {
        var context = ensureNotificationAudioContext();
        if (context && context.state === 'suspended') {
          context.resume().catch(function(){});
        }
      }

      ['click', 'touchstart', 'keydown'].forEach(function(eventName) {
        window.addEventListener(eventName, armNotificationAudio, { passive: true });
      });

      function playNotificationBeep() {
        var context = ensureNotificationAudioContext();
        if (!context) return;
        var now = context.currentTime;
        var oscillator = context.createOscillator();
        var gainNode = context.createGain();
        oscillator.type = 'sine';
        oscillator.frequency.setValueAtTime(920, now);
        oscillator.frequency.exponentialRampToValueAtTime(690, now + 0.18);
        gainNode.gain.setValueAtTime(0.0001, now);
        gainNode.gain.exponentialRampToValueAtTime(0.08, now + 0.02);
        gainNode.gain.exponentialRampToValueAtTime(0.0001, now + 0.22);
        oscillator.connect(gainNode);
        gainNode.connect(context.destination);
        oscillator.start(now);
        oscillator.stop(now + 0.24);
      }

      function renderNotificationsDropdown(items, unreadCount) {
        currentNotifications = Array.isArray(items) ? items : [];

        if (notifBadge) {
          notifBadge.hidden = !(unreadCount > 0);
          notifBadge.textContent = String(unreadCount || 0);
        }

        if (!notifDropdownBody) return;

        if (!currentNotifications.length) {
          notifDropdownBody.innerHTML = '<div class="px-3 py-3 text-muted">Aucune notification</div>';
          return;
        }

        var rowsHtml = currentNotifications.map(function(n) {
          var url = n.url || notificationsIndexUrl;
          var mentionBadge = n.is_mention ? '<span class="badge text-bg-warning ms-1">Mention</span>' : '';
          var weightClass = Number(n.is_read || 0) === 0 ? 'fw-semibold' : '';
          var dotClass = Number(n.is_read || 0) === 0 ? ' text-primary' : ' text-secondary';
          var markReadButton = Number(n.is_read || 0) === 0
            ? '<button type="button" class="btn btn-sm btn-link p-0 text-nowrap notification-mark-read" data-notification-id="' + Number(n.id || 0) + '">Marquer comme lu</button>'
            : '';
          return ''
            + '<li>'
            + '  <div class="dropdown-item small notification-entry ' + weightClass + '" data-notification-id="' + Number(n.id || 0) + '">'
            + '    <div class="d-flex align-items-start gap-2">'
            + '      <i class="fas fa-circle' + dotClass + ' notification-entry-dot" style="font-size:.5rem; margin-top:.45rem;"></i>'
            + '      <div class="flex-grow-1 min-w-0">'
            + '        <a class="text-decoration-none d-block notification-entry-link" href="' + escapeHtml(url) + '" data-notification-id="' + Number(n.id || 0) + '">'
            + '          <div>' + escapeHtml(n.title || 'Notification') + mentionBadge + '</div>'
            + (n.body ? '<div class="text-muted">' + escapeHtml(n.body) + '</div>' : '')
            + '          <div class="text-muted">' + escapeHtml(formatNotifDate(n.created_at)) + '</div>'
            + '        </a>'
            + '      </div>'
            +        markReadButton
            + '    </div>'
            + '  </div>'
            + '</li>';
        }).join('');

        notifDropdownBody.innerHTML = rowsHtml
          + '<li><hr class="dropdown-divider"></li>'
          + '<li><a class="dropdown-item text-center" href="' + escapeHtml(notificationsIndexUrl) + '">Voir plus</a></li>';
      }

      function showNotificationToasts(items) {
        if (!items || !items.length) return;
        var container = getToastContainer();
        items.slice(0, 2).forEach(function(n) {
          var html = ''
            + '<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="8000">'
            + '  <div class="toast-header">'
            + '    <span class="badge text-bg-info me-2">Alerte</span>'
            + '    <strong class="me-auto">' + escapeHtml(n.title || 'Notification') + '</strong>'
            + '    <small class="text-muted">' + escapeHtml(formatNotifDate(n.created_at)) + '</small>'
            + '    <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Fermer"></button>'
            + '  </div>'
            + '  <div class="toast-body">'
            +      escapeHtml(n.body || '')
            + '    <div class="mt-2">'
            + '      <a class="btn btn-sm btn-outline-primary" href="' + escapeHtml(n.url || notificationsIndexUrl) + '">Ouvrir</a>'
            + '    </div>'
            + '  </div>'
            + '</div>';

          var wrap = document.createElement('div');
          wrap.innerHTML = html;
          var el = wrap.firstElementChild;
          container.appendChild(el);

          if (window.bootstrap && typeof window.bootstrap.Toast === 'function') {
            window.bootstrap.Toast.getOrCreateInstance(el).show();
          } else {
            el.style.display = 'block';
            setTimeout(function(){ try { el.remove(); } catch (e) {} }, 8200);
          }
        });
      }

      function updateSeenNotifications(items, shouldNotify) {
        var unreadItems = (items || []).filter(function(n) { return Number(n.is_read || 0) === 0; });
        if (!unreadItems.length) {
          return;
        }

        var currentMax = unreadItems.reduce(function(max, item) {
          return Math.max(max, Number(item.id || 0));
        }, 0);
        var storedMax = parseInt(localStorage.getItem(notificationStorageKey) || '0', 10);
        if (!Number.isFinite(storedMax)) storedMax = 0;

        if (storedMax === 0) {
          localStorage.setItem(notificationStorageKey, String(currentMax));
          return;
        }

        var newItems = unreadItems.filter(function(item) {
          return Number(item.id || 0) > storedMax;
        });

        if (newItems.length && shouldNotify) {
          playNotificationBeep();
          showNotificationToasts(newItems);
        }

        localStorage.setItem(notificationStorageKey, String(Math.max(storedMax, currentMax)));
      }

      function fetchNotifications(options) {
        options = options || {};
        return fetch(notificationsFeedUrl, {
          method: 'GET',
          headers: { 'Accept': 'application/json' },
          credentials: 'same-origin'
        })
          .then(function(response) {
            if (!response.ok) throw new Error('notifications_feed_failed');
            return response.json();
          })
          .then(function(payload) {
            if (!payload || payload.ok === false) return;
            renderNotificationsDropdown(payload.notifications || [], Number(payload.unread || 0));
            updateSeenNotifications(payload.notifications || [], Boolean(options.playSound));
          })
          .catch(function(){});
      }

      function setNotificationsReadLocally(notificationIds) {
        var ids = Array.isArray(notificationIds) ? notificationIds.map(function(value) {
          return Number(value || 0);
        }).filter(function(value) {
          return value > 0;
        }) : [];

        if (!ids.length) {
          return 0;
        }

        var unreadCount = 0;
        currentNotifications = currentNotifications.map(function(item) {
          if (ids.indexOf(Number(item.id || 0)) !== -1) {
            return Object.assign({}, item, { is_read: 1 });
          }
          if (Number(item.is_read || 0) === 0) {
            unreadCount += 1;
          }
          return item;
        });

        return unreadCount;
      }

      function markNotificationRead(notificationId) {
        var id = Number(notificationId || 0);
        if (id <= 0) {
          return Promise.resolve();
        }

        return fetch(notificationsReadUrl, {
          method: 'POST',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'X-Requested-With': 'XMLHttpRequest'
          },
          credentials: 'same-origin',
          body: 'id=' + encodeURIComponent(String(id))
        })
          .then(function(response) {
            if (!response.ok) throw new Error('notification_read_failed');
            return response.json();
          })
          .then(function(payload) {
            var localUnreadCount = setNotificationsReadLocally([id]);
            renderNotificationsDropdown(currentNotifications, Number(payload && payload.unread != null ? payload.unread : localUnreadCount));
          })
          .catch(function(){});
      }

      function markNotificationsRead() {
        return fetch(notificationsReadAllUrl, {
          method: 'POST',
          headers: {
            'Accept': 'application/json',
            'X-Requested-With': 'XMLHttpRequest'
          },
          credentials: 'same-origin'
        })
          .then(function(response) {
            if (!response.ok) throw new Error('notifications_read_failed');
            return response.json();
          })
          .then(function(payload) {
            renderNotificationsDropdown(currentNotifications.map(function(item) {
              return Object.assign({}, item, { is_read: 1 });
            }), Number(payload && payload.unread != null ? payload.unread : 0));
          })
          .catch(function(){});
      }

      if (notifReadAllForm) {
        notifReadAllForm.addEventListener('submit', function(event) {
          event.preventDefault();
          markNotificationsRead();
        });
      }

      if (notifDropdown) {
        notifDropdown.addEventListener('show.bs.dropdown', function() {
          fetchNotifications({ playSound: false });
        });
      }

      document.addEventListener('click', function(event) {
        var markButton = event.target.closest('.notification-mark-read');
        if (markButton) {
          event.preventDefault();
          event.stopPropagation();
          markNotificationRead(markButton.getAttribute('data-notification-id'));
          return;
        }

        var notificationLink = event.target.closest('.notification-entry-link');
        if (notificationLink) {
          if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
            markNotificationRead(notificationLink.getAttribute('data-notification-id'));
            return;
          }

          event.preventDefault();
          var targetUrl = notificationLink.getAttribute('href') || notificationsIndexUrl;
          markNotificationRead(notificationLink.getAttribute('data-notification-id'))
            .finally(function() {
              window.location.href = targetUrl;
            });
        }
      });

      if (!notificationPollTimer) {
        notificationPollTimer = window.setInterval(function() {
          fetchNotifications({ playSound: true });
        }, notificationsPollingMs);
      }

      document.addEventListener('visibilitychange', function() {
        if (!document.hidden) {
          fetchNotifications({ playSound: false });
        }
      });

      window.addEventListener('focus', function() {
        fetchNotifications({ playSound: false });
      });

      fetchNotifications({ playSound: false });

      // Toggle manuel de la sidebar pour les vues mobiles
      document.querySelectorAll('[data-lte-toggle="sidebar"]').forEach(function(trigger) {
        trigger.addEventListener('click', function(e) {
          e.preventDefault();
          document.body.classList.toggle('sidebar-open');
        });
      });
      
      // Fermer la sidebar en cliquant sur l'overlay (mobile + tablette)
      if (window.innerWidth <= 991) {
        document.body.addEventListener('click', function(e) {
          if (document.body.classList.contains('sidebar-open')) {
            var sidebar = document.querySelector('.main-sidebar');
            if (sidebar && !sidebar.contains(e.target) && !e.target.closest('[data-lte-toggle="sidebar"]')) {
              document.body.classList.remove('sidebar-open');
            }
          }
        });
      }
    })();
  </script>

  <?php
    $trackingRole = strtolower((string)($u['role_key'] ?? ''));
    $trackingEligibleRole = in_array($trackingRole, ['technicien', 'technician', 'tech', 'agent'], true);
    $trackingOnCartographyPage = str_contains($currentPath, '/cartography') || str_contains($currentPath, '/cartographie');
  ?>
  <?php if ($trackingEligibleRole && !$trackingOnCartographyPage): ?>
    <script>
      (function() {
        if (!('geolocation' in navigator)) return;

        var trackingContextUrl = '<?= htmlspecialchars(route_url('/cartography/tracking-context')) ?>';
        var trackingUpdateUrl = '<?= htmlspecialchars(route_url('/cartography/update-location')) ?>';
        var watchId = null;
        var syncTimer = null;
        var lastSent = null;
        var minMoveMeters = 10;
        var minSendIntervalMs = 60000;
        var syncIntervalMs = 120000;

        function toRadians(value) {
          return (value * Math.PI) / 180;
        }

        function distanceMeters(startLat, startLng, endLat, endLng) {
          var earthRadius = 6371000;
          var deltaLat = toRadians(endLat - startLat);
          var deltaLng = toRadians(endLng - startLng);
          var a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)
            + Math.cos(toRadians(startLat)) * Math.cos(toRadians(endLat)) * Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2);
          return earthRadius * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        }

        function shouldSend(coords) {
          if (!lastSent) return true;

          var moved = distanceMeters(lastSent.lat, lastSent.lng, coords.latitude, coords.longitude);
          var elapsed = Date.now() - lastSent.sentAt;
          return moved >= minMoveMeters || elapsed >= minSendIntervalMs;
        }

        function pushPosition(position) {
          var coords = position && position.coords ? position.coords : null;
          if (!coords || !shouldSend(coords)) return;

          var formData = new FormData();
          formData.set('lat', String(coords.latitude));
          formData.set('lng', String(coords.longitude));
          formData.set('accuracy', String(coords.accuracy || ''));
          formData.set('heading', String(coords.heading || ''));
          formData.set('speed', String(coords.speed || ''));
          formData.set('source', 'web_auto_tracking');

          fetch(trackingUpdateUrl, {
            method: 'POST',
            headers: { 'Accept': 'application/json' },
            credentials: 'same-origin',
            body: formData
          }).then(function(response) {
            if (!response.ok) throw new Error('tracking_update_failed');
            lastSent = {
              lat: Number(coords.latitude),
              lng: Number(coords.longitude),
              sentAt: Date.now()
            };
          }).catch(function() {});
        }

        function stopWatch() {
          if (watchId !== null) {
            navigator.geolocation.clearWatch(watchId);
          }
          watchId = null;
        }

        function startWatch() {
          if (watchId !== null) return;

          navigator.geolocation.getCurrentPosition(function(position) {
            pushPosition(position);
          }, function() {}, {
            enableHighAccuracy: true,
            maximumAge: 15000,
            timeout: 20000
          });

          watchId = navigator.geolocation.watchPosition(function(position) {
            pushPosition(position);
          }, function() {}, {
            enableHighAccuracy: true,
            maximumAge: 15000,
            timeout: 20000
          });
        }

        function syncTracking() {
          return fetch(trackingContextUrl, {
            method: 'GET',
            headers: { 'Accept': 'application/json' },
            credentials: 'same-origin'
          }).then(function(response) {
            if (!response.ok) throw new Error('tracking_context_failed');
            return response.json();
          }).then(function(payload) {
            if (!payload || !payload.should_track) {
              stopWatch();
              return;
            }

            startWatch();
          }).catch(function() {});
        }

        function ensureSyncTimer() {
          if (syncTimer !== null) return;
          syncTimer = window.setInterval(function() {
            syncTracking();
          }, syncIntervalMs);
        }

        ensureSyncTimer();
        syncTracking();

        document.addEventListener('visibilitychange', function() {
          if (!document.hidden) {
            syncTracking();
          }
        });

        window.addEventListener('focus', function() {
          syncTracking();
        });

        window.addEventListener('beforeunload', function() {
          stopWatch();
        });
      })();
    </script>
  <?php endif; ?>

  <?php if (!empty($u ?? null)): ?>
    <?php
      $mentionNotifs = [];
      try {
        foreach (($notifRows ?? []) as $n) {
          $t = strtolower((string)($n['title'] ?? ''));
          $b = strtolower((string)($n['body'] ?? ''));
          $isMention = false;
          if (str_contains($t, 'mention') || str_contains($b, 'mention')) { $isMention = true; }
          if (!$isMention && preg_match('/@\[[^\]]+\]|@[a-z0-9_\.-]+/i', (string)($n['body'] ?? ''))) { $isMention = true; }
          if (!$isMention) { continue; }
          $mentionNotifs[] = [
            'id' => (int)($n['id'] ?? 0),
            'title' => (string)($n['title'] ?? ''),
            'body' => (string)($n['body'] ?? ''),
            'url' => (string)($n['url'] ?? ''),
            'created_at' => (string)($n['created_at'] ?? ''),
          ];
        }
      } catch (\Throwable $e) { $mentionNotifs = []; }
    ?>
    <div id="mentionToastContainer" class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1080;"></div>
    <script>
      (function(){
        try {
          var items = <?= json_encode($mentionNotifs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
          if (!items || !items.length) return;

          var lastKey = 'insuite:lastMentionNotifId';
          var lastShown = parseInt(localStorage.getItem(lastKey) || '0', 10);
          if (!isFinite(lastShown)) lastShown = 0;

          // Filtrer: seulement ce qui est "nouveau" depuis le dernier affichage
          var toShow = items
            .filter(function(n){ return (n && n.id && n.id > lastShown); })
            .sort(function(a,b){ return (a.id||0) - (b.id||0); });

          // Anti-spam: max 2 toasts par chargement
          toShow = toShow.slice(0, 2);
          if (!toShow.length) return;

          var container = document.getElementById('mentionToastContainer');
          if (!container) return;

          function escapeHtml(s){
            return String(s||'')
              .replace(/&/g,'&amp;')
              .replace(/</g,'&lt;')
              .replace(/>/g,'&gt;')
              .replace(/\"/g,'&quot;')
              .replace(/'/g,'&#039;');
          }

          var maxIdShown = lastShown;
          toShow.forEach(function(n){
            maxIdShown = Math.max(maxIdShown, n.id||0);
            var url = n.url || '<?= htmlspecialchars(route_url('/notifications')) ?>';
            var html = ''
              + '<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="9000">'
              + '  <div class="toast-header">'
              + '    <span class="badge text-bg-warning me-2">Mention</span>'
              + '    <strong class="me-auto">' + escapeHtml(n.title || 'Vous avez été mentionné') + '</strong>'
              + '    <small class="text-muted">' + escapeHtml((n.created_at||'').slice(11,16)) + '</small>'
              + '    <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Fermer"></button>'
              + '  </div>'
              + '  <div class="toast-body">'
              +      escapeHtml(n.body || '')
              + '    <div class="mt-2">'
              + '      <a class="btn btn-sm btn-outline-primary" href="' + escapeHtml(url) + '">Ouvrir</a>'
              + '    </div>'
              + '  </div>'
              + '</div>';

            var wrap = document.createElement('div');
            wrap.innerHTML = html;
            var el = wrap.firstElementChild;
            container.appendChild(el);

            // Bootstrap Toast si dispo, sinon fallback simple (afficher/cacher)
            if (window.bootstrap && typeof window.bootstrap.Toast === 'function') {
              new window.bootstrap.Toast(el).show();
            } else {
              el.style.display = 'block';
              setTimeout(function(){ try{ el.remove(); }catch(e){} }, 9500);
            }
          });

          localStorage.setItem(lastKey, String(maxIdShown));
        } catch(e) {}
      })();
    </script>
  <?php endif; ?>
  
</body>
</html>
