/* Feuille de style du volet « Événements » (panneau 6) — liste à gauche, carte de
   France à droite.
   Cf. docs/events-panel.md, docs/ui-shell.md (z-index, Échap),
   docs/design-rules.md (règle 3), docs/report-panel.md (coquille de volet, dont ce
   fichier est le décalque).

   CE FICHIER NE STYLE PAS L'ÉCRAN « MESSAGES ». Il l'a fait pendant le chantier, et
   c'était le symptôme d'un doublon : events.js injectait sa propre entrée dans le menu
   du compte, en plus de celle d'auth.js. Le menu utilisateur appartient à auth.js — qui
   le construit, le localise et le reconstruit au changement de langue — donc l'écran
   Messages et sa pastille sont stylés par auth.css. Ne pas réintroduire ici de règle
   `.ev-m*` / `.ev-modal*` : elle serait orpheline et le test la refuserait.

   TROIS CONTRAINTES GOUVERNENT CE FICHIER, chacune gardée par un test de
   tests/test_events_interface.py.

   1. PÉRIMÈTRE — la plus dure, et c'est la leçon d'auth.css. Ce fichier est chargé
      INCONDITIONNELLEMENT par index.html (lien bloquant dans le <head>), dans les DEUX
      modes, alors que le volet n'existe qu'en mode serveur : en mode local, events.js
      sort avant de créer le moindre nœud et cette feuille doit rester sans effet — pas
      un pixel de l'app de bureau ne bouge. Donc le PREMIER compound de CHAQUE sélecteur
      — y compris à l'intérieur d'un @media — descend d'un `#ev-*` ou d'une classe
      `.ev-*` que seul events.js (ou evmap.js) crée. Le piège, avec sa contre-épreuve
      dans le test, est la règle qui COMMENCE par un sélecteur légitime et glisse un
      élément partagé dans la même liste : `.ev-list, select{…}` cadrerait `select` sur
      TOUTE la page.
      Corollaire longtemps vrai, et qui ne l'est PLUS : `@keyframes` était interdit ici
      parce que le détecteur lisait les blocs internes et voyait `to{…}` / `0%{…}` comme
      des sélecteurs hors périmètre. Depuis la v0.6.161 il sait les ignorer, corps
      compris, et ce fichier en contient un (`ev-draft-pulse`). Ce n'est donc plus une
      contrainte, seulement une SOBRIÉTÉ : un indicateur de chargement se fait en TEXTE
      (`.ev-status`), pas en rotation.
      PIÈGE MESURÉ AILLEURS, QUI VAUT ICI (v0.6.162, cf. community.css et
      docs/design-rules.md §3) : une `transition` ne doit JAMAIS porter sur une propriété
      dont la valeur vient d'un `var(--…)` thématique — la couleur calculée cesse alors de
      suivre les cinq thèmes, définitivement. Ce fichier n'anime que la position, et c'est
      pour cela qu'il n'a jamais rencontré ce défaut.

   2. TOKENS SEULEMENT (règle de conception 3). Aucune couleur littérale — ni #rgb, ni
      #rrggbb, ni notation fonctionnelle : les cinq thèmes commutent à chaud et une
      valeur en dur devient illisible dans quatre d'entre eux. Les ombres passent par
      `var(--shadow)`, les fonds d'overlay par `var(--overlay)`, les états par les
      triplets `--ok/--ok-bg/--ok-line`, `--bad/…`, `--warn/…`. Cela vaut AUSSI pour le
      SVG de la carte : `fill`/`stroke` acceptent `var(--…)`, et c'est ce qui fait
      suivre la carte au changement de thème sans une ligne de JS.

   3. LES NOMS SONT CEUX QUE LE JS POSE, pas ceux qu'on aurait choisis. Deux tests
      croisent les deux inventaires dans les DEUX sens (règle sans cible / classe sans
      règle) parce que la première version de ce fichier a été écrite en parallèle du JS
      et visait un DOM imaginaire : mesuré alors, 48 règles sur 74 sans cible et 84
      classes sur 111 sans règle, la feuille passant pourtant tous les gardes hérités
      (aucune couleur littérale, aucun sélecteur hors périmètre, 100 % préfixé `ev-`).
      Concrètement à l'écran : les états de ligne étaient écrits `.cancelled/.mine/.reg`
      quand le JS pose `.ev-cancelled/.ev-own/.ev-reg` — un événement ANNULÉ n'était ni
      barré ni badgé, c'est-à-dire que la décision « annuler n'est pas supprimer » était
      invisible — et tout le préfixe `.ev-map-*` d'evmap.js n'avait aucune règle, donc
      la carte débordait de 540 px hors du volet en fenêtre étroite, emportant hors de
      l'écran les boutons de zoom ET la mention de licence.
      L'inventaire de référence est le bloc `CONTRAT CSS` en fin d'evmap.js pour la
      carte, et le balisage d'events.js pour le reste.

   Z-INDEX (registre tenu par docs/ui-shell.md — volets 3000, plein écran 3300,
   pop-overs de volet 3060, modaux import/export 3950, menu de thème 4000, menu
   utilisateur 4050, confirm/prompt 4100, zone admin ET écran « Messages » 4200,
   écran-porte 4300) : ce fichier ne déclare QUE 3000 et 3300. Le volet n'ouvre aucun
   modal propre — le formulaire vit dans la colonne de gauche et l'annulation se confirme
   EN LIGNE (règle 1) — et l'écran « Messages » appartient à auth.css. */

