/* =====================================================================
   Gexplorer - Complements de style
   Elements apparus avec les compagnons de route, l'itineraire, le
   podometre, les mises a jour et les suggestions partenaires.
   Se charge apres app.css et n'en redefinit aucune regle.
   ===================================================================== */

/* --- Compagnons de route --------------------------------------------- */

.marqueur-compagnon {
    width: 30px; height: 30px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, .9);
    box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 700; font-size: .82rem;
    transition: opacity .2s;
}
.marqueur-balise {
    font-size: 22px;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .5));
    text-align: center;
}

.liste-compagnons { list-style: none; padding: 0; margin: 0; }
.liste-compagnons li {
    display: flex; align-items: center; gap: 11px;
    padding: 10px 0;
    border-bottom: 1px solid var(--bordure);
}
.liste-compagnons li:last-child { border-bottom: none; }
.liste-compagnons .pion {
    width: 32px; height: 32px; flex: 0 0 auto;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 700; font-size: .84rem;
}
/* Le pion porte desormais un dessin, pas une lettre : la couleur passe
   dans la bordure, sinon elle recouvrirait l'animal. */
.liste-compagnons .pion-avatar {
    background: var(--fond-2, rgba(0, 0, 0, .04));
    border: 2px solid #3fa9f5;
    overflow: hidden;
    padding: 0;
}
.liste-compagnons .pion-avatar svg { width: 28px; height: 28px; }

.liste-compagnons .infos { flex: 1; min-width: 0; }
.liste-compagnons .nom { display: block; font-weight: 600; font-size: .92rem; }
.liste-compagnons .detail {
    display: block;
    color: var(--texte-doux); font-size: .78rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.liste-compagnons .perime { opacity: .5; }

.code-groupe {
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    font-size: 1.85rem;
    letter-spacing: .22em;
    font-weight: 700;
    color: var(--accent);
    background: var(--fond);
    border: 1px dashed var(--bordure);
    border-radius: var(--rayon-s);
    padding: 14px 18px;
    text-align: center;
    user-select: all;
}

/* --- Itineraire ------------------------------------------------------ */

.pastille-ordre {
    width: 22px; height: 22px;
    border-radius: 50%;
    background: var(--accent);
    color: #2a1c07;
    font-size: .72rem; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
    border: 2px solid rgba(255, 255, 255, .85);
    box-shadow: 0 2px 5px rgba(0, 0, 0, .4);
}

/* Reperes de depart et d'arrivee d'une promenade composee. */
.marqueur-repere {
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    font-size: 20px;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .55));
    cursor: grab;
}
.marqueur-repere:active { cursor: grabbing; }

/* La carte attend qu'on lui designe un point. */
.carte-en-choix { cursor: crosshair !important; }
.carte-en-choix .leaflet-interactive { cursor: crosshair !important; }

/* Variante compacte du selecteur, pour les panneaux flottants. */
.choix-mode.compact button { padding: 8px 4px; font-size: .72rem; }
.choix-mode.compact button .ico { font-size: 1.05rem; }

/* Curseur de distance. */
.panneau-itineraire input[type="range"] {
    width: 100%;
    accent-color: var(--accent);
    margin: 4px 0 2px;
}

.liste-itineraire li > span:last-child { flex: 1; }

.resume-itineraire {
    display: flex; align-items: center; gap: 14px;
    background: var(--fond-3);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 12px 15px;
    margin-bottom: 14px;
}
.resume-itineraire .chiffre { font-size: 1.3rem; font-weight: 700; line-height: 1; }
.resume-itineraire .libelle { color: var(--texte-doux); font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; }

/* --- Mode de deplacement --------------------------------------------- */

.choix-mode { display: flex; gap: 8px; margin-bottom: 14px; }
.choix-mode button {
    flex: 1;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    color: var(--texte-doux);
    padding: 10px 6px;
    font-family: inherit;
    font-size: .78rem;
    cursor: pointer;
    display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.choix-mode button .ico { font-size: 1.28rem; }
.choix-mode button.actif {
    background: var(--primaire);
    border-color: var(--primaire);
    color: #fff;
}

/* --- Indicateur d'energie -------------------------------------------- */

.jauge-energie {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: .74rem; color: var(--texte-doux);
}
.jauge-energie .point {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--succes);
}
[data-energie="economie"] .jauge-energie .point,
[data-energie="arriere"]  .jauge-energie .point { background: var(--accent); }
[data-energie="veille"]   .jauge-energie .point { background: var(--texte-doux); }

/* --- Interrupteur reseau ---------------------------------------------
 *
 * Il reprend le gabarit de la jauge d'energie voisine : meme taille,
 * meme pastille. Deux etats qui se distinguent au premier coup d'oeil,
 * sans avoir a lire — vert et allume quand les donnees circulent, ocre
 * et barre quand elles sont coupees.
 */
.bascule-reseau {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: .74rem; color: var(--texte-doux);
    background: none; border: 0; padding: 4px 8px;
    border-radius: 999px; cursor: pointer;
    font-family: inherit; line-height: 1;
}
.bascule-reseau:hover  { background: rgba(255, 255, 255, .07); }
.bascule-reseau:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bascule-reseau .point {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--succes);
}
.bascule-reseau.coupe        { color: var(--accent); }
.bascule-reseau.coupe .point {
    background: var(--accent);
    box-shadow: 0 0 0 3px rgba(224, 164, 88, .22);
}

