/* =========================================================
   ZonEvents — Design tokens
   Palette inspirée du Comminges/Pyrénées : forêts, vallées,
   lumière de fin de journée sur les crêtes.
   ========================================================= */
/* Icônes Google Material Symbols — remplace Font Awesome */
.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.material-symbols-outlined.filled {
  font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.em-spin {
  display: inline-block;
  animation: em-spin-rotate 1s linear infinite;
}
@keyframes em-spin-rotate {
  to { transform: rotate(360deg); }
}

/* Taille d'icône par défaut pour les boutons circulaires icône-seule
   (n'avaient pas besoin de font-size explicite avec Font Awesome, dont le
   rendu diffère légèrement de Material Symbols) */
.topbar__locate-btn .material-symbols-outlined,
.topbar__icon-btn .material-symbols-outlined,
.event-card__fav .material-symbols-outlined,
.event-card__close .material-symbols-outlined,
.event-card__nav .material-symbols-outlined {
  font-size: 24px;
}

:root {
  --em-nynjas: #990000;        /* couleur de marque unique — fusion de l'ancien --em-forest (identité principale) et --em-heart (rouge favori, différent avant) */
  --em-forest-dark: #1F4531;
  --em-amber: #E2A83A;        /* lumière de fin de journée — accent */
  --em-amber-dark: #C68F27;
  --em-alpine-blue: #517BBE;  /* lacs/ciel — info, liens secondaires */
  /* --em-heart retirée — fusionnée dans --em-nynjas ci-dessus */
  --em-stone-50: #F7F5F0;
  --em-stone-100: #EDEAE2;
  --em-stone-700: #4A4C46;
  --em-stone-900: #2B2C28;

  --em-font-display: "Google Sans", sans-serif;
  --em-font-body: "Work Sans", -apple-system, BlinkMacSystemFont, sans-serif;

  --em-radius: 14px;
  --em-shadow: 0 8px 28px rgba(43, 44, 40, 0.16);
}

* { box-sizing: border-box; }

/* Liens : pas de soulignement (jamais, même au survol), mis en gras à la
   place pour rester visuellement distincts du texte courant, en jaune
   (couleur d'accent de la marque) — sauf au survol, où ils prennent la
   couleur de fond des boutons principaux du site (rouge de marque), pour
   un vrai retour visuel distinct de l'état normal. */
a, a:visited, a:active {
  text-decoration: none;
  font-weight: 600;
  color: var(--em-amber);
}
a:hover {
  text-decoration: none;
  font-weight: 600;
  color: var(--em-nynjas);
}

/* Sélection de texte/image désactivée partout, sauf dans les vrais champs
   de saisie (sinon copier une adresse ou un mot-clé deviendrait impossible). */
body {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}
input, textarea, [contenteditable="true"] {
  -webkit-user-select: text;
  -moz-user-select: text;
  user-select: text;
}
img {
  -webkit-user-drag: none;
  user-drag: none;
}

html, body {
  height: 100%;
  margin: 0;
  font-family: var(--em-font-body);
  color: var(--em-stone-900);
  background: var(--em-stone-100);
  overscroll-behavior: none;
  /* Complète la balise viewport (maximum-scale/user-scalable) — certains
     navigateurs (iOS Safari notamment) ignorent partiellement ces
     attributs pour raisons d'accessibilité et autorisent quand même le
     pincement. touch-action supprime le geste de zoom au niveau CSS,
     tout en laissant le défilement normal (pan-x/pan-y) fonctionner. Le
     zoom de la carte elle-même n'est pas concerné : Leaflet gère son
     propre touch-action sur #map, qui n'hérite pas de celui du body. */
  touch-action: pan-x pan-y;
}

/* =========================================================
   Écran de chargement — logo + marqueur qui rebondit
   ========================================================= */
.app-loader {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0px;
  background: #fff;
  transition: opacity 0.35s ease, visibility 0.35s ease;
}
.app-loader.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.app-loader__marker {
  position: relative;
  width: 118px;
  height: 102px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.app-loader__mark {
  width: 96px;
  height: 96px;
  animation: em-loader-bounce 1.4s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

.app-loader__shadow {
  position: absolute;
  bottom: 0;
  width: 34px;
  height: 9px;
  border-radius: 50%;
  background: rgba(43, 44, 40, 0.2);
  animation: em-loader-shadow 1.4s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

.app-loader__title {
  font-family: var(--em-font-display);
  font-weight: 700;
  font-size: 2.4rem;
  letter-spacing: 0.02em;
  color: var(--em-nynjas);
}

.app-loader__count {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--em-stone-700);
  margin-top: 10px;
  font-variant-numeric: tabular-nums; /* évite que les chiffres "sautent" en largeur pendant l'incrémentation */
  min-height: 1.2em; /* réserve la place avant que le nombre n'arrive, pour ne pas décaler la version en dessous */
}
.app-loader__count strong {
  color: var(--em-nynjas);
  font-weight: 700;
}

@keyframes em-loader-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-20px); }
}
@keyframes em-loader-shadow {
  0%, 100% { transform: scale(1); opacity: 0.22; }
  50% { transform: scale(0.55); opacity: 0.1; }
}

@media (prefers-reduced-motion: reduce) {
  .app-loader__mark, .app-loader__shadow { animation: none; }
}

/* =========================================================
   Layout général
   ========================================================= */
#map {
  position: absolute;
  top: var(--em-topbar-h, 64px);
  bottom: 0; /* pleine hauteur — le footer flotte par-dessus (position fixed, z-index supérieur), la carte ne lui laisse plus une bande dédiée. Le décalage de centrage nécessaire est compensé par emCenterOnMarker() en JS plutôt qu'en réduisant la zone de la carte elle-même. */
  left: 0;
  right: 0;
  z-index: 0;
}

/* =========================================================
   Barre supérieure
   ========================================================= */
.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  min-height: 64px;
  z-index: 1500;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  row-gap: 8px;
  padding: 10px; /* uniforme (au lieu de 10px 14px) — aligne le bouton filtres avec les boutons flottants (+, réglages), tous à 10px du bord */
  background: var(--em-nynjas);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3); /* ombre portée nette vers le bas — l'ombre générale du site (--em-shadow) est plus douce/omnidirectionnelle, moins adaptée à une barre fixe qu'on veut clairement "au-dessus" du reste */
  /* La transition réelle est déclarée plus bas, combinée avec celle du
     décalage "right" (panneau qui pousse le contenu) — voir commentaire
     à cet endroit. La déclarer ici aussi n'aurait aucun effet (et prêterait
     à confusion) puisque cette autre règle, de même spécificité et plus
     bas dans le fichier, l'écraserait de toute façon. */
}
body.topbar-hidden .topbar {
  transform: translateY(-100%); /* tiroir poussé vers le haut, hors écran */
  pointer-events: none; /* ne bloque plus les clics sur la carte en dessous une fois masquée — sauf la poignée elle-même, remise à none ci-dessous */
}