/* ====================== bouton bascule (en-tête) ====================== */
/* Écrit directement au gabarit « bouton d'en-tête » plutôt qu'en FAB corrigé ensuite :
   la normalisation `#mtg-header-actions > #…-toggle` de search.css énumère les cinq
   volets existants par identifiant, et search.css ne connaît pas celui-ci. Un bouton
   qui se suffit à lui-même évite de faire dépendre son alignement d'un fichier tiers. */
#ev-toggle{
  position:static;
  background:var(--acc);color:var(--on-acc);border:none;border-radius:8px;
  padding:6px 12px;font:700 13px/1.2 system-ui,Segoe UI,Roboto,sans-serif;
  cursor:pointer;box-shadow:none;white-space:nowrap;
  display:inline-flex;gap:7px;align-items:center;
}
#ev-toggle:hover{filter:brightness(1.08)}
#ev-toggle:focus-visible{outline:none;box-shadow:0 0 0 3px var(--focus)}
.ev-tg-ic{font-size:14px;line-height:1}
.ev-tg-nm{line-height:1}

/* ====================== volet coulissant (depuis la droite) ====================== */
/* Aussi large que le volet rapport : deux colonnes y cohabitent, et une carte de France
   sous 420 px de large ne se lit plus. */
#ev-panel{
  position:fixed;top:0;right:0;height:100vh;width:min(1120px,100vw);z-index:3000;
  background:var(--panel);border-left:1px solid var(--line);color:var(--txt);
  display:flex;flex-direction:column;transform:translateX(102%);
  transition:transform .22s ease;box-shadow:-8px 0 32px var(--shadow);
  font:14px/1.5 system-ui,Segoe UI,Roboto,sans-serif;
}
#ev-panel.open{transform:translateX(0)}
#ev-panel.full{width:100vw;z-index:3300}
#ev-panel[hidden]{display:none}

/* ---- en-tête ---- */
.ev-head{
  padding:10px 14px;border-bottom:1px solid var(--line);flex:0 0 auto;
  display:flex;flex-direction:column;gap:8px;position:relative;
}
.ev-headtop{display:flex;gap:8px;align-items:center}
.ev-h-title{font-size:16px;font-weight:700;flex:1;min-width:0}
.ev-hbtn{background:none;border:none;color:var(--mut);cursor:pointer;line-height:1;padding:0 5px;font-size:18px}
.ev-hbtn:hover{color:var(--txt)}
.ev-hbtn.on{color:var(--acc)}
.ev-hbtn:focus-visible{outline:none;color:var(--txt);box-shadow:0 0 0 2px var(--focus);border-radius:6px}
#ev-close{font-size:24px}

/* Barre de filtre. Le champ prend toute la place restante : filtrer est le geste le
   plus fréquent du volet, créer un événement ne l'est pas. */
.ev-headrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
#ev-filter{
  flex:1;min-width:140px;background:var(--input);color:var(--txt);
  border:1px solid var(--line);border-radius:8px;padding:7px 10px;font:13px/1.2 inherit;
}
#ev-filter:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 2px var(--focus)}
/* Motif `/regex/` invalide : la bordure le dit, `.ev-ferr` l'explique, et la liste
   reste NON filtrée (se vider en silence se lirait « aucun événement » au lieu de
   « motif faux »). */
#ev-filter.ev-bad{border-color:var(--bad);box-shadow:0 0 0 2px var(--bad-bg)}
.ev-count{color:var(--mut);font-size:12px;white-space:nowrap}

/* Deux lignes de retour, jamais visibles en même temps que du contenu utile : hauteur
   nulle tant qu'elles sont vides, pour ne pas agiter la mise en page. */
