#header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background: var(--bg-header);
    color: white;
    padding: 10px 20px;
    z-index: 1000;
    box-shadow: 0 2px 6px rgba(0,0,0,0.2);
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 13px;
    flex-wrap: wrap;
    gap: 8px;
  }

  #header h1 {
    font-size: 16px;
    font-weight: 600;
  }

  #header .subtitle {
    font-size: 11px;
    opacity: 0.85;
    margin-top: 2px;
  }

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

  .controls button {
    background: var(--bg-header-btn);
    color: white;
    border: none;
    padding: 0 12px;
    height: 28px;             /* hauteur fixe pour TOUS les boutons */
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;            /* enlève l'inconsistance entre navigateurs */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    transition: background 0.15s;
    white-space: nowrap;
  }

  .controls button:hover { background: var(--bg-header-btn-hover); }

  /* === BARRE DE RECHERCHE === */
  /* Pile VERTICALE : column-reverse ⇒ le 1er enfant du DOM (#lang-toggle)
     reste collé en bas, et les suivants s'empilent vers le haut :
     ENG · ? · ← · Qualité des données · Navigation · Avis.
     Les panneaux (légende, navigation) s'ouvrent donc vers le haut
     depuis le coin inférieur gauche. */
  #bottom-left-panels {
    position: fixed;
    left: 10px;
    bottom: 10px;
    display: flex;
    flex-direction: column-reverse;
    gap: 8px;
    align-items: flex-start;
    /* Au-dessus de TOUTES les modales (3000 intro/incidents, 4000 avis) :
       la colonne latérale reste visible et cliquable en permanence. C'est
       ce qui permet d'imprimer ou de basculer le thème sans fermer une
       modale ouverte. */
    z-index: 4500;
    flex-wrap: nowrap;
    max-width: 300px;
    max-height: calc(100vh - 20px);
  }
  /* Panneaux flottants : ancrés en bas, À DROITE de la colonne d'icônes.
     Positionnés en absolu par rapport à #bottom-left-panels (fixed), ils
     ne participent pas à la pile verticale et ne la repoussent donc pas.
     Empilés en column-reverse : Qualité des données en bas (au niveau de
     son icône 🎨), Navigation juste au-dessus. */
  /* position:FIXED (et non absolute) : en absolu, le bloc conteneur serait
     #bottom-left-panels, large de ~36 px seulement. Avec left:100%, l'espace
     disponible pour le calcul shrink-to-fit tombe à 0 et le navigateur rabat
     les panneaux sur leur largeur min-content — ils deviennent des colonnes
     étroites et très hautes. Ancré sur le viewport, l'espace disponible est
     la largeur de l'écran : chaque panneau retrouve sa largeur naturelle,
     plafonnée par .floating-panel { max-width: 280px }.
     left = 10 px (marge de la colonne) + 36 px (icône) + 8 px (gouttière). */
  #bottom-panels-stack {
    position: fixed;
    left: 54px;
    bottom: 10px;
    display: flex;
    flex-direction: column-reverse;
    align-items: flex-start;
    gap: 8px;
    z-index: 4500;
    pointer-events: none; /* le conteneur vide ne doit rien intercepter */
  }
  /* Aucune contrainte de taille ici : les panneaux gardent exactement la
     boîte définie par .floating-panel (padding 10/14, font-size 11px,
     max-width 280px), comme lorsqu'ils étaient dans la rangée d'origine.
     flex:0 0 auto ⇒ ni étirement ni compression par le conteneur. */
  #bottom-panels-stack > .floating-panel {
    flex: 0 0 auto;
    pointer-events: auto;
  }

  .floating-panel {
    background: var(--bg-panel);
    color: var(--text-default);
    border: 1px solid var(--border-panel);
    border-radius: 6px;
    padding: 10px 14px 10px 14px;
    font-size: 11px;
    box-shadow: 0 2px 8px var(--shadow-panel);
    max-width: 280px;
    position: relative;
    transition: opacity 0.15s, transform 0.15s;
  }
  .floating-panel.hidden {
    display: none;
  }

  .floating-panel h3 {
    font-size: 12px;
    margin-bottom: 6px;
    color: var(--text-accent);
    padding-right: 22px; /* place pour le bouton réduire */
  }

  .floating-panel .legend-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 3px 0;
  }

  .floating-panel strong { color: var(--text-accent); }

  /* Bouton réduire commun aux panneaux flottants */
  .panel-collapse-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 18px;
    height: 18px;
    border: 1px solid var(--border-panel);
    background: var(--bg-page);
    color: var(--text-muted);
    border-radius: 3px;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .panel-collapse-btn:hover {
    background: var(--bg-header-btn);
    color: white;
    border-color: var(--bg-header-btn);
  }

  .legend-box {
    display: inline-block;
    width: 16px;
    height: 12px;
    border: 1px solid #555;
    border-radius: 2px;
    flex-shrink: 0;
  }

  /* Icônes restaurées (apparaissent à la place de leur bulle quand celle-ci
     est repliée). Elles sont des frères flex de #legend et #instructions
     dans #bottom-left-panels, donc elles s'alignent naturellement entre
     les bulles visibles. */
  .restore-icon {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--bg-panel);
    border: 1px solid var(--border-panel);
    box-shadow: 0 2px 6px var(--shadow-panel);
    cursor: pointer;
    font-size: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    flex-shrink: 0;
    transition: transform 0.1s, box-shadow 0.1s;
  }
  .restore-icon:hover {
    transform: scale(1.08);
    box-shadow: 0 4px 12px rgba(0,0,0,0.2);
  }
  .restore-icon.hidden { display: none; }

  /* Bascules de panneau (🎨 Qualité des données, 🧭 Navigation).
     Elles ne se cachent plus quand leur panneau est ouvert : elles
     restent en place et servent aussi à le refermer. L'état ouvert est
     signalé par une bordure et un halo en couleur d'accent, pour qu'on
     voie d'un coup d'œil quel bouton commande quelle fenêtre. */
  .restore-icon.panel-toggle-active {
    border-color: var(--text-accent);
    box-shadow: 0 0 0 2px var(--shadow-panel), 0 2px 6px var(--shadow-panel);
  }

  /* Bouton « ? » : rouvre le message d'accueil de la section.
     Déplacé de la barre du haut vers la colonne ; il hérite du cercle
     36 px de .restore-icon et ne redéfinit que le glyphe. */
  #btn-help {
    font-size: 17px;
    font-weight: 700;
    color: var(--text-accent);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  }
  #btn-help:hover { color: #fff; background: var(--text-accent); }

  /* 3e icône : relecture de l'AVIS DE NON-RESPONSABILITÉ
     (toujours visible, indépendante des préférences de collapse). */
  #reopen-disclaimer {
    border: 1px solid #c2185b;
  }

  /* 4e icône : bascule de langue FR ⇄ EN.
     Hérite du cercle 36 px de .restore-icon ; on remplace seulement
     l'apparence du label (texte plutôt qu'emoji). Bordure en accent
     pour la distinguer visuellement des trois icônes existantes. */
  #lang-toggle {
    border: 1px solid var(--text-accent);
    color: var(--text-accent);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.04em;
  }
  #lang-toggle:hover {
    background: var(--text-accent);
    color: #fff;
  }
  body.dark #lang-toggle {
    border-color: var(--text-accent);
    color: var(--text-accent);
  }
  body.dark #lang-toggle:hover {
    background: var(--bg-header-btn);
    border-color: var(--bg-header-btn);
    color: #fff;
  }
  /* Le span interne hérite proprement, mais on le force pour parer
     aux thèmes qui pourraient l'altérer. */
  #lang-toggle-label {
    display: inline-block;
    line-height: 1;
    pointer-events: none;
  }

  /* Overlays bloquants (Avis, Intro). La colonne est déjà à z-index 4500,
     donc TOUS ses boutons restent visibles et cliquables — c'est voulu :
     langue, à propos, thème, impression et navigation doivent rester
     accessibles en tout temps, exactement comme le bouton ENG l'était.
     Seuls les PANNEAUX (Qualité des données, Navigation) sont masqués :
     ce sont des fenêtres d'information, pas des commandes. */
  body.has-blocking-modal #bottom-panels-stack {
    display: none;
  }
  /* Contraste renforcé sur le voile sombre des overlays. */
  body.has-blocking-modal #bottom-left-panels .restore-icon {
    background: var(--bg-panel, #fff);
    box-shadow: 0 4px 14px rgba(0,0,0,0.4);
  }

  /* ─────────────────────────────────────────────────────────────
     AVIS LÉGAL NON ACCEPTÉ → seul ENG/FRA reste actionnable
     ─────────────────────────────────────────────────────────────
     Tant que l'avis est affiché en mode BLOQUANT — c.-à-d. présent
     (pas .hidden) et PAS en « lecture seule » (rouvert via ⚖️ après
     acceptation) —, on neutralise tous les boutons de la colonne sauf
     le bouton de langue. La bascule FR ⇄ EN doit rester possible pour
     qu'un anglophone puisse lire l'avis dans sa langue avant d'accepter.
     Sélecteur :has() → s'applique dès le premier rendu, sans JS, et se
     met à jour tout seul quand la classe de l'avis change (acceptation
     → .hidden ; réouverture → .read-only-mode). Le focus clavier est
     géré en complément par js/07-disclaimer.js. */
  body:has(#disclaimer-modal:not(.hidden):not(.read-only-mode))
       #bottom-left-panels .restore-icon:not(#lang-toggle) {
    pointer-events: none;
    opacity: 0.4;
    cursor: default;
    box-shadow: none;
  }

  /* ─────────────────────────────────────────────────────────────
     MÊME VERROU, ÉTENDU AU CONTENU PRINCIPAL (#header, #viewport)
     ─────────────────────────────────────────────────────────────
     Avant ce correctif, seule la colonne latérale était verrouillée : la
     barre d'outils (#header — recherche, Incidents, Coûts, etc.) et
     l'organigramme (#viewport) n'étaient hors d'atteinte que parce que le
     voile plein écran de l'avis les couvrait visuellement. Masquer cette
     seule modale via un filtre cosmétique d'ad-blocker (ex. uBlock
     « domaine###disclaimer-modal ») exposait donc tout le contenu, sans
     rien accepter. Le sélecteur ci-dessous répète le même mécanisme déjà
     robuste (indexé sur la classe .hidden que NOUS posons, jamais sur
     l'affichage visuel d'un tiers) et couvre désormais aussi le contenu
     principal. Renforcé par l'attribut natif `inert` posé en JS
     (js/07-disclaimer.js) sur ces deux conteneurs, qui bloque en plus le
     clavier et l'arbre d'accessibilité — indépendamment de tout style
     injecté ciblant #disclaimer-modal. */
  body:has(#disclaimer-modal:not(.hidden):not(.read-only-mode)) #header,
  body:has(#disclaimer-modal:not(.hidden):not(.read-only-mode)) #viewport,
  body:has(#disclaimer-modal:not(.hidden):not(.read-only-mode)) #zoom-indicator {
    pointer-events: none;
    filter: blur(4px);
    opacity: 0.45;
    user-select: none;
  }

  body.dark.has-blocking-modal #lang-toggle {
    background: var(--bg-panel, #1a1f24);
    box-shadow: 0 4px 14px rgba(0,0,0,0.6);
  }

  /* Badge "[FR]" appliqué automatiquement aux liens externes
     francophones quand l'interface est en anglais. Les liens à
     marquer portent class="ext-fr" — le badge n'apparaît que si
     <body> a la classe lang-en. Cela permet d'écrire les liens
     une seule fois, FR comme EN, sans dupliquer le balisage.
     Position : juste après le contenu textuel du <a>, avant tout
     pseudo-élément ::after déjà existant (ex. flèches « ↗ »). */
  body.lang-en a.ext-fr::before {
    content: "[FR]";
    display: inline-block;
    margin-right: 4px;
    padding: 0 4px;
    font-size: 0.75em;
    font-weight: 700;
    line-height: 1.4;
    vertical-align: baseline;
    color: var(--text-accent);
    background: var(--bg-modal-source, rgba(10,61,98,0.10));
    border: 1px solid var(--text-accent);
    border-radius: 3px;
    letter-spacing: 0.02em;
    text-decoration: none;
    /* Tooltip natif via CSS impossible, mais le title HTML reste
       sur le <a> parent — le badge hérite donc du title du lien. */
  }
  body.dark.lang-en a.ext-fr::before {
    color: #6cb6ee;
    border-color: #6cb6ee;
    background: rgba(108,182,238,0.15);
  }

  #zoom-indicator {
    position: fixed;
    right: 10px;
    bottom: 10px;
    background: rgba(0,0,0,0.7);
    color: white;
    padding: 5px 10px;
    border-radius: 4px;
    font-size: 11px;
    z-index: 900;
  }

  /* === SCROLLBARS GLOBALES — fines et foncées === */
  /* Webkit (Chrome, Safari, Edge, Opera) */
  ::-webkit-scrollbar {
    width: 14px;
    height: 14px;
  }
  ::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.05);
  }
  ::-webkit-scrollbar-thumb {
    background: rgba(60, 70, 80, 0.55);
    border-radius: 7px;
    border: 3px solid transparent;
    background-clip: padding-box;
    min-height: 30px;
  }
  ::-webkit-scrollbar-thumb:hover {
    background: rgba(40, 50, 60, 0.75);
    background-clip: padding-box;
  }
  ::-webkit-scrollbar-corner {
    background: transparent;
  }
  /* Flèches haut/bas (et gauche/droite) — restaurées explicitement
     car styler la scrollbar les supprime par défaut sur WebKit.
     Hauteur = largeur de la scrollbar pour que les flèches soient carrées
     et bien visibles aux deux extrémités. */
  ::-webkit-scrollbar-button {
    display: block;
    height: 14px;
    width: 14px;
    background-color: rgba(0, 0, 0, 0.05);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 8px 8px;
  }
  ::-webkit-scrollbar-button:hover {
    background-color: rgba(0, 0, 0, 0.12);
  }
  /* Flèche haut */
  ::-webkit-scrollbar-button:vertical:decrement {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><polygon points='4,1.5 7,6 1,6' fill='%23404a55'/></svg>");
  }
  /* Flèche bas */
  ::-webkit-scrollbar-button:vertical:increment {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><polygon points='1,2 7,2 4,6.5' fill='%23404a55'/></svg>");
  }
  /* Flèche gauche */
  ::-webkit-scrollbar-button:horizontal:decrement {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><polygon points='1.5,4 6,1 6,7' fill='%23404a55'/></svg>");
  }
  /* Flèche droite */
  ::-webkit-scrollbar-button:horizontal:increment {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><polygon points='2,1 2,7 6.5,4' fill='%23404a55'/></svg>");
  }
  /* WebKit affiche par défaut DEUX boutons en haut et en bas
     (single-button + double-button). On masque les double-buttons pour
     éviter d'avoir 4 flèches superposées. */
  ::-webkit-scrollbar-button:vertical:start:increment,
  ::-webkit-scrollbar-button:vertical:end:decrement,
  ::-webkit-scrollbar-button:horizontal:start:increment,
  ::-webkit-scrollbar-button:horizontal:end:decrement {
    display: none;
  }
  /* Mode nuit */
  #viewport {
    position: absolute;
    top: 50px;
    left: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
    cursor: grab;
  }

  /* Image de fond (drapeau Québec + mammouth) — derrière l'organigramme.
     Couvre tout le viewport, fixe (ne suit pas le pan/zoom du canvas).
     Affichée à pleine opacité ; un voile coloré semi-transparent par-dessus
     adoucit l'image et garantit la lisibilité des nœuds. */
  #viewport::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url('../assets/back.png');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    opacity: 1;
    pointer-events: none;
    z-index: 0;
  }
  /* Voile coloré semi-transparent par-dessus l'image pour adoucir et 
     garantir la lisibilité des nœuds. */
  #viewport::after {
    content: '';
    position: absolute;
    inset: 0;
    /* Mode jour : voile gris clair à 60% — équilibre entre visibilité de l'image
       de fond (drapeau bleu marine + texture rocheuse + mammouth fossilisé du
       back.png) et lisibilité des nœuds. */
    background: rgba(240, 244, 248, 0.60);
    pointer-events: none;
    z-index: 0;
    transition: background 0.3s;
  }
  /* Mode nuit : voile plus dense et sombre — les branches sont en bleu clair
     #5d8aae et doivent ressortir sur le fond très sombre. */
  body.dark #viewport::after {
    background: rgba(13, 20, 24, 0.55);
  }
  #canvas {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: 0 0;
    padding: 80px;
  }

  /* Styles des noeuds */
  #mobile-block {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 999999;
    background: #0a0e1a;
    color: #e6edf7;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    align-items: center;
    justify-content: center;
    padding: 24px;
    text-align: center;
  }
  #mobile-block .mb-card {
    max-width: 480px;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 16px;
    padding: 32px 28px;
    box-shadow: 0 8px 32px rgba(0,0,0,0.4);
  }
  #mobile-block .mb-lang-switch {
    display: flex;
    width: fit-content;
    align-items: center;
    gap: 8px;
    margin: 40px auto 0;
    padding: 9px 18px;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.20);
    border-radius: 999px;
    color: #e6edf7;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    cursor: pointer;
    text-decoration: none;
    font-family: inherit;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  }
  #mobile-block .mb-lang-switch:hover,
  #mobile-block .mb-lang-switch:focus-visible {
    background: #1565c0;
    border-color: #1565c0;
    color: #fff;
    outline: none;
  }
  #mobile-block .mb-globe { flex: none; opacity: 0.95; }
  #mobile-block .mb-icon {
    font-size: 56px;
    margin-bottom: 16px;
    display: block;
  }
  #mobile-block h2 {
    font-size: 22px;
    margin: 0 0 12px 0;
    color: #fff;
    line-height: 1.3;
  }
  #mobile-block p {
    margin: 12px 0;
    line-height: 1.55;
    font-size: 15px;
    color: #c5cbd6;
  }
  #mobile-block .mb-detail {
    font-size: 13px;
    color: #8b95a8;
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid rgba(255,255,255,0.06);
  }
  /* Activer si écran trop petit (<= 900px de largeur logique) */
  @media (max-width: 900px) {
    #mobile-block { display: flex; }
    body > *:not(#mobile-block) { display: none !important; }
  }

/* Boutons de la barre du haut : double espace entre l'icône et le texte */
.controls button > span[data-i18n] { margin-left: 0.3em; }

  /* ====== Bouton RETOUR (← vers le hub MammouthQuébec) ======
     Hérite du cercle 36 px de .restore-icon. Bordure et couleur d'accent
     pour l'apparenter visuellement au bouton de langue, juste à côté. */
  .nav-back-btn {
    border: 1px solid var(--text-accent);
    color: var(--text-accent);
  }
  .nav-back-btn:hover {
    background: var(--text-accent);
    color: #fff;
  }
  body.dark .nav-back-btn {
    border-color: var(--text-accent);
    color: var(--text-accent);
  }
  body.dark .nav-back-btn:hover {
    background: var(--bg-header-btn);
    border-color: var(--bg-header-btn);
    color: #fff;
  }
  /* Sous un overlay bloquant (Intro / Avis), garder le bouton retour
     visible et cliquable, exactement comme #lang-toggle. */
  body.has-blocking-modal #nav-back {
    visibility: visible;
    pointer-events: auto;
    background: var(--bg-panel, #fff);
    box-shadow: 0 4px 14px rgba(0,0,0,0.4);
  }
  body.dark.has-blocking-modal #nav-back {
    background: var(--bg-panel, #1a1f24);
    box-shadow: 0 4px 14px rgba(0,0,0,0.6);
  }

  /* ====== Bloc « Objectif du projet » dans la modale d'accueil ====== */
  .intro-objective {
    background: var(--bg-panel, #f7f9fc);
    border-left: 4px solid var(--text-accent, #1976d2);
    border-radius: 8px;
    padding: 14px 18px;
    margin: 6px 0 4px;
  }
  .intro-objective h2 { margin-top: 4px; }
  .intro-objective p:last-child { margin-bottom: 0; }
  body.dark .intro-objective { background: rgba(255,255,255,0.04); }
