/* ============================================================
   style.css — Style neutre et fonctionnel (mobile-first)
   La charte graphique définitive sera appliquée ultérieurement.
   ============================================================ */

:root {
  --color-primary: #191557;
  --color-primary-dark: #120f3d;
  --color-accent: #e8a13a;
  --color-bg: #f5f6f5;
  --color-surface: #ffffff;
  --color-text: #1f2420;
  --color-text-muted: #6b7570;
  --color-border: #e1e4e1;
  --color-input-bg: #f5f5f4;
  --color-danger: #c04848;
  --color-success: #2f8f5b;
  --radius: 12px;
  --shadow: 0 2px 10px rgba(0,0,0,0.07);
  --nav-height: 62px;
  --header-height: 70px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  -webkit-tap-highlight-color: transparent;
}

button, input, select, textarea { font-family: inherit; font-size: 16px; }
/* Sans ça, glisser un curseur horizontal (ex. rayon de recherche) sur mobile peut être
   interprété par le navigateur comme un geste de défilement de la page, qui bouge alors
   verticalement pendant le glissement. */
input[type="range"] { touch-action: none; }

/* Écran de démarrage (couleur unie), voir main.js → afficherEcranDemarrage(). Couleur par
   défaut ci-dessous volontairement neutre (identique au fond de l'appli) plutôt qu'une couleur
   de marque figée : sinon, si la couleur réglée dans la console diffère de cette valeur par
   défaut, on voit un flash de la mauvaise couleur le temps que l'API réponde. La transition sur
   background-color fait apparaître la vraie couleur en douceur une fois connue, sans à-coup. */
#splash-screen {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--color-bg);
  transition: opacity .6s ease, background-color .4s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
}
#splash-screen.splash-sortie { opacity: 0; pointer-events: none; }
.splash-logo {
  display: block;
  width: 82.5%;
  max-width: 330px;
  height: auto;
}
.splash-titre {
  margin: 0;
  color: #fff;
  font-weight: 700;
  font-size: 22px;
  letter-spacing: 2px;
  text-transform: uppercase;
}

#app {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  background: var(--color-bg);
  display: flex;
  flex-direction: column;
  position: relative;
}

/* Regroupe tout ce qui doit "glisser" quand le menu latéral s'ouvre (en-tête, vues,
   navigation basse) — reproduit ici la même disposition flex/colonne que #app appliquait
   directement à ces éléments auparavant, une fois déplacés d'un niveau. Le panneau du menu
   et son fond assombri restent en dehors, donc immobiles.
   padding-bottom (comme padding-top) vit ici et pas sur #app, pour la même raison : dès que
   la poussée du menu applique un transform à #app-contenu, celui-ci devient le bloc de
   confinement des éléments position:fixed ancrés en bas (bottom-nav, cartes "Accès visiteur"
   en bottom:50px…). Si le padding restait sur #app, le bord bas de #app-contenu remonterait
   de cette hauteur et ces éléments "bottom:X" se retrouveraient décalés vers le haut à
   l'ouverture du menu — bug observé sur les blocs Accès libre / Accès connecté. */
#app-contenu {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding-bottom: var(--nav-height);
  transition: transform 0.25s ease;
}
#app-contenu.pousse { transform: translateX(125px); }

/* ---------- Header ---------- */
.app-header {
  height: var(--header-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 14px;
  background: var(--color-primary);
  color: #fff;
  position: sticky;
  top: 0;
  z-index: 20;
}
.app-header h1 {
  font-size: 17px;
  font-weight: 600;
  margin: 0;
  position: relative;
  left: -10px;
}
.app-header .back-btn, .app-header .icon-btn {
  background: none;
  border: none;
  color: #fff;
  font-size: 20px;
  padding: 6px;
  cursor: pointer;
  line-height: 1;
}
/* Icône hamburger blanche, agrandie à 3x (200% de plus que la taille de base des icônes
   de l'en-tête, 20px → 60px). display:flex + align-items:center pour centrer verticalement
   le glyphe dans le bouton (sinon les métriques de la police le décalent visuellement). */
#btn-menu-hamburger {
  color: #fff;
  font-size: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

/* Icône filtres (3 ronds, en-tête "Près de vous") : masquée par défaut, visible uniquement
   quand la vue active est #view-visiteur-liste — via :has() plutôt qu'un style inline en JS,
   pour ne jamais entrer en conflit de priorité CSS avec cette règle. Même hauteur pleine que
   le hamburger, pour un alignement visuel identique. */
#btn-filtres {
  color: #fff;
  display: none;
  align-items: center;
  justify-content: center;
  height: 100%;
}
#btn-filtres svg { width: 47.5px; height: 47.5px; transform: translateY(8px); }
#app:has(#view-visiteur-liste.active) #btn-filtres { display: flex; }

