/* ============================================================================
   AgroClimat — feuille de style principale
   ----------------------------------------------------------------------------
   1. JETONS DE DESIGN  : les couleurs, rayons, ombres et espacements de
      l'application sont nommés une fois dans assets/css/jetons.css (feuille
      partagée avec l'espace compte, chargée avant celle-ci) puis référencés
      partout. L'ACCENT de l'interface tient en UNE SEULE ligne (`--accent`) :
      voir le bloc encadré en tête de jetons.css.
   2. STRUCTURE         : mise en page, panneau de filtres, carte, pied de page.
   3. COMPOSANTS        : panneau de filtres refondu (section 12 ter, qui
      transpose la maquette validée « refonte-filtres »), recherche,
      chargement, documentation de l'indicateur.
   4. RESPONSIVE        : mobile (tiroir), tablette, desktop (repli).

   NETTOYAGE — l'ancien système d'étapes repliables a disparu du gabarit ; les
   règles qui le servaient ont été supprimées de cette feuille :
   .control-section / .active-section / .minimized-section / .section-content /
   .section-selection / .selection-description / .section-title /
   .category-header / .category-tab / .indicator-tab / .type-tab / .model-tab
   (remplacée par .mod) / .coming-soon / .main-categories /
   .specific-indicators / .model-tabs / .*-icon / .*-name / .model-desc /
   .model-unavailable / .indicator-tooltip / .category-tooltip /
   .tooltip-content / .full-width-select / .segmentSelect / .paramsection /
   .segment-level / .segment-group / .segment-label / .simulation-wrapper.
   Vérifié par grep sur *.php et *.js : aucune de ces classes n'est plus
   produite. style.css n'est chargée que par index.php (vérifié) ; les
   `.section-title` de user/*.php relèvent d'une autre feuille.
   ========================================================================== */


/* ============================================================================
   1. JETONS DE DESIGN
   ----------------------------------------------------------------------------
   POINTS DE RUPTURE (rappel — @media n'accepte pas var(), ces valeurs sont
   donc écrites en dur dans les media queries ; toute modification doit être
   répercutée aux trois endroits) :
       mobile   : max-width: 768px
       tablette : min-width: 769px et max-width: 1024px
       desktop  : min-width: 769px  (repli de la sidebar autorisé)
   ========================================================================== */
/* Les jetons (bloc racine, repli @supports color-mix, thèmes data-theme
   dark/light) vivent désormais dans assets/css/jetons.css, feuille PARTAGÉE
   avec l'espace compte et chargée AVANT cette feuille par index.php. Toute
   couleur, rayon, ombre ou espacement nommé se règle là-bas, jamais ici.  */


/* ============================================================================
   2. BASE
   ========================================================================== */
body {
  margin: 0;
  padding: 0;
  font-family: Arial, sans-serif;
  background: var(--fond-page);
}

/* ── Sélecteur de langue (menu déroulant) ────────────────────────────── */
.lang-toggle {
  position: relative;
  flex-shrink: 0;
  align-self: flex-end;
  margin-left: 13px;           /* +3px : décale le sélecteur vers la droite */
  margin-right: var(--espace-xl); /* -3px : réduit l'écart vers l'icône compte */
}
/* REFONTE — la pastille de langue héritait du fond bleu plein de
   `.sidebar button` : dans un en-tête blanc à une seule couleur d'interface,
   c'était le seul aplat de couleur de la zone. Elle devient une puce bordée
   neutre. Texte --encre-1 sur --panneau : 15,58:1 (clair) / 13,82:1 (sombre). */
.sidebar .lang-toggle .lang-btn {
  font-size: 12px;
  font-weight: 600;
  padding: 5px var(--espace-sm); /* harmonisé entre item courant et options */
  width: auto;
  margin: 0;
  opacity: 1;
  color: var(--encre-1);
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-controle);
  transition: opacity var(--duree-courte), background var(--duree-rapide), color var(--duree-rapide);
  box-sizing: border-box;
}

.sidebar .lang-toggle .lang-btn:hover {
  color: var(--encre-1);
  background: var(--accent-clair);
  border-color: var(--accent);
}

.sidebar .lang-toggle .lang-btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}
.sidebar .lang-toggle .lang-current {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.sidebar .lang-toggle .lang-caret {
  font-size: 10px;
  line-height: 1;
  transition: transform var(--duree-rapide);
}
.sidebar .lang-toggle.open .lang-caret {
  transform: rotate(180deg);
}
.sidebar .lang-toggle .lang-menu {
  position: absolute;
  top: 100%;                    /* collé sous le bouton courant, sans gap */
  right: 0;
  display: none;
  flex-direction: column;
  gap: 0;                       /* options collées les unes aux autres */
  z-index: 50;
  width: 100%;                  /* même largeur que le bouton courant */
}
.sidebar .lang-toggle.open .lang-menu {
  display: flex;
}
.sidebar .lang-toggle .lang-option {
  width: 100%;
  background: var(--panneau);
  color: var(--encre-1);
  border: 1px solid var(--trait-fort);
  border-radius: 0;
  text-align: center;
}
.sidebar .lang-toggle .lang-option + .lang-option {
  border-top: 0;                /* évite la double bordure entre items */
}
.sidebar .lang-toggle .lang-option:first-child {
  border-top-left-radius: var(--rayon-controle);
  border-top-right-radius: var(--rayon-controle);
}
.sidebar .lang-toggle .lang-option:last-child {
  border-bottom-left-radius: var(--rayon-controle);
  border-bottom-right-radius: var(--rayon-controle);
}
.sidebar .lang-toggle .lang-option:hover {
  background: var(--accent-clair);
  color: var(--encre-1);
}

/* ============================================================================
   3. STRUCTURE : mise en page et sidebar
   ========================================================================== */
#main-layout {
  display: flex;
  height: 100vh;
  min-height: 600px;
  margin: 0 auto;
  box-shadow: var(--ombre-panneau);
  background: var(--blanc);
  border-radius: var(--rayon-panneau);
  overflow: hidden;
}
/* REFONTE — le panneau devient une surface unie (--panneau) : le dégradé
   bleuté entrait en concurrence avec la carte et interdisait tout aplat
   pâle lisible pour l'état sélectionné.
   Le rembourrage HAUT passe à 0 : `.rail-tete` est collant (sticky) et
   déborde latéralement jusqu'aux bords du panneau (marges négatives), ce
   qui exige que rien ne le précède verticalement. Le rembourrage
   horizontal reste porté par `.sidebar` : si le gabarit ne fournit pas de
   `.rail-tete`, le contenu reste correctement margé.
   La police passe à la pile système, comme la maquette, et UNIQUEMENT ici :
   le reste de l'application garde Arial. */
.sidebar {
  width: var(--largeur-sidebar);
  background: var(--panneau);
  color: var(--encre-1);
  font: 15px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  padding: 0 var(--espace-2xl) var(--espace-3xl);
  display: flex;
  flex-direction: column;
  gap: 0;
  border-right: 1px solid var(--trait);
  box-sizing: border-box;
  max-height: 100vh;
  overflow-y: auto;
  /* margin-left est animé pour le repli desktop (voir la media query desktop) */
  transition: transform var(--duree-moyenne) ease, margin-left var(--duree-moyenne) ease;
  z-index: var(--plan-sidebar);
  box-shadow: var(--ombre-sidebar);
  overflow-x: hidden;
}

.sidebar label {
  font-weight: 600;
  font-size: 15px;
  color: var(--encre-titre);
}
.sidebar select, .sidebar button {
  width: 100%;
  font-size: 15px;
  margin-top: var(--espace-xs);
  margin-bottom: var(--espace-md);
  padding: var(--espace-sm) var(--espace-md);
  border-radius: var(--rayon-controle);
  border: 1px solid var(--bord-fort);
  background: var(--blanc);
  transition: border-color var(--duree-courte);
}
/* ATTENTION — RÈGLES GÉNÉRIQUES DE SPÉCIFICITÉ (0,1,1) ET (0,2,1).
   Elles s'appliquent à TOUT <button> et <select> du panneau. Elles ont déjà
   cassé l'affichage par le passé (tuiles devenues des aplats pleine largeur)
   quand les tuiles sont passées de <div> à <button>. Tout composant du
   panneau doit donc porter au moins DEUX classes de sélecteur — c'est ce que
   fait le préfixe `.sidebar` de la section 12 ter — et réécrire
   explicitement width, margin, padding, background, border et border-radius.
   Ces règles ne sont plus atteintes par aucun bouton du gabarit actuel
   (vérifié : .dom, .type-item, .mod, .jour, .btn, .lang-btn,
   .indicator-search-clear, .sidebar-erreur-retry, .indicator-doc-more et
   .account-chip ont tous leur propre règle) ; elles restent comme filet pour
   un bouton futur, désormais dans l'accent et non plus dans le bleu. */
.sidebar button {
  background: var(--accent);
  color: var(--sur-accent);        /* 6,34:1 clair · 7,72:1 sombre */
  border: none;
  font-weight: 600;
  cursor: pointer;
  margin-bottom: 0;
  margin-top: var(--espace-md);
  transition: background var(--duree-courte);
}
.sidebar button:hover {
  background: var(--accent);
}
.sidebar-actions {
  margin-top: 40px;
  display: flex;
  flex-direction: column;
  gap: var(--espace-md);
}

.sidebar-collapsed {
  transform: translateX(-100%);
}

/* Ascenseur de la sidebar */
.sidebar::-webkit-scrollbar {
  width: 6px;
}

.sidebar::-webkit-scrollbar-track {
  background: var(--fond-piste);
}

.sidebar::-webkit-scrollbar-thumb {
  background: var(--gris-clair);
  border-radius: var(--rayon-etiquette);
}

.sidebar::-webkit-scrollbar-thumb:hover {
  background: var(--gris-fort);
}

/* Sécurité : si le gabarit ne pose pas de `.rail-tete`, le premier enfant du
   panneau retrouve un rembourrage haut (le `.sidebar` n'en a plus). */
.sidebar > :first-child:not(.rail-tete) {
  margin-top: var(--espace-2xl);
}

/* Racine Vue. Elle devient la colonne de blocs de la maquette (`.rail-corps`) :
   un seul écart vertical, déclaré une fois, entre tous les `.bloc`.
   NE PAS lui donner `display:flex` sans l'exception `[v-cloak]` ci-dessous :
   la règle `[v-cloak] { display:none }` ne vaut que (0,1,0) et serait battue
   par cet identifiant (1,0,0) — les accolades Vue non compilées
   s'afficheraient pendant le montage. */
/* Écart entre cartes. Depuis que chaque groupe est une carte (fond teinté +
   filet, voir `.sidebar .bloc`), la séparation est portée par le contraste et
   non plus par le vide : l'écart peut donc se resserrer, ce qui compense
   exactement la place prise par le rembourrage interne des cartes. Le panneau
   gagne en lisibilité SANS gagner en hauteur. */
#controle_boutons {
  overflow-y: visible;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.5vh, 17px);
  padding-top: var(--espace-lg);
}

#controle_boutons[v-cloak] {
  display: none;
}


/* ============================================================================
   4. CARTE ET CONTRÔLES
   ========================================================================== */
.main-map {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
  min-width: 0;
  background: var(--fond-page);
}
#map {
  flex: 1;
  width: 100%;
  height: 100%;
  min-height: 600px;
  border-radius: 0 0 var(--rayon-panneau) 0;
  z-index: 1;
}
/* Bloc unique : les deux déclarations historiques de .controls sont fusionnées */
.controls {
  padding: 0;
  background: none;
  border: none;
}
h1 {
  margin: 0;
  padding: var(--espace-xl);
  background-color: var(--bleu-marque);
  color: var(--blanc);
}
.info {
  padding: var(--espace-xs) var(--espace-sm);
  font: 14px/16px Arial, Helvetica, sans-serif;
  background: var(--blanc);
  background: var(--voile-blanc-80);
  box-shadow: var(--ombre-info);
  border-radius: var(--rayon-infobulle);
}
.info h4 {
  margin: 0 0 5px;
  color: var(--gris-doux);
  max-width: 200px;
}
.legend {
  text-align: left;
  line-height: 18px;
  color: var(--gris-fort);
}
.legend i {
  width: 18px;
  height: 18px;
  float: left;
  margin-right: var(--espace-sm);
  opacity: 0.7;
}

.leaflet-control-zoom {
  position: absolute;
  top: 60px;
}

#opacityContainer {
  position: absolute;
  width: 200px;
  bottom: 27px;
  left: 130px;
  height: 50px;
  z-index: 10;
  color: var(--bleu-marque);
  background-color: var(--voile-blanc-50);
  border-radius: var(--rayon-large);
  padding: var(--espace-md) var(--espace-xl) var(--espace-3xl);
}
#opacityContainer p {
  margin: 0px 0px 8px;
  font-weight: bold;
  font-size: 12px;
}
.main-map .noUi-value {
  margin-top: 5px;
}

.noUi-pips, .noUi-value {
  color: var(--noir);
}

.noUi-horizontal {
  height: 9px;
}
.noUi-horizontal .noUi-handle {
  height: 20px;
  border: 1px solid var(--bleu-marque);
  cursor: pointer;
}
.noUi-handle:after, .noUi-handle:before {
  top: 2px;
  background: var(--bleu-marque);
}


/* ============================================================================
   5. CHARGEMENT (superposition bloquante)
   ========================================================================== */
.loading {
  position: fixed !important;
  top: 50vh; /* Utiliser vh au lieu de % */
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--voile-blanc-95);
  padding: 25px 35px;
  border-radius: var(--rayon-panneau);
  box-shadow: var(--ombre-chargement);
  z-index: 10001 !important;
  font-size: 16px;
  font-weight: 500;
  text-align: center;
  display: none;
  /* Ajout de propriétés pour assurer la compatibilité mobile */
  margin: 0;
  max-width: 80%; /* Limiter la largeur sur petits écrans */
  width: auto;
  pointer-events: auto; /* S'assurer que les interactions fonctionnent */
}

