:root {
  --bleu-fonce: #0d3b66;
  --bleu: #1d5b96;
  --bleu-clair: #eaf2fb;
  --bleu-roi: #1e3a8a;
  --texte: #16232f;
  --texte-discret: #5b6b7a;
  --fond: #eaf0f9; /* légèrement plus bleuté qu'avant (#f5f8fc) — premier essai, à valider */
  --carte-fond: #ffffff;
  --bordure: #d7e3f0;
  --bordure-app: #000000;
  --epaisseur-bordure: 1px;
  --espace-petit: 19px; /* ~5mm : rythme vertical unique entre tous les blocs/modules */

  --niveau-vert: #2e7d32;
  --niveau-jaune: #d4a017;
  --niveau-orange: #e07b00;
  --niveau-rouge: #c62828;
  --niveau-indisponible: #9aa5b1;

  /* Jaune vif dédié au cycle décoratif du titre uniquement : --niveau-jaune
     (couleur officielle de vigilance, un or terne) se lit comme "olive" une
     fois affiché seul en grand sur fond blanc. Ne jamais utiliser cette
     variable pour un vrai niveau d'alerte — seul --niveau-jaune fait foi
     pour les données réelles (pictos, halos, triangle, etc.). */
  --titre-jaune-vif: #ffc107;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--fond);
  color: var(--texte);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  -webkit-tap-highlight-color: transparent;
}

/* Voir afficherEcran() dans app.js : évite une bande de fond clair visible
   quand #ecran-accueil déborde de sa hauteur fixe (100dvh). */
body.fond-ecran-accueil {
  background: var(--bleu-roi);
}

.ecran {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: var(--espace-petit) 18px calc(14px + env(safe-area-inset-bottom));
  position: relative;
  border: var(--epaisseur-bordure) solid var(--bordure-app);
}

.ecran[hidden] { display: none; }

#ecran-accueil {
  background: var(--bleu-roi);
  gap: var(--espace-petit);
  /* Hauteur bornée (pas juste min-height) : la fenêtre entière ne doit plus
     s'agrandir quand le détail s'ouvre — "Propulsé par BS Concept" doit
     rester à sa place. Seul le panneau de détail absorbe le surplus, en
     défilant lui-même (voir .panneau-detail, overflow-y + min-height:0). */
  height: 100vh;
  height: 100dvh;
}

#ecran-accueil > .entete-accueil,
#ecran-accueil > .banniere-exceptionnelle,
#ecran-accueil > .grille-pictos,
#ecran-accueil > .mention-source {
  flex-shrink: 0;
}

.bouton-annuler {
  position: absolute;
  top: calc(14px + env(safe-area-inset-top));
  right: 14px;
  font-size: 1.2rem;
  z-index: 5;
}

/* Bloc titre : même esprit visuel que les cartes de risque, mais non cliquable */

.bloc-titre {
  text-align: center;
  background: var(--carte-fond);
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 16px;
  padding: 14px 16px;
}

/* Écran de saisie */

.entete-saisie {
  margin: 32px 0 28px;
}

.titre-app {
  font-size: 1.6rem;
  margin: 0;
  text-wrap: balance;
  animation: cycle-couleurs-titre 3.8s linear infinite;
}

/* Vague continue rouge → jaune → vert → rouge, jamais un palier suivi d'un
   saut brusque ("clignotant", problématique pour l'épilepsie photosensible :
   retour explicite de l'utilisateur le 2026-08-14). Un seul point de
   couleur par étape (pas de plage figée) + timing `linear` : le navigateur
   interpolue en continu sur toute la durée, sans jamais s'arrêter sur une
   teinte ni accélérer/ralentir en dents de scie. */
@keyframes cycle-couleurs-titre {
  0% { color: var(--niveau-rouge); }
  33% { color: var(--titre-jaune-vif); }
  66% { color: var(--niveau-vert); }
  100% { color: var(--niveau-rouge); }
}

.sous-titre {
  color: var(--texte-discret);
  margin: 0;
  font-size: 0.95rem;
  text-wrap: balance;
}

/* Même traitement que .sous-titre-accueil (écran d'accueil) : sorti du bandeau
   blanc du titre, en dessous, sur une seule ligne — cohérence entre les deux
   écrans. Couleur conservée (fond clair ici, pas de fond bleu roi). */