/* Panneau de filtres : ancré sous l'en-tête (à droite, y compris sur PC — le "transform" sur
   l'overlay crée un nouveau bloc de confinement pour sa feuille en position fixed, qui
   s'aligne donc sur la colonne centrée de 480px, comme le header, pas sur le bord réel de
   l'écran). Fond blanc, 200px de large, hauteur qui suit son contenu (pas de bottom:0) avec
   30px d'espace sous le dernier texte plutôt que d'occuper toute la hauteur de l'écran. */
#modal-filtres {
  top: 0;
  right: auto;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  align-items: flex-start;
  justify-content: flex-end;
  /* Fond assombri en fondu enchaîné plutôt qu'en instantané : transparent au repos, la
     classe .filtres-visible (ajoutée en JS un cran après le retrait de .hidden, pour laisser
     le temps au navigateur de peindre l'état de départ) l'amène à la même valeur sombre que
     les autres modales (rgba(0,0,0,0.45)). */
  background: rgba(0,0,0,0);
  transition: background 0.25s ease;
}
#modal-filtres.filtres-visible { background: rgba(0,0,0,0.45); }
#modal-filtres .modal-sheet {
  position: fixed;
  top: var(--header-height);
  right: 0;
  left: auto;
  bottom: auto;
  width: 200px;
  max-width: 200px;
  max-height: none;
  border-radius: 0;
  margin: 0;
  padding: 14px 14px 30px;
  background: #fff;
  color: var(--color-text);
  overflow-y: auto;
  /* Déroulé du haut vers le bas : replié au-dessus de l'en-tête (translateY(-100%) de sa
     propre hauteur), déplié pile sous l'en-tête (translateY(0), position définie par
     top:var(--header-height) ci-dessus). */
  transform: translateY(-100%);
  transition: transform 0.25s ease;
}
#modal-filtres.filtres-visible .modal-sheet { transform: translateY(0); }
#modal-filtres .hint { color: var(--color-text-muted); font-size: 11px; margin: 14px 0 4px; }
#modal-filtres .hint:first-child { margin-top: 0; }
/* Filtres en texte seul, sans badge/pastille : liste verticale simple. */
#modal-filtres .filter-bar { display: flex; flex-direction: column; overflow: visible; gap: 2px; }
#modal-filtres .filter-pill {
  flex-shrink: 0;
  background: none;
  border: none;
  border-radius: 0;
  padding: 4px 0;
  font-size: 11.5px;
  color: var(--color-text);
  text-align: left;
  white-space: normal;
  cursor: pointer;
}
#modal-filtres .filter-pill.active { background: none; color: var(--color-primary); font-weight: 700; text-decoration: underline; }

/* Menu latéral coulissant, ouvert depuis l'icône hamburger de l'en-tête. Ombre légère
   uniquement sur le côté droit du panneau (décalage horizontal positif, pas de flou vertical).
   L'ancre est positionnée via --menu-anchor-left, une variable CSS mise à jour en JS
   (syncMenuLateralAnchor() dans main.js) à partir de la position RÉELLE de l'en-tête
   (getBoundingClientRect), plutôt que recalculée indépendamment en CSS — deux calculs
   séparés avec la même formule (position:fixed + left:50% + transform + max-width:480px)
   pouvaient diverger de quelques pixels selon la largeur de fenêtre. Ainsi le panneau est
   toujours pile aligné sur le bord gauche réel de l'en-tête. Largeur = celle du panneau
   (100px) avec overflow:hidden : replié (translateX(-100%) du panneau), il sort entièrement
   de cette bande de 100px et devient invisible ; déplié, il la remplit exactement. */