/* Enfant DIRECT de .topbar (pas un élément séparé) — c'est ce qui la rend
   vraiment "attachée" : positionnée en absolu par rapport à la navbar
   elle-même (bottom:0, décalée de sa propre hauteur vers le bas), elle
   hérite automatiquement du transform du parent. Quand .topbar glisse de
   -100% (sa propre hauteur), la poignée — qui pendait juste sous son bord
   inférieur — se retrouve exactement en haut de l'écran (0 - hauteur
   poignée + hauteur poignée = 0), comme la poignée d'un vrai tiroir qui
   reste visible une fois le tiroir repoussé. Aucune règle séparée n'est
   nécessaire pour l'état masqué, ni pour le recentrage quand un panneau
   pousse le contenu (elle suit le rétrécissement de .topbar puisque son
   left:50% est relatif à la largeur RÉELLE de la navbar, pas de l'écran).
   Elle reste cliquable même quand la navbar est masquée (pointer-events
   remis à auto), contrairement au reste de la navbar. */
.topbar-handle {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translate(-50%, 100%);
  pointer-events: auto;
  width: auto;
  height: 33px;
  padding: 0 15px 0 10px;
  border: none;
  border-radius: 0 0 21px 21px;
  background: var(--em-nynjas);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3); /* même ombre que .topbar, pour que l'ensemble navbar+poignée paraisse porter une seule ombre cohérente */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  cursor: pointer;
}
.topbar-handle__icon {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
}
.topbar-handle__label {
  font-family: var(--em-font-display);
  font-weight: 600;
  font-size: 1.125rem;
  color: #fff;
  letter-spacing: 0.01em;
}

.topbar__search-brand {
  display: flex;
  align-items: center;
  gap: 2px;
  background: transparent;
  border: none;
  padding: 0 10px 0 0;
  margin-right: 4px;
  border-right: 1px solid var(--em-stone-100);
  flex-shrink: 0;
}

.topbar__mark {
  width: 32px;
  height: 32px;
  display: inline-block;
  flex-shrink: 0;
}

.topbar__name {
  font-family: var(--em-font-display);
  font-weight: 600;
  font-size: 1.4rem;
  letter-spacing: 0.01em;
  color: var(--em-nynjas);
}

.topbar__search {
  position: relative;
  flex: 1 1 240px;
  min-width: 0;
  display: flex;
  align-items: center;
  background: #fff;
  border-radius: 999px;
  height: 40px;
}

.topbar__mode-btn {
  border: none;
  background: var(--em-stone-100);
  color: var(--em-nynjas);
  display: flex;
  align-items: center;
  gap: 1px;
  padding: 0 6px;
  height: 40px;
  border-radius: 999px;
  flex-shrink: 0;
  cursor: pointer;
}
.topbar__mode-btn:hover { background: var(--em-stone-50); }
.topbar__mode-btn .material-symbols-outlined { font-size: 20px; }
.topbar__mode-chevron { font-size: 16px !important; opacity: 0.6; }

.topbar__search-input {
  flex: 1;
  border: none;
  outline: none;
  font-family: var(--em-font-body);
  font-size: 1rem;
  background: transparent;
  min-width: 0;
}

.topbar__clear-btn {
  border: none;
  background: none;
  color: var(--em-stone-700);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
}
.topbar__clear-btn:hover { background: var(--em-stone-100); }
.topbar__clear-btn .material-symbols-outlined { font-size: 25px; }

.topbar__locate-btn {
  border: none;
  background: var(--em-amber);
  color: #fff;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  transition: background 0.15s ease;
}
.topbar__locate-btn:hover { background: var(--em-amber-dark); }
.topbar__locate-btn.is-active { background: var(--em-alpine-blue); }

.topbar__suggestions {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: #fff;
  border-radius: 12px;
  box-shadow: var(--em-shadow);
  overflow: hidden;
  max-height: 260px;
  overflow-y: auto;
  z-index: 10;
}

.map-result-count {
  position: fixed;
  z-index: 960;
  bottom: calc(var(--em-footer-h, 30px) + 10px); /* même emplacement que .app-toast */
  left: 50%;
  transform: translateX(-50%);
  background: rgba(43, 44, 40, 0.7); /* même opacité que .app-toast */
  color: #fff;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 6px 14px;
  border-radius: 999px;
  box-shadow: var(--em-shadow);
  white-space: nowrap;
}

.topbar__suggestions button {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  padding: 10px 14px;
  font-size: 0.88rem;
  cursor: pointer;
}
.topbar__suggestions button:hover { background: var(--em-stone-100); }
.topbar__suggestion-icon {
  flex-shrink: 0;
  font-size: 18px;
  color: var(--em-nynjas);
}

.topbar__icon-btn {
  border: none;
  background: var(--em-amber);
  color: #fff;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.topbar__icon-btn:hover { background: var(--em-amber-dark); }

/* =========================================================
   Contrôle de rayon (flottant)
   ========================================================= */
.topbar__radius {
  display: flex;
  align-items: center;
  gap: 8px;
  background: rgba(255,255,255,0.12);
  border-radius: 999px;
  padding: 0 6px;
  height: 40px;
  flex: 1 1 0%;
  min-width: 0;
}

.topbar__radius-icon {
  color: white;
  font-size: 2rem;
  flex-shrink: 0;
}

.topbar__radius input[type="range"] {
  width: 90px;
  min-width: 0;
  flex: 1 1 auto;
  accent-color: var(--em-amber);
  cursor: pointer;
}

.topbar__radius-value {
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
  white-space: nowrap;
  min-width: 42px;
  flex-shrink: 0;
}

/* =========================================================
   Catégories (offcanvas filtres)
   ========================================================= */
.offcanvas {
  z-index: 1600 !important;
  --bs-offcanvas-width: min(400px, 88vw);
}
.offcanvas-header {
  padding-bottom: 0
}
/* Le panneau pousse le reste du site vers la gauche plutôt que de le
   recouvrir — la topbar et la carte se rétrécissent le temps qu'il est
   ouvert, ce qui permet d'interagir avec les deux en même temps. */
body.em-panel-open.em-panel-push .topbar,
body.em-panel-open.em-panel-push #map,
body.em-panel-open.em-panel-push #search-area-btn,
body.em-panel-open.em-panel-push .loading-bar,
body.em-panel-open.em-panel-push .app-footer {
  right: var(--bs-offcanvas-width, min(400px, 88vw)) !important;
}
/* .topbar et #map ont besoin de LEUR PROPRE transition complète ici aussi
   (voir le même piège déjà rencontré plus bas, à la règle ".topbar { ... }"
   générale) — cette règle-ci, plus spécifique (activée seulement quand un
   panneau pousse le contenu), écraserait sinon leur transition
   transform/top habituelle dès qu'un panneau est ouvert. */
body.em-panel-open.em-panel-push .topbar {
  transition: right 0.3s ease, transform 0.3s ease-in-out;
}
body.em-panel-open.em-panel-push #map {
  transition: right 0.3s ease, top 0.3s ease-in-out;
}
body.em-panel-open.em-panel-push #search-area-btn,
body.em-panel-open.em-panel-push .loading-bar,
body.em-panel-open.em-panel-push .app-footer {
  transition: right 0.3s ease;
}
body.em-panel-open.em-panel-push .fab,
body.em-panel-open.em-panel-push .zoom-slider-wrap {
  right: calc(var(--bs-offcanvas-width, min(400px, 88vw)) + 10px) !important;
  transition: right 0.3s ease;

}
body.em-panel-open.em-panel-push .event-card-layer {
  right: var(--bs-offcanvas-width, min(400px, 88vw)) !important;
  transition: right 0.3s ease;
}
body.em-panel-open.em-panel-push .modal {
  /* .modal a une largeur fixe à 100% par défaut (Bootstrap) — "right" seul
     ne la réduit pas, il faut explicitement recalculer la largeur. */
  width: calc(100% - var(--bs-offcanvas-width, min(400px, 88vw))) !important;
  transition: width 0.3s ease;
}
body.em-panel-open.em-panel-push .search-area-btn,
body.em-panel-open.em-panel-push .map-result-count {
  left: calc(50% - min(400px, 88vw) / 2);
  transition: left 0.3s ease;
}
/* .topbar et #map ont chacune DEUX raisons de bouger (le panneau qui pousse
   le contenu via "right", et la navbar/poignée qui se masque via "transform"
   pour .topbar / "top" pour #map) — les deux transitions doivent être
   listées ENSEMBLE dans une seule déclaration "transition", pas réparties
   dans deux règles séparées avec la même spécificité : la seconde règle
   déclarée écraserait entièrement la première (un bug déjà rencontré ici,
   qui empêchait le tiroir de la navbar de s'animer). */