/* Style pour l'overlay */
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0; /* Assurer une couverture complète */
  bottom: 0; /* Assurer une couverture complète */
  width: 100%;
  height: 100%;
  z-index: 10000;
  display: none;
}

/* Gérer le défilement sur mobile quand l'overlay est visible */
body.loading-active {
  overflow: hidden;
  position: fixed;
  width: 100%;
  height: 100%;
}
.loading-spinner {
  border: 6px solid var(--fond-spinner);
  border-top: 6px solid var(--bleu-marque);
  border-radius: var(--rayon-rond);
  width: 40px;
  height: 40px;
  animation: spin 1.5s linear infinite;
  margin: var(--espace-xl) auto;
}

/* Déclaration UNIQUE de l'animation de rotation (elle existait en trois
   exemplaires identiques dans ce fichier). */
@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

#csvUrlInput {
  width: 60%;
}

/* Bouton d'application — déclaration unique (elle existait en double).
   Le bouton a été retiré du template ; la règle est conservée car elle sert
   de style générique aux boutons « verts » de l'application. */
.apply-button {
  background: linear-gradient(to bottom, var(--vert-marque) 0%, var(--vert-fonce) 100%);
  color: var(--blanc);
  border: none;
  padding: var(--espace-lg) var(--espace-3xl);
  border-radius: var(--rayon-controle);
  width: 100%;
  font-weight: 600;
  font-size: 15px;
  margin-top: var(--espace-3xl);
  cursor: pointer;
  transition: all var(--duree-moyenne) ease;
  box-shadow: var(--ombre-carte);
}

.apply-button:hover {
  background: linear-gradient(to bottom, var(--vert-clair) 0%, var(--vert-clair-fonce) 100%);
  box-shadow: var(--ombre-carte-survol);
}

.help-button {
  margin-top: var(--espace-3xl);
}

#downloadOverlay {
  margin: auto;
  padding-top: 5px;
}

#downloadOverlayButton {
  font-size: 16px;
  color: var(--blanc);
  background-color: var(--bleu-fonce);
  border: 0px;
  padding: var(--espace-2xs) var(--espace-md);
  border-radius: var(--rayon-bloc);
  cursor: pointer;
}
@keyframes dots {
  0%, 20% { content: ''; }
  40% { content: '.'; }
  60% { content: '..'; }
  80%, 100% { content: '...'; }
}


/* ============================================================================
   6. PIED DE PAGE
   ========================================================================== */
/* ============================================================================
   BAS DE PANNEAU — ce qui restait du pied de page

   Le bandeau faisait 350 px sous une carte qui occupe toute la fenêtre :
   personne ne descendait le voir, et il contenait un pavé d'avertissement en
   texte justifié plus des liens légaux en #bbb — 1,81:1 de contraste.

   Analyse de son contenu : la source du modèle était déjà affichée DEUX fois
   ailleurs (infobulle de la tuile, attribution de la carte), l'avertissement
   appartenait aux mentions légales, et le reste tient en quatre lignes. Elles
   sont ici, au bas de la colonne qui défile déjà — donc sans occuper d'espace
   tant qu'on ne descend pas jusqu'à elles.
   ========================================================================== */
.sidebar .panneau-pied {
  margin-top: var(--espace-lg);
  padding-top: var(--espace-lg);
  border-top: 1px solid var(--trait);
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--encre-3);
}

.sidebar .panneau-pied p {
  margin: 0 0 var(--espace-sm);
}

/* AVERTISSEMENT — petit corps, contraste plein.
   0,66 rem : le texte le plus petit du panneau, ce qui est cohérent avec son
   statut — il doit être lu, pas dominer. La couleur reste `--encre-2` (7,72:1)
   et non `--encre-3` (4,26:1) : en dessous de 4,5:1, un texte de cette taille
   n'est plus lisible pour beaucoup de gens, et un avertissement illisible ne
   remplit pas son office.
   Alignement à gauche, jamais justifié : dans une colonne de 326 px, la
   justification creuse des rivières blanches — c'était l'un des défauts de
   l'ancien bandeau. */
.sidebar .panneau-pied-avertissement {
  margin-bottom: var(--espace-md);
}

.sidebar .panneau-pied-avertissement p {
  margin: 0 0 var(--espace-xs);
  font-size: 0.66rem;
  line-height: 1.45;
  color: var(--encre-2);
  text-align: left;
}

.sidebar .panneau-pied-avertissement p:last-child {
  margin-bottom: 0;
}

.sidebar .panneau-pied p:last-child {
  margin-bottom: 0;
}

/* Les liens portent l'accent : sur un fond clair, le vert donne 5,97:1, quand
   le #bbb de l'ancien pied de page tombait à 1,81:1. */
.sidebar .panneau-pied a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.sidebar .panneau-pied a:hover {
  text-decoration: none;
}

.sidebar .panneau-pied a:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.sidebar .panneau-pied-liens {
  display: flex;
  flex-wrap: wrap;
  /* Le point médian est un SÉPARATEUR VISUEL, pas du texte : il est dessiné en
     ::before plutôt qu'écrit dans le gabarit, sinon un lecteur d'écran
     annoncerait « CGU point Confidentialité point ». */
  gap: 2px var(--espace-md);
  margin: 0 0 var(--espace-sm);
  padding: 0;
  list-style: none;
}

.sidebar .panneau-pied-liens li {
  position: relative;
  margin: 0;
}

.sidebar .panneau-pied-liens li + li::before {
  content: '·';
  position: absolute;
  left: calc(-1 * var(--espace-md) / 2 - 2px);
  color: var(--encre-3);
}

.sidebar .panneau-pied-mention {
  color: var(--encre-3);
}

/* Le lien devient un bloc de référence pour la mention « nouvel onglet ».
   SANS CELA, cette mention — en position: absolute — prend pour référence le
   bloc conteneur initial et non le panneau : elle échappe alors au découpage
   de `.sidebar` (overflow-y: auto) et se pose à sa position statique, tout en
   bas du contenu défilant. Le document passait de 800 à 1 714 px et la page
   se retrouvait avec 900 px de vide sous la carte. Constaté, mesuré, corrigé. */
.sidebar .panneau-pied a {
  position: relative;
}

/* Texte réservé aux lecteurs d'écran. Technique « visually hidden » standard,
   déjà employée pour l'étiquette du champ de recherche : l'élément garde sa
   place dans l'arbre d'accessibilité mais n'occupe aucun pixel. `display: none`
   ne conviendrait pas — il le retirerait aussi de la lecture. */
.hors-ecran {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


.noUi-pips-horizontal {
  padding: 0px 0;
  height: 24px;
  top: 100%;
  left: 0;
  width: 100%;
}

/* Style pour les checkboxes */
input[type="checkbox"] {
  accent-color: var(--accent);
  width: 18px;
  height: 18px;
  vertical-align: middle;
}

[v-cloak] { display: none; }


/* ============================================================================
   7. ÉCRAN D'ACCUEIL
   ========================================================================== */
#welcomeScreen {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9999;
}

/* Bloc unique : .welcome-container était déclaré deux fois. La seconde
   déclaration l'emportait sur le z-index (1000) ; cette valeur est conservée
   telle quelle — le conteneur est de toute façon enfant de #welcomeScreen
   (z-index 9999), qui porte seul l'empilement vis-à-vis du reste de la page. */
.welcome-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--voile-blanc-90);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  z-index: 1000;
  transition: opacity 0.8s ease, backdrop-filter 0.8s ease;
}

.welcome-container > div {
  background-color: var(--blanc);
  padding: 40px;
  border-radius: var(--rayon-panneau);
  box-shadow: var(--ombre-modale);
  max-width: 500px;
  width: 90%;
  text-align: center;
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.welcome-container.hide {
  opacity: 0;
  backdrop-filter: blur(0px);
  -webkit-backdrop-filter: blur(0px);
  pointer-events: none;
}

.welcome-container.hide > div {
  opacity: 0;
  transform: scale(0.95);
}

.welcome-logo {
  margin: auto;
  height: 70px;
  width: auto;
}

.welcome-byline {
  font-weight: bold;
  font-style: italic;
}

#welcome-loader {
  margin: var(--espace-3xl) auto;
}

#welcome-loader .spinner {
  width: 50px;
  height: 50px;
  margin: 0 auto;
  border: 4px solid rgba(var(--vert-marque-rvb), 0.2);
  border-radius: var(--rayon-rond);
  border-top-color: var(--vert-marque);
  animation: spin 1s ease-in-out infinite;
}

.welcome-enter-active, .welcome-leave-active {
  transition: all 0.5s ease;
}

.welcome-enter-from, .welcome-leave-to {
  opacity: 0;
  transform: translateY(20px);
}

.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from, .fade-leave-to {
  opacity: 0;
}

#closeWelcomeBtn:hover {
  color: var(--encre);
  transform: scale(1.2);
}


/* ============================================================================
   8. POIGNÉE DE REPLI ET SIMULATEUR DE TEMPÉRATURE
   ----------------------------------------------------------------------------
   Ce qui subsiste de l'ancienne section « sections de contrôles » : le bouton
   de repli du panneau, et les blocs du simulateur dont les identifiants sont
   imposés par simulateur-temperature.js. Leur mise en page à l'intérieur du
   bloc `.scenario` est reprise en section 12 ter.
   ========================================================================== */

/* Bouton de repli de la sidebar.
   Il est désormais affiché à TOUTES les largeurs (il était masqué de force
   au-dessus de 768px, ce qui rendait le repli impossible sur desktop).
   Sa position horizontale est ajustée par les media queries, avec !important
   car root.js pose un style inline sur `left`. */
#toggleControlsButton {
  display: flex;
  position: fixed;
  left: var(--espace-md);
  top: var(--espace-md);
  background: var(--accent);      /* poignée du panneau : couleur d'interface */
  color: var(--sur-accent);       /* 6,34:1 en clair, 7,72:1 en sombre        */
  width: 40px;
  height: 40px;
  border-radius: var(--rayon-rond);
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--ombre-bouton);
  z-index: var(--plan-bouton-menu);
  font-size: 24px;
  transition: all var(--duree-moyenne) ease;
}

.simulation-mode-container {
  display: flex;
  align-items: center;
  gap: var(--espace-md);
  padding: var(--espace-xl);
  background: var(--fond-section);
  border-radius: var(--rayon-bloc);
}
.simulation-mode-container label {
  cursor: pointer;
  font-weight: 500;
  user-select: none;
}
#enableSimulationMode {
  width: 18px;
  height: 18px;
  cursor: pointer;
}
.temperature-offset-container {
  display: none;
  flex-direction: column;
  margin-top: var(--espace-md);
  background: var(--fond-doux);
  border-radius: var(--rayon-bloc);
  padding: var(--espace-xl);
}
.temperature-offset-container.active {
  display: flex;
}
.slider-header {
  display: flex;
  align-items: center;
  margin-bottom: var(--espace-md);
}
#temperatureOffsetValue {
  margin-left: var(--espace-md);
  font-weight: bold;
  color: var(--bleu-marque);
}
#temperatureOffsetSlider {
  width: 100%;
  accent-color: var(--accent);
  margin-bottom: 5px;
}

.legend-container {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--gris);
}

.legend-item {
  display: flex;
  align-items: center;
  margin-bottom: 3px;
}

.legend-color {
  width: 15px;
  height: 15px;
  display: inline-block;
  margin-right: 5px;
}

#modelInfo {
  text-align: center;
  font-size: 12px;
  color: var(--gris-clair);
  font-style: italic;
  margin-top: var(--espace-xl);
}

#flash {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: var(--flash-succes);
  z-index: 1000;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
}

#toast {
  position: fixed;
  bottom: var(--espace-3xl);
  right: var(--espace-3xl);
  background-color: var(--couleur-succes);
  color: var(--blanc);
  padding: var(--espace-md) var(--espace-xl);
  border-radius: var(--rayon-petit);
  box-shadow: var(--ombre-toast);
  opacity: 0;
  transform: translateY(20px);
  transition: all var(--duree-moyenne) ease;
  z-index: 10000;
}


/* ============================================================================
   11. RECHERCHE D'INDICATEUR (dans .rail-tete)
   ----------------------------------------------------------------------------
   Structure posée par le gabarit :
       .indicator-search              conteneur (role="search")
         .indicator-search-label      libellé — masqué VISUELLEMENT (voir plus bas)
         .indicator-search-field      champ + bouton d'effacement
           .indicator-search-input    saisie
           .indicator-search-clear    bouton « × » (affiché si saisie)
         .indicator-search-results    <ul> des résultats
           .indicator-search-result   <li> (+ .active sur l'élément clavier)
             .indicator-search-name   libellé de l'indicateur
             .indicator-search-path   fil d'ariane
         .indicator-search-empty      message « aucun résultat »

   MAQUETTE — la recherche est « permanente et engageante, mais d'un poids
   visuel volontairement inférieur à la grille de domaines : un seul trait fin
   contre huit tuiles illustrées ». D'où : un champ de .87rem sur fond
   `--panneau-2`, sans libellé visible (le placeholder porte l'exemple concret),
   et le séparateur `.ou` juste en dessous qui nomme l'alternative.

   La liste de résultats reste DANS LE FLUX (et non en position:absolute) :
   dans un panneau en overflow-y:auto, un menu flottant serait rogné par le
   conteneur défilant. C'est la seule divergence assumée avec la maquette,
   qui est une page autonome sans conteneur défilant.
   ========================================================================== */
.sidebar .indicator-search {
  position: relative;
  margin: 11px 0 0;
}

/* Le libellé disparaît de l'œil mais PAS des technologies d'assistance :
   il reste le nom accessible du champ (le placeholder n'en est pas un).
   Technique standard « visually hidden ». */
.sidebar .indicator-search-label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.sidebar .indicator-search-field {
  position: relative;
  display: block;
}

/* La loupe est peinte en fond du champ : aucun balisage supplémentaire n'est
   requis, et la maquette la veut à 10px du bord gauche. Le SVG est en ligne
   (data:) — pas de requête réseau, compatible avec le déploiement FTP. */
