/* =====================================================================
   Gexplorer - Feuille de style principale
   Palette sombre orientee carte, accent ocre pour le patrimoine.
   ===================================================================== */

:root {
    --fond:          #0e1a17;
    --fond-2:        #142722;
    --fond-3:        #1b342d;
    --bordure:       #23453c;
    --texte:         #e8f0ed;
    --texte-doux:    #9db3ac;
    --primaire:      #1f6f5c;
    --primaire-clair:#2e9c80;
    --accent:        #e0a458;
    --accent-clair:  #f0bf82;
    --danger:        #d9534f;
    --succes:        #4caf7d;
    /* LES ANGLES SONT POLIS, PAS SUPPRIMES.

       L'application parle de vieilles pierres, et une vieille pierre n'a
       pas d'arete : seuils, margelles et bancs sont adoucis par l'usage.
       Les rayons sont donc genereux — mais les surfaces de LECTURE
       gardent des coins francs : un panneau trop rond mange ses marges
       et son texte flotte. La rondeur pleine (999px) est reservee a ce
       qu'on TOUCHE : boutons, pastilles, temoins. */
    --rayon:         20px;
    --rayon-s:       13px;
    /* L'ombre s'etale plus qu'elle ne noircit : une ombre dure decoupe,
       une ombre diffuse pose l'element sur la page sans le detacher. */
    --ombre:         0 12px 34px rgba(0, 0, 0, .28);
    --entete-h:      58px;
    --barre-h:       62px;
    --police:        system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    --police-titre:  "Iowan Old Style", "Palatino Linotype", Georgia, serif;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    background: var(--fond);
    color: var(--texte);
    font-family: var(--police);
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
    overscroll-behavior-y: none;
}

body { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-clair); }

h1, h2, h3 { font-family: var(--police-titre); font-weight: 600; line-height: 1.2; margin: 0 0 .5em; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.28rem; }
h3 { font-size: 1.08rem; }
p  { line-height: 1.62; margin: 0 0 1em; }

/* --- En-tete --------------------------------------------------------- */

.entete {
    height: var(--entete-h);
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 14px;
    background: var(--fond-2);
    border-bottom: 1px solid var(--bordure);
    position: sticky;
    top: 0;
    z-index: 900;
}

.entete .marque {
    font-family: var(--police-titre);
    font-size: 1.22rem;
    font-weight: 600;
    color: var(--texte);
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
}
.entete .marque .boussole { font-size: 1.35rem; }
.entete .espace { flex: 1; }

.entete-action {
    background: none;
    border: 1px solid var(--bordure);
    color: var(--texte-doux);
    border-radius: 999px;
    padding: 7px 13px;
    font-size: .84rem;
    cursor: pointer;
    font-family: inherit;
    white-space: nowrap;
}
.entete-action:hover { color: var(--texte); border-color: var(--primaire-clair); }

/* --- Contenu --------------------------------------------------------- */

.contenu {
    flex: 1 1 auto;
    padding: 18px 16px calc(var(--barre-h) + 22px);
    max-width: 1100px;
    width: 100%;
    margin: 0 auto;
}
.contenu.pleine-hauteur { padding: 0; max-width: none; position: relative; }

/* Une vitrine, pas un texte a lire.
   ---------------------------------------------------------------------
   1100 px conviennent a une page qu'on lit : au-dela, l'oeil perd sa
   ligne en revenant a la gauche. Mais l'accueil ne se lit pas, il se
   parcourt — des vignettes, des chiffres, quatre encarts. Sur un ecran
   de 1920, la colonne de 1100 laissait 410 px de vide de chaque cote.

   Les blocs qui contiennent VRAIMENT du texte suivi gardent leur largeur
   de lecture : ils la fixent eux-memes (voir .accueil-chiffres,
   .hero-texte, la pile de boutons). Ce n'est donc que la place des
   grilles qui augmente. */
.contenu-large { max-width: 1500px; }

/* Le bloc Android : le texte a gauche, le telechargement a droite.
   ---------------------------------------------------------------------
   Etire sur 1500 px, il donnait une phrase de cent quatre-vingts signes
   sur une ligne et un bouton large comme l'ecran. Deux colonnes remettent
   chacun a sa mesure — et sur un telephone, la grille repasse a une
   colonne sans qu'on ait rien a dire de plus. */
.bloc-android .corps {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 18px;
    align-items: center;
}
.bloc-android .android-texte h3 { margin-bottom: 8px; }
.bloc-android .android-texte p  { margin: 0 0 10px; max-width: 62ch; }
.bloc-android .android-action .aide { margin: 8px 0 0; }

@media (min-width: 900px) {
    .bloc-android .corps {
        grid-template-columns: minmax(0, 1fr) minmax(280px, 340px);
        gap: 32px;
    }
}

/* --- Barre de navigation basse --------------------------------------- */

.barre-nav {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    height: var(--barre-h);
    display: flex;
    background: rgba(20, 39, 34, .96);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--bordure);
    /* Les epaules rondes laissent passer un coin de carte : la barre est
       posee sur l'ecran, elle ne le coupe pas. */
    border-radius: 22px 22px 0 0;
    z-index: 950;
    padding-bottom: env(safe-area-inset-bottom);
}
.barre-nav a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    color: var(--texte-doux);
    /* MESURE
       Le plus long libelle est « Compagnons » : 64 px a .68rem. Un onglet
       dispose de 68 px a 360 de large (cinq onglets), et de 60 px a 320.
       Une taille fixe devait donc choisir entre etre lisible sur les uns
       et deborder sur les autres — la regle precedente tranchait a
       9,8 px pour tout le monde en dessous de 380, ce qui est petit pour
       lire en marchant.
       Elle suit maintenant la largeur : 10,9 px des 358 px d'ecran,
       9,8 px seulement sur les plus etroits, ou la place manque
       reellement. */
    font-size: clamp(.61rem, 3.05vw, .68rem);
    letter-spacing: .02em;
}
.barre-nav a .ico { font-size: 1.28rem; line-height: 1; }
.barre-nav a.actif { color: var(--accent); }

/* --- Carte ----------------------------------------------------------- */

#carte {
    position: absolute;
    inset: 0;
    bottom: var(--barre-h);
    background: var(--fond);
    /* Le geste vers le bas appartient a la carte, pas au navigateur :
       il veut dire « fais remonter la vue », pas « recharge ».
       `html, body` porte deja la regle, et c'est elle qui agit puisque
       #carte ne defile pas. On la repete ici pour que l'intention reste
       lisible a cote de la carte, et pour couvrir le jour ou ce
       conteneur deviendrait defilable.

       `touch-action` n'est PAS pose ici : Leaflet le regle lui-meme sur
       .leaflet-container, et le doubler risquerait d'empecher le
       defilement des bulles qu'il ouvre a l'interieur. */
    overscroll-behavior: none;
}
.leaflet-container {
    background: #16241f;
    font-family: var(--police);
    /* Le geste vers le bas appartient a la carte, ou qu'elle se trouve :
       plein ecran, dans la boutique, dans un formulaire de
       l'administration. `none` empeche la fin de course de remonter a la
       page, donc le « tirer pour rafraichir » du navigateur. */
    overscroll-behavior: none;
}
.leaflet-control-attribution {
    background: rgba(14, 26, 23, .78) !important;
    color: var(--texte-doux) !important;
    font-size: 10px !important;
}
.leaflet-control-attribution a { color: var(--texte-doux) !important; }
.leaflet-bar a {
    background: var(--fond-2) !important;
    color: var(--texte) !important;
    border-bottom-color: var(--bordure) !important;
}
.leaflet-bar a:hover { background: var(--fond-3) !important; }

/* Lissage des tuiles étirées au-delà du zoom natif.

   Leaflet pose `image-rendering: -webkit-optimize-contrast` sur les moteurs
   WebKit — utile pour une tuile à sa taille exacte, néfaste dès qu'on
   l'agrandit : le trait devient un escalier de pixels. Passé le z18, la
   tuile est justement étirée en permanence, donc on impose l'interpolation
   lisse partout, y compris dans la WebView Android. */
.leaflet-container img.leaflet-tile,
.leaflet-safari .leaflet-tile {
    image-rendering: auto !important;
    image-rendering: smooth !important;
    image-rendering: high-quality !important;
}

/* Lisser seul rendrait le trait laiteux. La convolution posée par
   carte.js lui rend son arête ; le léger gain de contraste compense la
   perte de densité de l'agrandissement. La classe n'est présente que
   au-delà du zoom natif, et jamais en mode économie d'énergie. */