.menu-lateral-anchor {
  position: fixed;
  top: 0;
  left: var(--menu-anchor-left, 0px);
  bottom: 0;
  width: 125px;
  z-index: 500;
  pointer-events: none;
  overflow: hidden;
}
.menu-lateral {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: 125px;
  background: #fff;
  transform: translateX(-100%);
  transition: transform .25s ease;
  overflow-y: auto;
  pointer-events: auto;
  /* 10px sous la barre de statut du smartphone (heure/encoche), pas juste sous le haut de
     l'écran : le logo doit rester à distance constante de l'heure sur tous les appareils. */
  padding-top: calc(env(safe-area-inset-top, 0px) + 10px);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.menu-lateral-logo-btn { background: none; border: none; padding: 0; cursor: pointer; display: block; }
.menu-lateral-logo { width: 70px; height: auto; }
/* Trait entre le logo et l'icône : 20px sous le logo, 5px avant le haut de l'icône suivante
   (espacement volontairement asymétrique), largeur 105px = 125px du panneau - 10px - 10px,
   centré par le align-items:center du parent flex. */
.menu-lateral-separateur {
  width: 105px;
  height: 2px;
  margin-top: 20px;
  margin-bottom: 5px;
  background: #191557;
  border: none;
}
/* Icône d'accès au profil visiteur, sous le trait (espacement porté par la marge basse du
   trait ci-dessus, pas de marge supplémentaire ici). */
.menu-lateral-icone {
  margin-top: 0;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.menu-lateral-icone img { width: 60px; height: 60px; }
/* 5px entre l'icône et le texte ; 5px sous le texte avant le trait qui suit. */
.menu-lateral-icone-label { margin-top: 0; margin-bottom: 10px; font-size: 12px; color: var(--color-text-muted); }
/* Un trait après une icône (ex. sous "Mon compte") n'a pas sa propre marge du dessus : l'espace
   de 5px est déjà porté par la marge basse du texte ci-dessus. Sa marge du dessous (10px,
   héritée de .menu-lateral-separateur) reste inchangée pour espacer l'icône suivante. */
.menu-lateral-icone + .menu-lateral-separateur { margin-top: 0; }
/* L'ombre n'est appliquée qu'une fois le panneau ouvert : repliée, même clippée par
   overflow:hidden sur l'ancre, elle déborderait de ~11px (décalage 3px + flou 8px) dans la
   zone visible juste à côté de l'en-tête, car ce débordement reste À L'INTÉRIEUR des bornes
   de l'ancre et n'est donc jamais coupé — c'était la bande grise visible à tort. */
.menu-lateral.ouvert {
  transform: translateX(0);
  box-shadow: 3px 0 8px rgba(0,0,0,0.15);
}
.menu-lateral-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.35);
  z-index: 499;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
}
.menu-lateral-backdrop.visible { opacity: 1; pointer-events: auto; }

/* "À propos" : modale classique (#modal-apropos, voir .modal-overlay/.modal-sheet), plus de
   cadre latéral dédié. Centrée à l'écran (RÈGLE POUR TOUS LES POPUPS de l'app, faits et à
   venir — voir mémoire) plutôt qu'en feuille du bas, même technique de centrage indépendant
   du flex que les autres modales ci-dessous. */
#modal-apropos .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
#modal-apropos p { margin: 0 0 14px; font-size: 13.5px; line-height: 1.5; color: var(--color-text); }
#modal-apropos a { color: var(--color-primary); }

/* Détail d'une mention légale (contenu chargé depuis /mentions-legales, propre à l'application
   courante), ouvert depuis la liste de #modal-apropos. Même règle de centrage. */
#modal-mention-legale .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 80vh;
  overflow-y: auto;
  border-radius: 16px;
  margin: 0;
}
#mention-legale-contenu { font-size: 13.5px; line-height: 1.5; color: var(--color-text); }

/* Popups restants qui n'avaient pas encore été centrés (suppression de compte, abonnement,
   position manuelle, réservation, paiement) — même règle : tous les popups doivent être
   centrés à l'écran, pas en feuille du bas. */
#modal-suppr-etape1 .modal-sheet,
#modal-suppr-etape2 .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 360px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
#modal-abonnement .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
#modal-position .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 480px;
  max-height: 85vh;
  border-radius: 16px;
  margin: 0;
}
#modal-ma-position .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 480px;
  max-height: 85vh;
  overflow-y: auto;
  border-radius: 16px;
  margin: 0;
}
#modal-reservation .modal-sheet,
#modal-paiement .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 85vh;
  border-radius: 16px;
  margin: 0;
}

/* Sur smartphones/tablettes, la barre du haut est fixée à l'écran (au lieu de "sticky") :
   plus robuste face aux comportements de la barre d'adresse mobile (Safari/Chrome) qui
   pouvaient la faire disparaître ou sauter pendant le défilement. */
@media (max-width: 1024px) {
  .app-header {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    max-width: 480px;
    /* Pousse le contenu de la barre sous la barre de statut iOS (celle-ci est rendue
       transparente par apple-mobile-web-app-status-bar-style=black-translucent en mode
       "ajouté à l'écran d'accueil", donc sans ce padding le titre/boutons seraient masqués
       par l'horloge/la batterie). Sans encoche/safe-area, env() vaut 0 : aucun effet. */
    padding-top: env(safe-area-inset-top, 0px);
    box-sizing: content-box;
  }
  /* Ce padding doit vivre sur #app-contenu (pas sur #app) : #app-contenu est le bloc de
     confinement de l'en-tête (position:fixed) une fois que la poussée du menu latéral lui
     applique un transform. Si le padding était sur #app, le bord haut de #app-contenu se
     retrouverait décalé de cette hauteur, et l'en-tête (top:0 relatif à ce bloc) descendrait
     d'autant à l'ouverture du menu — bug observé : l'en-tête "tombe" quand le menu s'ouvre. En
     le mettant directement sur #app-contenu, le padding pousse son CONTENU en flux normal
     (les vues) vers le bas, mais pas l'en-tête, qui est hors flux (position:fixed) et reste
     ancré au bord haut réel de #app-contenu (top:0), quel que soit l'état du menu. */
  #app-contenu { padding-top: calc(var(--header-height) + env(safe-area-inset-top, 0px)); }
}