.sidebar .indicator-search-input,
.sidebar .indicator-search input {
  width: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: 9px 30px 9px 31px;
  font: inherit;
  font-size: 0.87rem;
  color: var(--encre-1);
  background-color: var(--panneau-2);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237b8a80' stroke-width='1.6'%3E%3Ccircle cx='7' cy='7' r='4.5'/%3E%3Cpath d='M10.4 10.4 14 14' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 10px center;
  background-size: 14px 14px;
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-bloc);
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--duree-courte), background-color var(--duree-courte);
}

.sidebar .indicator-search-input::placeholder,
.sidebar .indicator-search input::placeholder {
  color: var(--encre-3);   /* 5,24:1 sur --panneau-2 */
  opacity: 1;              /* Firefox atténue les placeholders par défaut */
}

.sidebar .indicator-search-input:focus,
.sidebar .indicator-search input:focus {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  border-color: transparent;
  background-color: var(--panneau);
}

/* Bouton « × ». Il doit primer sur `.sidebar button` (fond plein, largeur
   100 %), d'où le sélecteur à deux classes. */
.sidebar .indicator-search-clear {
  position: absolute;
  top: 50%;
  right: 5px;
  transform: translateY(-50%);
  width: auto;
  height: auto;
  margin: 0;
  padding: 3px 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--encre-3);
  background: none;
  border: none;
  border-radius: var(--rayon-controle);
  cursor: pointer;
  transition: background-color var(--duree-rapide), color var(--duree-rapide);
}

.sidebar .indicator-search-clear:hover {
  background: var(--panneau-2);
  color: var(--encre-1);
}

.sidebar .indicator-search-clear:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* CORRECTIF CONSERVÉ — la liste était limitée en hauteur, mais RIEN
   n'indiquait qu'elle défilait : le dernier résultat visible était tranché net
   (les ascenseurs « overlay » de macOS restent invisibles au repos).
   Les trois signaux d'origine sont maintenus, mais exprimés avec les jetons
   du panneau pour rester justes en thème sombre :
     • hauteur maximale explicite laissant un résultat coupé en deux ;
     • voiles/ombres `background-attachment: local + scroll` ;
     • ascenseur toujours affiché. */
.sidebar .indicator-search-results {
  margin: 5px 0 0;
  padding: 0;
  list-style: none;
  max-height: 250px;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--trait-fort);
  border-radius: 9px;
  box-shadow: var(--ombre-douce);
  background:
    linear-gradient(var(--panneau) 30%, transparent) top / 100% 20px no-repeat local,
    linear-gradient(transparent, var(--panneau) 70%) bottom / 100% 24px no-repeat local,
    radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, 0.16), rgba(0, 0, 0, 0)) top / 100% 10px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.16), rgba(0, 0, 0, 0)) bottom / 100% 12px no-repeat scroll;
  background-color: var(--panneau);
  scrollbar-width: thin;
  scrollbar-color: var(--trait-fort) var(--panneau-2);
}

.sidebar .indicator-search-results::-webkit-scrollbar {
  width: 8px;
}

.sidebar .indicator-search-results::-webkit-scrollbar-track {
  background: var(--panneau-2);
  border-radius: var(--rayon-etiquette);
}

.sidebar .indicator-search-results::-webkit-scrollbar-thumb {
  background: var(--trait-fort);
  border-radius: var(--rayon-etiquette);
}

.sidebar .indicator-search-results::-webkit-scrollbar-thumb:hover {
  background: var(--encre-3);
}

/* Sécurité : une liste rendue vide ne laisse pas un cadre flottant. */
.sidebar .indicator-search-results:empty {
  display: none;
  border: none;
  box-shadow: none;
}

.sidebar .indicator-search-result {
  display: block;
  padding: 8px 11px;
  color: var(--encre-1);
  border-bottom: 1px solid var(--trait);
  cursor: pointer;
  scroll-margin: var(--espace-sm);   /* pour scrollIntoView au clavier */
  transition: background-color var(--duree-rapide);
}

.sidebar .indicator-search-result:last-child {
  border-bottom: none;
}

/* Élément actif de la navigation clavier : le gabarit pose `.active` ;
   `.is-active` et aria-selected sont acceptés pour la même raison. */
.sidebar .indicator-search-result:hover,
.sidebar .indicator-search-result.active,
.sidebar .indicator-search-result.is-active,
.sidebar .indicator-search-result[aria-selected="true"] {
  background-color: var(--accent-clair);
}

/* Liseré d'accent en plus : l'élément « au clavier » reste distinguable du
   simple survol souris. */
.sidebar .indicator-search-result.active,
.sidebar .indicator-search-result.is-active,
.sidebar .indicator-search-result[aria-selected="true"] {
  box-shadow: inset 3px 0 0 var(--accent);
}

/* Libellé de l'indicateur — 15,58:1 sur --panneau, 13,10:1 sur --accent-clair */
.sidebar .indicator-search-name {
  display: block;
  font-size: 0.84rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--encre-1);
}

/* Fil d'ariane (catégorie › type › paramètre) : plus petit et atténué.
   5,50:1 sur --panneau, 4,63:1 sur --accent-clair. */
.sidebar .indicator-search-path {
  display: block;
  margin-top: 2px;
  font-size: 0.72rem;
  line-height: 1.3;
  color: var(--encre-3);
}

/* Portion de texte correspondant à la saisie, si le gabarit la surligne. */
.sidebar .indicator-search-result mark {
  background: var(--accent-clair);
  color: inherit;
  padding: 0 1px;
  border-radius: 2px;
}

/* Message « aucun indicateur ne correspond ». */
.sidebar .indicator-search-empty {
  margin: 5px 0 0;
  padding: 13px;
  font-size: 0.84rem;
  line-height: 1.4;
  color: var(--encre-3);
  background: var(--panneau-2);
  border: 1px solid var(--trait);
  border-radius: 9px;
}


/* ============================================================================
   12. INDICATEUR DE CHARGEMENT DE LA CARTE
   ----------------------------------------------------------------------------
   Pastille discrète, en haut et au centre de la fenêtre, non bloquante.
   root.js le pilote par `el.style.display = visible ? '' : 'none'` : l'état
   « affiché » doit donc correspondre à la valeur définie ici, et l'état caché
   initial est posé par le template (style="display:none").
   La classe .map-loading-indicator est acceptée comme équivalent de l'id.
   ========================================================================== */
#mapLoadingIndicator,
.map-loading-indicator {
  /* Centrée sur la CARTE et non sur la fenêtre.
     « left: 50% » désignait le milieu de l'ÉCRAN ; avec 350 px de panneau à
     gauche, la pastille dérivait de 175 px vers la gauche de la carte et venait
     se poser sur la recherche de ville. Signalé.
     On ne peut pas l'ancrer sur `.main-map` : le gabarit la téléporte dans
     <body>, hors de la mise en page (voir le commentaire du teleport dans
     index.php). On décale donc son centre de la demi-largeur du panneau. */
  position: fixed;
  /* AU CENTRE DE LA CARTE, dans les deux sens.
     En haut, elle passait inaperçue : le regard est posé au milieu, là où sont
     les données. Elle vient donc s'y placer.
     Le centrage horizontal ne peut pas s'appuyer sur `.main-map` — le gabarit
     téléporte cet élément dans <body>, hors de la mise en page. On décale donc
     son centre de la demi-largeur du panneau ; les surcharges plus bas le
     ramènent au centre de la fenêtre quand le panneau est replié ou absent. */
  top: 50%;
  left: calc(50% + var(--largeur-sidebar) / 2);
  transform: translate(-50%, -50%);
  z-index: var(--plan-chargement-carte);
  display: flex;
  align-items: center;
  gap: var(--espace-md);
  padding: var(--espace-lg) var(--espace-2xl);
  border-radius: var(--rayon-bloc);
  /* Fond PLEIN et ombre portée franche. Au centre d'une carte désaturée, une
     pastille discrète se confondait avec le relief ; ce n'est plus une
     étiquette posée dans un coin mais l'objet qu'on regarde en attendant.
     `--accent` sur `--panneau` donne 6,34:1 en clair et 7,58:1 en sombre —
     l'ancien couple (bleu de marque sur blanc) ne donnait que 3,56:1. */
  background: var(--panneau);
  color: var(--accent);
  border: 1px solid var(--trait);
  font-size: 14px;
  font-weight: 640;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.18), 0 1px 3px rgba(0, 0, 0, 0.10);
  /* Reste TRAVERSANT : on continue de déplacer la carte pendant le calcul.
     C'est ce qui distingue cet indicateur de la fenêtre modale supprimée. */
  pointer-events: none;
}

/* Le rouet est un pseudo-élément : aucun balisage supplémentaire requis. */
/* ----------------------------------------------------------------------------
   ÉTAT DE CHARGEMENT DE LA CARTE

   Deux signaux, tous deux discrets, qui se lisent où que soit le regard :
   la carte se désature, et un filet court le long de son bord supérieur.

   La désaturation porte le sens à elle seule : elle dit « ce que vous voyez
   n'est plus d'actualité », ce qu'une étiquette de 200 px en haut d'un écran
   de 1 280 ne dit qu'à ceux qui la regardent. Elle reste donc active même en
   mouvement réduit, où seule l'animation du filet s'arrête.

   pointer-events reste intact : on continue de déplacer la carte pendant le
   calcul, qui prend 10 à 15 s.
   -------------------------------------------------------------------------- */
.main-map #map {
  transition: filter var(--duree-moyenne) ease;
}

.main-map.chargement #map {
  filter: saturate(0.45) opacity(0.75);
}

.main-map.chargement::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 2px;
  z-index: var(--plan-chargement-carte);
  background: linear-gradient(90deg,
    transparent 0%, var(--accent) 45%, var(--accent) 55%, transparent 100%);
  background-size: 45% 100%;
  background-repeat: no-repeat;
  animation: filet-chargement 1.15s ease-in-out infinite;
  pointer-events: none;
}

@keyframes filet-chargement {
  from { background-position: -45% 0; }
  to   { background-position: 145% 0; }
}

#mapLoadingIndicator::before,
.map-loading-indicator::before {
  content: '';
  width: 18px;
  height: 18px;
  flex: none;
  border: 2px solid var(--trait);
  border-top-color: var(--accent);
  border-radius: var(--rayon-rond);
  animation: spin 0.9s linear infinite;
}


/* ============================================================================
   12 bis. ÉTATS DE LA SIDEBAR ET ACCÈS À LA FICHE
   ----------------------------------------------------------------------------
   Classes posées par le gabarit depuis la phase 1 et qui n'avaient AUCUNE
   règle : elles s'affichaient donc avec les styles par défaut du navigateur
   (ou, pour les <button>, avec le bleu plein de `.sidebar button`).

       .sidebar-etat            « Chargement des indicateurs… »
       .sidebar-erreur          bloc d'erreur de l'arbre
       .sidebar-erreur-detail   message technique associé
       .sidebar-erreur-retry    bouton « Réessayer »
       .indicator-doc-actions   conteneur du bouton d'ouverture de la fiche
       .indicator-doc-more      bouton « En savoir plus »

   Les sélecteurs sont volontairement autonomes (aucune dépendance à
   l'imbrication exacte), le gabarit pouvant encore évoluer.
   ========================================================================== */

/* ── Chargement ──────────────────────────────────────────────────────────── */
.sidebar-etat {
  margin: 0;
  padding: var(--espace-md) var(--espace-lg);
  font-size: 13px;
  font-style: italic;
  color: var(--encre-2);           /* 7,82:1 clair · 7,82:1 sombre */
  background: var(--panneau-2);
  border-radius: var(--rayon-controle);
}

/* ── Erreur ──────────────────────────────────────────────────────────────── */
.sidebar-erreur {
  margin: 0;
  padding: var(--espace-lg) var(--espace-xl);
  font-size: 13px;
  line-height: 1.45;
  color: var(--encre-1);
  background: var(--panneau);
  border: 1px solid var(--trait);
  /* L'orange est SÉMANTIQUE (alerte) : il ne passe pas par --accent. */
  border-left: 4px solid var(--couleur-attention);
  border-radius: var(--rayon-controle);
  box-shadow: var(--ombre-fine);
}

.sidebar-erreur > p {
  margin: 0 0 var(--espace-sm);
  font-weight: 600;
}

/* Message technique : lisible mais secondaire, et il ne doit pas casser la
   largeur de la sidebar (une URL ou une trace peut être très longue). */
.sidebar-erreur-detail {
  margin: 0 0 var(--espace-lg);
  font-size: 12px;
  font-weight: normal;
  font-style: italic;
  color: var(--gris);
  overflow-wrap: break-word;
  word-break: break-word;
}

/* Bouton « Réessayer ». Le préfixe `.sidebar` neutralise la largeur de 100 %
   et les marges de `.sidebar button` : c'est une action de rattrapage, pas le
   bouton principal de la barre. */
.sidebar .sidebar-erreur-retry {
  width: auto;
  margin: 0;
  padding: var(--espace-xs) var(--espace-lg);
  font-size: 13px;
  font-weight: 600;
  color: var(--sur-accent);        /* 6,34:1 clair · 7,72:1 sombre */
  background: var(--accent);
  border: none;
  border-radius: var(--rayon-controle);
  cursor: pointer;
}

.sidebar .sidebar-erreur-retry:hover {
  color: var(--sur-accent);
  background: var(--accent);
}

.sidebar .sidebar-erreur-retry:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ── Accès à la fiche documentaire ───────────────────────────────────────── */
/* L'écart vertical vient désormais du `gap` de #controle_boutons : une marge
   propre s'y ajouterait. */
.indicator-doc-actions {
  display: flex;
  justify-content: center;
  margin: 0;
}

/* Bouton secondaire : la fiche est un complément, elle ne doit pas rivaliser
   visuellement avec les filtres.
   REFONTE — seules les COULEURS changent (le bleu de marque devenait la
   deuxième couleur d'interface d'un panneau qui n'en veut qu'une) ; la
   géométrie, le balisage et le comportement du panneau de documentation sont
   inchangés. Pour revenir au bleu, remplacer ici --accent/--accent-clair par
   --bleu-tres-fonce/--bleu-brume/--bleu-marque. */