.topbar {
  transition: right 0.3s ease, transform 0.3s ease-in-out;
}
#map {
  transition: right 0.3s ease, top 0.3s ease-in-out;
}

/* Mobile : panneau plein écran classique, avec fond noir (pas de push,
   pas assez de place pour laisser une bande de carte visible) */
@media (max-width: 560px) {
  .offcanvas {
    --bs-offcanvas-width: 100vw;
  }
}
.offcanvas-backdrop {
  z-index: 1590 !important;
}
.modal {
  z-index: 1700 !important;
}
.modal-backdrop {
  z-index: 1690 !important;
}
.category-filters {
  display: flex;
  flex-direction: column;
  gap: 0px;
}


.category-filter--global {
  margin-bottom: 4px;
}

.category-filter__icon--global {
  background: var(--em-stone-700);
}

.offcanvas-version {
  margin-top: auto;
  padding-top: 20px;
  font-size: 0.75rem;
  color: var(--em-stone-700);
  opacity: 0.7;
  text-align: center;
}

.offcanvas-update-btn {
  margin-top: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 0.8rem;
}

.offcanvas-support {
  background-color: black;
  margin-top: 10px;
  padding: 14px 10px;
}

.modal-header {
	background: var(--em-nynjas);
    color: white;
}

.legal-modal-body h3 {
  font-family: var(--em-font-display);
  font-size: 1rem;
  color: var(--em-nynjas);
  margin-top: 20px;
}
.legal-modal-body h3:first-child { margin-top: 0; }
.legal-modal-body p, .legal-modal-body li {
  font-size: 0.88rem;
  line-height: 1.5;
}
.legal-modal-body ul { padding-left: 20px; }

.category-filter {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 0;
}

.category-filter__icon {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 0.8rem;
  flex-shrink: 0;
}
.category-filter__icon .material-symbols-outlined {
  width: 1em;
  line-height: 1;
  text-align: center;
}

.category-filter__name {
  flex: 1;
  font-size: 0.92rem;
}

/* Couleur de catégorie sur chaque interrupteur (via --em-switch-color posée
   en inline style par js/app.js) */
.category-filters .form-check-input:checked {
  background-color: var(--em-switch-color, var(--em-nynjas));
  border-color: var(--em-switch-color, var(--em-nynjas));
}

.form-label {
  font-weight: bold;
}

/* Interrupteur global : toujours vert de marque, avec un état "mixte"
   (position centrale) quand seules certaines catégories sont actives */
#filter-global:checked {
  background-color: #198754;
  border-color: #198754;
}
#filter-favorites:checked {
  background-color: var(--em-nynjas);
  border-color: var(--em-nynjas);
}
#filter-show-past:checked {
  background-color: grey;
  border-color: grey;
}
#filter-global.is-mixed {
  background-position: center !important;
  background-color: var(--em-amber) !important;
  border-color: var(--em-amber) !important;
}

.category-filter-group {
  border-bottom: 1px solid var(--em-stone-100);
}
.category-filter-group:last-child { border-bottom: none; }

.category-filter-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  cursor: pointer;
}

.category-filter__chevron {
  color: var(--em-stone-700);
  font-size: 1.3rem;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.category-filter-header.is-expanded .category-filter__chevron {
  transform: rotate(180deg);
}

.category-filter-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 2px 0 10px 40px;
}