/* ---------- Main content ---------- */
.view {
  flex: 1;
  padding: 14px;
  padding-bottom: 24px;
  display: none;
}
.view.active { display: block; }
#view-visiteur-auth.active { padding-top: 50px; }
/* "Connexion professionnel" : cadre centré verticalement dans l'écran plutôt que collé en haut. */
#view-pro-auth.active { display: flex; flex-direction: column; justify-content: center; }
/* "Accès libre" et "Accès connecté" : même cadre (rôle-card et card-connexion partagent le
   même fond/arrondi/ombre/padding), ancrés ensemble à 50px du bas de l'écran réel — même
   technique que les boutons de l'accueil (position fixe indépendante du flux/scroll). */
.card-connexion { padding: 18px; }
/* En-tête icône + titre + description du bloc "Accès connecté", même agencement que
   l'icône/titre/texte du role-card "ACCÈS LIBRE" juste au-dessus. */
.connexion-entete { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.connexion-entete .emoji { font-size: 30px; }
.connexion-entete h3 { margin: 0 0 3px; font-size: 15px; }
.connexion-entete p { margin: 0; font-size: 12.5px; color: var(--color-text-muted); }
#view-visiteur-auth.active .visiteur-auth-blocs {
  position: fixed;
  left: 50%;
  bottom: 50px;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  padding: 0 14px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 30px;
  z-index: 15;
}

/* ---------- Bottom nav ---------- */
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  height: var(--nav-height);
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  display: flex;
  justify-content: space-evenly; /* même espace entre les icônes ET entre les bords et les icônes de chaque extrémité */
  z-index: 30;
}
.bottom-nav.hidden { display: none; }
.nav-btn {
  flex: 0 0 auto;
  border: none;
  background: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  color: var(--color-text-muted);
  font-size: 11px;
  cursor: pointer;
  padding: 4px;
}
.nav-btn .nav-icon { font-size: 20px; display: flex; align-items: center; justify-content: center; }
.nav-btn .nav-icon img { width: 22px; height: 22px; object-fit: contain; display: block; }
.nav-btn.active { color: var(--color-primary); font-weight: 600; }

/* ---------- Cards / lists ---------- */
.card {
  background: var(--color-surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 14px;
  margin-bottom: 12px;
}
/* La photo de la liste des événements (visiteur) est agrandie, carrée, avec une marge fixe
   de 5px de tous les côtés (taille figée en dur — les approches dynamiques précédentes,
   aspect-ratio/align-self:stretch, ne s'affichaient pas de façon fiable). Le padding de
   .card est entièrement délégué à .info (le texte) : le conteneur flex lui-même n'a plus de
   padding, ce qui laisse la marge de la photo (5px) seule responsable de l'espacement. */
.event-card {
  display: flex;
  gap: 0;
  cursor: pointer;
  padding: 0;
}
.event-card .thumb {
  width: 100px;
  height: 100px;
  flex-shrink: 0;
  margin: 5px;
}
.event-card .info {
  padding: 14px 14px 14px 0;
}
.thumb {
  width: 64px;
  height: 64px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--color-primary), var(--color-accent));
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 22px;
}
.event-card .info { flex: 1; min-width: 0; }
.pro-event-card { display: flex; gap: 10px; }
.pro-event-card .info { flex: 1; min-width: 0; }

/* Barre d'état verticale (tableau de bord annonceur) : couleur selon le statut de
   l'événement, clignotante à l'approche du début (vert) ou de la fin (rouge) — voir
   calculerEtatBarreEvenement() dans main.js. La vitesse de clignotement est réglée par
   variable CSS --barre-intervalle, injectée en style inline par événement. */