/* Coupure choisie : le bandeau le dit autrement que la coupure subie. */
.hors-ligne-actif.choisi { background: var(--texte-doux); color: #101a17; }

/* --- Temoin reseau permanent (mobile) --------------------------------
 *
 * Sur un ecran large, l'en-tete porte deja l'interrupteur : ce temoin y
 * serait un doublon. Il n'existe donc que la ou l'en-tete disparait.
 *
 * Vert et allume quand les donnees circulent, ocre et cercle quand elles
 * sont coupees : les deux etats se distinguent sans qu'on ait a lire, le
 * mot n'etant la que pour lever le doute.
 */
.temoin-reseau { display: none; }

@media (max-width: 899px) {
    .temoin-reseau {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        position: fixed;
        /* Sous l'encoche et la barre d'etat : sans cet inset, la pastille
           se glisse dessous sur un telephone a ecran borgne. */
        top: calc(env(safe-area-inset-top, 0px) + 8px);
        right: 12px;
        /* Au-dessus de la fiche de lecture (1400), qui prend tous les
           clics quand elle est ouverte : l'etat du reseau est justement
           ce qu'on veut savoir en lisant hors ligne. Sous les dialogues
           (2500) et la loupe (3000), qui, eux, sont modaux. */
        z-index: 1500;
        padding: 5px 11px 5px 9px;
        border-radius: 999px;
        background: rgba(20, 39, 34, .94);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
        border: 1px solid var(--bordure);
        box-shadow: 0 2px 10px rgba(0, 0, 0, .45);
        color: var(--texte-doux);
        font: inherit;
        font-size: .7rem;
        line-height: 1;
        cursor: pointer;
    }
    .temoin-reseau .point {
        width: 8px; height: 8px;
        border-radius: 50%;
        background: var(--succes);
        box-shadow: 0 0 0 3px rgba(76, 175, 125, .18);
    }
    .temoin-reseau.coupe { color: var(--accent); border-color: rgba(224, 164, 88, .45); }
    .temoin-reseau.coupe .point {
        background: var(--accent);
        box-shadow: 0 0 0 3px rgba(224, 164, 88, .22);
    }

    /* Hors ligne, le bandeau ocre occupe deja le haut de l'ecran : le
       temoin se pose dessous plutot que de le chevaucher. La classe est
       posee sur <html> par gex.js, on n'a donc rien a mesurer. */
    .hors-ligne .temoin-reseau { top: calc(env(safe-area-inset-top, 0px) + 36px); }
}

/* --- Pastille de mise a jour sur un pack ------------------------------
 *
 * La liste des mises a jour existe deja plus haut dans la page, mais
 * elle oblige a faire le lien entre deux endroits. La pastille dit la
 * chose la ou l'utilisateur regarde : sur le pack lui-meme.
 */
.pastille-maj {
    display: inline-flex; align-items: center; gap: 5px;
    background: var(--accent); color: #2a1c07;
    border: 0; border-radius: 999px;
    padding: 2px 9px; margin-left: 8px;
    font-size: .7rem; font-weight: 700; font-family: inherit;
    cursor: pointer; vertical-align: middle;
}
.pastille-maj:hover { filter: brightness(1.08); }
.pastille-maj.obligatoire { background: var(--danger, #c0533f); color: #fff; }
.pastille-maj[disabled]   { opacity: .55; cursor: default; }

/* Un bandeau discret rappelle que la position affichee est simulee. */
.gps-simule .marqueur-moi { background: #c96bd6; box-shadow: 0 0 0 6px rgba(201, 107, 214, .22); }
.bandeau-simulation {
    position: fixed; top: 0; left: 0; right: 0;
    background: #c96bd6; color: #2a0730;
    font-size: .74rem; font-weight: 700; text-align: center;
    padding: 3px; z-index: 1300; letter-spacing: .04em;
}

/* --- Telechargement d'un pack ---------------------------------------- */

.etape-telechargement {
    display: flex; align-items: center; gap: 11px;
    padding: 9px 0;
    font-size: .88rem;
    color: var(--texte-doux);
}
.etape-telechargement .puce {
    width: 20px; height: 20px; flex: 0 0 auto;
    border-radius: 50%;
    border: 2px solid var(--bordure);
    display: flex; align-items: center; justify-content: center;
    font-size: .68rem;
}
.etape-telechargement.faite   { color: var(--texte); }
.etape-telechargement.faite .puce { background: var(--succes); border-color: var(--succes); color: #fff; }
.etape-telechargement.en_cours .puce { border-color: var(--accent); border-top-color: transparent; animation: rotation .8s linear infinite; }
@keyframes rotation { to { transform: rotate(360deg); } }

/* --- Suggestions partenaires ----------------------------------------- */

/* La carte de suggestion : mention legale sur sa propre ligne, puis le
   logo et le texte.
   ---------------------------------------------------------------------
   La mention etait posee en absolu dans le coin, et l'on reservait sa
   place avec « padding-right: 76px » sur le texte. Mesure faite : la
   mention occupe 162 px. Le titre de l'annonce passait donc dessous, a
   320, 360, 390 et 430 px — a toutes les largeurs essayees. Et la
   reservation ne pouvait pas etre juste : le libelle se regle dans la
   configuration (cle « mention_publicite »), il n'a pas de longueur
   connue d'avance.

   On la met donc dans le flux, sur sa propre ligne. Plus rien ne se
   chevauche, quelle que soit la longueur du libelle ou la largeur de
   l'ecran. */
.suggestion {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
        "mention mention"
        "logo    corps";
    row-gap: 6px;
    align-items: start;
    background: var(--fond-3);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 12px 14px;
    margin-bottom: 14px;
}

/* Discrete par courtoisie, obligatoire par la loi : une publicite doit se
   signaler comme telle. A .62rem elle tombait a 9,9 px sur un telephone,
   sous le seuil de ce qui se lit d'un coup d'oeil. Une mention qu'on ne
   lit pas ne remplit pas son office. */
.suggestion .mention {
    grid-area: mention;
    justify-self: end;
    font-size: .70rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--texte-doux);
    border: 1px solid var(--bordure);
    border-radius: 3px;
    padding: 1px 5px;
}
.suggestion img.logo {
    grid-area: logo;
    width: 52px; height: 52px;
    margin-right: 12px;          /* plutot qu'un « gap » : sans logo,
                                    le texte ne garde pas un vide */
    border-radius: var(--rayon-s);
    object-fit: cover;
    background: var(--fond);
}
.suggestion .corps { grid-area: corps; min-width: 0; }
.suggestion .titre { font-weight: 600; font-size: .94rem; margin-bottom: 2px; }
.suggestion .accroche { color: var(--texte-doux); font-size: .82rem; line-height: 1.45; }
.suggestion .action { margin-top: 8px; }

.sans-pub {
    font-size: .76rem;
    color: var(--succes);
    display: inline-flex; align-items: center; gap: 5px;
}

/* --- Mise a jour d'un pack ------------------------------------------- */

.carte-maj {
    border-left: 3px solid var(--accent);
    background: var(--fond-2);
    border-radius: 0 var(--rayon-s) var(--rayon-s) 0;
    padding: 13px 15px;
    margin-bottom: 12px;
}
.carte-maj .entete-maj { display: flex; align-items: baseline; gap: 9px; margin-bottom: 5px; }
.carte-maj .version { color: var(--accent); font-size: .78rem; font-weight: 700; }
.carte-maj .notes { color: var(--texte-doux); font-size: .84rem; white-space: pre-line; line-height: 1.5; }
.carte-maj.obligatoire { border-left-color: var(--danger); }

/* --- Divers ---------------------------------------------------------- */

.ligne-entre { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pile { display: flex; flex-direction: column; gap: 10px; }
.discret { color: var(--texte-doux); font-size: .82rem; }
.centre { text-align: center; }
.mono { font-family: ui-monospace, Menlo, Consolas, monospace; }

/* --- Outils flottants de la carte ------------------------------------ */

.outils-carte {
    position: fixed;
    right: 14px;
    bottom: calc(var(--barre-h) + 18px);
    display: flex;
    flex-direction: column;
    gap: 9px;
    z-index: 800;
}
.outil {
    width: 46px; height: 46px;
    border-radius: 50%;
    background: rgba(20, 39, 34, .94);
    border: 1px solid var(--bordure);
    color: var(--texte);
    font-size: 1.18rem;
    cursor: pointer;
    box-shadow: var(--ombre);
    display: flex; align-items: center; justify-content: center;
}
.outil:hover { border-color: var(--primaire-clair); }
.outil.actif { background: var(--primaire); border-color: var(--primaire); }

.panneau-compteurs {
    position: fixed;
    left: 14px; right: 76px;
    bottom: calc(var(--barre-h) + 18px);
    background: rgba(20, 39, 34, .96);
    backdrop-filter: blur(8px);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 14px;
    z-index: 810;
    box-shadow: var(--ombre);
}
.panneau-compteurs .compteurs { margin-bottom: 12px; }
.panneau-compteurs .choix-mode { margin-bottom: 8px; }

.panneau-itineraire {
    position: fixed;
    left: 14px; right: 76px;
    bottom: calc(var(--barre-h) + 18px);
    max-height: 46vh;
    overflow-y: auto;
    background: rgba(20, 39, 34, .96);
    backdrop-filter: blur(8px);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 14px;
    z-index: 805;
    box-shadow: var(--ombre);
}
.liste-itineraire {
    list-style: none;
    padding: 0;
    margin: 10px 0 0;
    counter-reset: etape;
}
.liste-itineraire li {
    display: flex; align-items: center; gap: 10px;
    padding: 7px 0;
    font-size: .88rem;
    border-bottom: 1px solid var(--bordure);
}
.liste-itineraire li:last-child { border-bottom: none; }
.liste-itineraire .rang {
    width: 22px; height: 22px; flex: 0 0 auto;
    border-radius: 50%;
    background: var(--accent);
    color: #2a1c07;
    font-size: .72rem; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
}

/* --- Canal de discussion ---------------------------------------------- */

.canal {
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    background: var(--fond-2);
    overflow: hidden;
    margin-bottom: 18px;
}
.canal.mode-talkie { border-color: var(--accent); }

.canal-messages {
    max-height: 300px;
    overflow-y: auto;
    padding: 12px 14px;
    -webkit-overflow-scrolling: touch;
}

.canal-messages .message {
    display: flex;
    gap: 9px;
    margin-bottom: 11px;
    align-items: flex-start;
}
.canal-messages .message:last-child { margin-bottom: 0; }
.canal-messages .message .pion {
    width: 26px; height: 26px;
    flex: 0 0 auto;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: .72rem; font-weight: 700;
}
.canal-messages .message .corps { flex: 1; min-width: 0; }
.canal-messages .message .detail {
    display: block;
    font-size: .7rem;
    color: var(--texte-doux);
    margin-bottom: 2px;
}
.canal-messages .message .texte {
    display: block;
    font-size: .9rem;
    line-height: 1.5;
    word-wrap: break-word;
}
/* Ses propres messages se distinguent sans changer de colonne : sur un
   ecran etroit, l'alignement a droite gaspille de la place. */
.canal-messages .message.moi .corps { border-left: 2px solid var(--primaire-clair); padding-left: 9px; }
.canal-messages .message.systeme {
    justify-content: center;
    font-size: .74rem;
    color: var(--texte-doux);
    font-style: italic;
}

.canal-saisie {
    display: flex;
    gap: 8px;
    padding: 10px 12px;
    border-top: 1px solid var(--bordure);
    background: var(--fond);
}
.canal-saisie input {
    flex: 1;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    color: var(--texte);
    padding: 9px 12px;
    font-size: .92rem;
    font-family: inherit;
    min-width: 0;
}
.canal-saisie input:focus { outline: none; border-color: var(--primaire-clair); }

.canal-parole {
    padding: 14px 12px 16px;
    border-top: 1px solid var(--bordure);
}

/* Le bouton de parole : large, atteignable au pouce, et sans ambiguite
   sur son etat. On le maintient, on ne le clique pas. */
.bouton-parler {
    width: 100%;
    min-height: 68px;
    border-radius: var(--rayon);
    border: 2px solid var(--bordure);
    background: var(--fond-3);
    color: var(--texte);
    font-family: inherit;
    font-size: .92rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    touch-action: none;
    transition: background .12s, border-color .12s, transform .08s;
}
.bouton-parler .ico { font-size: 1.6rem; }
.bouton-parler:disabled { opacity: .45; cursor: not-allowed; }
.bouton-parler:not(:disabled):active { transform: scale(.99); }

.bouton-parler.parle {
    background: var(--danger);
    border-color: #ff8a86;
    color: #fff;
    animation: parle-pulse 1.1s ease-in-out infinite;
}
@keyframes parle-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(217, 83, 79, .55); }
    50%      { box-shadow: 0 0 0 14px rgba(217, 83, 79, 0); }
}

/* Bouton de parole flottant, sur la carte. */
.parler-flottant {
    position: fixed;
    left: 14px;
    bottom: calc(var(--barre-h) + 18px);
    width: 62px; height: 62px;
    border-radius: 50%;
    border: 2px solid var(--bordure);
    background: rgba(20, 39, 34, .95);
    color: var(--texte);
    font-size: 1.5rem;
    cursor: pointer;
    z-index: 820;
    box-shadow: var(--ombre);
    display: flex; align-items: center; justify-content: center;
    user-select: none; -webkit-user-select: none; touch-action: none;
}
.parler-flottant.parle {
    background: var(--danger);
    border-color: #ff8a86;
    animation: parle-pulse 1.1s ease-in-out infinite;
}

@media (min-width: 900px) {
    .parler-flottant { left: 24px; bottom: 24px; }
}

/* --- Edition depuis la carte (administration) -------------------------- */

.outil-admin.actif {
    background: var(--accent);
    border-color: var(--accent);
    color: #2a1c07;
}

.panneau-admin { border-left: 3px solid var(--accent); }

/* En mode edition, le curseur annonce que la carte est manipulable et
   les marqueurs se distinguent de leur etat ordinaire. */
.carte-edition #carte { cursor: crosshair; }
.carte-edition .marqueur-poi {
    border-color: var(--accent);
    box-shadow: 0 3px 10px rgba(0, 0, 0, .5), 0 0 0 3px rgba(224, 164, 88, .28);
    cursor: grab;
}
.carte-edition .marqueur-poi:active { cursor: grabbing; }

/* --- Choix des packs affiches ----------------------------------------- */

.titre-groupe {
    font-family: var(--police);
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--texte-doux);
    margin: 14px 0 8px;
    padding-bottom: 5px;
    border-bottom: 1px solid var(--bordure);
}
.titre-groupe:first-child { margin-top: 0; }

.case.ligne-pack {
    align-items: center;
    gap: 9px;
    margin-bottom: 8px;
    padding: 7px 9px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    background: var(--fond-2);
}
.case.ligne-pack:hover { border-color: var(--primaire-clair); }
.case.ligne-pack .puce-pack {
    width: 10px; height: 10px;
    flex: 0 0 auto;
    border-radius: 50%;
}
.case.ligne-pack .infos { flex: 1; min-width: 0; }
.case.ligne-pack .nom {
    display: block;
    color: var(--texte);
    font-weight: 600;
    font-size: .88rem;
}
.case.ligne-pack .detail {
    display: block;
    font-size: .74rem;
    color: var(--texte-doux);
}
/* « Y aller » : cadrer la carte sur ce pack.
   ---------------------------------------------------------------------
   La case a cocher et ce bouton repondent a deux questions differentes —
   « ce pack s'affiche-t-il ? » et « emmene-moi le voir ». Le bouton est
   donc distinct visuellement de la case, et assez large pour un pouce.
   Il reste en retrait : on lit d'abord le nom du pack. */
.case.ligne-pack .aller-pack {
    flex: 0 0 auto;
    align-self: center;
    background: none;
    border: 1px solid var(--bordure);
    border-radius: 999px;
    color: var(--texte-doux);
    font: inherit;
    font-size: .74rem;
    white-space: nowrap;
    padding: 7px 12px;
    cursor: pointer;
    transition: color .14s, border-color .14s, background .14s;
}
.case.ligne-pack .aller-pack:hover,
.case.ligne-pack .aller-pack:focus-visible {
    color: var(--accent);
    border-color: var(--accent);
    background: rgba(224, 164, 88, .1);
}

/* Un pack decoche s'efface, sans disparaitre de la liste.
   L'attenuation porte sur ce qui informe — la pastille de couleur et le
   texte — et non sur la ligne entiere : l'opacite d'un parent ne se
   rattrape pas sur un enfant, et attenuer tout le bloc rendait « Y aller »
   difficile a lire. Or c'est justement par la qu'on va rechercher un pack
   qu'on avait mis de cote. */
.case.ligne-pack:has(input:not(:checked)) .puce-pack,
.case.ligne-pack:has(input:not(:checked)) .infos { opacity: .5; }

/* Un pack acquis se distingue au premier coup d'oeil dans la boutique. */
.carte-item.acquis { border-color: rgba(76, 175, 125, .55); }
.carte-item.acquis .visuel .prix {
    background: var(--succes);
    color: #fff;
}

/* Le titre de groupe sert aussi de separateur dans la boutique. */
h2.titre-groupe {
    font-size: .78rem;
    margin-top: 22px;
}

/* --- Liseuse ---------------------------------------------------------- */
/* Se superpose a la carte en transparence : on continue de voir ou l'on
   se trouve pendant qu'on lit. Le flou d'arriere-plan rend le texte
   lisible sans masquer le contexte. */

.liseuse {
    position: fixed;
    inset: 0;
    /* Au-dessus de la carte et de ses commandes, sous les dialogues
       (2500) et la loupe (3000), qui doivent pouvoir s'ouvrir par-dessus
       la lecture. */
    z-index: 1400;
    display: none;
    pointer-events: none;
}
.liseuse.ouverte { display: block; }

/* OUVERTE EN GRAND, LA FICHE PREND TOUS LES CLICS.

   Elle ne couvre pas tout l'ecran : une bande transparente laisse voir la
   carte au-dessus du recit. Cette bande laissait aussi PASSER les appuis,
   et un marqueur qui s'y trouvait les recevait a la place de la fiche. On
   croyait cocher « Lieu explore », on ouvrait le lieu d'a cote.

   La bande reste transparente — on voit toujours ou l'on est — mais elle
   ne rend plus la main a la carte tant qu'on lit. Reduite, en revanche, la
   fiche n'est plus qu'une barre : tout le reste redevient la carte. */
.liseuse.ouverte:not(.reduite) { pointer-events: auto; }

.liseuse-cadre {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    top: max(64px, 18vh);
    display: flex;
    flex-direction: column;
    pointer-events: auto;

    background: rgba(14, 26, 23, .82);
    backdrop-filter: blur(14px) saturate(1.1);
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    border-top: 1px solid rgba(224, 164, 88, .35);
    border-radius: 28px 28px 0 0;
    box-shadow: 0 -14px 40px rgba(0, 0, 0, .5);

    animation: liseuse-monte .28s cubic-bezier(.22, .8, .3, 1);
}
.liseuse.reduite .liseuse-cadre { display: none; }

@keyframes liseuse-monte { from { transform: translateY(14px); opacity: 0; } }

.liseuse-tete {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 15px 18px 10px;
    flex: 0 0 auto;
    border-bottom: 1px solid rgba(255, 255, 255, .07);
}
.liseuse-titres { flex: 1; min-width: 0; }
.liseuse-tete h2 {
    margin: 0;
    font-size: 1.16rem;
    line-height: 1.25;
}
.liseuse-tete p {
    margin: 3px 0 0;
    font-size: .8rem;
    color: var(--texte-doux);
}
.liseuse-boutons { display: flex; gap: 8px; flex: 0 0 auto; }

.liseuse-btn {
    width: 34px; height: 34px;
    border-radius: 50%;
    border: 1px solid var(--bordure);
    background: rgba(20, 39, 34, .8);
    color: var(--texte);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    padding: 0;
}
.liseuse-btn:hover { border-color: var(--accent); color: var(--accent); }

/* La page de texte. La hauteur est bornée : c'est elle qui sert de
   gabarit au découpage, mesuré à l'exécution. */
.liseuse-page {
    flex: 1 1 auto;
    /* La pagination fait le gros du travail, mais un bloc insecable plus
       haut que l'ecran — une longue fiche technique, une image — doit
       pouvoir defiler plutot que d'etre coupe. */
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 16px 20px 8px;
    font-size: 1.02rem;
    line-height: 1.68;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: var(--bordure) transparent;
}
.liseuse-page::-webkit-scrollbar { width: 5px; }
.liseuse-page::-webkit-scrollbar-thumb {
    background: var(--bordure);
    border-radius: 3px;
}

/* Dans la liseuse, la fiche technique doit rester compacte : elle
   partage la page avec le reste. */
.liseuse-page .fiche-tech {
    margin-bottom: .9em;
    padding: 11px 13px;
    gap: 5px 12px;
    font-size: .84rem;
}
.liseuse-page .galerie img,
.liseuse-page .galerie video { height: 128px; }
.liseuse-page.mesure { visibility: hidden; }
.liseuse-page.tourne { animation: liseuse-tourne .22s ease; }
@keyframes liseuse-tourne { from { opacity: .25; transform: translateX(10px); } }

.liseuse-page p { margin: 0 0 1.05em; }
.liseuse-page p:last-child { margin-bottom: 0; }
.liseuse-page h3 { margin: 0 0 .6em; font-size: 1.02rem; color: var(--accent); }
.liseuse-page blockquote {
    margin: 0 0 1.05em;
    padding: 2px 0 2px 15px;
    border-left: 2px solid var(--accent);
    color: var(--texte-doux);
    font-style: italic;
}
.liseuse-page .galerie { margin-top: 4px; }

.liseuse-pied {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px calc(12px + env(safe-area-inset-bottom));
    border-top: 1px solid rgba(255, 255, 255, .07);
}
.liseuse-nav {
    width: 44px; height: 44px;
    border-radius: 50%;
    border: 1px solid var(--bordure);
    background: rgba(20, 39, 34, .7);
    color: var(--texte);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    flex: 0 0 auto;
}
.liseuse-nav:disabled { opacity: .25; cursor: default; }
.liseuse-nav:not(:disabled):hover { border-color: var(--accent); color: var(--accent); }

.liseuse-points {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex-wrap: wrap;
}
.liseuse-points .point {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--bordure);
    transition: background .2s, transform .2s;
}
.liseuse-points .point.actif { background: var(--accent); transform: scale(1.5); }
.liseuse-compte {
    width: 100%;
    text-align: center;
    font-size: .68rem;
    color: var(--texte-doux);
    font-variant-numeric: tabular-nums;
}

/* --- Cartes de proximite ---------------------------------------------- */
/* En haut de l'ecran, sous l'en-tete : elles signalent ce qui est a
   portee sans ouvrir quoi que ce soit. Une carte par lieu proche, la
   plus proche en tete — dans un centre ancien, deux lieux voisins se
   valent, et c'est a l'utilisateur de choisir ce qu'il veut lire. */

.proximite {
    position: fixed;
    top: calc(var(--entete-h) + 8px);
    left: 10px; right: 10px;
    z-index: 860;
    display: flex;
    flex-direction: column;
    gap: 7px;
    pointer-events: none;
}
.proximite:empty { display: none; }

.carte-proximite {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 8px 10px 12px;
    background: rgba(20, 39, 34, .93);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--bordure);
    border-left: 3px solid var(--accent);
    border-radius: var(--rayon);
    box-shadow: var(--ombre);
    cursor: pointer;
    animation: proximite-entre .25s cubic-bezier(.22, .8, .3, 1);
    transition: border-color .15s, transform .1s;
}
.carte-proximite:hover  { border-color: var(--primaire-clair); }
.carte-proximite:active { transform: scale(.99); }
.carte-proximite.vue    { border-left-color: var(--succes); }

