/* Feuille commune au frontoffice et au backoffice.
   Reprend la palette de carto/carte.gabarit.html pour que la carte servie par le
   serveur et la carte autonome se ressemblent — ce sont les mêmes données. */

:root {
  --fond: #f7f6f3;
  --texte: #1c1b19;
  --trait: #d8d4cc;
  --alerte: #b3261e;
  --orange: #c9820a;
  --vert: #2c6a68;
  --gris: #6b675f;
}

* { box-sizing: border-box }

body {
  margin: 0;
  font: 14px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: var(--texte);
  background: var(--fond);
}

a { color: #1a5fb4 }

code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .92em }

/* ── Ossature des pages de texte (fiche, backoffice) ───────────────────────── */

.page { max-width: 1080px; margin: 0 auto; padding: 18px 22px 80px }

.barre {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  border-bottom: 1px solid var(--trait); padding-bottom: 10px; margin-bottom: 18px;
}
.barre h1 { font-size: 19px; margin: 0 }
.barre nav { margin-left: auto; display: flex; gap: 14px }

section { margin: 26px 0 }
/* Le titre de section garde son apparence qu'il soit posé directement dans la
   `<section>` ou porté par le `<summary>` d'un volet repliable. */
section > h2, section > details.volet > summary > h2 {
  font: 600 11px/1 ui-monospace, monospace; letter-spacing: .11em;
  text-transform: uppercase; color: var(--gris);
  border-bottom: 1px solid var(--trait); padding-bottom: 7px; margin: 0 0 12px;
}
h3 { font-size: 14px; margin: 16px 0 6px }

/* ── Tableaux ──────────────────────────────────────────────────────────────── */