.leaflet-container.fond-etire img.leaflet-tile {
    filter: url(#gex-affine) contrast(1.05) saturate(1.03);
}
@supports not (filter: url(#gex-affine)) {
    .leaflet-container.fond-etire img.leaflet-tile {
        filter: contrast(1.08) saturate(1.05);
    }
}
/* Certains appareils rendent la convolution trop dure ; l'utilisateur qui
   demande moins d'effets visuels garde le lissage, sans le réaffûtage. */
@media (prefers-reduced-motion: reduce) {
    .leaflet-container.fond-etire img.leaflet-tile { filter: none; }
}

/* Case « Lieu exploré ». Pressable sur toute sa largeur — on la vise au
   pouce, souvent en marchant — et réversible : la coche se retire. */
.case-explore {
    display: flex; align-items: center; gap: 12px;
    width: 100%; padding: 13px 16px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: 16px;
    color: var(--texte);
    font: inherit; font-size: 15px; text-align: left;
    cursor: pointer;
    transition: background .16s, border-color .16s;
}
.case-explore:hover { background: var(--fond-3); }
.case-boite {
    flex: 0 0 auto;
    width: 22px; height: 22px;
    border: 2px solid var(--bordure);
    border-radius: 8px;
    background: transparent;
    position: relative;
    transition: background .16s, border-color .16s;
}
/* La coche est dessinée plutôt qu'écrite : un caractère ✓ se centre mal
   d'une police à l'autre, ces deux traits tombent toujours juste. */
.case-boite::after {
    content: '';
    position: absolute; left: 6px; top: 2px;
    width: 5px; height: 10px;
    border: solid #fff; border-width: 0 2.5px 2.5px 0;
    transform: rotate(45deg) scale(0);
    transition: transform .16s ease-out;
}
.case-explore.cochee { background: rgba(31, 111, 92, .17); border-color: var(--primary); }
.case-explore.cochee .case-boite { background: var(--primary); border-color: var(--primary); }
.case-explore.cochee .case-boite::after { transform: rotate(45deg) scale(1); }
.case-explore.cochee .case-texte { color: var(--primary); font-weight: 600; }
.case-explore:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Bascule plan / vue réelle. Deux pastilles empilées : la carte est déjà
   chargée en information, un sélecteur déroulant y serait une gêne. */
.gex-fond { display: flex; flex-direction: column; }
.gex-fond-btn {
    width: 34px; height: 34px;
    display: flex !important; align-items: center; justify-content: center;
    font-size: 17px; line-height: 1; text-decoration: none;
    cursor: pointer;
}
.gex-fond-btn.actif {
    background: var(--primary) !important;
    box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .22);
}
/* Hors ligne, la vue réelle n'existe pas : le bouton le dit avant d'être
   pressé, plutôt que d'échouer une fois cliqué. */
.gex-fond-btn.indisponible {
    opacity: .38;
    cursor: not-allowed;
    filter: grayscale(1);
}

/* L'échelle suit le zoom : de loin les marqueurs doivent tenir sans se
   marcher dessus, de près la place est libre et un repère plus grand se
   vise mieux du pouce. carte.js pose la variable à chaque changement de
   zoom. L'agrandissement part de la pointe du marqueur — c'est elle qui
   désigne le lieu, elle ne doit pas bouger d'un pixel. */
.leaflet-container { --echelle-marqueur: 1; }

/* La carte agrandie de 41 % pour tourner sans laisser de coins vides
   n'a plus lieu d'etre : elle est verrouillee au nord. Ce debordement
   faisait charger a Leaflet un tiers de tuiles de plus que necessaire —
   sur un pack de neuf cents lieux et une connexion de campagne, ce n'est
   pas rien. */
.leaflet-container.sans-animation { transition: none; }

/* La carte est verrouillée au nord : plus rien n'a besoin d'être
   redressé. Les règles de compensation qui vivaient ici ont disparu
   avec la rotation elle-même. */

.marqueur-poi {
    position: relative;
    width: 34px; height: 34px;
    border-radius: 50% 50% 50% 6px;
    /* Trois transformations composées, dans cet ordre : on annule la
       rotation de la carte pour que la goutte reste d'aplomb, on applique
       l'échelle du zoom, puis la rotation de -45° qui donne sa forme au
       marqueur. */
    transform: scale(var(--echelle-marqueur))
               rotate(-45deg);
    transform-origin: 20% 80%;
    display: flex; align-items: center; justify-content: center;
    background: var(--primaire);
    border: 2px solid rgba(255, 255, 255, .82);
    box-shadow: 0 3px 10px rgba(0, 0, 0, .5);
    transition: transform .18s ease-out;
}
.marqueur-poi span { transform: rotate(45deg); font-size: 15px; line-height: 1; }

/* Noms des lieux. Le conteneur ne reçoit aucun clic : il couvre toute la
   carte, il intercepterait tout. Les étiquettes elles-mêmes non plus —
   on vise le marqueur, pas son étiquette. */
.couche-etiquettes {
    position: absolute; inset: 0;
    pointer-events: none;
    z-index: 620;
}
.etiquette-lieu {
    position: absolute; top: 0; left: 0;
    /* Masquée mais mesurable : c'est sa largeur réelle qui décide des
       chevauchements, or `display: none` la rendrait nulle et toutes les
       étiquettes se croiraient placeables au même endroit. */
    visibility: hidden;
    max-width: 148px;
    padding: 2px 7px;
    border-radius: 6px;
    background: rgba(14, 26, 23, .8);
    color: #f2f5f3;
    font-size: 11.5px; font-weight: 600; line-height: 1.35;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    /* Le contour sombre garde le texte lisible au-dessus d'une photo
       aérienne claire, où un simple fond translucide ne suffit pas. */
    text-shadow: 0 1px 2px rgba(0, 0, 0, .9);
    pointer-events: none;
}
/* Révélée seulement une fois placée : sans cela on verrait toutes les
   étiquettes empilées en haut à gauche le temps du calcul. */
.etiquette-lieu.posee { visibility: visible; }

/* Marqueur photographique : la façade du lieu à la place de l'émoji.

   Classe autonome, et non un modificateur de `.marqueur-poi` : cette
   dernière porte un rotate(-45deg) et ne masque pas son débordement.
   Hériter d'elle signifierait qu'une feuille de style incomplète — cache
   périmé, fichier tronqué — afficherait la photo à sa taille réelle et de
   travers, couvrant la carte. Ici il n'y a rien à défaire. */
.marqueur-photo {
    /* Centree sur la pointe, et non calee en haut a gauche de la boite
       que Leaflet reserve. Sans cela, une vignette dont la taille change
       — ce qui arrive a chaque zoom — se decalerait du point qu'elle
       designe, d'autant plus qu'elle est grande. Ici la pointe reste
       fixe et la vignette grandit autour d'elle. */
    position: absolute;
    left: 50%;
    bottom: 0;
    /* Un liseré clair et une ombre portée : sans eux, une photo sombre
       se fond dans une carte chargée et cesse d'être repérable. */
    /* La taille est pilotée par carte.js, qui la réduit quand deux
       marqueurs se chevaucheraient. */
    width: var(--taille-photo, 46px);
    height: var(--taille-photo, 46px);
    /* Case à liseré arrondi plutôt que disque : un cadrage rectangulaire
       conserve les bords d'une façade, que le cercle rogne. */
    border-radius: 14px;
    overflow: hidden;
    /* Fond neutre et non vert : il ne se voit que le temps du chargement
       de l'image, ou si elle manque. Une teinte vive a cet endroit se
       lisait comme une couleur du marqueur alors qu'elle ne disait rien. */
    background: #1a1a1a;
    border: 3px solid rgba(255, 255, 255, .92);
    box-shadow: 0 2px 10px rgba(0, 0, 0, .55), 0 0 0 1px rgba(0, 0, 0, .35);
    /* La photo reste DROITE quel que soit l'angle de la carte : on annule
       la rotation d'ensemble. Un visage ou une façade penchée ne se
       reconnaît pas, et c'est précisément ce qu'on demande à ce marqueur.
       Seule l'échelle du zoom s'applique en plus. */
    /* translateX recentre, la rotation redresse la photo malgre l'angle
       de la carte. L'echelle du zoom n'intervient pas ici : elle est
       deja dans --taille-photo, que calcule carte.js. */
    transform: translateX(-50%);
    transform-origin: 50% 100%;
    /* Le rayon accompagne la taille : sans lui, le passage du cadre
       arrondi au disque claquerait pendant que la vignette, elle, se
       reduit en douceur - on lirait deux marqueurs differents la ou il
       n'y en a qu'un qui change de forme. */
    transition: width .18s ease-out, height .18s ease-out,
                border-radius .18s ease-out;
}
/* LA PHOTO REMPLIT LE CADRE, SANS RESERVE.

   Elle portait son propre arrondi, plus petit que celui du cadre : le
   fond du marqueur reapparaissait donc en quatre virgules aux angles.
   C'est le conteneur qui decoupe, avec son overflow:hidden ; l'image n'a
   qu'a s'etendre jusqu'au bord. */
.marqueur-photo img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 0;
    /* Réduite à trente-quelques pixels, une photographie perd son punch :
       un léger gain de contraste et de saturation lui rend sa lisibilité
       sans la dénaturer. */
    filter: contrast(1.08) saturate(1.1);
}
/* La pointe sous le disque : le marqueur doit désigner un point précis,
   pas une zone. Elle tourne avec le disque, donc reste sous lui. */
.marqueur-photo::after {
    content: '';
    position: absolute;
    left: 50%; bottom: -8px;
    transform: translateX(-50%);
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 8px solid rgba(255, 255, 255, .82);
}
/* Serré contre ses voisins, le marqueur se réduit : mieux vaut un repère
   petit mais entier qu'une pile illisible. En dessous d'un certain seuil
   le liseré mangerait l'image, on l'affine donc aussi. */
.marqueur-photo.serre { border-width: 2px; }
.marqueur-photo.serre img { border-radius: 0; }

/* Repli sur l'icône : la vignette rend les armes.

   Réduire indéfiniment ne mène nulle part. Sous une quarantaine de
   pixels, une façade n'est plus une façade : c'est une tache de couleur
   qui coûte le prix d'une image et ne dit plus rien. Empilée vingt fois
   sur un même pâté de maisons, elle cache en plus le fond de carte et
   ses voisines.

   Le marqueur redevient donc ce qu'il était avant d'avoir une photo :
   une pastille ronde à emoji. Elle est plus petite, elle se lit en tas,
   et elle rend la seule information qui survive à cette taille — la
   catégorie du lieu. La façade revient dès qu'on zoome.

   Les deux coins cliquables disparaissent avec elle : à trente pixels,
   ils n'offrent plus de cible atteignable au doigt et déborderaient sur
   le marqueur voisin. Marquer un lieu se fait alors depuis sa fiche, ou
   après un zoom.

   La forme change, mais pas la pointe ni les états : un lieu prévu reste
   reconnaissable à son liseré, quelle que soit sa taille. */
.marqueur-photo .symbole-repli { display: none; }
.marqueur-photo.repli-icone {
    border-radius: 50%;
    border-width: 2px;
    background: var(--primaire);
}
.marqueur-photo.repli-icone img,
.marqueur-photo.repli-icone .marque-fait,
.marqueur-photo.repli-icone .marque-projet { display: none; }
.marqueur-photo.repli-icone .symbole-repli {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%; height: 100%;
    /* Proportionnel à la pastille : le symbole occupe toujours la même
       part du disque, quel que soit le réglage de --taille-photo. */
    font-size: calc(var(--taille-photo, 30px) * .54);
    line-height: 1;
}
.marqueur-photo.etape { border-color: var(--accent); }
.marqueur-photo.etape::after { border-top-color: var(--accent); }
.marqueur-photo.proche { animation: pulsation 1.5s ease-in-out infinite; }
.marqueur-photo.devant {
    border-color: #fff;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .6), 0 0 0 3px rgba(255, 255, 255, .3);
}
.leaflet-container.sans-animation .marqueur-photo { transition: none; animation: none; }


/* Marqueur ramené au premier plan parce que le doigt ou la souris en est
   le plus proche : un liseré suffit à dire lequel répondra au clic. */
.marqueur-poi.devant {
    border-color: #fff;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .6), 0 0 0 3px rgba(255, 255, 255, .3);
}

/* En mode économie d'énergie, aucune transition : chaque animation
   maintenue coûte des réveils de rendu. */