.sidebar .indicator-doc-actions .indicator-doc-more,
.sidebar .indicator-doc-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-sm);
  width: 100%;
  margin: 0;
  padding: var(--espace-sm) var(--espace-lg);
  font-size: 0.81rem;
  font-weight: 600;
  color: var(--accent);            /* 5,33:1 sur --accent-clair (clair)
                                      6,07:1 (sombre)                    */
  background: var(--accent-clair);
  border: 1px solid var(--accent);
  border-radius: var(--rayon-bloc);
  cursor: pointer;
  transition: background-color var(--duree-courte), color var(--duree-courte);
}

.sidebar .indicator-doc-more:hover {
  color: var(--sur-accent);
  background: var(--accent);       /* 6,34:1 clair · 7,72:1 sombre */
  border-color: var(--accent);
}

.sidebar .indicator-doc-more:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.sidebar .indicator-doc-more i {
  font-size: 14px;
}


/* ============================================================================
   12 ter. PANNEAU DE FILTRES REFONDU (maquette « refonte-filtres »)
   ----------------------------------------------------------------------------
   Transposition fidèle de la maquette validée. Structure, du haut vers le bas :

       .sidebar
         .rail-tete            en-tête collant : .logo + .indicator-search
         .ou                   séparateur « ou parcourez le catalogue »
         .specimen             lecture de l'indicateur courant
         .bloc × n             .bloc-titre/.bloc-compteur + contenu
           .domaines > .dom    grille d'icônes, 4 colonnes
           .liste-types > .type-item
           .params > .champ
           .modeles > .mod
         .scenario             .jours-rail > .jour + .curseur-ligne
         .actions > .btn

   ─── POURQUOI TOUS LES SÉLECTEURS SONT PRÉFIXÉS `.sidebar` ────────────────
   `.sidebar select, .sidebar button` (section 3) valent (0,1,1) et
   `.sidebar button:hover` (0,2,1). Ils imposent width:100 %, des marges, un
   fond plein et du texte blanc. Une classe seule (0,1,0) perd contre eux :
   c'est exactement l'incident déjà survenu (« tuiles devenues bleues pleine
   largeur »). Le préfixe porte l'état de base à (0,2,0) et les états à
   (0,3,0) — suffisant dans les deux cas.
   NE PAS retirer ce préfixe. Ne pas non plus se contenter d'hériter :
   width, margin, padding, background, border et border-radius sont
   RÉÉCRITS explicitement sur chaque composant à base de <button>.

   ─── COULEURS ────────────────────────────────────────────────────────────
   Une seule couleur d'interaction : `--accent` (voir le bloc en tête de
   fichier). Les couleurs de l'échelle de risque appartiennent aux DONNÉES et
   ne passent jamais par `--accent` : elles arrivent en style inline depuis la
   base, cette feuille ne les touche pas.
   ══════════════════════════════════════════════════════════════════════ */

/* EN-TÊTE COLLANT.
   Le commentaire du panneau annonçait un en-tête « collant » depuis la
   refonte, mais aucune règle ne le rendait tel : il défilait avec le reste et
   le logo touchait le bord supérieur, faute de rembourrage haut sur `.sidebar`
   (laissé à 0 précisément pour cet en-tête).

   Il porte le logo, le sélecteur de langue, le compte et la recherche
   d'indicateur — c'est-à-dire l'identité et le seul moyen d'atteindre un
   indicateur directement. Ces éléments doivent rester accessibles quand on
   descend dans un panneau qui dépasse les 1 900 px.

   Les marges négatives le font déborder jusqu'aux bords du panneau, pour que
   son fond couvre toute la largeur pendant le défilement ; le rembourrage
   horizontal compense. */
.sidebar .rail-tete {
  position: sticky;
  top: 0;
  z-index: 3;
  margin: 0 calc(-1 * var(--espace-2xl));
  padding: var(--espace-lg) var(--espace-2xl) var(--espace-md);
  background: var(--panneau);
}

/* Trait de séparation permanent.
   Une première version ne l'affichait qu'une fois le panneau défilé, via une
   classe posée en JavaScript. Élégant sur le papier, mais l'écouteur s'est
   révélé peu fiable et un en-tête collant SANS séparation laisse le contenu
   glisser dessous sans frontière visible. Un filet d'un pixel ne coûte rien
   et ne peut pas tomber en panne. */
.sidebar .rail-tete {
  border-bottom: 1px solid var(--trait);
}

.sidebar .rail-tete .logo {
  display: flex;
  align-items: center;
  gap: var(--espace-sm);
  font-size: 1rem;
  font-weight: 760;
  letter-spacing: -0.02em;
  color: var(--encre-1);
}

/* La marque garde sa largeur naturelle à gauche ; les outils (langue,
   compte) sont poussés à droite par `margin-left:auto`. Le lien ne doit PAS
   être en `flex:1` : il s'étirerait sur toute la place libre. Il ne
   rétrécit pas non plus (flex-shrink 0) : la marque ne se tronque jamais —
   sur panneau étroit, ce sont les outils qui passent à la ligne (voir
   plus bas). */
.sidebar .rail-tete .logo-lien {
  display: block;
  flex: 0 0 auto;
  color: inherit;
  text-decoration: none;
  border-radius: var(--rayon-petit);
}

.sidebar .rail-tete .logo-lien:hover {
  color: inherit;
  text-decoration: none;
}

.sidebar .rail-tete .logo-lien:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* LA MARQUE, à la place de l'image du logo : le même en-tête que Mon espace
   (.compte-marque dans compte.css) — le nom du site en fort
   (« Agrométéorologie » / « Agroclimatologie »), et dessous la signature
   « un site AgroClimat2050 » en petit. Deux lignes, JAMAIS tronquées : ni
   ellipse, ni rognage. La signature reste sur mobile aussi — c'est là
   qu'on lit le moins bien de quel site il s'agit. */
.sidebar .rail-tete .rail-marque {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  letter-spacing: normal;
}

.sidebar .rail-tete .rail-marque strong {
  font-size: 0.95rem;
  font-weight: 760;
  letter-spacing: -0.02em;
  color: var(--encre-1);            /* 15,58:1 clair · 13,82:1 sombre */
  white-space: nowrap;
}

.sidebar .rail-tete .rail-marque small {
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--encre-3);            /* 5,50:1 clair · 5,85:1 sombre */
  white-space: nowrap;
}

/* PANNEAUX ÉTROITS (tiroir mobile de 300 px, panneau de 260 px sur
   tablette) : « Agrométéorologie » fait 131 px à 0,95 rem, et la ligne doit
   aussi loger la langue, le compte et la réserve de la poignée. Mesuré en
   375 px : la marque n'avait que 91 px, le nom était rogné.
   Trois choses, dans l'ordre :
   1. les marges du sélecteur de langue (13 + 15 px, réglées du temps de
      la puce API) sont retirées — le `gap` de .rail-outils suffit ;
   2. le nom descend à 0,84 rem (≈ 117 px), la signature à 0,64 rem, et
      celle-ci peut passer à la ligne au blanc (« un site » /
      « AgroClimat2050 ») si la place manque — à la ligne, jamais tronquée ;
      l'écart entre la marque et les outils tombe à 4 px (mesuré en 375 px :
      224 px pour tout loger, 117 + 4 + 97 = 218) ;
   3. filet de sécurité : si la marque ne tient vraiment pas à côté des
      outils (tiroir de 272 px sur un écran de 320 px, police système plus
      large), ce sont les outils qui passent à la ligne — la marque, elle,
      ne rétrécit jamais (flex-shrink 0 sur .logo-lien). */
@media (max-width: 1024px) {
  .sidebar .rail-tete .logo {
    flex-wrap: wrap;
    gap: 4px;
  }
  .sidebar .rail-tete .lang-toggle {
    margin-left: 0;
    margin-right: 0;
  }
  .sidebar .rail-tete .rail-marque strong {
    font-size: 0.84rem;
  }
  .sidebar .rail-tete .rail-marque small {
    font-size: 0.64rem;
    white-space: normal;
  }
}

.sidebar .rail-tete .rail-outils {
  margin-left: auto;
}

/* ── Infobulle des familles d'indicateurs ─────────────────────────────────
   Téléportée dans <body> et positionnée en `fixed` par le script : la barre
   latérale est en `overflow-y:auto` et rognerait un élément positionné en
   absolu. Apparition immédiate, sans le délai d'une seconde des infobulles
   natives du navigateur. */
.info-bulle {
  --largeur-infobulle: 260px;       /* doit correspondre à LARGEUR dans vue-app.js */
  position: fixed;
  z-index: var(--plan-panneau-doc, 1200);
  width: var(--largeur-infobulle);
  padding: 10px 12px;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--encre-1);
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-large);
  box-shadow: 0 4px 16px rgba(20, 40, 28, 0.14);
  pointer-events: none;             /* ne doit jamais voler le survol à l'icône */
}

@media (prefers-color-scheme: dark) {
  .info-bulle { box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5); }
}

/* ── Séparateur « ou parcourez le catalogue » ─────────────────────────────
   Il nomme la relation entre les deux chemins : ni titre, ni bouton. */
.sidebar .ou {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: 0.68rem;
  font-weight: 660;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--encre-3);            /* 5,50:1 clair · 5,85:1 sombre */
}

.sidebar .ou::before,
.sidebar .ou::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--trait);
}

/* ── Indicateurs suivis : passer de l'un à l'autre sans quitter la carte ──
   Liste #blocSuivis rendue par PHP (index.php), HORS de l'application Vue,
   entre l'en-tête collant et le séparateur « ou parcourez le catalogue » :
   le chemin le plus court vers ce que l'utilisateur a déjà choisi de
   suivre. UNE LIGNE PAR INDICATEUR, sur le modèle de la liste
   « Indicateur » (.liste-types / .type-item) : le nom en entier, et dessous
   le modèle et l'échéance. Les puces horizontales de la première version
   tronquaient les noms — refusées par le client.

   Structure :
       .bloc-suivis                 conteneur (padding haut = celui de
                                    #controle_boutons, qui suit)
         .bloc-titre                étiquette en petites capitales
         .suivi-liste               la liste (role=group), coins arrondis
           .suivi-item              <button aria-pressed> — une recherche
             .suivi-item-nom        le nom, sur une ligne (ellipse en
                                    dernier recours ; title = nom complet)
             .suivi-item-meta       « DMI · Demain »
         .suivi-tous                lien « Mon espace » ou « Voir les N
                                    indicateurs », sous la liste

   Les lignes sont des <button> : même préfixe `.sidebar` que les autres
   composants du panneau, et width/margin/padding/background/border
   réécrits, sans quoi la règle générique `.sidebar button` (aplat d'accent
   pleine largeur) les rattrape. Voir l'avertissement en tête de section. */
.sidebar .bloc-suivis {
  padding-top: var(--espace-lg);
}

/* Connecté sans indicateur suivi : le bloc existe (une première sauvegarde
   le dévoile sans recharger) mais ne doit rien montrer. Rappel explicite
   de `hidden` : la règle précédente, plus spécifique que celle du
   navigateur, l'emporterait sinon sur l'attribut. */
.sidebar .bloc-suivis[hidden] {
  display: none;
}

.sidebar .bloc-suivis .bloc-titre {
  margin-bottom: 6px;
}

/* Comme .liste-types, avec un filet VISIBLE : la liste des indicateurs est
   posée dans une carte teintée (.bloc) qui la détache déjà, celle-ci est
   posée à même le panneau blanc — sans filet, ses lignes flotteraient. */
.sidebar .suivi-liste {
  background: var(--panneau);
  border: 1px solid var(--trait);
  border-radius: 9px;
  overflow: hidden;                 /* pour que les coins arrondis rognent les lignes */
}

/* Une ligne au-delà des trois visibles reste dans le balisage (le script y
   lit la liste complète) mais ne s'affiche pas. Même rappel de `hidden`
   que pour le bloc : la règle ci-dessous est plus spécifique. */
.sidebar .suivi-item[hidden] {
  display: none;
}

/* Reprise de .type-item : rangée pleine largeur, nom en gras, seconde ligne
   en petit, filet entre les lignes, fond d'accent au survol, filet gauche
   d'accent + fond pâle sur la ligne active. min-height : 44 px, la ligne
   est une cible tactile quel que soit l'appareil. */
.sidebar .suivi-item {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 0;
  width: 100%;
  min-width: 0;
  max-width: none;
  min-height: 44px;
  margin: 0;
  padding: 7px 11px;
  font: inherit;
  font-weight: 400;
  color: var(--encre-1);
  text-align: left;
  background: var(--panneau);
  border: 0;
  border-bottom: 1px solid var(--trait);
  border-radius: 0;
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--duree-rapide);
}

.sidebar .suivi-item:last-child {
  border-bottom: 0;
}

/* Le dernier filet est celui de la ligne visible en dernier : une ligne
   cachée qui suit ne compte pas (le sélecteur :last-child, lui, la verrait).
   Règle À PART, et non jointe à la précédente : un navigateur qui ignore
   :has() rejette toute la liste de sélecteurs, et :last-child tomberait
   avec. Sans :has(), il reste au pire un filet de trop sous la troisième
   ligne. */
.sidebar .suivi-item:has(+ .suivi-item[hidden]) {
  border-bottom: 0;
}

.sidebar .suivi-item:hover {
  color: var(--encre-1);
  background: var(--accent-clair);
}

/* Décalage NÉGATIF : la liste est en overflow hidden, un anneau posé à
   l'extérieur serait rogné sur le premier et le dernier élément. */
.sidebar .suivi-item:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

/* Ligne active : indicateur ET modèle de la carte — le même marquage que
   la famille retenue dans la liste « Indicateur ». */
.sidebar .suivi-item[aria-pressed="true"] {
  background: var(--accent-clair);
  box-shadow: inset 3px 0 0 var(--accent);
}