.barre-etat { width: 6px; align-self: stretch; border-radius: 4px; flex: none; }
.barre-etat-vert { background: #27ae60; }
.barre-etat-orange { background: #e67e22; }
.barre-etat-jaune { background: #f1c40f; }
.barre-etat-rouge { background: #c0392b; }
.barre-etat-neutre { background: #bdc3c7; }
@keyframes clignoter-barre-etat { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .15; } }
.barre-etat.clignote { animation: clignoter-barre-etat var(--barre-intervalle, 1s) steps(1) infinite; }

/* Rubrique "Mes événements terminés" : repliée par défaut, en fin de liste.
   Même gabarit typographique que .section-title (ex. "MES ÉVÉNEMENTS"), sans l'icône
   d'origine et avec la flèche de déploiement déplacée à droite (marqueur natif masqué). */
#pro-events-termines-details { margin-top: 4px; }
#pro-events-termines-details summary {
  cursor: pointer; padding: 10px 4px;
  color: var(--color-text-muted, #767b86);
  font-size: 14px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  display: flex; justify-content: space-between; align-items: center;
  list-style: none;
}
#pro-events-termines-details summary::-webkit-details-marker { display: none; }
#pro-events-termines-details summary::after {
  content: '▾'; margin-left: 8px; flex-shrink: 0;
  font-size: 37.5px; line-height: 1; color: var(--color-text-muted, #767b86);
  transition: transform .15s ease;
}
#pro-events-termines-details[open] summary::after { transform: rotate(180deg); }
/* Clignote en rouge tant que la rubrique est dépliée, comme les autres flèches de
   déploiement des rubriques (voir .bouton-repli.ouvert dans icilagoconsole). */
@keyframes clignoter-fleche-repli-rouge { 0%, 49% { color: var(--color-text-muted, #767b86); } 50%, 100% { color: var(--color-danger); } }
#pro-events-termines-details[open] summary::after { animation: clignoter-fleche-repli-rouge .6s steps(1) infinite; }
.fav-toggle {
  position: absolute;
  top: 8px;
  right: 8px;
  background: rgba(255,255,255,0.9);
  border: none;
  border-radius: 50%;
  width: 28px;
  height: 28px;
  font-size: 14px;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0,0,0,0.15);
}

/* Rond d'état (liste "Près de vous") : même code couleur que la barre d'état du tableau de
   bord annonceur (voir calculerEtatBarreEvenement), sous l'icône favori, coin bas-droit. */
.point-etat {
  position: absolute;
  bottom: 8px;
  right: 8px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(255,255,255,.9), 0 1px 4px rgba(0,0,0,0.15);
}

.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid #eceff1;
}
.toggle-row-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.toggle-row-text span { font-size: 14.5px; color: var(--color-text); }
.toggle-row-text em { font-size: 12px; color: var(--color-text-muted); font-style: italic; }
.toggle-switch {
  position: relative;
  display: inline-block;
  width: 46px;
  height: 26px;
  flex-shrink: 0;
}
.toggle-switch input {
  opacity: 0;
  width: 0;
  height: 0;
}
.toggle-slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background-color: #d9dcdf;
  border-radius: 26px;
  transition: background-color .2s ease;
}
.toggle-slider::before {
  content: "";
  position: absolute;
  height: 22px;
  width: 22px;
  left: 2px;
  top: 2px;
  background-color: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.25);
  transition: transform .2s ease;
}
.toggle-switch input:checked + .toggle-slider { background-color: var(--color-primary); }
.toggle-switch input:checked + .toggle-slider::before { transform: translateX(20px); }
.toggle-row-option {
  padding: 4px 14px 12px;
  border-bottom: 1px solid #eceff1;
  background: #fafbfc;
}
.toggle-row-option label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--color-text-muted);
}
.toggle-row-option input[type="number"] {
  width: 80px;
  padding: 5px 8px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  font-size: 13px;
}
.toggle-row-option .chip-group { margin-top: 2px; }
.event-card h3 { margin: 0 0 4px; font-size: 15px; }
.event-card .meta {
  font-size: 12.5px;
  color: var(--color-text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 20px;
  background: var(--color-border);
  color: var(--color-text);
}
.badge.free { background: #e2f3ea; color: var(--color-success); }
.badge.paid { background: #fdecd6; color: #a86a1d; }
.badge.locked { background: #f3e2e2; color: var(--color-danger); }
.badge.attente-validation { background: var(--color-danger); color: #fff; }

/* ---------- Forms ---------- */
.field { margin-bottom: 14px; }
.field label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--color-text);
}
.field .hint { font-size: 12px; color: var(--color-text-muted); margin-top: 4px; }
input[type="text"], input[type="email"], input[type="tel"], input[type="password"],
input[type="number"], input[type="date"], input[type="time"], input[type="file"],
select, textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  background: var(--color-input-bg);
  color: var(--color-text);
}
textarea { min-height: 80px; resize: vertical; }

/* Bouton "œil" afficher/masquer, ajouté automatiquement sur tous les champs
   mot de passe (voir activerAfficherMotDePasse() dans main.js). */
.password-field-wrapper { position: relative; }
.password-field-wrapper input { padding-right: 42px; }
.password-toggle-btn {
  position: absolute;
  right: 2px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 8px;
  color: var(--color-text-muted);
}
.password-toggle-btn:hover { color: var(--color-text); }
.chip-group { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  padding: 6px 12px;
  border-radius: 20px;
  border: 1px solid var(--color-border);
  background: #fff;
  font-size: 13px;
  cursor: pointer;
  color: var(--color-text-muted);
}
.chip.selected {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}
.radio-group { display: flex; gap: 8px; flex-wrap: wrap; }
.radio-group label {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  font-size: 13px;
  font-weight: 400;
  cursor: pointer;
}
.checkbox-field {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  cursor: pointer;
}
.checkbox-field input[type="checkbox"] { width: 18px; height: 18px; }

.info-tip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-border);
  color: var(--color-text-muted);
  font-size: 11px;
  cursor: help;
  margin-left: 4px;
  vertical-align: middle;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  padding: 12px 16px;
  border-radius: 10px;
  border: none;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  /* Légère ombre portée sur tous les boutons de l'application. */
  box-shadow: 0 2px 6px rgba(0,0,0,0.12);
}
.btn-primary { background: var(--color-primary); color: #fff; }
.btn-primary:active { background: var(--color-primary-dark); }
.btn-secondary { background: #fff; color: var(--color-primary); border: 1px solid var(--color-primary); }
.btn-accent { background: var(--color-accent); color: #fff; }
.btn-danger { background: var(--color-danger); color: #fff; }
.btn-ghost { background: none; color: var(--color-text-muted); }
.btn-sm { padding: 8px 12px; font-size: 13px; width: auto; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* Fonctionnalité non incluse dans le palier d'accès actuel : reste cliquable (un message
   d'invitation à changer de palier s'affiche), mais visuellement estompée. */
.is-grise { opacity: 0.4; }
.is-grise:hover, .is-grise:focus { opacity: 0.55; }
input.is-grise, select.is-grise { background: var(--color-bg); cursor: not-allowed; }

/* ---------- Home / role picker ---------- */
/* Sur l'accueil, la barre du haut (bandeau bleu "ICILAGO Events") est masquée : le vrai logo
   remplace le bandeau + le logo emoji + le titre texte. */
#app:has(#view-accueil.active) .app-header { display: none; }
#app-contenu:has(#view-accueil.active) { padding-top: 0; }
/* Image de fond plein écran de l'accueil (croppée pour couvrir tout l'écran, sans déformation). */
#view-accueil.active {
  padding-top: 0;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  z-index: 1;
  background-image: url('/Images/Ecrans_accueil/Pict_01.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.hero {
  text-align: center;
  padding: 10px 20px 20px;
}
/* Le bloc logo est ancré en position fixe (comme .accueil-bottom) pour ne plus bouger du tout
   au toucher/glissement — il ne fait plus partie du flux défilable de la vue. */
#view-accueil.active .hero {
  position: fixed;
  /* + safe-area-inset-top : garde 10px sous l'encoche/barre de statut plutôt que sous le
     tout premier pixel de l'écran (utile en mode "ajouté à l'écran d'accueil"). */
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  padding: 0 20px;
  box-sizing: border-box;
  z-index: 15;
}
.hero-logo {
  display: block;
  width: 70%;
  max-width: 260px;
  height: auto;
  margin: 0 auto 14px;
}
.hero p { color: #fff; font-size: 14px; margin: 0; }
/* Fondu léger lors du changement de message rotatif sous le logo (voir chargerMessageAccueilRotatifDepuisApi). */
#accueil-message-rotatif { transition: opacity .25s ease; }
#accueil-message-rotatif.message-accueil-fondu { opacity: 0; }
.role-cards { display: flex; flex-direction: column; gap: 12px; margin-top: 20px; }
/* Sur l'accueil, les boutons + le texte de consentement position sont ancrés ensemble en bas
   de l'écran réel (et non du bas de la vue, qui laisse un espace mort réservé à la barre de
   nav masquée sur cet écran). Le gap de 50px place les boutons exactement 50px au-dessus du
   texte, qui reste lui juste au-dessus du bord de l'écran. */
#view-accueil.active .accueil-bottom {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  padding: 0 14px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 50px;
  z-index: 15;
}
#view-accueil.active .accueil-bottom .role-cards { margin-top: 0; }
.accueil-bas-texte { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.lien-partage-app {
  background: none;
  border: none;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  padding: 4px;
}
.accueil-note {
  margin: 0;
  text-align: center;
  font-size: 12.5px;
  line-height: 1.4;
  color: #fff;
}
.role-card {
  background: var(--color-surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
  cursor: pointer;
  border: 2px solid transparent;
  display: flex;
  align-items: center;
  gap: 14px;
}
.role-card:active { border-color: var(--color-primary); }
.role-card .emoji { font-size: 30px; }
.role-card h3 { margin: 0 0 3px; font-size: 15px; }
.role-card p { margin: 0; font-size: 12.5px; color: var(--color-text-muted); }

/* ---------- Utility ---------- */
.section-title { font-size: 14px; font-weight: 700; margin: 18px 0 10px; text-transform: uppercase; letter-spacing: .03em; color: var(--color-text-muted); }
.row { display: flex; gap: 10px; }
.row > * { flex: 1; }
.empty-state { text-align: center; padding: 40px 12px; color: var(--color-text-muted); }
.empty-state .emoji { font-size: 34px; display: block; margin-bottom: 10px; }
.divider { height: 1px; background: var(--color-border); margin: 16px 0; }
.stat-row { display: flex; justify-content: space-between; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--color-border); }
.stat-row:last-child { border-bottom: none; }
.stat-value { font-weight: 700; font-size: 16px; }
.bar-row { margin-bottom: 8px; }
.bar-label { display: flex; justify-content: space-between; font-size: 12.5px; margin-bottom: 3px; }
.bar-track { height: 8px; background: var(--color-border); border-radius: 6px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--color-primary); }

/* ---------- Admin ---------- */
.admin-taxo-list { display: flex; flex-direction: column; }
.admin-taxo-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 13.5px;
  background: var(--color-surface);
}
.admin-taxo-row:last-child { border-bottom: none; }
.admin-taxo-row.dragging { opacity: 0.5; background: var(--color-bg); border-radius: 8px; }
.admin-taxo-text { flex: 1; min-width: 0; }
.admin-taxo-actions { display: flex; gap: 4px; align-items: center; flex-shrink: 0; }
.admin-taxo-actions button {
  background: none;
  border: none;
  font-size: 15px;
  padding: 4px 6px;
  cursor: pointer;
}
.admin-color-input { width: 30px; height: 26px; padding: 0; border: 1px solid var(--color-border); border-radius: 6px; cursor: pointer; }
.color-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 4px; vertical-align: middle; }
.drag-handle {
  flex-shrink: 0;
  cursor: grab;
  touch-action: none;
  padding: 4px 6px;
  font-size: 15px;
  color: var(--color-text-muted);
  user-select: none;
}
.drag-handle:active { cursor: grabbing; }

/* ---------- Adresse structurée / téléphone avec indicatif ---------- */
.phone-field { display: flex; gap: 8px; }
.phone-field select { flex: 0 0 118px; }
.phone-field input { flex: 1; }

/* ---------- Profil pro : icône + champ lien (Web et réseaux) ---------- */
.field-icone { display: flex; align-items: center; gap: 10px; }
.field-icone img { width: 32px; height: 32px; object-fit: contain; flex: none; }
.field-icone input { flex: 1; }
.toast {
  position: fixed;
  bottom: calc(var(--nav-height) + 10px);
  left: 50%;
  transform: translateX(-50%);
  max-width: 440px;
  width: calc(100% - 28px);
  background: var(--color-text);
  color: #fff;
  padding: 12px 16px;
  border-radius: 10px;
  font-size: 13.5px;
  z-index: 100;
  box-shadow: var(--shadow);
}
.lock-banner {
  background: #fff8ea;
  border: 1px solid #f0d8a4;
  border-radius: 10px;
  padding: 12px 14px;
  font-size: 13px;
  margin-bottom: 14px;
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

/* ---------- Modal ---------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Doit rester au-dessus des cartes Leaflet, dont les panneaux/contrôles internes
     utilisent des z-index allant jusqu'à ~1000 (sinon la carte s'affiche par-dessus
     la fiche, ex. dans Statistiques). */
  z-index: 3000;
}
.modal-overlay.hidden { display: none; }
.modal-sheet {
  background: #fff;
  width: 100%;
  max-width: 480px;
  border-radius: 16px 16px 0 0;
  padding: 20px;
  max-height: 88vh;
  overflow-y: auto;
}
.modal-sheet h2 { margin-top: 0; font-size: 17px; }
.modal-handle { width: 40px; height: 4px; background: var(--color-border); border-radius: 4px; margin: 0 auto 14px; }

/* La fiche événement (ouverte depuis "Près de vous") s'affiche centrée à l'écran plutôt
   qu'en feuille du bas, même technique de centrage indépendant du flex. */
#modal-event-detail .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 480px;
  max-height: 85vh;
  border-radius: 16px;
  margin: 0;
}

/* Le recadrage de photo événement s'affiche centré à l'écran plutôt qu'en feuille du bas,
   même technique de centrage indépendant du flex. */
#modal-crop-image .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 85vh;
  border-radius: 16px;
  margin: 0;
}