table.grille { border-collapse: collapse; width: 100%; font-size: 13px }
table.grille th, table.grille td {
  text-align: left; padding: 5px 9px; border-bottom: 1px solid var(--trait);
  vertical-align: top;
}
table.grille th { font: 600 11px/1.4 ui-monospace, monospace; color: var(--gris) }
table.grille td.chiffre, table.grille th.chiffre {
  text-align: right; font-variant-numeric: tabular-nums;
}
table.grille tbody tr:hover { background: #fffdf8 }

/* ── États et encadrés ─────────────────────────────────────────────────────── */

/* 🔴 « non évalué » ne doit jamais ressembler à une valeur. Gris, en italique, et
   distinct d'un zéro : c'est la règle n° 3, elle a déjà été violée deux fois. */
.non-evalue { color: var(--gris); font-style: italic }
.alerte { color: var(--alerte) }
.aparte { color: var(--gris); font-size: 12.5px }

.encadre {
  border: 1px solid var(--trait); border-left: 4px solid var(--gris);
  background: #fff; border-radius: 5px; padding: 9px 13px; margin: 10px 0;
}
.encadre.rouge { border-left-color: var(--alerte) }
.encadre.orange { border-left-color: var(--orange) }
.encadre ul { margin: .4em 0 0; padding-left: 1.2em }

.jeton {
  display: inline-block; font-size: 11.5px; padding: 2px 7px; border-radius: 3px;
  background: #ecebe7; color: var(--gris); border: 1px solid var(--trait);
}
.jeton-vert { background: #dceae8; color: var(--vert); border-color: #b9d5d2 }
.jeton-rouge { background: #f7e3e1; color: var(--alerte); border-color: #e9c4c1 }

.score { font-size: 16px; margin: 6px 0 }
.texte { white-space: pre-wrap; background: #fff; border: 1px solid var(--trait);
         border-radius: 5px; padding: 10px 13px; font-size: 13.5px }

.vignettes { display: flex; flex-wrap: wrap; gap: 8px }
.vignettes img { width: 190px; height: 140px; object-fit: cover; border-radius: 4px;
                 border: 1px solid var(--trait) }

.fiches-cles { display: flex; flex-wrap: wrap; gap: 8px 26px; margin: 10px 0 }
.fiches-cles div { min-width: 130px }
.fiches-cles b { display: block; font: 600 10px/1.6 ui-monospace, monospace;
                 letter-spacing: .09em; text-transform: uppercase; color: var(--gris) }

/* ── Contrôles ─────────────────────────────────────────────────────────────── */

button, select, input[type=text], input[type=number], textarea {
  font: inherit; color: inherit; border: 1px solid var(--trait);
  background: #fff; border-radius: 4px; padding: 5px 9px;
}
button { cursor: pointer; background: #f6f7f4 }
button:hover:not(:disabled) { background: #eceeea }
button:disabled { opacity: .45; cursor: not-allowed }
button.principal { background: var(--vert); color: #fff; border-color: var(--vert) }
button.danger { border-color: var(--alerte); color: var(--alerte) }

textarea { width: 100%; min-height: 380px; font-family: ui-monospace, monospace;
           font-size: 12.5px; line-height: 1.5; white-space: pre }

.rangee { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 8px 0 }

.console {
  background: #16150f; color: #dcd7c9; border-radius: 5px; padding: 10px 13px;
  font-family: ui-monospace, monospace; font-size: 12px; line-height: 1.5;
  max-height: 380px; overflow-y: auto; white-space: pre-wrap; word-break: break-word;
}

/* Dépôt de fichier — import manuel ingatlan.com. Un `<label>` et non une `<div>` :
   cliquer la zone ouvre le sélecteur de fichier sans une ligne de JavaScript, et le
   glisser-déposer n'est qu'un raccourci par-dessus. */
.depot {
  display: block; border: 2px dashed var(--trait); border-radius: 6px;
  background: #fff; padding: 16px 18px; margin: 10px 0; cursor: pointer;
}
.depot.survol { border-color: var(--vert); background: #f4faf8 }
.depot b { display: block; margin-bottom: 3px }
.depot input[type=file] { display: block; margin-top: 8px; font-size: 12.5px }

.niveau-WARNING { color: var(--orange); font-weight: 600 }
.niveau-ERROR, .niveau-CRITICAL { color: var(--alerte); font-weight: 600 }
.niveau-DEBUG { color: var(--gris) }

.onglets { display: flex; gap: 6px; margin-bottom: 10px }
.onglets button[aria-selected=true] { background: #fff; border-bottom-color: #fff;
                                      font-weight: 600 }

/* ── Avis de Guillaume : trois états, jamais deux ───────────────────────────── */
/*
   🔴 L'état neutre — aucun avis posé — reste NEUTRE visuellement. Ni rouge, ni barré,
   ni grisé « comme si » : « pas encore regardé » ne doit ressembler ni de près ni de
   loin à « écarté ». Seul un bouton réellement pressé prend une couleur.
*/
.avis { border: 1px solid var(--trait); border-left: 4px solid var(--gris);
        background: #fff; border-radius: 5px; padding: 9px 13px; margin: 10px 0 }
.avis[data-avis-valeur=aime] { border-left-color: var(--vert) }
.avis[data-avis-valeur=ecarte] { border-left-color: var(--alerte) }
.avis-etat { margin: 0 0 8px }
.avis-boutons { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px }
.avis-boutons button.actif[data-avis-poser=aime] {
  background: var(--vert); color: #fff; border-color: var(--vert) }
.avis-boutons button.actif[data-avis-poser=ecarte] {
  background: var(--alerte); color: #fff; border-color: var(--alerte) }
.avis-motif { display: block; font-size: 12.5px; color: var(--gris) }
.avis-motif input { width: 100%; margin-top: 3px; color: var(--texte) }
.avis-retour { margin: 6px 0 0; min-height: 1.2em }

/* ── Onglets de navigation entre les deux listes de préférences ─────────────── */

.onglets a.onglet {
  text-decoration: none; color: var(--texte); border: 1px solid var(--trait);
  border-radius: 4px 4px 0 0; padding: 6px 12px; background: #ecebe7;
}
.onglets a.onglet.courant { background: #fff; border-bottom-color: #fff;
                            font-weight: 600 }
.rangee a.bouton {
  text-decoration: none; border: 1px solid var(--trait); background: #f6f7f4;
  border-radius: 4px; padding: 5px 9px; color: var(--texte);
}
.rangee a.bouton:hover { background: #eceeea }

/* Dans la bulle de la carte, le widget occupe toute la largeur disponible. */
.leaflet-popup-content .avis { margin: 8px 0 0; padding: 7px 9px; font-size: 12.5px }
.leaflet-popup-content .avis-motif input { font-size: 12px }

/* ── Volets repliables (fiche de bureau) ───────────────────────────────────── */
/* `<details>` natif plutôt qu'un accordéon en JavaScript : ça marche sans script,
   c'est accessible au clavier, et Safari le gère depuis longtemps. La fiche s'est
   beaucoup allongée — bloc de crue, tête de puits, sol, forage, solaire, nappe — et
   tout déplié elle demande de faire défiler pour trouver ce qui inquiète.

   🔴 Un volet replié ne fait jamais disparaître une alerte : `vues._volet_bureau`
   ouvre celui qui alerte ET recopie sa marque dans le titre. Le style ne fait que
   suivre cette décision, il ne la prend pas. */

details.volet > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
}

details.volet > summary::-webkit-details-marker { display: none }

details.volet > summary::after {
  content: "▾";
  margin-left: 10px;
  color: var(--gris);
  font-size: 12px;
}

details.volet[open] > summary::after { content: "▴" }

/* Le `<h2>` reste le titre de section : il garde sa sémantique, ses styles et sa
   place dans le sommaire d'un lecteur d'écran. Seule sa marge change, le `summary`
   la portant désormais. */
details.volet > summary > h2 { margin: 0; border: 0; padding: 0; flex: 1 1 auto }

/* ── Profil de recherche (page « préférences ») ─────────────────────────────────
   Un formulaire de seuils, pas un tableau de bord : les champs sont larges, empilés,
   et chaque grille porte sa légende. Un réglage qu'on ne relit pas est un réglage
   qu'on repose de travers. */
.groupe-profil {
  border: 1px solid #ddd8cf; border-radius: 6px; padding: 10px 12px; margin: 10px 0;
}
.groupe-profil legend { font-weight: 600; padding: 0 6px }
.champ-profil {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 6px 0; font-size: 14px;
}
.champ-profil select { margin-left: auto; min-width: 180px }
.champ-profil small { color: #6b675f; font-size: 12px; flex-basis: 100%; }
/* 🔴 L'avertissement d'un drapeau ne se replie pas et ne s'atténue pas : c'est la seule
   phrase qui dit qu'un mot du vendeur a déjà fait disparaître le meilleur bien. */
.champ-profil small.avertissement { color: #b3261e }

/* ── Accès aux modèles locaux (page « préférences ») ────────────────────────────
   🔴 Trois états, trois couleurs, et le gris n'est PAS un vert pâle : « jamais
   éprouvé » doit se lire comme une absence de mesure, pas comme un feu au vert. */
.acces-ligne {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 10px 0 4px; padding: 8px 10px;
  border: 1px dashed var(--trait); border-radius: 6px; background: #fbfaf8;
}
.acces-ligne button { margin-left: auto }
.pastille { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
            font-weight: 600; color: var(--gris) }
.pastille::before {
  content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--gris);
}
.pastille.joignable { color: var(--vert) }
.pastille.joignable::before { background: var(--vert) }
.pastille.injoignable { color: var(--alerte) }
.pastille.injoignable::before { background: var(--alerte) }
.acces-detail { flex-basis: 100%; color: #6b675f; font-size: 12px }
/* Une divergence entre le modèle configuré et le modèle servi ne s'atténue pas :
   c'est la seule phrase qui dise qu'une passe tourne sur autre chose que ce qu'on
   croit. */
.acces-detail.divergence { color: var(--alerte); font-weight: 600 }
.liste-ecartes { margin: .4em 0 0; padding-left: 1.2em; font-size: 13px }
.liste-ecartes small { display: block; color: #6b675f; font-size: 12px }
.aparte.avertissement { color: var(--alerte) }

/* ── Menu de « Préférences » : de grosses tuiles cliquables ─────────────────────
   🔴 Dimensionnées pour le POUCE et pour l'écran d'un iPhone. Mesuré sur ce projet
   avant de coder : le panneau de filtres de la carte occupait 778 px sur 844 (92 % de
   l'écran d'un iPhone 14/15). Une grille de deux colonnes à 132 px de haut tient les
   quatre tuiles en ~290 px, soit un tiers de l'écran, sans acrobatie.
   `minmax(220px, 1fr)` : une seule colonne en dessous de ~460 px de large, deux
   au-delà — aucune requête média à maintenir en double avec le JavaScript. */
.tuiles {
  display: grid; gap: 12px; margin: 18px 0;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.tuile {
  display: flex; flex-direction: column; gap: 6px;
  /* 🔴 Cible tactile généreuse : la tuile ENTIÈRE est le lien, pas son titre. */
  min-height: 132px; padding: 14px 16px;
  border: 1px solid var(--trait); border-radius: 10px; background: #fff;
  color: var(--texte); text-decoration: none;
}
.tuile:hover, .tuile:focus-visible { border-color: var(--vert); color: var(--vert) }
.tuile:focus-visible { outline: 2px solid var(--vert); outline-offset: 2px }
/* Le pictogramme suit la couleur du texte (`currentColor` dans le SVG) : au survol il
   change avec le titre, au lieu de rester collé comme une image importée. */
.pict-tuile { width: 34px; height: 34px; display: block }
.tuile-titre { font-size: 15px }
.tuile-resume { color: var(--gris); font-size: 12.5px }
.tuile .jeton { align-self: flex-start; margin-top: auto }

/* Libellé d'une liaison ou d'un lieu, dans une `.acces-ligne`. */
.acces-libelle { font-weight: 600 }

/* 🔴 Une ligne ÉCARTÉE d'un classement — jamais cachée, jamais rangée à zéro. Elle
   reste lisible, en retrait, et la phrase au-dessus dit combien elles sont. */
tr.hors-classement td { background: #faf8f4; color: var(--gris) }
tr.hors-classement td:first-child { border-left: 3px solid var(--trait) }

/* Lu par les lecteurs d'écran, invisible à l'œil. Sert aux annonces `aria-live` qui
 * doubleraient un titre déjà affiché — les répéter à l'écran serait du bruit, les
 * supprimer rendrait le changement muet pour qui ne voit pas la page. */
.hors-ecran {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* ── Explications repliées derrière un « ? » ─────────────────────────────────────
 *
 * Le fait reste en clair, la démonstration se replie. Le bouton doit se voir sans
 * attirer l'œil plus que la donnée qu'il explique. */
button.aide {
  appearance: none;
  border: 1px solid var(--trait);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 11px;
  line-height: 1;
  width: 16px; height: 16px;
  border-radius: 50%;
  padding: 0;
  cursor: help;
  vertical-align: baseline;
  opacity: .65;
}
button.aide:hover, button.aide:focus-visible { opacity: 1; background: var(--fond-doux, #eee) }

dialog.aide-modale {
  max-width: 46em;
  border: 1px solid var(--trait);
  border-radius: 4px;
  padding: 18px 22px;
  color: var(--texte);
  background: var(--fond);
}
dialog.aide-modale::backdrop { background: rgba(0, 0, 0, .35) }
dialog.aide-modale h2 { margin: 0 0 10px; font-size: 16px }
dialog.aide-modale .aide-corps p { margin: 0 0 10px }
dialog.aide-modale .aide-pied { text-align: right; margin-top: 4px }

/* ── Progression de chargement de la carte ─────────────────────────────────────
   🔴 Posé au-dessus de la carte, pas dans le tiroir des filtres : celui-ci est fermé à
   l'ouverture, donc l'ancien message de chargement était invisible quand il servait.
   Mesure du 2026-09-14 : /api/biens.geojson faisait 9,9 Mo non compressés et 15,7 s
   d'attente pendant lesquelles la carte restait vide sans rien dire. */
#progres-carte {
  position: absolute;
  top: 12px; left: 50%; transform: translateX(-50%);
  z-index: 800;                 /* au-dessus des tuiles, sous les menus déroulants */
  display: flex; align-items: center; gap: 10px;
  padding: 8px 14px; border-radius: 8px;
  background: var(--fond, #fff); color: var(--encre, #1a1a1a);
  border: 1px solid rgba(0, 0, 0, .18);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
  font: 12px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  max-width: min(90vw, 420px);
}
#progres-carte[hidden] { display: none !important; }
#progres-barre { width: 160px; height: 8px; flex: 0 0 auto }
#progres-texte { white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
/* Une barre sans `value` s'affiche indéterminée — c'est exactement ce qu'on veut quand la
   taille réelle est inconnue (réponse compressée : `Content-Length` est la taille
   COMPRESSÉE, un pourcentage calculé dessus dépasserait 100 %). */
@media (prefers-color-scheme: dark) {
  #progres-carte:not([data-theme="light"]) {
    background: #24262b; color: #e8e8ea; border-color: rgba(255, 255, 255, .16);
  }
}