/* Le nom tient sur UNE ligne ; les points de suspension ne viennent qu'en
   dernier recours, pour un nom plus long que le panneau (title = nom
   complet). text-overflow exige un bloc en overflow caché : d'où le
   display:block sur le <b>. */
.sidebar .suivi-item-nom {
  display: block;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 0.84rem;
  font-weight: 640;
  line-height: 1.3;
}

.sidebar .suivi-item-meta {
  display: block;
  margin-top: 2px;
  font-size: 0.71rem;
  line-height: 1.35;
  color: var(--encre-3);            /* 5,50:1 clair · 5,85:1 sombre
                                       4,63:1 / 4,69:1 sur --accent-clair */
}

/* Lien sous la liste, discret : « Mon espace », ou « Voir les N
   indicateurs » quand la liste n'en montre que trois. Hauteur de 32 px au
   pointeur fin, 44 px au doigt (voir plus bas). */
.sidebar .suivi-tous {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  margin-top: 4px;
  padding: 0 4px;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--accent);             /* 6,2:1 sur --panneau */
  text-decoration: none;
  border-radius: var(--rayon-petit);
}

.sidebar .suivi-tous:hover {
  text-decoration: underline;
}

.sidebar .suivi-tous:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* Cible tactile du lien : 44 px de haut dès que le pointeur est un doigt,
   et sous 768 px comme les autres commandes du panneau (voir la section
   RESPONSIVE, qui suit la même règle pour la langue et le compte). Les
   lignes font déjà 44 px partout. */
@media (pointer: coarse), (max-width: 768px) {
  .sidebar .suivi-tous {
    min-height: 44px;
  }
}

/* ── Spécimen : ce que l'on regarde en ce moment ──────────────────────────
   La légende de seuils remonte de la carte vers le panneau : on lit le sens
   des couleurs sans quitter des yeux le contrôle. */
.sidebar .specimen {
  overflow: hidden;
  background: var(--panneau-2);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-large);
}

.sidebar .specimen-tete {
  padding: 11px 12px 10px;
}

.sidebar .specimen-nom {
  font-size: 0.94rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.012em;
  color: var(--encre-1);            /* 14,85:1 clair · 14,70:1 sombre */
  text-wrap: balance;
}

.sidebar .specimen-meta {
  margin-top: 3px;
  font-size: 0.75rem;
  color: var(--encre-3);            /* 5,24:1 clair · 6,22:1 sombre */
}

/* Les bandes reçoivent leur couleur en style inline (données de l'échelle).
   Cette feuille ne fixe QUE la géométrie. */


/* Classe courante : liseré intérieur d'encre, pas d'accent — la mise en
   évidence porte sur une valeur de DONNÉE, pas sur une sélection d'interface. */




/* ── Bloc générique de filtres ─────────────────────────────────────────────
   L'écart vertical entre blocs vient du `gap` de #controle_boutons : aucun
   `margin` ici, sinon les deux se cumulent. */
/* Chaque groupe de filtres devient une carte : fond légèrement teinté, filet et
   rayon, comme le spécimen et le bloc d'échéance qui l'étaient déjà. Les
   contrôles (tuiles, listes, menus) restent blancs et ressortent donc sur ce
   fond — c'est ce contraste, et non l'espace vide, qui sépare désormais les
   groupes. L'écart entre cartes peut de ce fait être réduit sans que le panneau
   redevienne confus : voir le `gap` de #controle_boutons. */
.sidebar .bloc {
  min-width: 0;
  padding: 11px 12px 12px;
  background: var(--panneau-2);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-large);
}

.sidebar .bloc-titre {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--espace-sm);
  margin-bottom: 7px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--encre-3);            /* 5,50:1 clair · 5,85:1 sombre */
}

/* ── Étapes numérotées du panneau ─────────────────────────────────────────
   Retour de Jérôme (PAESI) du 30 septembre 2026, maquette à l'appui : sans
   les numéros ni les verbes de la v1, « on comprend moins bien la cinématique
   du menu de sélection ». Chaque bloc de choix porte donc son rang (calculé
   par `etapes`, vue-app.js — le bloc Paramètres n'existe pas partout) et un
   intitulé à l'impératif, dans la typographie du panneau (petites capitales
   espacées, inchangée).

   L'étape EN COURS — la première dont le choix n'est pas fait — reprend la
   proposition de sa maquette : son intitulé devient un BANDEAU PLEIN vert en
   tête de la carte, qui déborde du rembourrage par des marges négatives et
   épouse les coins hauts. C'est le seul point d'appel du panneau, le bouton
   de soutien ayant été ramené à un liseré (social-media.css).

   Ratios mesurés : --encre-3 sur --panneau-2 5,24:1 (intitulé au repos),
   --sur-accent sur --accent 6,34:1 (bandeau de l'étape en cours). */
.sidebar .bloc-titre .etape {
  display: flex; align-items: baseline; gap: 6px; min-width: 0;
  /* Moins d'interlettrage que les anciens intitulés d'un mot : « 1. CHOISISSEZ
     UN DOMAINE » et son compteur passent alors sur une seule ligne dans un
     panneau de 280 px. Mesuré, pas supposé. */
  letter-spacing: 0.05em;
}
.sidebar .etape-num { font-variant-numeric: tabular-nums; }

.sidebar .bloc-etape.etape-active { border-color: var(--accent); }
/* Le bandeau : marges négatives = rembourrage du bloc (11px 12px), pour aller
   d'un bord à l'autre ; le rayon reprend celui de la carte moins le filet. */
.sidebar .bloc-etape.etape-active > .bloc-titre {
  margin: -11px -12px 9px;
  padding: 7px 12px 6px;
  background: var(--accent);
  color: var(--sur-accent);
  border-radius: calc(var(--rayon-large) - 1px) calc(var(--rayon-large) - 1px) 0 0;
}
.sidebar .bloc-etape.etape-active > .bloc-titre .bloc-compteur { color: var(--sur-accent); }

.sidebar .bloc-compteur {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Domaines : les huit d'un seul regard ─────────────────────────────────
   Grille d'icônes compacte. Remplace les grandes tuiles empilées qui
   imposaient quatre lignes et un défilement. */
.sidebar .domaines {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 5px;
}

.sidebar .dom {
  width: auto;
  min-width: 0;
  max-width: none;
  margin: 0;
  /* Interligne resserré : le libellé passe souvent sur deux lignes
     (« Pratiques agricoles », « Sécheresse ») et toutes les tuiles s'alignent
     sur la plus haute. Quelques pixels par ligne, multipliés par deux rangées,
     suffisent à faire tenir les boutons d'action à l'écran. */
  padding: 6px 3px 5px;
  line-height: 1.15;
  font: inherit;
  font-weight: 400;
  line-height: normal;
  color: var(--encre-1);
  text-align: center;
  background: var(--panneau);
  border: 1px solid var(--trait);
  border-radius: 9px;
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--duree-rapide),
              border-color var(--duree-rapide),
              box-shadow var(--duree-rapide);
}

.sidebar .dom:hover {
  color: var(--encre-1);
  background: var(--accent-clair);
  border-color: var(--accent);
}

.sidebar .dom:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* Sélection : fond pâle d'accent + double bordure d'accent (le box-shadow
   intérieur épaissit le trait sans décaler la grille d'un pixel). */
.sidebar .dom[aria-pressed="true"] {
  background: var(--accent-clair);
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.sidebar .dom-icone {
  display: block;
  font-size: 1.05rem;
  line-height: 1.15;
}

.sidebar .dom-libelle {
  display: block;
  margin-top: 2px;
  font-size: 0.6rem;
  line-height: 1.15;
  color: var(--encre-2);            /* 8,21:1 clair · 7,36:1 sombre */
  overflow-wrap: anywhere;          /* « Sécheresse » dans 76px */
}

.sidebar .dom[aria-pressed="true"] .dom-libelle {
  color: var(--encre-1);            /* 13,10:1 clair · 11,07:1 sombre */
  font-weight: 660;
}

.sidebar .dom-nombre {
  display: block;
  font-size: 0.56rem;
  color: var(--encre-3);            /* 5,50:1 clair · 5,85:1 sombre
                                       4,63:1 / 4,69:1 sur --accent-clair */
  font-variant-numeric: tabular-nums;
}

/* Domaine sans indicateur disponible (« à venir »). Le libellé RESTE lisible :
   l'opacité globale de 0,4 d'autrefois faisait tomber le texte à 2,3:1 alors
   que la tuile restait focalisable. Seule l'icône est atténuée. */
.sidebar .dom[aria-disabled="true"],
.sidebar .dom.disabled {
  opacity: 1;
  background: var(--panneau-2);
  border-color: var(--trait);
  cursor: not-allowed;
}

.sidebar .dom[aria-disabled="true"]:hover,
.sidebar .dom.disabled:hover {
  background: var(--panneau-2);
  border-color: var(--trait);
}

.sidebar .dom[aria-disabled="true"] .dom-icone,
.sidebar .dom.disabled .dom-icone {
  opacity: 0.45;
}

/* La description du domaine s'affiche SOUS la grille, en clair. Elle
   remplace l'infobulle au survol, rognée en haut de panneau et inutilisable
   sur tablette. */
.sidebar .dom-description {
  margin: var(--espace-sm) 0 0;
  font-size: 0.75rem;
  line-height: 1.45;
  color: var(--encre-2);            /* 8,21:1 clair · 7,36:1 sombre */
}

/* ── Indicateurs : liste lisible, une ligne par famille ───────────────────── */
/* Pas de défilement interne EN DESKTOP : un panneau qui défile ET une liste qui
   défile à l'intérieur, c'est une zone morte où l'utilisateur ne sait plus ce
   qu'il fait bouger. Sept familles au maximum (Végétaux), une ligne chacune :
   la liste tient. La description de la famille retenue est affichée dans le
   bloc du haut, comme pour les domaines.
   En mobile et en tablette, la hauteur disponible impose en revanche un
   plafond : les media queries concernées posent alors `overflow-y: auto` en
   même temps que `max-height`. Un plafond sans défilement rendait les
   dernières familles purement inatteignables — ni ascenseur, ni molette, ni
   indice visuel. */
/* Pas de filet propre : la carte qui contient la liste l'encadre déjà. Un bloc
   blanc à coins arrondis sur le fond teinté de la carte suffit à la détacher,
   et évite le filet dans un filet. */
.sidebar .liste-types {
  background: var(--panneau);
  border: 1px solid var(--trait);
  border-color: transparent;
  border-radius: 9px;
  overflow: hidden;                 /* pour que les coins arrondis rognent les lignes */
}

/* Ce que mesure l'indicateur retenu, dans le bloc du haut. Remplace l'échelle
   de couleurs qui y figurait : celle-ci répétait la légende de la carte, déjà
   affichée en permanence en bas à droite. */
.sidebar .specimen-description {
  margin: 0;
  padding: 0 12px 11px;
  font-size: 0.75rem;
  line-height: 1.45;
  color: var(--encre-2);
}

/* ── « Suivre cet indicateur », dans la fiche ─────────────────────────────
   Petit bouton en pilule sous la description : la même action qu'au bas du
   panneau, mais à l'endroit où l'on vient de lire ce que l'on regarde.
   Sélecteur à trois classes (0,3,0) : il doit battre `.sidebar .btn`
   (display:flex, width:100 %) quel que soit l'ordre des règles, y compris
   sa variante mobile. */
.sidebar .specimen-actions {
  padding: 0 12px 11px;
}

.sidebar .btn.specimen-suivre {
  display: inline-flex;
  width: auto;
  min-height: 32px;
  padding: 4px 12px;
  font-size: 0.78rem;
  border-radius: var(--rayon-pilule);
}

/* État « Suivi » : aplat pâle d'accent, icône pleine, et DÉSACTIVÉ — c'est
   un constat, l'action est portée par la ligne active de la liste des
   indicateurs suivis (.suivi-item[aria-pressed="true"]). Couleur et
   opacité sont réaffirmées : un bouton désactivé prend sinon le gris du
   navigateur (GrayText), sous le seuil de contraste. Ici --accent sur
   --accent-clair : 5,3:1. */
.sidebar .btn.specimen-suivre.est-suivi,
.sidebar .btn.specimen-suivre.est-suivi:disabled,
.sidebar .btn.specimen-suivre.est-suivi:hover {
  color: var(--accent);
  background: var(--accent-clair);
  border-color: var(--accent);
  opacity: 1;
  cursor: default;
}

/* Cible tactile de 44 px, comme les lignes de la liste des indicateurs
   suivis (.suivi-item, 44 px partout) et son lien. Déclarée APRÈS la
   règle de base, de même spécificité : placée plus haut dans la feuille,
   elle perdrait à l'ordre de la cascade. */
@media (pointer: coarse), (max-width: 768px) {
  .sidebar .btn.specimen-suivre {
    min-height: 44px;
  }
}

/* Icône d'information des lignes d'indicateur. Elle porte l'infobulle : c'est
   elle qu'on survole, et sa seule présence annonce qu'une explication existe.
   Discrète au repos, elle s'affirme au survol de la ligne pour inviter au
   geste. `pointer-events:auto` explicite : l'infobulle native doit se
   déclencher sur l'icône même si la ligne est désactivée (aria-disabled). */
.sidebar .info-icone {
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  margin-left: auto;
  font-size: 0.66rem;
  font-weight: 700;
  font-style: italic;
  font-family: Georgia, "Times New Roman", serif;
  line-height: 1;
  color: var(--encre-3);
  cursor: help;
  pointer-events: auto;
  background: transparent;
  border: 1px solid var(--trait-fort);
  border-radius: 50%;
  transition: color var(--duree-rapide), border-color var(--duree-rapide),
              background-color var(--duree-rapide);
}

.sidebar .type-item:hover .info-icone,
.sidebar .type-item:focus-visible .info-icone {
  color: var(--accent);
  border-color: var(--accent);
}

.sidebar .info-icone:hover {
  color: var(--sur-accent, #fff);
  background: var(--accent);
  border-color: var(--accent);
}

.sidebar .type-item {
  /* Rangée et non bloc : le libellé à gauche, l'icône d'information poussée à
     droite par `margin-left:auto`. */
  display: flex;
  align-items: center;
  gap: var(--espace-sm);
  width: 100%;
  min-width: 0;
  max-width: none;
  margin: 0;
  padding: 8px 11px;
  font: inherit;
  font-weight: 400;
  color: var(--encre-1);
  text-align: left;
  background: var(--panneau);
  border: 0;
  border-bottom: 1px solid var(--trait);
  border-radius: 0;
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--duree-rapide);
}

.sidebar .type-item:last-child {
  border-bottom: 0;
}

.sidebar .type-item:hover {
  color: var(--encre-1);
  background: var(--accent-clair);
}

/* Décalage NÉGATIF : la liste est en overflow hidden, un anneau posé à
   l'extérieur serait rogné sur le premier et le dernier élément. */
.sidebar .type-item:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

.sidebar .type-item[aria-pressed="true"] {
  background: var(--accent-clair);
  box-shadow: inset 3px 0 0 var(--accent);
}

.sidebar .type-item b {
  display: block;
  font-size: 0.84rem;
  font-weight: 640;
  line-height: 1.3;
}

.sidebar .type-item small {
  display: block;
  margin-top: 2px;
  font-size: 0.71rem;
  line-height: 1.35;
  color: var(--encre-3);            /* 5,50:1 clair · 5,85:1 sombre
                                       4,63:1 / 4,69:1 sur --accent-clair */
}

.sidebar .type-item[aria-disabled="true"],
.sidebar .type-item.disabled {
  background: var(--panneau-2);
  cursor: not-allowed;
}

.sidebar .type-item[aria-disabled="true"]:hover,
.sidebar .type-item.disabled:hover {
  background: var(--panneau-2);
}

/* ── Paramètres : listes déroulantes toujours visibles ────────────────────
   `.sidebar .champ label` vaut (0,2,1) : il prime sur `.sidebar label`
   (0,1,1), qui imposerait 15px et l'encre des titres.
   `.sidebar .champ select` vaut (0,2,1) : il prime sur `.sidebar select`
   (0,1,1), qui imposerait des marges et un rayon différents. */
/* Chaque champ est un CHOIX DISTINCT (l'espèce, puis le stade, puis la variété).
   L'écart entre deux champs doit donc être nettement supérieur à l'écart entre
   un libellé et son propre menu, sinon l'œil ne rattache plus le bon libellé au
   bon menu et les paramètres paraissent collés. */
.sidebar .params {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.sidebar .champ {
  min-width: 0;
}

.sidebar .champ label {
  display: block;
  margin-bottom: 5px;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--encre-2);            /* 8,21:1 clair · 7,36:1 sombre */
}

.sidebar .champ select {
  width: 100%;
  margin: 0;
  padding: 7px 9px;
  font: inherit;
  font-size: 0.84rem;
  color: var(--encre-1);
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: 7px;
}

.sidebar .champ select:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ----------------------------------------------------------------------------
   PARAMÈTRES — boutons segmentés, valeur figée, filtre de liste

   Neuf sélecteurs sur dix du catalogue proposent trois options ou moins. Pour
   ceux-là, la liste déroulante demandait deux gestes et masquait des options
   qui tenaient à l'écran. Voir modeChamp() dans vue-app.js pour la règle.
   -------------------------------------------------------------------------- */

/* L'intitulé n'est plus toujours un <label> : un groupe de boutons n'a pas de
   contrôle unique à étiqueter, il est décrit par aria-labelledby. Les deux
   présentations doivent rester visuellement identiques. */
.sidebar .champ-etiquette {
  display: block;
  margin-bottom: 5px;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--encre-2);
}

/* Valeur imposée (un seul choix possible) : présentée comme une information,
   sans bordure ni affordance de clic, pour ne pas laisser croire à un contrôle
   qui ne répondrait pas. */
.sidebar .champ-fige {
  margin: 0;
  padding: 6px 0 0;
  font-size: 0.84rem;
  color: var(--encre-1);
}

/* Grille et non flex : avec `flex: 1 1 auto`, un seul libellé long — « 0 à
   200 cm (zone racinaire) » — suffisait à faire passer chaque bouton sur sa
   propre ligne, puis à l'étirer sur toute la largeur. Mesuré : quatre options
   sur quatre rangées de 244 px. Des colonnes automatiques donnent une largeur
   régulière quel que soit le plus long des libellés, et laissent celui-ci
   passer sur deux lignes plutôt que d'imposer sa loi aux autres. */
.sidebar .segmente {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--espace-2xs);
}