.sous-titre-saisie {
  margin: 8px 0 0;
  font-size: 0.82rem;
  text-align: center;
}

#form-commune {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 420px;
  width: 100%;
  margin: 0 auto;
}

.conteneur-champ {
  position: relative;
}

#form-commune label {
  font-weight: 600;
  color: var(--bleu-fonce);
  text-wrap: balance;
}

#champ-commune {
  width: 100%;
  padding: 14px 16px;
  font-size: 1rem;
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 12px;
  background: var(--carte-fond);
  color: var(--texte);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.liste-suggestions {
  list-style: none;
  margin: 0;
  padding: 4px;
  background: var(--carte-fond);
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 12px;
  max-height: 240px;
  overflow-y: auto;
  position: absolute;
  /* Toujours collée au champ, quelle que soit sa hauteur réelle (taille de
     texte système augmentée, libellé sur 2 lignes, etc.) — un `top` fixe en
     pixels s'est révélé faux dès que la taille de police change (bug trouvé
     et corrigé le 2026-08-14, voir SUIVI_QUALITE.md). */
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 5;
  box-shadow: 0 8px 24px rgba(13, 59, 102, 0.12);
}

.liste-suggestions[hidden] { display: none; }

.liste-suggestions li button {
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  background: none;
  border: none;
  border-radius: 8px;
  font-size: 0.95rem;
  color: var(--texte);
  cursor: pointer;
}

.liste-suggestions li button:hover,
.liste-suggestions li button:focus {
  background: var(--bleu-clair);
}

.liste-suggestions .departement {
  color: var(--texte-discret);
  font-size: 0.85rem;
}

#bouton-valider {
  margin-top: 8px;
  padding: 14px;
  font-size: 1rem;
  font-weight: 600;
  color: #fff;
  background: var(--bleu);
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 12px;
  cursor: pointer;
  outline: none;
}

#bouton-valider:disabled {
  background: var(--bordure);
  color: var(--texte-discret);
  cursor: not-allowed;
}

.mention-source {
  text-align: center;
  color: var(--texte-discret);
  font-size: 0.8rem;
  margin-top: auto;
  padding-top: 14px;
  text-wrap: balance;
}

.entete-accueil ~ .mention-source {
  color: #ffffff;
  font-size: 0.85rem;
  padding-top: 0;
}

.mention-source a { color: var(--bleu); }

.entete-accueil ~ .mention-source a {
  color: #ffffff;
  text-decoration-color: rgba(255, 255, 255, 0.6);
}

/* Écran d'accueil */

.entete-accueil {
  display: flex;
  flex-direction: column;
  gap: var(--espace-petit);
  margin: 0;
}

.entete-accueil .titre-app {
  font-size: 1.75rem;
  margin: 0;
}

.sous-titre-accueil {
  /* Rapproché du bloc-titre juste au-dessus (rythme --espace-petit trop
     large pour ce couple précis) sans toucher au gap entre les autres blocs. */
  margin: -11px 0 0;
  font-size: 0.82rem;
  text-align: center;
  color: #ffffff;
}