.ev-ferr{color:var(--bad);font-size:12px;display:none}
.ev-ferr.on{display:block}
/* Ligne d'état : elle sert aussi de témoin de chargement (« … ») — cf. l'interdiction
   d'@keyframes en tête de fichier. */
.ev-status{color:var(--acc);font-size:12px;min-height:15px}
.ev-status.bad{color:var(--bad)}

/* ====================== corps : liste | carte ====================== */
/* La liste porte une base FIXE et la carte absorbe le reste : l'inverse (deux colonnes
   élastiques) laissait la liste se faire écraser dès qu'un titre était long, alors que
   c'est elle qui porte l'information. */
.ev-body{flex:1 1 auto;min-height:0;display:flex;gap:0}
/* `min-height:0` N'EST PAS DÉCORATIF, et son absence a été mesurée (v0.6.171) : un élément
   de flex a `min-height:auto` sur son axe PRINCIPAL, donc il refuse de descendre sous la
   hauteur de son contenu. Tant que cette colonne ne contenait que la liste — qui, elle,
   porte `min-height:0` — personne ne le voyait. Dès qu'un second bloc s'y est ajouté
   (la présence, v0.6.171), la colonne a pris la hauteur de la LISTE ENTIÈRE (954 px
   mesurés dans un corps de 156) et le bloc suivant est parti SOUS le bas de l'écran :
   il avait bien son propre ascenseur, mais on ne pouvait pas l'atteindre.
   Le volet est en `position:fixed` : son débordement ne produit aucune barre de
   défilement, donc rien ne dit à l'utilisateur que la moitié de la colonne est en
   dessous. C'est ce qui rend ce défaut invisible plutôt que gênant. */
.ev-side{
  flex:0 0 clamp(300px,38%,440px);min-width:0;min-height:0;
  display:flex;flex-direction:column;
  border-right:1px solid var(--line);
}
.ev-mapcol{
  flex:1 1 auto;min-width:0;display:flex;flex-direction:column;
  padding:10px;gap:8px;background:var(--bg);overflow:hidden;
}

/* ---- liste ---- */
/* C'est la LISTE qui défile, pas le volet : le volet est en `position:fixed` et son
   débordement serait purement invisible (mesuré : 540 px de carte peints sous le bas de
   l'écran, sans barre de défilement pour le dire). */
.ev-list{flex:1 1 auto;min-height:0;overflow-y:auto;list-style:none;margin:0;padding:0}
.ev-row{
  display:flex;gap:10px;align-items:flex-start;flex-wrap:wrap;width:100%;text-align:left;
  padding:9px 12px 9px 9px;border:0;border-left:3px solid transparent;
  border-bottom:1px solid var(--line);
  background:transparent;color:var(--txt);font:inherit;cursor:pointer;
}
.ev-row:hover{background:var(--panel2)}
.ev-row:focus-visible{outline:none;background:var(--panel2);box-shadow:inset 0 0 0 2px var(--focus)}
/* Les états d'une ligne, du plus faible au plus fort — l'ordre de déclaration EST la
   priorité, puisque tous ont la même spécificité. Un événement annulé QUI EST LE MIEN
   porte donc le liseré `--bad` et non l'accent : « ça n'aura pas lieu » prime sur
   « c'est à moi ». */
.ev-row.ev-past{opacity:.55}
.ev-row.ev-own{border-left-color:var(--acc)}
.ev-row.ev-reg{border-left-color:var(--ok)}
.ev-row.ev-cancelled{border-left-color:var(--bad)}
/* Décision 4 du chantier, rendue VISIBLE : annuler n'est pas supprimer — la ligne reste,
   barrée et badgée. Le titre seul est barré (barrer la date et le lieu les rendrait
   illisibles pour rien). */
.ev-row.ev-cancelled .ev-r-title{text-decoration:line-through}
.ev-row.ev-cancelled .ev-r-time{text-decoration:line-through}
/* Prochain événement à venir quand on a révélé le passé : c'est la ligne qu'on cherche
   des yeux, elle est amenée à l'écran une fois par le JS et signalée ici. */
.ev-row.ev-next{box-shadow:inset 3px 0 0 var(--warn)}
.ev-row.sel{background:var(--panel2);border-left-color:var(--acc)}
.ev-row.sel .ev-r-title{color:var(--acc)}