/* La fiche de réservation (statistiques pro) s'affiche centrée à l'écran plutôt qu'en feuille du bas.
   Le positionnement se fait directement sur la feuille elle-même (position fixed + transform),
   indépendamment du flex du parent, pour un centrage vertical fiable quelle que soit la hauteur
   du contenu ou la position de défilement de la page. */
#modal-fiche-reservation .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}

/* Le QR code (ex: "Mes réservations" dans le compte visiteur, partage d'événement) s'affiche
   centré à l'écran plutôt qu'en feuille du bas — même technique de centrage indépendant du flex. */
#modal-qrcode .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 360px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}

/* Popup "Annonce en cours de vérification" (après validation de la fiche événement),
   centrée à l'écran plutôt qu'en feuille du bas, même technique de centrage. */
#modal-moderation-info .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}

/* Historique des modifications d'un événement, centré à l'écran, même technique. */
#modal-historique-modifs .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 420px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
.historique-modif-ligne {
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 13px;
}
.historique-modif-ligne:last-child { border-bottom: none; }
.historique-modif-date {
  font-weight: 700;
  font-size: 12px;
  color: var(--color-text-muted);
  margin-bottom: 2px;
}
.historique-modif-champs { font-size: 13px; }
#modal-historique-modifs h2 { font-size: 15px; }
#modal-historique-modifs #historique-modifs-subtitle { font-size: 13px; font-weight: 600; margin-top: -8px; }