.leaflet-container.sans-animation .marqueur-poi { transition: none; }
.marqueur-poi.verrouille { background: #4a5652; opacity: .78; }
.marqueur-poi.visite     { background: var(--succes); }
.marqueur-poi.etape      { background: var(--accent); }
.marqueur-poi.proche     { animation: pulsation 1.5s ease-in-out infinite; }

@keyframes pulsation {
    0%, 100% { box-shadow: 0 3px 10px rgba(0,0,0,.5), 0 0 0 0 rgba(224, 164, 88, .55); }
    50%      { box-shadow: 0 3px 10px rgba(0,0,0,.5), 0 0 0 13px rgba(224, 164, 88, 0); }
}

.marqueur-moi {
    width: 18px; height: 18px; border-radius: 50%;
    background: #3fa9f5;
    border: 3px solid #fff;
    box-shadow: 0 0 0 6px rgba(63, 169, 245, .22);
    /* La flèche se place par rapport au point, et déborde de lui. */
    position: relative;
}

/* La flèche de marche.
   Rouge, et elle seule : c'est la seule chose rouge de la carte, donc
   la seule qu'on trouve sans la chercher. Elle pivote autour du point,
   qui reste le repère — le cap tourne, pas la position.

   Elle n'apparaît que si le GPS annonce une direction fiable : à
   l'arrêt, une flèche qui pointe au hasard serait crue. */
.fleche-cap {
    position: absolute;
    left: 50%; top: 50%;
    width: 0; height: 0;
    /* L'origine est le centre du point : la flèche décrit un cercle
       autour de lui, elle ne pivote pas sur elle-même. */
    transform-origin: 0 0;
    pointer-events: none;
}
.fleche-cap::before {
    content: '';
    position: absolute;
    left: -6px;
    /* Posée au-dessus du point : à 0 degré, elle indique le nord, ce qui
       est juste puisque la carte y est verrouillée. */
    top: -22px;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-bottom: 11px solid #e33a3a;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .55));
}

/* En économie d'énergie, la flèche ne s'anime pas : elle saute d'une
   position à l'autre, ce qui coûte moins qu'une transition permanente. */
.leaflet-container:not(.sans-animation) .fleche-cap {
    transition: transform .25s ease-out;
}

/* --- Cartes de contenu ----------------------------------------------- */

.carte-item {
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    overflow: hidden;
    margin-bottom: 14px;
    transition: border-color .15s, transform .15s;
}
.carte-item:hover { border-color: var(--primaire-clair); }
.carte-item .visuel {
    height: 132px;
    background: linear-gradient(135deg, var(--fond-3), var(--primaire));
    background-size: cover;
    background-position: center;
    position: relative;
}
.carte-item .visuel .etiquette {
    position: absolute; top: 10px; left: 10px;
    background: rgba(14, 26, 23, .82);
    border-radius: 999px;
    padding: 4px 11px;
    font-size: .7rem;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.carte-item .visuel .prix {
    position: absolute; bottom: 10px; right: 10px;
    background: var(--accent);
    color: #2a1c07;
    font-weight: 700;
    border-radius: 999px;
    padding: 5px 13px;
    font-size: .84rem;
}
.carte-item .corps { padding: 13px 15px 15px; }
.carte-item .corps h3 { margin-bottom: 3px; }
.carte-item .corps .sous { color: var(--texte-doux); font-size: .85rem; margin-bottom: 9px; }

.meta {
    display: flex; flex-wrap: wrap; gap: 6px 14px;
    color: var(--texte-doux); font-size: .78rem;
}
.meta span { display: inline-flex; align-items: center; gap: 4px; }

.grille {
    display: grid;
    /* « auto-fit » et non « auto-fill » : avec trois packs gratuits dans
       un conteneur qui en accepterait cinq, « auto-fill » cree cinq
       pistes, garde les deux dernieres vides, et laisse les trois cartes
       serrees a gauche devant un vide. « auto-fit » replie les pistes
       inutilisees et les trois cartes occupent toute la largeur.
       Quand il y a de quoi remplir — la boutique — les deux se
       comportent identiquement. */
    grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
    gap: 14px;
    /* Les cellules d'une même rangée s'alignent sur la plus haute. Sans
       cela, un titre qui passe à deux lignes décale sa carte et laisse
       un décroché sous ses voisines. */
    align-items: stretch;
}

/* Enveloppe d'un pack dans la boutique : la carte et son lien « Fiche
   détaillée » comptent pour UNE cellule. Émis côte à côte, ils en
   occupaient deux, et une cellule sur deux ne contenait qu'un lien
   flottant dans le vide. */
.vignette {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
/* La carte occupe toute la hauteur disponible ; le lien reste collé en
   bas, aligné d'une vignette à l'autre. */
.vignette .carte-item { flex: 1; margin-bottom: 0; }
.vignette .aide { margin: 8px 0 0; }

/* La marge basse de la carte fait double emploi avec l'espacement de la
   grille : elle appartient aux listes verticales, pas aux grilles. */
.grille > .carte-item { margin-bottom: 0; }

/* =====================================================================
   « Comment ça marche »
   =====================================================================

   POURQUOI CETTE SECTION A SA PROPRE MISE EN PAGE

   Elle partageait « .grille » et « .carte-item » avec les vignettes de
   pack qui la precedent. Or les deux ne font pas le meme travail : une
   vignette de pack est un objet qu'on survole et sur lequel on clique,
   quatre idees a lire demandent de l'air. Avec 268 px de largeur
   minimale, les quatre tuiles tombaient a trois par rangee plus une
   orpheline, chacune serree dans 13 px de marge interne, texte a 0,82rem
   colle a son titre.

   Ici : deux par deux sur un ecran large, l'une sous l'autre sur un
   telephone, marges doublees, interligne aere. Rien de partage avec les
   packs, donc rien qui puisse les abimer en retour.

   LE FOND

   Une ruelle de nuit, tres sombre et sans sujet net au centre — c'est
   un fond derriere du texte, pas une image a regarder. Les fiches sont
   translucides et floutees par-dessus : l'image transparait sans jamais
   passer devant les mots. Une couche de couleur est posee en plus du
   fichier, ce qui garantit le contraste meme si l'image ne se charge
   pas.

   WebP et non AVIF : l'AVIF compresse mieux, mais l'application tourne
   aussi dans une WebView Android dont on ne choisit pas la version. Le
   WebP est lu partout depuis 2020, et sur une image aussi sombre et
   aussi peu detaillee l'ecart de poids ne justifie pas le risque.
   ===================================================================== */

.bloc-methode {
    position: relative;
    margin: 40px 0 8px;
    /* 64 px en haut : de quoi laisser paraitre une bande de ruelle
       au-dessus du titre. Sans cela l'image ne se devinait qu'entre les
       fiches, ou elle ne ressemblait plus a rien. */
    padding: 64px 22px 34px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    overflow: hidden;
    isolation: isolate;

    /* Le degrade est pose AVANT l'image dans la pile, donc au-dessus
       d'elle : c'est lui qui garantit la lisibilite.

       Il est LEGER EN HAUT et lourd en bas, et non l'inverse comme au
       premier essai. En haut il n'y a que le titre, sur une ligne : la
       ruelle peut s'y voir. En bas les fiches occupent presque toute la
       largeur, et l'image n'y servirait qu'a salir les bords. */
    background-color: var(--fond-2);
    background-image:
        linear-gradient(180deg,
            rgba(14, 26, 23, .42) 0%,
            rgba(14, 26, 23, .70) 30%,
            rgba(14, 26, 23, .90) 62%,
            rgba(14, 26, 23, .95) 100%),
        url("../img/fond-methode-desktop.webp");
    background-size: cover, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
}

.bloc-methode > h2 {
    margin: 0 0 30px;
    letter-spacing: .01em;
    /* Le titre passe sur la partie claire de l'image : une ombre portee
       le decolle du fond sans l'assombrir. */
    text-shadow: 0 2px 14px rgba(6, 14, 11, .85);
}

.grille-methode {
    display: grid;
    /* QUATRE ENCARTS, DONC 1, 2 OU 4 COLONNES — JAMAIS 3.
       ------------------------------------------------------------------
       Une piste elastique (« auto-fit » et une largeur minimale) donne
       trois colonnes des que la place le permet, et laisse le quatrieme
       encart seul sur sa rangee. C'est exactement ce qu'on cherchait a
       corriger. Avec quatre elements, seuls 1, 2 et 4 remplissent leurs
       rangees : on les nomme donc, plutot que de les esperer. */
    grid-template-columns: 1fr;
    gap: 18px;
    align-items: stretch;
}

/* Deux de front des que deux colonnes de 340 px tiennent. */
@media (min-width: 760px) {
    .grille-methode { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Quatre de front sur un large ecran. A 1500 px de conteneur cela fait
   350 px par encart, soit environ 45 signes par ligne — la largeur de
   lecture confortable. En deux colonnes, la meme place donnerait des
   lignes de 85 signes, ou l'oeil se perd en revenant a la gauche. */
@media (min-width: 1240px) {
    .grille-methode { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.fiche-methode {
    padding: 22px 24px 24px;
    border: 1px solid rgba(35, 69, 60, .9);
    border-radius: var(--rayon-s);
    background: rgba(20, 39, 34, .74);
    backdrop-filter: blur(9px);
    -webkit-backdrop-filter: blur(9px);
    transition: border-color .16s, background .16s;
}
.fiche-methode:hover {
    border-color: var(--primaire-clair);
    background: rgba(20, 39, 34, .86);
}

.fiche-methode h3 {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin: 0 0 11px;
    font-size: 1.06rem;
    line-height: 1.3;
    color: var(--texte);
}
.fiche-methode h3 .ico {
    font-size: 1.2rem;
    line-height: 1;
    flex: 0 0 auto;
}

.fiche-methode p {
    margin: 0;
    color: var(--texte-doux);
    font-size: .9rem;
    /* 1,7 plutot que 1,5 : ce sont trois a quatre lignes qu'on lit d'une
       traite, pas une legende qu'on parcourt. */
    line-height: 1.7;
}

/* Ecrans etroits : le fond passe en cadrage vertical, et la section perd
   ses marges laterales — sur 390 px, 22 px de chaque cote pris au bloc
   plus 24 px pris a la fiche laissaient 44 px de texte en moins. */
@media (max-width: 620px) {
    .bloc-methode {
        margin: 30px -14px 4px;
        padding: 52px 14px 26px;
        border-left: none;
        border-right: none;
        border-radius: 0;
        background-image:
            linear-gradient(180deg,
                rgba(14, 26, 23, .40) 0%,
                rgba(14, 26, 23, .72) 24%,
                rgba(14, 26, 23, .92) 52%,
                rgba(14, 26, 23, .96) 100%),
            url("../img/fond-methode-mobile.webp");
    }
    .bloc-methode > h2 { margin-bottom: 18px; }
    .grille-methode { gap: 14px; }
    .fiche-methode { padding: 18px 17px 19px; }
    .fiche-methode h3 { font-size: 1rem; margin-bottom: 9px; }
}

/* Le flou d'arriere-plan coute cher a dessiner. Sur une machine qui
   demande moins d'animation, on le retire et l'on compense par une
   surface plus opaque. */
@media (prefers-reduced-motion: reduce) {
    .fiche-methode {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(20, 39, 34, .93);
    }
}

/* =====================================================================
   Pages legales et pied de mentions
   =====================================================================

   Un document juridique se lit d'un bout a l'autre, contrairement au
   reste de l'application qui se parcourt. Il garde donc une colonne
   etroite meme sur un grand ecran — 68 caracteres environ, la largeur ou
   l'oeil retrouve sans effort le debut de la ligne suivante. C'est
   exactement l'inverse du choix fait pour l'accueil, et pour la meme
   raison : la forme suit l'usage. */

.colonne-lecture {
    /* MESURE, PAS INTUITION.
       « 68ch » semblait dire « 68 caracteres » : l'unite ch vaut la
       largeur du glyphe « 0 », plus large que la moyenne dans une police
       proportionnelle. Mesure faite a 1280 px : 587 px de colonne, soit
       92 signes par ligne — bien au-dela des 55 a 75 ou l'oeil retrouve
       sans effort le debut de la ligne suivante.
       On fixe donc la largeur en pixels, calee sur la largeur moyenne
       reellement mesuree (6,7 px par signe a cette taille). */
    max-width: 500px;
    margin: 0 auto;
    padding-bottom: 10px;
    font-size: 1.03rem;
}
.colonne-lecture h1 { margin-bottom: 6px; }
.colonne-lecture h2 {
    margin: 30px 0 10px;
    padding-top: 14px;
    border-top: 1px solid var(--bordure);
    font-size: 1.18rem;
}
.colonne-lecture h2:first-of-type { border-top: none; padding-top: 0; }
.colonne-lecture h3 { margin: 20px 0 6px; font-size: 1rem; }
.colonne-lecture p  { line-height: 1.72; margin: 0 0 14px; }
.colonne-lecture ul { margin: 0 0 16px; padding-left: 22px; line-height: 1.72; }
.colonne-lecture li { margin-bottom: 7px; }
.colonne-lecture .chapeau {
    font-size: 1.02rem;
    color: var(--texte);
    border-left: 3px solid var(--accent);
    padding-left: 15px;
    margin-bottom: 24px;
}
/* Un tableau de durees ou de sous-traitants doit pouvoir defiler seul :
   sur un telephone, ce sont deux ou trois colonnes qui ne se replient
   pas, et c'est la page entiere qui partirait de cote sans cela. */
.colonne-lecture .tableau { width: 100%; margin-bottom: 18px; }
.colonne-lecture table { display: block; overflow-x: auto; }

/* La liste de renvois en fin de document : de la navigation, pas de la
   prose. Ses liens ont donc droit a une surface, contrairement a ceux qui
   vivent au milieu d'une phrase — les rembourrer ferait se chevaucher les
   lignes du paragraphe. */
@media (pointer: coarse) {
    .liens-documents li { margin-bottom: 0; }
    .liens-documents a {
        display: inline-block;
        padding: 12px 4px;
        margin: -6px 0;
    }
}

/* La case d'acceptation : la seule obligatoire du formulaire, donc la
   seule qui se detache. L'asterisque suit la convention du reste du
   formulaire, ou « * » marque un champ requis. */
.case-conditions {
    margin-top: 4px;
    padding: 12px 13px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    background: var(--fond-2);
    color: var(--texte);
}
.case-conditions a { color: var(--accent); text-decoration: underline; }
.case-conditions .obligatoire { color: var(--accent); font-weight: 700; }
.case-conditions:has(input:invalid) { border-color: var(--accent); }

/* Le pied de mentions, present sur toutes les pages. Discret : il doit
   se trouver quand on le cherche, pas se voir quand on ne le cherche
   pas. */
.pied-legal {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 4px 10px;
    padding: 22px 16px calc(var(--barre-h) + 18px);
    font-size: .78rem;
    color: var(--texte-doux);
}
.pied-legal a { color: var(--texte-doux); text-decoration: none; }
.pied-legal a:hover { color: var(--accent); text-decoration: underline; }

@media (pointer: coarse) {
    /* Trois liens de texte cote a cote : sans surface propre, ils sont
       intouchables au pouce. */
    /* Mesure : a 11 px de rembourrage le lien faisait 38 px de haut,
       sous le seuil du pouce. */
    .pied-legal a { display: inline-block; padding: 14px 8px; margin: -10px 0; }
}

/* La carte n'a pas de pied : elle occupe tout l'ecran, et un pied
   flottant par-dessus masquerait des lieux. Les mentions y restent
   joignables par le profil. */
.contenu.pleine-hauteur ~ .pied-legal { display: none; }

/* --- Boutons --------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: var(--primaire);
    color: #fff;
    border: none;
    /* Pleinement rond : un bouton est un galet qu'on presse. La forme
       distingue d'un coup d'oeil ce qui agit (rond) de ce qui se lit
       (coins francs), sans rien avoir a apprendre. */
    border-radius: 999px;
    padding: 11px 21px;
    font-size: .94rem;
    font-family: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s, opacity .15s;
}
.btn:hover  { background: var(--primaire-clair); color: #fff; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn.accent { background: var(--accent); color: #2a1c07; }
.btn.accent:hover { background: var(--accent-clair); }
.btn.fantome {
    background: transparent;
    border: 1px solid var(--bordure);
    color: var(--texte);
}
.btn.fantome:hover { border-color: var(--primaire-clair); background: var(--fond-3); }
.btn.danger { background: var(--danger); }
.btn.bloc   { width: 100%; }
.btn.petit  { padding: 7px 13px; font-size: .82rem; }

/* --- Formulaires ----------------------------------------------------- */

.champ { margin-bottom: 15px; }
.champ label {
    display: block;
    font-size: .8rem;
    color: var(--texte-doux);
    margin-bottom: 6px;
    letter-spacing: .02em;
}
.champ input, .champ select, .champ textarea {
    width: 100%;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    color: var(--texte);
    padding: 11px 13px;
    font-size: 1rem;
    font-family: inherit;
}
.champ input:focus, .champ select:focus, .champ textarea:focus {
    outline: none;
    border-color: var(--primaire-clair);
}
.champ textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
.champ .aide { font-size: .76rem; color: var(--texte-doux); margin-top: 5px; }
/* Une ligne de champs — recherche, filtres, prenom/nom.
   ---------------------------------------------------------------------
   Elle ne tenait pas sur un telephone : trois champs dans 358 px de large
   donnaient 111 px chacun, et les listes deroulantes affichaient
   « Tous les t » puis « Tous les r ». Un filtre dont on ne lit pas le
   libelle ne se choisit pas.

   Plutot qu'une regle a part pour les petits ecrans, on donne a chaque
   champ une largeur en dessous de laquelle il refuse de descendre : il
   passe alors a la ligne. Un grand ecran garde sa ligne unique, un
   telephone en fait deux ou trois, et rien n'est a regler par palier. */
.champ-ligne { display: flex; flex-wrap: wrap; gap: 12px; }
.champ-ligne > * { flex: 1 1 170px; }

/* --- Panneau lieu (feuille glissante) -------------------------------- */

.feuille {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    max-height: 86vh;
    background: var(--fond-2);
    border-top-left-radius: 20px;
    border-top-right-radius: 20px;
    border-top: 1px solid var(--bordure);
    box-shadow: var(--ombre);
    transform: translateY(102%);
    transition: transform .28s cubic-bezier(.22, .8, .3, 1);
    z-index: 1000;
    display: flex;
    flex-direction: column;
}
.feuille.ouverte { transform: translateY(0); }
.feuille .poignee {
    width: 42px; height: 4px;
    background: var(--bordure);
    border-radius: 2px;
    margin: 10px auto 4px;
    flex: 0 0 auto;
}
.feuille .feuille-corps {
    overflow-y: auto;
    padding: 8px 18px calc(24px + env(safe-area-inset-bottom));
    -webkit-overflow-scrolling: touch;
}

.galerie { display: flex; gap: 9px; overflow-x: auto; padding: 4px 0 10px; }
/* La photographie du lieu, montrée en clair sur la dernière page. Le
   crédit se lit sous l'image : une photo sous CC BY-SA sans attribution
   n'est pas une photo mal légendée, c'est une infraction. */
.photo-lieu { margin: 0; flex: 0 0 auto; display: flex; flex-direction: column; gap: 4px; }
.photo-lieu figcaption {
    font-size: 10.5px;
    line-height: 1.3;
    color: var(--texte-doux);
    max-width: 220px;
}
.galerie img, .galerie video {
    height: 148px;
    border-radius: var(--rayon-s);
    border: 1px solid var(--bordure);
    flex: 0 0 auto;
    cursor: pointer;
    object-fit: cover;
}

.fiche-tech {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 6px 14px;
    font-size: .86rem;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 13px 15px;
    margin-bottom: 15px;
}
.fiche-tech dt { color: var(--texte-doux); }
.fiche-tech dd { margin: 0; }

.encart {
    background: var(--fond-3);
    border-left: 3px solid var(--accent);
    border-radius: 0 var(--rayon-s) var(--rayon-s) 0;
    padding: 12px 15px;
    margin: 0 0 15px;
    font-size: .9rem;
}
.encart strong { color: var(--accent); }

/* --- Etats / bandeaux ------------------------------------------------ */

.bandeau {
    border-radius: var(--rayon-s);
    padding: 11px 15px;
    margin-bottom: 15px;
    font-size: .88rem;
    border: 1px solid;
}
.bandeau.info    { background: rgba(31, 111, 92, .16);  border-color: var(--primaire);  }
.bandeau.alerte  { background: rgba(224, 164, 88, .14); border-color: var(--accent);    }
.bandeau.erreur  { background: rgba(217, 83, 79, .14);  border-color: var(--danger);    }
.bandeau.succes  { background: rgba(76, 175, 125, .14); border-color: var(--succes);    }

.pastille {
    display: inline-block;
    background: var(--fond-3);
    border: 1px solid var(--bordure);
    border-radius: 999px;
    padding: 3px 11px;
    font-size: .74rem;
    color: var(--texte-doux);
}
.pastille.actif { background: var(--primaire); border-color: var(--primaire); color: #fff; }

.hors-ligne-actif {
    position: fixed;
    top: var(--entete-h); left: 0; right: 0;
    background: var(--accent);
    color: #2a1c07;
    text-align: center;
    font-size: .8rem;
    font-weight: 600;
    padding: 5px 14px;
    border-radius: 0 0 16px 16px;
    z-index: 940;
}

/* --- Progression ----------------------------------------------------- */

.progression {
    height: 8px;
    background: var(--fond);
    border-radius: 999px;
    overflow: hidden;
    border: 1px solid var(--bordure);
}
.progression > div {
    height: 100%;
    background: linear-gradient(90deg, var(--primaire), var(--primaire-clair));
    width: 0;
    transition: width .25s;
}

/* --- Notifications --------------------------------------------------- */

#notifs {
    position: fixed;
    left: 50%;
    bottom: calc(var(--barre-h) + 16px);
    transform: translateX(-50%);
    z-index: 1200;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: min(92vw, 430px);
    pointer-events: none;
}
.notif {
    background: var(--fond-3);
    border: 1px solid var(--bordure);
    border-left: 3px solid var(--primaire-clair);
    border-radius: var(--rayon-s);
    padding: 11px 15px;
    font-size: .88rem;
    box-shadow: var(--ombre);
    animation: monte .25s ease;
}
.notif.erreur { border-left-color: var(--danger); }
.notif.succes { border-left-color: var(--succes); }
.notif.accent { border-left-color: var(--accent); }
@keyframes monte { from { opacity: 0; transform: translateY(12px); } }

/* --- Jeu ------------------------------------------------------------- */

.chrono {
    font-variant-numeric: tabular-nums;
    font-size: 1.28rem;
    font-weight: 700;
    letter-spacing: .04em;
}
.chrono.urgent { color: var(--danger); }

.etape-liste { list-style: none; padding: 0; margin: 0; }
.etape-liste li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 0;
    border-bottom: 1px solid var(--bordure);
}
.etape-liste li:last-child { border-bottom: none; }
.etape-liste .num {
    width: 30px; height: 30px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--fond-3);
    border: 1px solid var(--bordure);
    display: flex; align-items: center; justify-content: center;
    font-size: .84rem; font-weight: 700;
}
.etape-liste li.resolue .num { background: var(--succes); border-color: var(--succes); color: #fff; }
.etape-liste li.en_cours .num { background: var(--accent); border-color: var(--accent); color: #2a1c07; }
.etape-liste li.verrouillee { opacity: .48; }
.etape-liste .titre { flex: 1; font-size: .92rem; }

.indice {
    background: var(--fond);
    border: 1px dashed var(--bordure);
    border-radius: var(--rayon-s);
    padding: 11px 14px;
    margin-bottom: 9px;
    font-size: .88rem;
}

.vide {
    text-align: center;
    color: var(--texte-doux);
    padding: 46px 20px;
}
.vide .ico { font-size: 2.6rem; display: block; margin-bottom: 12px; opacity: .6; }

/* --- Tableaux (back-office) ------------------------------------------ */

.tableau { width: 100%; border-collapse: collapse; font-size: .88rem; }
.tableau th, .tableau td {
    text-align: left;
    padding: 10px 12px;
    border-bottom: 1px solid var(--bordure);
}
.tableau th { color: var(--texte-doux); font-weight: 600; font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; }
.tableau tr:hover td { background: var(--fond-2); }
.tableau .actions { white-space: nowrap; text-align: right; }

.enveloppe-tableau { overflow-x: auto; border: 1px solid var(--bordure); border-radius: var(--rayon); }

@media (min-width: 900px) {
    .barre-nav { display: none; }
    :root { --barre-h: 0px; }
    .contenu { padding-bottom: 40px; }
    #carte { bottom: 0; }
    .entete .nav-large { display: flex; gap: 6px; }
    .feuille {
        left: auto; right: 18px; bottom: 18px;
        width: 420px;
        max-height: calc(100vh - var(--entete-h) - 36px);
        border-radius: var(--rayon);
        border: 1px solid var(--bordure);
        transform: translateY(calc(100% + 30px));
    }
    .feuille.ouverte { transform: translateY(0); }
    #notifs { bottom: 18px; left: 18px; transform: none; }
}
@media (max-width: 899px) {
    .entete .nav-large { display: none; }
}

/* =====================================================================
   --- Back-office ---
   Styles reserves aux ecrans d'administration (/admin). Aucune regle
   ci-dessus n'est modifiee : tout est ajoute en fin de feuille.
   ===================================================================== */

.contenu.admin {
    max-width: 1420px;
    padding-bottom: 46px;
}

/* --- Menu d'administration ------------------------------------------- */

.admin-menu {
    flex: 0 0 auto;
    display: flex;
    gap: 4px;
    padding: 8px 14px;
    background: var(--fond-2);
    border-bottom: 1px solid var(--bordure);
    overflow-x: auto;
    white-space: nowrap;
    position: sticky;
    top: var(--entete-h);
    z-index: 880;
}
.admin-menu a {
    color: var(--texte-doux);
    font-size: .86rem;
    padding: 7px 14px;
    border-radius: 999px;
    border: 1px solid transparent;
}
.admin-menu a:hover { color: var(--texte); background: var(--fond-3); }
.admin-menu a.actif {
    color: #fff;
    background: var(--primaire);
    border-color: var(--primaire-clair);
}

/* --- Titre d'ecran et barres d'outils -------------------------------- */

.admin-titre {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}
.admin-titre h1 { margin: 0; flex: 1 1 auto; }
.admin-titre .actions { display: flex; flex-wrap: wrap; gap: 8px; }

.barre-outils {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 12px 14px;
    margin-bottom: 16px;
}
.barre-outils .champ { margin-bottom: 0; min-width: 150px; }
.barre-outils .champ.large { flex: 1 1 240px; }

.actions-ligne { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.actions-ligne form { display: inline; margin: 0; }

/* --- Blocs de formulaire --------------------------------------------- */

.bloc-form {
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 16px 18px;
    margin-bottom: 16px;
}
.bloc-form > h2, .bloc-form > h3 { margin-top: 0; }
.bloc-form .sous-bloc {
    border-top: 1px solid var(--bordure);
    margin-top: 14px;
    padding-top: 14px;
}

.deux-colonnes  { display: grid; grid-template-columns: 1fr; gap: 0 18px; }
.trois-colonnes { display: grid; grid-template-columns: 1fr; gap: 0 18px; }
@media (min-width: 760px) {
    .deux-colonnes  { grid-template-columns: 1fr 1fr; }
    .trois-colonnes { grid-template-columns: 1fr 1fr 1fr; }
}
.pleine-largeur { grid-column: 1 / -1; }

.case {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: .88rem;
    color: var(--texte);
    margin-bottom: 12px;
    cursor: pointer;
}
.case input[type="checkbox"] {
    width: 18px; height: 18px;
    accent-color: var(--primaire-clair);
    flex: 0 0 auto;
}

/* Le compteur de caracteres sous un champ de saisie : discret, aligne a
   droite, sous le champ qu'il commente. */
.compteur { font-size: .74rem; color: var(--texte-doux); text-align: right; margin-top: 4px; }
.compteur.limite { color: var(--danger); }

/* Les blocs de chiffres — pas, lieux vus, packs publies.
   ---------------------------------------------------------------------
   Meme mot, deux objets : celui du dessus compte des caracteres, celui-ci
   affiche une statistique. Ce qui les separe est le parent : une
   statistique vit toujours dans « .compteurs », un compteur de saisie
   jamais. On s'appuie sur cela plutot que de renommer neuf fichiers.

   Ces regles vivaient dans complements.css, que l'administration ne
   charge pas. Consequence mesuree : sur admin/methode.php et
   admin/points_test.php, les grands nombres tombaient a 11,8 px, gris,
   alignes a droite, sans cadre — ils heritaient du compteur de saisie.
   Une statistique qu'on ne lit pas ne sert a rien. */
.compteurs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: 10px;
    margin-bottom: 16px;
}
.compteurs .compteur {
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 13px 12px;
    text-align: center;
    font-size: 1rem;
    color: var(--texte);
    margin-top: 0;
}
.compteurs .valeur {
    font-size: 1.42rem; font-weight: 700; line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.compteurs .unite {
    color: var(--texte-doux); font-size: .72rem;
    text-transform: uppercase; letter-spacing: .05em; margin-top: 4px;
}
.compteurs .compteur.accent .valeur { color: var(--accent); }

/* --- Autocompletion (villes) ----------------------------------------- */

.champ-auto { position: relative; }
.liste-suggestions {
    position: absolute;
    left: 0; right: 0; top: 100%;
    z-index: 1100;
    background: var(--fond-3);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    box-shadow: var(--ombre);
    max-height: 260px;
    overflow-y: auto;
    display: none;
}
.liste-suggestions.ouverte { display: block; }
.liste-suggestions button {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    border-bottom: 1px solid var(--bordure);
    color: var(--texte);
    font-family: inherit;
    font-size: .88rem;
    padding: 9px 13px;
    cursor: pointer;
}
.liste-suggestions button:last-child { border-bottom: none; }
.liste-suggestions button:hover { background: var(--primaire); color: #fff; }
.liste-suggestions button .detail { color: var(--texte-doux); font-size: .78rem; margin-left: 6px; }
.liste-suggestions button:hover .detail { color: rgba(255, 255, 255, .8); }

/* --- Cartes d'edition ------------------------------------------------ */

.carte-edition {
    height: 400px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    overflow: hidden;
    margin-bottom: 12px;
    background: #16241f;
}
.carte-edition.haute { height: 540px; }
.carte-edition.basse { height: 300px; }

.poignee-coin {
    width: 15px; height: 15px;
    border-radius: 3px;
    background: var(--accent);
    border: 2px solid #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, .5);
    cursor: move;
}
.marqueur-num {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: #2a1c07;
    border: 2px solid #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: .8rem; font-weight: 700;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .5);
}
.marqueur-sim {
    width: 20px; height: 20px;
    border-radius: 50%;
    background: var(--accent);
    border: 3px solid #fff;
    box-shadow: 0 0 0 6px rgba(224, 164, 88, .25);
    cursor: grab;
}

/* --- Statistiques du tableau de bord --------------------------------- */

.stat-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
    gap: 12px;
    margin-bottom: 20px;
}
.stat {
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 14px 16px;
}
.stat .valeur {
    font-size: 1.7rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    color: var(--accent);
}
.stat .libelle { font-size: .78rem; color: var(--texte-doux); margin-top: 4px; }
.stat a { font-size: .78rem; }

/* --- Medias d'un lieu ------------------------------------------------ */

.media-liste { display: grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 900px) { .media-liste { grid-template-columns: 1fr 1fr; } }

.media-item {
    display: flex;
    gap: 12px;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 11px 12px;
}
.media-item .vignette {
    width: 108px;
    height: 108px;
    flex: 0 0 auto;
    border-radius: var(--rayon-s);
    border: 1px solid var(--bordure);
    background: var(--fond-3);
    object-fit: cover;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.8rem;
    overflow: hidden;
}
.media-item .champs { flex: 1 1 auto; min-width: 0; }
.media-item .champ { margin-bottom: 8px; }
.media-item .champ input,
.media-item .champ select { padding: 7px 10px; font-size: .86rem; }

/* --- Etats ------------------------------------------------------------ */

.pastille.publie    { background: var(--primaire); border-color: var(--primaire-clair); color: #fff; }
.pastille.brouillon { background: rgba(224, 164, 88, .18); border-color: var(--accent); color: var(--accent-clair); }
.pastille.archive   { background: var(--fond); border-color: var(--bordure); color: var(--texte-doux); }
.pastille.inactif   { background: rgba(217, 83, 79, .16); border-color: var(--danger); color: #f0a6a4; }

/* --- Simulateur ------------------------------------------------------- */

.sim-colonnes { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 1050px) { .sim-colonnes { grid-template-columns: 2fr 1fr; } }

.sim-panneau {
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 14px 16px;
    margin-bottom: 14px;
}
.sim-panneau h3 { margin-bottom: 10px; }

.journal-sim {
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 10px 12px;
    max-height: 260px;
    overflow-y: auto;
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
    line-height: 1.7;
}
.journal-sim div { border-bottom: 1px dashed var(--bordure); padding-bottom: 3px; }
.journal-sim div:last-child { border-bottom: none; }
.journal-sim .heure { color: var(--texte-doux); margin-right: 8px; }
.journal-sim .declenche { color: var(--succes); }

.liste-distances { max-height: 320px; overflow-y: auto; }
.liste-distances .tableau td { padding: 7px 9px; }
.liste-distances tr.dedans td { background: rgba(76, 175, 125, .12); }

input[type="range"] { width: 100%; accent-color: var(--accent); }

.mono { font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; font-size: .85rem; }

/* --- Regie : partenaires, annonces et statistiques -------------------- */

/* Etats d'une annonce (annonces.statut). Le statut « brouillon » reutilise
   la pastille deja definie plus haut pour les packs. */
.pastille.active    { background: var(--primaire); border-color: var(--primaire-clair); color: #fff; }
.pastille.suspendue { background: rgba(224, 164, 88, .18); border-color: var(--accent); color: var(--accent-clair); }
.pastille.terminee  { background: var(--fond); border-color: var(--bordure); color: var(--texte-doux); }

/* Marqueur gris : position heritee du partenaire, jamais enregistree
   dans les champs de l'annonce. */
.marqueur-poi.herite {
    background: #4a5652;
    border-color: rgba(255, 255, 255, .55);
    opacity: .8;
}

/* Histogramme SVG des impressions et des clics : il deborde volontiers
   sur 90 jours, on le fait defiler sans jamais elargir la page. */
.histogramme {
    overflow-x: auto;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    background: var(--fond);
    padding: 12px 10px;
}
.histogramme svg.histo { display: block; max-width: none; }
.histogramme svg.histo rect { shape-rendering: crispEdges; }

.legende-histo {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    font-size: .8rem;
    color: var(--texte-doux);
    margin-bottom: 10px;
}
.legende-histo .puce {
    display: inline-block;
    width: 11px; height: 11px;
    border-radius: 2px;
    margin-right: 6px;
    vertical-align: -1px;
}

/* Bloc « Regie » du tableau de bord. */
.regie-resume { display: flex; flex-wrap: wrap; gap: 10px; align-items: baseline; }


/* --- Page de methode -------------------------------------------------- */

.liste-methode {
    margin: 10px 0 0;
    padding-left: 20px;
    font-size: .9rem;
    line-height: 1.65;
    color: var(--texte-doux);
}
.liste-methode li { margin-bottom: 7px; }
.liste-methode li strong { color: var(--texte); }

.bloc-code {
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 13px 15px;
    overflow-x: auto;
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: .78rem;
    line-height: 1.55;
    color: var(--texte-doux);
    white-space: pre;
}


/* --- Aperçu d'un lieu : photo agrandie et description courte --------

   Il s'ouvre au survol sur un écran pointé, au toucher sur un mobile.
   Il n'est jamais cliquable : c'est un coup d'œil, pas une étape de
   navigation — pour ouvrir la fiche on appuie sur le marqueur. */
.apercu-lieu {
    position: absolute;
    z-index: 1200;
    width: 208px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: 18px;
    box-shadow: 0 12px 30px rgba(0, 0, 0, .45);
    overflow: hidden;
    pointer-events: none;
    opacity: 0;
    transform: translateY(6px);
    transition: opacity .14s ease-out, transform .14s ease-out;
}
.apercu-lieu.visible { opacity: 1; transform: translateY(0); }
.apercu-lieu img {
    width: 100%;
    height: 116px;
    object-fit: cover;
    display: block;
    background: var(--fond-3);
    /* Le cadre entier ignore les clics — il couvre la carte et les
       intercepterait. Son image, elle, les reçoit : c'est le seul
       élément sur lequel on ait quelque chose à faire. */
    pointer-events: auto;
    cursor: zoom-in;
}
.apercu-lieu img:hover { filter: brightness(1.06); }
.apercu-lieu .corps { padding: 9px 11px 11px; }
.apercu-lieu h4 {
    margin: 0 0 3px;
    font-size: 13.5px;
    line-height: 1.25;
    color: var(--texte);
}
.apercu-lieu .sous {
    margin: 0 0 5px;
    font-size: 11px;
    color: var(--accent);
    line-height: 1.3;
}
.apercu-lieu p {
    margin: 0;
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--texte-doux);
    /* Trois lignes au plus : au-delà ce n'est plus un aperçu, et la
       carte disparaît derrière. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.leaflet-container.sans-animation .apercu-lieu { transition: none; }

/* LA JAUGE DE L'APPUI TENU.

   Ouvrir le recit demande cinq secondes de doigt immobile. Sans rien a
   l'ecran, ces cinq secondes ressemblent a une panne : on relache au
   bout de deux, on conclut que rien ne marche. La jauge dit qu'il se
   passe quelque chose, et surtout combien de temps il reste.

   Elle n'est pas decorative : on ne la coupe donc pas en economie
   d'energie, contrairement aux animations d'agrement. */
.leaflet-container.appui-recit::after {
    content: '';
    position: absolute;
    left: 0; top: 0;
    height: 3px;
    width: 0;
    background: var(--accent);
    box-shadow: 0 0 6px rgba(224, 164, 88, .6);
    z-index: 700;
    pointer-events: none;
    animation: appui-recit 5s linear forwards;
}
@keyframes appui-recit { from { width: 0; } to { width: 100%; } }


/* --- Cycle de vie d'un lieu, lu au liseré ---------------------------

       jaune   prévu   « celui-là m'intéresse »
       vert    validé  « c'est décidé, j'y vais »
       gris    fait    et le repère rétrécit

   L'état « fait » l'emporte sur l'intention : une fois sur place, ce
   qu'on avait prévu n'a plus d'importance. Le liseré est épaissi pour
   que la couleur se lise à la taille d'un marqueur — un filet d'un pixel
   ne se distingue pas en marchant. */
.marqueur-poi.prevu,
.marqueur-photo.prevu  { border-color: #e8b33c; }
.marqueur-poi.valide,
.marqueur-photo.valide { border-color: #3fbf7f; }
.marqueur-poi.fait,
.marqueur-photo.fait   { border-color: #7d8a86; }

.marqueur-photo.prevu,
.marqueur-photo.valide { border-width: 3px; }

/* Un lieu fait s'efface sans disparaître : il reste retrouvable, mais
   cesse de disputer la place à ce qui reste à voir. */
.marqueur-photo.fait {
    --taille-photo: 30px;
    border-width: 2px;
    opacity: .72;
}
.marqueur-photo.fait img { border-radius: 0; filter: saturate(.55); }
.marqueur-photo.fait::after { border-top-color: #7d8a86; }

/* Points posés par le visiteur : hôtel, voiture, rendez-vous. Losange
   plutôt que goutte ou case — la forme suffit à dire « ceci est à moi »
   sans qu'on ait à lire quoi que ce soit. */
.marqueur-perso {
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    background: var(--fond-2);
    border: 2px solid var(--accent);
    border-radius: 11px;
    box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
    font-size: 15px; line-height: 1;
    transform: scale(var(--echelle-marqueur));
    transform-origin: 50% 100%;
}
.marqueur-perso.hotel   { border-color: #7ab8e8; }
.marqueur-perso.voiture { border-color: #c88ae0; }

/* Stations de métro et de tramway.

   Un rond, discret, sans emoji ni étiquette. Ce ne sont pas des lieux à
   visiter : elles doivent se voir quand on les cherche et s'oublier le
   reste du temps. Le nom reste accessible par le title du marqueur, donc
   au survol et aux lecteurs d'écran, sans encombrer la carte. */
.marqueur-station {
    width: 11px; height: 11px;
    margin: 2px;
    border-radius: 50%;
    background: var(--fond-2);
    border: 2px solid #7ab8e8;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .55);
    opacity: .8;
}
.marqueur-station.tram    { border-color: #9fd0a8; }
.marqueur-station.choisie {
    /* Le départ retenu : on doit le retrouver d'un coup d'œil au milieu
       des autres, une fois la promenade composée. */
    width: 15px; height: 15px;
    margin: 0;
    border-color: var(--accent);
    background: var(--accent);
    opacity: 1;
    box-shadow: 0 0 0 3px rgba(224, 164, 88, .3);
}

/* Liste de choix d'une station : une grande ville en compte plusieurs
   centaines, elle défile. */
.liste-stations {
    max-height: 46vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 6px;
}
.liste-stations .station {
    display: grid;
    grid-template-columns: 26px 1fr auto;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 10px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    color: var(--texte);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.liste-stations .station:hover,
.liste-stations .station:focus-visible { background: var(--fond-3); }
.liste-stations .station .nom  { font-size: 13.5px; }
.liste-stations .station .meta { font-size: 11px; color: var(--texte-doux); text-align: right; }

/* Ligne pratique de l'aperçu : horaires et tarif, ce qu'on cherche avant
   de se déplacer. */
.apercu-lieu .pratique {
    margin-top: 7px;
    padding-top: 6px;
    border-top: 1px solid var(--bordure);
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 10.5px;
    line-height: 1.35;
    color: var(--texte-doux);
}
.apercu-lieu .pratique span { display: block; }


/* --- Les deux marques d'une vignette --------------------------------

   En haut à droite, la coche de ce qui est FAIT : un constat, gagné sur
   le terrain, qu'on ne peut pas se donner soi-même. Elle n'est donc pas
   cliquable.

   En bas à gauche, la case de ce qu'on VEUT faire : une intention, qui
   se coche et se décoche, et qui alimente le calcul d'itinéraire.

   Les séparer physiquement évite la confusion la plus coûteuse — cocher
   « j'y vais » en croyant dire « j'y suis allé ». Deux coins opposés,
   deux couleurs, deux comportements. */
.marque-fait,
.marque-projet {
    position: absolute;
    /* La taille suit celle de la vignette, sans descendre sous le seuil
       où le doigt ne les distingue plus. */
    width:  clamp(16px, calc(var(--taille-photo, 46px) * .32), 26px);
    height: clamp(16px, calc(var(--taille-photo, 46px) * .32), 26px);
    display: flex; align-items: center; justify-content: center;
    line-height: 1;
    padding: 0;
    /* NI PASTILLE, NI CADRE.

       Les deux marques portaient chacune un disque opaque et un liseré
       blanc. Sur une vignette de quarante-six pixels, cela faisait deux
       jetons qui mangeaient les angles de la photographie — on voyait
       les jetons avant de voir le lieu. Elles se posent désormais à même
       l'image : c'est l'ombre portée qui les détache, comme un sous-titre
       incrusté se détache d'un film sans avoir besoin d'un bandeau. */
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    cursor: pointer;
    /* Le marqueur entier ignore les événements de pointage sur certains
       navigateurs : on les rétablit explicitement pour ces marques. */
    pointer-events: auto;
    transition: color .15s, transform .15s;
}

/* Coche « exploré », toujours présente : pâle tant que le lieu ne l'est
   pas, verte ensuite. Ne l'afficher qu'une fois validée cacherait le
   moyen de la valider — il faudrait le deviner. */
.marque-fait {
    /* A L'INTERIEUR DU CADRE, ET NON DEBORDANTE.

       Le conteneur porte overflow:hidden pour decouper la photographie :
       tout ce qui depasse est coupe net. Les marques debordaient de
       quatre pixels et se faisaient donc rogner par le coin arrondi —
       c'est ce qui leur donnait cet air de jeton mal pose. Elles tiennent
       maintenant entierement dans l'image. */
    top: 1px; right: 2px;
    color: rgba(255, 255, 255, .72);
    font-size: clamp(12px, calc(var(--taille-photo, 46px) * .30), 20px);
    font-weight: 700;
    /* Quatre ombres courtes plutôt qu'un contour : le glyphe reste lisible
       sur un ciel clair comme sur une façade sombre, sans rien ajouter
       autour de lui. */
    text-shadow: 0 0 3px rgba(0, 0, 0, .95), 0 1px 2px rgba(0, 0, 0, .9),
                 1px 0 2px rgba(0, 0, 0, .75), -1px 0 2px rgba(0, 0, 0, .75);
}
.marque-fait:hover { transform: scale(1.18); }
.marque-fait.valide { color: #5fe0a4; }

/* Case « j'y vais » : une pastille pleine, sans carré tracé ni cerceau.
   Sa couleur seule dit l'état, et se lit à la taille où un contour
   deviendrait illisible. */
.marque-projet { bottom: 1px; left: 2px; }
.marque-projet::before {
    content: '';
    width: 52%; height: 52%;
    border-radius: 50%;
    background: rgba(255, 255, 255, .78);
    box-shadow: 0 0 3px rgba(0, 0, 0, .95), 0 1px 2px rgba(0, 0, 0, .8);
    transition: background .15s, transform .15s;
}
.marque-projet:hover::before { transform: scale(1.25); }
/* Prévu : jaune. Validé : vert, et la pastille grossit — la progression
   se lit sans légende, à la couleur et à la taille. */
.marque-projet.prevu::before  { background: #ffc94a; }
.marque-projet.valide::before { background: #5fe0a4; width: 66%; height: 66%; }

/* Un lieu déjà fait n'a plus à être planifié : la case s'efface. */
.marqueur-photo.fait .marque-projet { display: none; }
/* La coche du haut reste, elle : c'est par elle qu'on dévalide. */
.marqueur-photo.fait .marque-fait { opacity: 1; }


/* Compteur des lieux retenus. Caché tant que rien n'est coché : un
   compteur à zéro affiché en permanence est du bruit, et l'on découvre
   la fonction en s'en servant plutôt qu'en lisant une étiquette. */
.compteur-retenus {
    display: none;
    padding: 7px 14px;
    background: var(--accent);
    color: #2a1c07;
    border: none;
    border-radius: 999px;
    font: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 3px 12px rgba(0, 0, 0, .45);
    white-space: nowrap;
}
.compteur-retenus.visible { display: block; }
.compteur-retenus:hover { filter: brightness(1.08); }


/* --- Agrandissement d'une image -------------------------------------

   Une vignette de quarante pixels, ou une image de galerie dans une
   liseuse étroite, ne montrent qu'une indication. Sur place on veut
   parfois comparer un détail sculpté à ce qu'on a devant les yeux : il
   faut alors la voir vraiment, avec sa légende dessous. */
.loupe {
    position: fixed;
    inset: 0;
    z-index: 3000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(6, 12, 10, .93);
    /* -webkit- conservé : la WebView Android d'anciennes versions ne
       connaît pas encore la propriété non préfixée. */
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .18s ease-out, visibility .18s;
}
.loupe.visible { opacity: 1; visibility: visible; }

.loupe figure {
    margin: 0;
    max-width: min(1100px, 100%);
    max-height: 100%;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
/* =====================================================================
   La loupe : barre d'outils, zoom, déplacement
   ===================================================================== */

/* La barre reste au-dessus de l'image, jamais dessus : elle ne doit pas
   cacher le détail qu'on est justement venu regarder. */
.loupe-barre {
    position: absolute;
    top: calc(env(safe-area-inset-top, 0px) + 10px);
    right: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
    z-index: 2;
}

.loupe-btn {
    min-width: 40px; height: 40px;
    padding: 0 10px;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid rgba(255, 255, 255, .22);
    border-radius: 10px;
    background: rgba(0, 0, 0, .55);
    color: #fff;
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    text-decoration: none;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
}
.loupe-btn:hover:not(:disabled) { background: rgba(255, 255, 255, .18); }
.loupe-btn:disabled { opacity: .5; cursor: default; }
.loupe-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.loupe-hd { font-size: 13px; font-weight: 600; letter-spacing: .04em; }

.loupe-facteur {
    min-width: 56px;
    text-align: center;
    color: rgba(255, 255, 255, .8);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

/* Le cadre borne l'image agrandie : sans lui, une image zoomée
   déborderait sur la légende et sur la barre. */
.loupe-cadre {
    overflow: hidden;
    overscroll-behavior: contain;
    display: flex;
    align-items: center;
    justify-content: center;
    max-height: calc(100vh - 180px);
    border-radius: 10px;
    /* Le navigateur ne doit pas s'emparer du pincement ni du glissement :
       c'est nous qui les traitons, et laisser les deux se superposer
       donne une image qui saute. */
    touch-action: none;
}

.loupe img {
    /* L'image occupe la place disponible sans jamais déborder ni se
       déformer : c'est elle qu'on est venu voir. */
    max-width: 100%;
    max-height: calc(100vh - 180px);
    object-fit: contain;
    border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, .6);
    background: var(--fond-2);
    transform-origin: center center;
    /* Pas de transition : elle rendrait le pincement mou et en retard sur
       les doigts. Le zoom doit coller au geste. */
    will-change: transform;
    user-select: none;
    -webkit-user-drag: none;
}

/* Une fois agrandie, l'image se déplace : le curseur doit le dire. */
.loupe.zoomee img { cursor: grab; }
.loupe.zoomee img:active { cursor: grabbing; }

/* Sur une image agrandie, l'interpolation lisse noie les détails d'une
   vignette de 330 px. Les pixels nets valent mieux qu'un flou. */
.loupe.zoomee img { image-rendering: -webkit-optimize-contrast; }

.loupe-credit {
    font-size: 11.5px;
    opacity: .75;
}
.loupe-credit a { color: inherit; text-decoration: underline; }

@media (max-width: 520px) {
    .loupe-barre { right: 8px; gap: 4px; }
    .loupe-btn   { min-width: 36px; height: 36px; padding: 0 7px; font-size: 15px; }
    .loupe-facteur { min-width: 44px; font-size: 11px; }
}
.loupe figcaption {
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
    color: var(--texte-doux);
    font-size: 13px;
    line-height: 1.5;
}
.loupe figcaption strong { color: var(--texte); font-size: 15px; }

/* La croix a rejoint la barre d'outils : elle ne se positionne plus
   toute seule, sinon elle sortirait de la rangee et viendrait se poser
   par-dessus les boutons de zoom. */
.loupe-fermer { border-radius: 50%; }

/* La page ne défile plus derrière l'agrandissement : sur un téléphone,
   un glissement destiné à l'image ferait glisser la carte dessous. */
body.loupe-ouverte { overflow: hidden; }

/* Les images de galerie annoncent qu'elles s'ouvrent. */
img.agrandissable { cursor: zoom-in; }


/* --- Aperçu de l'éditeur de tuiles ----------------------------------

   256 pixels de côté, à l'échelle exacte : ce qu'on règle ici est ce que
   verront les appareils, il ne faut donc aucune mise à l'échelle
   trompeuse entre les deux. */
.apercu-tuile {
    position: relative;
    width: 256px; height: 256px;
    margin: 6px 0 10px;
    border: 1px solid var(--bordure);
    border-radius: 6px;
    overflow: hidden;
    background: #1a2320;
}
.apercu-tuile img { position: absolute; display: block; }
#fond-tuile { top: 0; left: 0; width: 256px; height: 256px; }
#collage-tuile { top: 50%; left: 50%; transform-origin: center; }

/* Repères au tiers : sans eux, centrer une image à l'œil dans un carré
   uni est un exercice de patience. */
.apercu-tuile .grille-tuile {
    position: absolute; inset: 0;
    pointer-events: none;
    background-image:
        linear-gradient(to right,  rgba(255,255,255,.16) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(255,255,255,.16) 1px, transparent 1px);
    background-size: 85.33px 85.33px;
}
.apercu-tuile .grille-tuile::after {
    content: '';
    position: absolute; inset: 0;
    border: 1px dashed rgba(224, 164, 88, .45);
}


/* --- Point d'ancrage : ligne modifiable -----------------------------

   Renommer un hébergement ou corriger ses dates ne doit pas obliger à le
   reposer sur la carte : on se trompe rarement d'endroit, souvent d'un
   jour. Le crayon dit que la ligne s'ouvre, sans occuper la place d'un
   bouton. */
.lien-modifier {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 0;
    background: none;
    border: none;
    color: var(--texte);
    font: inherit;
    font-size: 12.5px;
    text-align: left;
    cursor: pointer;
    border-bottom: 1px dashed var(--bordure);
}
.lien-modifier:hover { color: var(--accent); border-bottom-color: var(--accent); }
.lien-modifier .crayon { opacity: .55; font-size: 11px; }
.lien-modifier:hover .crayon { opacity: 1; }
.alerte-texte { color: #e0a458; }

/* --- Petite boîte de dialogue --------------------------------------

   Utilisée pour poser et pour modifier un point personnel. Elle couvre
   l'écran plutôt que de s'ancrer quelque part : sur un téléphone tenu
   d'une main, une fenêtre flottante finit toujours sous le pouce. */
.dialogue-perso {
    position: fixed;
    inset: 0;
    z-index: 2500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(6, 12, 10, .82);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
}
.dialogue-corps {
    width: 100%;
    max-width: 380px;
    max-height: 88vh;
    overflow-y: auto;
    padding: 22px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: 24px;
    box-shadow: 0 16px 44px rgba(0, 0, 0, .6);
}
.dialogue-corps h3 { margin: 0 0 4px; font-size: 17px; }
.dialogue-corps .btn.bloc { display: block; width: 100%; text-align: left; }
.dialogue-corps .btn.bloc .meta { display: block; margin-top: 2px; font-weight: 400; }


/* --- Première page --------------------------------------------------

   Autonome : ni bandeau ni barre de navigation, qui n'auraient pas de
   sens avant qu'on soit entré. Elle tient sur un écran de téléphone
   sans défilement dans la plupart des cas. */
.page-bienvenue { background: var(--fond); }
.bienvenue {
    max-width: 560px;
    margin: 0 auto;
    padding: 32px 20px calc(28px + env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    gap: 26px;
    min-height: 100vh;
    min-height: 100dvh;
    justify-content: center;
}
.bienvenue-tete { text-align: center; }
.bienvenue-tete h1 {
    margin: 0 0 6px;
    font-size: 30px;
    letter-spacing: -.01em;
}
.bienvenue-tete .accroche { margin: 0; color: var(--accent); font-size: 15px; }

.bienvenue h2 {
    margin: 0 0 12px;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--texte-doux);
    font-weight: 600;
}

/* Pas de drapeaux : une langue n'est pas un pays. Chaque langue est
   écrite dans sa propre graphie — c'est ainsi qu'on la reconnaît sans
   savoir la lire. */
.grille-langues {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: 9px;
}
.carte-langue {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 13px 15px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: 12px;
    color: var(--texte);
    text-decoration: none;
    transition: border-color .15s, background .15s, transform .15s;
}
.carte-langue:hover { border-color: var(--primaire-clair); transform: translateY(-1px); }
.carte-langue.actif { border-color: var(--accent); background: rgba(224, 164, 88, .12); }
.carte-langue .code {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    color: var(--texte-doux);
}
.carte-langue.actif .code { color: var(--accent); }
.carte-langue .nom { font-size: 14.5px; }

.etapes {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
    counter-reset: etape;
}
.etapes li {
    display: grid;
    grid-template-columns: 34px 1fr;
    grid-template-rows: auto auto;
    column-gap: 12px;
    align-items: baseline;
}
.etapes .ico { grid-row: 1 / 3; font-size: 20px; line-height: 1; align-self: center; }
.etapes strong { font-size: 14.5px; }
.etapes span:not(.ico) { font-size: 13px; color: var(--texte-doux); line-height: 1.45; }

.bienvenue-fin { text-align: center; }
.bienvenue-fin .meta { margin: 0 0 12px; }
.btn.grand { padding: 15px 22px; font-size: 16px; }


/* --- Langue d'un pack ------------------------------------------------

   Elle se voit avant l'achat. Découvrir qu'un pack est dans une langue
   qu'on ne lit pas après l'avoir payé serait le pire moment pour
   l'apprendre. L'étoile marque la langue d'origine — celle où le texte
   est complet, les autres pouvant être partielles. */
.langues-pack {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin: 6px 0 10px;
    font-size: 12px;
}
.etiquette.langues {
    position: absolute; top: 10px; right: 10px;
    background: rgba(14, 26, 23, .82);
    border-radius: 999px;
    padding: 3px 9px;
    font-size: .64rem;
    letter-spacing: .06em;
    color: var(--texte-doux);
}


/* --- Carte mondiale des packs ---------------------------------------

   Une liste ne dit pas OÙ se trouvent les choses : « Pérouges » ne
   signifie rien à qui ne connaît pas l'Ain. Un point sur une carte le
   dit en une seconde. */
.carte-monde-boite { margin: 18px 0 6px; }
.entete-carte-monde {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 8px;
}
.entete-carte-monde h2 {
    margin: 0;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--texte-doux);
}
.carte-monde {
    height: 300px;
    border-radius: 12px;
    border: 1px solid var(--bordure);
    overflow: hidden;
    background: var(--fond-2);
}
@media (max-width: 640px) { .carte-monde { height: 230px; } }

.pion-pack {
    display: block;
    width: 18px; height: 18px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, .9);
    box-shadow: 0 2px 7px rgba(0, 0, 0, .55);
    font-size: 9px;
    line-height: 15px;
    text-align: center;
    color: #fff;
    cursor: pointer;
}
/* Étiquette permanente : sur une carte de quelques points, obliger à
   survoler chacun pour savoir ce que c'est n'apporte rien. */
.etiquette-pack {
    background: rgba(14, 26, 23, .84);
    border: none;
    color: #f2f5f3;
    font-size: 11px;
    font-weight: 600;
    padding: 2px 7px;
    border-radius: 5px;
    box-shadow: none;
    white-space: nowrap;
}
.etiquette-pack::before { display: none; }


/* --- Classement géographique des packs ------------------------------

   <details> plutôt qu'un accordéon en JavaScript : il se plie sans une
   ligne de script, reste utilisable au clavier, et le navigateur le
   déplie tout seul quand on cherche du texte dans la page (Ctrl+F). Un
   accordéon maison perd ces trois propriétés. */
.groupe-geo { margin: 0 0 4px; }
.groupe-geo > summary {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 12px;
    border-radius: 9px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    transition: background .14s;
}
.groupe-geo > summary::-webkit-details-marker { display: none; }
.groupe-geo > summary::before {
    content: '▸';
    font-size: 11px;
    color: var(--texte-doux);
    transition: transform .16s;
}
.groupe-geo[open] > summary::before { transform: rotate(90deg); }
.groupe-geo > summary:hover { background: var(--fond-2); }
.groupe-geo .nom { flex: 1; }
.groupe-geo .compte {
    font-size: 11px;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--fond-3);
    color: var(--texte-doux);
}

/* Trois niveaux, trois graisses : la hiérarchie se lit sans compter les
   indentations. */
.groupe-geo.continent > summary { font-size: 15px; font-weight: 600; }
.groupe-geo.pays      > summary { font-size: 14px; margin-left: 14px; }
.groupe-geo.secteur   > summary { font-size: 13px; margin-left: 28px; color: var(--texte-doux); }
.groupe-geo.secteur   > .grille,
.groupe-geo.secteur   > .titre-ville { margin-left: 28px; }

.titre-ville {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 12px 0 8px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--accent);
    font-weight: 600;
}
.titre-ville .compte {
    font-size: 10.5px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--fond-3);
    color: var(--texte-doux);
    letter-spacing: 0;
}

@media (max-width: 640px) {
    .groupe-geo.pays    > summary { margin-left: 8px; }
    .groupe-geo.secteur > summary,
    .groupe-geo.secteur > .grille,
    .groupe-geo.secteur > .titre-ville { margin-left: 16px; }
}


/* --- Le carnet du visiteur -------------------------------------------

   Privé : rien n'est publié ni agrégé. C'est un souvenir de voyage, pas
   un avis de plateforme. */
.carnet { display: flex; flex-direction: column; gap: 10px; }

.entree-carnet {
    display: grid;
    grid-template-columns: 64px 1fr 36px;
    gap: 12px;
    padding: 12px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: 12px;
}
.entree-carnet .vignette {
    width: 64px; height: 64px;
    border-radius: 9px;
    object-fit: cover;
    background: var(--fond-3);
    display: flex; align-items: center; justify-content: center;
    font-size: 26px;
}
.entree-carnet h3 { margin: 0 0 2px; font-size: 15px; }
.entree-carnet .favori { color: var(--accent); }
.entree-carnet .meta { font-size: 11.5px; margin-bottom: 6px; }

/* Cinq étoiles, et zéro qui n'est pas une mauvaise note mais l'absence
   de note. On l'écrit plutôt que d'afficher cinq étoiles vides, qui se
   lisent comme un jugement. */
.etoiles { display: inline-flex; gap: 2px; vertical-align: middle; }
.etoile {
    background: none;
    border: none;
    padding: 0 1px;
    font-size: 17px;
    line-height: 1;
    color: var(--bordure);
    cursor: pointer;
    transition: color .12s, transform .12s;
}
.etoile:hover { transform: scale(1.18); }
.etoile.pleine { color: #f0b429; }
.note-valeur { margin-left: 8px; font-size: 11.5px; color: var(--texte-doux); }

.entree-carnet .mot { margin-top: 7px; position: relative; }
.entree-carnet textarea {
    width: 100%;
    min-height: 44px;
    padding: 7px 9px;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: 8px;
    color: var(--texte);
    font: inherit;
    font-size: 12.5px;
    line-height: 1.45;
    resize: vertical;
}
.entree-carnet .etat {
    position: absolute; right: 8px; bottom: 6px;
    font-size: 10.5px;
    color: var(--texte-doux);
    pointer-events: none;
}

.btn-favori {
    align-self: start;
    width: 34px; height: 34px;
    background: none;
    border: 1px solid var(--bordure);
    border-radius: 50%;
    color: var(--texte-doux);
    font-size: 16px;
    cursor: pointer;
    transition: color .14s, border-color .14s;
}
.btn-favori:hover { color: var(--accent); border-color: var(--accent); }
.btn-favori.actif { color: var(--accent); border-color: var(--accent); background: rgba(224,164,88,.12); }

@media (max-width: 640px) {
    .entree-carnet { grid-template-columns: 48px 1fr 32px; gap: 9px; }
    .entree-carnet .vignette { width: 48px; height: 48px; font-size: 20px; }
}


/* =====================================================================
   Cibles tactiles
   =====================================================================

   MESURE, PAS SUPPOSITION

   Un audit conduit dans un vrai navigateur, a 390 puis 360 pixels, avec
   emulation tactile, a releve : les commandes de carte a 30 x 30 px, les
   depliants a 26 px de haut, les boutons de l'administration a 31 px, et
   des listes deroulantes a 19 px. Un pouce couvre environ 45 px. En
   dessous, on vise, on rate, on recommence — debout, en marchant, d'une
   seule main.

   POURQUOI DANS CETTE FEUILLE ET NON DANS LES COMPLEMENTS

   L'administration ne charge pas complements.css. Les regles posees
   la-bas n'y arrivaient donc jamais, et l'audit le montrait : les memes
   commandes restaient a 30 px sur admin/pois.php. Atteindre un bouton
   n'est pas un complement, c'est une condition d'usage.

   POURQUOI SOUS « pointer: coarse »

   Au doigt seulement. Grossir ces commandes sur un ecran pointe les
   rendrait envahissantes sans rien apporter : la souris est precise au
   pixel. */

@media (pointer: coarse) {

    /* Les commandes de carte : les plus sollicitees de l'application, et
       les plus petites. Leaflet les fixe a 30 px dans sa propre feuille,
       d'ou le poids necessaire ici. */
    .leaflet-bar a,
    .leaflet-control-zoom-in,
    .leaflet-control-zoom-out,
    .gex-fond-btn {
        /* « display » AVANT tout le reste : sur un ecran ou la feuille de
           Leaflet n'a pas pris — l'editeur de tuiles etait dans ce cas —
           le lien reste « inline », et largeur comme hauteur sont alors
           purement decoratives. Le style calcule annoncait 44 px, le
           rendu mesurait 13 x 26. Poser une boite explicite rend la
           regle vraie partout. */
        display: flex !important;
        align-items: center;
        justify-content: center;
        width: 44px !important;
        height: 44px !important;
        line-height: 1 !important;
        font-size: 19px !important;
    }
    .leaflet-bar { border-radius: 14px; overflow: hidden; }

    /* Les depliants sont des boutons qui n'en ont pas l'air. */
    summary {
        min-height: 44px;
        display: flex;
        align-items: center;
        gap: 8px;
    }

    /* Boutons, liens-boutons et champs. « petit » qualifie l'apparence,
       pas la surface sensible. */
    .btn,
    .btn.petit,
    button,
    select,
    input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]) {
        min-height: 44px;
    }

    /* Les listes deroulantes de l'administration tombaient a 19 px de
       haut : la valeur choisie s'y lisait, mais on ne pouvait pas
       l'atteindre sans zoomer. */
    select { padding-block: 8px; }

    /* La navigation de l'administration : des liens de texte, donc sans
       surface propre. On elargit la zone sans deplacer la ligne. */
    .entete-action,
    .marque,
    .admin-menu a {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }

    /* Les liens d'un tableau ouvrent une fiche : ce sont des commandes,
       meme s'ils ressemblent a du texte. On epaissit leur surface sans
       agrandir la ligne, en jouant sur le remplissage vertical.

       Les liens dans une PHRASE, eux, restent tels quels : les gonfler
       casserait l'interligne du paragraphe, et personne ne les vise a
       l'aveugle — ils sont lus dans leur contexte. */
    .tableau td a,
    .tableau th a {
        display: inline-block;
        padding: 11px 2px;
        margin: -11px 0;
    }

    /* Les liens de pied de page se touchent aussi : on agrandit la
       surface sensible sans bouger le texte. */
    p.discret.centre a,
    p.centre.discret a {
        display: inline-block;
        padding: 12px 4px;
    }

    /* Une case a cocher se touche par son libelle, mais le carre doit
       rester visible et atteignable. */
    .case input[type="checkbox"],
    .case input[type="radio"] {
        width: 22px; height: 22px;
        flex: 0 0 auto;
    }
    .case { min-height: 44px; align-items: center; }

    /* Les cinq etoiles de notation. Mesure : 16 px de large chacune, soit
       cinq cibles dans 80 px. Un pouce en couvre trois. On visait quatre
       etoiles, on en posait trois — et comme un second appui sur la meme
       etoile retire la note, se tromper puis se corriger efface tout.
       Elargies, les cinq tiennent dans 230 px : elles rentrent meme sur
       un ecran de 360 px. */
    .etoile {
        min-width: 44px;
        min-height: 44px;
        padding: 0;
        font-size: 25px;
    }
    .etoiles { gap: 0; }

    /* Les liens d'action sous un chiffre de l'administration
       (« Gerer les partenaires »). Du texte nu, 16 px de haut : on
       agrandit la surface sensible sans deplacer la ligne. */
    .stat .libelle a {
        display: inline-block;
        padding: 12px 4px;
        margin: -10px 0;
    }
}

/* =====================================================================
   Accueil public — le mur de lieux
   =====================================================================

   La vitrine montre le produit avec sa propre matiere : de vraies
   photographies de lieux, tirees des packs publies, changees chaque
   jour. Par-dessus, une carte de proximite — la replique du moment que
   vend l'application : on marche, un lieu se met a raconter.

   Le mur est un DECOR : tres assombri, legerement flou sur les bords du
   voile, il porte le titre sans se disputer avec lui. Les photographies
   nettes, c'est le role de la carte posee dessus et des cartes de packs
   plus bas. */

.hero-lieux {
    position: relative;
    /* Annule exactement le rembourrage de .contenu (18px haut, 16px
       cotes ; 14px en haut sur mobile) : le mur touche les bords. */
    margin: -18px -16px 22px;
    padding: clamp(48px, 9vh, 84px) 20px clamp(56px, 10vh, 92px);
    border-radius: 0 0 28px 28px;
    overflow: hidden;
    background: var(--fond-2);
}
.hero-mur {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: 1fr;
}
.hero-mur img {
    width: 100%; height: 100%;
    object-fit: cover;
    /* Assombries et desaturees ensemble : douze photos aux dominantes
       differentes feraient un damier criard ; ramenees vers le vert du
       site, elles font une matiere. */
    filter: brightness(.5) saturate(.65);
}
.hero-voile {
    position: absolute;
    inset: 0;
    /* Deux lumieres : l'ombre du bas assoit le texte, la lueur ocre en
       haut a droite rechauffe — c'est elle qui dit « bienvenue » sans un
       mot. Le vert du site reste la teinte de fond. */
    background:
        radial-gradient(70% 90% at 80% 0%, rgba(224, 164, 88, .28), transparent 60%),
        linear-gradient(to bottom, rgba(14, 26, 23, .55), rgba(14, 26, 23, .82) 78%, var(--fond) 100%);
}
.hero-texte {
    position: relative;
    max-width: 640px;
    margin: 0 auto;
    text-align: center;
}
.hero-texte h1 {
    margin: 0 0 6px;
    font-family: var(--police-titre);
    font-size: clamp(2.4rem, 7vw, 3.6rem);
    font-weight: 600;
    letter-spacing: .01em;
    text-shadow: 0 2px 18px rgba(0, 0, 0, .6);
}
.hero-accroche {
    margin: 0 0 14px;
    font-family: var(--police-titre);
    font-style: italic;
    font-size: clamp(1.05rem, 3vw, 1.3rem);
    color: var(--accent-clair);
    text-shadow: 0 1px 10px rgba(0, 0, 0, .6);
}
.hero-promesse {
    margin: 0 auto;
    max-width: 460px;
    font-size: .95rem;
    line-height: 1.55;
    color: var(--texte);
    text-shadow: 0 1px 8px rgba(0, 0, 0, .7);
}

/* La carte de proximite, posee sur le mur. C'est la meme silhouette que
   dans l'application : qui l'a vue ici la reconnaitra sur le terrain. */
.hero-carte {
    position: absolute;
    right: clamp(10px, 4vw, 48px);
    bottom: 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: 300px;
    padding: 8px 14px 8px 8px;
    background: rgba(20, 39, 34, .92);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(224, 164, 88, .4);
    border-radius: 16px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
    color: var(--texte);
    text-decoration: none;
    animation: hero-carte-entre .6s cubic-bezier(.22, .8, .3, 1) .35s backwards;
}
.hero-carte:hover { border-color: var(--accent); }
.hero-carte:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.hero-carte img {
    width: 52px; height: 52px;
    object-fit: cover;
    border-radius: 10px;
    flex: 0 0 auto;
}
.hero-carte .corps { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.hero-carte .nom {
    font-size: .92rem;
    font-weight: 600;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hero-carte .detail { font-size: .74rem; color: var(--accent-clair); }
@keyframes hero-carte-entre {
    from { opacity: 0; transform: translateY(14px); }
}
@media (prefers-reduced-motion: reduce) {
    .hero-carte { animation: none; }
}

/* Les chiffres en une phrase : quatre boites a grands nombres disaient
   « gabarit de page » ; une ligne de prose dit la meme chose en parlant. */
.accueil-chiffres {
    max-width: 560px;
    margin: 0 auto 24px;
    text-align: center;
    font-size: .95rem;
    line-height: 1.6;
    color: var(--texte-doux);
}
.accueil-chiffres strong {
    color: var(--accent-clair);
    font-family: var(--police-titre);
    font-size: 1.15em;
}

@media (max-width: 899px) {
    .hero-lieux { margin: -14px -16px 18px; }
    .hero-mur { grid-template-columns: repeat(4, 1fr); }
    .hero-mur img:nth-child(n+9) { display: none; }
    .hero-carte {
        position: relative;
        right: auto; bottom: auto;
        margin: 22px auto 0;
        width: fit-content;
    }
}