.ev-r-date{flex:0 0 auto;color:var(--mut);font-size:12px;font-variant-numeric:tabular-nums}
.ev-r-time{flex:0 0 auto;color:var(--mut);font-size:12px;font-variant-numeric:tabular-nums}
.ev-r-title{flex:1 1 100%;min-width:0;font-weight:600;overflow-wrap:anywhere}
.ev-r-place{flex:1 1 auto;min-width:0;color:var(--txt2);font-size:12px;overflow-wrap:anywhere}
.ev-r-regs{flex:0 0 auto;color:var(--mut);font-size:12px;white-space:nowrap}
.ev-r-badges{flex:0 0 auto;display:inline-flex;gap:4px;flex-wrap:wrap}

.ev-badge{
  display:inline-block;padding:1px 6px;border-radius:999px;
  font-size:11px;font-weight:600;line-height:1.5;
  border:1px solid var(--line);color:var(--mut);
}
.ev-b-cancel{background:var(--bad-bg);border-color:var(--bad-line);color:var(--bad)}
.ev-b-mine{background:var(--panel2);border-color:var(--acc);color:var(--acc)}
.ev-b-reg{background:var(--ok-bg);border-color:var(--ok-line);color:var(--ok)}

/* Règle 6 : jamais d'interface vide sans un mot. Ce bloc dit POURQUOI la liste est
   vide (aucun événement, ou aucun qui corresponde au filtre). */
.ev-empty{padding:22px 14px;color:var(--mut);text-align:center;font-size:13px}

/* ---- fiche détaillée / formulaire (bas de la colonne gauche) ---- */
/* Une carte en bas de la colonne de gauche, PAS un calque sur la carte de France :
   c'est elle qui a servi à sélectionner, la recouvrir ferait perdre le contexte. */
.ev-detail{
  flex:0 0 auto;max-height:48%;overflow-y:auto;
  border-top:1px solid var(--line);background:var(--panel2);
  padding:0;display:none;
}
.ev-detail.on{display:block;padding:12px 14px 14px}
.ev-d-head{display:flex;gap:8px;align-items:flex-start}
.ev-d-title{margin:0;font-size:15px;font-weight:700;flex:1;min-width:0;overflow-wrap:anywhere}
.ev-d-meta{
  display:grid;grid-template-columns:auto 1fr;gap:3px 10px;
  margin:8px 0 0;font-size:13px;
}
.ev-d-k{color:var(--mut);font-size:12px}
.ev-d-v{color:var(--txt);min-width:0;overflow-wrap:anywhere}
.ev-d-by{margin-top:8px;color:var(--mut);font-size:12px}
/* La description est saisie dans un <textarea> : ses retours à la ligne sont un choix
   de l'auteur, pas du remplissage. */
.ev-d-desc{margin-top:8px;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--txt2)}
.ev-d-acts{margin-top:12px;display:flex;gap:8px;flex-wrap:wrap;align-items:center}
/* Confirmation d'annulation EN LIGNE (règle 1 : pas de confirm() natif), sur le modèle
   de la suppression de compte de la zone admin. Teinte --warn : c'est un avertissement,
   pas encore un échec. */
.ev-ask{
  font-size:12px;color:var(--warn);background:var(--warn-bg);
  border:1px solid var(--warn-line);border-radius:6px;padding:3px 8px;
}

/* ---- boutons ---- */
.ev-btn{
  background:var(--input);color:var(--txt);border:1px solid var(--line);
  border-radius:8px;padding:6px 12px;font:600 13px/1.2 inherit;cursor:pointer;
}
.ev-btn:hover{border-color:var(--acc)}
.ev-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--focus)}
.ev-btn.prim{background:var(--acc);color:var(--on-acc);border-color:var(--acc)}
.ev-btn.ghost{background:transparent;color:var(--mut)}
.ev-btn.ghost:hover{color:var(--txt)}
.ev-btn.bad{background:var(--bad-bg);color:var(--bad);border-color:var(--bad-line)}
/* Bascule ARMÉE (« Placer sur la carte » en attente d'un clic). Cet état doit se voir de
   loin : il change le curseur de toute la carte. */
.ev-btn.on{background:var(--acc);color:var(--on-acc);border-color:var(--acc)}
.ev-x{
  background:none;border:none;color:var(--mut);font-size:20px;line-height:1;
  cursor:pointer;padding:0 4px;
}
.ev-x:hover{color:var(--txt)}
.ev-x:focus-visible{outline:none;box-shadow:0 0 0 2px var(--focus);border-radius:6px}