.category-filter-tag {
  border: 1px solid var(--em-tag-color, var(--em-stone-100));
  background: #fff;
  color: var(--em-tag-color, var(--em-stone-700));
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.78rem;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.category-filter-tag.is-active {
  background: var(--em-tag-color, var(--em-nynjas));
  border-color: var(--em-tag-color, var(--em-nynjas));
  color: #fff;
}

/* État mixte (certains tags actifs, pas tous) sur un interrupteur de
   catégorie — même traitement visuel que le switch global. */
.category-filter__switch-wrap input.is-mixed {
  background-position: center !important;
  background-color: var(--em-amber) !important;
  border-color: var(--em-amber) !important;
}

/* =========================================================
   Markers Leaflet personnalisés
   ========================================================= */
.em-marker-wrapper {
  position: relative;
  width: 34px;
  height: 34px;
  transition: transform 0.15s ease;
}
.em-marker-wrapper:hover {
  /* Même effet que .em-establishment-wrapper:hover, à la demande explicite
     — un agrandissement grossit aussi la vraie zone cliquable, ce qui
     avait été évité ici jusque-là par prudence (risque de scintillement
     si le curseur se retrouve pile au bord de la zone agrandie). Les
     établissements utilisent ce même effet sans souci connu à ce jour ;
     à surveiller si le symptôme réapparaît sur les événements.
     Le passage au premier plan se fait via l'API Leaflet
     (setZIndexOffset), pas ici — voir js/app.js. */
  transform: scale(1.3);
}

.em-marker {
  width: 34px;
  height: 34px;
  border-radius: 50% 50% 50% 4px;
  transform: rotate(-45deg);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(0,0,0,0.35);
  border: 2px solid #fff;
}

.em-marker-fav-badge {
    position: absolute;
    top: -3px;
    left: -5px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    -webkit-text-stroke: 1.5px #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--em-nynjas);
    font-size: 20px;
    line-height: 1;
    pointer-events: none;
}
/* Position différente sur un marqueur d'établissement (carré) que sur un
   marqueur d'événement (goutte) — la forme et les proportions ne sont pas
   les mêmes, la même position ne convenait pas aux deux. */
.em-establishment-marker .em-marker-fav-badge {
    top: -8px;
    left: -9px;
}

.em-marker .material-symbols-outlined {
  transform: rotate(45deg);
  color: #fff;
  /* font-size: 2em; */
  width: 1em;
  line-height: 1;
  text-align: center;
}

.em-marker--past {
  opacity: 0.5;
}

.em-cluster-wrapper {
  background: transparent;
  border: none;
  transition: transform 0.15s ease;
}
/* Un cluster contenant un boosté passe toujours devant les autres,
   indépendamment du calcul automatique de z-index par latitude que fait
   Leaflet pour tout marqueur (y compris les clusters) — sinon un cluster
   boosté peut se retrouver visuellement caché derrière un voisin selon sa
   position exacte, malgré son halo pulsé. !important nécessaire : Leaflet
   fixe lui-même un z-index en style inline sur chaque icône. */
.em-cluster-wrapper:has(.em-cluster--boosted) {
  z-index: 10000 !important;
}
.em-cluster-wrapper:hover,
.em-cluster-wrapper.em-hovered {
  /* Même effet que .em-marker-wrapper:hover ci-dessus, voir sa note sur
     le changement de choix (scale plutôt que filtre). Le survol CSS
     classique (:hover) est gardé en filet de sécurité, mais le
     déclencheur principal est la classe .em-hovered, ajoutée/retirée en
     JS via délégation DOM (voir js/app.js) — plus fiable ici, la
     structure DOM d'un cluster semblant échapper au :hover seul dans
     certains cas. */
  transform: scale(1.3);
}
.em-cluster {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--em-nynjas);
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid rgba(255,255,255,0.85);
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
/* Un cluster qui contient au moins un événement boosté (voir
   iconCreateFunction de markerCluster dans js/app.js) — pulsation propre
   (pas les mêmes keyframes que le marqueur boosté individuel : celles-ci
   incluent une rotation -45deg pensée pour la forme "goutte" de
   .em-marker, qui ferait pencher le chiffre affiché dans une bulle ronde).
   La bordure jaune reprend la même couleur de reconnaissance. */
.em-cluster--boosted {
  border-color: #FFD400;
  animation: em-cluster-boost-pulse 1.4s ease-in-out infinite;
}
/* Une bulle de cluster FERMÉE reste bien plus isolée de ses voisines
   qu'un marqueur mélangé dans l'éventail serré d'un cluster ouvert
   (Leaflet espace déjà les bulles d'un rayon minimal) — un agrandissement
   ici ne risque pas de voler le clic d'une bulle/d'un marqueur voisin,
   contrairement au marqueur boosté individuel (voir plus bas, traité
   différemment pour cette raison). */
@keyframes em-cluster-boost-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.2); }
}
@media (prefers-reduced-motion: reduce) {
  .em-cluster--boosted { animation: none; }
}

/* Balayage radar sur le disque de rayon pendant le chargement d'une
   recherche — un faisceau qui tourne avec une traînée qui s'estompe,
   comme un écran de sonar. Purement décoratif (pointer-events désactivés
   plus haut, via l'option interactive:false du marqueur) — n'affecte
   jamais les clics sur la carte en dessous. */
.em-radar-sweep {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  overflow: hidden;
  pointer-events: none;
}
.em-radar-sweep__beam {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    rgba(226, 168, 58, 0) 0deg,
    rgba(226, 168, 58, 0) 270deg,
    rgba(226, 168, 58, 0.55) 350deg,
    rgba(226, 168, 58, 0.9) 360deg
  );
  transform-origin: 50% 50%;
  animation: em-radar-rotate 2.2s linear infinite;
}
@keyframes em-radar-rotate {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .em-radar-sweep__beam { animation: none; }
}