.sidebar .segmente button {
  min-width: 0;
  padding: 7px 9px;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.25;
  color: var(--encre-1);
  text-align: center;
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: 7px;
  cursor: pointer;
  transition: background-color var(--duree-rapide), border-color var(--duree-rapide);
}

.sidebar .segmente button:hover {
  /* Le fond DOIT être redéclaré. La règle générale `.sidebar button:hover`
     pose un aplat d'accent ; ne surcharger que la bordure laissait un fond
     vert sous un texte sombre — 1,9:1 au contraste, illisible. Signalé. */
  background: var(--panneau);
  border-color: var(--accent);
}

.sidebar .segmente button:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* Option retenue : même aplat d'accent que l'échéance choisie, pour que le
   « c'est celui-là » se lise de la même façon partout dans le panneau. */
.sidebar .segmente button[aria-checked="true"] {
  color: var(--sur-accent);
  font-weight: 640;
  background: var(--accent);
  border-color: var(--accent);
}

/* Option pas encore disponible. Le libellé RESTE lisible — c'est une
   information, pas un élément décoratif : seul le fond signale l'inactivité. */
.sidebar .segmente button.indisponible {
  color: var(--encre-3);
  background: var(--panneau-2);
  border-style: dashed;
  cursor: not-allowed;
}

.sidebar .segmente button.indisponible:hover {
  border-color: var(--trait-fort);
}

.sidebar .segmente button small {
  display: block;
  font-size: 0.62rem;
  color: var(--encre-3);
}

/* ----------------------------------------------------------------------------
   SÉLECTEUR À RECHERCHE INTÉGRÉE (plus de 9 options)

   Un champ de filtre posé AU-DESSUS d'une liste native donnait deux contrôles
   empilés pour un seul choix : on ne savait plus lequel manipuler. Ici, un seul
   contrôle, qui affiche la valeur retenue et s'ouvre sur une liste filtrable.

   La liste se déploie EN PLACE et non en surcouche flottante : le panneau
   latéral est en overflow-y:auto et rognerait un élément positionné en absolu —
   c'est le défaut qui avait déjà coûté les infobulles de l'ancienne interface.
   -------------------------------------------------------------------------- */
.sidebar .combo {
  position: relative;
}

.sidebar .combo-declencheur {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-sm);
  width: 100%;
  padding: 7px 9px;
  font: inherit;
  font-size: 0.84rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--encre-1);
  text-align: left;
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: 7px;
  cursor: pointer;
}

.sidebar .combo-declencheur:hover {
  background: var(--panneau);   /* voir .segmente button:hover : même piège */
  border-color: var(--accent);
}

.sidebar .combo-declencheur:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.sidebar .combo.ouvert .combo-declencheur {
  border-color: var(--accent);
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* Aucune valeur retenue : le texte d'invite ne doit pas se confondre avec un
   choix réel. */
.sidebar .combo-valeur.vide { color: var(--encre-3); }

.sidebar .combo-fleche {
  flex: 0 0 auto;
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--encre-2);
}

.sidebar .combo.ouvert .combo-fleche {
  border-top: 0;
  border-bottom: 5px solid var(--accent);
}

.sidebar .combo-panneau {
  border: 1px solid var(--accent);
  border-top: 0;
  border-radius: 0 0 7px 7px;
  background: var(--panneau);
  overflow: hidden;
}

.sidebar .combo-recherche {
  box-sizing: border-box;
  width: 100%;
  padding: 7px 9px;
  font: inherit;
  font-size: 0.8rem;
  color: var(--encre-1);
  background: var(--panneau-2);
  border: 0;
  border-bottom: 1px solid var(--trait);
}

.sidebar .combo-recherche:focus { outline: none; }

.sidebar .combo-liste {
  /* Plafond volontaire : sans lui, 98 cultures pousseraient tout le reste du
     panneau hors de vue à chaque ouverture. */
  max-height: 210px;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}

.sidebar .combo-option {
  display: flex;
  align-items: baseline;
  gap: var(--espace-sm);
  padding: 8px 9px;
  font-size: 0.82rem;
  color: var(--encre-1);
  cursor: pointer;
}

.sidebar .combo-option.actif { background: var(--accent-clair); }

.sidebar .combo-option[aria-selected="true"] {
  font-weight: 640;
  color: var(--accent);
}

/* Option pas encore disponible : le libellé RESTE lisible, seul le curseur et
   la mention « à venir » signalent qu'elle ne répondra pas. */
.sidebar .combo-option.indisponible {
  color: var(--encre-3);
  cursor: not-allowed;
}

.sidebar .combo-option small {
  margin-left: auto;
  font-size: 0.68rem;
  color: var(--encre-3);
  white-space: nowrap;
}

.sidebar .combo-vide {
  padding: 10px 9px;
  font-size: 0.8rem;
  color: var(--encre-3);
}

/* Cibles tactiles : une option de 8 px de rembourrage se vise mal au doigt. */
@media (max-width: 768px) {
  .sidebar .combo-declencheur { min-height: 44px; }
  .sidebar .combo-option { padding: 12px 9px; }
}

/* ── Modèles météo ────────────────────────────────────────────────────────── */
.sidebar .modeles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 5px;
}

.sidebar .mod {
  width: auto;
  min-width: 0;
  max-width: none;
  margin: 0;
  padding: 7px 8px;
  font: inherit;
  font-weight: 400;
  line-height: normal;
  color: var(--encre-1);
  text-align: left;
  background: var(--panneau);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-bloc);
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--duree-rapide), border-color var(--duree-rapide);
}

.sidebar .mod:hover {
  color: var(--encre-1);
  background: var(--panneau);
  border-color: var(--accent);
}

.sidebar .mod:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.sidebar .mod[aria-pressed="true"] {
  background: var(--accent-clair);
  border-color: var(--accent);
}

.sidebar .mod b {
  display: block;
  /* Place réservée à l'icône d'information, épinglée en haut à droite : sans
     ce retrait, les noms longs (« SIM2 — Humidité des sols ») passeraient
     dessous. */
  padding-right: 18px;
  font-size: 0.8rem;
  font-weight: 680;
}

/* ORIGINE DU MODÈLE — l'icône est épinglée dans le coin plutôt que posée dans
   le flux : la tuile empile nom, description et horizon en blocs, et une icône
   dans ce flux occuperait une ligne à elle seule. `margin-left: auto`, hérité
   de la règle générale conçue pour une ligne flex, n'a plus de sens ici. */
.sidebar .mod {
  position: relative;
}

.sidebar .mod .info-icone {
  position: absolute;
  top: 6px;
  right: 6px;
  margin-left: 0;
}

/* Même révélation au survol que pour les familles d'indicateurs : discrète au
   repos, elle prend l'accent dès que la tuile est survolée. */
.sidebar .mod:hover .info-icone,
.sidebar .mod:focus-visible .info-icone {
  color: var(--accent);
  border-color: var(--accent);
}

.sidebar .mod small {
  display: block;
  font-size: 0.67rem;
  line-height: 1.3;
  color: var(--encre-3);            /* 5,50:1 clair · 5,85:1 sombre */
}

/* Horizon du modèle : c'est le seul chiffre qui porte l'accent, parce qu'il
   commande directement le rail des échéances juste en dessous. */
.sidebar .mod-jours {
  display: block;
  font-size: 0.67rem;
  font-weight: 640;
  color: var(--accent);             /* 6,34:1 clair · 7,58:1 sombre
                                       5,33:1 / 6,07:1 sur --accent-clair */
  font-variant-numeric: tabular-nums;
}

.sidebar .mod[aria-disabled="true"],
.sidebar .mod.disabled {
  background: var(--panneau-2);
  border-color: var(--trait);
  cursor: not-allowed;
}

.sidebar .mod[aria-disabled="true"]:hover,
.sidebar .mod.disabled:hover {
  background: var(--panneau-2);
  border-color: var(--trait);
}

/* ── Scénario : échéance + correction de température ───────────────────── */
.sidebar .scenario {
  padding: 11px 12px;
  background: var(--panneau-2);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-large);
}

.sidebar .scenario .bloc-titre {
  margin-bottom: var(--espace-xs);
}

/* RETOUR À LA LIGNE, ni compression ni défilement.
   Les tuiles ne peuvent pas être comprimées : avec `flex:1`, les modèles longs
   (GFS 240 h, ECMWF 216 h, CZ-GLOBE 228 h) les réduisaient à 26 px et
   « Demain » devenait illisible — 20 px disponibles pour 44 px de texte, pire
   en anglais (« Tomorrow ») ou en allemand (« Morgen »).
   Le défilement horizontal qui avait été retenu à la place s'est révélé pire :
   macOS masque les barres de défilement, et une souris sans molette latérale ne
   peut pas atteindre la droite du rail. Depuis l'ouverture des jours passés,
   GFS en compte 12 : la moitié était donc INATTEIGNABLE.
   Une grille à colonnes automatiques garde des tuiles lisibles ET rend chaque
   jour cliquable sans geste particulier. Trois rangées au pire, dans un panneau
   qui défile déjà verticalement. */
.sidebar .jours-rail {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(3.4rem, 1fr));
  gap: var(--espace-2xs);
}

.sidebar .jour {
  min-width: 0;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 5px 2px;
  font: inherit;
  font-weight: 400;
  line-height: normal;
  color: var(--encre-1);            /* 15,58:1 clair · 13,82:1 sombre */
  text-align: center;
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: 7px;
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--duree-rapide), border-color var(--duree-rapide);
}