/* ---- formulaire ---- */
.ev-f-head{display:flex;gap:8px;align-items:center;margin-bottom:10px}
.ev-f-head h3{margin:0;font-size:15px;font-weight:700;flex:1;min-width:0}
.ev-form{display:flex;flex-direction:column;gap:9px}
.ev-f{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--mut);min-width:0}
.ev-f input,.ev-f select,.ev-f textarea{
  background:var(--input);color:var(--txt);border:1px solid var(--line);
  border-radius:8px;padding:7px 10px;font:13px/1.35 inherit;width:100%;
  box-sizing:border-box;
}
.ev-f textarea{resize:vertical;min-height:70px}
.ev-f input:focus,.ev-f select:focus,.ev-f textarea:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 2px var(--focus)}
.ev-f-row{display:flex;gap:8px;flex-wrap:wrap}
.ev-f-row .ev-f{flex:1 1 130px}
.ev-f-coords{flex-direction:row;align-items:center;gap:8px;flex-wrap:wrap}
.ev-coords{
  font-variant-numeric:tabular-nums;color:var(--txt);
  background:var(--input);border:1px solid var(--line);border-radius:6px;padding:3px 8px;
}
.ev-coords.none{color:var(--mut);font-style:italic;background:transparent;border-style:dashed}
.ev-f-err{color:var(--bad);font-size:12px;display:none}
.ev-f-err.on{display:block}
.ev-f-acts{display:flex;gap:8px;flex-wrap:wrap;margin-top:2px}
/* Les cinq champs identifiés sont pilotés par le JS (valeurs, focus d'erreur) ; leur
   aspect vient des règles génériques ci-dessus. Ces sélecteurs existent pour que la
   feuille et le balisage soient croisables dans les deux sens, et pour tenir les
   largeurs des champs de date/heure, qui sinon s'étalent différemment par navigateur. */
#ev-f-title{font-weight:600}
#ev-f-day,#ev-f-start,#ev-f-end{min-width:0}
#ev-f-place{min-width:0}
#ev-f-desc{min-height:80px}
#ev-new{flex:0 0 auto}
#ev-full{font-size:16px}

/* ====================== carte (evmap.js) ====================== */
/* CES NOMS VIENNENT DU BLOC `CONTRAT CSS` EN FIN D'evmap.js. Le widget monte sa propre
   racine `.ev-map-root` DANS le `#ev-map` d'events.js (renommée exprès : la collision
   avec `.ev-map` était certaine). C'est donc `.ev-map-root` qui doit porter le
   positionnement, le rognage et une HAUTEUR NON NULLE — sans quoi le SVG garde le ratio
   de son viewBox (mesuré : 745 px de haut dans une colonne de 306, débordant de 540 px
   sous le volet, boutons de zoom et mention de licence hors écran). */
#ev-map{flex:1 1 auto;min-height:160px;min-width:0;display:flex;overflow:hidden}
.ev-map-root{
  position:relative;overflow:hidden;flex:1 1 auto;
  width:100%;height:100%;min-height:160px;min-width:0;
  border:1px solid var(--line);border-radius:10px;background:var(--panel);
}
.ev-map-spacer{min-height:160px;pointer-events:none}
.ev-map-svg{display:block;width:100%;height:100%;background:var(--panel);touch-action:none}
.ev-map-root.ev-map-picking{cursor:crosshair}
.ev-map-root.ev-map-dragging{cursor:grabbing}

/* Barre d'outils EN SURIMPRESSION (haut-droite) et non dans le flux : dans le flux elle
   poussait le SVG et sortait de l'écran en fenêtre étroite. */
.ev-map-tools{
  position:absolute;top:8px;right:8px;z-index:2;
  display:flex;flex-direction:column;gap:5px;
}
.ev-map-btn{
  width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;
  background:var(--panel2);color:var(--txt);border:1px solid var(--line);
  border-radius:7px;font:600 15px/1 inherit;cursor:pointer;box-shadow:0 1px 4px var(--shadow);
}
.ev-map-btn:hover{border-color:var(--acc);color:var(--acc)}
.ev-map-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--focus)}

/* Bandeau du mode placement : EN BAS. En haut il masquerait le nord de la carte,
   c'est-à-dire une région d'événements. */
.ev-map-hint{
  position:absolute;left:8px;right:8px;bottom:8px;z-index:2;
  display:flex;gap:8px;align-items:center;
  background:var(--acc);color:var(--on-acc);
  border-radius:8px;padding:6px 10px;font-size:12px;box-shadow:0 2px 8px var(--shadow);
}
.ev-map-hint[hidden]{display:none}
.ev-map-hint-txt{flex:1;min-width:0}
.ev-map-cancel{
  background:transparent;color:var(--on-acc);border:1px solid var(--on-acc);
  border-radius:6px;padding:2px 8px;font:600 12px/1.4 inherit;cursor:pointer;
}
.ev-map-cancel:focus-visible{outline:none;box-shadow:0 0 0 2px var(--focus)}