.em-origin-marker {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  /* border: 3px solid #fff; */
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.em-origin-marker .material-symbols-outlined {
  font-size: 25px;
}

/* Position réelle (géolocalisation navigateur) — pulsation façon "vous êtes ici" */
.em-origin-marker--geo {
  background: var(--em-alpine-blue);
  box-shadow: 0 0 0 4px rgba(74,127,165,0.3), 0 2px 6px rgba(0,0,0,0.3);
  animation: em-geo-pulse 2.2s ease-out infinite;
}

/* Centre de recherche choisi manuellement (adresse, clic sur la carte,
   centre par défaut) — statique, couleur ambre pour ne pas le confondre
   avec la géolocalisation réelle. */
/* Centre de recherche choisi manuellement (adresse, clic sur la carte,
   centre par défaut) — simple réticule en croix, volontairement sans
   pastille colorée pour ne pas le confondre avec le bouton "+" d'ajout
   d'événement. */
.em-origin-marker--crosshair {
  position: relative;
  width: 28px;
  height: 28px;
}
.em-origin-marker--crosshair span {
  position: absolute;
  background: rgba(255, 255, 255, 0.75);
}
.em-origin-marker--crosshair span:first-child {
  top: 50%;
  left: 3px;
  right: 3px;
  height: 1px;
  transform: translateY(-50%);
}
.em-origin-marker--crosshair span:last-child {
  left: 50%;
  top: 3px;
  bottom: 3px;
  width: 1px;
  transform: translateX(-50%);
}

@keyframes em-geo-pulse {
  0%   { box-shadow: 0 0 0 4px rgba(74,127,165,0.3), 0 2px 6px rgba(0,0,0,0.3); }
  70%  { box-shadow: 0 0 0 16px rgba(74,127,165,0), 0 2px 6px rgba(0,0,0,0.3); }
  100% { box-shadow: 0 0 0 4px rgba(74,127,165,0), 0 2px 6px rgba(0,0,0,0.3); }
}

/* =========================================================
   Événements boostés (mise en avant payante) — toujours visibles quelle
   que soit la recherche en cours (voir php/api/events.php). Membre normal
   du même cluster que les events classiques (voir markerCluster dans
   js/app.js), à la MÊME taille qu'un marqueur normal désormais — un
   marqueur agrandi débordait sur ses voisins une fois mélangé à d'autres
   dans l'éventail serré d'un cluster ouvert. Seules la bordure jaune
   (même épaisseur que la bordure blanche d'un marqueur normal, 2px) et
   le halo pulsé (même principe que .em-geo-pulse pour "vous êtes ici",
   ci-dessus, en jaune) le distinguent désormais.
   ========================================================= */
.em-boosted-wrapper {
  position: relative;
  width: 34px;
  height: 34px;
}
.em-boosted-wrapper:hover .em-marker {
  /* rotate(-45deg) inchangé (forme de goutte) — un scale en plus poserait
     le même risque de scintillement que sur les marqueurs normaux (voir
     .em-marker-wrapper:hover un peu plus haut). */
  filter: drop-shadow(0 0 4px rgba(0,0,0,0.5)) brightness(1.12);
}
.em-boosted-wrapper .em-marker {
  width: 34px;
  height: 34px;
  border: 2px solid #FFD400;
  box-shadow: 0 0 0 4px rgba(255,212,0,0.35), 0 2px 6px rgba(0,0,0,0.35);
  animation: em-boost-pulse 2.2s ease-out infinite;
  transition: filter 0.15s ease;
}
/* Un halo en box-shadow (jamais un scale) ne change jamais la taille ni la
   zone cliquable réelle du marqueur — contrairement à un agrandissement,
   qui pouvait voler le clic d'un marqueur voisin plus petit juste à côté
   une fois plusieurs marqueurs serrés au même endroit. Le box-shadow de
   base (ombre portée + halo au repos) est repris à chaque étape car
   l'animation REMPLACE toute la valeur, elle ne s'ajoute pas dessus. */
@keyframes em-boost-pulse {
  0%   { box-shadow: 0 0 0 4px rgba(255,212,0,0.35), 0 2px 6px rgba(0,0,0,0.35); }
  70%  { box-shadow: 0 0 0 12px rgba(255,212,0,0), 0 2px 6px rgba(0,0,0,0.35); }
  100% { box-shadow: 0 0 0 4px rgba(255,212,0,0), 0 2px 6px rgba(0,0,0,0.35); }
}
@media (prefers-reduced-motion: reduce) {
  .em-boosted-wrapper .em-marker { animation: none; }
}

/* =========================================================
   Établissements PRO (abonnement) — présence permanente, indépendante des
   dates, jamais mêlée aux clusters d'événements (couche séparée en JS,
   voir establishmentLayer). Carré DROIT (pas pivoté, contrairement au
   marqueur événement) à coins arrondis, avec un pointeur triangulaire
   blanc séparé en dessous, qui reste inchangé pendant le morphing vers la
   fiche (seuls le carré et son contenu s'agrandissent, voir plus bas).
   Contour blanc, même épaisseur que le marqueur événement (2px).
   ========================================================= */
.em-establishment-wrapper {
  position: relative;
  width: 40px;
  height: 47px; /* carré (40px) + pointeur (7px) — correspond à iconSize en JS */
  transition: transform 0.15s ease;
}
.em-establishment-wrapper:hover {
  transform: scale(1.3);
}
.em-establishment-wrapper.is-expanded:hover {
  transform: none; /* pas d'agrandissement du carré une fois la fiche dépliée — déformerait toute la fiche, qui en est un enfant direct */
}
.em-establishment-marker {
  width: 40px;
  height: 40px;
  border-radius: 5px;
  background: #fff;
  border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(0,0,0,0.35);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.em-establishment-marker__inner {
  overflow: hidden;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.em-establishment-marker__inner img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.em-establishment-marker__inner .material-symbols-outlined {
  color: var(--em-nynjas);
  font-size: 22px;
}
.em-establishment-pointer {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  filter: drop-shadow(0 2px 1px rgba(0,0,0,0.25));
}
.em-establishment-cluster-wrapper { background: transparent; border: none; }
.em-establishment-cluster {
  width: 34px;
  height: 34px;
  border-radius: 10px; /* pas de rotation/pointe ici — un cluster ne pointe pas vers un lieu précis, contrairement à un marqueur individuel */
  background: #fff;
  color: var(--em-nynjas);
  font-weight: 700;
  font-size: 0.8rem;
  border: 2px solid var(--em-nynjas); /* couleurs inversées par rapport à avant (fond blanc, bordure colorée) — pour se distinguer visuellement des clusters d'événements (.em-cluster), fond coloré/bordure blanche */
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Marqueur établissement : replié par défaut (carré + pointeur, jamais
   affectés eux-mêmes par le dépliage). La fiche dépliée, elle, est un
   élément DOM SÉPARÉ (voir #establishment-expanded dans index.html),
   repositionné en JS sur la position écran réelle du marqueur à chaque
   clic et à chaque déplacement de la carte — pas un enfant imbriqué du
   marqueur (une tentative précédente avec position:absolute imbriquée
   dans le DOM du marqueur Leaflet produisait un décalage de
   positionnement inexpliqué, malgré des valeurs CSS correctes en
   apparence). */
.em-establishment-wrapper.is-expanded {
  z-index: 10000 !important; /* passe au-dessus des autres marqueurs — plus de marker.setZIndexOffset() disponible depuis la délégation DOM globale */
}
.em-report-modal {
  position: relative;
  pointer-events: auto;
  width: min(380px, calc(100vw - 28px));
  background: #fff;
  border-radius: 18px;
  box-shadow: var(--em-shadow);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.em-report-modal__topbar {
  background: var(--em-nynjas);
}
.em-report-modal__topbar-icon {
  color: #fff;
  margin-left: 4px;
  font-size: 22px;
}
.em-report-modal__topbar .event-card__close {
  color: #fff;
  background: transparent;
}
.em-boost-modal__topbar {
  background: linear-gradient(135deg, #FFC800, #FFA000); /* même famille de couleur que le halo pulsé des événements boostés (.em-cluster--boosted) */
}
.em-boost-modal__topbar-icon {
  color: #fff;
  margin-left: 4px;
  font-size: 22px;
}
.em-boost-modal__topbar .event-card__close {
  color: #fff;
  background: transparent;
}
.em-boost-modal__plans {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.em-boost-modal__plan {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--em-stone-200, #ddd);
  border-radius: 10px;
  padding: 10px 12px;
  cursor: pointer;
  font-size: 0.9rem;
}
.em-boost-modal__plan:has(input:checked) {
  border-color: #FFA000;
  background: #FFF8E1;
}
.em-boost-modal__plan input { accent-color: #FFA000; }
.em-boost-modal__plan-price { font-weight: 700; color: var(--em-stone-900); }
.em-report-modal__body {
  padding: 4px 16px 16px;
}
.em-report-modal__target {
  font-size: 0.82rem;
  color: var(--em-stone-700);
  margin: 0 0 10px;
}
.em-report-modal__textarea {
  width: 100%;
  border: 1px solid var(--em-stone-200, #ddd);
  border-radius: 10px;
  padding: 10px;
  font: inherit;
  font-size: 0.9rem;
  resize: vertical;
  box-sizing: border-box;
}
/* Piège à robots — un humain ne le voit jamais (voir report-modal-honeypot
   dans index.html) ; display:none seul est ignoré par certains bots qui
   scannent aussi les styles, donc position hors écran en plus. */
#report-modal-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}
.em-report-modal__submit {
  margin-top: 10px;
  width: 100%;
  border: none;
  border-radius: 10px;
  background: #198754; /* même vert que .btn-success (Bootstrap) — tout bouton de validation/confirmation reste cohérent d'un bout à l'autre du site */
  color: #fff;
  font-weight: 700;
  padding: 10px;
  cursor: pointer;
}
.em-report-modal__submit:disabled { background: #a8d5bd; cursor: default; } /* vert atténué plutôt qu'une simple opacité réduite — reste identifiable comme le même bouton, pas un gris ambigu */
#add-establishment-submit:disabled { background-color: #a8d5bd; opacity: 1; border-color: #a8d5bd; } /* même logique que .em-report-modal__submit ci-dessus — écrase l'opacité réduite par défaut de Bootstrap sur .btn-success:disabled */
.em-report-modal__submit:hover:not(:disabled) { background: #157347; }
.em-report-modal__status {
  font-size: 0.82rem;
  margin: 8px 0 0;
  text-align: center;
}
.em-report-modal__status--error { color: #c0392b; }
.em-report-modal__status--success { color: #2a7f4f; }

.em-establishment-expanded {
  position: relative;
  pointer-events: auto;
  width: min(420px, calc(100vw - 28px));
  max-height: 100%;
  background: #fff;
  border-radius: 18px;
  box-shadow: var(--em-shadow);
  transform-origin: center center;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Morphing (technique FLIP) : au moment de l'ouverture, l'élément démarre
   avec un transform calculé en JS pour visuellement coïncider avec la
   position/taille du marqueur cliqué, puis cette classe est ajoutée pour
   déclencher la transition vers sa position naturelle centrée (comme une
   fiche événement). */
.em-establishment-expanded.em-morphing {
  transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.em-establishment-expanded__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 16px;
  text-align: left;
}
.em-establishment-expanded__logo {
  display: block;
  max-width: 100%;
  max-height: 110px;
  object-fit: contain;
  margin: 0 auto 10px;
  cursor: pointer;
}
/* Sans ce correctif, l'attribut [hidden] de l'img est neutralisé : la règle
   de classe ci-dessus (display:block, même s'il ne s'agit pas de la même
   spécificité que [hidden], les styles auteur l'emportent toujours sur les
   styles par défaut du navigateur) l'emporterait silencieusement, gardant
   le logo visible même masqué en JS — même piège déjà rencontré ailleurs
   sur ce projet (voir .event-card-layer[hidden]). */
.em-establishment-expanded__logo[hidden] {
  display: none;
}
/* Rangée logo + galerie (voir emOpenEstablishmentCard dans js/app.js) —
   masquée entièrement si les deux sont vides. */
.em-establishment-expanded__media {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 10px;
}
.em-establishment-expanded__media[hidden] {
  display: none;
}
.em-establishment-expanded__media--logo-only {
  justify-content: center;
}
.em-establishment-expanded__media .em-establishment-expanded__logo {
  /* Dans cette rangée flex, le logo n'est plus seul centré — marges reprises
     à zéro, la largeur max le tient raisonnablement compact à côté de la
     galerie. */
  margin: 0;
  flex-shrink: 0;
  max-width: 110px;
}
.em-establishment-expanded__gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  flex: 1;
  min-width: 0;
}
.em-establishment-expanded__gallery[hidden] {
  display: none;
}
.em-establishment-expanded__gallery img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 6px;
  cursor: pointer;
}
.em-establishment-expanded__description {
  font-size: 0.88rem;
  line-height: 1.4;
  margin: 8px 0;
}
.em-establishment-expanded__row {
  font-size: 0.85rem;
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 6px 0;
  color: var(--em-stone-900);
}
.em-establishment-expanded__row a {
  color: var(--em-amber);
}
.em-establishment-expanded__row .material-symbols-outlined {
  font-size: 18px;
  flex-shrink: 0;
  margin-top: 1px;
  width: 18px; /* les icônes matérial-symbols ont une largeur variable selon le glyphe sans cette contrainte — désaligne les lignes entre elles sinon */
}
.em-establishment-expanded__link .material-symbols-outlined,
.em-establishment-expanded__link svg {
  font-size: 18px;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
.em-establishment-expanded__link {
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 6px 0;
  color: var(--em-amber); /* tous les liens en jaune ici, pas de lien "propre" à un événement pour justifier une exception de couleur */
  font-weight: 600;
}

@media (prefers-reduced-motion: reduce) {
  .em-origin-marker--geo { animation: none; }
}

/* =========================================================
   Fiche événement
   ========================================================= */
.event-card-layer {
  position: fixed;
  z-index: 1200;
  top: var(--em-topbar-h, 64px);
  bottom: var(--em-timeline-h, 34px);
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  pointer-events: none; /* laisse la carte cliquable autour de la fiche */
}
.event-card-layer[hidden] {
  display: none; /* l'attribut hidden seul peut être neutralisé par le display:flex ci-dessus (même spécificité, l'ordre de cascade décide) — cette règle, plus spécifique, garantit qu'il l'emporte toujours */
}
/* Flou d'arrière-plan pour les modales de confirmation (boost,
   signalement) — contrairement aux fiches événement/établissement, qui
   restent volontairement "posées" sur la carte sans l'assombrir. */
#report-modal-layer,
#boost-modal-layer {
  background: rgba(20,20,20,0.35);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  pointer-events: auto;
}

.event-card {
  position: relative;
  pointer-events: auto;
  width: min(420px, calc(100vw - 28px));
  max-height: 100%;
  background: #fff;
  border-radius: 18px;
  box-shadow: var(--em-shadow);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Fiche d'un event boosté — bordure jaune de reconnaissance, même épaisseur
   que celle des marqueurs (2px, voir .em-marker) — voir emRenderEventCard
   dans js/app.js pour la classe posée sur .event-card. */
.event-card.event-card--boosted {
  border: 2px solid #FFD400;
}
/* Même dégradé que la topbar de la modale de boost (em-boost-modal__topbar)
   — reconnaissable au premier coup d'œil comme un événement mis en avant. */
.event-card.event-card--boosted .event-card__topbar,
.event-card.event-card--boosted .event-card__toolbar {
  background: linear-gradient(135deg, #FFC800, #FFA000);
}
.event-card.event-card--boosted .event-card__close,
.event-card.event-card--boosted .event-card__toolbar-btn {
  color: #fff;
}
.event-card.event-card--boosted .event-card__toolbar-btn:hover {
  background: rgba(255,255,255,0.2);
}
.event-card.event-card--boosted .em-icon-boost {
  color: #fff; /* le jaune de .em-icon-boost se fondrait dans le dégradé doré de la barre déjà boostée */
}

.event-card__topbar {
  flex-shrink: 0;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--em-stone-100);
  padding: 0 8px;
}

.event-card__fav,
.event-card__close {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.event-card__fav {color: var(--em-nynjas);}
.event-card__fav.is-active i { font-weight: 900; }
.event-card__close {color: var(--em-stone-900);}

.event-card__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: transparent;
  /* box-shadow: 0 2px 8px rgba(0,0,0,0.18); */
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 2;
}
.event-card__nav--prev {/* left: 8px; */}
.event-card__nav--next {right: 0px;}

.event-card__body {
  flex: 1 1 auto;
  padding: 7px 40px 7px;
  overflow-y: auto;
}

.event-card__toolbar {
  flex-shrink: 0;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--em-stone-100);
  padding: 0 8px;
}

.event-card__title {
  font-family: var(--em-font-display);
  font-size: 1.3rem;
  margin: 0 0 8px;
  line-height: 1.25;
  text-align: center;
}

.event-card__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top; /* formats hors gabarit (portrait...) : garde le haut visible plutôt qu'un recadrage centré */
  cursor: pointer;
}
.event-card__image-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 12px;
  background: var(--em-stone-100);
  display: flex;
  align-items: center;
  justify-content: center;
}
.event-card__image-loader {
  /* Centré par le flex du parent ci-dessus, jamais par transform ici —
     .em-spin anime déjà transform (rotation), et un transform statique en
     plus (translate pour centrer) se faisait écraser à chaque image de
     l'animation plutôt que s'y combiner : le loader "sautait" au coin
     avant de tourner au lieu de tourner sur place. */
  position: absolute;
  font-size: 32px;
  color: var(--em-stone-400, #aaa);
}

.event-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 10px;
}
.event-card__tag {
  border: 1px solid var(--em-tag-color, var(--em-stone-100));
  color: var(--em-tag-color, var(--em-stone-700));
  border-radius: 999px;
  padding: 2px 10px;
  font-size: 0.72rem;
}

.event-card__category-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--em-badge-color, var(--em-nynjas));
  background: var(--em-badge-bg, rgba(45, 95, 66, 0.1));
  padding: 4px 10px;
  border-radius: 999px;
  margin-bottom: 6px;
}

.event-card__datetime,
.event-card__recurrences,
.event-card__address,
.event-card__price {
  font-size: 0.88rem;
  color: var(--em-stone-700);
  margin: 0 0 6px;
  display: flex;
  gap: 8px;
  align-items: flex-start;
}
.event-card__address a {
  color: inherit;
}
.event-card__datetime .material-symbols-outlined,
.event-card__recurrences .material-symbols-outlined,
.event-card__address .material-symbols-outlined,
.event-card__price .material-symbols-outlined,
.event-card__link .material-symbols-outlined {
  font-size: 18px;
  flex-shrink: 0;
  margin-top: 1px;
}

.event-card__description {
  font-size: 0.9rem;
  line-height: 1.5;
  margin: 12px 0;
  text-align: justify;
}

.event-card__link {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--em-alpine-blue);
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 6px;
}

.event-card__toolbar-btn {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--em-stone-900);
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.event-card__toolbar-btn:hover { background: rgba(0,0,0,0.06); }
.em-icon-boost {
  color: var(--em-amber);
  transform: rotate(180deg);
  display: inline-block;
}
.event-card__toolbar-btn--directions[hidden] { display: none; }
.event-card__toolbar-btn--translate[hidden] { display: none; }
.event-card__recurrences[hidden] { display: none; }
.event-card__address[hidden] { display: none; }
.event-card__price[hidden] { display: none; }

/* =========================================================
   Menu temporel — signature : lignes de niveau topographiques
   ========================================================= */
.app-footer {
  position: fixed;
  z-index: 1000;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 16px;
  background: #fff;
  border-top: 1px solid var(--em-stone-100);
  font-size: 0.72rem;
  color: var(--em-stone-700);
}
.app-footer__col:first-child { text-align: left; }
.app-footer__col:nth-child(2) { text-align: center; }
.app-footer__col:last-child { text-align: right; }
.app-footer__brand { color: var(--em-nynjas); } /* rouge de marque */
.app-footer__link {
  border: none;
  background: none;
  padding: 0;
  font-size: 0.72rem;
  color: var(--em-amber);
  font-weight: 600;
  cursor: pointer;
}

.topbar__dates {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  background: rgba(255,255,255,0.12);
  border-radius: 999px;
  padding: 0;
  height: 40px;
  flex: 0 1 auto;
  min-width: 0;
}

.topbar__date-field {
  position: relative;
  height: 40px;
  flex: 0 0 auto;
}

.topbar__date {
  border: none;
  border-radius: 999px;
  padding: 0 44px; /* place pour les deux boutons superposés (40px + petite marge) de chaque côté */
  height: 40px;
  font-size: 1rem;
  font-family: var(--em-font-body);
  text-align: center;
  min-width: 0;
  width: 190px; /* assez large pour afficher une date complète ("11/09/2026") sans être coupée, boutons compris */
  background: #fff;
  color: var(--em-stone-900);
  cursor: pointer;
}
.topbar__date:focus {
  outline: none;
  box-shadow: none;
}

.topbar__date-arrow {
  color: #fff;
  font-size: 1.5em;
  padding: 0 2px;
  flex-shrink: 0;
}

.topbar__date-inline-btn {
  position: absolute;
  top: 0;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: var(--em-amber);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 2;
  transition: background 0.15s ease;
}
.topbar__date-inline-btn:hover { background: var(--em-amber-dark); }
.topbar__date-inline-btn .material-symbols-outlined { font-size: 20px; }
.topbar__date-inline-btn--left { left: 0; }
.topbar__date-inline-btn--right { right: 0; }

.topbar__date-lock-btn {
  border: none;
  background: none;
  color: #fff;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  opacity: 0.85;
}
.topbar__date-lock-btn:hover { opacity: 1; background: rgba(255,255,255,0.15); }
.topbar__date-lock-btn.is-locked { color: var(--em-amber); opacity: 1; }
.topbar__date-lock-btn .material-symbols-outlined { font-size: 20px; }

/* =========================================================
   Bouton ajouter un événement (FAB)
   ========================================================= */
.fab {
  position: fixed;
  z-index: 1000;
  right: 10px;
  bottom: calc(var(--em-footer-h, 30px) + 10px);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: var(--em-amber);
  color: #fff;
  font-size: 1.3rem;
  /* Ombre plus marquée que --em-shadow (trop diffuse/discrète, pensée pour
     un fond clair uni) — un bouton posé directement sur la carte, aux
     couleurs très variables (vert, bleu, terrain...), a besoin d'un
     contraste plus net pour bien se détacher et paraître "flotter"
     au-dessus, quel que soit ce qu'il y a en dessous. */
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.fab:hover { background: var(--em-amber-dark); }
.fab--establishment {
  right: auto;
  left: 10px; /* côté opposé au FAB événement, plus empilé au-dessus */
  background: var(--em-amber);
}
.fab--establishment:hover { background: var(--em-amber-dark); }

/* Slider de zoom vertical — reconstruit "à la main" (pas un <input
   type="range"> natif) : son orientation verticale via -webkit-appearance:
   slider-vertical s'est révélée trop capricieuse (poignée mal centrée sur
   la glissière, style de poignée personnalisé pas toujours appliqué,
   incohérences entre navigateurs) — un simple div + JS donne un contrôle
   total et fiable sur l'alignement. Occupe toute la hauteur disponible
   entre la barre de recherche (--em-topbar-h, déjà calculée dynamiquement
   ailleurs sur le site) et le bouton + (même décalage à droite que lui,
   pour former un même groupe visuel). */
.zoom-slider-wrap {
  position: fixed;
  z-index: 1000;
  right: 10px;
  top: calc(var(--em-topbar-h, 64px) + 10px);
  bottom: calc(var(--em-footer-h, 30px) + 10px + 42px + 10px); /* juste au-dessus du bouton + (42px de haut, même taille que le bouton réglages) avec un peu d'air */
  width: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.zoom-slider__icon-btn {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border: none;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  cursor: pointer;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.6)); /* lisible sur un fond de carte clair comme sur un fond foncé */
}
.zoom-slider__icon-btn .material-symbols-outlined {
  font-size: 22px;
}
.zoom-slider__track {
  position: relative;
  flex: 1;
  width: 6px;
  border-radius: 999px;
  background: rgba(255,255,255,0.5); /* glissière blanche, opacité 0.5, comme demandé */
  cursor: pointer;
  touch-action: none; /* laisse notre propre logique de glisser-déposer gérer le geste, sans que le navigateur y mêle un défilement de page */
}
/* Poignée — positionnée en JS via "bottom" en pourcentage (0% = zoom
   minimal tout en bas, 100% = zoom maximal tout en haut), jamais avec
   "top" : plus simple à raisonner comme une valeur qui "monte" avec le
   zoom. Centrée sur la glissière (6px) grâce à translate(-50%, 50%),
   son propre point d'ancrage (bottom: X%) restant sur son bord bas. */
.zoom-slider__thumb {
  position: absolute;
  left: 50%;
  bottom: 0%;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--em-amber);
  box-shadow: var(--em-shadow);
  transform: translate(-50%, 50%);
  cursor: pointer;
  touch-action: none;
}
.zoom-slider__thumb:hover,
.zoom-slider__thumb:focus-visible {
  background: var(--em-amber-dark);
  outline: none;
}

/* =========================================================
   Toast de mise à jour PWA
   ========================================================= */


.app-toast {
  position: fixed;
  z-index: 1400;
  bottom: calc(var(--em-footer-h, 30px) + 10px); /* aligné verticalement avec le bouton + (même valeur que .fab) */
  left: 50%;
  transform: translateX(-50%);
  background: rgba(43, 44, 40, 0.7);
  color: #fff;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 0.85rem;
  max-width: min(360px, calc(100vw - 32px));
  text-align: center;
  box-shadow: var(--em-shadow);
  animation: em-toast-in 0.2s ease;
}

.route-panel {
  position: fixed;
  z-index: 1400;
  left: 50%;
  bottom: calc(var(--em-footer-h, 30px) + 10px); /* même emplacement que #search-area-btn (jamais affichés en même temps, voir emShowRoute) */
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: #fff;
  color: var(--em-stone-900);
  padding: 10px 10px 10px 16px;
  border-radius: 999px;
  font-size: 0.85rem;
  box-shadow: var(--em-shadow);
  animation: em-toast-in 0.2s ease;
  white-space: nowrap;
}
.route-panel .material-symbols-outlined { font-size: 20px; color: var(--em-alpine-blue); }
.route-panel__info {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.route-panel #route-panel-gmaps,
.route-panel #route-panel-close {
  border: none;
  background: var(--em-stone-100);
  border-radius: 50%;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  margin-left: 4px;
}
.route-panel #route-panel-gmaps .material-symbols-outlined,
.route-panel #route-panel-close .material-symbols-outlined { font-size: 16px; color: var(--em-stone-700); }


@keyframes em-toast-in {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

.loading-bar {
  position: fixed;
  z-index: 950;
  top: var(--em-topbar-h, 64px);
  left: 0;
  right: 0;
  height: 6px;
  overflow: hidden;
  background: rgba(226, 168, 58, 0.15);
}
.loading-bar::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: -30%;
  width: 30%;
  background: var(--em-amber);
  animation: em-loading-slide 1.1s ease-in-out infinite;
}
@keyframes em-loading-slide {
  0% { left: -30%; }
  100% { left: 100%; }
}

.search-area-btn {
  position: fixed;
  z-index: 950;
  bottom: calc(var(--em-footer-h, 30px) + 10px); /* aligné verticalement avec le bouton + (même valeur que .fab) */
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: rgba(255, 255, 255, 0.75);
  color: var(--em-nynjas);
  border: none;
  border-radius: 999px;
  padding: 9px 14px;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  width: max-content;
  box-shadow: var(--em-shadow);
  cursor: pointer;
  animation: em-search-area-in 0.2s ease;
}
.search-area-btn:hover { background: var(--em-stone-50); }
.search-area-btn .material-symbols-outlined { font-size: 18px; }

@keyframes em-search-area-in {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

/* =========================================================
   Accessibilité
   ========================================================= */
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--em-amber);
  outline-offset: 2px;
}
.topbar__search-input:focus-visible {
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* =========================================================
   Mobile
   ========================================================= */
/* Navbar — exactement deux états, uniquement selon la largeur (rien
   d'autre : ni orientation, ni hauteur). */

/* État large : tout sur une ligne. topbar__search fait 2x la largeur de
   topbar__radius (flex-grow 2 vs 1, même base 0 pour un ratio propre).
   dates et filters-toggle à taille fixe — ils ne grandissent/rétrécissent
   jamais avec la largeur disponible, contrairement à search/radius. */
@media (min-width: 1000px) {
  .topbar__search { flex: 2 1 0; }
  .topbar__radius { flex: 1 1 0; }
  .topbar__dates { flex: 0 0 auto; }
  #filters-toggle { flex: 0 0 auto; }
}

/* État étroit : 3 lignes, chaque groupe sur 100% de large. */
@media (max-width: 999px) {
  .topbar {
    display: grid;
    grid-template-columns: 1fr 40px;
    grid-template-areas:
      "search  search"
      "radius  filters"
      "dates   dates";
    align-items: center;
  }
  .topbar__search { grid-area: search; min-width: 0; }
  .topbar__radius { grid-area: radius; min-width: 0; overflow: hidden; }
  #filters-toggle { grid-area: filters; }
  .topbar__dates { grid-area: dates; min-width: 0; }
  .topbar__date-field { flex: 1 1 0%; min-width: 0; height: 40px; }
  .topbar__date { width: 100%; min-width: 0; text-align: center; font-size: 0.72rem; padding: 0 40px; }
}

/* =========================================================
   Lightbox image plein écran
   ========================================================= */
.image-lightbox {
  position: fixed;
  inset: 0;
  z-index: 3000;
  background: rgba(20, 20, 18, 0);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
  transition: background 0.3s ease;
}
.image-lightbox.is-open {
  background: rgba(20, 20, 18, 0.92);
}
.image-lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 8px;
  cursor: default;
  transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.image-lightbox__close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.15);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 1.4rem;
}
.image-lightbox__close:hover { background: rgba(255,255,255,0.28); }

/* Chevrons précédent/suivant — même principe que .event-card__nav, mais
   masqués par défaut (image seule, ex: logo établissement) et affichés
   uniquement quand la lightbox porte sur plusieurs images (ex: galerie
   établissement, voir emOpenImageLightbox / la classe .has-nav dans
   js/app.js). */
.image-lightbox__nav {
  display: none;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.15);
  color: #fff;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 1.6rem;
}
.image-lightbox__nav:hover { background: rgba(255,255,255,0.28); }
.image-lightbox__nav--prev { left: 16px; }
.image-lightbox__nav--next { right: 16px; }
.image-lightbox.has-nav .image-lightbox__nav { display: flex; }