/* JOURS PASSÉS — de l'analyse, pas de la prévision.
   Fond légèrement creusé et bordure en pointillés : la rangée se lit alors en
   deux temps, ce qui est derrière puis ce qui est devant. C'est ce qui explique
   d'un coup d'œil qu'un modèle « 2 jours d'horizon » propose quatre cases.
   Le texte garde son contraste plein : ces jours sont pleinement consultables,
   ils ne sont ni désactivés ni secondaires. */
.sidebar .jour.passe {
  background: var(--fond-page);
  border-style: dashed;
}

.sidebar .jour:hover {
  color: var(--encre-1);
  background: var(--panneau);
  border-color: var(--accent);
}

.sidebar .jour:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* Seul aplat plein d'accent du panneau : l'échéance choisie. `--sur-accent`
   bascule avec le thème (blanc en clair, vert très sombre en sombre) —
   6,34:1 et 7,72:1. Déclaré APRÈS :hover pour que la pastille sélectionnée
   garde son fond quand la souris la survole. */
.sidebar .jour[aria-pressed="true"],
.sidebar .jour[aria-pressed="true"]:hover {
  color: var(--sur-accent);
  background: var(--accent);
  border-color: var(--accent);
}

.sidebar .jour b {
  display: block;
  font-size: 0.73rem;
  font-weight: 680;
}

/* 0,82 et non 0,72 (maquette) : à 0,72 la date du jour SÉLECTIONNÉ ne
   donnait que 4,18:1 sur l'aplat d'accent. À 0,82 elle donne 4,87:1 en
   clair et 5,41:1 en sombre, et 8,72:1 / 9,64:1 sur les pastilles inactives. */
.sidebar .jour small {
  display: block;
  font-size: 0.62rem;
  opacity: 0.82;
  font-variant-numeric: tabular-nums;
}

.sidebar .jour[aria-disabled="true"],
.sidebar .jour.disabled {
  color: var(--encre-3);
  background: var(--panneau-2);
  border-color: var(--trait);
  cursor: not-allowed;
}

/* ── Correction de température ─────────────────────────────────────────────
   IDENTIFIANTS IMPOSÉS : #enableSimulationMode, #temperatureOffsetSlider,
   #temperatureOffsetValue, #temperatureCorrectionSection.
   simulateur-temperature.js s'y accroche par getElementById et par
   délégation d'événements : ne jamais les renommer.
   Les sélecteurs ci-dessous sont écrits en (1,2,0) pour primer sur les
   règles historiques de la section 10 (#temperatureOffsetValue en bleu,
   #temperatureOffsetSlider en largeur 100 %). */
.sidebar .curseur-ligne {
  display: flex;
  flex-direction: column;
  gap: var(--espace-xs);
  margin-top: var(--espace-md);
  padding-top: var(--espace-md);
  border-top: 1px solid var(--trait);
}

.sidebar .curseur-ligne label {
  margin: 0;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--encre-2);            /* 7,82:1 clair · 7,82:1 sombre */
  white-space: nowrap;
}

/* Le gabarit conserve la structure historique du simulateur (deux blocs
   empilés, `.slider-header` regroupant le libellé et la valeur) parce que
   simulateur-temperature.js en dépend. Ces règles la ramènent à la ligne
   unique de la maquette — libellé, curseur, valeur — sans toucher au
   balisage : `display: contents` fait remonter les enfants de
   `.slider-header` au niveau du conteneur en flex, et `order` les remet
   dans l'ordre voulu. Si un moteur ignore `display: contents`, on retombe
   sur deux lignes empilées : dégradé, pas cassé. */
.sidebar .curseur-ligne .simulation-mode-container {
  display: flex;
  align-items: center;
  gap: var(--espace-sm);
  margin: 0;
  padding: 0;
  background: none;
  border-radius: 0;
}

.sidebar .curseur-ligne .simulation-mode-container label {
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--encre-2);
  white-space: normal;
}

.sidebar .curseur-ligne #enableSimulationMode {
  flex: none;
  width: 15px;
  height: 15px;
}

.sidebar .curseur-ligne .temperature-offset-container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-sm);
  margin: 0;
  padding: 0;
  background: none;
  border-radius: 0;
}

.sidebar .curseur-ligne .slider-header {
  display: contents;
  margin: 0;
}

.sidebar .curseur-ligne .slider-header label {
  order: 1;
}

.sidebar .curseur-ligne .legend-container {
  order: 4;
  flex-basis: 100%;
  margin: 0;
  font-size: 0.62rem;
  color: var(--encre-3);            /* 5,24:1 clair · 6,22:1 sombre */
  font-variant-numeric: tabular-nums;
}

/* `flex-basis: 110px` plutôt que `flex: 1` : si le libellé traduit est long
   (« Correction appliquée : » fait 133px en français), le curseur passe seul
   à la ligne suivante au lieu d'être écrasé à 70px. Avec un libellé court il
   reste sur la même ligne, comme dans la maquette. */
.sidebar .curseur-ligne input[type="range"],
.sidebar .curseur-ligne #temperatureOffsetSlider {
  order: 2;
  flex: 1 1 110px;
  width: auto;
  min-width: 0;
  margin: 0;
  accent-color: var(--accent);
}

.sidebar .curseur-ligne input[type="range"]:focus-visible,
.sidebar .curseur-ligne #temperatureOffsetSlider:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* La COULEUR du texte est posée en style inline par simulateur-temperature.js
   (bleu si la correction est négative, rouge si elle est positive) : c'est une
   couleur de DONNÉE — froid/chaud — et non un accent d'interface, elle est
   donc laissée telle quelle. Mesurée dans l'application : 9,11:1 à −1,5 °C.
   `color` ci-dessous ne sert que lorsque le JS n'a encore rien posé. */
.sidebar .curseur-ligne .valeur,
.sidebar .curseur-ligne #temperatureOffsetValue {
  order: 3;
  flex: none;
  min-width: 52px;
  margin: 0;
  padding: 4px 5px;
  font: 600 0.78rem/1 ui-monospace, Menlo, Consolas, monospace;
  color: var(--encre-1);            /* 15,58:1 clair · 13,82:1 sombre */
  text-align: center;
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-controle);
}

/* ── Actions de bas de panneau ────────────────────────────────────────────
   Boutons secondaires : ils accompagnent la carte, ils ne rivalisent pas
   avec les filtres. Aucun aplat plein. */
.sidebar .actions {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.sidebar .btn {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 7px 10px;
  font: inherit;
  font-size: 0.81rem;
  font-weight: 600;
  color: var(--encre-1);            /* 15,58:1 clair · 13,82:1 sombre */
  text-align: left;
  background: var(--panneau);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-bloc);
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--duree-rapide), border-color var(--duree-rapide);
}

.sidebar .btn:hover {
  color: var(--encre-1);            /* 13,10:1 clair · 11,07:1 sombre */
  background: var(--accent-clair);
  border-color: var(--accent);
}

.sidebar .btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.sidebar .btn i,
.sidebar .btn .btn-icone {
  flex: none;
  font-size: 0.9em;
  color: var(--accent);
}


/* ============================================================================
   13. VOILE DU TIROIR MOBILE
   ----------------------------------------------------------------------------
   Deux implémentations complémentaires :
   - .sidebar-voile : élément réel, si le template en fournit un (il peut alors
     être cliqué pour fermer le tiroir) ;
   - #main-layout::before : repli purement CSS, sans balisage, piloté par la
     présence de .sidebar-collapsed. Il s'efface si un élément réel existe,
     pour ne pas assombrir deux fois.
   Les deux ne sont visibles qu'en mobile (voir la media query correspondante).
   ========================================================================== */
.sidebar-voile,
#main-layout::before {
  display: none;
}


/* ============================================================================
   14. BOUTON « VOIR LA CARTE » (mobile uniquement)
   ========================================================================== */
/* Masqué hors mobile. Le sélecteur est préfixé par `.sidebar` — spécificité
   (0,2,0) — parce que le bouton porte aussi la classe `.btn` : la règle
   `.sidebar .btn { display:flex }`, de même spécificité mais déclarée plus
   loin, l'emportait sur un simple `.voir-carte-btn` (0,1,0). Le bouton
   s'affichait donc en desktop, où il n'a aucun sens : la carte y est déjà
   visible à côté du panneau. */
.voir-carte-btn,
.sidebar .voir-carte-btn {
  display: none;   /* activé uniquement sous 768px */
}


/* ============================================================================
   15. RESPONSIVE — MOBILE (≤ 768px)
   ========================================================================== */