/* Mode dégradé (asset absent ou illisible) : la carte se replie sur un graticule et le
   DIT — règle 6, jamais d'interface muette. */
.ev-map-msg{
  position:absolute;left:8px;top:8px;max-width:70%;z-index:2;
  background:var(--warn-bg);border:1px solid var(--warn-line);color:var(--warn);
  border-radius:8px;padding:5px 9px;font-size:12px;
}
.ev-map-empty{
  position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);
  text-align:center;color:var(--mut);font-size:13px;pointer-events:none;
}
/* OBLIGATION DE LICENCE (Licence Ouverte / Etalab) : la mention de source peut être
   TRONQUÉE, jamais masquée. Ni `display:none`, ni `visibility:hidden` ici — un test le
   vérifie, parce que c'est le seul endroit du projet où l'on peut manquer à cette
   licence. Elle est lue DANS l'asset par evmap.js, pas codée en dur. */
.ev-map-credit{
  position:absolute;left:8px;bottom:8px;right:44px;z-index:1;
  color:var(--mut);font-size:10px;line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;
}
/* Région d'annonce pour lecteur d'écran : masquée VISUELLEMENT et jamais par
   `display:none` — sinon elle cesse d'être lue, ce qui est exactement l'inverse du but. */
.ev-map-live{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ---- contenu SVG ---- */
/* `vector-effect:non-scaling-stroke` est posé en ATTRIBUT par evmap.js ; sans lui un
   zoom ×8 épaissit les frontières jusqu'à noyer les petits départements. */
.ev-grid{pointer-events:none}
.ev-grid-line{stroke:var(--line);stroke-width:1;stroke-dasharray:3 5;fill:none}
.ev-geo{pointer-events:auto}
/* Le stroke est volontairement plus contrasté que `--line` : en thème clair, un
   département `--panel2` cerné de `--line` sur un fond `--panel` est presque invisible,
   et la Corse — petit polygone détaché — se confond avec le fond. */
.ev-dept{fill:var(--panel2);stroke:var(--mut);stroke-width:.6;stroke-opacity:.55}
.ev-dept:hover{fill:var(--input)}

/* Fond en tuiles OpenStreetMap. C'est du BITMAP : il ne suit aucun des 5 thèmes, et
   aucune retouche CSS ne le fera — la règle 3 s'arrête là où la donnée est une image.
   Ce qu'on peut faire, et qui compte, c'est le RECULER : une carte routière est un
   décor chargé de traits colorés, sur lequel les pastilles d'événements se perdent.
   Une légère désaturation rend la hiérarchie au premier plan sans dénaturer le fond.
   `pointer-events:none` : les tuiles ne doivent jamais intercepter le clic de
   placement ni le glissé — c'est le SVG qui écoute, pas le décor. */
.ev-tiles{pointer-events:none}
.ev-tile{filter:saturate(.72)}
/* Sur un fond mondial, les contours vectoriels sont vides ; la règle ne s'applique
   donc à rien tant que les tuiles répondent, et redevient seule au repli. */

.ev-pins{pointer-events:auto}
.ev-pin{cursor:pointer}
.ev-pin:focus-visible{outline:none}
.ev-pin:focus-visible .ev-pin-halo{stroke:var(--focus);stroke-width:3;fill:none}
.ev-pin-dot{fill:var(--mut);stroke:var(--panel);stroke-width:1.5}
.ev-pin:hover .ev-pin-dot{fill:var(--txt2)}
/* L'anneau de sélection est un ANNEAU, pas un grossissement : deux points voisins qui
   grossissent se recouvrent. Il est `fill:none` par défaut et n'apparaît qu'avec
   `.ev-pin-sel` — peint en `--acc`, jamais en `--panel` (mesuré : un halo `--panel` est
   exactement la couleur du fond du volet, donc invisible dans les cinq thèmes). */
.ev-pin-halo{fill:none;stroke:none}
.ev-pin-mine .ev-pin-dot{fill:var(--acc)}
.ev-pin-cluster .ev-pin-dot{fill:var(--txt2);stroke-width:2}
/* Le compteur d'un groupe : PAS de `font-size` ici — evmap.js le pose en style inline,
   et c'est ce qui le garde constant à l'écran quel que soit le zoom. */
.ev-pin-count{fill:var(--on-acc);font-weight:700;pointer-events:none}
.ev-pin-cluster .ev-pin-count{fill:var(--bg)}
.ev-pin-sel .ev-pin-dot{fill:var(--acc)}
.ev-pin-sel .ev-pin-halo{stroke:var(--acc);stroke-width:2.5;stroke-opacity:.75}
/* Point PROVISOIRE du placement : pointillé, pour qu'il ne se confonde pas avec un
   événement réellement enregistré. */
/* ----------------------- carnet d'inscrits (fiche détail) ----------------------- */
/* Visible du seul organisateur (et de l'administrateur qui modère) : c'est la seule
   donnée personnelle du volet — qui sera où, et quand. Rendu sobre, en colonne, pour
   qu'une soirée à vingt inscrits reste lisible sans faire défiler la fiche entière. */
.ev-d-regs{margin-top:10px;padding-top:8px;border-top:1px solid var(--line)}
.ev-reglist{
  list-style:none;margin:4px 0 0;padding:0;
  display:flex;flex-wrap:wrap;gap:4px 6px;max-height:9em;overflow:auto;
}
.ev-reg{
  font-size:11.5px;padding:1px 8px;border-radius:999px;
  color:var(--txt2);background:var(--panel2);border:1px solid var(--line);
}

/* MARQUEUR DU POINT CHOISI (mode placement). Il doit se distinguer au premier coup d'œil
   des épingles d'événements, qui l'entourent : teinte d'avertissement, halo permanent et
   pulsation. Sans le halo, un point posé au milieu d'une grappe d'événements existants
   était indiscernable d'eux — on ne savait pas si le clic avait pris. */
.ev-pin-draft .ev-pin-dot{fill:var(--warn);stroke:var(--panel);stroke-width:1.5}
.ev-pin-draft .ev-pin-halo{
  stroke:var(--warn);stroke-width:1.5;stroke-dasharray:3 2;opacity:.9;
  animation:ev-draft-pulse 1.6s ease-in-out infinite;
}
@keyframes ev-draft-pulse{
  0%,100%{opacity:.85;transform:scale(1)}
  50%    {opacity:.35;transform:scale(1.25)}
}
/* Respect de « prefers-reduced-motion » : la pulsation est un confort, pas l'information
   (le halo pointillé suffit à repérer le point). */
@media (prefers-reduced-motion: reduce){
  .ev-pin-draft .ev-pin-halo{animation:none}
}
.ev-leg{stroke:var(--mut);stroke-width:1;stroke-dasharray:2 3;fill:none;pointer-events:none}

/* Repli quand evmap.js est absent (règle 6 : le volet reste utilisable sans la carte —
   liste, filtre, fiche et inscription fonctionnent, seule la POSE d'un point est
   impossible, et on le dit). */
.ev-map-missing{
  margin:auto;padding:18px;text-align:center;color:var(--mut);font-size:13px;
}
.ev-map-root.ev-map-degraded .ev-map-svg{background:var(--bg)}

/* ====================== fenêtre étroite ====================== */
/* La carte passe AU-DESSUS de la liste et sa hauteur est PLAFONNÉE : c'est la liste qui
   porte l'information, elle ne doit jamais se faire écraser. Le plancher (200 px) et le
   plafond (320 px) sont tenus par un `clamp` sur `.ev-mapcol`, et `.ev-map-root` rogne
   ce qui dépasse — sans ce rognage, mesuré à 820 px de large : 540 px de carte peints
   sous le bas du volet, invisibles (le volet est `position:fixed`, donc pas de barre de
   défilement pour le signaler) avec les contrôles de zoom et la mention Etalab. */
@media (max-width:900px){
  .ev-body{flex-direction:column}
  .ev-mapcol{order:1;flex:0 0 clamp(200px,32vh,320px);min-height:0;overflow:hidden}
  .ev-side{order:2;flex:1 1 auto;border-right:none;border-top:1px solid var(--line)}
  .ev-detail{max-height:60%}
}
@media (max-width:560px){
  .ev-mapcol{flex:0 0 clamp(180px,28vh,260px);padding:6px}
  .ev-head{padding:8px 10px}
  .ev-r-date,.ev-r-time{font-size:11px}
  .ev-map-credit{right:40px;font-size:9px}
}


/* ---------------------------------------------------------------- COUCHES (v0.6.171) --
   Trois natures de points cohabitent sur la carte, et le filtre ne sert a rien si on ne
   les distingue pas a l'oeil : la teinte du `.ev-pin-dot` porte donc la nature. Les trois
   sont des TOKENS — aucune couleur litterale (regle 3), et elles restent lisibles dans les
   cinq themes. */
.ev-layers{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:2px}
.ev-layers-lbl{font-size:11px;color:var(--mut);text-transform:uppercase;letter-spacing:.05em}
.ev-layer{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--txt2);cursor:pointer}
/* `width` explicite : `search.css` pose `input{width:100%}` en global, et une case a
   cocher de 305 px de large a deja ete mesuree une fois (panneau de maintenance,
   v0.6.164). */