/* Consentement de position (à l'entrée de l'accès visiteur) centré à l'écran, même technique. */
#modal-consentement-position .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 360px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
#modal-consentement-position h2 { letter-spacing: 1px; font-size: 17px; }

/* "Dommage" (refus de la position) centré à l'écran, même technique. */
#modal-regret-position .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 360px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
#modal-regret-position h2 { letter-spacing: 1px; font-size: 17px; }

/* "Modifications non enregistrées" (Mon compte, avant de quitter via le logo du menu latéral)
   centré à l'écran, même technique. */
#modal-confirmer-quitter-compte .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 360px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
#modal-confirmer-quitter-compte h2 { letter-spacing: 1px; font-size: 17px; }

/* "Déconnexion" centrée à l'écran, même technique. */
#modal-confirmer-deconnexion .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 360px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
#modal-confirmer-deconnexion h2 { letter-spacing: 1px; font-size: 17px; }

/* "Mot de passe oublié" centré à l'écran, même technique. */
#modal-mdp-oublie .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 400px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}

/* "Bienvenue" à la connexion visiteur, centrée, sans bouton (se referme seule après 2s). */
#modal-bienvenue-visiteur .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 60px);
  max-width: 320px;
  border-radius: 16px;
  margin: 0;
  padding: 22px 20px;
}