@media (max-width: 768px) {
  .social-share-container {
    flex-direction: column;
    align-items: flex-start;
  }

  .share-text {
    margin-right: 0;
    margin-bottom: var(--espace-md);
  }

  h1 {
    font-size: 1.2rem;
    padding: var(--espace-lg);
  }

  .controls > div {
    flex-direction: column;
    gap: var(--espace-md);
  }

  /* LA CARTE OCCUPE L'ÉCRAN.
     `height: 400px` était ici depuis longtemps et n'a jamais rien fait : la
     règle de base pose aussi `min-height: 600px` sur #map, que rien ne
     neutralisait. Le minimum l'emportant toujours sur la hauteur, la carte
     mesurait 600px — plus haute que la fenêtre d'un iPhone SE, et pourtant
     suivie de 475px de pied de page. Le minimum doit donc tomber en premier.

     100svh et non 100vh : sur mobile, `vh` se rapporte à la fenêtre BARRE
     D'ADRESSE MASQUÉE, ce qui pousse toujours un fragment de carte hors de
     l'écran. `svh` prend la plus petite fenêtre possible et tient dans tous
     les cas. `dvh` conviendrait aussi mais change de valeur au défilement, ce
     qui ferait sauter le calque Leaflet. La ligne `vh` reste en repli pour les
     navigateurs qui ignorent `svh`.

     La hauteur est portée par .main-map et non par #map : ce dernier est un
     enfant flex avec `flex: 1`, donc `flex-basis: 0%`, ce qui écrase toute
     hauteur qu'on lui donnerait. C'est le CONTENEUR qu'il faut dimensionner ;
     #map n'a plus qu'à voir son minimum levé. */
  #map {
    min-height: 0;
  }

  #main-layout {
    flex-direction: column;
    min-height: unset;
    height: auto;
  }

  /* Tiroir latéral.
     Nettoyage : la largeur était déclarée deux fois (100% puis 85%) et un
     flex-direction:row contredisait la colonne du bloc de base — dans un
     tiroir de 300px au maximum, les contrôles doivent rester empilés.
     flex-wrap est retiré pour la même raison (en colonne, il découperait le
     contenu en plusieurs colonnes au lieu de le laisser défiler). */
  /* Le rembourrage HAUT reste à 0 : `.rail-tete` est collant et déborde
     latéralement de --espace-lg (12px), la valeur du rembourrage horizontal
     ci-dessous. Les deux doivent rester égales. */
  .sidebar {
    width: 85%;
    max-width: var(--largeur-tiroir-mobile);
    min-width: unset;
    gap: 0;
    padding: 0 var(--espace-lg) var(--espace-3xl);
    border-right: none;
    border-bottom: 1px solid var(--trait);
    position: fixed !important;
    top: 0;
    left: 0;
    bottom: 0;
    background: var(--panneau);
  }

  .sidebar .rail-tete {
    margin: 0 calc(-1 * var(--espace-lg));
    padding: var(--espace-lg) var(--espace-lg) var(--espace-md);
  }

  /* #toggleControlsButton (position:fixed, 40×40) fait office de croix de
     fermeture, épinglé au bord droit du tiroir. Mesuré en 375px : bouton
     x 240→280, pastille de compte x 244→282 — la pastille était intégralement
     recouverte. On lui réserve sa place sur la LIGNE DU LOGO seulement, pour
     que le champ de recherche garde toute sa largeur. */
  .sidebar .rail-tete .logo {
    padding-right: 46px;
  }

  /* PLACEMENT DE LA POIGNÉE, tiroir ouvert.
     Il était posé en JS à 240px en dur. Sous 320px de large le tiroir ne fait
     que 272px : le bouton (40px) débordait alors du tiroir et se posait sur la
     carte, à côté d'une croix qui ne fermait plus rien visuellement. Calculé
     depuis la largeur réelle du tiroir, il reste collé à son bord intérieur
     quelle que soit la taille de l'écran.
     Replié, il revient dans le coin de la fenêtre — c'est la valeur de base
     de la règle #toggleControlsButton, qu'on ne redéclare donc pas. */
  #main-layout:has(.sidebar:not(.sidebar-collapsed)) #toggleControlsButton {
    left: min(85vw, var(--largeur-tiroir-mobile));
    transform: translateX(calc(-100% - var(--espace-md)));
  }

  .sidebar > :first-child:not(.rail-tete) {
    margin-top: var(--espace-lg);
  }

  /* TROIS COLONNES, ET NON QUATRE.
     Sur 4 colonnes, un tiroir de 300px laisse ~62px par tuile : « Sécheresse »
     s'y coupait en « Sécheress / e » — overflow-wrap: anywhere fait son office,
     mais un mot tronqué au milieu se lit mal et ne s'oublie pas. Trois colonnes
     donnent ~86px, où le mot tient entier. Le domaine le plus long,
     « Pratiques agricoles », passe sur deux lignes, ce qui est normal.
     Une rangée de plus en hauteur est un prix acceptable pour des libellés
     lisibles — c'est le premier choix que fait l'utilisateur. */
  .sidebar .domaines {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--espace-2xs);
  }

  .sidebar .dom {
    padding: 8px 4px 7px;
  }

  /* La coupure au milieu d'un mot redevient un dernier recours, et non le
     comportement courant : sur 86px, seuls des libellés futurs anormalement
     longs y tomberaient. */
  .sidebar .dom-libelle {
    overflow-wrap: break-word;
    hyphens: auto;
  }

  /* La liste d'indicateurs peut respirer : le tiroir occupe toute la hauteur. */
  .sidebar .liste-types {
    max-height: 46vh;
    overflow-y: auto;   /* sans quoi les dernières familles sont inatteignables */
  }

  /* Cibles tactiles : 5px de haut pour une pastille de jour est en dessous
     du minimum confortable au doigt. */
  .sidebar .jour {
    padding: var(--espace-sm) 2px;
  }

  .sidebar .btn {
    padding: var(--espace-md) var(--espace-lg);
  }

  /* CIBLES TACTILES — plancher à 44px.
     Mesuré au doigt sur un écran de 390px : le sélecteur de langue faisait
     26px de haut, la pastille de compte 32, les listes déroulantes 34 et les
     boutons de partage 36. Toutes cliquables à la souris, toutes pénibles au
     pouce. 44px est le minimum recommandé par Apple comme par Google ; on s'y
     tient, sans grossir la typographie, en jouant sur le rembourrage. */
  .sidebar .lang-toggle .lang-btn,
  .sidebar .account-chip,
  .account-chip {
    min-height: 44px;
  }

  .sidebar .champ select {
    min-height: 44px;
  }

  .social-button {
    min-width: 44px;
    min-height: 44px;
  }

  .main-map {
    min-height: 100vh;
    min-height: 100svh;
  }

  .leaflet-left {
    padding-top: 50px !important;
  }

  #toggleControlsButton {
    display: flex;
    left: var(--espace-md);
  }

  .leaflet-control-zoom {
    top: 108px;
  }

  /* Sur mobile le panneau est un tiroir : la carte occupe toute la largeur, la
     pastille se recentre donc sur la fenêtre. Et comme la recherche de ville
     s'étale en haut de carte, elle descend sous elle.
     L'ID DOIT FIGURER dans le sélecteur : la règle de base s'écrit
     `#mapLoadingIndicator, .map-loading-indicator`, et un id (1,0,0) bat
     n'importe quelle combinaison de classes. Une surcharge par la seule classe
     reste inerte — vérifié, elle l'était. */
  #mapLoadingIndicator,
  .map-loading-indicator {
    /* Le tiroir occupe toute la largeur : le centre de la carte est celui de
       la fenêtre. Le décalage vertical qui évitait la recherche de ville n'a
       plus lieu d'être, le centre étant libre de tout contrôle. */
    left: 50%;
    max-width: calc(100vw - 2 * var(--espace-2xl));
  }

  /* CORRECTIF — superposition « Opacité du calque » / légende.
     Le panneau d'opacité était une boîte flottante de 160px de large ancrée en
     bas à gauche (bottom:120px), tandis que la légende Leaflet occupe le coin
     bas droit sur plus de 300px de large et jusqu'à 200px de haut : sous
     400px de large, les deux se recouvraient et leurs textes se lisaient l'un
     par-dessus l'autre, le filigrane AGROCLIMAT (bottom-left) chevauchant en
     prime le dégradé de la légende.

     Nouvelle disposition, sans recouvrement possible :
       • le panneau d'opacité devient une BARRE pleine largeur collée en bas ;
       • tous les contrôles Leaflet du bas (filigrane à gauche, légende et
         attribution à droite) sont remontés au-dessus de cette barre ;
       • le filigrane est réduit et la légende plafonnée en largeur et en
         hauteur, pour qu'ils tiennent côte à côte sur 375px. */
  #opacityContainer {
    left: var(--espace-md);
    right: var(--espace-md);
    bottom: var(--espace-md);
    width: auto;
    height: auto;
    display: flex;
    align-items: center;
    gap: var(--espace-lg);
    padding: var(--espace-sm) var(--espace-lg);
    background-color: var(--voile-blanc-95);
    box-shadow: var(--ombre-carte);
  }

  #opacityContainer p {
    margin: 0;
    flex: none;
    font-size: 11px;
    line-height: 1.2;
    white-space: nowrap;
  }

  /* Le curseur (seul <div> enfant) occupe la place restante. */
  #opacityContainer > div {
    flex: 1;
    min-width: 0;
  }

  #opacityContainer .noUi-pips {
    display: none;
  }

  /* Les contrôles du bas de carte passent au-dessus de la barre d'opacité
     (hauteur de la barre + marge). */
  .leaflet-bottom {
    bottom: 56px;
  }

  /* Le filigrane monte encore d'un cran : la ligne d'attribution Leaflet
     s'étale sur toute la largeur et se superposait à lui. */
  .leaflet-bottom.leaflet-left {
    bottom: 96px;
  }

  /* Filigrane réduit : il laisse la place à la légende sur la même bande. */
  .logo-control img {
    width: 68px;
  }

  .logo-attribution {
    font-size: 10px;
  }

  /* Légende plafonnée : jamais plus large que l'espace laissé par le
     filigrane, jamais plus haute que 40 % de l'écran. */
  .leaflet-bottom.leaflet-right .legend {
    box-sizing: border-box;   /* sinon le plafond ignore les 8px de padding */
    max-width: calc(100vw - 120px);
    max-height: 40vh;
    overflow-y: auto;
    font-size: 11px;
    background: var(--voile-blanc-95);
  }

  .leaflet-bottom.leaflet-right .legend h4 {
    max-width: 100%;
  }

  /* ── Voile de fond du tiroir ─────────────────────────────────────────── */
  #main-layout::before {
    content: '';
    display: block;
    position: fixed;
    inset: 0;
    background: var(--voile-sombre);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    z-index: var(--plan-voile);   /* sous la sidebar, au-dessus de la carte */
    transition: opacity var(--duree-moyenne) ease, visibility var(--duree-moyenne) ease;
  }

  /* Tiroir ouvert = sidebar sans la classe de repli. */
  #main-layout:has(.sidebar:not(.sidebar-collapsed))::before {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;   /* neutralise les clics parasites sur la carte */
  }

  /* Un voile fourni par le template rend le repli CSS inutile. */
  #main-layout:has(.sidebar-voile)::before {
    content: none;
  }

  .sidebar-voile {
    display: block;
    position: fixed;
    inset: 0;
    background: var(--voile-sombre);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    z-index: var(--plan-voile);
    transition: opacity var(--duree-moyenne) ease, visibility var(--duree-moyenne) ease;
  }

  .sidebar-voile.est-visible,
  .sidebar:not(.sidebar-collapsed) ~ .sidebar-voile {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  /* ── Bouton « Voir la carte » ────────────────────────────────────────── */
  .voir-carte-btn {
    display: flex;
  }

  /* Dans la sidebar, il prime sur le style générique `.sidebar button` ET sur
     `.sidebar .btn` (même spécificité (0,2,0), mais déclaré plus loin dans le
     fichier).
     Le dégradé vert de marque a disparu : c'était une SECONDE couleur
     d'interface, exactement ce que la refonte supprime. C'est le seul bouton
     du panneau qui porte un aplat plein d'accent, parce qu'il est l'action de
     sortie du tiroir. `--sur-accent` sur `--accent` : 6,34:1. */
  .sidebar .voir-carte-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--espace-sm);
    position: sticky;
    bottom: 0;
    z-index: 2;
    width: 100%;
    margin: var(--espace-xs) 0 0;
    padding: var(--espace-lg) var(--espace-3xl);
    font-size: 15px;
    font-weight: 600;
    color: var(--sur-accent);
    background: var(--accent);
    border: 1px solid var(--accent);
    border-radius: var(--rayon-bloc);
    box-shadow: var(--ombre-carte);
    cursor: pointer;
    transition: background-color var(--duree-courte) ease, box-shadow var(--duree-courte) ease;
  }

  .sidebar .voir-carte-btn:hover {
    color: var(--sur-accent);
    background: var(--accent);
    box-shadow: var(--ombre-carte-survol);
  }

  .sidebar .voir-carte-btn i,
  .sidebar .voir-carte-btn .btn-icone {
    color: inherit;   /* sinon l'icône hérite de `.sidebar .btn i` (accent sur accent) */
  }
}


/* ============================================================================
   16. RESPONSIVE — TABLETTE (769px → 1024px)
   ----------------------------------------------------------------------------
   Entre ces largeurs, une sidebar de 350px consommait 35 à 45 % de l'écran et
   la grille à deux colonnes réduisait les tuiles à une centaine de pixels,
   illisibles. On rétrécit la sidebar et on passe la grille sur une colonne.
   ========================================================================== */
@media (min-width: 769px) and (max-width: 1024px) {
  /* --largeur-sidebar passe à 260px sur tablette : la redéfinition du jeton
     vit dans jetons.css, seule feuille autorisée à écrire les jetons. */

  /* Rembourrage horizontal réduit à 12px : `.rail-tete` déborde d'autant
     (voir la règle qui suit). */
  .sidebar {
    padding: 0 var(--espace-lg) var(--espace-2xl);
    gap: 0;
  }

  .sidebar .rail-tete {
    margin: 0 calc(-1 * var(--espace-lg));
    padding: var(--espace-md) var(--espace-lg);
  }

  .sidebar > :first-child:not(.rail-tete) {
    margin-top: var(--espace-lg);
  }

  #controle_boutons {
    gap: var(--espace-xl);
  }

  /* Panneau à 260px, moins 24px de rembourrage : 4 colonnes tomberaient à
     54px, trop étroites pour « Sécheresse » ou « Ravageurs ». 3 colonnes de
     ~74px redonnent une ligne de libellé lisible. */
  .sidebar .domaines {
    grid-template-columns: repeat(3, 1fr);
  }

  .sidebar .liste-types {
    max-height: 160px;
    overflow-y: auto;   /* sans quoi les dernières familles sont inatteignables */
  }

}


/* ============================================================================
   17. RESPONSIVE — DESKTOP ET TABLETTE (≥ 769px)
   ----------------------------------------------------------------------------
   Le repli de la sidebar était impossible au-dessus de 768px : le bouton était
   masqué (display:none !important) et, surtout, un simple translateX() laissait
   un vide de 350px puisque la transformation ne libère pas la place en flux.
   On combine donc : bouton visible, marge négative pour rendre la largeur à la
   carte, et transformation neutralisée.
   ========================================================================== */
@media (min-width: 769px) {
  /* Poignée verticalement centrée sur le bord de la sidebar : le coin haut
     gauche de la carte est déjà occupé par la recherche de ville et le zoom
     Leaflet.
     Les !important qui figuraient ici ne servaient qu'à contrer un `left`
     posé en ligne par root.js. Ce style en ligne a été supprimé — la feuille
     de style est désormais seule à placer ce bouton. */
  #toggleControlsButton {
    display: flex;
    top: 50%;
    transform: translateY(-50%);
    left: calc(var(--largeur-sidebar) + var(--espace-md));
  }

  .sidebar.sidebar-collapsed {
    transform: none;
    margin-left: calc(-1 * var(--largeur-sidebar));
  }

  /* Sidebar repliée : le bouton revient dans le coin de la fenêtre. */
  #main-layout:has(.sidebar.sidebar-collapsed) #toggleControlsButton {
    left: var(--espace-md);
  }

  /* Panneau replié : la carte occupe toute la fenêtre, la pastille se
     recentre. Le sélecteur part de `body` et non de `#main-layout` — la
     pastille est téléportée hors de ce dernier. */
  body:has(.sidebar.sidebar-collapsed) #mapLoadingIndicator,
  body:has(.sidebar.sidebar-collapsed) .map-loading-indicator {
    left: 50%;
  }

  /* La carte occupe la largeur libérée. */
  #main-layout:has(.sidebar.sidebar-collapsed) #map {
    border-bottom-left-radius: var(--rayon-panneau);
  }
}


/* ============================================================================
   18. ACCESSIBILITÉ — mouvement réduit
   ----------------------------------------------------------------------------
   Neutralise les animations et transitions introduites ou modifiées ici pour
   les utilisateurs qui demandent moins de mouvement. Le rouet de chargement
   conserve un signal visuel (variation d'opacité) plutôt que de disparaître.
   ========================================================================== */
@keyframes pulsation-douce {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* ============================================================================
   APPARITION DES BLOCS DU PANNEAU
   ----------------------------------------------------------------------------
   Un bloc qui surgit et pousse le reste d'un coup laisse l'utilisateur chercher
   ce qui vient de changer. Un fondu et un glissement de quatre pixels suffisent
   à porter l'œil : assez pour être suivi, trop court pour être attendu.

   L'animation ne marque que les blocs qui APPARAISSENT en cours d'usage — bloc
   du modèle, bloc de l'échéance —, pas ceux présents au chargement. Une cascade
   à chaque visite fait joli une fois et coûte une seconde à chaque fois ensuite.
   C'est le rôle de la classe `anime-entree`, posée par Vue.
   ========================================================================== */
@keyframes entree-bloc {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

.sidebar .bloc.anime-entree {
  animation: entree-bloc 160ms ease-out both;
}

@media (prefers-reduced-motion: reduce) {
  /* RÈGLE GÉNÉRALE, ET NON UNE LISTE DE COMPOSANTS.
     Cette section énumérait une vingtaine de sélecteurs, un par un. Tout ce qui
     a été ajouté depuis lui échappait : le bouton Tipeee et les boutons de
     partage, qui portent pourtant `transition: all .3s`, n'ont jamais été
     couverts. Une liste à tenir à jour manuellement finit toujours par ne plus
     l'être — d'autant qu'un oubli ne se voit pas, sauf par les personnes
     précisément concernées.
     On coupe donc par défaut, partout, et l'on rétablit les rares exceptions
     juste en dessous.

     `0.01ms` et non `none` : la durée reste non nulle, donc l'événement
     `transitionend` continue d'être émis. root.js s'en sert pour attendre la
     fin du repli du panneau avant de recalculer la taille de la carte — avec
     `none`, il ne dépendrait plus que de son délai de secours. */
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* EXCEPTION — le rouet de chargement.
     Il doit rester perceptible : sans aucun signal, une carte qui met 10 à 15 s
     à venir passerait pour une page figée. Il ne tourne plus, il respire. La
     durée et la répétition sont réaffirmées ici pour échapper à la règle
     générale ci-dessus. */
  #mapLoadingIndicator::before,
  .map-loading-indicator::before {
    animation: pulsation-douce 1.6s ease-in-out infinite !important;
    animation-duration: 1.6s !important;
    animation-iteration-count: infinite !important;
  }
}