@keyframes proximite-entre { from { opacity: 0; transform: translateY(-10px); } }

.carte-proximite .pastille-lieu {
    width: 34px; height: 34px;
    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: 1.05rem;
}
.carte-proximite .corps { flex: 1; min-width: 0; }
.carte-proximite .nom {
    display: block;
    font-weight: 600;
    font-size: .93rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.carte-proximite .detail {
    display: block;
    font-size: .74rem;
    color: var(--texte-doux);
}
.carte-proximite .ecarter {
    width: 30px; height: 30px;
    flex: 0 0 auto;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--texte-doux);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.carte-proximite .ecarter:hover { color: var(--texte); background: var(--fond-3); }

@media (min-width: 900px) {
    .proximite { left: auto; right: 24px; width: 380px; top: calc(var(--entete-h) + 16px); }
}

/* Etat replie de la liseuse : la barre rejoint les cartes de proximite
   en haut de l'ecran, pour que tout ce qui appelle un geste se trouve
   au meme endroit. */
.liseuse-barre {
    position: absolute;
    left: 10px; right: 10px;
    top: calc(var(--entete-h) + 8px);
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px 10px 15px;
    background: rgba(20, 39, 34, .93);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--bordure);
    border-left: 3px solid var(--accent);
    border-radius: var(--rayon);
    box-shadow: var(--ombre);
    cursor: pointer;
}
.liseuse-barre-titre {
    flex: 1;
    font-weight: 600;
    font-size: .9rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.liseuse-barre-etat {
    font-size: .74rem;
    color: var(--texte-doux);
    white-space: nowrap;
}

@media (min-width: 900px) {
    .liseuse-cadre {
        left: auto;
        right: 24px;
        bottom: 24px;
        top: auto;
        width: 440px;
        height: min(74vh, 680px);
        border-radius: var(--rayon);
        border: 1px solid rgba(224, 164, 88, .3);
    }
    .liseuse-barre { left: auto; right: 24px; width: 380px; top: calc(var(--entete-h) + 16px); }
}

/* --- Recit d'un lieu -------------------------------------------------- */

.recit { line-height: 1.68; }
.recit p { margin: 0 0 .9em; }
.recit h3 { margin-top: 1.2em; }
.recit blockquote {
    margin: 1em 0;
    padding-left: 14px;
    border-left: 2px solid var(--accent);
    color: var(--texte-doux);
    font-style: italic;
}
.galerie audio { width: 260px; }

/* --- Radar ------------------------------------------------------------ */

.radar {
    text-align: center;
    padding: 22px 16px;
    border-radius: var(--rayon);
    border: 1px solid var(--bordure);
    background: var(--fond);
    margin-bottom: 14px;
    transition: border-color .4s, background .4s;
}
.radar .palier { font-size: 1.6rem; font-weight: 700; letter-spacing: .02em; }
.radar .indication { color: var(--texte-doux); font-size: .84rem; margin-top: 6px; }
.radar .onde {
    width: 84px; height: 84px;
    margin: 12px auto 6px;
    border-radius: 50%;
    border: 2px solid currentColor;
    opacity: .35;
    animation: onde-radar 2s ease-out infinite;
}
@keyframes onde-radar {
    0%   { transform: scale(.55); opacity: .7; }
    100% { transform: scale(1.15); opacity: 0; }
}

/* --- Rassemblement ---------------------------------------------------- */

.rassemblement {
    background: var(--fond-3);
    border: 1px solid var(--accent);
    border-radius: var(--rayon-s);
    padding: 13px 15px;
    margin-bottom: 14px;
}
.rassemblement .jauge {
    display: flex; gap: 6px; margin: 10px 0 8px;
}
.rassemblement .place {
    flex: 1; height: 8px;
    border-radius: 999px;
    background: var(--fond);
    border: 1px solid var(--bordure);
}
.rassemblement .place.occupee { background: var(--succes); border-color: var(--succes); }

/* --- Fiche de pack ---------------------------------------------------- */

.visuel-pack {
    height: 190px;
    border-radius: var(--rayon);
    background-size: cover;
    background-position: center;
    margin-bottom: 18px;
    border: 1px solid var(--bordure);
}
.carte-apercu {
    height: 300px;
    border-radius: var(--rayon);
    border: 1px solid var(--bordure);
    overflow: hidden;
}
.avantages {
    list-style: none;
    padding: 0;
    margin: 14px 0 0;
    font-size: .88rem;
}
.avantages li {
    padding: 5px 0 5px 24px;
    position: relative;
    color: var(--texte-doux);
}
.avantages li::before {
    content: '✓';
    position: absolute;
    left: 0;
    color: var(--succes);
    font-weight: 700;
}

/* --- Malle (bibliotheque) --------------------------------------------- */

.pack-installe {
    display: flex;
    gap: 13px;
    align-items: flex-start;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 14px 15px;
    margin-bottom: 13px;
}
.pack-installe .vignette {
    width: 62px; height: 62px; flex: 0 0 auto;
    border-radius: var(--rayon-s);
    background: linear-gradient(135deg, var(--fond-3), var(--primaire));
    background-size: cover; background-position: center;
}
.pack-installe .details { flex: 1; min-width: 0; }
.pack-installe .actions-pack { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; }

.occupation {
    display: flex; align-items: center; gap: 12px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 12px 15px;
    margin-bottom: 16px;
    font-size: .86rem;
}
.occupation .progression { flex: 1; }

/* --- Formulaires et mise en page -------------------------------------- */

.colonne-etroite { max-width: 480px; margin: 0 auto; }

.case {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 12px;
    font-size: .86rem;
    line-height: 1.5;
    color: var(--texte-doux);
    cursor: pointer;
}
.case input[type="checkbox"] {
    width: 19px; height: 19px;
    flex: 0 0 auto;
    margin-top: 1px;
    accent-color: var(--primaire);
}
.case span { flex: 1; }

/* --- Filtre par type de lieu ----------------------------------------- */
/*
   Quatorze types, sur un telephone, dans un panneau deja occupe : la
   liste doit rester compacte sans devenir illisible. On resserre donc
   l'interligne des cases de ce filtre-la, et l'on ajoute deux raccourcis
   plus un « seul » par ligne — sans eux, isoler un type demanderait
   treize appuis. */

.filtre-raccourcis {
    display: flex;
    gap: 8px;
    margin-bottom: 10px;
}
.filtre-raccourcis .btn { flex: 1; }
.filtre-raccourcis .btn[disabled] { opacity: .4; pointer-events: none; }

#filtre-categorie .case { margin-bottom: 7px; align-items: center; }
#filtre-categorie .case > span {
    display: flex;
    align-items: center;
    gap: 7px;
}