/* Popups de suppression de compte (visiteur + pro) : centrés, fond rouge,
   texte blanc en gras — cohérent avec la gravité de l'action. */
#modal-suppr-etape1 .modal-sheet,
#modal-suppr-etape2 .modal-sheet,
#modal-suppr-annulee .modal-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% - 40px);
  max-width: 380px;
  max-height: 80vh;
  border-radius: 16px;
  margin: 0;
}
.suppr-danger {
  background: #c0392b !important;
}
.suppr-danger .suppr-titre {
  color: #fff;
  font-weight: 700;
  font-size: 16px;
  margin: 0 0 16px;
  text-align: center;
}
.suppr-danger .row { gap: 10px; }
.suppr-btn-oui, .suppr-btn-non {
  flex: 1;
  font-weight: 700;
  border-radius: 10px;
  padding: 12px;
}
.suppr-btn-oui {
  background: #fff;
  color: #c0392b;
  border: none;
}
.suppr-btn-non {
  background: transparent;
  color: #fff;
  border: 2px solid #fff;
}
#suppr-etape2-password-field input {
  border-radius: 8px;
  border: none;
  padding: 10px 12px;
}

/* ---------- Map ---------- */
/* Leaflet fixe déjà position:relative sur .leaflet-container (dans leaflet.css) mais sans
   z-index — donc sans nouveau contexte d'empilement. Ses contrôles internes (zoom, etc., avec
   z-index jusqu'à 1000 dans les styles de Leaflet) se comparent alors directement aux autres
   éléments de la page dans le MÊME contexte d'empilement, y compris l'en-tête (z-index:20) :
   1000 > 20, donc la carte pouvait apparaître par-dessus l'en-tête en défilant (ex. "Ma
   position" dans Mon compte). En donnant un z-index explicite au conteneur, on crée un
   contexte d'empilement local qui confine tous ses contrôles internes à l'intérieur de sa
   propre boîte — la carte, dans son ensemble, ne compte plus que pour ce seul z-index (0) vis
   à vis du reste de la page, donc elle reste sous l'en-tête comme n'importe quel autre bloc. */
.leaflet-container { z-index: 0; }
#map-container { height: 340px; border-radius: var(--radius); overflow: hidden; margin-bottom: 14px; box-shadow: var(--shadow); }
#detail-map { height: 200px; border-radius: var(--radius); overflow: hidden; margin: 14px 0; }
#stats-map { height: 240px; border-radius: var(--radius); overflow: hidden; }
#evt-position-map { height: 320px; border-radius: var(--radius); overflow: hidden; margin-top: 10px; box-shadow: var(--shadow); }
.map-legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 4px; vertical-align: middle; }

/* ---------- Filters bar ---------- */
.filter-bar { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 6px; margin-bottom: 8px; }
.filter-bar::-webkit-scrollbar { display: none; }
.filter-pill {
  flex-shrink: 0;
  padding: 7px 13px;
  border-radius: 20px;
  background: #fff;
  border: 1px solid var(--color-border);
  font-size: 12.5px;
  cursor: pointer;
  white-space: nowrap;
}
.filter-pill.active { background: var(--color-primary); color: #fff; border-color: var(--color-primary); }

/* ---------- Loading ---------- */
.spinner {
  width: 22px; height: 22px;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  margin: 0 auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (min-width: 500px) {
  .bottom-nav { border-left: 1px solid var(--color-border); border-right: 1px solid var(--color-border); }
}