.ev-layer input{width:15px;height:15px;flex:0 0 auto;accent-color:var(--acc)}
.ev-layer-nm{white-space:nowrap}
/* Le bouton « Ma presence » ferme la ligne, pousse a droite : c'est une ACTION au milieu
   de trois filtres, et les coller ferait lire un quatrieme filtre. */
#ev-presence{margin-left:auto}
/* Bouton « Communauté », a cote de « Ma presence » : deux ACTIONS a la suite des trois
   filtres. `margin-left:auto` est deja pose par `#ev-presence`, qui les pousse tous deux
   a droite ; celui-ci ne fait que suivre. */
#ev-communities{margin-left:6px}

/* NATURE d'un point. `--mut` reste la teinte de l'evenement ordinaire (regle historique,
   inchangee) ; le joueur prend `--ok` et la communaute `--warn`, deux tokens deja portes
   par le volet, donc deja verifies dans les cinq themes. */
.ev-pin-event .ev-pin-dot{fill:var(--mut)}
.ev-pin-player .ev-pin-dot{fill:var(--ok)}
.ev-pin-place .ev-pin-dot{fill:var(--warn)}
/* L'ORDRE DE CES TROIS LIGNES EST LEUR PRIORITE, puisqu'elles ont toutes la meme
   specificite (0,2,0) — meme convention que les etats d'une ligne de liste, plus haut.
   nature < « c'est a moi » < « c'est selectionne ».

   `.ev-pin-mine` et `.ev-pin-sel` sont REPETES ICI, et ce n'est pas un doublon a nettoyer :
   ils sont declares plus haut, donc AVANT les trois regles de nature, donc perdants. Sans
   cette reprise, l'epingle selectionnee reprenait la teinte de sa nature et le clic depuis
   la liste ne se voyait plus — regression introduite par les couches, et rattrapee en
   relisant l'ordre du fichier plutot qu'a l'ecran. */