/* Le bouton « seul » ne se montre qu'a la ligne survolee ou touchee :
   quatorze boutons alignes feraient un mur. Au doigt, il n'y a pas de
   survol — il reste donc visible en permanence, en retrait. */
#filtre-categorie .seul {
    margin-left: auto;
    flex: 0 0 auto;
    background: none;
    border: 1px solid var(--bordure);
    border-radius: 999px;
    color: var(--texte-doux);
    font: inherit;
    font-size: .72rem;
    padding: 2px 9px;
    cursor: pointer;
    opacity: 0;
    transition: opacity .14s, color .14s, border-color .14s;
}
#filtre-categorie .case:hover .seul,
#filtre-categorie .seul:focus-visible { opacity: 1; }
#filtre-categorie .seul:hover {
    color: var(--accent);
    border-color: var(--accent);
}
@media (pointer: coarse) {
    #filtre-categorie .seul {
        opacity: .75;
        padding: 7px 12px;      /* la surface sensible, pas l'apparence */
        margin-block: -5px;
    }
}

.champ input[type="color"] {
    height: 44px;
    padding: 4px;
    cursor: pointer;
}

/* --- Barre d'une partie en cours -------------------------------------- */

.barre-partie {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--fond-2);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-s);
    padding: 10px 14px;
    margin-bottom: 12px;
    position: sticky;
    top: calc(var(--entete-h) + 6px);
    z-index: 700;
}
.barre-partie .espace { flex: 1; }