.ligne-commune {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.nom-commune {
  font-size: 1.1rem;
  font-weight: 600;
  color: #ffffff;
}

.bouton-localisation {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 50%;
  width: 50px;
  height: 50px;
  color: var(--bordure-app);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  outline: none;
}

.icone-pin {
  position: relative;
  z-index: 1;
  width: 34px;
  height: 34px;
}

/* Repère de découverte : anneau bleu clair qui pulse vite autour du picto
   localisation tant que l'utilisateur n'a jamais cliqué dessus. Le picto
   lui-même ne change pas — voir js/app.js pour la condition d'affichage. */
.anneau-pulsation-pin {
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: var(--bleu-clair);
  pointer-events: none;
  animation: anneau-pulsation-pin 1s ease-out infinite;
}

.anneau-pulsation-pin[hidden] { display: none; }

@keyframes anneau-pulsation-pin {
  0% { transform: scale(0.9); opacity: 0.7; }
  100% { transform: scale(1.3); opacity: 0; }
}

.bouton-discret {
  background: none;
  border: none;
  font-size: 1.2rem;
  color: var(--texte-discret);
  cursor: pointer;
  padding: 6px;
  line-height: 1;
}

/* Bannière "Alerte exceptionnelle" (5 phénomènes hors grille) — repensée le
   2026-08-19 après retour utilisateur sur le rendu réel (voir
   SUIVI_QUALITE.md) : d'abord un cadre en dégradé animé volontairement
   distinct du style carte, jugé trop "usine à gaz" une fois vu en vrai.
   Désormais même bordure/carte que les autres modules ("même état d'esprit"),
   avec une pulsation rouge en plus — même technique que la sélection d'un
   picto (pulsation-bordure-selection), juste un peu plus marquée (halo plus
   large) puisqu'il s'agit d'une alerte plus grave. box-shadow, jamais
   border-width : ne participe jamais au calcul de mise en page (leçon du
   2026-08-14). */
.banniere-exceptionnelle {
  position: relative;
  max-width: 480px;
  width: 100%;
  margin: 0 auto;
  background: var(--carte-fond);
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 16px;
  padding: 14px 16px;
  animation: pulsation-banniere-exceptionnelle 3s ease-in-out infinite;
}

.banniere-exceptionnelle[hidden] { display: none; }

@keyframes pulsation-banniere-exceptionnelle {
  0%, 100% { border-color: var(--bordure-app); box-shadow: 0 0 0 0 transparent; }
  50% { border-color: var(--couleur-banniere-pulsation); box-shadow: 0 0 0 5px var(--couleur-banniere-pulsation); }
}

.banniere-exceptionnelle[data-niveau="orange"] { --couleur-banniere-pulsation: var(--niveau-orange); }
.banniere-exceptionnelle[data-niveau="rouge"] { --couleur-banniere-pulsation: var(--niveau-rouge); }

/* Grille à 3 colonnes (espaceur | titre | croix) plutôt qu'un positionnement
   en pixels fixes (padding-right, transform et marges négatives, tous
   essayés et abandonnés le 2026-08-20, voir SUIVI_QUALITE.md) : les deux
   colonnes externes ont EXACTEMENT la même largeur, donc le titre reste
   centré sur le vrai centre de la carte quelle que soit sa largeur — les
   réglages en pixels fixes tenaient à 375px mais se remettaient à chevaucher
   la croix à 320px (iPhone SE), ce correctif est indépendant de la largeur
   d'écran par construction, pas seulement ajusté pour un format précis. */
.banniere-exceptionnelle-entete {
  display: grid;
  grid-template-columns: 28px 1fr 28px;
  align-items: start;
  margin: 0 0 12px;
}

.banniere-exceptionnelle-titre-ligne {
  grid-column: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.banniere-exceptionnelle .bouton-fermer {
  grid-column: 3;
  justify-self: end;
  position: static;
  margin: 0;
}

/* Titre ET triangle pulsent exactement comme la bordure (même durée/timing,
   même forme noir -> couleur -> noir) : retour utilisateur du 2026-08-19,
   "l'ensemble doit pulser en même temps" pour une vraie cohérence visuelle
   — pas seulement la bordure et le triangle, le titre aussi. margin-top du
   triangle remis à 0 : le hack de .symbole-niveau (décalage pour s'aligner
   sur un paragraphe voisin) ne s'applique pas ici, l'icône est centrée
   verticalement avec le titre via align-items:center. */
#banniere-titre,
.banniere-symbole {
  margin: 0;
  animation: pulsation-couleur-banniere 3s ease-in-out infinite;
}

/* Taille réduite par rapport au h2 par défaut du navigateur (~1.5em) :
   "Alerte exceptionnelle" doit tenir sur une seule ligne, centré, entre
   deux colonnes de 28px réservées à la croix — sinon le titre passe sur
   2 lignes à 320px (iPhone SE) et le triangle (centré verticalement dans
   ce bloc désormais plus haut) chevauche la croix (checklist de lancement,
   2026-08-20). Le panneau de détail garde le h2 par défaut, non concerné :
   son titre n'est ni centré ni voisin d'une croix sur la même ligne.
   0.95rem choisi après mesure directe à 320px (le pire cas) : en dessous,
   le triangle grignote la colonne réservée à la croix (essayé, comprime le
   bouton lui-même — mauvais pour la zone tactile) ; à 1rem pile, il ne
   reste que 1px d'écart, trop fragile d'un système à l'autre (la police
   système diffère réellement entre iOS/Android/Windows) ; 0.95rem laisse
   5px de marge nette, mesurés, au prix d'un titre à peine plus petit que
   le texte du corps (16px) — la graisse du h2 (gras par défaut) suffit à
   le distinguer visuellement, écart de taille imperceptible en usage réel. */
#banniere-titre {
  font-size: 0.95rem;
}

@keyframes pulsation-couleur-banniere {
  0%, 100% { color: var(--bordure-app); }
  50% { color: var(--couleur-banniere-pulsation); }
}

.grille-pictos {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  max-width: 480px;
  margin: 0 auto;
  width: 100%;
}

.carte-picto {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px 6px 8px;
  background: var(--carte-fond);
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 16px;
  cursor: pointer;
  overflow: hidden;
  outline: none;
}

/* Feedback tactile bref au clic/appui : fond bleu clair, en plus de la
   bordure — repère nécessaire depuis que la forme est ronde partout. */
.carte-picto:active,
.carte-picto:focus-visible,
.bouton-localisation:active,
.bouton-localisation:focus-visible {
  background-color: var(--bleu-clair);
}

/* Repère persistant : le picto dont le détail est actuellement ouvert garde une
   bordure bleue (au lieu de noire) tant qu'on ne sélectionne pas un autre picto
   ou qu'on ne ferme pas le détail — pour savoir où on a cliqué même après avoir
   relâché. Pulsation douce et continue (pas un flash ponctuel) tant qu'il reste
   sélectionné, effet "vague" qui va et vient. Le renfort blanc est un halo
   EXTÉRIEUR en `box-shadow` (jamais `inset`, jamais `border-width`) : un anneau
   intérieur reste invisible car la carte est déjà blanche à l'intérieur (retour
   utilisateur du 2026-08-14) — vers l'extérieur, il se détache nettement sur le
   fond bleu roi de l'écran. Comme la bordure classique, le box-shadow ne compte
   jamais dans la taille de l'élément (inset ou non) : les 2 pictos non
   sélectionnés restent parfaitement fixes pendant que l'autre pulse, même en
   partageant la même ligne de la grille CSS. */
.carte-picto[data-selectionnee="true"] {
  animation: pulsation-bordure-selection 1.8s ease-in-out infinite;
}

@keyframes pulsation-bordure-selection {
  0%, 100% { border-color: var(--bleu); box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  50% { border-color: #ffffff; box-shadow: 0 0 0 3px #ffffff; }
}

.halo-niveau {
  position: absolute;
  inset: 0;
  opacity: 0.16;
}
.halo-niveau[data-niveau="vert"] { background: var(--niveau-vert); }
.halo-niveau[data-niveau="jaune"] { background: var(--niveau-jaune); }
.halo-niveau[data-niveau="orange"] { background: var(--niveau-orange); }
.halo-niveau[data-niveau="rouge"] { background: var(--niveau-rouge); }
.halo-niveau[data-niveau="indisponible"] { background: var(--niveau-indisponible); }

.icone-svg {
  width: 48px;
  height: 48px;
  position: relative;
}
.carte-picto[data-niveau="vert"] .icone-svg { color: var(--niveau-vert); }
.carte-picto[data-niveau="indisponible"] .icone-svg { color: var(--niveau-indisponible); }

/* Repère visuel : dès qu'un picto a une vraie alerte (jaune/orange/rouge),
   son icône respire entre le vert ("rien à signaler") et sa vraie couleur —
   pour repérer en un coup d'œil, parmi les 4, lequel a changé et mérite un
   clic. Jamais sur vert ni indisponible : rien à signaler dans ces cas.
   Un seul jeu d'images clés réutilisé via --couleur-alerte-picto, seule la
   couleur cible change par niveau (cohérent avec le clignotement doux déjà
   utilisé ailleurs dans l'app, jamais un flash brusque). */
.carte-picto[data-niveau="jaune"] .icone-svg,
.carte-picto[data-niveau="orange"] .icone-svg,
.carte-picto[data-niveau="rouge"] .icone-svg {
  animation: respiration-alerte-picto 2s ease-in-out infinite;
}
.carte-picto[data-niveau="jaune"] .icone-svg { --couleur-alerte-picto: var(--niveau-jaune); }
.carte-picto[data-niveau="orange"] .icone-svg { --couleur-alerte-picto: var(--niveau-orange); }
.carte-picto[data-niveau="rouge"] .icone-svg { --couleur-alerte-picto: var(--niveau-rouge); }

@keyframes respiration-alerte-picto {
  0%, 100% { color: var(--niveau-vert); }
  50% { color: var(--couleur-alerte-picto); }
}


.etiquette {
  position: relative;
  font-size: 0.95rem;
  font-weight: 600;
  text-align: center;
  color: var(--texte);
  text-wrap: balance;
}

/* Panneau de détail : carte en flux normal, juste sous la grille de pictos */

.panneau-detail {
  position: relative;
  max-width: 480px;
  width: 100%;
  margin: 0 auto;
  background: var(--carte-fond);
  border: var(--epaisseur-bordure) solid var(--bordure-app);
  border-radius: 16px;
  padding: 20px 20px 16px;
  /* Défile en interne plutôt que de pousser toute la fenêtre (et donc
     "Propulsé par BS Concept") vers le bas. min-height:0 est nécessaire
     dans un flex column pour qu'un élément accepte de se réduire en
     dessous de la taille de son contenu, sinon overflow-y n'a aucun effet. */
  min-height: 0;
  overflow-y: auto;
}

.panneau-detail[hidden] { display: none; }

.bouton-fermer {
  position: absolute;
  top: 12px;
  right: 14px;
  font-size: 1.1rem;
}

#detail-titre {
  color: var(--bleu-fonce);
  margin: 0 0 12px;
}

.panneau-detail[data-niveau="vert"] #detail-titre { color: var(--niveau-vert); }
.panneau-detail[data-niveau="jaune"] #detail-titre { color: var(--niveau-jaune); }
.panneau-detail[data-niveau="orange"] #detail-titre { color: var(--niveau-orange); }
.panneau-detail[data-niveau="rouge"] #detail-titre { color: var(--niveau-rouge); }
.panneau-detail[data-niveau="indisponible"] #detail-titre { color: var(--niveau-indisponible); }

.ligne-niveau-detail {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 16px;
}

/* La FORME suit le sens du message, pas seulement la couleur : triangle
   (urgence) réservé à jaune/orange/rouge, coche pour vert (tout va bien),
   tiret neutre pour donnée indisponible — voir mettreAJourSymboleGravite()
   dans js/app.js pour le choix de la forme. */
.symbole-niveau {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--niveau-indisponible);
}

.panneau-detail[data-niveau="vert"] .symbole-niveau { color: var(--niveau-vert); }
.panneau-detail[data-niveau="jaune"] .symbole-niveau { color: var(--niveau-jaune); }
.panneau-detail[data-niveau="orange"] .symbole-niveau { color: var(--niveau-orange); }
.panneau-detail[data-niveau="rouge"] .symbole-niveau { color: var(--niveau-rouge); }
.panneau-detail[data-niveau="indisponible"] .symbole-niveau { color: var(--niveau-indisponible); }

#detail-texte,
#banniere-texte {
  margin: 0;
  line-height: 1.5;
  color: var(--texte);
  /* "balance"/"pretty" essayés le 2026-08-20 pour éviter un mot isolé en fin
     de paragraphe ("orphelin") : corrigent bien ce cas, mais rétrécissent le
     bloc de texte pour égaliser les lignes, laissant un vide à droite même
     quand la largeur ne manque pas — jugé plus gênant que l'orphelin
     occasionnel qu'ils évitaient (choix explicite de l'utilisateur, voir
     SUIVI_QUALITE.md). Revenu volontairement au retour à la ligne par défaut
     du navigateur : utilise toute la largeur disponible sur (quasi) toutes
     les lignes, au prix d'un mot seul en toute fin de temps en temps. */
}

@media (min-width: 600px) {
  .ecran { padding-top: 60px; }
}