.ev-pin-mine .ev-pin-dot{fill:var(--acc)}
.ev-pin-sel .ev-pin-dot{fill:var(--acc)}

/* Fente de la presence, remplie par `players.js`. La feuille de ce module-la fait tout
   l'aspect ; ce qui se decide ICI est sa place dans la colonne : elle ne doit ni pousser
   la liste hors de l'ecran, ni se retracter quand la fiche est longue. */
/* La fente de la présence PARTAGE la colonne avec la liste, elle ne s'ajoute pas dessous.
   `flex:0 1 auto` + `min-height:0` : elle prend la hauteur de son CONTENU, rétrécit (et
   défile en interne) quand la colonne est trop courte, et ne s'étire JAMAIS — le `1 1`
   essayé d'abord faisait bâiller une fiche de trois lignes sur la moitié de la colonne dès
   que la liste d'événements était courte. C'est la LISTE qui absorbe le mou (`flex:1 1`).
   La première écriture disait
   `flex:0 0 auto;max-height:52vh` — un bloc qui refuse de rétrécir dans une colonne qui
   ne rétrécissait pas non plus, donc deux raisons de sortir de l'écran. `52vh` mesurait en
   plus la FENÊTRE, pas la colonne : sur un volet court, la moitié de la fenêtre est déjà
   plus que toute la place restante. */
#ev-players{flex:0 1 auto;min-height:0;overflow:auto}

/* ============================ USAGE MOBILE (v0.6.162) ============================
   La disposition est déjà traitée plus haut (900 px et 560 px). Ne manquait que le
   POINTEUR : le volet est celui qu'on consulte le plus vraisemblablement en déplacement,
   une carte à la main. Registre des seuils : section mobile de search.css. */
@media (hover:none){
  /* Boutons de fiche et d'en-tête : ~26 px de haut avec leur padding. */
  .ev-btn{min-height:40px}
  .ev-hbtn{min-height:40px;min-width:40px}
  /* Les contrôles de zoom de la carte sont posés en absolu dans un coin : au doigt, un
     bouton de 24 px à 8 px du bord est presque impossible à atteindre sans déplacer la
     carte au lieu de zoomer. */
  .ev-map-btn{min-width:40px;min-height:40px}
  /* Le champ de filtre et le sélecteur de visibilité sont les deux seules saisies du
     volet : ils doivent accepter le doigt sans zoom du navigateur (16 px est le seuil
     en dessous duquel iOS zoome automatiquement sur le champ focalisé). */
  #ev-filter,.ev-f input,.ev-f select,.ev-f textarea{min-height:40px;font-size:16px}
}