.indices { margin-top: 10px; }

@media (min-width: 900px) {
    .outils-carte      { bottom: 24px; right: 24px; }
    .panneau-compteurs,
    .panneau-itineraire { left: 24px; right: auto; width: 340px; bottom: 24px; }
}

/* =====================================================================
   Disposition mobile
   =====================================================================
   Sur un telephone, l'en-tete disparait et tout passe dans la barre du
   bas : c'est la seule zone que le pouce atteint sans changer de prise,
   et cela rend a la carte les cinquante-huit pixels que la barre du haut
   lui prenait.

   La barre se cale au-dessus de la barre systeme d'Android — gestes ou
   trois boutons — grace a env(safe-area-inset-bottom). Cet inset n'est
   renseigne que si le document declare viewport-fit=cover, ce que fait
   l'en-tete de l'application. Tout ce qui flotte au-dessus de la carte
   se decale de la meme quantite, sinon les boutons finiraient sous la
   barre systeme.
   ===================================================================== */

@media (max-width: 899px) {
    :root {
        --entete-h: 0px;
        --barre-h: 62px;
        /* Hauteur reellement occupee en bas : barre + zone systeme. */
        --bas-sur: calc(var(--barre-h) + env(safe-area-inset-bottom, 0px));
    }

    .entete { display: none; }


    /* Le contenu court sous la barre du bas : on lui rend sa marge. */
    .contenu { padding-top: 14px; padding-bottom: calc(var(--bas-sur) + 24px); }
    #carte { top: 0; bottom: var(--bas-sur); }

    .barre-nav {
        height: auto;
        min-height: var(--barre-h);
        padding-bottom: env(safe-area-inset-bottom, 0px);
        /* Une ombre portee vers le haut detache la barre de la carte. */
        box-shadow: 0 -6px 20px rgba(0, 0, 0, .35);
    }
    .barre-nav a { padding: 9px 2px 7px; gap: 4px; }
    .barre-nav a .ico { font-size: 1.34rem; }
    .barre-nav a.actif { position: relative; }
    /* Un trait au-dessus de l'onglet actif : sur fond sombre, la couleur
       seule ne suffit pas toujours a le distinguer. */
    .barre-nav a.actif::before {
        content: '';
        position: absolute;
        top: 0; left: 22%; right: 22%;
        height: 2px;
        border-radius: 0 0 2px 2px;
        background: var(--accent);
    }

    /* Tout ce qui flotte remonte au-dessus de la barre et de la zone
       systeme, et repart du haut de l'ecran puisque l'en-tete a disparu. */
    /* Sous le temoin reseau, qui occupe le coin haut droit en
       permanence : a dix pixels du bord, cartes de proximite et barre de
       fiche reduite lui passaient dessous. Hors ligne, le bandeau ocre
       s'ajoute et tout descend d'un cran de plus.

       C'est LE seul endroit qui regle ces hauteurs : une premiere version
       vivait plus haut dans le fichier et se faisait ecraser ici meme,
       en silence — a specificite egale, la derniere regle du fichier
       gagne. */
    .proximite      { top: calc(env(safe-area-inset-top, 0px) + 44px); }
    .liseuse-barre  { top: calc(env(safe-area-inset-top, 0px) + 44px); }
    .hors-ligne .proximite,
    .hors-ligne .liseuse-barre { top: calc(env(safe-area-inset-top, 0px) + 72px); }
    .bandeau-simulation { top: env(safe-area-inset-top, 0px); }

    .outils-carte       { bottom: calc(var(--bas-sur) + 14px); }
    .panneau-compteurs,
    .panneau-itineraire { bottom: calc(var(--bas-sur) + 14px); }
    .parler-flottant    { bottom: calc(var(--bas-sur) + 14px); }
    #notifs             { bottom: calc(var(--bas-sur) + 14px); }

    /* La liseuse occupe l'ecran jusqu'a la barre du bas, pas au-dela. */
    .liseuse-cadre {
        top: calc(env(safe-area-inset-top, 0px) + 56px);
        bottom: var(--bas-sur);
        border-radius: 28px 28px 0 0;
    }
    .liseuse-pied { padding-bottom: 12px; }

    /* Cibles tactiles : rien en dessous de 44 px de cote. */
    .btn { min-height: 44px; }
    .outil { width: 50px; height: 50px; }
}

