/* ==========================================================================
   LIVE MAP — FEUILLE DE STYLE
   Fichier : assets/css/live-map.css

   Fusion des deux blocs <style> inline qui vivaient dans la page de la carte
   et son partiel de panneau lateral (~3 580 lignes non cachables,
   re-transmises a chaque requete et incompatibles avec une CSP stricte).

   Chargee via pe_asset_css(), versionnee par filemtime.

   ETAPE E3 : deplacement a l'identique, aucun refactor visuel.
   La refonte des tokens, de la typographie et du responsive intervient en
   phase 3 du plan.
   ========================================================================== */

/* ==========================================================================
   PARTIE 1 — CARTE
   ========================================================================== */

        /* ==========================================================================
           1. JETONS DE STYLE

           PORTEE : body.page-europe-live, et non :root.
           Ce bloc redefinissait six jetons GLOBAUX de style.css — --accent
           (l'or #fbbf24 devenait bleu), --radius (16px -> 12px), --bg-deep,
           --border, --text-muted, --font-sans. Comme live-map.css est charge
           apres style.css, le header et le footer de cette page heritaient des
           valeurs de la carte. Le scope les confine a la page.

           Les jetons qui ont un equivalent global y sont ALIASES plutot que
           redefinis : la carte suit ainsi le systeme du site, et une evolution
           de style.css se propage ici.
           ========================================================================== */
        /* Portee : les conteneurs de la carte, PAS body — sinon les jetons
           redescendent sur le header et le footer, qui sont hors carte. Les
           popups et modales sont des freres de .dashboard (ils vivent en fin
           de body pour echapper aux overflow), d'ou la liste. */
        .dashboard,
        .detail-popup, .detail-popup-overlay,
        .cluster-list,
        .alliance-modal, .alliance-modal-overlay,
        .maplibregl-popup {
            /* --- alias vers le systeme global (style.css) --- */
            --accent:      var(--primary);            /* bleu electrique du site */
            --accent-glow: var(--primary-glow);
            --text-white:  var(--text-main);
            --border:      rgba(255, 255, 255, 0.06);
            --radius:      12px;                      /* la carte est plus dense que les pages */

            /* --- specifiques a la carte, sans equivalent global --- */
            --bg-void: #020408;
            --bg-panel: #0d1525;
            --bg-card: #131d2e;
            --bg-card-hover: #1a2744;

            --success: #10b981;
            --warning: #fbbf24;
            --danger: #ef4444;
            --info: #0ea5e9;
            --purple: #8b5cf6;

            /* Echelle de severite. Le bas de gamme est volontairement
               desature : l'oeil doit aller vers ce qui compte, pas vers le
               bruit de fond. Voir aussi les paliers .sev-tier-* plus bas. */
            --sev-1: #64748b;
            --sev-2: #94a3b8;
            --sev-3: #fbbf24;
            --sev-4: #f97316;
            --sev-5: #ef4444;

            --text-light: #cbd5e1;
            --text-muted: #94a3b8;
            --text-dim: #475569;
            --border-light: rgba(255,255,255,0.1);

            /* Outfit est la police reelle du site (chargee par l'en-tete).
               La carte tirait Inter + JetBrains Mono, soit deux requetes
               Google Fonts bloquantes pour un rendu incoherent avec le reste. */
            --font-sans: 'Outfit', system-ui, sans-serif;
            --font-mono: 'Outfit', system-ui, sans-serif;

            --sidebar-w: 420px;
            --radius-sm: 8px;
        }

        /* Chiffres alignes la ou le monospace servait vraiment : horloge,
           coordonnees, compteurs. Outfit + tabular-nums remplace une seconde
           famille de police. */
        body.page-europe-live .hud-clock,
        body.page-europe-live .tz-time,
        body.page-europe-live .hud-metric-value,
        body.page-europe-live .event-coords,
        body.page-europe-live .chip-count {
            font-variant-numeric: tabular-nums;
            font-feature-settings: 'tnum' 1;
        }

        /* Le conteneur de page global contraint la largeur et ajoute du
           padding : la carte doit occuper toute la surface. Remplace un bloc
           de six !important qui combattait style.css. */
        body.page-europe-live #main-content {
            padding: 0;
            max-width: none;
            width: 100%;
            display: flex;
            align-items: stretch;
        }

        * { box-sizing: border-box; margin: 0; padding: 0; }

        html.popup-locked,
        body.popup-locked {
            overflow: hidden;
            overscroll-behavior: none;
        }

        /* Le header reste sticky comme partout ailleurs sur le site : la carte
           n'a plus besoin de le forcer en `position: relative`. Ces regles
           etaient portees par six !important ; elles vivent desormais dans le
           bloc scope `body.page-europe-live` en tete de fichier. */
        body.page-europe-live #main-content {
            flex: 1;
            flex-direction: column;
        }

        ::-webkit-scrollbar { width: 6px; height: 6px; }
        ::-webkit-scrollbar-track { background: rgba(0,0,0,0.2); }
        ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 3px; }
        ::-webkit-scrollbar-thumb:hover { background: var(--accent); }

        /* ==========================================================================
           2. LAYOUT
           ========================================================================== */
        .dashboard {
            display: grid;
            grid-template-rows: auto minmax(0, 1fr);
            width: 100%;
            overflow: hidden;

            /* Hauteur : viewport moins le header du site.
               --nav-height vient de style.css (90px) : le 90 code en dur ici
               etait un nombre magique qui se desynchronisait a la moindre
               evolution du header.

               L'ordre des trois declarations compte. 100vh ignore la barre
               d'URL mobile : la carte depassait sous l'ecran sur iOS. svh est
               le plancher sur (la plus PETITE hauteur possible), dvh suit la
               barre en temps reel. Les navigateurs qui ne connaissent pas une
               unite ignorent la ligne et gardent la precedente. */
            height: calc(100vh - var(--nav-height, 90px));
            height: calc(100svh - var(--nav-height, 90px));
            height: calc(100dvh - var(--nav-height, 90px));
        }

        .dashboard-header {
            background: linear-gradient(180deg, var(--bg-deep) 0%, transparent 100%);
            border-bottom: 1px solid var(--border);
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 14px 20px;
            z-index: 100;
            backdrop-filter: blur(12px);
        }

        .dashboard-body {
            display: grid;
            grid-template-columns: 1fr var(--sidebar-w);
            grid-template-rows: 100%;
            overflow: hidden;
            min-height: 0;
        }

        .map-section {
            position: relative;
            background: radial-gradient(ellipse at 50% 30%, #1e293b 0%, var(--bg-void) 70%);
            overflow: hidden;
            height: 100%;
            min-height: 0;
            display: flex;
            flex-direction: column;
        }

        .sidebar-section {
            background: var(--bg-deep);
            border-left: 1px solid var(--border);
            display: flex;
            flex-direction: column;
            overflow: hidden;
            height: 100%;
        }

        /* ==========================================================================
           3. HEADER HUD
           ========================================================================== */
        .hud-brand {
            display: flex;
            align-items: center;
            gap: 16px;
        }

        .hud-title-group h1 {
            font-size: 1.1rem;
            font-weight: 700;
            color: var(--text-white);
            letter-spacing: -0.02em;
        }

        .hud-tagline {
            margin: 2px 0 0;
            font-size: 0.78rem;
            color: var(--text-muted);
            line-height: 1.3;
        }

        /* Pastille "live" honnete : etat reel du flux, pas un decor.
           JS bascule .is-stale / .is-error via #lm-live-status. */
        .hud-status {
            display: flex;
            align-items: center;
            gap: 7px;
            margin-top: 6px;
            font-size: 0.72rem;
            font-variant-numeric: tabular-nums;
            color: var(--success);
        }

        .lm-live-dot {
            width: 6px;
            height: 6px;
            flex: none;
            background: currentColor;
            border-radius: 50%;
            box-shadow: 0 0 8px currentColor;
            animation: pulse 2s infinite;
        }

        .hud-status.is-stale { color: var(--warning); }
        .hud-status.is-error { color: var(--danger); }
        .hud-status.is-error .lm-live-dot { animation: none; }

        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.5; }
        }

        @media (prefers-reduced-motion: reduce) {
            .lm-live-dot { animation: none; }
        }

        .hud-center {
            display: flex;
            align-items: center;
            gap: 24px;
        }

        .hud-clock {
            font-family: var(--font-mono);
            font-size: 1.5rem;
            font-weight: 500;
            color: var(--text-white);
            letter-spacing: 2px;
        }

        .hud-date {
            font-size: 0.75rem;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .hud-timeblock {
            display: flex;
            flex-direction: column;
            gap: 4px;
            align-items: flex-end;
            text-align: right;
        }

        .hud-timezones {
            display: flex;
            align-items: center;
            gap: 8px;
            flex-wrap: wrap;
        }

        .tz-compare {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            font-size: 0.62rem;
            color: var(--text-muted);
        }

        .tz-pill {
            padding: 2px 6px;
            border-radius: 999px;
            border: 1px solid rgba(255,255,255,0.1);
            background: rgba(255,255,255,0.04);
            font-weight: 700;
            letter-spacing: 0.4px;
            font-size: 0.55rem;
            text-transform: uppercase;
            color: var(--text-dim);
        }

        .tz-pill.tz-selected {
            color: #fff;
            border-color: rgba(59, 130, 246, 0.5);
            background: rgba(59, 130, 246, 0.2);
        }

        .tz-pill.tz-local {
            color: var(--text-light);
        }

        .tz-time {
            font-family: var(--font-mono);
            font-size: 0.68rem;
            color: var(--text-light);
        }

        .tz-sep {
            color: var(--text-dim);
        }

        .tz-select {
            background: #0b1220;
            border: 1px solid rgba(148, 163, 184, 0.4);
            color: #f8fafc;
            border-radius: 8px;
            padding: 2px 8px;
            font-size: 0.58rem;
            font-weight: 600;
            font-family: var(--font-mono);
            line-height: 1.1;
            height: 24px;
            box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.6);
        }

        .tz-select:focus {
            outline: none;
            border-color: rgba(59, 130, 246, 0.8);
            box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
        }

        .tz-select option {
            background: #0b1220;
            color: #e2e8f0;
        }

        .hud-metrics {
            display: flex;
            gap: 20px;
        }

        .hud-metric {
            text-align: center;
            padding: 8px 16px;
            background: rgba(255,255,255,0.03);
            border: 1px solid var(--border);
            border-radius: var(--radius-sm);
        }

        .hud-metric-value {
            font-family: var(--font-mono);
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--text-white);
        }

        .hud-metric-label {
            font-size: 0.65rem;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .hud-metric.critical .hud-metric-value { color: var(--danger); }
        .hud-metric.warning .hud-metric-value { color: var(--warning); }

        .hud-btn {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 10px 16px;
            background: rgba(255,255,255,0.05);
            border: 1px solid var(--border);
            border-radius: var(--radius-sm);
            color: var(--text-light);
            font-size: 0.8rem;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.2s;
            text-decoration: none;
        }

        .hud-btn:hover {
            background: rgba(255,255,255,0.1);
            border-color: var(--accent);
            color: var(--text-white);
        }

        .hud-btn i { font-size: 1.1rem; }

        /* ==========================================================================
           4. CATEGORY FILTERS
           ========================================================================== */
        .filters-bar {
            padding: 6px 16px;
            background: var(--bg-deep);
            border-bottom: 1px solid var(--border);
            display: flex;
            align-items: center;
            gap: 8px;
            flex-wrap: nowrap;
            flex-shrink: 0;
            overflow: hidden;
        }

        /* Les puces de categorie vivent desormais dans le panneau deroulant
           « Categories » (voir la section MENUS DEROULANTS en fin de fichier).
           Elles gardent leur classe et leur attribut data-category — c'est le
           contrat lu par le JS — mais se presentent en rangees de liste, pas
           en pilules alignees : une grille tient neuf entrees dans 300 px de
           large, la rangee horizontale en demandait plus de 900. */
        .filter-chip {
            display: flex;
            align-items: center;
            gap: 8px;
            width: 100%;
            padding: 7px 9px;
            background: transparent;
            border: 1px solid transparent;
            border-radius: 8px;
            font-family: inherit;
            font-size: 0.74rem;
            font-weight: 500;
            text-align: left;
            color: var(--text-muted);
            cursor: pointer;
            transition: background 0.15s ease, color 0.15s ease;
            user-select: none;
        }

        .filter-chip:hover {
            background: rgba(255,255,255,0.05);
            color: var(--text-light);
        }

        .filter-chip:focus-visible {
            outline: 2px solid rgba(96,165,250,0.85);
            outline-offset: -1px;
        }

        /* Etat actif : la couleur de la categorie passe de la pastille au
           texte. Une rangee eteinte reste lisible mais recule — on voit d'un
           coup d'oeil ce qui est allume sans compter les cases. */
        .filter-chip.active { color: var(--text-white); }

        .filter-chip .chip-icon {
            width: 26px;
            height: 26px;
            flex: none;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 7px;
            background: rgba(255,255,255,0.05);
            color: var(--text-dim);
            transition: background 0.15s ease, color 0.15s ease;
        }
        .filter-chip.active .chip-icon {
            background: var(--chip-color, var(--accent));
            color: #fff;
        }
        .filter-chip .chip-icon svg,
        .filter-chip .chip-icon img {
            width: 15px;
            height: 15px;
            display: block;
        }
        .filter-chip .chip-icon i { font-size: 0.9rem; }

        .filter-chip .chip-label {
            flex: 1 1 auto;
            min-width: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .filter-chip .chip-count {
            flex: none;
            padding: 1px 6px;
            border-radius: 10px;
            background: rgba(255,255,255,0.06);
            font-size: 0.62rem;
            font-variant-numeric: tabular-nums;
            color: var(--text-dim);
        }
        .filter-chip.active .chip-count {
            background: rgba(255,255,255,0.12);
            color: var(--text-light);
        }

        .filter-divider {
            width: 1px;
            height: 20px;
            background: var(--border);
            margin: 0 6px;
            flex: 0 0 auto;
        }

        .filter-toggle {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 6px 10px;
            background: rgba(255,255,255,0.03);
            border: 1px solid var(--border);
            border-radius: 20px;
            font-size: 0.7rem;
            color: var(--text-muted);
            cursor: pointer;
            transition: all 0.2s;
            white-space: nowrap;
            flex: 0 0 auto;
        }

        .filter-toggle:hover { color: var(--text-light); }
        .filter-toggle.active { color: var(--accent); border-color: var(--accent); }

        .severity-range {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 6px 10px;
            background: rgba(255,255,255,0.03);
            border: 1px solid var(--border);
            border-radius: 999px;
            font-size: 0.65rem;
            color: var(--text-muted);
            white-space: nowrap;
            flex: 0 0 auto;
            position: relative;
        }

        .severity-label {
            font-size: 0.6rem;
            text-transform: uppercase;
            letter-spacing: 0.6px;
            color: var(--text-dim);
        }

        .severity-sliders {
            position: relative;
            width: 140px;
            height: 18px;
            cursor: grab;
            touch-action: none;
        }

        .severity-sliders::before {
            content: '';
            position: absolute;
            left: 0;
            right: 0;
            top: 50%;
            height: 4px;
            background: rgba(255,255,255,0.08);
            border-radius: 999px;
            transform: translateY(-50%);
        }

        .severity-sliders::after {
            content: '';
            position: absolute;
            left: var(--sev-low, 0%);
            right: calc(100% - var(--sev-high, 100%));
            top: 50%;
            height: 4px;
            background: linear-gradient(90deg, var(--sev-2), var(--sev-5));
            border-radius: 999px;
            transform: translateY(-50%);
        }

        .severity-sliders input[type="range"] {
            position: absolute;
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            width: 100%;
            height: 18px;
            background: transparent;
            -webkit-appearance: none;
            appearance: none;
            margin: 0;
            pointer-events: none;
        }

        .severity-low { z-index: 1; }
        .severity-high { z-index: 2; }

        .severity-sliders input[type="range"]::-webkit-slider-runnable-track {
            height: 4px;
            background: transparent;
        }

        .severity-sliders input[type="range"]::-moz-range-track {
            height: 4px;
            background: transparent;
        }

        .severity-sliders input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 14px;
            height: 14px;
            border-radius: 50%;
            background: #0f172a;
            border: 2px solid var(--accent);
            box-shadow: 0 2px 6px rgba(0,0,0,0.35);
            margin-top: -5px;
        }

        .severity-sliders input[type="range"]::-moz-range-thumb {
            width: 14px;
            height: 14px;
            border-radius: 50%;
            background: #0f172a;
            border: 2px solid var(--accent);
            box-shadow: 0 2px 6px rgba(0,0,0,0.35);
            transform: translateY(-5px);
        }

        .severity-low::-webkit-slider-thumb,
        .severity-low::-moz-range-thumb {
            border-color: var(--sev-2);
        }

        .severity-high::-webkit-slider-thumb,
        .severity-high::-moz-range-thumb {
            border-color: var(--sev-5);
        }

        .severity-range.stacked .severity-low {
            z-index: 3;
        }

        .severity-range.stacked .severity-high {
            z-index: 2;
        }

        .severity-range.stacked .severity-high::-webkit-slider-thumb {
            transform: translateX(0);
            opacity: 0;
        }

        .severity-range.stacked .severity-high::-moz-range-thumb {
            transform: translateX(0);
            opacity: 0;
        }

        .severity-range.stacked .severity-low::-webkit-slider-thumb {
            width: 18px;
            height: 18px;
            background: radial-gradient(circle at 35% 35%, #1f2937 0%, #0b1220 45%, #0f172a 100%);
            border-width: 2px;
            box-shadow: 0 0 0 1px rgba(59,130,246,0.35), 0 4px 10px rgba(0,0,0,0.55);
        }

        .severity-range.stacked .severity-low::-moz-range-thumb {
            width: 18px;
            height: 18px;
            background: radial-gradient(circle at 35% 35%, #1f2937 0%, #0b1220 45%, #0f172a 100%);
            border-width: 2px;
            box-shadow: 0 0 0 1px rgba(59,130,246,0.35), 0 4px 10px rgba(0,0,0,0.55);
        }

        .severity-range.active-low .severity-low { z-index: 4; }
        .severity-range.active-low .severity-high { z-index: 2; }
        .severity-range.active-high .severity-high { z-index: 4; }
        .severity-range.active-high .severity-low { z-index: 2; }
        .severity-range.dragging .severity-sliders { cursor: grabbing; }
        .severity-range.stacked .severity-sliders { cursor: pointer; }

        .severity-value {
            font-family: var(--font-mono);
            font-size: 0.65rem;
            color: var(--text-light);
        }

        /* ==========================================================================
           5. MAP AREA
           ========================================================================== */
        .map-viewport {
            position: relative;
            flex: 1 1 auto;
            min-height: 0;
            overflow: hidden;
        }

        .map-container {
            position: absolute;
            inset: 0;
            min-height: 0;
        }

        #europe-map {
            width: 100%;
            height: 100%;
            touch-action: none;
            min-height: 0;
            background: #000;
        }

        #europe-map .maplibregl-canvas {
            outline: none;
        }

        .maplibregl-ctrl-attrib {
            font-size: 0.6rem;
            background: rgba(0,0,0,0.5) !important;
        }

        .maplibregl-ctrl-attrib a {
            color: var(--text-dim) !important;
        }

        .map-marker {
            width: 16px;
            height: 16px;
            border-radius: 50%;
            border: 2px solid rgba(255,255,255,0.9);
            box-shadow: 0 0 0 2px rgba(0,0,0,0.25);
            cursor: pointer;
            transition: box-shadow 0.15s ease, border-color 0.15s ease;
        }

        .map-marker.base {
            width: 10px;
            height: 10px;
            border-width: 1px;
            box-shadow: 0 0 0 1px rgba(0,0,0,0.2);
        }

        .map-marker:hover {
            box-shadow: 0 0 0 3px rgba(59,130,246,0.25);
        }

        .map-marker.pulse {
            animation: markerPulse 1.4s ease-in-out infinite;
        }

        @keyframes markerPulse {
            0%, 100% { box-shadow: 0 0 0 2px rgba(59,130,246,0.35); }
            50% { box-shadow: 0 0 0 6px rgba(59,130,246,0.1); }
        }

        /* New event ripple animation - for individual markers */
        .map-marker.new-event-ripple {
            position: relative;
        }
        .map-marker.new-event-ripple::before,
        .map-marker.new-event-ripple::after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            border: 2px solid var(--marker-color, var(--accent));
            animation: newEventRipple 3.5s ease-out forwards;
        }
        .map-marker.new-event-ripple::after {
            animation-delay: 0.7s;
        }
        @keyframes newEventRipple {
            0% {
                width: 100%;
                height: 100%;
                opacity: 1;
            }
            100% {
                width: 300%;
                height: 300%;
                opacity: 0;
            }
        }

        /* New cluster ripple animation - for clusters with new events */
        .map-marker.cluster.new-cluster-ripple {
            position: relative;
        }
        .map-marker.cluster.new-cluster-ripple::before,
        .map-marker.cluster.new-cluster-ripple::after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            border: 3px solid var(--accent);
            animation: clusterRipple 3.5s ease-out forwards;
            pointer-events: none;
        }
        .map-marker.cluster.new-cluster-ripple::after {
            animation-delay: 0.7s;
        }
        .map-marker.cluster.new-cluster-ripple::before {
            animation-delay: 0s;
        }
        @keyframes clusterRipple {
            0% {
                width: 100%;
                height: 100%;
                opacity: 1;
                border-color: var(--accent);
            }
            50% {
                opacity: 0.6;
            }
            100% {
                width: 400%;
                height: 400%;
                opacity: 0;
                border-color: var(--accent);
            }
        }

        /* Event marker with SVG icon */
        .map-marker.event-marker {
            width: 24px;
            height: 24px;
            background: var(--bg-card);
            border: 2px solid var(--marker-color, var(--accent));
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 2px 6px rgba(0,0,0,0.3);
        }

        .map-marker.event-marker svg,
        .map-marker.event-marker img {
            width: 12px;
            height: 12px;
            color: var(--marker-color, var(--accent));
            display: block;
        }

        .map-marker.event-marker:hover {
            box-shadow: 0 3px 10px rgba(0,0,0,0.4);
        }

        /* Market index markers (overlay badges) */
	        .market-index-marker {
            display: flex;
            flex-direction: column;
            gap: 2px;
            padding: 6px 8px 6px 8px;
            min-width: 74px;
            background: rgba(13, 21, 37, 0.92);
            backdrop-filter: blur(8px);
            border: 1px solid rgba(255,255,255,0.10);
            border-left: 3px solid rgba(148,163,184,0.7);
            border-radius: 10px;
	            box-shadow: 0 10px 28px rgba(0,0,0,0.45);
	            font-family: var(--font-mono);
	            pointer-events: auto;
	            user-select: none;
	            cursor: pointer;
	        }

        .market-index-marker .mi-code {
            font-size: 0.62rem;
            font-weight: 800;
            letter-spacing: 0.8px;
            text-transform: uppercase;
            color: var(--text-white);
            line-height: 1.05;
        }

        .market-index-marker .mi-change {
            font-size: 0.62rem;
            color: var(--text-muted);
            line-height: 1.05;
            white-space: nowrap;
        }

        .market-index-marker.up { border-left-color: rgba(16,185,129,0.95); }
        .market-index-marker.up .mi-change { color: rgba(110,231,183,0.95); }

        .market-index-marker.down { border-left-color: rgba(239,68,68,0.95); }
        .market-index-marker.down .mi-change { color: rgba(252,165,165,0.95); }

        .market-index-marker.flat { border-left-color: rgba(148,163,184,0.7); }

        /* .tactical-grid supprimee : la grille facon console militaire etait
           du decor, et exactement le registre dont la carte devait sortir.
           Les tuiles font la texture. */

        .map-controls {
            position: absolute;
            bottom: 24px;
            left: 24px;
            display: flex;
            flex-direction: column;
            gap: 8px;
            z-index: 50;
        }

        .map-ctrl-btn {
            width: 40px;
            height: 40px;
            background: rgba(13, 21, 37, 0.9);
            backdrop-filter: blur(8px);
            border: 1px solid var(--border);
            border-radius: var(--radius-sm);
            color: var(--text-light);
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: all 0.2s;
        }

        .map-ctrl-btn:hover {
            background: var(--bg-card);
            border-color: var(--accent);
            color: var(--text-white);
        }

        .map-legend {
            position: absolute;
            bottom: 24px;
            right: 24px;
            /* Le panneau accueille desormais aussi les sources : sans borne,
               les lignes d'attribution (longues par nature) l'etiraient sur
               plus de 400 px et il mangeait le tiers de la carte. */
            max-width: min(300px, calc(100% - 48px));
            /* Plafond global : le panneau ne peut jamais manger plus de la
               moitie basse de la carte. */
            max-height: min(58vh, 430px);
            display: flex;
            flex-direction: column;
            background: rgba(13, 21, 37, 0.9);
            backdrop-filter: blur(8px);
            border: 1px solid var(--border);
            border-radius: var(--radius);
            padding: 16px;
            z-index: 50;
        }

        /* C'est un <button> depuis qu'il a cesse d'etre un <div> cliquable :
           il faut donc neutraliser l'apparence native. */
        .legend-title {
            width: 100%;
            padding: 0;
            background: none;
            border: 0;
            font-family: inherit;
            font-size: 0.7rem;
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 1px;
            margin-bottom: 12px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 6px;
        }
        .legend-title:hover { color: var(--text-light); }
        .legend-title:focus-visible {
            outline: 2px solid rgba(96,165,250,.85);
            outline-offset: 3px;
        }

        .legend-title::after {
            content: '▾';
            font-size: 0.6rem;
            color: var(--text-dim);
            transition: transform 0.2s ease;
        }

        .map-legend.collapsed .legend-title {
            margin-bottom: 0;
        }

        .map-legend.collapsed .legend-title::after {
            transform: rotate(-90deg);
        }

        /* Replier masque tout le corps, echelle des incendies comprise. */
        .map-legend.collapsed #lm-legend-body {
            display: none;
        }

        /* EN LIGNES QUI SE REPLIENT, ET NON EN COLONNE.
           Cinq paliers d'importance, plus les echelles des couches allumees,
           faisaient une quinzaine de lignes empilees : la legende occupait la
           moitie de la hauteur de la carte, et c'est la carte qu'on vient
           regarder. Les libelles sont courts (« Majeur », « Critique ») — ils
           tiennent a deux ou trois par ligne. */
        .legend-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px 12px;
        }

        .legend-item {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 0.72rem;
            color: var(--text-light);
        }

        /* Les sous-legendes des couches gardent une lecture en colonne : leurs
           libelles sont plus longs (« Activite soutenue », « Vigilance
           orange ») et se replieraient mal. */
        .legend-items-weather,
        .legend-items-migration {
            flex-direction: column;
            flex-wrap: nowrap;
            gap: 4px;
        }

        /* DERNIER GARDE-FOU. Meme repliees, les echelles cumulees d'incendie,
           de vent, de vigilance et de passages finissent par depasser sur un
           ecran bas. Le corps de la legende defile alors sur lui-meme plutot
           que de pousser le panneau hors de l'ecran. */
        #lm-legend-body {
            max-height: min(46vh, 340px);
            overflow-y: auto;
            overscroll-behavior: contain;
        }

        .legend-dot {
            width: 10px;
            height: 10px;
            border-radius: 50%;
        }

        /* ==========================================================================
           5.2 EU MARKETS WIDGET
           ========================================================================== */
        .market-widget {
            position: relative;
            width: auto;
            max-width: none;
            margin: 8px 10px 6px;
            background: rgba(13, 21, 37, 0.95);
            backdrop-filter: blur(10px);
            border: 1px solid var(--border);
            border-radius: var(--radius);
            box-shadow: 0 14px 40px rgba(0,0,0,0.45);
            z-index: 10;
            overflow: hidden;
            user-select: none;
            flex-shrink: 0;
        }

        .market-widget.collapsed .market-widget-meta,
        .market-widget.collapsed .market-widget-body {
            display: none;
        }

        .market-widget-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 10px 12px;
            border-bottom: 1px solid var(--border);
            background: linear-gradient(180deg, rgba(19, 29, 46, 0.95) 0%, rgba(13, 21, 37, 0.7) 100%);
        }

        .market-widget-title {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.7rem;
            font-weight: 700;
            color: var(--text-white);
            letter-spacing: 0.5px;
            text-transform: uppercase;
        }

        .market-widget-title i { font-size: 0.9rem; color: var(--accent); }

        .market-live-dot {
            width: 6px;
            height: 6px;
            border-radius: 50%;
            background: var(--success);
            box-shadow: 0 0 10px rgba(16,185,129,0.55);
            animation: marketLivePulse 2s infinite;
        }

        @keyframes marketLivePulse {
            0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
            50% { opacity: 0.85; box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
        }

        .market-widget-actions {
            display: flex;
            align-items: center;
            gap: 6px;
        }

        .market-widget-btn {
            width: 30px;
            height: 30px;
            border-radius: 8px;
            background: rgba(255,255,255,0.03);
            border: 1px solid var(--border);
            color: var(--text-light);
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.2s, border-color 0.2s, color 0.2s, transform 0.08s;
        }

        .market-widget-btn:hover {
            background: rgba(255,255,255,0.06);
            border-color: rgba(59,130,246,0.35);
            color: var(--text-white);
        }

        .market-widget-btn:active {
            transform: translateY(1px);
        }

        .market-widget-meta {
            display: grid;
            grid-template-columns: minmax(0, 1fr);
            gap: 8px;
            padding: 10px 12px;
            border-bottom: 1px solid var(--border);
        }

        .market-pill {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 5px 8px;
            border-radius: 999px;
            font-size: 0.62rem;
            font-family: var(--font-mono);
            border: 1px solid rgba(255,255,255,0.08);
            background: rgba(255,255,255,0.03);
            color: var(--text-light);
            width: fit-content;
            max-width: 100%;
        }

        .market-pill.low { border-color: rgba(16,185,129,0.25); background: rgba(16,185,129,0.08); color: #a7f3d0; }
        .market-pill.guarded { border-color: rgba(59,130,246,0.28); background: rgba(59,130,246,0.10); color: #bfdbfe; }
        .market-pill.elevated { border-color: rgba(251,191,36,0.30); background: rgba(251,191,36,0.10); color: #fde68a; }
        .market-pill.high { border-color: rgba(249,115,22,0.30); background: rgba(249,115,22,0.10); color: #fed7aa; }
        .market-pill.critical { border-color: rgba(239,68,68,0.30); background: rgba(239,68,68,0.10); color: #fecaca; }

        .market-breadth {
            justify-self: start;
            font-family: var(--font-mono);
            font-size: 0.62rem;
            color: var(--text-muted);
            white-space: normal;
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 6px;
            line-height: 1.25;
            max-width: 100%;
        }

        .market-breadth-item {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            padding: 2px 6px;
            border-radius: 999px;
            border: 1px solid rgba(255,255,255,0.10);
            background: rgba(255,255,255,0.03);
            white-space: nowrap;
        }

        .market-session {
            font-family: var(--font-mono);
            font-size: 0.62rem;
            color: var(--text-muted);
            line-height: 1.35;
            white-space: normal;
            overflow-wrap: anywhere;
            max-width: 100%;
            display: flex;
            flex-direction: column;
            gap: 2px;
        }

        .market-session-state {
            font-weight: 650;
            color: var(--text-light);
        }

        .market-session-state.open {
            color: #a7f3d0;
        }

        .market-session-state.closed {
            color: #cbd5e1;
        }

	        .market-updated {
	            grid-column: 1 / -1;
	            font-family: var(--font-mono);
	            font-size: 0.58rem;
	            color: var(--text-dim);
	        }

	        .market-warnings {
	            grid-column: 1 / -1;
	            font-family: var(--font-mono);
	            font-size: 0.56rem;
	            color: rgba(251, 191, 36, 0.85);
	            line-height: 1.25;
	            white-space: normal;
	            word-break: break-word;
	        }

        .market-widget-body {
            padding: 6px 0 10px;
        }

        .market-table {
            display: flex;
            flex-direction: column;
        }

        .market-row {
            display: grid;
            grid-template-columns: 1fr auto;
            gap: 10px;
            padding: 9px 12px;
            border-top: 1px solid rgba(255,255,255,0.05);
            cursor: default;
        }

        .market-row:first-child {
            border-top: none;
        }

        .market-row:hover {
            background: rgba(255,255,255,0.03);
        }

        .market-left {
            display: flex;
            flex-direction: column;
            gap: 5px;
            min-width: 0;
        }

        .market-name {
            display: flex;
            align-items: baseline;
            justify-content: space-between;
            gap: 10px;
        }

        .market-name .label {
            font-size: 0.72rem;
            font-weight: 650;
            color: var(--text-white);
            line-height: 1.2;
            min-width: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .market-name .symbol {
            font-family: var(--font-mono);
            font-size: 0.58rem;
            color: var(--text-dim);
            flex-shrink: 0;
        }

        .market-spark {
            width: 100%;
            height: 18px;
        }

        .market-right {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
            justify-content: center;
            gap: 3px;
            text-align: right;
        }

        .market-price {
            font-family: var(--font-mono);
            font-size: 0.75rem;
            font-weight: 650;
            color: var(--text-white);
            white-space: nowrap;
        }

        .market-change {
            font-family: var(--font-mono);
            font-size: 0.64rem;
            white-space: nowrap;
        }

        .market-change.up { color: var(--success); }
        .market-change.down { color: var(--danger); }
        .market-change.flat { color: var(--text-muted); }

        .market-footnote {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            padding: 10px 12px 0;
            font-size: 0.55rem;
            color: var(--text-dim);
            border-top: 1px solid rgba(255,255,255,0.05);
            margin-top: 6px;
        }

        .market-source-link {
            color: var(--text-muted);
            text-decoration: none;
            display: inline-flex;
            align-items: center;
            gap: 6px;
            white-space: nowrap;
        }

        .market-source-link:hover {
            color: #fff;
        }

        @media (max-width: 768px) {
            .market-widget { margin: 8px 8px 6px; }
        }

        /* ==========================================================================
           5.5 CLUSTER MARKERS & RADIAL POPUP (TasteAtlas Style)
           ========================================================================== */
        .map-marker.cluster {
            width: 32px;
            height: 32px;
            background: var(--bg-card);
            border: 2px solid var(--accent);
            display: flex;
            align-items: center;
            justify-content: center;
            font-family: var(--font-mono);
            font-size: 0.75rem;
            font-weight: 700;
            color: var(--text-white);
            box-shadow: 0 2px 8px rgba(0,0,0,0.4), 0 0 0 3px rgba(59, 130, 246, 0.2);
            transition: box-shadow 0.2s, border-color 0.2s;
        }

        .map-marker.cluster:hover {
            box-shadow: 0 4px 16px rgba(0,0,0,0.5), 0 0 0 5px rgba(59, 130, 246, 0.3);
        }

        .map-marker.cluster .cluster-count {
            position: absolute;
            top: -6px;
            right: -6px;
            min-width: 18px;
            height: 18px;
            background: var(--danger);
            border: 2px solid var(--bg-deep);
            border-radius: 10px;
            font-size: 0.6rem;
            font-weight: 700;
            color: #fff;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0 4px;
        }

        /* ------------------------------------------------------------------
           CONTENU D'UN AMAS — UNE LISTE ANCREE

           L'eventail radial qui occupait cette place disposait ses membres sur
           trois anneaux autour du point de clic. C'etait joli et illisible :
           les titres tenaient en dix caracteres, l'ordre etait dicte par la
           geometrie plutot que par l'importance, et au-dela d'une trentaine
           d'evenements le troisieme anneau debordait sans que rien ne le dise.

           Une liste repond mieux a la seule question qu'on pose a un amas :
           « qu'est-ce qu'il y a la-dedans ? ». Elle est ancree pres du disque,
           pas centree sur l'ecran ; elle ne verrouille pas le defilement de la
           page ; elle ne deplace pas la camera.
           ------------------------------------------------------------------ */
        .cluster-list {
            position: fixed;
            z-index: 460;
            width: min(340px, calc(100vw - 32px));
            display: flex;
            flex-direction: column;
            background: var(--bg-panel, #0d1525);
            border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
            border-radius: 12px;
            box-shadow: 0 18px 44px rgba(2, 4, 8, 0.62);
            overflow: hidden;
        }
        .cluster-list[hidden] { display: none; }

        .cluster-list-head {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 9px 10px 9px 12px;
            border-bottom: 1px solid var(--border, rgba(255, 255, 255, 0.08));
            background: rgba(255, 255, 255, 0.03);
        }
        .cluster-list-title {
            flex: 1 1 auto;
            font-size: 0.78rem;
            font-weight: 600;
            color: var(--text-white, #e2e8f0);
        }
        /* « Zoomer ici » : le mouvement de camera que l'ancienne modale
           imposait devient une action facultative, et nommee. */
        .cluster-list-zoom {
            flex: none;
            padding: 3px 9px;
            border: 1px solid rgba(59, 130, 246, 0.45);
            border-radius: 999px;
            background: rgba(59, 130, 246, 0.14);
            color: #93c5fd;
            font-family: inherit;
            font-size: 0.66rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s ease, border-color 0.15s ease;
        }
        .cluster-list-zoom:hover {
            background: rgba(59, 130, 246, 0.26);
            border-color: rgba(59, 130, 246, 0.8);
        }
        .cluster-list-close {
            flex: none;
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            border: 0;
            border-radius: 6px;
            background: transparent;
            color: var(--text-muted, #94a3b8);
            font-size: 0.85rem;
            cursor: pointer;
            transition: background 0.15s ease, color 0.15s ease;
        }
        .cluster-list-close:hover {
            background: rgba(255, 255, 255, 0.08);
            color: #fff;
        }

        /* Douze lignes visibles, le reste defile. Un amas de cent evenements
           reste integralement atteignable — ce que les trois anneaux ne
           permettaient pas. */
        .cluster-list-items {
            margin: 0;
            padding: 4px;
            list-style: none;
            max-height: min(52vh, 420px);
            overflow-y: auto;
            overscroll-behavior: contain;
        }

        .cluster-row {
            display: flex;
            align-items: flex-start;
            gap: 8px;
            padding: 7px 8px;
            border-radius: 8px;
            cursor: pointer;
            transition: background 0.12s ease;
        }
        .cluster-row:hover,
        .cluster-row:focus-visible { background: rgba(255, 255, 255, 0.06); }
        .cluster-row:focus-visible { outline: 2px solid rgba(96, 165, 250, 0.9); outline-offset: -2px; }
        /* Ligne dont la fiche est ouverte : on garde le fil de sa lecture en
           parcourant l'amas. */
        .cluster-row.is-open { background: rgba(59, 130, 246, 0.16); }

        /* Filet de gravite : la meme echelle que les marqueurs de la carte,
           pour qu'on relie la ligne au point sans effort. */
        .cluster-row-sev {
            flex: none;
            width: 3px;
            align-self: stretch;
            border-radius: 2px;
            background: var(--text-dim, #475569);
        }
        .cluster-row[data-tier='critical'] .cluster-row-sev { background: #ef4444; }
        .cluster-row[data-tier='major']    .cluster-row-sev { background: #f97316; }
        .cluster-row[data-tier='notable']  .cluster-row-sev { background: #eab308; }
        .cluster-row[data-tier='minor']    .cluster-row-sev { background: #38bdf8; }

        .cluster-row-icon {
            flex: none;
            width: 18px;
            height: 18px;
            margin-top: 1px;
            color: var(--text-muted, #94a3b8);
        }
        .cluster-row-icon svg { width: 100%; height: 100%; display: block; }

        .cluster-row-body { flex: 1 1 auto; min-width: 0; }

        /* Le titre ENTIER, sur deux lignes au plus. L'eventail le coupait a
           dix caracteres : « Incendie d… » ne distingue rien. */
        .cluster-row-title {
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
            overflow: hidden;
            font-size: 0.74rem;
            line-height: 1.3;
            color: var(--text-light, #cbd5e1);
        }
        .cluster-row.is-open .cluster-row-title { color: #fff; }

        .cluster-row-meta {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 5px;
            margin-top: 3px;
            font-size: 0.63rem;
            color: var(--text-dim, #475569);
        }
        .cluster-row-flag {
            width: 14px;
            height: auto;
            border-radius: 2px;
            flex: none;
        }
        .cluster-row-place { color: var(--text-muted, #94a3b8); }
        .cluster-row-age::before { content: '· '; }
        .cluster-row-approx {
            padding: 0 5px;
            border: 1px dashed rgba(148, 163, 184, 0.5);
            border-radius: 999px;
            font-size: 0.58rem;
            color: var(--text-muted, #94a3b8);
        }
        .cluster-row-toll {
            padding: 0 5px;
            border-radius: 999px;
            background: rgba(239, 68, 68, 0.18);
            color: #fca5a5;
            font-weight: 700;
            font-size: 0.58rem;
        }
        .cluster-row-toll::after { content: ' \2020'; }

        /* Ecran etroit : la liste s'elargit et se raccourcit — sur un telephone
           la carte doit rester visible derriere elle. */
        @media (max-width: 768px) {
            .cluster-list { width: calc(100vw - 24px); }
            .cluster-list-items { max-height: 42vh; }
        }

        /* ==========================================================================
           6. SIDEBAR
           ========================================================================== */
        .sidebar-header {
            padding: 20px;
            border-bottom: 1px solid var(--border);
        }

        .sidebar-title {
            font-size: 0.9rem;
            font-weight: 700;
            color: var(--text-white);
            margin-bottom: 4px;
        }

        .sidebar-subtitle {
            font-size: 0.7rem;
            color: var(--text-muted);
        }

        .sidebar-search {
            padding: 0 20px;
            margin: 16px 0;
        }

        .search-input-wrap {
            position: relative;
        }

        .search-input {
            width: 100%;
            padding: 12px 16px 12px 40px;
            background: var(--bg-card);
            border: 1px solid var(--border);
            border-radius: var(--radius-sm);
            color: var(--text-white);
            font-size: 0.85rem;
            outline: none;
            transition: all 0.2s;
        }

        .search-input::placeholder { color: var(--text-dim); }
        .search-input:focus { border-color: var(--accent); }

        .search-icon {
            position: absolute;
            left: 14px;
            top: 50%;
            transform: translateY(-50%);
            color: var(--text-dim);
        }

        .feed-section-title {
            padding: 12px 8px;
            font-size: 0.7rem;
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 1px;
            position: sticky;
            top: 0;
            background: var(--bg-deep);
            z-index: 10;
        }

        /* ==========================================================================
           7. EVENT CARDS
           ========================================================================== */
        .event-card {
            background: var(--bg-card);
            border: 1px solid var(--border);
            border-radius: var(--radius);
            padding: 14px;
            margin-bottom: 10px;
            cursor: pointer;
            transition: all 0.2s;
            position: relative;
            overflow: hidden;
        }

        .event-card::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            width: 3px;
            background: var(--event-color, var(--accent));
        }

        .event-card:hover {
            background: var(--bg-card-hover);
            border-color: var(--border-light);
            transform: translateX(2px);
        }

        .event-header {
            display: flex;
            align-items: flex-start;
            justify-content: space-between;
            gap: 12px;
            margin-bottom: 8px;
        }

        .event-category {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 0.65rem;
            color: var(--event-color, var(--text-muted));
            text-transform: uppercase;
            letter-spacing: 0.5px;
            font-weight: 600;
        }

        .event-severity {
            padding: 3px 8px;
            border-radius: 4px;
            font-size: 0.6rem;
            font-weight: 700;
            font-family: var(--font-mono);
            text-transform: uppercase;
            background: var(--event-color, var(--accent));
            color: #fff;
        }

        .event-title {
            font-size: 0.85rem;
            font-weight: 600;
            color: var(--text-white);
            line-height: 1.4;
            margin-bottom: 8px;
        }

        .event-meta {
            display: flex;
            align-items: center;
            gap: 12px;
            font-size: 0.7rem;
            color: var(--text-muted);
        }

        .event-meta-item {
            display: flex;
            align-items: center;
            gap: 4px;
        }

        .event-meta-item i { font-size: 0.85rem; }

        /* ==========================================================================
           8. STATS FOOTER
           ========================================================================== */
        .stats-footer {
            padding: 16px 20px;
            background: var(--bg-panel);
            border-top: 1px solid var(--border);
        }

        .stats-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 12px;
        }

        .stat-card {
            background: var(--bg-card);
            border: 1px solid var(--border);
            border-radius: var(--radius-sm);
            padding: 12px;
            text-align: center;
        }

        .stat-value {
            font-family: var(--font-mono);
            font-size: 1.3rem;
            font-weight: 700;
            color: var(--text-white);
        }

        .stat-label {
            font-size: 0.6rem;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            margin-top: 4px;
        }

        /* ==========================================================================
           9. RESPONSIVE
           ========================================================================== */
        @media (max-width: 1200px) {
            /* meme portee que le bloc de jetons en tete de fichier */
            .dashboard { --sidebar-w: 360px; }
        }

        /* ==================================================================
           MOBILE / TABLETTE — LA CARTE EN PLEIN ECRAN, LE FLUX EN FEUILLE

           L'ancienne mise en page empilait une carte de 60vh au-dessus d'un
           panneau en `overflow: visible` : la page mesurait plus de 4 000 px
           de haut, la carte etait reduite a un bandeau, et le flux se
           parcourait en faisant defiler la page entiere.

           Desormais la carte occupe toute la surface et le flux devient une
           feuille glissante par-dessus, a trois crans (apercu / moitie /
           plein). La carte reste visible et manipulable aux deux premiers.
           ================================================================== */
        @media (max-width: 1024px) {
            .dashboard {
                /* Plus de `height: auto` : la feuille est positionnee par
                   rapport a une hauteur connue, la page ne defile plus. */
                height: calc(100vh - var(--nav-height, 90px));
                height: calc(100svh - var(--nav-height, 90px));
                height: calc(100dvh - var(--nav-height, 90px));
                grid-template-rows: auto minmax(0, 1fr);
                overflow: hidden;
            }

            .dashboard-body {
                position: relative;          /* reference de la feuille */
                display: block;              /* on sort de la grille 2 colonnes */
                grid-template-columns: none;
                overflow: hidden;
            }

            /* CEINTURE ET BRETELLES. `.dashboard` est deja borne a la hauteur
               de la fenetre, mais il a suffi d'une regle de position perdue
               pour que le panneau ressorte du cadre et rende la page haute de
               1 868 px sur un ecran de 812. Une page qui ne defile pas ne peut
               pas partir vers son pied de page pendant qu'on tire la feuille.

               Portee a la SEULE page de la carte, via sa classe de body. Un
               `html:has(.dashboard)` aurait fait la meme chose, mais la carte
               n'est pas seule a pouvoir porter un jour une classe aussi
               commune que « dashboard » — et geler le defilement d'une autre
               page par ricochet serait un degat difficile a relier a sa
               cause. */
            body.page-europe-live,
            html:has(body.page-europe-live) {
                overflow: hidden;
                overscroll-behavior-y: none;
            }

            /* La carte prend toute la zone disponible. */
            .map-section {
                position: absolute;
                inset: 0;
                display: flex;
                flex-direction: column;
            }

            /* ---- La feuille ----

               SELECTEUR VOLONTAIREMENT PLUS SPECIFIQUE que `.sidebar-section`.

               La mise en page « feuille glissante » ne s'appliquait PAS. Une
               autre regle `.sidebar-section { position: relative }`, sans
               media query, vit un millier de lignes plus bas : a specificite
               egale, c'est l'ordre du fichier qui tranche, et elle gagnait.

               Le panneau restait donc un bloc dans le flux, sous la carte —
               d'ou le symptome signale : tirer la feuille faisait descendre la
               PAGE vers le pied de page au lieu d'ouvrir le panneau, qui se
               trouvait reellement la-bas. Rien ne le laissait deviner : la
               poignee s'affichait, le JS calculait ses crans, la transform
               s'appliquait — sur un element mal positionne.

               `.dashboard-body > .sidebar-section` porte deux classes : il
               l'emporte quelle que soit la position des regles dans le
               fichier. */
            .dashboard-body > .sidebar-section {
                position: absolute;
                left: 0;
                right: 0;
                bottom: 0;
                z-index: 60;
                height: 92%;
                max-height: 92%;
                border-left: none;
                border-top: 1px solid var(--border-light);
                border-radius: 18px 18px 0 0;
                background: var(--bg-panel);
                box-shadow: 0 -18px 46px rgba(0, 0, 0, .55);
                display: flex;
                flex-direction: column;
                overflow: hidden;            /* le scroll appartient au corps */

                /* Position pilotee par 15-sheet.js. La valeur de repli place
                   la feuille au cran « apercu » avant l'execution du JS, pour
                   qu'elle ne surgisse pas apres coup. */
                transform: translateY(var(--sheet-y, calc(100% - 148px)));
                will-change: transform;
            }
            /* Transition uniquement hors glissement : pendant le drag on suit
               le doigt au pixel, sinon le mouvement paraitrait en retard. */
            .dashboard-body > .sidebar-section:not(.is-dragging) {
                transition: transform .34s cubic-bezier(.22, 1, .36, 1);
            }

            .sheet-grabber {
                display: flex;
                align-items: center;
                justify-content: center;
                width: 100%;
                height: 30px;
                flex: none;
                padding: 0;
                border: none;
                background: transparent;
                cursor: grab;
                /* Le navigateur ne doit pas s'approprier le geste vertical :
                   uniquement ici, pas sur le corps de la feuille (qui doit,
                   lui, defiler normalement). */
                touch-action: none;
            }
            .sheet-grabber:active { cursor: grabbing; }

            /* L'EN-TETE EST AUSSI UNE PRISE.
               Une poignee de 30 px est trop etroite pour un pouce ; la manquer
               ne se contentait pas de ne rien faire, cela declenchait le
               defilement de la page. `touch-action: none` doit couvrir toute
               la zone que le JS ecoute, sinon le navigateur s'approprie le
               geste avant que preventDefault() ne soit atteint. */
            .sidebar-section .sidebar-header {
                touch-action: none;
                cursor: grab;
                user-select: none;
            }
            .sidebar-section.is-dragging .sidebar-header { cursor: grabbing; }
            .sheet-grabber-bar {
                width: 42px;
                height: 4px;
                border-radius: 99px;
                background: rgba(255, 255, 255, .26);
                transition: background .2s ease, width .2s ease;
            }
            .sheet-grabber:hover .sheet-grabber-bar,
            .sheet-grabber:focus-visible .sheet-grabber-bar {
                background: rgba(255, 255, 255, .45);
                width: 52px;
            }
            .sheet-grabber:focus-visible {
                outline: 2px solid rgba(96, 165, 250, .75);
                outline-offset: -4px;
                border-radius: 18px 18px 0 0;
            }

            /* En-tete compact : au cran « apercu » c'est la seule chose
               visible, elle doit tenir en une ligne. */
            .sidebar-header {
                flex: none;
                padding: 0 16px 8px;
            }
            .sidebar-tabs { flex: none; }

            /* Le corps est le seul element defilant, et son elastique ne doit
               pas se propager a la page derriere. */
            .sidebar-panels {
                flex: 1;
                min-height: 0;
                overflow: hidden;
            }
            .sidebar-panel.active {
                height: 100%;
                overflow-y: auto;
                overscroll-behavior: contain;
                -webkit-overflow-scrolling: touch;
            }

            /* Legende et controles se rangent au-dessus du cran « apercu »
               pour ne pas passer sous la feuille. */
            .map-legend {
                bottom: 168px;
                right: 12px;
                padding: 10px 12px;
                max-height: 42vh;
            }
            #lm-legend-body { max-height: 30vh; }
            .map-controls {
                bottom: 168px;
                left: 12px;
            }

            .dashboard-header { padding: 12px 18px; }
            .filters-bar { padding: 6px 14px; gap: 6px; }
        }

        /* ---- EN-TETE SUR MOBILE ----
           Marque + horloge + 3 KPI ne tiennent pas sur une ligne de 390 px.
           On empile en deux rangees et on retire ce qui releve du detail
           expert (date longue, comparaison de fuseaux, selecteur de fuseau) :
           ces elements reviendront avec le preset Expert.

           Les KPI, eux, ne disparaissent plus : `display: none` supprimait
           l'information la plus dense de la page precisement sur l'ecran ou
           elle est la plus utile. */
        @media (max-width: 768px) {
            .dashboard-header {
                flex-direction: column;
                align-items: stretch;
                gap: 8px;
                padding: 10px 14px;
            }

            .hud-brand { flex: none; }
            .hud-title-group h1 { font-size: 1rem; white-space: nowrap; }
            .hud-tagline { display: none; }      /* redondant avec le titre de page */
            .hud-status { margin-top: 2px; font-size: .68rem; }

            .hud-center {
                display: flex;
                align-items: center;
                justify-content: space-between;
                gap: 10px;
                width: 100%;
            }

            /* Horloge seule : la date et la double heure sont du detail. */
            .hud-timeblock { flex: none; }
            .hud-clock { font-size: 1rem; }
            .hud-date,
            .hud-timezones { display: none; }

            .hud-metrics {
                display: flex;
                gap: 6px;
                flex: 1;
                justify-content: flex-end;
                min-width: 0;
            }
            .hud-metric {
                padding: 4px 8px;
                min-width: 0;
                text-align: center;
            }
            .hud-metric-value { font-size: .95rem; line-height: 1.1; }
            .hud-metric-label {
                font-size: .48rem;
                letter-spacing: .03em;
                white-space: nowrap;
            }
        }

        /* Tres petits ecrans : on garde les KPI, on lache la marque textuelle
           (le titre de la page et l'onglet du navigateur la portent deja). */
        @media (max-width: 400px) {
            .hud-title-group h1 { font-size: .92rem; }
            .hud-metric { padding: 3px 6px; }
            .hud-metric-label { font-size: .45rem; }
        }

        @media (prefers-reduced-motion: reduce) {
            .sidebar-section:not(.is-dragging) { transition: none; }
        }

        @media (max-width: 768px) {
            /* `.hud-metrics { display: none }` retire : les KPI sont desormais
               compactes (voir le bloc « EN-TETE SUR MOBILE » plus haut) plutot
               que supprimes. */
            .filters-bar { padding: 6px 12px; gap: 6px; }
            .filter-chip { padding: 5px 8px; font-size: 0.65rem; }
        }

        /* ==========================================================================
           10. DETAIL POPUP / MODAL
           ========================================================================== */
        .detail-popup-overlay {
            position: fixed;
            inset: 0;
            background: rgba(2, 4, 8, 0.7);
            backdrop-filter: blur(4px);
            z-index: 500;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s ease;
        }

        .detail-popup-overlay.active {
            opacity: 1;
            visibility: visible;
        }

        .detail-popup {
            position: fixed;
            bottom: 24px;
            left: 24px;
            width: 400px;
            min-width: 320px;
            min-height: 250px;
            max-width: calc(100vw - 48px);
            max-height: calc(100vh - 150px);
            background: var(--bg-panel);
            border: 1px solid var(--border-light);
            border-radius: var(--radius);
            box-shadow: 0 25px 60px rgba(0, 0, 0, 0.5);
            z-index: 510;
            transform: translateY(20px);
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            resize: none;
            contain: layout paint;
        }

        .detail-popup.active {
            transform: translateY(0);
            opacity: 1;
            visibility: visible;
        }

        .detail-popup.dragging {
            transition: none !important;
            user-select: none;
            box-shadow: none;
        }

        .detail-popup.dragging .detail-popup-body {
            pointer-events: none;
        }

        .detail-popup.dragging .detail-popup-header *,
        .detail-popup.dragging .detail-popup-body * {
            animation: none !important;
            transition: none !important;
        }

        body.popup-dragging .detail-popup,
        body.popup-dragging .detail-popup * {
            box-shadow: none !important;
            filter: none !important;
        }

        body.popup-dragging .detail-popup-overlay {
            backdrop-filter: none !important;
        }

        /* Resize handle */
        .detail-popup::after {
            content: none;
        }

        .detail-popup-header {
            padding: 12px 16px;
            background: var(--bg-card);
            border-bottom: 1px solid var(--border);
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            position: relative;
            cursor: grab;
            user-select: none;
            touch-action: none;
        }

        .detail-popup-header:active {
            cursor: grabbing;
        }

        .detail-popup-header::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            width: 4px;
            background: var(--popup-color, var(--accent));
        }

        /* Navigation arrows */
        .detail-popup-nav {
            display: flex;
            align-items: center;
            gap: 4px;
            margin-right: 8px;
        }

        .detail-popup-nav-btn {
            width: 28px;
            height: 28px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid var(--border);
            border-radius: 6px;
            color: var(--text-muted);
            cursor: pointer;
            transition: all 0.2s;
            font-size: 0.9rem;
        }

        .detail-popup-nav-btn:hover:not(:disabled) {
            background: rgba(59, 130, 246, 0.2);
            border-color: var(--accent);
            color: var(--text-white);
        }

        .detail-popup-nav-btn:disabled {
            opacity: 0.3;
            cursor: not-allowed;
        }

        .detail-popup-nav-counter {
            font-size: 0.65rem;
            color: var(--text-dim);
            font-family: var(--font-mono);
            min-width: 50px;
            text-align: center;
        }

        .detail-popup-header-controls {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .detail-popup-category {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 0.7rem;
            font-weight: 600;
            color: var(--popup-color, var(--accent));
            text-transform: uppercase;
            letter-spacing: 0.5px;
            flex: 1;
            min-width: 0;
        }

        .detail-popup-category svg,
        .detail-popup-category img {
            width: 16px;
            height: 16px;
            flex-shrink: 0;
            display: block;
        }

        .detail-popup-close {
            width: 28px;
            height: 28px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid var(--border);
            border-radius: 6px;
            color: var(--text-muted);
            cursor: pointer;
            transition: all 0.2s;
            flex-shrink: 0;
        }

        .detail-popup-close:hover {
            background: rgba(239, 68, 68, 0.2);
            border-color: var(--danger);
            color: var(--danger);
        }

        /* Approximate location indicator */
        .detail-popup-tag.approximate {
            background: rgba(251, 191, 36, 0.15);
            color: #fbbf24;
            border: 1px solid rgba(251, 191, 36, 0.3);
        }

        .detail-popup-body {
            padding: 20px;
            overflow-y: auto;
            flex: 1;
            contain: content;
        }

        .detail-popup-tags {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-bottom: 14px;
        }

        .detail-popup-tag {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 0.65rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.3px;
        }

        .detail-popup-tag.category {
            background: var(--popup-color, var(--accent));
            color: #fff;
        }

        .detail-popup-tag.severity {
            background: var(--severity-bg);
            color: var(--severity-color);
            border: 1px solid var(--severity-color);
        }

        .detail-popup-tag.type {
            background: rgba(139, 92, 246, 0.15);
            color: #a78bfa;
            border: 1px solid rgba(139, 92, 246, 0.3);
        }

        .detail-popup-tag.death-toll {
            background: rgba(239, 68, 68, 0.15);
            color: #f87171;
            border: 1px solid rgba(239, 68, 68, 0.35);
        }

        .detail-popup-tag.death-toll svg {
            width: 14px;
            height: 14px;
        }

        /* ------------------------------------------------------------------
           FICHE D'UN EVENEMENT — HIERARCHIE DE LECTURE

           gravite -> quand -> ou -> quoi -> combien -> sources -> actions.
           Les classes .detail-popup-tags / -meta / -coords qui suivent plus
           bas ne sont PAS supprimees : la fiche d'une base militaire les
           utilise encore.
           ------------------------------------------------------------------ */

        /* 1. Bandeau de gravite. Le palier y est ecrit en toutes lettres :
              une pastille coloree seule oblige a chercher la legende. */
        .detail-popup-band {
            display: flex;
            align-items: baseline;
            flex-wrap: wrap;
            gap: 8px;
            padding: 7px 11px;
            margin-bottom: 10px;
            border-radius: 8px;
            border-left: 3px solid var(--severity-color, #64748b);
            background: var(--severity-bg, rgba(148, 163, 184, 0.12));
        }
        .detail-popup-band-tier {
            font-size: 0.68rem;
            font-weight: 700;
            letter-spacing: 0.06em;
            text-transform: uppercase;
            color: var(--severity-color, #cbd5e1);
        }
        .detail-popup-band-cat {
            font-size: 0.7rem;
            color: var(--text-light, #cbd5e1);
        }
        .detail-popup-band-cat::before { content: '· '; color: var(--text-dim, #475569); }
        .detail-popup-band-when {
            margin-left: auto;
            font-size: 0.68rem;
            color: var(--text-muted, #94a3b8);
            white-space: nowrap;
        }

        /* 2. Ou. La REGION existait en base et n'etait affichee nulle part —
              or « France » ne situe pas un incendie, « Haute-Loire » si. */
        .detail-popup-place {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: 7px;
            margin-bottom: 9px;
            font-size: 0.76rem;
        }
        .detail-popup-place-flag {
            width: 20px;
            height: auto;
            border-radius: 2px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
            flex: none;
        }
        .detail-popup-place-name {
            font-weight: 600;
            color: var(--text-light, #cbd5e1);
        }
        .detail-popup-place-region { color: var(--text-muted, #94a3b8); }
        .detail-popup-place-region::before { content: '· '; color: var(--text-dim, #475569); }

        /* 3. Faits cles : les trois questions qu'on pose avant de lire. */
        .detail-popup-facts {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-bottom: 12px;
        }
        .detail-fact {
            display: inline-flex;
            align-items: center;
            gap: 5px;
            padding: 3px 9px;
            border-radius: 999px;
            font-size: 0.68rem;
            font-weight: 600;
            border: 1px solid transparent;
        }
        .detail-fact svg { width: 13px; height: 13px; }
        .detail-fact.is-toll {
            background: rgba(239, 68, 68, 0.15);
            border-color: rgba(239, 68, 68, 0.35);
            color: #f87171;
        }
        .detail-fact.is-verified {
            background: rgba(34, 197, 94, 0.13);
            border-color: rgba(34, 197, 94, 0.32);
            color: #4ade80;
        }
        /* Le pointille dit « estimation » — meme convention que le perimetre
           potentiellement brule sur la carte. */
        .detail-fact.is-approx {
            border-style: dashed;
            border-color: rgba(148, 163, 184, 0.5);
            color: var(--text-muted, #94a3b8);
            cursor: help;
        }
        .detail-fact.is-exact {
            background: rgba(148, 163, 184, 0.1);
            border-color: rgba(148, 163, 184, 0.25);
            color: var(--text-muted, #94a3b8);
            font-weight: 500;
        }

        /* 6. Sources. Un simple « +3 » ne disait pas de qui il s'agissait :
              elles sont desormais toutes nommees, sous un intitule. */
        .detail-popup-sources-label {
            flex: 1 0 100%;
            font-size: 0.62rem;
            font-weight: 700;
            letter-spacing: 0.09em;
            text-transform: uppercase;
            color: var(--text-dim, #475569);
        }

        /* 7. Actions, groupees en pied de fiche. */
        .detail-popup-actions {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: 8px;
            padding-top: 12px;
            border-top: 1px solid var(--border, rgba(255, 255, 255, 0.06));
        }
        .detail-popup-coords-value {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            margin-right: auto;
            font-size: 0.72rem;
            font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
            color: var(--text-muted, #94a3b8);
        }
        .detail-popup-action {
            padding: 4px 11px;
            border: 1px solid rgba(59, 130, 246, 0.35);
            border-radius: 6px;
            background: rgba(59, 130, 246, 0.12);
            color: #93c5fd;
            font-family: inherit;
            font-size: 0.68rem;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.15s ease, border-color 0.15s ease;
        }
        .detail-popup-action:hover {
            background: rgba(59, 130, 246, 0.24);
            border-color: rgba(59, 130, 246, 0.7);
        }

        .detail-popup-title {
            font-size: 1.05rem;
            font-weight: 600;
            color: var(--text-white);
            line-height: 1.4;
            margin-bottom: 12px;
        }

        .detail-popup-description {
            font-size: 0.85rem;
            color: var(--text-light);
            line-height: 1.6;
            margin-bottom: 16px;
        }

        .detail-popup-meta {
            display: flex;
            flex-direction: column;
            gap: 10px;
            margin-bottom: 16px;
        }

        .detail-popup-meta-item {
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 0.8rem;
            color: var(--text-muted);
        }

        .detail-popup-meta-item i {
            font-size: 1rem;
            width: 20px;
            color: var(--text-dim);
        }

        .detail-popup-meta-item strong {
            color: var(--text-light);
        }

        .detail-popup-sources {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-bottom: 16px;
        }

        .detail-popup-source {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 8px 14px;
            background: rgba(59, 130, 246, 0.1);
            border: 1px solid rgba(59, 130, 246, 0.25);
            border-radius: 6px;
            font-size: 0.75rem;
            font-weight: 500;
            color: var(--accent);
            text-decoration: none;
            transition: all 0.2s;
        }

        .detail-popup-source:hover {
            background: rgba(59, 130, 246, 0.2);
            border-color: var(--accent);
            color: #fff;
        }

        .detail-popup-divider {
            height: 1px;
            background: var(--border);
            margin: 16px 0;
        }

        .detail-popup-coords {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 12px;
            background: var(--bg-card);
            border: 1px solid var(--border);
            border-radius: 8px;
            font-family: var(--font-mono);
            font-size: 0.8rem;
            color: var(--text-muted);
        }

        .detail-popup-coords i {
            color: var(--accent);
        }

        .detail-popup-coords button {
            margin-left: auto;
            padding: 6px 12px;
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid var(--border);
            border-radius: 4px;
            color: var(--text-light);
            font-size: 0.7rem;
            cursor: pointer;
            transition: all 0.2s;
        }

        .detail-popup-coords button:hover {
            background: var(--accent);
            border-color: var(--accent);
            color: #fff;
        }

        /* Confirmation de copie. Auparavant posee en style inline depuis le
           JS ; passee en classe pour que l'etat visuel vive avec le reste de
           la feuille plutot que dispersee dans le script. */
        .detail-popup-coords button.is-copied,
        .detail-popup-coords button.is-copied:hover {
            background: var(--success, #22c55e);
            border-color: var(--success, #22c55e);
            color: #fff;
        }

        /* Military Base specific */
        .detail-popup-base-info {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 12px;
            margin-bottom: 16px;
        }

        .detail-popup-base-stat {
            padding: 12px;
            background: var(--bg-card);
            border: 1px solid var(--border);
            border-radius: 8px;
            text-align: center;
        }

        .detail-popup-base-stat .value {
            font-family: var(--font-mono);
            font-size: 1.1rem;
            font-weight: 700;
            color: var(--text-white);
        }

        .detail-popup-base-stat .label {
            font-size: 0.65rem;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            margin-top: 4px;
        }

        /* Custom Map Popup (War Room Style) */
        .custom-map-popup .maplibregl-popup-content {
            background: rgba(15, 23, 42, 0.95);
            backdrop-filter: blur(12px);
            border: 1px solid rgba(59, 130, 246, 0.3);
            border-radius: 12px;
            padding: 0;
            color: #fff;
            box-shadow: 0 10px 30px -5px rgba(0, 0, 0, 0.8);
            font-family: var(--font-sans);
            min-width: 240px;
            overflow: hidden;
        }
        .custom-map-popup .maplibregl-popup-close-button {
            color: #94a3b8;
            font-size: 18px;
            padding: 6px 10px;
            z-index: 10;
        }
        .custom-map-popup .maplibregl-popup-close-button:hover {
            color: #fff;
            background: transparent;
        }
        .custom-map-popup .maplibregl-popup-tip {
            border-top-color: rgba(59, 130, 246, 0.3);
        }
        .popup-flag-img { width: 24px; height: auto; border-radius: 3px; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: inline-block; vertical-align: middle; }
        .popup-header {
            background: rgba(59, 130, 246, 0.1);
            padding: 12px 16px;
            border-bottom: 1px solid rgba(59, 130, 246, 0.2);
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .popup-flag { font-size: 1.4rem; line-height: 1; }
        .popup-title { font-weight: 700; font-size: 0.95rem; color: #fff; text-transform: uppercase; letter-spacing: 0.5px; }
        .popup-body { padding: 16px; }
        .popup-row { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 0.85rem; color: #cbd5e1; }
        .popup-row:last-child { margin-bottom: 0; }
        .popup-label { color: #94a3b8; font-size: 0.75rem; text-transform: uppercase; }
        .popup-value { font-weight: 600; font-family: var(--font-mono); }
        .popup-badge {
            display: inline-block; padding: 2px 8px; border-radius: 4px;
            font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
            background: rgba(16, 185, 129, 0.15); color: #34d399; border: 1px solid rgba(16, 185, 129, 0.3);
            margin-top: 8px;
        }
        .popup-badge.non-eu {
            background: rgba(251, 191, 36, 0.15); color: #fbbf24; border-color: rgba(251, 191, 36, 0.3);
        }
        .popup-badge.candidate {
            background: rgba(59, 130, 246, 0.15); color: #60a5fa; border-color: rgba(59, 130, 246, 0.3);
        }
        .popup-badge.partner {
            background: rgba(139, 92, 246, 0.15); color: #a78bfa; border-color: rgba(139, 92, 246, 0.3);
        }
        .popup-badge.popup-badge-eu {
            background: rgba(0, 51, 153, 0.2); color: #6699ff; border-color: rgba(0, 51, 153, 0.4);
            display: inline-flex; align-items: center;
            /* Devenu un <a> pour ouvrir la fiche de l'Union : on retire la
               decoration de lien, on garde le curseur qui annonce le clic. */
            text-decoration: none; cursor: pointer;
        }
        .popup-badge.popup-badge-eu:hover {
            background: rgba(0, 51, 153, 0.32); color: #8ab4ff;
        }
        .popup-badge.popup-badge-brexit {
            background: rgba(239, 68, 68, 0.15); color: #f87171; border-color: rgba(239, 68, 68, 0.3);
        }
        /* Alliance badges container */
        .popup-alliances {
            display: flex;
            gap: 6px;
            flex-wrap: wrap;
            margin-top: 10px;
            padding-top: 8px;
            border-top: 1px solid var(--border);
        }
        .popup-alliance-badge {
            display: inline-flex;
            align-items: center;
            gap: 5px;
            padding: 4px 10px;
            border-radius: 6px;
            font-size: 0.7rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
            text-decoration: none;
        }
        .popup-alliance-badge:hover {
            transform: translateY(-1px);
        }
        .popup-alliance-badge.eurozone {
            background: rgba(255, 215, 0, 0.15);
            color: #ffd700;
            border: 1px solid rgba(255, 215, 0, 0.3);
        }
        .popup-alliance-badge.eurozone:hover {
            background: rgba(255, 215, 0, 0.25);
        }
        .popup-alliance-badge.nato {
            background: rgba(0, 75, 135, 0.2);
            color: #60a5fa;
            border: 1px solid rgba(0, 75, 135, 0.4);
        }
        .popup-alliance-badge.nato:hover {
            background: rgba(0, 75, 135, 0.3);
        }
        /* Bleu Europe : la teinte du drapeau, celle qu'emploie deja le badge
           de statut juste au-dessus. */
        .popup-alliance-badge.eu {
            background: rgba(0, 51, 153, 0.2);
            color: #6699ff;
            border: 1px solid rgba(0, 51, 153, 0.4);
        }
        .popup-alliance-badge.eu:hover {
            background: rgba(0, 51, 153, 0.32);
        }
        /* Violet pour l'AELE : les trois autres groupes occupent deja le bleu
           (Union), le jaune (Eurozone) et le bleu sombre (OTAN). Une
           quatrieme teinte distincte evite qu'on lise deux badges voisins
           comme un seul. */
        .popup-alliance-badge.efta {
            background: rgba(168, 85, 247, 0.16);
            color: #c084fc;
            border: 1px solid rgba(168, 85, 247, 0.35);
        }
        .popup-alliance-badge.efta:hover {
            background: rgba(168, 85, 247, 0.28);
        }
        .popup-alliance-badge i {
            font-size: 0.85rem;
        }
        .popup-eu-flag {
            border-radius: 3px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        }
        .popup-note {
            font-size: 0.7rem;
            color: var(--text-muted);
            margin-top: 8px;
            padding-top: 8px;
            border-top: 1px solid var(--border);
            font-style: italic;
        }

        /* Responsive popup */
        @media (max-width: 768px) {
            .detail-popup {
                bottom: 0;
                left: 0;
                right: 0;
                width: 100%;
                max-width: 100%;
                border-radius: var(--radius) var(--radius) 0 0;
                max-height: 60vh;
            }
        }

        /* Map scroll lock - prevents page scroll when hovering map */
        /* Alliance Modal (Eurozone/NATO) */
        .alliance-modal-overlay {
            position: fixed;
            inset: 0;
            background: rgba(0,0,0,0.7);
            z-index: 2000;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s;
        }
        .alliance-modal-overlay.active {
            opacity: 1;
            visibility: visible;
        }
        .alliance-modal {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%) scale(0.9);
            width: 90%;
            max-width: 700px;
            max-height: 85vh;
            background: linear-gradient(180deg, #0f172a 0%, #1e293b 100%);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 16px;
            z-index: 2001;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }
        .alliance-modal.active {
            opacity: 1;
            visibility: visible;
            transform: translate(-50%, -50%) scale(1);
        }
        .alliance-modal-header {
            display: flex;
            align-items: center;
            gap: 16px;
            padding: 20px 24px;
            border-bottom: 1px solid rgba(255,255,255,0.08);
            flex-shrink: 0;
        }
        .alliance-modal-icon {
            width: 48px;
            height: 48px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.5rem;
        }
        .alliance-modal-icon.eurozone { background: rgba(59,130,246,0.2); color: #3b82f6; }
        .alliance-modal-icon.nato { background: rgba(16,185,129,0.2); color: #10b981; }
        .alliance-modal-icon.eu { background: rgba(0,51,153,0.22); color: #6699ff; }
        .alliance-modal-icon.efta { background: rgba(168,85,247,0.2); color: #c084fc; }
        .alliance-modal-title-group { flex: 1; }
        .alliance-modal-title-group h2 { color: #fff; font-size: 1.2rem; margin: 0 0 4px; }
        .alliance-modal-title-group p { color: #64748b; font-size: 0.85rem; margin: 0; }
        .alliance-modal-close {
            background: none;
            border: none;
            color: #64748b;
            font-size: 1.8rem;
            cursor: pointer;
            padding: 0;
            line-height: 1;
        }
        .alliance-modal-close:hover { color: #fff; }
        .alliance-modal-body {
            padding: 20px 24px;
            overflow-y: auto;
            flex: 1;
        }
        .alliance-section { margin-bottom: 24px; }
        .alliance-section:last-child { margin-bottom: 0; }
        .alliance-section-title {
            font-size: 0.75rem;
            font-weight: 600;
            color: #64748b;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .alliance-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
            gap: 10px;
        }
        .alliance-country {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 10px 12px;
            background: rgba(255,255,255,0.03);
            border: 1px solid rgba(255,255,255,0.06);
            border-radius: 8px;
            transition: all 0.2s;
        }
        .alliance-country:hover {
            background: rgba(255,255,255,0.06);
            border-color: rgba(255,255,255,0.1);
        }
        /* Meme gabarit que .alliance-rup-flag : les drapeaux des membres sont
           desormais des images, pas des emojis (Windows n'a pas de police de
           drapeaux et affichait « BE » a la place). Taille FIXE : sans elle,
           les proportions nationales — du 1:1 suisse au 1:2 des pays
           nordiques — donneraient une grille en dents de scie. */
        .alliance-country-flag {
            width: 26px;
            height: 18px;
            flex: 0 0 auto;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            border-radius: 3px;
            overflow: hidden;
            background: rgba(15, 23, 42, 0.45);
            font-size: 1.15rem;
            line-height: 1;
        }
        .alliance-country-flag img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            display: block;
        }
        .alliance-country-info { flex: 1; min-width: 0; }
        .alliance-country-name {
            font-size: 0.85rem;
            color: #fff;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .alliance-country-code {
            font-size: 0.7rem;
            color: #64748b;
        }
        .rup-badge {
            font-size: 0.6rem;
            background: rgba(139,92,246,0.2);
            color: #a78bfa;
            padding: 2px 6px;
            border-radius: 4px;
            margin-left: auto;
        }

        /* RUP (Overseas Territories) cards in alliance modal */
        .alliance-rup-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 12px;
        }
        .alliance-rup-card {
            background: rgba(139,92,246,0.08);
            border: 1px solid rgba(139,92,246,0.2);
            border-radius: 10px;
            padding: 12px;
            transition: all 0.2s;
        }
        .alliance-rup-card:hover {
            background: rgba(139,92,246,0.12);
            border-color: rgba(139,92,246,0.3);
        }
        .alliance-rup-header {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-bottom: 10px;
        }
        .alliance-rup-flag {
            width: 32px;
            height: 22px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            border-radius: 4px;
            overflow: hidden;
            background: rgba(15, 23, 42, 0.45);
        }
        .alliance-rup-flag img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            display: block;
        }
        .alliance-flag-emoji {
            font-size: 1.35rem;
            line-height: 1;
        }
        .alliance-rup-name {
            font-size: 0.95rem;
            font-weight: 600;
            color: #fff;
        }
        .alliance-rup-admin {
            background: rgba(0,0,0,0.2);
            border-radius: 6px;
            padding: 8px 10px;
        }
        .alliance-rup-admin-label {
            display: block;
            font-size: 0.65rem;
            color: #64748b;
            text-transform: uppercase;
            letter-spacing: 0.3px;
            margin-bottom: 4px;
        }
        .alliance-rup-admin-value {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 0.85rem;
            color: #cbd5e1;
            font-weight: 500;
        }
        .alliance-rup-parent-flag {
            font-size: 1rem;
        }
        .alliance-rup-note {
            margin-top: 8px;
            font-size: 0.7rem;
            color: #94a3b8;
            font-style: italic;
        }

/* ==========================================================================
   PARTIE 2 — PANNEAU LATERAL
   ========================================================================== */

    .sidebar-section {
        display: flex;
        flex-direction: column;
        height: 100%;
        width: 100%;
        max-height: 100%;
        min-height: 0;
        overflow: hidden;
        position: relative;
        background: var(--bg-deep);
    }

    .sidebar-header {
        padding: 8px 10px 6px;
        border-bottom: 1px solid var(--border);
        flex-shrink: 0;
    }

    .sidebar-title {
        font-size: 0.72rem;
        font-weight: 700;
        color: var(--text-white);
        margin-bottom: 1px;
        display: flex;
        align-items: center;
        gap: 5px;
    }

    .sidebar-title::before {
        content: '';
        width: 6px;
        height: 6px;
        background: var(--success);
        border-radius: 50%;
        animation: livePulse 2s infinite;
    }

    @keyframes livePulse {
        0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
        50% { opacity: 0.8; box-shadow: 0 0 0 4px rgba(16, 185, 129, 0); }
    }

    .sidebar-subtitle {
        font-size: 0.55rem;
        color: var(--text-muted);
        font-family: var(--font-mono);
    }

    .sidebar-tabs {
        padding: 6px 8px;
        border-bottom: 1px solid var(--border);
        display: flex;
        gap: 6px;
        flex-shrink: 0;
        background: rgba(0,0,0,0.08);
    }

    .sidebar-tab-btn {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
        padding: 7px 10px;
        border-radius: 10px;
        border: 1px solid var(--border);
        background: rgba(255,255,255,0.03);
        color: var(--text-muted);
        cursor: pointer;
        font-size: 0.6rem;
        font-weight: 800;
        letter-spacing: 1px;
        text-transform: uppercase;
        transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
    }

    .sidebar-tab-btn i {
        font-size: 0.85rem;
    }

    .sidebar-tab-btn:hover {
        color: var(--text-light);
        border-color: rgba(255,255,255,0.12);
        background: rgba(255,255,255,0.05);
    }

    .sidebar-tab-btn.active {
        color: var(--text-white);
        border-color: rgba(59, 130, 246, 0.35);
        background: rgba(59, 130, 246, 0.12);
    }

    .sidebar-panels {
        flex: 1;
        min-height: 0;
        overflow: hidden;
        position: relative;
        display: flex;
        flex-direction: column;
    }

    .sidebar-panel {
        display: none;
        flex: 1;
        min-height: 0;
        overflow: hidden;
        flex-direction: column;
    }

    .sidebar-panel.active {
        display: flex;
    }

    .sidebar-panel[data-tab="markets"] {
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    /* --- Markets UI overrides (compact rows + thin sparklines + modal) --- */
    .market-widget {
        margin: 8px 8px 10px;
    }
    .market-widget-header {
        padding: 10px 12px;
    }
    .market-widget-meta {
        padding: 8px 12px;
        gap: 8px;
        grid-template-columns: minmax(0, 1fr) !important;
        align-items: start;
    }
    .market-widget-body {
        padding: 8px 8px 10px;
    }
    .market-row {
        padding: 8px 10px;
        border-radius: 12px;
        cursor: pointer;
    }
    .market-row:focus {
        outline: 2px solid rgba(59,130,246,0.55);
        outline-offset: 2px;
    }
    .market-name .label {
        font-size: 0.78rem;
    }
    .market-name .symbol {
        font-size: 0.68rem;
    }
    .market-price {
        font-size: 0.92rem;
    }
    .market-change {
        font-size: 0.78rem;
    }
    .market-session {
        font-size: 0.78rem;
        color: rgba(148,163,184,0.95);
        font-weight: 800;
        white-space: normal;
        line-height: 1.35;
        overflow-wrap: anywhere;
    }
    .market-breadth {
        justify-self: start !important;
        white-space: normal !important;
        line-height: 1.35;
        overflow-wrap: anywhere;
        max-width: 100%;
    }
    .market-pill {
        max-width: 100%;
        width: fit-content;
    }
    .market-spark {
        height: 12px;
        width: 70px;
        opacity: 0.95;
    }

    /* Ensure HTML `hidden` works even though we set explicit display rules below. */
    .market-modal[hidden],
    .market-modal-overlay[hidden] {
        display: none !important;
    }

    .market-modal-overlay {
        position: fixed;
        inset: 0;
        background: rgba(0,0,0,0.55);
        backdrop-filter: blur(6px);
        z-index: 200000;
    }
    .market-modal {
        position: fixed;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        width: min(860px, calc(100vw - 24px));
        max-height: min(720px, calc(100vh - 24px));
        overflow: hidden;
        z-index: 200001;
        border-radius: 18px;
        border: 1px solid rgba(255,255,255,0.10);
        background: rgba(15, 23, 42, 0.92);
        box-shadow: 0 35px 80px rgba(0,0,0,0.55);
        display: grid;
        grid-template-rows: auto auto 1fr;
    }
    .market-modal-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 14px;
        padding: 14px 16px 10px;
        border-bottom: 1px solid rgba(255,255,255,0.08);
    }
    .market-modal-title { min-width: 0; }
    .market-modal-name {
        font-size: 1.05rem;
        font-weight: 900;
        letter-spacing: 0.02em;
        color: #fff;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 640px;
    }
    .market-modal-symbol {
        margin-top: 2px;
        font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
        font-size: 0.8rem;
        color: rgba(148,163,184,0.95);
    }
    .market-modal-close {
        width: 38px;
        height: 38px;
        border-radius: 12px;
        border: 1px solid rgba(255,255,255,0.10);
        background: rgba(255,255,255,0.04);
        color: #e2e8f0;
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        transition: 0.15s;
        flex-shrink: 0;
    }
    .market-modal-close:hover {
        background: rgba(255,255,255,0.07);
        color: #fff;
    }
    .market-modal-controls {
        padding: 10px 16px 12px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 10px;
        flex-wrap: wrap;
    }
    .market-modal-tabs {
        padding: 8px 10px;
        border-bottom: 1px solid rgba(255,255,255,0.08);
        display: flex;
        gap: 8px;
        align-items: center;
        flex-wrap: wrap;
    }
    .market-tab {
        border: 1px solid rgba(255,255,255,0.10);
        background: rgba(255,255,255,0.03);
        color: rgba(226,232,240,0.92);
        border-radius: 999px;
        padding: 7px 10px;
        font-size: 0.78rem;
        font-weight: 900;
        letter-spacing: 0.02em;
        cursor: pointer;
        transition: 0.15s;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        user-select: none;
    }
    .market-tab:hover { background: rgba(255,255,255,0.06); color: #fff; }
    .market-tab.active {
        border-color: rgba(59,130,246,0.55);
        background: rgba(59,130,246,0.16);
        color: #fff;
    }
	    .market-modal-body {
	        overflow: auto;
	        -webkit-overflow-scrolling: touch;
	        min-height: 0;
	    }
	    .market-modal-panel {
	        display: grid;
	        gap: 0;
	        min-height: 0;
	    }
	    .market-modal-panel[hidden] { display: none !important; }
    .market-modal-meta {
        padding: 10px 16px 12px;
        border-bottom: 1px solid rgba(255,255,255,0.08);
        display: grid;
        gap: 10px;
    }
    .market-meta-desc {
        color: rgba(226,232,240,0.92);
        font-size: 0.86rem;
        line-height: 1.35;
        font-weight: 650;
    }
    .market-meta-grid {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        gap: 10px;
    }
    .market-meta-item {
        border: 1px solid rgba(255,255,255,0.08);
        background: rgba(255,255,255,0.03);
        border-radius: 14px;
        padding: 10px 12px;
        min-width: 0;
    }
    .market-meta-item .k {
        font-size: 0.7rem;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: rgba(148,163,184,0.95);
        font-weight: 900;
    }
    .market-meta-item .v {
        margin-top: 4px;
        font-size: 0.9rem;
        font-weight: 850;
        color: #fff;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .market-meta-constituents {
        border: 1px solid rgba(255,255,255,0.08);
        background: rgba(255,255,255,0.02);
        border-radius: 14px;
        padding: 10px 12px;
    }
    .market-meta-title {
        font-size: 0.78rem;
        font-weight: 900;
        letter-spacing: 0.02em;
        color: rgba(226,232,240,0.92);
    }
    .market-meta-note {
        margin-top: 4px;
        font-size: 0.75rem;
        color: rgba(148,163,184,0.95);
        font-weight: 700;
    }
    .market-meta-list {
        margin: 8px 0 0;
        padding-left: 20px;
        color: rgba(226,232,240,0.92);
        font-size: 0.82rem;
        line-height: 1.35;
    }
    .market-meta-links {
        margin-top: 8px;
        display: flex;
        gap: 10px;
        flex-wrap: wrap;
    }
    .market-meta-links a {
        color: rgba(96,165,250,0.95);
        font-weight: 800;
        font-size: 0.78rem;
        text-decoration: none;
        border: 1px solid rgba(96,165,250,0.28);
        background: rgba(96,165,250,0.08);
        padding: 6px 10px;
        border-radius: 999px;
    }
	    .market-meta-links a:hover { background: rgba(96,165,250,0.14); color: #fff; }

	    .market-meta-embed {
	        padding: 10px 16px 14px;
	        display: grid;
	        gap: 8px;
	    }
	    .market-embed-frame {
	        border: 1px solid rgba(255,255,255,0.10);
	        background: rgba(255,255,255,0.02);
	        border-radius: 14px;
	        overflow: hidden;
	    }
	    .market-embed-frame iframe {
	        display: block;
	        width: 100%;
	        height: min(560px, 62vh);
	        border: 0;
	        background: rgba(0,0,0,0.12);
	    }
    .market-modal-group {
        display: inline-flex;
        gap: 8px;
        flex-wrap: wrap;
    }
    .market-chip {
        border: 1px solid rgba(255,255,255,0.10);
        background: rgba(255,255,255,0.04);
        color: rgba(226,232,240,0.92);
        border-radius: 999px;
        padding: 7px 10px;
        font-size: 0.78rem;
        font-weight: 800;
        letter-spacing: 0.02em;
        cursor: pointer;
        transition: 0.15s;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        user-select: none;
    }
    .market-chip-static {
        cursor: default;
        pointer-events: none;
        opacity: 0.95;
    }
    .market-chip:hover { background: rgba(255,255,255,0.07); color: #fff; }
    .market-chip.active {
        border-color: rgba(59,130,246,0.55);
        background: rgba(59,130,246,0.16);
        color: #fff;
    }
    .market-chip-style { margin-left: auto; }
    .market-modal-chart {
        padding: 12px 12px 10px;
        position: relative;
        min-height: 260px;
        display: grid;
        place-items: center;
        background: radial-gradient(1200px 500px at 20% 0%, rgba(59,130,246,0.12), transparent 60%),
                    radial-gradient(800px 420px at 80% 20%, rgba(16,185,129,0.10), transparent 65%);
    }
    .market-modal-chart svg { width: 100%; height: 100%; }
    .market-tooltip {
        position: absolute;
        z-index: 2;
        padding: 10px 12px;
        border-radius: 14px;
        border: 1px solid rgba(255,255,255,0.10);
        background: rgba(2, 6, 23, 0.88);
        box-shadow: 0 18px 50px rgba(0,0,0,0.55);
        backdrop-filter: blur(10px);
        pointer-events: none;
        min-width: 160px;
        text-align: left;
    }
    .market-tooltip-fixed {
        position: fixed;
        z-index: 200010; /* above modal (200001) */
    }
    .market-tooltip .t-date {
        font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
        font-size: 0.76rem;
        color: rgba(148,163,184,0.95);
        font-weight: 800;
        letter-spacing: 0.02em;
    }
    .market-tooltip .t-val {
        margin-top: 4px;
        font-size: 1.05rem;
        font-weight: 900;
        color: rgba(255,255,255,0.98);
    }
    .market-tooltip .t-pct {
        margin-top: 2px;
        font-size: 0.78rem;
        font-weight: 800;
        color: rgba(226,232,240,0.92);
    }
    .market-modal-loading {
        font-size: 0.9rem;
        color: rgba(148,163,184,0.95);
        font-weight: 700;
    }
    .market-modal-detail {
        padding: 10px 16px 14px;
        border-top: 1px solid rgba(255,255,255,0.08);
        display: grid;
        grid-template-columns: 1.6fr 1fr 1fr 1fr 1fr;
        gap: 10px;
    }
    .market-modal-kv {
        border: 1px solid rgba(255,255,255,0.08);
        background: rgba(255,255,255,0.03);
        border-radius: 14px;
        padding: 10px 12px;
        min-width: 0;
    }
    .market-k {
        font-size: 0.7rem;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: rgba(148,163,184,0.95);
        font-weight: 900;
    }
    .market-v {
        margin-top: 4px;
        font-size: 0.95rem;
        font-weight: 900;
        color: #fff;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    @media (max-width: 780px) {
        .market-modal { grid-template-rows: auto auto 1fr; }
        .market-modal-detail { grid-template-columns: 1fr 1fr; }
        .market-chip-style { width: 100%; justify-content: center; }
        .market-meta-grid { grid-template-columns: 1fr; }
    }

    .sidebar-search {
        padding: 5px 8px;
        flex-shrink: 0;
        border-bottom: 1px solid var(--border);
    }

    .search-input-wrap {
        position: relative;
    }

    .search-input {
        width: 100%;
        padding: 6px 9px 6px 28px;
        background: var(--bg-card);
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        color: var(--text-white);
        font-size: 0.68rem;
        outline: none;
        transition: all 0.2s;
    }

    .search-input::placeholder { color: var(--text-dim); }
    .search-input:focus { border-color: var(--accent); }

    .search-icon {
        position: absolute;
        left: 8px;
        top: 50%;
        transform: translateY(-50%);
        color: var(--text-dim);
        font-size: 0.75rem;
    }

    #active-country-filter {
        margin-top: 6px;
        padding: 5px 8px;
        background: rgba(59, 130, 246, 0.1);
        border: 1px solid rgba(59, 130, 246, 0.25);
        border-radius: 6px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        font-size: 0.64rem;
        color: var(--text-light);
    }

    #clear-country-filter {
        background: none;
        border: none;
        color: var(--text-muted);
        cursor: pointer;
        padding: 4px;
        display: flex;
        align-items: center;
        transition: color 0.2s;
    }

    #clear-country-filter:hover { color: #fff; }

    .feed-section-header {
        padding: 5px 8px;
        border-bottom: 1px solid var(--border);
        background: var(--bg-deep);
        flex-shrink: 0;
        display: flex;
        align-items: center;
        justify-content: space-between;
    }

    .event-feed {
        flex: 1;
        overflow-y: auto;
        overscroll-behavior: contain;
        min-height: 0;
        padding: 6px 8px 8px;
        scrollbar-width: thin;
        scrollbar-color: rgba(255,255,255,0.15) transparent;
    }

    /* ======================================================================
       LE FIL S'ELARGIT EN COLONNES, PAS EN CARTES GEANTES

       Le panneau est redimensionnable (poignee de separation cote bureau,
       crans de la feuille cote mobile). Chaque carte occupait toute la
       largeur : a 700 px, une depeche de deux lignes s'etalait sur un pave de
       700 px de large et 90 px de haut, avec un titre perdu au milieu d'un
       vide. Plus on agrandissait le panneau, MOINS on voyait d'evenements —
       exactement l'inverse de ce qu'on demande en l'agrandissant.

       La grille corrige cela : au-dela de 620 px, le fil se decoupe en
       colonnes de 300 px au minimum. Elargir ajoute des colonnes, donc des
       evenements visibles.

       REQUETE DE CONTENEUR, ET NON MEDIA QUERY : c'est la largeur du PANNEAU
       qui compte, pas celle de l'ecran. Un panneau etroit sur un grand ecran
       doit rester en colonne unique, et une feuille plein ecran sur tablette
       doit passer en deux colonnes. Une media query ne sait dire ni l'un ni
       l'autre.

       Sans prise en charge des requetes de conteneur, rien ne s'applique : on
       retombe sur la colonne unique d'avant, qui reste correcte. */
    .sidebar-panel[data-tab="events"] {
        container-type: inline-size;
        container-name: lmfeed;
    }

    /* ---- PALIERS DE COLONNES -------------------------------------------

       Nombre de colonnes FIXE par palier, et non `auto-fill` avec une largeur
       minimale. `auto-fill` remplit l'espace des qu'il le peut : a 900 px il
       posait deja quatre colonnes de 277 px, et la carte retrecissait a chaque
       elargissement. Un palier explicite fait l'inverse — la carte garde une
       largeur confortable, et c'est le nombre d'evenements lisibles qui
       augmente.

       Les seuils sont choisis pour que la carte reste entre ~300 et ~520 px a
       tous les crans : 680 pour deux colonnes, 1080 pour trois, 1520 pour
       quatre. */
    @container lmfeed (min-width: 680px) {
        .event-feed {
            display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: 8px;
            align-content: start;

            /* ⚠️ INDISPENSABLE — SANS CETTE LIGNE LES CARTES S'EFFONDRENT.

               `.event-card` porte `overflow: hidden` (pour que les coins
               arrondis rognent la barre de couleur). En CSS Grid, un element
               dont l'overflow n'est pas `visible` est un conteneur de
               defilement, et sa taille minimale automatique vaut alors ZERO au
               lieu d'etre deduite du contenu. La rangee se calait donc sur
               15 px, la carte s'etirait a cette hauteur, et ses 146 px de
               contenu etaient rognes : a l'ecran, une barre vide de 2 px.

               Mesure avant / apres : 2 px -> 148 px de hauteur de carte.

               `min-content` sur les rangees redonne la hauteur du contenu, et
               conserve l'egalite des cartes d'une meme rangee — ce que ne fait
               pas `align-items: start`, qui donne des bas de cartes en dents
               de scie. */
            grid-auto-rows: min-content;
        }
        /* La marge basse servait d'espacement en pile ; c'est `gap` qui s'en
           charge en grille, sinon les rangees prennent le double. */
        .event-feed .event-card { margin-bottom: 0; }
    }

    @container lmfeed (min-width: 1080px) {
        .event-feed { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    }

    @container lmfeed (min-width: 1520px) {
        .event-feed { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    }

    /* ---- MOBILE, FEUILLE OUVERTE EN GRAND ------------------------------
       Une colonne de 380 px ne se decoupe pas. Ce qu'on peut gagner, c'est de
       la DENSITE : quand la feuille est tiree au maximum, l'utilisateur veut
       lire le flux, pas admirer les marges.

       ⚠️ La cible est `.event-content`, PAS `.event-card`. La carte a
       `padding: 0` — tout son rembourrage vit sur son enfant. Les regles de
       densite existantes (`[data-density]`, plus bas) visent la carte et sont
       donc sans effet depuis toujours ; elles sont corrigees de la meme
       facon. */
    #lm-sheet[data-snap='full'] .event-content { padding: 6px 9px 6px 11px; }
    #lm-sheet[data-snap='full'] .event-card { margin-bottom: 4px; }
    #lm-sheet[data-snap='full'] .event-description {
        font-size: 0.78rem;
        line-height: 1.4;
    }

    /* ====================================================================
       CARTE ENRICHIE — CE QUI N'ETAIT AFFICHE NULLE PART

       Extrait de description, bilan humain, region, position approchee et
       sources nommees existent en base depuis le debut. La carte etroite n'a
       pas la place de les porter : le bloc est donc emis en permanence dans
       le DOM et REVELE par la largeur reelle du panneau.

       Le declencheur est une requete de CONTENEUR, et non les attributs
       `data-split` / `data-snap` : c'est la largeur du fil qui decide s'il y
       a la place, pas l'etat nominal d'un panneau. Un panneau « etendu » sur
       un ecran de 1 100 px n'est pas plus large qu'un panneau normal sur un
       ecran de 1 900 px.
       ==================================================================== */
    .event-extra { display: none; }

    @container lmfeed (min-width: 680px) {
        .event-extra {
            display: flex;
            flex-direction: column;
            gap: 6px;
            margin: 6px 0 2px;
        }
    }
    /* Telephone, feuille tiree au maximum : meme contenu, meme raison. */
    #lm-sheet[data-snap='full'] .event-extra {
        display: flex;
        flex-direction: column;
        gap: 6px;
        margin: 6px 0 2px;
    }

    .event-excerpt {
        margin: 0;
        font-size: 0.72rem;
        line-height: 1.45;
        color: var(--text-muted, #94a3b8);
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    .event-facts {
        display: flex;
        flex-wrap: wrap;
        gap: 5px;
    }
    .event-fact {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 7px;
        border-radius: 999px;
        border: 1px solid transparent;
        font-size: 0.6rem;
        font-weight: 600;
        white-space: nowrap;
    }
    .event-fact i { font-size: 0.72rem; }
    .event-fact.is-toll {
        background: rgba(239, 68, 68, 0.15);
        border-color: rgba(239, 68, 68, 0.35);
        color: #f87171;
    }
    .event-fact.is-region {
        background: rgba(148, 163, 184, 0.1);
        border-color: rgba(148, 163, 184, 0.22);
        color: var(--text-muted, #94a3b8);
        font-weight: 500;
    }
    /* Pointille = estimation, meme convention que le perimetre potentiellement
       brule sur la carte et que la fiche d'evenement. */
    .event-fact.is-approx {
        border-style: dashed;
        border-color: rgba(148, 163, 184, 0.5);
        color: var(--text-muted, #94a3b8);
        font-weight: 500;
        cursor: help;
    }

    /* Les sources, NOMMEES. Le « +3 » de la ligne du bas devient redondant
       des lors que la liste complete est la : on le retire pour ne pas
       compter deux fois la meme chose. */
    .event-sources {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 5px;
    }
    .event-sources-label {
        flex: 1 0 100%;
        font-size: 0.55rem;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--text-dim, #475569);
    }
    .event-source-chip {
        padding: 2px 8px;
        border: 1px solid rgba(59, 130, 246, 0.25);
        border-radius: 999px;
        background: rgba(59, 130, 246, 0.1);
        font-size: 0.6rem;
        color: var(--accent, #3b82f6);
        text-decoration: none;
        transition: background 0.15s ease, color 0.15s ease;
    }
    .event-source-chip:hover {
        background: rgba(59, 130, 246, 0.22);
        color: #fff;
    }

    @container lmfeed (min-width: 680px) {
        .event-source-more { display: none; }
    }
    #lm-sheet[data-snap='full'] .event-source-more { display: none; }

    .event-feed::-webkit-scrollbar { width: 4px; }
    .event-feed::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 4px; }
    .event-feed::-webkit-scrollbar-track { background: transparent; }

    .feed-section-title {
        padding: 0;
        font-size: 0.54rem;
        font-weight: 600;
        color: var(--text-muted);
        text-transform: uppercase;
        letter-spacing: 1px;
    }

    .auto-refresh-indicator {
        display: flex;
        align-items: center;
        gap: 4px;
        font-size: 0.52rem;
        color: var(--text-dim);
        padding: 2px 6px;
        border-radius: 4px;
        background: rgba(255,255,255,0.03);
        transition: all 0.3s;
    }

    .auto-refresh-indicator i {
        font-size: 0.6rem;
        transition: transform 0.3s;
    }

    .auto-refresh-indicator.refreshing {
        color: var(--accent);
        background: rgba(59, 130, 246, 0.1);
    }

    .auto-refresh-indicator.refreshing i {
        animation: spin 1s linear infinite;
    }

    .auto-refresh-indicator.success {
        color: var(--success);
        background: rgba(16, 185, 129, 0.1);
    }

    .auto-refresh-indicator.error {
        color: var(--danger);
        background: rgba(239, 68, 68, 0.1);
    }

    @keyframes spin {
        from { transform: rotate(0deg); }
        to { transform: rotate(360deg); }
    }

    /* ==========================================================================
       EVENT CARD - Situation.watch Style
       ========================================================================== */
    .event-card {
        background: var(--bg-card);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        padding: 0;
        margin-bottom: 5px;
        cursor: pointer;
        transition: all 0.2s ease;
        position: relative;
        overflow: hidden;
    }

    .event-card::before {
        content: '';
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        width: 3px;
        background: var(--event-color, var(--accent));
    }

    .event-card:hover {
        background: var(--bg-card-hover);
        border-color: var(--border-light);
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
    }

    /* New event flash animation */
    .event-card.new-event-flash {
        animation: newEventFlash 2s ease-out;
    }
    @keyframes newEventFlash {
        0% {
            background: rgba(59, 130, 246, 0.3);
            border-color: var(--accent);
            box-shadow: 0 0 20px rgba(59, 130, 246, 0.4);
            transform: scale(1.02);
        }
        50% {
            background: rgba(59, 130, 246, 0.15);
            box-shadow: 0 0 10px rgba(59, 130, 246, 0.2);
        }
        100% {
            background: var(--bg-card);
            border-color: var(--border);
            box-shadow: none;
            transform: scale(1);
        }
    }

    .event-card.highlight {
        border-color: var(--accent);
        box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25);
        background: var(--bg-card-hover);
    }

    /* Card Content */
    .event-content {
        padding: 8px 10px 8px 12px;
    }

    /* Category Label (top) */
    .event-category-label {
        font-size: 0.55rem;
        font-weight: 600;
        color: var(--event-color, var(--text-muted));
        text-transform: uppercase;
        letter-spacing: 0.5px;
        margin-bottom: 4px;
        display: flex;
        align-items: center;
        gap: 5px;
    }

    .event-category-label svg,
    .event-category-label img {
        width: 14px;
        height: 14px;
        display: block;
    }

    /* Tags Row */
    .event-tags {
        display: flex;
        flex-wrap: wrap;
        gap: 4px;
        margin-bottom: 5px;
    }

    .event-tag {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 6px;
        border-radius: 4px;
        font-size: 0.5rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.3px;
    }

    .event-tag.category {
        background: var(--event-color, var(--accent));
        color: #fff;
    }

    .event-tag.severity {
        background: var(--severity-bg, rgba(255,255,255,0.1));
        color: var(--severity-color, #fff);
        border: 1px solid var(--severity-color, var(--border));
    }

    .event-tag.location {
        background: rgba(255, 255, 255, 0.05);
        color: var(--text-light);
        border: 1px solid var(--border);
    }

    /* Description/Title */
    .event-description {
        font-size: 0.74rem;
        font-weight: 500;
        color: var(--text-white);
        line-height: 1.45;
        margin-bottom: 5px;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    /* Date/Time + Source Row */
    .event-meta {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-bottom: 6px;
    }

    .event-datetime {
        font-size: 0.6rem;
        color: var(--text-muted);
        font-family: var(--font-mono);
        display: flex;
        align-items: center;
        gap: 6px;
    }

    .event-datetime i {
        font-size: 0.8rem;
        opacity: 0.7;
    }

    .event-source-inline {
        margin-left: auto;
        font-size: 0.55rem;
        font-weight: 600;
        color: var(--text-light);
        text-decoration: none;
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 6px;
        border-radius: 6px;
        background: rgba(255, 255, 255, 0.04);
        border: 1px solid rgba(255, 255, 255, 0.08);
        max-width: 48%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .event-source-inline:hover {
        color: #fff;
        border-color: rgba(59, 130, 246, 0.4);
        background: rgba(59, 130, 246, 0.12);
    }

    .event-source-more {
        font-size: 0.55rem;
        color: var(--text-dim);
    }

    /* Sources Row */
    .event-sources {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        margin-bottom: 6px;
    }

    .source-link {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 7px;
        background: rgba(59, 130, 246, 0.1);
        border: 1px solid rgba(59, 130, 246, 0.2);
        border-radius: 4px;
        font-size: 0.55rem;
        font-weight: 500;
        color: var(--accent);
        text-decoration: none;
        transition: all 0.2s;
    }

    .source-link:hover {
        background: rgba(59, 130, 246, 0.2);
        border-color: var(--accent);
        color: #fff;
    }

    .source-link i {
        font-size: 0.7rem;
    }

    /* Dividers */
    .event-divider {
        height: 1px;
        background: var(--border);
        margin: 6px 0;
    }

    /* Coordinates */
    .event-coords {
        font-size: 0.55rem;
        font-family: var(--font-mono);
        color: var(--text-dim);
        display: flex;
        align-items: center;
        gap: 6px;
    }

    .event-coords i {
        font-size: 0.8rem;
        color: var(--text-muted);
    }

    .event-coords .coord-value {
        color: var(--text-muted);
    }

    /* Verified Badge */
    .verified-badge {
        display: inline-flex;
        align-items: center;
        gap: 3px;
        font-size: 0.6rem;
        color: var(--success);
        margin-left: auto;
    }

    .scroll-top-btn {
        position: absolute;
        right: 14px;
        bottom: 70px;
        width: 34px;
        height: 34px;
        border-radius: 50%;
        border: 1px solid rgba(255, 255, 255, 0.1);
        background: rgba(15, 23, 42, 0.9);
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        opacity: 0;
        pointer-events: none;
        transform: translateY(6px);
        transition: opacity 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
        z-index: 20;
    }

    .scroll-top-btn.visible {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0);
    }

    .scroll-top-btn:hover {
        border-color: rgba(59, 130, 246, 0.5);
        color: var(--accent);
    }

    /* Stats Footer */
    .stats-footer {
        padding: 6px 8px;
        background: var(--bg-panel);
        border-top: 1px solid var(--border);
        flex-shrink: 0;
    }

    .stats-grid {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 5px;
    }

    .stat-card {
        background: var(--bg-card);
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        padding: 5px;
        text-align: center;
    }

    .stat-value {
        font-family: var(--font-mono);
        font-size: 0.88rem;
        font-weight: 700;
        color: var(--text-white);
    }

    .stat-label {
        font-size: 0.5rem;
        color: var(--text-muted);
        text-transform: uppercase;
        letter-spacing: 0.5px;
        margin-top: 2px;
    }

    /* Empty State */
    .empty-state {
        text-align: center;
        padding: 40px 20px;
        color: var(--text-muted);
    }

    .empty-state i {
        font-size: 3rem;
        opacity: 0.3;
        display: block;
        margin-bottom: 16px;
    }

    @media (max-width: 1024px) {
        .sidebar-header { padding: 8px 10px 6px; }
        .sidebar-search { padding: 5px 8px; }
        .search-input { padding: 6px 9px 6px 28px; font-size: 0.66rem; }
        .search-icon { left: 8px; font-size: 0.75rem; }
        #active-country-filter { margin-top: 6px; padding: 5px 8px; font-size: 0.62rem; }
        .feed-section-header { padding: 5px 8px; }
        .event-feed { padding: 6px 8px 8px; }
        .stats-footer { padding: 6px 8px; }
        .stat-value { font-size: 0.85rem; }
    }

    @media (max-width: 768px) {
        .sidebar-header { padding: 7px 8px 6px; }
        .sidebar-subtitle { display: none; }
        .sidebar-tabs { padding: 6px 7px; }
        .sidebar-tab-btn { padding: 7px 8px; font-size: 0.58rem; }
        .sidebar-search { padding: 5px 7px; }
        .search-input { padding: 6px 8px 6px 26px; font-size: 0.64rem; }
        .search-icon { left: 7px; font-size: 0.72rem; }
        .feed-section-header { padding: 5px 7px; }
        .event-feed { padding: 6px 7px 8px; }
        .stats-grid { gap: 4px; }
        .stat-card { padding: 4px; }
        .stat-value { font-size: 0.82rem; }
        .stat-label { font-size: 0.46rem; }
    }

/* ==========================================================================
   PARTIE 3 — AJOUTS PHASE 2
   ========================================================================== */

/* Puce de langue d'origine : affichee quand un evenement n'a pas de
   traduction anglaise et retombe sur le titre de la source. Discrete, elle
   explique pourquoi le titre n'est pas dans la langue de l'interface. */
.event-lang-chip {
    display: inline-block;
    vertical-align: middle;
    margin-right: 6px;
    padding: 1px 5px;
    border: 1px solid var(--border-light, rgba(255, 255, 255, 0.1));
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.04);
    color: var(--text-muted, #64748b);
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    line-height: 1.5;
    cursor: help;
}

/* ==========================================================================
   COUCHE INCENDIES — foyers NASA FIRMS + surfaces brulees Copernicus EFFIS
   ========================================================================== */

/* Le bouton emprunte la teinte du feu plutot que l'accent bleu : la couche
   est thematique, pas structurelle. */
.filter-toggle-fires {
    font: inherit;
    cursor: pointer;
}
.filter-toggle-fires.active {
    background: rgba(249, 115, 22, 0.14);
    border-color: rgba(249, 115, 22, 0.5);
    color: #fdba74;
}
.filter-toggle-fires.active i {
    color: #fb923c;
}

/* --- Popup d'un foyer --------------------------------------------------- */
.fire-popup-shell .maplibregl-popup-content {
    background: var(--bg-panel, #0d1525);
    border: 1px solid var(--border-light, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-sm, 8px);
    padding: 14px 16px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
}
.fire-popup-shell .maplibregl-popup-tip { border-top-color: var(--bg-panel, #0d1525); }
.fire-popup-shell .maplibregl-popup-close-button {
    color: var(--text-muted, #64748b);
    font-size: 1.1rem;
    padding: 2px 7px;
}
.fire-popup-shell .maplibregl-popup-close-button:hover {
    background: transparent;
    color: var(--text-white, #f1f5f9);
}

/* --- Popup d'une region sous vigilance ---------------------------------
   Meme coque que le popup de foyer : ces deux fiches sont du meme ordre
   (une couche de donnees qu'on interroge), et rien ne justifierait deux
   habillages differents. */
.weather-popup-shell .maplibregl-popup-content {
    background: var(--bg-panel, #0d1525);
    border: 1px solid var(--border-light, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-sm, 8px);
    padding: 14px 16px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
}
.weather-popup-shell .maplibregl-popup-tip { border-top-color: var(--bg-panel, #0d1525); }
.weather-popup-shell .maplibregl-popup-close-button {
    color: var(--text-muted, #64748b);
    font-size: 1.1rem;
    padding: 2px 7px;
}
.weather-popup-shell .maplibregl-popup-close-button:hover {
    background: transparent;
    color: var(--text-white, #f1f5f9);
}
.weather-popup-head {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 4px;
}
.weather-popup-dot {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    flex: 0 0 auto;
}
.weather-popup-level {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-light, #cbd5e1);
}
.weather-popup-region {
    margin-bottom: 9px;
    color: var(--text-white, #f1f5f9);
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1.25;
}
.weather-popup-hazards {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-bottom: 9px;
}
.weather-popup-hazard {
    padding: 2px 7px;
    border: 1px solid var(--border, rgba(255, 255, 255, 0.12));
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.04);
    color: var(--text-light, #cbd5e1);
    font-size: 0.68rem;
}
.weather-popup-sources {
    margin: 0 0 9px;
    padding-left: 15px;
    color: var(--text-light, #cbd5e1);
    font-size: 0.72rem;
    line-height: 1.45;
}
.weather-popup-sources a { color: inherit; text-decoration: underline; }
.weather-popup-sources a:hover { color: var(--text-white, #f1f5f9); }
.weather-popup-src {
    color: var(--text-muted, #64748b);
    font-size: 0.62rem;
    font-style: italic;
}

/* --- Popup d'un point de passage --------------------------------------
   Reprend la coque des vigilances : meme nature d'objet (une couche de
   donnees qu'on interroge), donc meme habillage. */
.migr-popup-head { display: flex; align-items: center; gap: 7px; margin-bottom: 4px; }
.migr-popup-dot  { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.migr-popup-level {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-light, #cbd5e1);
}
.migr-popup-name {
    margin-bottom: 3px;
    color: var(--text-white, #f1f5f9);
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.25;
}
.migr-popup-route {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-bottom: 9px;
    color: var(--text-muted, #64748b);
    font-size: 0.72rem;
}
.migr-popup-sources {
    margin: 0 0 9px;
    padding-left: 15px;
    color: var(--text-light, #cbd5e1);
    font-size: 0.72rem;
    line-height: 1.45;
}
.migr-popup-sources a { color: inherit; text-decoration: underline; }
.migr-popup-sources a:hover { color: var(--text-white, #f1f5f9); }
.migr-popup-empty {
    margin: 0 0 9px;
    color: var(--text-muted, #64748b);
    font-size: 0.72rem;
}
.migr-popup-src {
    color: var(--text-muted, #64748b);
    font-size: 0.6rem;
    font-style: italic;
    line-height: 1.35;
}

/* Pastilles de la legende des vigilances : des aplats, pas des points —
   la couche dessine des surfaces. */
.map-legend .legend-item .legend-dot.dot-warn-yellow,
.map-legend .legend-item .legend-dot.dot-warn-orange,
.map-legend .legend-item .legend-dot.dot-warn-red {
    width: 12px;
    height: 9px;
    border-radius: 3px;
}
.map-legend .legend-item .legend-dot.dot-warn-yellow { background: rgba(234, 179, 8, .55);  border: 1px solid #ca8a04; }
.map-legend .legend-item .legend-dot.dot-warn-orange { background: rgba(249, 115, 22, .55); border: 1px solid #c2410c; }
.map-legend .legend-item .legend-dot.dot-warn-red    { background: rgba(220, 38, 38, .55);  border: 1px solid #991b1b; }

/* Passages migratoires : des points, comme sur la carte — et non des aplats
   comme pour les vigilances. La forme de la pastille de legende doit dire de
   quel TYPE d'objet il s'agit. */
.map-legend .legend-item .legend-dot.dot-migr-0,
.map-legend .legend-item .legend-dot.dot-migr-1,
.map-legend .legend-item .legend-dot.dot-migr-2,
.map-legend .legend-item .legend-dot.dot-migr-3 {
    width: 10px;
    height: 10px;
    border-radius: 50%;
}
.map-legend .legend-item .legend-dot.dot-migr-0 { background: #64748b; opacity: .5; }
.map-legend .legend-item .legend-dot.dot-migr-1 { background: #eab308; }
.map-legend .legend-item .legend-dot.dot-migr-2 { background: #f97316; }
.map-legend .legend-item .legend-dot.dot-migr-3 { background: #e11d48; }

/* Mise en garde de legende. Elle n'est pas decorative : sans elle, « afflux
   majeur » se lit comme un chiffre d'arrivees alors que c'est un comptage
   d'articles. */
.map-legend .legend-caveat {
    margin: 6px 0 0;
    color: var(--text-muted, #64748b);
    font-size: 0.62rem;
    font-style: italic;
    line-height: 1.35;
}

/* --- Fiche d'une zone brulee (clic droit) -----------------------------
   Meme coque que la fiche d'un foyer. La pastille de tete dit d'un coup
   d'oeil de quelle des deux natures il s'agit : perimetre releve ou emprise
   estimee. C'est l'information la plus importante de la fiche, elle vient
   donc en premier et sous forme graphique. */
.burnt-popup-swatch {
    width: 12px;
    height: 9px;
    border-radius: 2px;
    flex: 0 0 auto;
    background: rgba(110, 54, 38, .9);
    border: 1px solid #c64624;
}
.burnt-popup-swatch.is-potential {
    background: rgba(169, 120, 79, .5);
    border: 1px dashed #c99b6f;
}
.burnt-popup-place {
    margin: -4px 0 8px;
    color: var(--text-white, #f1f5f9);
    font-size: 0.86rem;
    font-weight: 600;
    line-height: 1.25;
}
.burnt-popup-rows {
    margin: 0 0 9px;
    padding: 0;
    list-style: none;
    color: var(--text-light, #cbd5e1);
    font-size: 0.74rem;
    line-height: 1.55;
}
.burnt-popup-rows li + li { border-top: 1px solid rgba(255, 255, 255, 0.05); }
.burnt-popup-rows strong { color: #fdba74; font-weight: 600; }
.burnt-popup-empty {
    margin: 0 0 9px;
    color: var(--text-muted, #64748b);
    font-size: 0.74rem;
}
.burnt-popup.is-potential .fire-popup-title { color: #d9b48c; }

.fire-popup-title {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 10px;
    color: #fdba74;
    font-size: 0.82rem;
    font-weight: 700;
}
.fire-popup-title::before {
    content: '';
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #f97316;
    box-shadow: 0 0 8px rgba(249, 115, 22, 0.8);
}

.fire-popup-rows { margin: 0; }
.fire-popup-rows > div {
    display: flex;
    justify-content: space-between;
    gap: 14px;
    padding: 3px 0;
}
.fire-popup-rows dt {
    color: var(--text-muted, #64748b);
    font-size: 0.72rem;
}
.fire-popup-rows dd {
    margin: 0;
    color: var(--text-light, #cbd5e1);
    font-size: 0.75rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* L'avertissement compte autant que la donnee : une anomalie thermique
   n'est pas forcement un incendie de foret. */
.fire-popup-note {
    margin: 10px 0 0;
    padding-top: 9px;
    border-top: 1px solid var(--border, rgba(255, 255, 255, 0.06));
    color: var(--text-muted, #64748b);
    font-size: 0.69rem;
    line-height: 1.45;
}
.fire-popup-credit {
    margin: 7px 0 0;
    color: var(--text-dim, #475569);
    font-size: 0.62rem;
    letter-spacing: 0.04em;
}

/* La poignee du bottom sheet n'existe que sous 1024px : au-dessus, le panneau
   est une colonne fixe et la poignee n'aurait aucune fonction.
   Requete `min-width` volontairement exclusive de celle du sheet : deux
   regles de meme specificite se departagent par l'ordre du fichier, et une
   simple regle de base placee ici (apres le bloc mobile) l'aurait ecrase. */
@media (min-width: 1025px) {
    .sheet-grabber { display: none; }
}

/* ==========================================================================
   PALIERS D'IMPORTANCE — phase 3

   Cinq teintes a la taille d'un marqueur sont indiscernables au premier coup
   d'oeil. Quatre paliers, ou la TAILLE porte l'information autant que la
   couleur : perception pre-attentive, robuste au daltonisme (~8 % des
   hommes), et encore lisible sur un ecran de 375 px.

   Le bas de gamme est volontairement desature — l'oeil doit aller vers ce
   qui compte, pas vers le bruit de fond.
   ========================================================================== */

.legend-items { list-style: none; margin: 0; padding: 0; }

.legend-item {
    display: flex;
    align-items: center;
    gap: 9px;
}

/* La pastille de legende reproduit la taille reelle du marqueur. */
.legend-item .legend-dot {
    display: inline-block;
    border-radius: 50%;
    flex: none;
}
.legend-item.tier-routine  .legend-dot { width: 7px;  height: 7px;  background: var(--sev-1); }
.legend-item.tier-notable  .legend-dot { width: 10px; height: 10px; background: var(--sev-3); }
.legend-item.tier-major    .legend-dot { width: 13px; height: 13px; background: var(--sev-4); }
.legend-item.tier-critical .legend-dot {
    width: 16px; height: 16px; background: var(--sev-5);
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.18);
}
/* Colonne alignee malgre des pastilles de tailles differentes. */
.legend-item { min-height: 20px; }
.legend-item .legend-dot { margin: 0 auto; }
.legend-item > span:first-child { width: 18px; display: flex; justify-content: center; }

/* --- Etiquettes de palier (cartes du flux, popups) ---
   Remplacent « SEV-3 », jargon d'echelle qui ne parle qu'aux inities. */
.event-tag.severity,
.detail-popup-tag.severity {
    font-variant-numeric: normal;
    letter-spacing: .02em;
}
.event-tag.severity.tier-routine,
.detail-popup-tag.severity.tier-routine {
    background: rgba(100, 116, 139, 0.16);
    color: #94a3b8;
    border-color: rgba(100, 116, 139, 0.3);
}
.event-tag.severity.tier-notable,
.detail-popup-tag.severity.tier-notable {
    background: rgba(251, 191, 36, 0.14);
    color: #fcd34d;
    border-color: rgba(251, 191, 36, 0.32);
}
.event-tag.severity.tier-major,
.detail-popup-tag.severity.tier-major {
    background: rgba(249, 115, 22, 0.15);
    color: #fdba74;
    border-color: rgba(249, 115, 22, 0.35);
}
.event-tag.severity.tier-critical,
.detail-popup-tag.severity.tier-critical {
    background: rgba(239, 68, 68, 0.16);
    color: #fca5a5;
    border-color: rgba(239, 68, 68, 0.4);
}

/* ==========================================================================
   SELECTEUR DE DENSITE — phase 5

   Trois crans exclusifs. Le curseur actif est un fond plein qui glisse ;
   seul `transform` est anime, comme partout ailleurs dans ce projet.
   ========================================================================== */

.preset-switch {
    position: relative;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border-light, rgba(255, 255, 255, 0.1));
    border-radius: 10px;
    flex: none;
}

.preset-btn {
    position: relative;
    padding: 5px 11px;
    border: none;
    border-radius: 7px;
    background: transparent;
    color: var(--text-muted, #94a3b8);
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.18s ease, background 0.18s ease;
}
.preset-btn:hover { color: var(--text-light, #cbd5e1); }
.preset-btn.active {
    background: var(--accent, #3b82f6);
    color: #fff;
}
.preset-btn:focus-visible {
    outline: 2px solid rgba(96, 165, 250, 0.85);
    outline-offset: 1px;
}

/* Etat « modifie » : le cran de base reste selectionne, un point signale
   l'ecart. On ne cree pas un quatrieme cran fantome. */
.preset-switch.is-edited .preset-btn.active::after {
    content: '';
    position: absolute;
    top: 3px;
    right: 3px;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--warning, #fbbf24);
}

.preset-reset {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    margin-left: 2px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text-muted, #94a3b8);
    cursor: pointer;
    font-size: 0.8rem;
    transition: background 0.18s ease, color 0.18s ease;
}
.preset-reset:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-white, #f1f5f9);
}
.preset-reset[hidden] { display: none; }

/* Densite du flux : le preset Essentiel aere les cartes, Expert les resserre.
   Piloté par data-density sur le panneau. */
/* Meme correction de cible que ci-dessus : le rembourrage d'une carte vit sur
   `.event-content`, la carte elle-meme est a `padding: 0`. Ces trois regles
   etaient donc sans effet. */
#lm-sheet[data-density='comfortable'] .event-content { padding: 12px 13px 12px 15px; }
#lm-sheet[data-density='comfortable'] .event-description { font-size: 0.86rem; line-height: 1.5; }
#lm-sheet[data-density='compact'] .event-content { padding: 6px 9px 6px 11px; }
#lm-sheet[data-density='compact'] .event-description { font-size: 0.76rem; }

@media (max-width: 1024px) {
    /* Sur mobile le selecteur reste en tete de barre mais se resserre. */
    .preset-btn { padding: 5px 8px; font-size: 0.66rem; }
}

/* ==========================================================================
   PHASE 6 — ACCESSIBILITE, ATTRIBUTION, NOUVELLES COUCHES
   ========================================================================== */

/* Lien d'evitement : invisible jusqu'au focus clavier. Premier element
   atteignable dans le viewport de carte, il mene au flux — la seule
   representation parcourable des donnees. */
.lm-skip {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 80;
    padding: 9px 14px;
    background: var(--accent, #3b82f6);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
    border-radius: 8px;
    text-decoration: none;
    transform: translateY(-160%);
    transition: transform 0.2s ease;
}
.lm-skip:focus {
    transform: translateY(0);
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Cartes du flux focusables : l'anneau doit rester visible malgre le
   defilement du conteneur. */
.event-card:focus-visible {
    outline: 2px solid var(--accent, #3b82f6);
    outline-offset: -2px;
    border-radius: 8px;
}

/* --- Panneau d'attribution --- */
/* Les sources vivent DANS la legende, en pied de panneau : ce n'est plus une
   boite flottante autonome mais une section repliable du meme bloc. D'ou
   `position: static` et l'absence de fond propre — le panneau porte deja le
   sien. */
.lm-attribution {
    display: block;
    margin-top: 10px;
    padding-top: 9px;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
    font-size: 0.68rem;
}
.lm-attribution summary {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 1px 0;
    color: var(--text-dim, #475569);
    cursor: pointer;
    list-style: none;
    user-select: none;
    white-space: nowrap;
    font-size: 0.63rem;
    transition: color 0.15s ease;
}
.lm-attribution summary::-webkit-details-marker { display: none; }
.lm-attribution summary:hover { color: var(--text-light, #cbd5e1); }
.lm-attribution summary:focus-visible {
    outline: 2px solid rgba(96, 165, 250, 0.8);
    outline-offset: 2px;
    border-radius: 4px;
}
/* Ouvert, la liste peut etre longue : elle defile dans le panneau plutot que
   de le faire deborder de la carte. */
.lm-attribution[open] {
    max-height: 34vh;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.lm-attribution-body { padding: 2px 0 0; }

.lm-attr-list { margin: 0; }
.lm-attr-list dt {
    margin-top: 7px;
    color: var(--text-light, #cbd5e1);
    font-weight: 600;
    font-size: 0.66rem;
}
.lm-attr-list dd {
    margin: 1px 0 0;
    color: var(--text-muted, #94a3b8);
    line-height: 1.45;
    font-size: 0.64rem;
}
.lm-attr-stamp {
    margin: 9px 0 0;
    padding-top: 7px;
    border-top: 1px solid var(--border, rgba(255, 255, 255, 0.06));
    color: var(--text-dim, #475569);
    font-size: 0.63rem;
    font-variant-numeric: tabular-nums;
}

/* Le panneau des sources suit desormais la legende : plus de positionnement
   propre a corriger sur mobile. La legende, elle, remonte deja au-dessus du
   cran « apercu » de la feuille (voir .map-legend dans la requete media). */
@media (max-width: 1024px) {
    .lm-attribution[open] { max-height: 26vh; }
}

/* --- Couches vent / satellite --- */
.filter-toggle#toggle-wind.active {
    background: rgba(56, 189, 248, 0.14);
    border-color: rgba(56, 189, 248, 0.5);
    color: #7dd3fc;
}
.filter-toggle#toggle-satellite.active {
    background: rgba(34, 197, 94, 0.14);
    border-color: rgba(34, 197, 94, 0.45);
    color: #86efac;
}

@media (prefers-reduced-motion: reduce) {
    .lm-skip { transition: none; }
}

/* ==========================================================================
   LEGENDE — 5 PALIERS, ALIGNEMENT CORRIGE

   Les pastilles ont des tailles differentes (c'est le principe : la taille
   porte l'information). Sans colonne de largeur fixe ET centrage vertical
   commun, les libelles se decalaient les uns par rapport aux autres.
   Grille a deux colonnes : la premiere a la largeur de la plus grosse
   pastille, la seconde aligne tous les libelles sur la meme verticale.
   ========================================================================== */

.map-legend .legend-items {
    display: grid;
    grid-template-columns: 20px 1fr;
    gap: 7px 10px;
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Chaque item occupe les deux colonnes de la grille parente. */
.map-legend .legend-item {
    display: contents;
}

.map-legend .legend-item .legend-dot {
    grid-column: 1;
    justify-self: center;
    align-self: center;
    border-radius: 50%;
    flex: none;
    margin: 0;
}
.map-legend .legend-item > span:last-child {
    grid-column: 2;
    align-self: center;
    font-size: 0.72rem;
    line-height: 1.2;
    white-space: nowrap;
}

/* Rampe de taille : identique a celle des marqueurs sur la carte, pour que
   la legende soit une cle de lecture exacte et non une approximation. */
/* ---- Echelle des incendies ----
   Un DEGRADE continu, pas cinq pastilles : la recence est une grandeur
   continue, et la couche l'interpole. Montrer des paliers laisserait croire
   a des classes qui n'existent pas. */
/* Mention de recalage dans la fiche d'un incendie : une deduction, signalee
   comme telle. Ton informatif, pas alarmant — ce n'est pas une erreur. */
.detail-popup-snap {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    margin: 10px 0 0;
    padding: 8px 10px;
    border-radius: 8px;
    background: rgba(224, 113, 41, 0.10);
    border: 1px solid rgba(224, 113, 41, 0.28);
    color: var(--text-muted, #94a3b8);
    font-size: 0.72rem;
    line-height: 1.4;
}
.detail-popup-snap i {
    flex: none;
    margin-top: 1px;
    color: #e07129;
    font-size: 0.9rem;
}

.legend-fire {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
}
.legend-fire[hidden] { display: none; }

.legend-sub {
    margin-bottom: 7px;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-dim, #475569);
}

.legend-ramp {
    height: 8px;
    border-radius: 99px;
    /* Memes arrets que circle-color de la couche 'fires-point', mais lus de
       droite a gauche : le degrade va du plus ANCIEN (brun, a gauche) au plus
       recent (blanc-jaune, a droite), dans le sens d'une frise temporelle. */
    background: linear-gradient(90deg,
        #6e3626 0%, #8a4028 20%, #c64624 40%, #e07129 60%, #ecc34f 80%, #ffe066 94%, #fff8d4 100%);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.3);
}
/* Memes arrets que WIND_RAMP dans 20-map-core.js. Registre FROID, pour ne
   jamais se confondre avec la palette chaude des incendies. */
.legend-ramp.ramp-wind {
    background: linear-gradient(90deg,
        rgb(207,250,254) 0%, rgb(103,232,249) 18%, rgb(56,189,248) 36%,
        rgb(99,102,241) 55%, rgb(168,85,247) 73%, rgb(232,121,249) 100%);
}

.legend-ramp-ends {
    display: flex;
    justify-content: space-between;
    margin-top: 3px;
    font-size: 0.58rem;
    color: var(--text-dim, #475569);
    font-variant-numeric: tabular-nums;
}

.legend-items-fire { margin-top: 8px; }
.map-legend .legend-item .legend-dot.dot-burnt {
    width: 12px;
    height: 9px;
    border-radius: 3px;
    background: #6e3626;
    border: 1px solid #c64624;
}
/* Perimetre ESTIME : brun clair et contour pointille — la meme signature que
   sur la carte. Le pointille est le signal le plus fiable des deux : il dit
   « estimation » meme a qui ne compare pas les teintes. */
.map-legend .legend-item .legend-dot.dot-burnt-potential {
    width: 12px;
    height: 9px;
    border-radius: 3px;
    background: rgba(210, 166, 121, .45);
    border: 1px dashed #e8c9a0;
}

.map-legend .legend-item.tier-routine  .legend-dot { width: 7px;  height: 7px;  background: var(--sev-1); }
.map-legend .legend-item.tier-minor    .legend-dot { width: 9px;  height: 9px;  background: var(--sev-2); }
.map-legend .legend-item.tier-notable  .legend-dot { width: 12px; height: 12px; background: var(--sev-3); }
.map-legend .legend-item.tier-major    .legend-dot { width: 15px; height: 15px; background: var(--sev-4); }
.map-legend .legend-item.tier-critical .legend-dot {
    width: 18px; height: 18px; background: var(--sev-5);
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.18);
}

/* Etiquette du 5e palier dans le flux et les popups. */
.event-tag.severity.tier-minor,
.detail-popup-tag.severity.tier-minor {
    background: rgba(56, 189, 248, 0.14);
    color: #7dd3fc;
    border-color: rgba(56, 189, 248, 0.3);
}

/* ==========================================================================
   SEPARATEUR REDIMENSIONNABLE — ECRAN SCINDE (desktop)

   La largeur du panneau devient une variable, pilotee par 16-splitter.js.
   Trois etats nommes : `map` (carte seule), `split`, `panel` (liste seule).
   ========================================================================== */

@media (min-width: 1025px) {
    .dashboard-body {
        /* --lm-panel-w est ecrite sur :root par le JS ; la valeur de repli
           reproduit la largeur historique. */
        grid-template-columns: minmax(0, 1fr) auto var(--lm-panel-w, var(--sidebar-w, 420px));
    }

    .lm-splitter {
        position: relative;
        width: 7px;
        flex: none;
        cursor: col-resize;
        background: transparent;
        border: none;
        padding: 0;
        z-index: 60;
        touch-action: none;
        transition: background 0.15s ease;
    }
    .lm-splitter::before {
        /* Zone de saisie plus large que le trait visible : viser 7 px a la
           souris est desagreable. */
        content: '';
        position: absolute;
        inset: 0 -5px;
    }
    .lm-splitter:hover,
    .lm-splitter:focus-visible,
    body.lm-splitting .lm-splitter {
        background: rgba(96, 165, 250, 0.35);
    }
    .lm-splitter:focus-visible {
        outline: 2px solid rgba(96, 165, 250, 0.85);
        outline-offset: -2px;
    }

    /* Poignee : trois traits verticaux, convention des separateurs. */
    .lm-splitter-grip {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 3px;
        height: 34px;
        border-radius: 99px;
        background: rgba(255, 255, 255, 0.22);
        transition: background 0.15s ease, height 0.15s ease;
    }
    .lm-splitter:hover .lm-splitter-grip,
    .lm-splitter:focus-visible .lm-splitter-grip {
        background: rgba(255, 255, 255, 0.55);
        height: 46px;
    }

    /* Pendant le glissement : on neutralise la selection de texte et on force
       le curseur sur toute la page, sinon il change en survolant un enfant. */
    body.lm-splitting {
        cursor: col-resize;
        user-select: none;
    }
    body.lm-splitting * { pointer-events: none; }
    body.lm-splitting .lm-splitter { pointer-events: auto; }

    /* --- Etats extremes --- */
    .dashboard-body[data-split='map'] .sidebar-section {
        width: 0;
        min-width: 0;
        overflow: hidden;
        border-left: none;
    }
    .dashboard-body[data-split='panel'] .map-section {
        width: 0;
        min-width: 0;
        overflow: hidden;
    }
    /* Replie, le separateur reste attrapable pour revenir en arriere. */
    .dashboard-body[data-split='map'] .lm-splitter,
    .dashboard-body[data-split='panel'] .lm-splitter {
        background: rgba(96, 165, 250, 0.25);
    }

    /* Le panneau ne doit pas imposer sa largeur minimale intrinseque, sinon
       la colonne refuse de descendre sous ~380 px. */
    .sidebar-section { min-width: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .lm-splitter, .lm-splitter-grip { transition: none; }
}

/* ==========================================================================
   PANNEAU DE CALQUES

   Les interrupteurs de couches ont quitte la barre de filtres. Ils y
   debordaient — le bouton incendies disparaissait des que la barre etait
   pleine — et surtout ils y melangeaient deux natures de controle :
   FILTRER quels evenements on lit (les puces de categorie), contre CHOISIR
   quoi dessiner sur la carte (les calques). Un bouton, une liste, comme le
   « Calques » de flamap.
   ========================================================================== */

/* Champ de vent — canvas superpose au canvas WebGL de MapLibre.
   Insere dans le conteneur de canvas de la carte, donc il suit
   automatiquement ses transformations de taille. Transparent aux
   evenements : cliquer « a travers » le vent doit atteindre la carte. */
.lm-wind-canvas {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    /* Au-dessus des tuiles, sous les marqueurs et les popups. */
    z-index: 2;
}

/* La fumee se pose SOUS les trainees de vent et sous les marqueurs : elle est
   un fond d'ambiance, pas une donnee a lire. Le canvas vent occupe z-index 2,
   celui-ci reste juste au-dessous. */
.lm-smoke-canvas {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 1;
}

.lm-pop { position: relative; flex: none; }

.lm-pop-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 30px;
    padding: 0 10px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--border-light, rgba(255, 255, 255, 0.1));
    border-radius: 8px;
    color: var(--text-light, #cbd5e1);
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.18s ease, border-color 0.18s ease;
}
.lm-pop-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.22);
}
.lm-pop-btn[aria-expanded='true'] {
    background: rgba(96, 165, 250, 0.14);
    border-color: rgba(96, 165, 250, 0.4);
    color: #bfdbfe;
}
.lm-pop-btn:focus-visible {
    outline: 2px solid rgba(96, 165, 250, 0.85);
    outline-offset: 2px;
}
.lm-pop-caret {
    font-size: 0.7rem;
    opacity: 0.7;
    transition: transform 0.18s ease;
}
.lm-pop-btn[aria-expanded='true'] .lm-pop-caret { transform: rotate(180deg); }

/* Compteur : combien d'entrees sont actives, lisible sans ouvrir. */
.lm-pop-count {
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 99px;
    background: var(--accent, #3b82f6);
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.lm-pop-count[hidden] { display: none; }

/* `position: fixed`, et non `absolute`.
   La barre de filtres est en `overflow: hidden` — elle doit l'etre, sinon les
   controles debordent sur la carte. Un panneau en `position: absolute` est un
   descendant de cette barre : il etait donc DECOUPE a la hauteur de la barre,
   quel que soit son z-index. C'etait la cause du « le bouton calque ne
   s'ouvre pas » : le panneau s'ouvrait bel et bien, mais dans une zone
   invisible. En `fixed`, il sort du flux de decoupage ; ses coordonnees sont
   posees en JS depuis le rect du bouton (voir positionPopover()). */
/* LARGEUR BORNEE — sans quoi c'est le texte le plus long qui decide.
   Un element `fixed` sans largeur declaree se dimensionne au « shrink to
   fit » : il prend la largeur de son contenu le plus large, dans la limite
   du viewport. Le panneau contenait un message d'etat d'une seule phrase,
   sans contrainte de largeur — mesure a 832 px. Le panneau s'ouvrait donc a
   864 px, et les colonnes `1fr` de la grille de vignettes suivaient : 273 px
   par vignette, la moitie de l'ecran pour trois cases a cocher.

   `max-width` rend le panneau independant de son contenu : la prose passe a
   la ligne au lieu d'ecarter les murs. */
.lm-pop-panel {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1200;
    width: max-content;
    min-width: 240px;
    /* ELARGI. A 300 px, quatre vignettes de 72 px ne tenaient pas sur une
       ligne : la quatrieme passait seule a la ligne suivante et le panneau
       gagnait 100 px de haut pour une seule case. */
    max-width: min(344px, calc(100vw - 24px));
    max-height: min(78vh, 620px);
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Le degrade du bas signale qu'il reste du contenu sous le pli. Il est
       ancre au conteneur (`local` pour le fond qui defile, `scroll` pour
       l'ombre) : il disparait de lui-meme une fois le bas atteint. */
    background-repeat: no-repeat;
    background-attachment: local, local, scroll, scroll;
    padding: 10px;
    background: var(--bg-panel, #0d1525);
    border: 1px solid var(--border-light, rgba(255, 255, 255, 0.12));
    border-radius: 12px;
    box-shadow: 0 18px 46px rgba(0, 0, 0, 0.55);
    animation: lmPopIn 0.15s ease-out;
}
.lm-pop-panel[hidden] { display: none; }

@keyframes lmPopIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .lm-pop-panel { animation: none; }
}

/* ==========================================================================
   VERROU DE DEFILEMENT PENDANT LE GLISSEMENT DE LA FEUILLE

   Pose sur <html> par 15-sheet.js le temps du geste. Sans lui, un doigt qui
   sort de la zone de prise en cours de route rend la main au navigateur, et
   la page part vers le pied de page pendant que la feuille reste sur place.

   `overflow: hidden` sur les deux elements racines : selon le navigateur,
   c'est l'un ou l'autre qui porte le defilement du document.
   ========================================================================== */
html.lm-sheet-dragging,
html.lm-sheet-dragging body {
    overflow: hidden !important;
    overscroll-behavior: none;
}

/* --- COMPTEURS DES COUCHES, DANS LE FIL -------------------------------
   « 379 foyers · 5 jours », « 85 regions en vigilance »… Ces lignes disent ce
   que la carte MONTRE : leur place est aupres du nombre d'evenements, pas
   dans un menu qu'il faut ouvrir — donc qui masque la carte dont il parle.

   En puces sur une ligne qui se replie : quatre valeurs courtes tiennent en
   une ou deux lignes, contre quatre lignes empilees auparavant. */
.layer-readout {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 6px;
    margin-top: 8px;
}
.layer-readout:empty { display: none; }
.layer-readout .layer-status {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 0;
    padding: 2px 8px 2px 6px;
    border: 1px solid rgba(255, 255, 255, .1);
    border-radius: 99px;
    background: rgba(255, 255, 255, .04);
    color: var(--text-muted, #94a3b8);
    font-size: 0.66rem;
    line-height: 1.5;
    white-space: nowrap;
}
/* La pastille reprend la couleur de la couche : on relie le compteur au
   calque sans avoir a le nommer. */
.layer-readout .layer-status::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex: 0 0 auto;
    background: currentColor;
}
.layer-readout .layer-status[data-layer="fires"]     { color: #fb923c; }
.layer-readout .layer-status[data-layer="weather"]   { color: #fbbf24; }
.layer-readout .layer-status[data-layer="migration"] { color: #fb7185; }
.layer-readout .layer-status[data-layer="wind"]      { color: #67e8f9; }
.layer-readout .layer-status.is-error  { color: #f87171; }
.layer-readout .layer-status.is-empty  { color: var(--text-dim, #475569); }
.layer-readout .layer-status.is-loading { opacity: .7; }

/* ---- Panneau des categories ---- */
.lm-pop-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 6px;
    padding: 0 3px 7px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.lm-pop-title {
    color: var(--text-dim, #475569);
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.lm-pop-action {
    padding: 3px 8px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 6px;
    color: var(--text-light, #cbd5e1);
    font-family: inherit;
    font-size: 0.64rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease;
}
.lm-pop-action:hover { background: rgba(255, 255, 255, 0.1); }

/* Etat d'une couche : discret quand tout va bien, ambre quand il n'y a rien
   a montrer, rouge quand le service ne repond pas. */
.layers-hint {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin: 9px 3px 1px;
    padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
    color: var(--text-dim, #475569);
    font-size: 0.63rem;
    line-height: 1.35;
}
.layers-hint i { flex: none; margin-top: 1px; font-size: 0.8rem; }

.layer-statuses:empty { display: none; }
.layer-status {
    margin: 4px 2px 0;
    font-size: 0.63rem;
    line-height: 1.3;
    color: var(--text-dim, #475569);
}
.layer-status[hidden] { display: none; }
.layer-status.is-ok      { color: var(--text-muted, #94a3b8); }
.layer-status.is-loading { color: var(--text-dim, #475569); font-style: italic; }
.layer-status.is-empty   { color: #d9a441; }
.layer-status.is-error   { color: #e8735f; }

.cats-panel { min-width: 264px; }
.cats-grid { display: flex; flex-direction: column; gap: 1px; }

/* ---- VIGNETTES DE CALQUE (facon Google Maps) ----
   Les apercus sont dessines en CSS pur — degrades et motifs repetes — et
   non en images : trois fichiers de plus a charger pour 56 px de cote
   n'auraient aucun sens, et une vignette en CSS suit le theme. */
.layers-panel { min-width: 272px; }

/* VIGNETTES A TAILLE FIXE, ET NON EN FRACTIONS.
   `repeat(3, 1fr)` fait grandir chaque vignette avec le panneau : trois
   colonnes elastiques pour une ou deux vignettes reelles, cela donnait des
   pastilles de 273 px de cote quand la couche incendies etait masquee.
   Une taille definie garde la meme vignette qu'il y en ait une, deux ou
   trois — c'est aussi ce que fait le selecteur de calques de Google Maps. */
.tile-grid {
    display: grid;
    /* `auto-fill` avec une largeur MINIMALE, et non un nombre de colonnes fixe.
       Trois colonnes en dur imposaient la mise en page quel que soit le nombre
       de vignettes : avec quatre couches, la derniere se retrouvait seule sur
       une deuxieme ligne. Le panneau place desormais autant de colonnes qu'il
       peut, et les vignettes gardent une taille lisible. */
    grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
    gap: 7px;
    margin-bottom: 4px;
}

.map-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 0;
    background: none;
    border: 0;
    font-family: inherit;
    cursor: pointer;
}
.map-tile input { position: absolute; opacity: 0; pointer-events: none; }

/* --- TEINTE PROPRE A CHAQUE COUCHE ------------------------------------
   Les pictogrammes etaient tous du meme gris : il fallait lire le libelle
   pour savoir lequel on regardait, et rien ne reliait la vignette a ce que la
   couche dessine sur la carte. Chaque icone reprend donc la couleur DOMINANTE
   de son rendu — l'orange des foyers, l'ambre des vigilances, le rose des
   points de passage, le cyan du vent. Le lien entre le menu et la carte se
   fait alors sans le lire.

   La teinte est presente des l'etat au repos, seulement plus sourde : c'est
   ce qui permet de reconnaitre une couche AVANT de l'allumer. */
.map-tile-thumb[data-layer="fires"]     { color: #fb923c; }
.map-tile-thumb[data-layer="weather"]   { color: #fbbf24; }
.map-tile-thumb[data-layer="migration"] { color: #fb7185; }
.map-tile-thumb[data-layer="wind"]      { color: #67e8f9; }
.map-tile-thumb[data-layer="basemap"]   { color: #93c5fd; }
.map-tile-thumb[data-layer="satellite"] { color: #86efac; }

/* Au repos, la couleur est la — attenuee. Allumee ou survolee, elle sort. */
.map-tile-thumb[data-layer] { opacity: .62; }
.map-tile:hover .map-tile-thumb[data-layer],
.map-tile input:checked ~ .map-tile-thumb[data-layer],
.map-tile-btn.active .map-tile-thumb[data-layer] { opacity: 1; }

.map-tile-thumb {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    /* Plafond de taille. Sans lui, la vignette prend TOUTE la largeur de sa
       colonne : le panneau s'elargissant, quatre pictogrammes finissaient a
       plus de 80 px, hors de proportion avec le reste du menu. Le `minmax`
       de la grille ne suffit pas — il fixe un plancher, pas un plafond. */
    max-width: 54px;
    aspect-ratio: 1 / 1;
    border-radius: 9px;
    border: 2px solid transparent;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12);
    /* Fond neutre : c'est le PICTOGRAMME qui porte le sens, pas la vignette.
       Les anciens degrades tentaient de reproduire le rendu de la couche et
       donnaient, a 72 px, une tache indistincte. */
    background: linear-gradient(160deg, rgba(148, 163, 184, 0.10), rgba(15, 23, 42, 0.55));
    color: var(--text-muted, #94a3b8);
    transition: border-color .15s ease, box-shadow .15s ease,
                color .15s ease, background .2s ease, transform .15s ease;
    overflow: hidden;
}
.map-tile:hover .map-tile-thumb {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3);
    transform: translateY(-1px);
}

/* --- PICTOGRAMME ------------------------------------------------------
   L'animation SVG ne tourne QUE sur une couche allumee ou survolee. Quatre
   icones qui s'agitent en permanence dans un menu ferait clignoter le coin
   de l'ecran sans rien apprendre : le mouvement doit signaler un etat, pas
   meubler. `animation-play-state` ne pilote pas les elements <animate> —
   on se sert donc de la visibilite de l'icone animee. */
.lm-tile-icon {
    width: 58%;
    height: 58%;
    display: block;
}
.map-tile-thumb .lm-tile-icon animate,
.map-tile-thumb .lm-tile-icon animateTransform {
    /* Etat au repos : la valeur de depart, figee. */
    display: none;
}
.map-tile:hover .lm-tile-icon animate,
.map-tile:hover .lm-tile-icon animateTransform,
.map-tile input:checked ~ .map-tile-thumb .lm-tile-icon animate,
.map-tile input:checked ~ .map-tile-thumb .lm-tile-icon animateTransform,
.map-tile-btn.active .lm-tile-icon animate,
.map-tile-btn.active .lm-tile-icon animateTransform {
    display: inline;
}

/* Rien ne bouge pour qui a demande moins de mouvement. */
@media (prefers-reduced-motion: reduce) {
    .lm-tile-icon animate,
    .lm-tile-icon animateTransform { display: none !important; }
    .map-tile:hover .map-tile-thumb { transform: none; }
}

/* Etat selectionne : liseré bleu, comme le « Satellite » actif de Google. */
.map-tile input:checked ~ .map-tile-thumb,
.map-tile-btn.active .map-tile-thumb {
    border-color: var(--accent, #3b82f6);
    box-shadow: 0 0 0 1px var(--accent, #3b82f6);
    background: linear-gradient(160deg, rgba(59, 130, 246, 0.22), rgba(15, 23, 42, 0.6));
}
.map-tile input:focus-visible ~ .map-tile-thumb,
.map-tile-btn:focus-visible .map-tile-thumb {
    outline: 2px solid rgba(96, 165, 250, 0.9);
    outline-offset: 2px;
}

.map-tile-label {
    font-size: 0.66rem;
    font-weight: 500;
    line-height: 1.15;
    text-align: center;
    color: var(--text-muted, #94a3b8);
    transition: color 0.15s ease;
}
.map-tile input:checked ~ .map-tile-label,
.map-tile-btn.active .map-tile-label {
    color: #93c5fd;
    font-weight: 600;
}

.layers-group-label {
    margin: 8px 0 4px;
    color: var(--text-dim, #475569);
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.layers-group-label:first-child { margin-top: 0; }

.layer-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 6px;
    border-radius: 7px;
    cursor: pointer;
    transition: background 0.15s ease;
}
.layer-row:hover { background: rgba(255, 255, 255, 0.05); }
.layer-row input[type='checkbox'] {
    width: 15px;
    height: 15px;
    accent-color: var(--accent, #3b82f6);
    cursor: pointer;
    flex: none;
}
.layer-name {
    color: var(--text-light, #cbd5e1);
    font-size: 0.74rem;
    line-height: 1.25;
}

/* Pastille de couleur : rappelle le rendu du calque sur la carte, pour
   qu'on sache ce qu'on allume avant de l'allumer. */
.layer-swatch {
    width: 11px;
    height: 11px;
    border-radius: 3px;
    flex: none;
}
.swatch-fires   { background: linear-gradient(135deg, #fde047, #b91c1c); }
.swatch-wind    { background: linear-gradient(135deg, #e2e8f0, #38bdf8); }
.swatch-sat     { background: linear-gradient(135deg, #4ade80, #166534); }
.swatch-markets { background: linear-gradient(135deg, #93c5fd, #1d4ed8); }
.swatch-bases   { background: #0ea5e9; }
.swatch-eez     { background: rgba(56, 189, 248, 0.45); border: 1px solid rgba(56, 189, 248, 0.8); }

.layers-note {
    margin: 4px 6px 2px;
    color: var(--text-dim, #475569);
    font-size: 0.68rem;
    font-style: italic;
}

/* Etroit : le libelle disparait, l'icone et le compteur restent. Le panneau
   garde sa largeur — c'est lui qui porte l'information, le bouton n'est
   qu'une poignee. */
@media (max-width: 900px) {
    .lm-pop-label { display: none; }
    .lm-pop-btn { padding: 0 8px; gap: 5px; }
}

/* Sous 720 px, meme reduits, les cinq controles ne tiennent plus sur une
   ligne : le curseur de gravite se retrouvait entierement hors-champ, et la
   barre etant en `overflow: hidden`, il disparaissait SANS aucun indice —
   pas de barre de defilement, pas de troncature visible. Or c'est le reglage
   le plus utilise. On passe donc a deux rangees, le curseur occupant la
   seconde sur toute la largeur, ou il est enfin confortable a manipuler au
   pouce. */
@media (max-width: 720px) {
    .filters-bar {
        flex-wrap: wrap;
        row-gap: 8px;
        padding-bottom: 8px;
    }
    /* Ce separateur marquait la frontiere avec le curseur : le passage a la
       ligne joue desormais ce role. */
    .divider-before-severity { display: none; }
    .severity-range {
        flex: 1 1 100%;
        justify-content: space-between;
    }
    .severity-range .severity-sliders { flex: 1 1 auto; }
}