/* Ecrans etroits : l'icone cede un peu de place au libelle. La taille du
   libelle, elle, se regle desormais en continu dans app.css. */
@media (max-width: 380px) {
    .barre-nav a .ico { font-size: 1.22rem; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* =====================================================================
   Avatars animaliers
   ===================================================================== */

.avatar { display: block; }

/* --- Le pion d'un compagnon sur la carte --------------------------- */

/* La bordure porte la couleur du pion, le SVG porte l'identite. De loin
   on voit le cercle colore, de pres on reconnait l'animal : deux
   niveaux de lecture pour un seul marqueur. */
.marqueur-avatar {
    width: 44px; height: 44px;
    border-radius: 50%;
    border: 3px solid #3fa9f5;
    background: var(--fond-carte, #fdfbf7);
    box-shadow: 0 3px 10px rgba(0, 0, 0, .45);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
    transition: transform .18s ease;
}
.marqueur-avatar svg { width: 38px; height: 38px; }

.leaflet-container.sans-animation .marqueur-avatar { transition: none; }

/* --- Le choix dans le profil --------------------------------------- */

.avatar-choix {
    display: flex;
    gap: 18px;
    align-items: flex-start;
    flex-wrap: wrap;
    margin-top: 10px;
}

.avatar-apercu {
    flex: 0 0 auto;
    text-align: center;
    padding: 10px 14px;
    border-radius: 14px;
    background: var(--fond-2, rgba(0, 0, 0, .04));
}
.avatar-apercu svg { margin: 0 auto; }
.avatar-apercu .discret { margin-top: 4px; font-size: .82rem; }

.avatar-grille {
    flex: 1 1 320px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
    gap: 6px;
}

.avatar-case {
    display: flex; align-items: center; justify-content: center;
    padding: 5px;
    border: 2px solid transparent;
    border-radius: 12px;
    background: var(--fond-2, rgba(0, 0, 0, .04));
    cursor: pointer;
    transition: border-color .12s ease, transform .12s ease;
}
.avatar-case:hover  { transform: translateY(-2px); }
.avatar-case.choisi { border-color: var(--accent, #e0a458); background: rgba(224, 164, 88, .16); }
.avatar-case:focus-visible { outline: 2px solid var(--accent, #e0a458); outline-offset: 2px; }

/* --- La palette, avec son option « normal » ------------------------- */

.avatar-couleurs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }

.pastille-couleur {
    width: 34px; height: 34px;
    border-radius: 50%;
    border: 3px solid transparent;
    cursor: pointer;
    padding: 0;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18);
}
.pastille-couleur.choisi { border-color: var(--texte, #2b2b2b); }
.pastille-couleur:focus-visible { outline: 2px solid var(--accent, #e0a458); outline-offset: 2px; }

/* « Normal » n'est pas une couleur : elle ne peut donc pas etre une
   pastille teintee. Elle s'ecrit. */
.pastille-couleur.normal {
    width: auto; height: 34px;
    padding: 0 12px;
    border-radius: 17px;
    font-size: .8rem;
    background: var(--fond-2, rgba(0, 0, 0, .04));
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}

/* --- Le choix d'humeur pendant une sortie --------------------------- */

.humeurs {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-top: 8px;
}
.humeur-case {
    display: flex; flex-direction: column; align-items: center;
    gap: 2px;
    padding: 5px 6px;
    border: 2px solid transparent;
    border-radius: 12px;
    background: var(--fond-2, rgba(0, 0, 0, .04));
    cursor: pointer;
    font-size: .68rem;
    line-height: 1.1;
    min-width: 62px;
}
.humeur-case.choisi { border-color: var(--accent, #e0a458); background: rgba(224, 164, 88, .16); }
.humeur-case:focus-visible { outline: 2px solid var(--accent, #e0a458); outline-offset: 2px; }

/* =====================================================================
   Recherche sur la carte
   ===================================================================== */

/* Elle se pose PAR-DESSUS la carte, pas au-dessus d'elle : sur un
   telephone, chaque bandeau permanent mange la hauteur utile, et c'est
   la carte qu'on est venu voir. */
.recherche-carte {
    position: absolute;
    top: calc(env(safe-area-inset-top, 0px) + 62px);
    left: 10px; right: 10px;
    z-index: 900;
    max-width: 520px;
    margin: 0 auto;
    background: var(--fond-1, #12201c);
    border: 1px solid var(--bordure);
    border-radius: 14px;
    box-shadow: 0 10px 32px rgba(0, 0, 0, .5);
    overflow: hidden;
}
.recherche-carte[hidden] { display: none; }

.champ-recherche { display: flex; gap: 8px; padding: 9px 10px; align-items: center; }
.champ-recherche input {
    flex: 1;
    min-height: 40px;
    padding: 8px 11px;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: 9px;
    color: var(--texte);
    font: inherit;
}

.resultats-recherche { max-height: 46vh; overflow-y: auto; }
.resultats-recherche .aide { padding: 4px 14px 12px; margin: 0; }

.resultat-lieu {
    display: block;
    width: 100%;
    text-align: left;
    padding: 9px 14px;
    background: none;
    border: none;
    border-top: 1px solid var(--bordure);
    color: inherit;
    cursor: pointer;
}
.resultat-lieu:hover, .resultat-lieu:focus-visible { background: rgba(255, 255, 255, .06); }
.resultat-lieu .nom    { display: block; font-weight: 600; font-size: .92rem; }
.resultat-lieu .detail {
    display: block;
    font-size: .76rem;
    color: var(--texte-doux);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* =====================================================================
   Note et commentaire sur la fiche d'un lieu
   ===================================================================== */

.bloc-note {
    margin-top: 14px;
    padding: 11px 12px;
    border: 1px solid var(--bordure);
    border-radius: 12px;
    background: var(--fond-2, rgba(255, 255, 255, .03));
}
.bloc-note .note-etoiles { margin: 6px 0 8px; }
.bloc-note .etat-note    { font-size: .76rem; }

.bloc-note textarea {
    width: 100%;
    min-height: 46px;
    padding: 8px 10px;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: 9px;
    color: var(--texte);
    font: inherit;
    font-size: .86rem;
    line-height: 1.45;
    resize: vertical;
}

/* =====================================================================
   Partenaires
   ===================================================================== */

/* Le marqueur est volontairement discret : plus petit qu'un lieu, sous
   lui dans l'empilement. C'est un complement au patrimoine, pas le
   sujet — et c'est ce que le dessin doit dire avant les mots. */
.marqueur-partenaire {
    width: 30px; height: 30px;
    border-radius: 8px;
    background: var(--fond-1, #14231f);
    border: 2px solid var(--accent, #e0a458);
    display: flex; align-items: center; justify-content: center;
    font-size: 13px;
    color: var(--accent, #e0a458);
    box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
    overflow: hidden;
}
.marqueur-partenaire img { width: 100%; height: 100%; object-fit: cover; }

.popup-partenaire .leaflet-popup-content { margin: 0; width: 250px !important; }
.popup-partenaire .leaflet-popup-content-wrapper { padding: 0; overflow: hidden; border-radius: 12px; }

.fiche-partenaire { font-size: .84rem; }

/* La photo d'abord : on reconnait une devanture avant de lire une
   enseigne, surtout en marchant. */
.photo-partenaire {
    height: 118px;
    background-size: cover;
    background-position: center;
}
.corps-partenaire { padding: 9px 11px 11px; }
.corps-partenaire strong { display: block; font-size: .95rem; }
.corps-partenaire .pastille { margin-top: 3px; display: inline-block; }
.corps-partenaire p { margin: 6px 0 0; line-height: 1.45; }
.corps-partenaire .meta { margin-top: 5px; font-size: .76rem; }

/* Le partenariat est ecrit, pas devine : le promeneur a le droit de
   savoir pourquoi ce commerce-la lui est montre. */
.mention-partenaire {
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid var(--bordure);
    font-size: .68rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--texte-doux);
}

.partenaires-itineraire { margin-top: 12px; }
.partenaires-itineraire[hidden] { display: none; }
.partenaires-itineraire h4 {
    margin: 10px 0 4px;
    font-size: .74rem;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--texte-doux);
}
.liste-partenaires { list-style: none; margin: 0; padding: 0; }
.liste-partenaires li {
    padding: 5px 0;
    border-bottom: 1px solid var(--bordure);
    font-size: .84rem;
}
.liste-partenaires li:last-child { border-bottom: none; }

/* L'avatar dans l'onglet du profil : il remplace l'émoji « 👤 », et doit
   donc occuper la même place qu'un caractère, sans décaler la ligne. */
.avatar-onglet {
    display: inline-block;
    vertical-align: -5px;
    margin-right: 2px;
}
.barre-nav .ico .avatar-onglet {
    vertical-align: middle;
    margin: 0;
    width: 22px; height: 22px;
}

/* La photo du lieu, en fond du récit.
   Elle remplace une seconde boîte qui n'affichait guère que le nom :
   l'information utile — à quoi ressemble l'endroit — passe SOUS le
   texte au lieu de le recouvrir. */
.liseuse-fond {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    border-radius: 28px 28px 0 0;
    pointer-events: none;
    z-index: 0;

    /* Trois traitements, et les trois sont nécessaires. Une photo à
       pleine intensité rend un texte illisible dès qu'elle porte du clair
       et du sombre : on la désature pour qu'aucune couleur ne concurrence
       le texte, on l'assombrit, et on l'efface presque. Ce qu'il en reste
       suffit à reconnaître le lieu, pas à gêner la lecture. */
    opacity: .13;
    filter: grayscale(.7) brightness(.75) contrast(.9);
}
.liseuse-fond[hidden] { display: none; }

/* Un dégradé par-dessus : le texte commence en haut, là où il a le plus
   besoin d'un fond calme, et la photo respire vers le bas. */
.liseuse-cadre::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 28px 28px 0 0;
    background: linear-gradient(to bottom,
                rgba(14, 26, 23, .55) 0%,
                rgba(14, 26, 23, .25) 45%,
                rgba(14, 26, 23, .05) 100%);
    pointer-events: none;
    z-index: 0;
}

/* Le contenu repasse devant les deux couches. */
.liseuse-tete, .liseuse-page, .liseuse-pied { position: relative; z-index: 1; }

/* =====================================================================
   Code promotionnel
   ===================================================================== */

/* Replié par défaut : la majorité des acheteurs n'a pas de code, et un
   champ vide en évidence donne l'impression désagréable de payer plus
   cher que quelqu'un d'autre. */
.promo-bloc { margin-top: 14px; }
.promo-bloc summary {
    cursor: pointer;
    font-size: .86rem;
    color: var(--texte-doux);
    padding: 4px 0;
}
.promo-bloc summary:hover { color: var(--accent); }

.promo-saisie { display: flex; gap: 8px; margin-top: 8px; }
.promo-saisie input {
    flex: 1;
    min-height: 40px;
    padding: 8px 11px;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: 9px;
    color: var(--texte);
    font: inherit;
    text-transform: uppercase;
    letter-spacing: .06em;
}

.promo-accepte { color: var(--succes); }
.promo-refuse  { color: var(--alerte, #e0a458); }

/* Le prix d'avant, barré à côté du nouveau. Sans lui, on ne voit pas
   ce que le code a changé. */
.promo-barre {
    font-size: .82rem;
    font-weight: 400;
    color: var(--texte-doux);
    margin-left: 6px;
}

/* L'adresse de l'APK, à recopier sur un téléphone : elle doit pouvoir
   être lue caractère par caractère, donc se couper n'importe où. */
.adresse-apk {
    display: block;
    padding: 9px 11px;
    background: var(--fond);
    border: 1px solid var(--bordure);
    border-radius: 9px;
    font-size: .8rem;
    line-height: 1.5;
    word-break: break-all;
}

/* La bascule hors ligne dans la barre de la carte.
   L'en-tête disparaît sur mobile : c'est là, en marchant, qu'on veut
   couper le réseau pour épargner la batterie. */
.bascule-reseau-carte {
    position: relative;
}
.bascule-reseau-carte .point {
    width: 12px; height: 12px;
    border-radius: 50%;
    background: var(--succes, #4caf7d);
    box-shadow: 0 0 0 3px rgba(76, 175, 125, .22);
    transition: background .2s, box-shadow .2s;
}
/* Hors ligne subi — le réseau est tombé — et hors ligne choisi ne se
   disent pas pareil : l'un est un état, l'autre une décision. */
.hors-ligne .bascule-reseau-carte .point {
    background: var(--accent, #e0a458);
    box-shadow: 0 0 0 3px rgba(224, 164, 88, .22);
}
.hors-ligne-choisi .bascule-reseau-carte .point {
    background: var(--texte-doux, #8a9a94);
    box-shadow: 0 0 0 3px rgba(138, 154, 148, .2);
}

/* Une tuile d'ancêtre, étirée faute de mieux : elle est floue, et il
   vaut mieux que cela se voie. Une carte nette qui ment sur son niveau
   de détail serait pire qu'une carte visiblement approximative. */
.tuile-approchee { opacity: .82; filter: saturate(.85); }

