/* France Incendie — © 2022-2026 E.repare · TOUS DROITS RÉSERVÉS. Voir /LICENSE.
   Feuille de style de la carte (/), sortie d'index.html le 13/10/2026 (audit MO-40, étape 2) : ces 325 Ko repartaient
   avec la page à chaque visite et à chaque déploiement. Fichier à part, adressé par l'empreinte de son contenu
   (style.css?v=…, scripts/versionner-scripts.mjs) : le service worker et le navigateur le gardent tant qu'il ne change pas.
   Chargée à la MÊME place que l'ancien bloc de style en ligne (après les feuilles de Leaflet) : l'ordre de la cascade est inchangé. */
  :root{
    --bg:#eef1f6; --panel:#ffffff; --panel2:#f5f7fb; --line:#e3e8f0;
    --txt:#18202e; --muted:#5b6473; --fire:#ea4a12; --fire2:#f26b1f; --ember:#ffb020;
    /* Contrastes (13/10/2026, audit MO-23) : orange en TEXTE et aplat orange sous texte blanc, 4,5:1 au moins. */
    --fire-txt:#c2410c; --fire-on:#c2410c;
    --now-tint:#fff6f1; --gold-tint:#fffaf0; /* teintes hautes de cards (crème clair en thème clair) */
    --danger:#e11d1d; --warn:#e08a00; --ok:#16a34a; --accent:#1f7ae0; --wind:#2b8fd6;
    --shadow:0 6px 22px rgba(20,30,50,.10); --shadow-lg:0 12px 40px rgba(20,30,50,.16);
    color-scheme:light;
  }
  /* THÈME SOMBRE (option Réglages). data-theme="dark" force le sombre ; data-theme="light" force le clair ;
     sans attribut = AUTO (suit le système via prefers-color-scheme). Les accents (fire/danger/ok…) restent. */
  :root[data-theme="dark"]{
    --bg:#0b0f14; --panel:#151b26; --panel2:#0f141c; --line:#28323f;
    --txt:#e7edf5; --muted:#93a0b4; --accent:#4a9bec; --wind:#4aa8e6; --now-tint:rgba(234,74,18,.16); --gold-tint:rgba(224,176,0,.15);
    --fire-txt:#f26b1f;
    --shadow:0 6px 22px rgba(0,0,0,.5); --shadow-lg:0 12px 40px rgba(0,0,0,.6);
    color-scheme:dark;
  }
  @media (prefers-color-scheme:dark) and (max-width:1099px){:root:not([data-theme="light"]) #sheet.collapsed.mini{background:rgba(22,26,34,.72);border-top-color:rgba(255,255,255,.14);box-shadow:0 -4px 20px rgba(0,0,0,.25)}
    :root:not([data-theme="light"]) #sheet.collapsed.mini #grip::before{background:rgba(235,235,245,.32)}}
  @media (max-width:1099px){:root[data-theme="dark"] #sheet.collapsed.mini{background:rgba(22,26,34,.72);border-top-color:rgba(255,255,255,.14);box-shadow:0 -4px 20px rgba(0,0,0,.25)}
    :root[data-theme="dark"] #sheet.collapsed.mini #grip::before{background:rgba(235,235,245,.32)}}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
    --bg:#0b0f14; --panel:#151b26; --panel2:#0f141c; --line:#28323f;
    --txt:#e7edf5; --muted:#93a0b4; --accent:#4a9bec; --wind:#4aa8e6; --now-tint:rgba(234,74,18,.16); --gold-tint:rgba(224,176,0,.15);
    --fire-txt:#f26b1f;
    --shadow:0 6px 22px rgba(0,0,0,.5); --shadow-lg:0 12px 40px rgba(0,0,0,.6);
    color-scheme:dark;
  }}
  *{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
  html,body{margin:0;height:100%;background:var(--bg);color:var(--txt);
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,system-ui,sans-serif;
    /* ⚠️ `overflow:hidden` empêche le défilement PAR L'UTILISATEUR mais laisse l'élément être un conteneur de
       défilement que le SCRIPT peut déplacer : un scrollIntoView() faisait défiler le <body> de ~225 px, ce qui
       remontait #app et découvrait une grande bande de fond sous le panneau (constaté 2026-07-28, « gros blanc
       en bas »). `overflow:clip` ne crée AUCUN conteneur de défilement → le body devient indéplaçable.
       `hidden` est conservé juste avant comme repli pour les navigateurs sans support de `clip`. */
    -webkit-font-smoothing:antialiased;overflow:hidden;overflow:clip}
  #app{display:flex;flex-direction:column;height:100dvh;position:relative}
  :root{--fv-ad-top:0px;--fv-ad-bottom:0px;--fv-height:calc(100dvh - var(--fv-ad-top) - var(--fv-ad-bottom))}
  /* La carte prend la place libre autour d’une annonce ancrée Google. L’annonce et sa fermeture restent intactes. */
  #app[data-publicite-ancree]{position:fixed;left:0;right:0;top:var(--fv-ad-top);height:var(--fv-height);overflow:clip}
  /* Bandeau verre dépoli, quasi-opaque pour rester lisible sur satellite (contrasté + pro) */
  header{position:absolute;top:0;left:0;right:0;display:flex;flex-wrap:nowrap;align-items:center;gap:11px;padding:calc(env(safe-area-inset-top) + 10px) 16px 10px;
    /* Header OPAQUE (plus de backdrop-filter) : le flou verre au-dessus de la carte animée + du calque canvas
       provoquait un ARTEFACT rectangle noir sur certains Android (compositing GPU). Fond plein = 0 artefact,
       rendu quasi identique (il était déjà opaque à 94 %) et plus lisible sur satellite. */
    background:linear-gradient(180deg,#ffffff,#f4f7fb);
    /* ⚠️ PAS de translateZ/will-change sur le header : la promotion en couche GPU le faisait FLASHER NOIR
       (rectangle sombre) sur certains Android pendant le zoom. Opaque + NON promu = repaint normal (cheap
       pour une barre) et artefact IMPOSSIBLE (ni backdrop-filter ni couche à glitcher). */
    border-bottom:1px solid rgba(20,30,50,.10);z-index:1200;box-shadow:0 3px 16px rgba(20,30,50,.13)}
  header h1{color:#141a24}
  /* Header theme-aware en SOMBRE (fond plein opaque, PAS de backdrop-filter → aucun artefact Android). */
  :root[data-theme="dark"] header{background:linear-gradient(180deg,#141a24,#0f141c);border-bottom-color:rgba(255,255,255,.08);box-shadow:0 3px 16px rgba(0,0,0,.5)}
  :root[data-theme="dark"] header h1{color:#e7edf5}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) header{background:linear-gradient(180deg,#141a24,#0f141c);border-bottom-color:rgba(255,255,255,.08);box-shadow:0 3px 16px rgba(0,0,0,.5)}:root:not([data-theme="light"]) header h1{color:#e7edf5}}
  /* Titre flexible + tronqué : les traductions plus longues (ES) ne doivent PAS faire grandir le header. */
  header .htitle{min-width:0;flex:1 1 auto}
  /* Complément du <h1> destiné aux moteurs et aux lecteurs d'écran : le titre visible
     (« France Incendie ») ne dit ni ce que fait la page ni où. Ce n'est PAS du texte
     masqué trompeur · il décrit exactement le contenu réel, et reste lu à voix haute. */
  .h1kw{font-size:.7em;font-weight:600;color:var(--muted);letter-spacing:0}
.h1sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
  header h1,header .sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* Le complément SEO/a11y « · carte des incendies en France en direct » (.h1kw) ne doit JAMAIS apparaître
     TRONQUÉ (« · carte des incend… » coupé = laid). Sous 900px on le rend invisible à l'oeil mais TOUJOURS
     présent pour les moteurs et lu par les lecteurs d'écran (sr-only) ; sur desktop large il s'affiche en entier. */
  @media (max-width:900px){.h1kw{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}}
  header .live{flex:0 0 auto;white-space:nowrap}
  header .logo{width:35px;height:35px;border-radius:11px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;
    background:linear-gradient(155deg,#3a1608,#160805);box-shadow:0 4px 14px rgba(234,74,18,.42),inset 0 1px 0 rgba(255,180,80,.28)}
  header .logo svg{filter:drop-shadow(0 0 4px rgba(255,120,30,.75));transform-origin:center bottom;animation:flick 2.4s ease-in-out infinite}
  @keyframes flick{0%,100%{transform:scale(1) rotate(0)}30%{transform:scale(1.07) rotate(-1.5deg)}60%{transform:scale(.98) rotate(1deg)}}
  header h1{font-size:16px;margin:0;font-weight:800;line-height:1.05;letter-spacing:-.01em}
  header .sub{font-size:11.5px;color:var(--muted);margin-top:2px}
  .langwrap{margin-left:auto;position:relative;flex:0 0 auto}
  #langBtn{background:var(--panel2);border:1px solid var(--line);width:34px;height:34px;border-radius:10px;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1;padding:0}
  #langBtn:active{transform:scale(.94)}
  /* Drapeaux SVG (cross-OS) : les emojis drapeaux ne s'affichent pas sous Windows. */
  .lf{display:inline-flex;align-items:center}
  .fx-flag{width:20px;height:14px;border-radius:2px;display:inline-block;vertical-align:middle;box-shadow:0 0 0 .5px rgba(0,0,0,.25);flex:none}
  #langMenu .fx-flag{width:18px;height:12px}
  .langmenu{position:absolute;top:40px;right:0;z-index:1300;background:var(--panel);border:1px solid var(--line);border-radius:12px;
    box-shadow:0 10px 30px rgba(20,30,50,.25);padding:5px;display:none;min-width:150px}
  .langmenu.open{display:block}
  .langmenu button{display:flex;align-items:center;gap:9px;width:100%;background:none;border:0;color:var(--txt);font-size:13.5px;font-weight:600;
    text-align:left;padding:9px 11px;border-radius:8px;cursor:pointer}
  .langmenu button span{font-size:16px}
  .langmenu button:hover{background:var(--panel2)}
  .langmenu button.on{background:var(--panel2);color:var(--accent)}
  #hdrRefresh{background:var(--panel2);border:1px solid var(--line);color:var(--txt);width:34px;height:34px;border-radius:10px;font-size:17px;cursor:pointer;flex:0 0 auto;display:flex;align-items:center;justify-content:center;line-height:1}
  #hdrRefresh:active{transform:scale(.94)}
  #hdrRefresh .ic{display:inline-block;line-height:1}
  #hdrRefresh.spin{pointer-events:none;opacity:.75}
  #hdrRefresh.spin .ic{animation:hspin .8s linear infinite}
  /* Écran de chargement (patience propre pendant que les données arrivent) */
  #loading{position:absolute;inset:0;z-index:1500;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;
    background:radial-gradient(120% 80% at 50% 40%,#141a24,#0a0c11);color:#f2f4f8;transition:opacity .5s ease;padding:24px;text-align:center}
  #loading.hidden{opacity:0;pointer-events:none}
  /* Finale puis fondu enchaînés par le navigateur (08/10/2026) : les deux minuteurs d'avant (0,85 s puis 0,6 s)
     attendaient le fil principal, occupé à dessiner la carte ; mesuré en production, l'écran « maîtrisé » restait
     8 s et le fondu durait 8 s de plus. Le délai de transition, lui, est tenu par le compositeur. */
  #loading.done.hidden{transition:opacity .5s ease .85s;will-change:opacity}
  /* Visite de retour (14/10/2026) : crédits déjà vus, finale courte avant le fondu, comme la carte des inondations. */
  #loading.done.hidden.retour{transition-delay:.3s}
  /* Loader « intervention aérienne » : la flamme (logo) BRÛLE en boucle, les bombardiers larguent
     l'eau à leur passage ; l'EXTINCTION se joue quand l'app est prête (#loading.done). Classes/keyframes
     préfixées ld- pour ne rien croiser avec la carte. */
  #loading .ld-scene{position:relative;width:240px;height:190px;margin-bottom:2px}
  #loading .ld-scenefx{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
  #loading .ld-ring{transform-origin:120px 150px;fill:none;stroke:#12b8d8;stroke-width:2.5}
  #loading .ld-ring.a{animation:ldring 2.2s ease-out infinite}
  #loading .ld-ring.b{animation:ldring 2.2s ease-out infinite;animation-delay:1.1s}
  @keyframes ldring{0%{r:16px;opacity:.85}80%{opacity:0}100%{r:74px;opacity:0}}
  #loading .ld-plane{position:absolute;left:0;top:0;width:26px;height:26px;filter:drop-shadow(0 1px 2px rgba(0,0,0,.55));animation:ldfly1 2.6s linear infinite;will-change:transform}
  #loading .ld-plane svg{display:block;transform:rotate(90deg);transform-origin:50% 50%;animation:ldbank 2.6s ease-in-out infinite}
  #loading .ld-p2 svg{animation-delay:1.3s}
  /* petit coup d'aile (bank) synchronisé sur le largage : l'avion s'incline en lâchant l'eau puis se redresse */
  @keyframes ldbank{0%,42%{transform:rotate(90deg)}54%{transform:rotate(71deg)}66%{transform:rotate(100deg)}78%,100%{transform:rotate(90deg)}}
  #loading .ld-p1{animation-name:ldfly1}
  #loading .ld-p2{animation-name:ldfly2;width:24px;height:24px;animation-delay:1.3s}
  /* FLUIDITÉ DE L'OUVERTURE (08/10/2026, fondateur : « le changement n'est pas fluide à l'ouverture sur PC ») : les
     avions suivaient leur arc par offset-path, animation que Chrome calcule sur le FIL PRINCIPAL ; or pendant
     l'écran d'ouverture ce fil exécute le chargement (plusieurs secondes d'un seul tenant sur un portable) et les
     avions restaient figés. Même arc, même vitesse constante, même orientation le long de la courbe, mais en
     « transform » (24 étapes calculées sur la courbe) : le compositeur l'anime seul, fil principal occupé ou non. */
  @keyframes ldfly1{0%{transform:translate(-30.0px,120.0px) translate(-50%,-50%) rotate(-37.7deg)}4.17%{transform:translate(-19.1px,111.8px) translate(-50%,-50%) rotate(-35.6deg)}8.33%{transform:translate(-7.8px,104.1px) translate(-50%,-50%) rotate(-33.4deg)}12.5%{transform:translate(3.8px,96.8px) translate(-50%,-50%) rotate(-30.9deg)}16.67%{transform:translate(15.6px,90.1px) translate(-50%,-50%) rotate(-28.3deg)}20.83%{transform:translate(27.8px,83.9px) translate(-50%,-50%) rotate(-25.4deg)}25%{transform:translate(40.3px,78.4px) translate(-50%,-50%) rotate(-22.3deg)}29.17%{transform:translate(53.0px,73.6px) translate(-50%,-50%) rotate(-19.0deg)}33.33%{transform:translate(66.1px,69.5px) translate(-50%,-50%) rotate(-15.5deg)}37.5%{transform:translate(79.3px,66.3px) translate(-50%,-50%) rotate(-11.8deg)}41.67%{transform:translate(92.8px,63.9px) translate(-50%,-50%) rotate(-8.0deg)}45.83%{transform:translate(106.4px,62.5px) translate(-50%,-50%) rotate(-4.0deg)}50%{transform:translate(120.0px,62.0px) translate(-50%,-50%) rotate(0.0deg)}54.17%{transform:translate(133.6px,62.5px) translate(-50%,-50%) rotate(4.0deg)}58.33%{transform:translate(147.2px,63.9px) translate(-50%,-50%) rotate(8.0deg)}62.5%{transform:translate(160.7px,66.3px) translate(-50%,-50%) rotate(11.8deg)}66.67%{transform:translate(173.9px,69.5px) translate(-50%,-50%) rotate(15.5deg)}70.83%{transform:translate(187.0px,73.6px) translate(-50%,-50%) rotate(19.0deg)}75%{transform:translate(199.7px,78.4px) translate(-50%,-50%) rotate(22.3deg)}79.17%{transform:translate(212.2px,83.9px) translate(-50%,-50%) rotate(25.4deg)}83.33%{transform:translate(224.4px,90.1px) translate(-50%,-50%) rotate(28.3deg)}87.5%{transform:translate(236.2px,96.8px) translate(-50%,-50%) rotate(30.9deg)}91.67%{transform:translate(247.8px,104.1px) translate(-50%,-50%) rotate(33.4deg)}95.83%{transform:translate(259.1px,111.8px) translate(-50%,-50%) rotate(35.6deg)}100%{transform:translate(270.0px,120.0px) translate(-50%,-50%) rotate(37.7deg)}}
  @keyframes ldfly2{0%{transform:translate(270.0px,130.0px) translate(-50%,-50%) rotate(-144.2deg)}4.17%{transform:translate(258.9px,122.3px) translate(-50%,-50%) rotate(-146.3deg)}8.33%{transform:translate(247.5px,115.0px) translate(-50%,-50%) rotate(-148.5deg)}12.5%{transform:translate(235.9px,108.2px) translate(-50%,-50%) rotate(-150.9deg)}16.67%{transform:translate(223.9px,101.9px) translate(-50%,-50%) rotate(-153.5deg)}20.83%{transform:translate(211.7px,96.2px) translate(-50%,-50%) rotate(-156.2deg)}25%{transform:translate(199.2px,91.0px) translate(-50%,-50%) rotate(-159.2deg)}29.17%{transform:translate(186.4px,86.6px) translate(-50%,-50%) rotate(-162.3deg)}33.33%{transform:translate(173.5px,82.9px) translate(-50%,-50%) rotate(-165.6deg)}37.5%{transform:translate(160.3px,79.9px) translate(-50%,-50%) rotate(-169.1deg)}41.67%{transform:translate(146.9px,77.7px) translate(-50%,-50%) rotate(-172.6deg)}45.83%{transform:translate(133.5px,76.4px) translate(-50%,-50%) rotate(-176.3deg)}50%{transform:translate(120.0px,76.0px) translate(-50%,-50%) rotate(-180.0deg)}54.17%{transform:translate(106.5px,76.4px) translate(-50%,-50%) rotate(-183.7deg)}58.33%{transform:translate(93.1px,77.7px) translate(-50%,-50%) rotate(-187.4deg)}62.5%{transform:translate(79.7px,79.9px) translate(-50%,-50%) rotate(-190.9deg)}66.67%{transform:translate(66.5px,82.9px) translate(-50%,-50%) rotate(-194.4deg)}70.83%{transform:translate(53.6px,86.6px) translate(-50%,-50%) rotate(-197.7deg)}75%{transform:translate(40.8px,91.0px) translate(-50%,-50%) rotate(-200.8deg)}79.17%{transform:translate(28.3px,96.2px) translate(-50%,-50%) rotate(-203.8deg)}83.33%{transform:translate(16.1px,101.9px) translate(-50%,-50%) rotate(-206.5deg)}87.5%{transform:translate(4.1px,108.2px) translate(-50%,-50%) rotate(-209.1deg)}91.67%{transform:translate(-7.5px,115.0px) translate(-50%,-50%) rotate(-211.5deg)}95.83%{transform:translate(-18.9px,122.3px) translate(-50%,-50%) rotate(-213.7deg)}100%{transform:translate(-30.0px,130.0px) translate(-50%,-50%) rotate(-215.8deg)}}
  #loading .ld-trail i{position:absolute;left:0;top:0;border-radius:50%;background:#12b8d8;box-shadow:0 0 6px rgba(18,184,216,.75);animation:ldfly1 2.6s linear infinite;will-change:transform}
  #loading .ld-trail.t1 i{animation-name:ldfly1}
  #loading .ld-trail.t2 i{animation-name:ldfly2}
  #loading .ld-trail i:nth-child(1){width:6px;height:6px;opacity:.75}
  #loading .ld-trail i:nth-child(2){width:5px;height:5px;opacity:.55}
  #loading .ld-trail i:nth-child(3){width:4px;height:4px;opacity:.38}
  #loading .ld-trail i:nth-child(4){width:3.5px;height:3.5px;opacity:.24}
  #loading .ld-trail i:nth-child(5){width:3px;height:3px;opacity:.13}
  #loading .ld-trail.t1 i:nth-child(1){animation-delay:.06s}#loading .ld-trail.t1 i:nth-child(2){animation-delay:.12s}#loading .ld-trail.t1 i:nth-child(3){animation-delay:.18s}#loading .ld-trail.t1 i:nth-child(4){animation-delay:.24s}#loading .ld-trail.t1 i:nth-child(5){animation-delay:.30s}
  #loading .ld-trail.t2 i:nth-child(1){animation-delay:1.36s}#loading .ld-trail.t2 i:nth-child(2){animation-delay:1.42s}#loading .ld-trail.t2 i:nth-child(3){animation-delay:1.48s}#loading .ld-trail.t2 i:nth-child(4){animation-delay:1.54s}#loading .ld-trail.t2 i:nth-child(5){animation-delay:1.60s}
  #loading .ld-flame{position:absolute;left:120px;bottom:26px;transform:translateX(-50%);transform-origin:center bottom;filter:drop-shadow(0 0 24px rgba(255,110,25,.85));animation:ldflame .9s ease-in-out infinite}
  #loading .ld-flame svg{display:block}
  #loading .ld-flame::before{content:"";position:absolute;left:50%;top:54%;width:104px;height:104px;transform:translate(-50%,-50%);border-radius:50%;background:radial-gradient(circle,rgba(255,140,45,.55),rgba(255,70,15,0) 68%);z-index:-1;animation:ldhalo .9s ease-in-out infinite}
  @keyframes ldflame{0%,100%{transform:translateX(-50%) scale(1) skewX(0)}25%{transform:translateX(-51%) scale(1.05,.97) skewX(2deg)}50%{transform:translateX(-49%) scale(.94,1.06) skewX(-1.5deg)}75%{transform:translateX(-50%) scale(1.03,.98)}}
  @keyframes ldhalo{0%,100%{opacity:.5}50%{opacity:.9}}
  #loading .ld-ember{position:absolute;left:120px;bottom:44px;width:5px;height:5px;border-radius:50%;background:radial-gradient(circle,#ffe9a8,#ff8a1f 70%);box-shadow:0 0 6px 1px rgba(255,150,45,.85);opacity:0;animation:ldember 1.9s ease-out infinite}
  #loading .ld-ember:nth-of-type(2){--dx:-12px}#loading .ld-ember:nth-of-type(3){--dx:11px;width:4px;height:4px;animation-delay:.7s}#loading .ld-ember:nth-of-type(4){--dx:-4px;width:6px;height:6px;animation-delay:1.3s}
  @keyframes ldember{0%{opacity:0;transform:translate(-50%,0) scale(.5)}12%{opacity:1}100%{opacity:0;transform:translate(calc(-50% + var(--dx,0px)),-52px) scale(.1)}}
  #loading .ld-drops{position:absolute;left:120px;width:50px;transform:translateX(-50%);pointer-events:none}
  #loading .ld-d1{top:74px}#loading .ld-d2{top:86px}
  #loading .ld-drops i{position:absolute;top:0;width:7px;height:9px;border-radius:50% 50% 50% 50%/58% 58% 42% 42%;background:linear-gradient(180deg,#eaf7fe,#4bb8e0 60%,#1284b0);box-shadow:0 0 4px rgba(120,200,240,.7);opacity:0;transform-origin:center bottom;animation:lddrop 2.6s ease-in infinite}
  #loading .ld-drops i:nth-child(1){left:4%;--dx:-9px;--rot:-15deg;--fall:90px}#loading .ld-drops i:nth-child(2){left:16%;--dx:7px;--rot:11deg;--fall:96px}#loading .ld-drops i:nth-child(3){left:28%;--dx:-4px;--rot:-8deg;--fall:86px}#loading .ld-drops i:nth-child(4){left:40%;--dx:11px;--rot:17deg;--fall:98px}#loading .ld-drops i:nth-child(5){left:52%;--dx:-11px;--rot:-19deg;--fall:91px}#loading .ld-drops i:nth-child(6){left:64%;--dx:4px;--rot:7deg;--fall:94px}#loading .ld-drops i:nth-child(7){left:76%;--dx:-6px;--rot:-10deg;--fall:88px}#loading .ld-drops i:nth-child(8){left:88%;--dx:9px;--rot:14deg;--fall:95px}
  /* Léger décalage de release par goutte À L'INTÉRIEUR de chaque vague → largage naturel, sans casser la synchro avion (vague 1 ≈ 0s, vague 2 ≈ 1.3s). */
  #loading .ld-d1 i:nth-child(2n){animation-delay:.10s}#loading .ld-d1 i:nth-child(3n){animation-delay:.20s}#loading .ld-d1 i:nth-child(5n){animation-delay:.06s}
  #loading .ld-d2 i{animation-delay:1.3s}#loading .ld-d2 i:nth-child(2n){animation-delay:1.4s}#loading .ld-d2 i:nth-child(3n){animation-delay:1.5s}#loading .ld-d2 i:nth-child(5n){animation-delay:1.36s}
  /* chute → impact qui s'écrase → flaque qui s'étale et s'évapore (transform-origin bottom : la flaque reste au sol) */
  @keyframes lddrop{
    0%,44%{opacity:0;transform:translate(0,-6px) rotate(0) scale(.7,.7)}
    48%{opacity:1;transform:translate(calc(var(--dx,0px)*.1),0) rotate(calc(var(--rot,0deg)*.3)) scale(.9,1)}
    60%{opacity:1;transform:translate(calc(var(--dx,0px)*.55),calc(var(--fall,58px)*.8)) rotate(calc(var(--rot,0deg)*.6)) scale(.82,1.18)}
    67%{opacity:.95;transform:translate(var(--dx,0px),var(--fall,58px)) rotate(0) scale(1.7,.42)}
    78%{opacity:0;transform:translate(var(--dx,0px),var(--fall,58px)) rotate(0) scale(2.6,.22)}
    100%{opacity:0}
  }
  #loading .ld-steam{position:absolute;left:120px;bottom:40px;width:66px;height:66px;transform:translate(-50%,0);border-radius:50%;opacity:0;filter:blur(5px);background:radial-gradient(circle,rgba(255,255,255,.95),rgba(214,236,248,.42) 50%,rgba(214,236,248,0) 72%);animation:ldsteam 2.6s ease-out infinite}
  #loading .ld-steam.s2{animation-delay:1.3s}
  /* la vapeur naît PILE quand l'eau s'écrase (≈67 %) et monte en s'évasant, bien visible sur la flamme */
  @keyframes ldsteam{0%,58%{opacity:0;transform:translate(-50%,0) scale(.35)}67%{opacity:.95;transform:translate(-50%,-14px) scale(1.05)}80%{opacity:.55;transform:translate(-50%,-32px) scale(1.7)}92%{opacity:0;transform:translate(-50%,-48px) scale(2.2)}100%{opacity:0}}
  #loading .ld-final-smoke{position:absolute;left:120px;bottom:30px;width:60px;height:60px;transform:translate(-50%,0);border-radius:50%;opacity:0;filter:blur(6px);background:radial-gradient(circle,rgba(200,208,220,.7),rgba(150,160,178,.2) 55%,rgba(150,160,178,0) 74%)}
  /* Extinction quand l'app est prête (#loading.done) */
  #loading.done .ld-flame,#loading.done .ld-ember{animation:ldquench .8s ease-in forwards}
  #loading.done .ld-plane,#loading.done .ld-trail i,#loading.done .ld-drops i,#loading.done .ld-steam,#loading.done .ld-ring{animation:none;opacity:0;transition:opacity .3s}
  #loading.done .ld-final-smoke{animation:ldfsmoke 1.1s ease-out forwards}
  @keyframes ldquench{0%{transform:translateX(-50%) scale(1)}20%{transform:translateX(-50%) scale(1.06)}100%{transform:translateX(-50%) scale(.04);opacity:0}}
  @keyframes ldfsmoke{0%{opacity:0;transform:translate(-50%,4px) scale(.5)}40%{opacity:.8;transform:translate(-50%,-8px) scale(1.1)}100%{opacity:0;transform:translate(-50%,-38px) scale(1.6)}}
  @media (prefers-reduced-motion:reduce){#loading .ld-plane,#loading .ld-trail i,#loading .ld-ring,#loading .ld-ember,#loading .ld-drops i,#loading .ld-steam,#loading .ld-flame,#loading .ld-flame::before{animation:none}#loading .ld-plane,#loading .ld-trail i,#loading .ld-drops i{opacity:0}}
  #loading .ld-t{font-size:15.5px;font-weight:800;letter-spacing:-.01em;margin-top:4px}
  #loading .ld-s{font-size:12px;color:#8a92a6}
  #loading .ld-bar{width:180px;max-width:60vw;height:4px;border-radius:4px;background:rgba(255,255,255,.1);overflow:hidden;margin-top:8px}
  #loading .ld-bar i{display:block;height:100%;width:40%;border-radius:4px;background:linear-gradient(90deg,#ff8a3d,#ff3b30);animation:ldslide 1.1s ease-in-out infinite}
  @keyframes ldslide{0%{transform:translateX(-110%)}100%{transform:translateX(360%)}}
  #loading .ld-credit{position:absolute;bottom:max(calc(env(safe-area-inset-bottom, 0px) + 18px), 54px);left:0;right:0;display:flex;flex-direction:column;align-items:center;gap:5px;padding:0 20px}
  #loading .ld-free{font-size:12px;font-weight:700;color:#cdd4e0;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.12);border-radius:20px;padding:6px 14px}
  #loading .ld-by{font-size:12.5px;color:#aeb6c6;margin-top:4px}
  #loading .ld-by b{color:#fff}
  #loading .ld-idea{font-size:11.5px;color:#c2c9d6;margin-top:2px}
  #loading .ld-fx{font-size:11px;color:#7f8798;letter-spacing:.3px;margin-top:2px}
  #loading .ld-fx b{color:#ff8a3d}
  #loading .ld-credit a{color:inherit;text-decoration:underline;text-underline-offset:2px}
  #loading .ld-by a b{color:#fff}
  #loading .ld-logos{display:flex;justify-content:center;gap:30px;margin-top:11px}
  #loading .ld-logos img{width:40px;height:40px;border-radius:50%;object-fit:cover;background:var(--panel);border:1.5px solid rgba(255,255,255,.3);padding:2px}
  /* Mobile / écran court : crédits EN FLUX (plus en position:absolute) → ils ne chevauchent plus
     la scène ; le tout défile si besoin (jamais de recouvrement ni de coupe). */
  @media (max-width:560px), (max-height:760px){
    #loading{gap:6px;justify-content:safe center;overflow-y:auto;padding:24px 16px}
    #loading .ld-credit{position:static;bottom:auto;left:auto;right:auto;margin-top:16px}
    #loading .ld-logos{margin-top:8px}
    #loading .ld-logos img{width:34px;height:34px}
  }
  /* Attribution honnête (crédit éditeur + confiance) */
  .madeby{margin-top:10px;padding:11px 13px;background:var(--panel2);border:1px solid var(--line);border-radius:12px}
  .madeby p{margin:0;font-size:11.5px;line-height:1.5;color:var(--muted)}
  .madeby p+p{margin-top:6px}
  .madeby a{color:var(--accent);text-decoration:none;font-weight:700}
  .madeby a:hover{text-decoration:underline}
  .madeby .credits{font-size:11px;padding-top:7px;margin-top:7px;border-top:1px dashed var(--line)}
  .madeby-logos{display:flex;justify-content:space-between;align-items:center;margin-top:10px}
  .madeby-logos img{width:38px;height:38px;border-radius:50%;object-fit:cover;background:var(--panel);border:1px solid var(--line);padding:2px;display:block}
  /* Maillage SEO : index des pages département (crawlable, replié par défaut). */
  /* Maillage SEO départements/régions — refonte visuelle « chips » modernes (2026-08-15) */
  .dept-nav{margin-top:16px;border:1px solid var(--line);border-radius:16px;background:var(--panel2);overflow:hidden}
  .dept-nav summary{cursor:pointer;color:var(--txt);font-weight:800;font-size:13px;padding:13px 15px;list-style:none;display:flex;align-items:center;gap:9px;user-select:none;transition:background .15s}
  .dept-nav summary::-webkit-details-marker{display:none}
  .dept-nav summary::after{content:'';margin-left:auto;width:8px;height:8px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(45deg);transition:transform .22s;flex:0 0 auto}
  .dept-nav[open] summary::after{transform:rotate(-135deg)}
  .dept-nav summary:hover{background:rgba(127,127,127,.06)}
  .dept-nav-cat{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);padding:11px 15px 0}
  .dept-nav-links{display:flex;flex-wrap:wrap;gap:7px;padding:8px 15px}
  .dept-nav-links:last-child{padding-bottom:14px}
  .dept-nav-links a{color:var(--txt);text-decoration:none;white-space:nowrap;font-size:11.5px;font-weight:600;line-height:1;background:rgba(127,127,127,.09);border:1px solid var(--line);border-radius:999px;padding:6px 12px;transition:transform .14s,background .14s,color .14s,border-color .14s}
  .dept-nav-links a:hover{background:var(--accent);color:#fff;border-color:var(--accent);transform:translateY(-1px)}
  .discord-card{display:flex;align-items:center;gap:12px;background:#5865F2;border:0;border-radius:12px;padding:12px 14px;text-decoration:none;margin-bottom:10px;box-shadow:0 3px 12px rgba(88,101,242,.28)}
  .discord-card .dc-ico svg{width:26px;height:26px;fill:#fff;display:block}
  .discord-card .dc-txt{display:flex;flex-direction:column;flex:1;min-width:0}
  .discord-card .dc-txt b{color:#fff;font-size:13.5px;font-weight:800}
  .discord-card .dc-txt small{color:#e5e7ff;font-size:11.5px;margin-top:2px;line-height:1.35}
  .discord-card .dc-go{color:#fff;font-size:20px;font-weight:800;opacity:.85}
  .discord-card:active{filter:brightness(.93)}
  /* Historique des incendies (onglet Progression) */
  .hist-region{font-size:12px;font-weight:800;color:#b45309;margin:9px 0 4px;padding-bottom:3px;border-bottom:1.5px solid rgba(180,83,9,.25)}
  .hist-row{display:flex;align-items:center;gap:9px;padding:6px 2px;border-bottom:1px solid var(--line)}
  .hist-row:last-of-type{border-bottom:0}
  .hist-tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
  .hist-tx b{font-size:12.5px;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .hist-tx small{font-size:11px;color:var(--muted)}
  .hist-name{display:flex;align-items:center;gap:5px;min-width:0}
  .deptb{display:inline-flex;align-items:center;gap:3px;flex:0 0 auto;background:rgba(255,255,255,.06);border:1px solid var(--line);border-radius:999px;padding:1px 7px 1px 4px;font-size:10.5px;line-height:1.5}
  .deptb b{font-weight:800;color:var(--txt)}
  .deptb-sh{flex:0 0 auto;filter:drop-shadow(0 1px 1px rgba(0,0,0,.4))}
  /* Section « Moyens de lutte » de l'onglet Comprendre + lien fiche dans la bulle d'un avion (17/09/2026). */
  .ml-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .ml-card{display:flex;flex-direction:column;gap:3px;padding:10px 11px;border-radius:11px;background:var(--panel2);border:1px solid var(--line);color:inherit;text-decoration:none;min-width:0}
  .ml-card b{font-size:13px}
  .ml-card span{font-size:11.5px;line-height:1.35;color:var(--muted)}
  .ml-card:hover,.ml-card:focus-visible{border-color:#ff7a1a}
  .ml-top{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}
  .ml-top a{font-size:12px;padding:5px 9px;border-radius:999px;border:1px solid var(--line);color:inherit;text-decoration:none;background:var(--panel2)}
  .ml-all{display:inline-block;text-decoration:none;padding:8px 14px;font-size:12.5px}
  /* RECHERCHE de lieu / d'incendie (onglet Situation, 20/09/2026). Pensée d'abord pour un
     téléphone de 390 px : une seule ligne, cible tactile de 42 px, résultats juste dessous.
     La liste n'a PAS de hauteur fixe en dur — elle se plafonne à 42 vh pour ne jamais recouvrir
     tout le panneau, et son propre défilement reste interne (le sheet garde le sien). */
  .fvs{margin:2px 0 8px}
  .fvs-bar{display:flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);
    border-radius:12px;padding:0 10px;height:42px;transition:border-color .15s,box-shadow .15s}
  .fvs-bar:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px rgba(31,122,224,.15)}
  .fvs-ic{flex:0 0 auto;color:var(--muted)}
  .fvs-bar input{flex:1;min-width:0;background:none;border:0;outline:none;color:var(--txt);
    font:inherit;font-size:14px;padding:0;-webkit-appearance:none;appearance:none}
  .fvs-bar input::-webkit-search-cancel-button{display:none}
  .fvs-bar input::placeholder{color:var(--muted);opacity:.9}
  .fvs-x[hidden]{display:none}   /* la règle suivante (display:flex) l'emportait sur [hidden] : ✕ visible champ vide (audit B-1) */
  .fvs-x{flex:0 0 auto;width:26px;height:26px;border-radius:50%;border:0;background:var(--line);
    color:var(--txt);font-size:15px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
  /* Saisie dans la recherche sur téléphone (audit MO-29) : les bannières flottantes s'effacent, la liste reste lisible. */
  @media (max-width:1099px){body.fv-saisie .sponsor-card,body.fv-saisie .fv-float,body.fv-saisie #installBanner,body.fv-saisie #renameBanner,body.fv-saisie #retroBanner,body.fv-saisie #galBanner,body.fv-saisie #donBanner,body.fv-saisie #featBanner,body.fv-saisie #petsBanner,body.fv-saisie #notifOptin,body.fv-saisie #petAnnonce{visibility:hidden;pointer-events:none}}
  .fvs-res{margin-top:6px;border:1px solid var(--line);border-radius:12px;background:var(--panel);
    box-shadow:var(--shadow);overflow:hidden auto;max-height:42vh;-webkit-overflow-scrolling:touch}
  .fvs-it{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:none;border:0;
    border-top:1px solid var(--line);padding:9px 11px;color:var(--txt);font:inherit;cursor:pointer}
  .fvs-it:first-child{border-top:0}
  .fvs-it:hover,.fvs-it.on{background:var(--panel2)}
  .fvs-it .ic{flex:0 0 26px;height:26px;border-radius:8px;display:flex;align-items:center;justify-content:center;
    background:var(--panel2);border:1px solid var(--line);color:var(--muted)}
  .fvs-it.feu .ic{color:var(--fire);border-color:rgba(234,74,18,.35)}
  .fvs-tx{min-width:0;flex:1}
  .fvs-tx b{display:block;font-size:13.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fvs-tx small{display:block;font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fvs-msg{padding:11px;font-size:12.5px;color:var(--muted)}
  /* Onglet Situation condensé (17/09/2026) : actions sur une ligne, blocs secondaires repliables. */
  .row.sit-actions{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px;margin:2px 0 4px}
  .row.sit-actions>button{width:100%;max-width:none;flex:none;margin:0;justify-content:center;padding:8px 6px;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* CARTES Situation / Progression (20/09/2026, fondateur : « gros pâté, pas pro, pas intuitif ») : une synthèse
     d'une ligne, une carte par feu (statut, chiffre clé, fraîcheur, vent local avec flèche, avions, communes sous le
     vent), deux KPI compacts. Même vocabulaire que .block / .kpi : fond --panel sur --panel2, bord --line, arrondis. */
  .block.now #txtNow,.block.next #txtNext{font-size:13.5px;line-height:1.5;margin:0}
  .spf-texte{margin:0;font-size:13.5px;line-height:1.55}
  .spf-synth{font-size:14px;font-weight:800;color:var(--txt);margin:0 0 9px;line-height:1.35}
  .spf-cartes{display:flex;flex-direction:column;gap:7px;min-width:0}
  .spf-carte{position:relative;display:block;padding:10px 30px 10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--panel);cursor:pointer;min-width:0;transition:border-color .15s,transform .1s}
  .spf-carte:hover,.spf-carte:focus-visible{border-color:var(--accent);outline:none}
  .spf-carte:active{transform:scale(.99)}
  .spf-carte.spf-vieux{opacity:.62}
  .spf-h{display:flex;justify-content:space-between;align-items:baseline;gap:8px;min-width:0}
  .spf-nom{font-size:13.5px;line-height:1.3;color:var(--txt);min-width:0;overflow-wrap:anywhere}
  .spf-chiffre{flex:0 0 auto;font-size:13px;font-weight:800;color:var(--fire);white-space:nowrap}
  .spf-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:5px}
  .spf-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;font-size:10.5px;font-weight:800;color:#fff;text-transform:uppercase;letter-spacing:.03em;line-height:1.6;white-space:nowrap}
  .spf-badge-n{background:var(--muted)}
  .spf-badge svg{width:11px;height:11px;vertical-align:0}
  .spf-frais{font-size:11px;color:var(--muted);white-space:nowrap}
  .spf-l{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:6px;font-size:12px;color:var(--txt);line-height:1.45}
  .spf-i{display:inline-flex;align-items:center;gap:5px;min-width:0;max-width:100%}
  .spf-i>svg{flex:0 0 auto;color:var(--muted);vertical-align:0}
  .spf-i small{color:var(--muted);font-size:11px}
  .spf-menace{color:var(--danger);font-weight:700}
  .spf-fleche{display:inline-block;width:13px;height:13px;flex:0 0 auto;color:var(--wind);transition:transform .3s}
  .spf-fleche-big{width:16px;height:16px}
  .spf-dir{flex:0 0 auto;display:inline-flex;align-items:center;gap:5px;font-size:12.5px;font-weight:800;color:var(--accent);white-space:nowrap}
  .spf-go{position:absolute;right:11px;top:50%;transform:translateY(-50%);font-size:22px;line-height:1;color:var(--muted);font-weight:700}
  .spf-autres{font-size:11.5px;color:var(--muted);margin-top:7px;line-height:1.45}
  .spf-kpis{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-top:9px}
  .spf-kpi{border:1px solid var(--line);border-radius:12px;background:var(--panel);padding:9px 8px;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;min-width:0}
  .spf-kpi .v{font-size:17px;font-weight:800;line-height:1.1;color:var(--txt)}
  .spf-kpi .v.spf-ok{color:#15803d}.spf-kpi .v.spf-warn{color:#c2620a}.spf-kpi .v.spf-danger{color:#c81e1e}
  .spf-kpi .l{font-size:11px;color:var(--muted);margin-top:4px;text-transform:uppercase;letter-spacing:.04em;font-weight:600}
  .spf-kpi .s{font-size:11px;color:var(--muted);margin-top:2px}
  .spf-alerte{margin-top:8px;font-size:12.5px;color:var(--danger)}
  :root[data-theme="dark"] .spf-menace,:root[data-theme="dark"] .spf-alerte{color:#ff9d92}
  :root[data-theme="dark"] .spf-kpi .v.spf-ok{color:#86e0a6}:root[data-theme="dark"] .spf-kpi .v.spf-warn{color:#f0c479}:root[data-theme="dark"] .spf-kpi .v.spf-danger{color:#ff9d92}
  @media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .spf-menace,:root:not([data-theme="light"]) .spf-alerte{color:#ff9d92}:root:not([data-theme="light"]) .spf-kpi .v.spf-ok{color:#86e0a6}:root:not([data-theme="light"]) .spf-kpi .v.spf-warn{color:#f0c479}:root:not([data-theme="light"]) .spf-kpi .v.spf-danger{color:#ff9d92}}
  .ai-fold>summary{list-style:none;cursor:pointer;user-select:none}
  .ai-fold>summary::-webkit-details-marker{display:none}
  .ai-fold-hint{margin-left:auto;font-size:11px;font-weight:700;letter-spacing:.2px;text-transform:none;opacity:.85;display:flex;align-items:center;gap:6px}
  .ai-fold-hint::after{content:'';width:6px;height:6px;border-right:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(45deg);transition:transform .2s}
  .ai-fold[open] .ai-fold-hint::after{transform:rotate(-135deg)}
  details.fold{padding:0 14px;overflow:hidden}
  details.fold>summary{list-style:none;cursor:pointer;user-select:none;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 14px;margin:0 -14px}
  details.fold>summary::-webkit-details-marker{display:none}
  details.fold>summary h2,details.fold>summary h3{margin:0;flex:1;min-width:0}
  details.fold>summary::after{content:'';width:8px;height:8px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(45deg);transition:transform .22s;flex:0 0 auto}
  details.fold[open]>summary::after{transform:rotate(-135deg)}
  details.fold>summary h2{font-size:13px;line-height:1.35}
  details.fold[open]{padding-bottom:12px}
  details.madeby-fold{margin-top:10px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
  details.madeby-fold>summary{font-weight:800;font-size:13px;color:var(--txt)}
  details.madeby-fold>.madeby{margin:0;border:0;background:transparent;padding:4px 0 0}
  .pane[data-p="situation"] .disclaimer{font-size:11px;margin:10px 2px 4px}
  .spf-intro{font-size:11.5px;color:var(--muted);line-height:1.5;margin:2px 2px 9px}
  .spf-intro a{color:var(--accent);font-weight:600;white-space:nowrap}
  .ml-hero{margin:8px 0 12px;border-radius:14px;border:1px solid rgba(255,122,26,.35);background:linear-gradient(135deg,rgba(255,122,26,.14),rgba(255,122,26,.04) 60%),var(--panel2);overflow:hidden}
  .ml-hero-head{display:flex;align-items:center;gap:11px;padding:12px 13px 10px;color:inherit;text-decoration:none}
  .ml-hero-ic{flex:0 0 38px;height:38px;border-radius:11px;display:flex;align-items:center;justify-content:center;color:#fff;background:linear-gradient(160deg,#ff9a3c,#e8490f);box-shadow:0 3px 10px rgba(232,73,15,.3)}
  .ml-hero-tx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
  .ml-hero-tx b{font-size:14px;line-height:1.25}
  .ml-hero-tx small{font-size:11.5px;line-height:1.35;color:var(--muted)}
  .ml-hero-go{font-size:24px;line-height:1;color:#ff7a1a;font-weight:700}
  .ml-hero-links{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));border-top:1px solid var(--line)}
  .ml-hero-links a{display:flex;flex-direction:column;align-items:center;gap:4px;padding:9px 4px 10px;color:inherit;text-decoration:none;font-size:11.5px;font-weight:700;min-width:0}
  .ml-hero-links a+a{border-left:1px solid var(--line)}
  .ml-hero-links a svg{color:#ff7a1a}
  .ml-hero a:hover,.ml-hero a:focus-visible{background:rgba(255,122,26,.08)}
  .mlbtn{margin-top:8px;text-decoration:none;background:linear-gradient(180deg,#ff8a2a,#e8590f);box-shadow:0 3px 10px rgba(232,89,15,.28)}
  .ml-air{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:10px 0 0;font-size:12px;color:var(--muted)}
  .ml-air a{padding:4px 9px;border-radius:999px;border:1px solid var(--line);background:var(--panel2);color:inherit;text-decoration:none;font-weight:600}
  .ac-fiche{display:block;margin:6px 0 2px;font-size:12px;font-weight:800;color:#12b8d8;text-decoration:none}
  #airList .ac-fiche{margin:3px 0 0;font-size:11.5px}
  /* Ligne « Comprendre » des bulles et fiches de feu (liens vers /moyens-de-lutte, 24/09/2026). */
  .fiches-utiles{display:block!important;font-size:11.5px;line-height:1.55;margin-top:7px}
  .fiches-utiles a{color:#0369a1;font-weight:700;text-decoration:underline;text-underline-offset:2px}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .fiches-utiles a{color:#7dd3fc}}
  :root[data-theme="dark"] .fiches-utiles a{color:#7dd3fc}
  .fold-more{display:inline-block;margin-top:8px;font-size:12px;font-weight:700;color:#0369a1;text-decoration:underline;text-underline-offset:2px}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .fold-more{color:#7dd3fc}}
  :root[data-theme="dark"] .fold-more{color:#7dd3fc}
  .hist-voir{flex:0 0 auto;background:#b45309;color:#fff;border:0;border-radius:9px;padding:5.5px 12px;font-size:11.5px;font-weight:800;cursor:pointer}
  .hist-btns{flex:0 0 auto;display:flex;gap:6px;align-items:center}
  .hist-fiche{background:var(--panel2,#182338);color:var(--txt,#e8edf7);border:1px solid var(--line);border-radius:9px;padding:5.5px 11px;font-size:11.5px;font-weight:800;cursor:pointer;text-decoration:none;white-space:nowrap}
  .hist-fiche:hover{border-color:#3b74ff}
  /* Entraide / solidarité (ancré presse) */
  .soli-region td{background:rgba(14,159,110,.10);color:#047857;font-weight:800;font-size:12px;padding:7px 9px;border-top:2px solid rgba(14,159,110,.25)}
  .soli-region-n{color:#6b7280;font-weight:600}
  .soli-box{margin-bottom:10px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:12px 13px}
  .soli-head{display:flex;flex-direction:column;margin-bottom:8px}
  .soli-head b{font-size:13.5px;font-weight:800;color:var(--txt)}
  .soli-head small{font-size:11px;color:var(--muted);margin-top:2px;line-height:1.35}
  .soli-list{margin-top:9px}
  .soli-list:empty{margin-top:0}
  /* Cartes plateformes d'entraide (liens directs vérifiés) */
  .platforms{display:flex;flex-direction:column;gap:8px;margin-top:9px}
  .plat{display:block;text-decoration:none;background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:10px 12px}
  .plat:active{filter:brightness(.96)}
  .plat b{display:block;font-size:13px;font-weight:800;color:var(--txt);line-height:1.25}
  .plat small{display:block;font-size:11px;color:var(--muted);margin-top:3px;line-height:1.4}
  .plat .plat-go{display:inline-block;margin-top:5px;font-size:11px;font-weight:700;color:var(--fire2)}
  /* Numéros d'urgence officiels · grille de boutons appelables (tel:) */
  .soli-emg{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px;margin-top:9px}
  .emg-btn{display:flex;align-items:center;gap:9px;text-decoration:none;background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:9px 11px}
  .emg-btn:active{filter:brightness(.95)}
  .emg-ico{font-size:19px;flex:0 0 auto}
  .emg-tx{min-width:0}
  .emg-tx b{display:block;font-size:14px;font-weight:800;color:var(--txt);line-height:1.1}
  .emg-tx small{font-size:11px;color:var(--muted)}
  .emg-btn.hot{background:rgba(225,52,13,.1);border-color:rgba(225,52,13,.4)}
  .emg-btn.hot .emg-tx b{color:#e2340d}
  /* Cellule « où » du tableau : liens itinéraire Maps/Waze */
  /* Vrais boutons (14/10/2026, audit B-23 et B-24) : les liens Maps et Waze faisaient 14 px de haut. */
  .soli-nav{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
  .soli-table .soli-nav a{display:inline-flex;align-items:center;justify-content:center;min-height:32px;min-width:58px;padding:5px 12px;
    border:1px solid var(--line);border-radius:9px;background:var(--panel2);color:var(--txt);font-size:12px;font-weight:700}
  /* Groupes Facebook locaux (chips) · 1 vérifié (bleu FB) + recherches par commune concernée */
  .fbgroups{display:flex;flex-wrap:wrap;gap:7px;margin-top:9px}
  .fbg{display:inline-flex;align-items:center;gap:5px;text-decoration:none;font-size:12px;font-weight:700;background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:6px 11px;color:var(--txt)}
  .fbg:active{filter:brightness(.95)}
  .fbg.verified{background:#1877F2;color:#fff;border-color:#1877F2}
  /* Tableau des aides (Type · Action · Où+coordonnées · Contact) · wrapper scroll-x pour ne jamais déborder. */
  .soli-tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--line);border-radius:10px}
  .soli-table{width:100%;border-collapse:collapse;font-size:12px;background:var(--panel)}
  .soli-table th{text-align:left;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.03em;color:var(--muted);padding:7px 8px;border-bottom:1px solid var(--line);white-space:nowrap;background:var(--panel2)}
  .soli-table td{padding:8px;border-bottom:1px solid var(--line);vertical-align:top}
  .soli-table tr:last-child td{border-bottom:0}
  .soli-c-k{text-align:center;width:40px}
  /* Logo DANS une pastille ronde verte (cohérente avec les marqueurs carte). */
  .soli-pill{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;background:#0e9f6e;font-size:15px;line-height:1;box-shadow:0 1px 4px rgba(0,0,0,.25)}
  .soli-c-a b{font-weight:700;color:var(--txt);line-height:1.3}
  .soli-sub{font-size:11px;color:var(--muted);margin-top:2px}
  .soli-c-w{color:var(--txt);min-width:88px}
  .soli-coord{font-size:11px;color:var(--muted);margin-top:2px;font-variant-numeric:tabular-nums}
  .soli-c-ct{min-width:96px}
  .soli-table a{color:var(--fire-txt);font-weight:700;text-decoration:none;word-break:break-word}
  .soli-table a:active{opacity:.7}
  /* Volet étroit (téléphone, ou volet de 400 px sur ordinateur) : le tableau des aides devient une liste de cartes
     (14/10/2026, audit B-24). Requête de conteneur : c'est la largeur du volet qui compte, pas celle de l'écran. */
  .soli-tablewrap{container-type:inline-size}
  @container (max-width:520px){
    .soli-table thead{display:none}
    .soli-table,.soli-table tbody{display:block}
    .soli-table tr{display:grid;grid-template-columns:40px minmax(0,1fr);column-gap:10px;padding:10px 10px 8px;border-bottom:1px solid var(--line)}
    .soli-table tr:last-child{border-bottom:0}
    .soli-table td{display:block;padding:0;border:0;min-width:0}
    .soli-table td.soli-c-k{grid-row:1 / span 3;width:auto}
    .soli-table td.soli-c-a,.soli-table td.soli-c-w,.soli-table td.soli-c-ct{grid-column:2}
    .soli-table td.soli-c-w,.soli-table td.soli-c-ct{margin-top:6px}
    .soli-table tr.soli-region{display:block;padding:0}
    .soli-table tr.soli-region td{display:block;padding:8px 10px;border-top:2px solid rgba(14,159,110,.25)}
  }
  @keyframes hspin{to{transform:rotate(360deg)}}
  header .live{margin-left:8px;font-size:10px;font-weight:800;color:var(--danger);display:flex;align-items:center;gap:5px;letter-spacing:.05em;background:rgba(225,29,29,.08);padding:5px 9px;border-radius:20px;flex:0 0 auto}
  /* ── Compteur de visiteurs en direct ──────────────────────────────────────────────────────────────
     Greffé DANS le badge DIRECT existant : pas de nouvel élément flottant, donc pas un pixel pris sur la
     carte. Pastille CSS turquoise plutôt qu'un émoji 👁 (rendu et alignement variables selon l'OS), et
     couleur DISTINCTE du rouge pour ne jamais se lire comme une alerte. `tabular-nums` empêche le badge
     de tressauter en largeur quand le nombre change (9 → 10 → 9). */
  /* Le compteur était en gris sur le fond rosé du badge : peu lisible et « inachevé ». Il devient une
     vraie pastille pleine, dans un bleu ardoise neutre qui ne concurrence pas le rouge « DIRECT » (lequel
     porte une information de fraîcheur et garde la priorité visuelle). Chasse fixe pour que la largeur ne
     tressaute pas quand le nombre change. */
  /* Compteur de visiteurs RETIRÉ (demande fondateur) : display:none complet — le badge garde
     seulement « DIRECT » rouge + point pulsé. ⚠️ display:none ici est INDISPENSABLE : l'ancien
     display:inline-flex écrasait l'attribut `hidden` (spécificité > [hidden]{display:none}), donc
     l'icône bonhomme s'affichait même vide. Retirer cette règle = plus d'icône visiteur. */
  header .live .onl{display:none;align-items:center;gap:5px;margin-left:7px;
    background:#334155;color:#fff;font-weight:800;letter-spacing:0;
    font-variant-numeric:tabular-nums;font-size:10.5px;padding:2px 9px 2px 7px;border-radius:20px;
    box-shadow:0 1px 3px rgba(15,23,42,.28)}
  /* Silhouette en SVG masqué plutôt qu'un émoji 👤 : le glyphe émoji change d'un OS à l'autre et
     s'aligne mal ; le masque, lui, prend la couleur du texte et reste net à toutes les tailles. */
  header .live .onl::before{content:"";width:10px;height:10px;flex:0 0 auto;background:#5eead4;
    -webkit-mask:var(--ico-onl) center/contain no-repeat;mask:var(--ico-onl) center/contain no-repeat;
    animation:onlPulse 2.6s ease-in-out infinite}
  :root{--ico-onl:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 8.2a3.4 3.4 0 1 0 0-6.8 3.4 3.4 0 0 0 0 6.8Zm0 1.4c-3.2 0-5.8 1.8-5.8 4v1h11.6v-1c0-2.2-2.6-4-5.8-4Z'/%3E%3C/svg%3E");
    /* Croix des bulles (masque : seul l'alpha compte, tracé noir ; jamais de « # » dans une data-URI). */
    --ic-x:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E")}
  @keyframes onlPulse{0%,100%{opacity:1}50%{opacity:.55}}
  body.leger header .live .onl::before{animation:none} /* mode léger : pas d'animation décorative */
  /* ⚠️ Mesuré : sur un écran de 412 px, ce compteur volait 51 px au titre, qui devenait « Feux Giron… ».
     Plutôt que de sacrifier l'un des deux, on récupère la place sur le mot « DIRECT » lui-même : sous
     430 px il s'efface et sa pastille rouge pulsée suffit à dire « en direct ». Bilan de largeur ≈ nul :
     le titre reste ENTIER et le compteur reste VISIBLE. */
  /* Sous 640 px, la ligne de sous-titre du header doit tenir sans pousser « France Incendie » : on ne garde que
     l'heure de mise à jour, qui est ce que l'utilisateur vient vérifier. Le comptage de points et l'âge du
     passage satellite restent dans le DOM pour les écrans plus larges. */
  @media (max-width:640px){header .sub .lu-sec{display:none}}
  /* (Retiré) : sous 430 px on masquait le mot « DIRECT » pour laisser la place au compteur de
     visiteurs. Le compteur n'existe plus → on garde « DIRECT » (rouge + point pulsé) affiché
     PARTOUT, y compris mobile. */
  /* « France Incendie » est plus long que l'ancien nom : mesuré à 127 px pour 118 disponibles
     sur un écran de 390 px, le titre se faisait couper (« France Incendi… »). On récupère les
     9 px manquants sur la typographie du titre LUI-MÊME plutôt qu'en sacrifiant un autre
     élément du header. Au-dessus de 430 px, rien ne change. */
  @media (max-width:430px){header h1{font-size:14.5px;letter-spacing:-.02em}}
  /* Rappel en TÊTE du tiroir, à côté du badge de version : même pastille, formulation complète. */
  /* Fréquentation publique en tête du tiroir (01/10/2026) : trois chiffres (en ligne avec point vivant, visites du
     jour, visites au total), mêmes compteurs que le tableau de bord, agrégats seulement ; une case vide reste masquée. */
  #onlDrawer{display:none;flex:0 0 auto;grid-auto-flow:column;grid-auto-columns:1fr;margin:0 0 10px;border:1px solid var(--line, rgba(255,255,255,.12));
    border-radius:14px;background:linear-gradient(180deg,rgba(249,115,22,.08),rgba(249,115,22,.02));overflow:hidden}
  #onlDrawer:not([hidden]){display:grid}
  #onlDrawer .aud-kpi{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;min-width:0;margin:0;padding:10px 6px 9px;text-align:center}
  #onlDrawer .aud-kpi[hidden]{display:none}
  #onlDrawer .aud-kpi:not([hidden]) ~ .aud-kpi:not([hidden]){border-left:1px solid var(--line, rgba(255,255,255,.12))}
  #onlDrawer .aud-kpi b{display:inline-flex;align-items:center;gap:6px;color:var(--txt);font-size:17px;font-weight:800;line-height:1.1;letter-spacing:-.01em;font-variant-numeric:tabular-nums}
  #onlDrawer .aud-kpi span{color:var(--muted);font-size:11px;font-weight:800;line-height:1.25;letter-spacing:.06em;text-transform:uppercase}
  #onlDrawer .aud-direct b{color:#2dd4bf}
  /* PASTILLES PULSÉES SANS RECALCUL DE STYLE (13/10/2026, audit H-3) : l'onde était un box-shadow animé, repeint à chaque
     image (50 recalculs de style par seconde carte immobile, dont celle du volet FERMÉ). L'onde est désormais un
     pseudo-élément animé seulement en transform et opacity, que le navigateur anime sans repasser par la page.
     Même dessin : pastille fixe, anneau qui s'élargit de 7 px en s'effaçant. */
  #onlDrawer .aud-direct b{position:relative}
  #onlDrawer .aud-direct b::before{content:"";width:8px;height:8px;flex:0 0 auto;border-radius:50%;background:#2dd4bf}
  #onlDrawer .aud-direct b::after{content:"";position:absolute;left:0;top:calc(50% - 4px);width:8px;height:8px;border-radius:50%;
    background:rgba(45,212,191,.55);pointer-events:none;will-change:transform,opacity;animation:audPouls 2s ease-out infinite}
  body.leger #onlDrawer .aud-direct b::after,#drawer.closed #onlDrawer .aud-direct b::after{animation:none;opacity:0}
  @media (prefers-reduced-motion:reduce){#onlDrawer .aud-direct b::after{animation:none;opacity:0}}
  @keyframes audPouls{0%{transform:scale(1);opacity:1}100%{transform:scale(2.75);opacity:0}}
  /* Moins de 380 px (audit B-17, 13/10/2026) : « DIRECT » se lit seulement par les lecteurs d'écran, le point rouge reste ;
     le nom « France Incendie » n'est plus tronqué à 360 px. */
  @media (max-width:379px){header .live{padding:7px}header .live .lbl{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}}
  /* Pendant l'écran d'ouverture (audit B-12) : ces trois blocs se posaient puis bougeaient dessous (décalage de mise en page
     de 0,10 à 0,15). Ils apparaissent quand l'écran commence à s'effacer (.hidden), à leur place finale. */
  body:has(#loading:not(.hidden)) #modeSeg,body:has(#loading:not(.hidden)) #ventHud,body:has(#loading:not(.hidden)) #fireWinMap{visibility:hidden}
  header .live .dot{position:relative;width:7px;height:7px;border-radius:50%;background:var(--danger)}
  header .live .dot::after{content:"";position:absolute;inset:0;border-radius:50%;background:rgba(225,29,29,.5);pointer-events:none;
    will-change:transform,opacity;animation:pulse 1.4s infinite}
  @keyframes pulse{0%{transform:scale(1);opacity:1}70%{transform:scale(3);opacity:0}100%{transform:scale(1);opacity:0}}
  #map{flex:1;min-height:0;background:#dfe5ee}
  /* Boutons calques (Vent/Fumée/Avions) */
  .toggles{display:flex;flex-direction:column;gap:0;max-width:none;padding:0 6px 4px}
  /* Fond theme-aware (var(--panel2), plus le blanc en dur qui tranchait mal en thème sombre) et chip
     PLEINE quand actif (fond teinté, pas juste un liseré) : l'état sélectionné se lit d'un coup d'œil
     au lieu d'un simple contour discret. */
  .toggles button{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;min-height:44px;background:none;color:var(--txt);border:0;border-top:1px solid var(--line);border-radius:0;padding:9px 2px;font-size:13px;line-height:1.25;font-weight:700;text-align:left;cursor:pointer;transition:.15s;box-shadow:none}
  /* Interrupteur dessiné à droite de chaque ligne (même geste que la carte des inondations) : piste + bouton rond.
     Sauf « Mode léger » (#perfSeg .ios-toggle), qui a déjà son interrupteur dans le balisage : il en affichait deux
     (30/09/2026, fondateur : « pourquoi on a deux switch là ? »). */
  .toggles button:not(.ios-toggle)::after{content:'';flex:0 0 auto;width:40px;height:24px;border-radius:999px;background-color:color-mix(in srgb,var(--txt) 22%,transparent);background-image:radial-gradient(circle at 12px 12px,#fff 9.5px,transparent 10.5px);transition:background-color .2s,background-image .2s}
  /* Vert, comme les interrupteurs du tiroir des calques et du mode léger (audit B-15) : une seule couleur d'état actif. */
  .toggles button.on:not(.ios-toggle)::after{background-color:#34c759;background-image:radial-gradient(circle at 28px 12px,#fff 9.5px,transparent 10.5px)}
  /* Barré retiré : un texte barré se lit comme une erreur/un élément supprimé, pas comme
     « actuellement masqué sur la carte ». L'opacité seule (icône déjà grisée juste au-dessus) suffit
     à dire « off » sans donner l'impression que l'option a disparu. */
  .toggles button:not(.on){opacity:1;color:var(--txt)}
  .toggles button.on{border-color:var(--line);background:none}
  /* Mode léger = interrupteur ON/OFF style iOS (plus explicite qu'une pastille). Le JS ne fait que
     basculer la classe .on : la piste vire au vert + la pastille glisse en pur CSS. On NEUTRALISE ici
     les styles génériques .toggles button (fond orange à l'état on, opacité .55 à l'état off) pour ce
     bouton précis, sinon le rendu interrupteur serait écrasé. */
  #perfSeg .ios-toggle{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;
    padding:10px 12px;border-radius:12px;font-size:13px;min-height:44px;opacity:1;box-shadow:var(--shadow)}
  #perfSeg .ios-toggle:not(.on){opacity:1}
  #perfSeg .ios-toggle.on{border-color:var(--line);background:var(--panel2)}
  #perfSeg .ios-toggle .iosw-label{flex:1 1 auto;text-align:left;line-height:1.2}
  #perfSeg .ios-toggle .iosw-track{flex:0 0 auto;width:46px;height:28px;border-radius:999px;position:relative;
    background:color-mix(in srgb,var(--txt) 22%,transparent);transition:background .22s ease}
  #perfSeg .ios-toggle .iosw-knob{position:absolute;top:2px;left:2px;width:24px;height:24px;border-radius:50%;
    background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.35);transition:transform .22s cubic-bezier(.3,1.4,.5,1)}
  #perfSeg .ios-toggle.on .iosw-track{background:#34c759}
  #perfSeg .ios-toggle.on .iosw-knob{transform:translateX(18px)}
  /* Sous-titres de regroupement : distincts des grands titres .dsec (FOND DE CARTE, AFFICHER SUR LA
     CARTE…) · plus petits et plus doux, ils subdivisent SANS dupliquer visuellement le titre parent.
     Avant, les 17 interrupteurs de calques s'empilaient en un seul bloc sans hiérarchie : impossible
     de s'y retrouver d'un coup d'œil. Regroupés par intention (ce que l'utilisateur cherche à voir),
     pas par ordre d'ajout dans le code. */
  .tglabel{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:10px 0 5px}
  .tglabel:first-of-type{margin-top:2px}
  /* Accordéon des catégories : chaque groupe se déplie/replie. Le compteur « n/total » reste
     visible même replié · on sait ce qui est actif sans avoir à ouvrir le groupe. */
  .tgroup{margin:2px 0}
  .tgroup-head{width:100%;display:flex;align-items:center;gap:7px;background:none;border:0;
    appearance:none;-webkit-appearance:none;
    padding:9px 2px;cursor:pointer;font-size:10px;font-weight:800;text-transform:uppercase;
    letter-spacing:.06em;color:var(--muted);text-align:left;-webkit-tap-highlight-color:transparent}
  /* Pastille pleine (même langage visuel que les puces de filtres --icb/--ic ci-dessous) plutôt
     qu'un trait de couleur nu sur fond transparent : un simple contour saturé sans assise
     lisait « pictogramme jouet », le fond plein l'ancre dans le même vocabulaire pro que le reste. */
  .tgroup-ic-wrap{flex:0 0 auto;width:19px;height:19px;border-radius:6px;display:flex;
    align-items:center;justify-content:center;background:var(--gc)}
  .tgroup-ic{width:12.5px;height:12.5px}
  .tgroup-name{flex:1 1 auto}
  .tgroup-count{font-size:10px;font-weight:700;color:var(--muted);background:var(--panel2);
    border:1px solid var(--line);border-radius:20px;padding:1px 8px;font-variant-numeric:tabular-nums}
  .tgroup-chev{flex:0 0 auto;color:var(--muted);transition:transform .22s ease}
  .tgroup.open .tgroup-chev{transform:rotate(180deg)}
  /* max-height plutôt que display:none : transition douce à l'ouverture/fermeture. Plafond
     généreux (chaque groupe fait 5 boutons max, largement sous la limite) sans mesure JS. */
  .tgroup .toggles{max-height:0;overflow:hidden;transition:max-height .25s ease;max-width:none}
  .tgroup.open .toggles{max-height:2400px;overflow:visible}
  /* ── MENU « AFFICHER SUR LA CARTE » = celui de la carte des inondations (26/09/2026, demande fondateur) ──
     Groupes en cartes arrondies, en-têtes lisibles (plus de petites capitales), et chaque calque est une
     LIGNE pleine largeur : pastille d'icône, libellé, interrupteur façon iOS à droite. Les calques restent
     des <button data-t> à classe .on (app.js inchangé : saveLayers, applyLayer, rattrapages) ; l'interrupteur
     est dessiné en CSS pur (::after : piste + pastille blanche en dégradé radial qui glisse), l'état
     accessible est porté par role="switch" + aria-checked, synchronisés depuis la classe .on par app.js. */
  #toggleSeg .tgroup{border:1px solid var(--line);border-radius:12px;background:var(--panel2);margin:0 0 8px;overflow:hidden}
  #toggleSeg .tgroup-head{padding:10px 10px;gap:9px;font-size:13px;font-weight:800;text-transform:none;letter-spacing:0;color:var(--txt)}
  #toggleSeg .tgroup-ic-wrap{width:24px;height:24px;border-radius:7px}
  #toggleSeg .tgroup-ic{width:15px;height:15px}
  #toggleSeg .tgroup-count{font-size:11px;font-weight:800;background:var(--panel)}
  #perfSeg{max-width:none}
  #toggleSeg .toggles{display:flex;flex-direction:column;flex-wrap:nowrap;gap:0;max-width:none;padding:0 10px}
  #toggleSeg .tgroup.open .toggles{max-height:1200px;overflow:visible;padding-bottom:4px}
  #toggleSeg .toggles button{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;margin:0;padding:9px 2px;
    background-color:transparent;border:0;border-top:1px solid var(--line);border-radius:0;box-shadow:none;
    font-size:13px;font-weight:700;line-height:1.25;text-align:left;color:var(--txt);opacity:1;-webkit-tap-highlight-color:transparent}
  #toggleSeg .toggles button:not(.on),#toggleSeg .toggles button.on{opacity:1;background-color:transparent;border-color:var(--line)}
  #toggleSeg .toggles button::before{flex:0 0 auto;margin:0;vertical-align:0}
  #toggleSeg .toggles button::after{content:"";flex:0 0 auto;margin-left:auto;width:40px;height:24px;border-radius:999px;
    background:radial-gradient(circle at center,#fff 0 9.6px,rgba(0,0,0,.22) 10.4px,transparent 11.6px) no-repeat,
      color-mix(in srgb,var(--txt) 24%,transparent);
    background-size:24px 24px,100% 100%;background-position:0 0,0 0;
    box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--txt) 14%,transparent);
    transition:background-position .22s cubic-bezier(.3,1.4,.5,1),background-color .2s}
  #toggleSeg .toggles button.on::after{background:radial-gradient(circle at center,#fff 0 9.6px,rgba(0,0,0,.22) 10.4px,transparent 11.6px) no-repeat,#34c759;
    background-size:24px 24px,100% 100%;background-position:16px 0,0 0;box-shadow:none}
  #toggleSeg .toggles button:focus-visible{outline:2px solid #34c759;outline-offset:-2px;border-radius:8px}
  body.leger #toggleSeg .toggles button::after{transition:none}
  @media (prefers-reduced-motion:reduce){#toggleSeg .toggles button::after{transition:none}}

  /* ── ICÔNES DES CALQUES · vectorielles, plus d'emoji ──
     Les emoji étaient rendus par la police système : dessin différent sur chaque appareil, et
     plusieurs apparaissaient cassés (tofu) selon la plateforme. Ils faisaient aussi doublon
     (la même flamme pour « Zones » et « Statut des feux », la même poignée de main pour
     « Entraide » et « Partenaires »), ce qui rendait la légende ambiguë.
     Ici : un tracé SVG par calque, en masque CSS, donc la couleur suit le texte et l'état
     actif/inactif reste lisible sans règle supplémentaire. */
  /* ⚠️ NE PAS passer ces boutons en `display:flex` : le conteneur `.seg` calcule sa hauteur sur des
     enfants en flux normal. Le passer en flex l'a fait tomber à 2 px de haut avec `overflow:hidden`,
     et les quatre fonds de carte ont purement disparu de l'écran. L'icône est donc posée en
     `inline-block` aligné sur la ligne de texte, sans toucher au mode d'affichage du bouton. */
  /* PASTILLE COLORÉE · un trait fin de 12 px ne fait pas un repère : à cette taille l'œil accroche
     une SURFACE, pas un contour. D'où le fond teinté + l'icône colorée au centre, qui reprennent
     la couleur du repère correspondant sur la carte.
     La couleur est CUITE dans le SVG (tracé coloré) au lieu d'un masque : un masque ne permet pas
     d'avoir à la fois un fond teinté et un tracé de couleur sur le même élément. */
  /* `.toggles button` (pas juste `#toggleSeg button`) : sinon la règle décore aussi les boutons
     d'en-tête d'accordéon `.tgroup-head` (qui n'ont pas de data-t/--ic) d'un carré gris de repli
     vide, planté devant l'icône de catégorie · carré fallback constaté en réel, absent des tests
     desktop car invisible à cette résolution. */
  #layerSeg button::before,#toggleSeg .toggles button::before{content:'';display:inline-block;
    width:19px;height:19px;margin-right:6px;vertical-align:-5px;border-radius:6px;
    background-color:var(--icb,#7a8092);
    background-image:var(--ic);background-size:12.5px 12.5px;
    background-position:center;background-repeat:no-repeat}
  /* Calque MASQUÉ : la pastille se désature. L'état doit rester lisible avant la couleur · une
     pastille vive sur une ligne barrée ferait croire que le calque est affiché. */
  #toggleSeg button:not(.on)::before{filter:grayscale(1);opacity:.5}
  /* Calque MASQUÉ : l'icône repasse en gris. Une pastille colorée sur une ligne barrée
     laisserait croire que le calque est actif · l'état doit primer sur le code couleur. */
  #layerSeg button[data-l="sat"],#toggleSeg button[data-t="sat"]{--icb:#8fa6c4;--icc:#8fa6c4;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223%22%2F%3E%3Cpath%20d%3D%22M3.6%208.5a10.5%2010.5%200%200%201%204.9-4.9M20.4%2015.5a10.5%2010.5%200%200%201-4.9%204.9M4.7%2016.6A10.5%2010.5%200%200%200%2012%2020.5M19.3%207.4A10.5%2010.5%200%200%200%2012%203.5%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="ign"]{--icb:#8fa6c4;--icc:#8fa6c4;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223%22%2F%3E%3Cpath%20d%3D%22M3.6%208.5a10.5%2010.5%200%200%201%204.9-4.9M20.4%2015.5a10.5%2010.5%200%200%201-4.9%204.9M4.7%2016.6A10.5%2010.5%200%200%200%2012%2020.5M19.3%207.4A10.5%2010.5%200%200%200%2012%203.5%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="clair"],#toggleSeg button[data-t="clair"]{--icb:#e0b64a;--icc:#e0b64a;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%224.2%22%2F%3E%3Cpath%20d%3D%22M12%202.3v2.4M12%2019.3v2.4M2.3%2012h2.4M19.3%2012h2.4M5.1%205.1l1.7%201.7M17.2%2017.2l1.7%201.7M18.9%205.1l-1.7%201.7M6.8%2017.2l-1.7%201.7%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="dark"],#toggleSeg button[data-t="dark"]{--icb:#8b93b8;--icc:#8b93b8;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M20%2014.2A8.4%208.4%200%200%201%209.8%204%208.4%208.4%200%201%200%2020%2014.2Z%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="thermique"],#toggleSeg button[data-t="thermique"]{--icb:#e07a4a;--icc:#e07a4a;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M13.5%2013.4V4.6a1.9%201.9%200%200%200-3.8%200v8.8a4%204%200%201%200%203.8%200Z%22%2F%3E%3Cpath%20d%3D%22M11.6%208.4v6.9%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="wind"],#toggleSeg button[data-t="wind"]{--icb:#7fb6e8;--icc:#7fb6e8;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M3%208.5h9.4a2.7%202.7%200%201%200-2.7-2.7M3%2012.5h13a2.7%202.7%200%201%201-2.7%202.7M3%2016.4h7.6a2.4%202.4%200%201%201-2.4%202.4%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="smoke"],#toggleSeg button[data-t="smoke"]{--icb:#9aa4b4;--icc:#9aa4b4;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M4%2017.5c2-1.6%204-1.6%206%200s4%201.6%206%200%202.7-1.4%204-.6M4%2013c2-1.6%204-1.6%206%200s4%201.6%206%200%202.7-1.4%204-.6M6%208.5c1.6-1.3%203.2-1.3%204.8%200s3.2%201.3%204.8%200%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="air"],#toggleSeg button[data-t="air"]{--icb:#5ec8e0;--icc:#5ec8e0;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M21%2015.5%2012.8%2011V5.2a1.7%201.7%200%201%200-3.4%200V11L1.2%2015.5v2.2l8.2-2.5v3.5l-2.3%201.6v1.4l3.9-1%203.9%201v-1.4l-2.3-1.6v-3.5l8.4%202.5Z%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="traces"],#toggleSeg button[data-t="traces"]{--icb:#7fc7d9;--icc:#7fc7d9;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22white%22%20stroke-width%3D%221.7%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M2%2021c6%200%203-7%208-9%22%20stroke-dasharray%3D%222%203%22%2F%3E%3Cpath%20d%3D%22M17%202v5l5%204v2l-5-2v4l2%202v1l-3-1-3%201v-1l2-2v-4l-5%202v-2l5-4V2Z%22%2F%3E%3C%2Fsvg%3E")}
  #toggleSeg button[data-t="helis"]{--icb:#5ec8e0;--icc:#5ec8e0;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22white%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M3%204h17M11%204v4M5%2010h8a4%204%200%200%201%204%204v2H7a3%203%200%200%201-3-3v-1l1-2ZM17%2013h4l1-5M7%2016v4h11M11%2016v4%22%2F%3E%3C%2Fsvg%3E")}
  #toggleSeg button[data-t="heliTraces"]{--icb:#5ec8e0;--icc:#5ec8e0;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22white%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M2%2021c7%200%204-8%2010-9M9%203h12M15%203v3M11%208h5a3%203%200%200%201%203%203v2h-6a3%203%200%200%201-3-3l1-2ZM19%2010h3M13%2013v3h7%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="zone"],#toggleSeg button[data-t="zone"]{--icb:#ff6b35;--icc:#ff6b35;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M12%202.8c3.4%203.4%205.6%206%205.6%209.1a5.6%205.6%200%201%201-11.2%200c0-3.1%202.2-5.7%205.6-9.1Z%22%2F%3E%3Cpath%20d%3D%22M12%2018.6a3%203%200%200%201-1.7-5.4c1%201.1%201.7-.7%201.7-2.2%202.2%202.1%203%203.6%203%204.6a3%203%200%200%201-3%203Z%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="rain"],#toggleSeg button[data-t="rain"]{--icb:#5b8dd9;--icc:#5b8dd9;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M7.2%2015.5a4.3%204.3%200%200%201%20.5-8.6%205.6%205.6%200%200%201%2010.5%201.6%203.6%203.6%200%200%201-.7%207%22%2F%3E%3Cpath%20d%3D%22M9%2018.2l-.9%202.4M13%2018.2l-.9%202.4M17%2018.2l-.9%202.4%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="roads"],#toggleSeg button[data-t="roads"]{--icb:#e8a33d;--icc:#e8a33d;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M8%203%205%2021M16%203l3%2018M12%204v2.6M12%2010.7v2.6M12%2017.4V20%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="works"],#toggleSeg button[data-t="works"]{--icb:#d98324;--icc:#d98324;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M12%204%203%2020h18Z%22%2F%3E%3Cpath%20d%3D%22M12%2010v4M12%2017h.01%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="sea"],#toggleSeg button[data-t="sea"]{--icb:#2fb8a8;--icc:#2fb8a8;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%225.2%22%20r%3D%222.2%22%2F%3E%3Cpath%20d%3D%22M12%207.4V21M7.4%2010.4h9.2M4%2015.2a8%208%200%200%200%2016%200%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="evac"],#toggleSeg button[data-t="evac"]{--icb:#3fc46a;--icc:#3fc46a;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M3.5%2010.8%2012%204l8.5%206.8V20a1.4%201.4%200%200%201-1.4%201.4H4.9A1.4%201.4%200%200%201%203.5%2020Z%22%2F%3E%3Cpath%20d%3D%22m9%2013.6%202.2%202.2%204-4%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="burnt"],#toggleSeg button[data-t="burnt"]{--icb:#c0392b;--icc:#c0392b;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%223.4%22%20y%3D%225.6%22%20width%3D%2217.2%22%20height%3D%2212.8%22%20rx%3D%221.8%22%2F%3E%3Cpath%20d%3D%22m5%2015%204-4M9%2017l6.6-6.6M13.4%2017.6%2019%2012%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="firebreak"],#toggleSeg button[data-t="firebreak"]{--icb:#a9714b;--icc:#a9714b;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M4%2020%2014.4%209.6%22%2F%3E%3Cpath%20d%3D%22M12.8%205.2a4.6%204.6%200%200%201%206.5%206.5l-2.2-2.2-2.1%202.1Z%22%2F%3E%3Cpath%20d%3D%22M3%203.6%206.4%207%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="firms"],#toggleSeg button[data-t="firms"]{--icb:#ff8c3a;--icc:#ff8c3a;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27white%27%3E%3Ccircle%20cx%3D%276.5%27%20cy%3D%277%27%20r%3D%273%27%2F%3E%3Ccircle%20cx%3D%2713%27%20cy%3D%275.5%27%20r%3D%272.8%27%2F%3E%3Ccircle%20cx%3D%2718%27%20cy%3D%279.5%27%20r%3D%272.8%27%2F%3E%3Ccircle%20cx%3D%277.5%27%20cy%3D%2715.5%27%20r%3D%272.8%27%2F%3E%3Ccircle%20cx%3D%2716%27%20cy%3D%2716%27%20r%3D%273%27%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="firestatus"],#toggleSeg button[data-t="firestatus"]{--icb:#ff4d3d;--icc:#ff4d3d;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M12%202.6%204.4%205.8v6c0%204.4%203.2%208.4%207.6%209.6%204.4-1.2%207.6-5.2%207.6-9.6v-6Z%22%2F%3E%3Cpath%20d%3D%22M12%208.2c1.8%201.8%202.8%203.1%202.8%204.6a2.8%202.8%200%201%201-5.6%200c0-1.5%201-2.8%202.8-4.6Z%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="dfci"],#toggleSeg button[data-t="dfci"]{--icb:#1f8fd6;--icc:#1f8fd6;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M12%203.2c3%203.6%204.9%206.2%204.9%209a4.9%204.9%200%201%201-9.8%200c0-2.8%201.9-5.4%204.9-9Z%22%2F%3E%3Cpath%20d%3D%22M9.6%2013.4a2.4%202.4%200%200%200%202.4%202.4%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="tht"],#toggleSeg button[data-t="tht"]{--icb:#8b5cf6;--icc:#8b5cf6;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M13%202%206%2013h4l-1.5%209L19%2010h-4.5Z%22%2F%3E%3C%2Fsvg%3E")}
  #toggleSeg button[data-t="mtgfire"]{--icb:#e0563a;--icc:#e0563a;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M12%203c2.5%202.6%204%204.6%204%206.9a4%204%200%201%201-8%200C8%207.6%209.5%205.6%2012%203Z%22%2F%3E%3Cpath%20d%3D%22M2%208.5a10.5%2010.5%200%200%201%204.9-4.9M22%2015.5a10.5%2010.5%200%200%201-4.9%204.9%22%2F%3E%3C%2Fsvg%3E")}
  #toggleSeg button[data-t="trains"]{--icb:#c2410c;--icc:#c2410c;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%275%27%20y%3D%273%27%20width%3D%2714%27%20height%3D%2714%27%20rx%3D%273%27%2F%3E%3Cpath%20d%3D%22M5%2011h14%22%2F%3E%3Ccircle%20cx%3D%279%27%20cy%3D%2714.2%27%20r%3D%271%27%2F%3E%3Ccircle%20cx%3D%2715%27%20cy%3D%2714.2%27%20r%3D%271%27%2F%3E%3Cpath%20d%3D%22M8%2021l2-4M16%2021l-2-4%22%2F%3E%3C%2Fsvg%3E")}
  /* Trains perturbés par un incendie (SNCF, 27/09/2026) : une pastille par gare, nombre de trains ; rouge = supprimés. */
  .train-pin{display:inline-flex;align-items:center;gap:3px;height:22px;padding:0 6px;border-radius:999px;color:#fff;background:#c2410c;border:2px solid #fff;box-shadow:0 2px 5px rgba(0,0,0,.35);font:700 11.5px/1 system-ui,sans-serif;box-sizing:border-box;cursor:pointer;white-space:nowrap}
  .train-pin.supprimes{background:#b91c1c}
  .train-pin svg{flex:0 0 auto}
  .evp-train{margin:6px 0 0;font-size:12px;line-height:1.4;color:var(--txt)}
  .evp-train b{font-weight:700}
  #toggleSeg button[data-t="webcam"]{--icb:#475569;--icc:#475569;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M4%207h3l2-2h6l2%202h3v12H4Z%22%2F%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2713%27%20r%3D%273.4%27%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="foudre"],#toggleSeg button[data-t="foudre"]{--icb:#eab308;--icc:#eab308;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27white%27%20stroke%3D%27none%27%3E%3Cpath%20d%3D%22M13%202%206%2013h4l-1.5%209L19%2010h-4.5Z%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="solidarity"],#toggleSeg button[data-t="solidarity"]{--icb:#b06fd4;--icc:#b06fd4;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M12%2020.4%204.6%2013a4.3%204.3%200%200%201%206.1-6.1l1.3%201.3%201.3-1.3A4.3%204.3%200%200%201%2019.4%2013Z%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="partenaires"],#toggleSeg button[data-t="partenaires"]{--icb:#e2b53d;--icc:#e2b53d;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22m12%202.8%202.7%205.6%206.1.9-4.4%204.3%201%206.1-5.4-2.9-5.4%202.9%201-6.1L3.2%209.3l6.1-.9Z%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="villes"],#toggleSeg button[data-t="villes"]{--icb:#f0a63a;--icc:#f0a63a;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M3.6%2020.4V11l5.2-3.8L14%2011v9.4Z%22%2F%3E%3Cpath%20d%3D%22M14%2020.4V8.4l3.4-2.4%203%202.2v12.2Z%22%2F%3E%3Cpath%20d%3D%22M7%2020.4v-4.2h3.6v4.2%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="sites"],#toggleSeg button[data-t="sites"]{--icb:#ef5b5b;--icc:#ef5b5b;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%22M12%204.2%203%2020.4h18Z%22%2F%3E%3Cpath%20d%3D%22M12%204.2%208.4%2020.4M12%204.2l3.6%2016.2%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="photos"],#toggleSeg button[data-t="photos"]{--icb:#4dc3d9;--icc:#4dc3d9;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%222.8%22%20y%3D%226.6%22%20width%3D%2218.4%22%20height%3D%2213.4%22%20rx%3D%222.4%22%2F%3E%3Cpath%20d%3D%22M8.6%206.6%2010.2%204h3.6l1.6%202.6%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2213.4%22%20r%3D%223.4%22%2F%3E%3C%2Fsvg%3E")}
  #layerSeg button[data-l="animaux"],#toggleSeg button[data-t="animaux"]{--icb:#ef7bb0;--icc:#ef7bb0;--ic:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27white%27%20stroke-width%3D%272.35%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cellipse%20cx%3D%226.4%22%20cy%3D%2210.4%22%20rx%3D%222.1%22%20ry%3D%222.6%22%2F%3E%3Cellipse%20cx%3D%2217.6%22%20cy%3D%2210.4%22%20rx%3D%222.1%22%20ry%3D%222.6%22%2F%3E%3Cellipse%20cx%3D%229.8%22%20cy%3D%225.9%22%20rx%3D%221.9%22%20ry%3D%222.4%22%2F%3E%3Cellipse%20cx%3D%2214.2%22%20cy%3D%225.9%22%20rx%3D%221.9%22%20ry%3D%222.4%22%2F%3E%3Cpath%20d%3D%22M12%2013.2c3.1%200%205%202.1%205%204.2%200%201.9-1.6%203-3.4%202.6-1-.2-2.2-.2-3.2%200-1.8.4-3.4-.7-3.4-2.6%200-2.1%201.9-4.2%205-4.2Z%22%2F%3E%3C%2Fsvg%3E")}

  /* ── POPUPS ACCUEIL / RETOUR / ENTRAIDE · cartes modernes, zéro emoji ──
     Le « retour possible » est une annonce de SOULAGEMENT : elle mérite une carte posée
     (bandeau teinté, coche en médaillon, citation en exergue) · pas une pile de <br> avec
     des emoji système inégaux selon la plateforme. Le bandeau porte la couleur du TYPE
     (bleu ciel = retour, vert = accueil, orange = entraide), le corps reste blanc lisible. */
  .evpop-wrap .leaflet-popup-content{margin:0;line-height:1.45;min-width:232px}
  /* Desktop (html[data-desk]) : popups/cartes agrandies — calibrage mobile trop petit sur grand écran. */
  html[data-desk] .leaflet-popup-content{font-size:13.5px}
  html[data-desk] .evpop-wrap .leaflet-popup-content{min-width:296px}
  html[data-desk] .evp-head{padding:13px 16px}
  html[data-desk] .evp-head b{font-size:15.5px}
  html[data-desk] .evp-head small{font-size:11px}
  html[data-desk] .evp-body{font-size:13px}
  /* CONSENTEMENT GOOGLE (Funding Choices/CMP TCF) : sa boîte est servie par Google (iframe/dashboard) et
     N'EST PAS repositionnable par notre CSS. Elle apparaît en bas à gauche et recouvrait notre carte
     partenaire (#sponsorCard). Correctif CONTRÔLABLE : sur DESKTOP on remonte le sponsorCard au-dessus de la
     zone où Google pose sa boîte → plus de superposition. (Le centrage de la boîte Google, lui, se règle dans
     AdSense → Confidentialité et messages → style du message RGPD = superposition.) */
  /* 1100 px et plus seulement (13/10/2026, audit H-7) : entre 820 et 1099 px le volet est encore celui du bas, la carte doit
     suivre --peek comme sur téléphone (règle .sponsor-card), au lieu de se poser à 150 px sur le haut du volet replié. */
  @media (min-width:1100px){ #sponsorCard{bottom:150px !important} }
  html[data-desk] .evp-row{font-size:13px}
  .evpop-wrap .leaflet-popup-content-wrapper{border-radius:14px;overflow:hidden;padding:0;
    box-shadow:0 12px 34px rgba(15,30,60,.28)}
  .evp-head{display:flex;align-items:center;gap:10px;padding:11px 14px;color:#fff}
/* Zones brûlées EFFIS (fondateur 2026-09-03 : « pas violettes : rouge transparent, fin, moderne, lisse »).
     L'ancien hue-rotate(155°) sur le bleu EFFIS retombait en MAGENTA. Recoloration ROBUSTE quelle que
     soit la teinte source : grayscale → sepia → rotation vers le rouge ; opacité basse (le terrain reste
     lisible), plus d'animation « braise » (rendu calme et lisse). */
  .ember-pane{filter:grayscale(1) sepia(1) saturate(5.5) hue-rotate(-42deg) brightness(.92) contrast(1.05);opacity:.52;will-change:auto}
    .conf-i{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;border:1.3px solid currentColor;font-size:10px;font-style:italic;font-weight:700;line-height:1;cursor:pointer;vertical-align:middle;opacity:.6;-webkit-user-select:none;user-select:none}
  .conf-i:hover,.conf-i:focus-visible{opacity:1;outline:none}
  .conf-expl{margin:5px 0 1px;font-size:11px;line-height:1.45;color:var(--muted)}
  .evpop-retour .evp-head{background:linear-gradient(135deg,#0369a1,#0ea5e9)}
  .evpop-nonconf .evp-head{background:linear-gradient(135deg,#b45309,#f59e0b)}   /* vigie aérienne sans corroboration : jamais rouge */
  .evpop-evac .evp-head{background:linear-gradient(135deg,#b91c1c,#ef4444)}
  .evpop-accueil .evp-head{background:linear-gradient(135deg,#15803d,#22c55e)}
  .evpop-soli .evp-head{background:linear-gradient(135deg,#c2410c,#f97316)}
  /* Variantes de bandeau pour les AUTRES couches, même carte : zones brûlées (rouge sombre =
     périmètre officiel/presse, orange = estimation satellite), communes (rouge = évacuation
     imminente, ambre = exposée, ambre-brun = proximité), statut de feu (couleur du statut,
     cf. _fsMeta dans app.js) et entraide (vert émeraude). */
  .evpop-burnt .evp-head{background:linear-gradient(135deg,#7a1e12,#c0392b)}
  .evpop-burnt-est .evp-head{background:linear-gradient(135deg,#b45309,#f97316)}
  .evpop-town-evac .evp-head{background:linear-gradient(135deg,#b91c1c,#ff3b30)}
  .evpop-town .evp-head{background:linear-gradient(135deg,#b45309,#f59e0b)}
  .evpop-town-prox .evp-head{background:linear-gradient(135deg,#92400e,#c47b0e)}
  .evpop-fs-encours .evp-head{background:linear-gradient(135deg,#a01508,#e2340d)}
  .evpop-fs-circonscrit .evp-head{background:linear-gradient(135deg,#c2410c,#ea580c)}
  .evpop-fs-fixe .evp-head{background:linear-gradient(135deg,#b45309,#f59e0b)}
  .evpop-fs-maitrise .evp-head{background:linear-gradient(135deg,#15803d,#16a34a)}
  .evpop-fs-eteint .evp-head{background:linear-gradient(135deg,#4b5563,#6b7280)}
  .evpop-solid .evp-head{background:linear-gradient(135deg,#047857,#10b981)}
  .evpop-ac .evp-head{background:linear-gradient(135deg,#123a63,#2f6fdb)} /* aviation : bleu acier */
  .evpop-aerod .evp-head{background:linear-gradient(135deg,#1d3f66,#3b6ea5)} /* aérodrome : bleu nuit du symbole */
  .evpop-aerod-H .evp-head{background:linear-gradient(135deg,#5b1f5f,#8e3a93)} /* héliport : prune du « H » */
  .evp-ic{flex:0 0 auto;width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.2);
    display:flex;align-items:center;justify-content:center}
  .evp-ht{display:flex;flex-direction:column;min-width:0}
  /* Surtitre du bandeau : 10,5 px graisse 700 (29/09/2026). En 9,5 px graisse 800, Windows prenait « Segoe UI Black »
     (aucune graisse 800 dans Segoe UI) : lettres pâteuses et crénelées sur PC, le « pixelisé » signalé. */
  .evp-ht small{font-size:11px;line-height:1.3;letter-spacing:.06em;text-transform:uppercase;font-weight:700;opacity:.92}
  .evp-ht b{font-size:14.5px;letter-spacing:-.2px;line-height:1.25}
  /* Couleur de texte du corps de popup = variable de thème (était figée #18202e → texte
     quasi-noir sur panneau sombre en thème sombre : liste ARS/garde illisibles, signalé). */
  .evp-body{padding:10px 14px 12px;background:var(--panel);color:var(--txt)}
  .evp-quote{margin:2px 0 4px;padding:7px 10px;border-left:3px solid #0ea5e9;background:rgba(14,165,233,.08);
    border-radius:0 8px 8px 0;font-style:italic;font-size:12px;color:#0369a1}
  .evp-row{display:flex;align-items:center;gap:7px;font-size:12px;color:#697386;margin:6px 0 0}
  .evp-row svg{flex:0 0 auto;opacity:.75}
  .evp-row a{color:#1f7ae0;font-weight:600}
  /* « Feu vérifié » et « Position affinée » : couleurs lisibles dans LES DEUX thèmes (29/09/2026). En dur (#047857,
     #0e7490), elles tombaient à un contraste d'environ 2,5:1 sur le corps sombre des bulles en thème sombre. */
  .evp-verif{color:#047857;font-weight:800;gap:6px}
  .evp-affine{font-size:11px;color:#0e7490;font-weight:700}
  :root[data-theme="dark"] .evp-verif{color:#34d399}
  :root[data-theme="dark"] .evp-affine{color:#67e8f9}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .evp-verif{color:#34d399}:root:not([data-theme="light"]) .evp-affine{color:#67e8f9}}
  /* Fiche avion : le résumé IA est un PARAGRAPHE (gras/retours ligne via mdLite) · en flex, chaque
     fragment <b>/texte devenait un item empilé en colonne de 3 caractères (constaté, popup illisible).
     Bloc classique + retour à la ligne normal pour tout ce qui vit dans .ac-info. */
  .ac-info .evp-row{display:block;line-height:1.5;overflow-wrap:break-word}
  /* Ligne de TEXTE avec une mise en gras dedans (15/10/2026, fondateur, bulle « Trajet de FHRTF ») : « Passé ici <b>il y a
     6 h 52</b>. » et « <b>Ce vol :</b> vol de liaison… ». En flex (.evp-row, écart de 7 px), chaque morceau devenait un
     item : espaces en trop, point isolé, « Ce vol : » coupé sur deux lignes dans une colonne étroite, et le nom d'un site
     industriel (FIRMS) empilé lettre par lettre. Ces lignes redeviennent un bloc de texte ordinaire. */
  .evp-row.evp-txt{display:block;line-height:1.45;overflow-wrap:break-word}
  /* Bloc de DESCRIPTION d'un aeronef (modele, role, resume IA). Volontairement distinct de
     .evp-row : cette derniere est un conteneur flex pense pour « icone + libelle sur une
     ligne », et un texte riche y eclatait en colonnes de deux ou trois lettres. */
  /* ⚠️ Couleurs prises sur les VARIABLES DE THEME, jamais en dur : le corps de ces popups est
     `background:var(--panel);color:var(--txt)` et reste sombre meme en theme clair. Un premier
     essai en #3d4a5c s'affichait quasi illisible sur ce fond (signale user 2026-08-30). */
  .ac-desc{display:block;line-height:1.5;font-size:12px;color:var(--txt);opacity:.85;margin:6px 0 0;overflow-wrap:break-word;hyphens:auto}
  html[data-desk] .ac-desc{font-size:13px}
  .ac-desc strong,.ac-desc b{color:inherit;font-weight:700;opacity:1}
  /* Lecture d'activite d'un aeronef : le constat en clair, les chiffres bruts juste en dessous
     pour que le lecteur juge lui-meme. Teinte chaude reservee aux largages probables. */
  .ac-act{display:block;margin:8px 0 0;padding:8px 10px;border-radius:8px;background:rgba(127,145,175,.16);border-left:3px solid #8fa3bf;font-size:12.5px;line-height:1.45;color:var(--txt);font-weight:600}
  .ac-act-chaud{background:rgba(235,125,40,.20);border-left-color:#f08a30;color:#ffb870}
  .ac-act-mission{background:rgba(138,127,212,.18);border-left-color:#8a7fd4;color:#cfc8ff}
  /* Puce d'état en tête de la fiche avion : même code couleur que le badge rond sur la carte. */
  .ac-state{display:inline-flex;align-items:center;gap:6px;margin:8px 0 0;padding:4px 10px;border-radius:999px;font-size:11.5px;font-weight:800;letter-spacing:.2px;text-transform:uppercase}
  .ac-state::before{content:'';width:8px;height:8px;border-radius:50%;background:currentColor;box-shadow:0 0 0 3px rgba(255,255,255,.12)}
  .ac-state-interv{background:rgba(18,184,216,.18);color:#5fe0f6;border:1px solid rgba(18,184,216,.45)}
  .ac-state-mission{background:rgba(138,127,212,.18);color:#c9c2ff;border:1px solid rgba(138,127,212,.5)}
  /* Phase de vol près d'un terrain (25/09/2026) : neutre, jamais la couleur d'une intervention. */
  .ac-state-phase{background:rgba(100,116,139,.18);color:var(--txt);border:1px solid rgba(100,116,139,.55)}   /* lisible en thème clair ET sombre */
  .ac-act-phase{background:rgba(100,116,139,.16);border-left-color:#94a3b8}
  .ac-act-num{display:block;margin-top:4px;font-size:11px;font-weight:500;opacity:.75}
  /* Mobile : avec la photo (280 px) + résumé IA + 2 boutons, la fiche avion dépassait l'écran (le titre
     finissait SOUS le bandeau de l'app, « cassé sur mobile » constaté). La popup se borne à l'écran et
     défile À L'INTÉRIEUR ; la photo est plafonnée pour laisser la place aux infos. */
  /* BANDEAU FIXE, SEUL LE CORPS DÉFILE (29/09/2026, fondateur : « la croix des popups est fondue dans l'ascenseur
     pour descendre »). Tout le contenu défilait : la barre longeait aussi le bandeau coloré et passait sous la
     croix. .evpop est désormais une colonne bornée à la MÊME hauteur que son conteneur (--pop-max-h) : le bandeau
     reste en place et .evp-body défile dessous, barre fine. Le conteneur garde borne et défilement pour les rares
     bulles sans .evpop (repli inchangé) ; à hauteur égale, il ne défile jamais quand la bulle est une .evpop. */
  .evpop-wrap{--pop-max-h:min(60vh,560px)}
  .evpop-wrap .leaflet-popup-content{max-height:var(--pop-max-h);overflow-y:auto;-webkit-overflow-scrolling:touch}
  .evpop{display:flex;flex-direction:column;max-height:var(--pop-max-h)}
  .evp-head{flex:0 0 auto}
  .evp-body{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
    scrollbar-width:thin;scrollbar-color:rgba(100,116,139,.45) transparent}
  .evp-body::-webkit-scrollbar{width:9px}
  .evp-body::-webkit-scrollbar-track{background:transparent}
  .evp-body::-webkit-scrollbar-thumb{background:rgba(100,116,139,.42);border-radius:9px;border:2px solid transparent;background-clip:padding-box}
  .evp-body::-webkit-scrollbar-thumb:hover{background-color:rgba(100,116,139,.62)}
  /* CROIX : pastille ronde contrastée de 30 px (cible tactile), posée dans le bandeau et plus jamais sur la barre
     de défilement ; libellé « Fermer » posé à l'ouverture (app.js, popupopen). Leaflet la dessinait en 24 px,
     gris #757575, en Tahoma : un « × » quasi invisible sur les bandeaux rouges. Tracé en masque SVG : net à
     toutes les densités d'écran, couleur pilotée par `color`. */
  .leaflet-container a.leaflet-popup-close-button{top:8px;right:8px;width:30px;height:30px;border-radius:50%;padding:0;
    display:flex;align-items:center;justify-content:center;font:0/0 sans-serif;color:var(--muted);background:rgba(100,116,139,.14);
    z-index:5;transition:background-color .15s,color .15s}
  .leaflet-container a.leaflet-popup-close-button span{display:none}
  .leaflet-container a.leaflet-popup-close-button::before{content:"";width:13px;height:13px;background:currentColor;
    -webkit-mask:var(--ic-x) center/contain no-repeat;mask:var(--ic-x) center/contain no-repeat}
  .leaflet-container a.leaflet-popup-close-button:hover,.leaflet-container a.leaflet-popup-close-button:focus-visible{background:rgba(100,116,139,.28);color:var(--txt);outline:none}
  .leaflet-container .evpop-wrap a.leaflet-popup-close-button{color:#fff;background:rgba(0,0,0,.24);box-shadow:inset 0 0 0 1px rgba(255,255,255,.28)}
  .leaflet-container .evpop-wrap a.leaflet-popup-close-button:hover,.leaflet-container .evpop-wrap a.leaflet-popup-close-button:focus-visible{background:rgba(0,0,0,.38);color:#fff}
  .evpop-wrap .evp-head{padding-right:46px}
  html[data-desk] .evpop-wrap .evp-head{padding-right:50px}
  /* Bulles simples (sans bandeau) : une cale flottante réserve le coin de la croix ; le titre passe à la ligne avant
     elle, le reste du texte garde toute la largeur. */
  .leaflet-popup:not(.evpop-wrap) .leaflet-popup-content::before{content:"";float:right;width:30px;height:26px;margin:-4px -7px 4px 8px}
  /* CASES « moyens engagés » (_moyensCases) : chiffre calé en BAS de sa case, alignés d'une case à l'autre même
     quand un libellé tient sur deux lignes. */
  .moy-cases{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 2px}
  .moy-titre{margin:8px 0 -1px;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
  .moy-case{flex:1 1 44%;min-width:96px;display:flex;flex-direction:column;justify-content:space-between;gap:3px;
    background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:7px 9px}
  /* Libellé en minuscules (11 px) et coupure aux ESPACES seulement : en capitales, « BOMBARDIERS » ne tenait
     pas dans une demi-case et `overflow-wrap:anywhere` des bulles le coupait en « BOMBARDIER / S ». */
  .moy-case-k{display:flex;align-items:flex-start;gap:5px;font-size:11px;line-height:1.25;font-weight:600;
    color:var(--muted);overflow-wrap:normal;word-break:normal}
  .moy-case-k svg{flex:0 0 auto;margin-top:-1px}
  .moy-case-v{font-size:18px;font-weight:800;line-height:1.1;color:var(--txt);font-variant-numeric:tabular-nums}
  /* Moyens OBSERVÉS (ADS-B, 07/10/2026) : case pointillée quand le chiffre vient seulement de l'observation, mention courte. */
  .moy-case-obs{border-style:dashed}
  .moy-case-o{font-size:11px;font-weight:700;line-height:1.2;color:var(--muted)}
  /* BOUTONS D'ACTION DES BULLES ET FICHES DE FEUX, PLEINS ET COMPACTS (14/10/2026, 12 h 05, fondateur : « les boutons ne
     doivent pas être semi-transparents façon IA mais colorés »). La v11.54 avait passé les actions secondaires en teinte
     douce (fond pâle, texte coloré) : sur téléphone, en sombre surtout, on aurait dit des boutons presque transparents.
     Désormais TOUS les boutons sont PLEINS : aplat coloré à dégradé subtil (deux nuances de la même couleur), texte et
     icône blancs (AA : 4,5:1 au moins sur CHAQUE nuance, vérifié par tests/bulles-retro-boutons-navigateur.test.mjs),
     filet de la nuance foncée, légère ombre. Une couleur par action : fiche en bleu (action principale, 44 px, pleine
     largeur), « Revoir le feu » en violet, presse en orangé, témoignage en vert, page dédiée en ardoise ; les secondaires
     restent COMPACTS (40 px, 14 px) et en rangée (pas les gros boutons empilés de la v11.50). Coins homogènes (réglage
     « Arrondi des angles » compris), enfoncement à l'appui, aucune surbrillance au toucher, contour au clavier seulement.
     Mêmes couleurs en thème clair et sombre (seule l'ombre s'approfondit sur fond sombre). */
  :root{--evp-focus:#2563eb;--evp-ombre:0 1px 2px rgba(15,23,42,.22),0 2px 6px -2px rgba(15,23,42,.18)}
  :root[data-theme="dark"]{--evp-focus:#93c5fd;--evp-ombre:0 1px 2px rgba(0,0,0,.45),0 2px 8px -2px rgba(0,0,0,.4)}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--evp-focus:#93c5fd;--evp-ombre:0 1px 2px rgba(0,0,0,.45),0 2px 8px -2px rgba(0,0,0,.4)}}
  .evp-btn,.leaflet-container a.evp-btn{--b1:#475569;--b2:#334155;
    box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:6px;width:100%;min-width:0;
    min-height:40px;margin:8px 0 0;padding:8px 12px;border:1px solid var(--b2);border-radius:10px;
    background-color:var(--b1);background-image:linear-gradient(180deg,var(--b1),var(--b2));color:#fff;
    box-shadow:inset 0 1px 0 rgba(255,255,255,.16),var(--evp-ombre);
    font:inherit;font-size:14px;font-weight:600;line-height:1.2;letter-spacing:0;text-align:center;text-decoration:none;
    cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:manipulation;user-select:none;-webkit-user-select:none;
    transition:filter .15s ease,transform .08s ease,box-shadow .15s ease}
  .leaflet-container a.evp-btn,.leaflet-container a.evp-btn:hover,.leaflet-container a.evp-btn:visited{color:#fff}
  .evp-btn span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .evp-btn svg{flex:0 0 auto;width:16px;height:16px;color:#fff}
  @media (hover:hover){.evp-btn:hover{filter:brightness(1.08)}}
  .evp-btn:active{transform:translateY(1px) scale(.985);filter:brightness(.94);box-shadow:inset 0 2px 4px rgba(0,0,0,.25)}
  .evp-btn:focus:not(:focus-visible){outline:none}
  .evp-btn:focus-visible{outline:2px solid var(--evp-focus);outline-offset:2px}
  .evp-btn:disabled{cursor:default;filter:saturate(.6) brightness(.95)}
  .evp-btn[hidden],.leaflet-container a.evp-btn[hidden]{display:none!important}
  .evp-btn-1,.leaflet-container a.evp-btn-1{--b1:#2563eb;--b2:#1d4ed8;min-height:44px;margin-top:12px;padding:10px 14px;font-size:15px}
  .evp-btn-1 span{white-space:normal;text-wrap:balance}
  /* Téléphone : l'action principale tient sur une ligne (14,5 px ; icône retirée sous 400 px de large). */
  html:not([data-desk]) .evp-btn-1{font-size:14.5px;padding:10px}
  @media (max-width:399px){html:not([data-desk]) .evp-btn-1 svg{display:none}}
  .evp-btn-retro,.leaflet-container a.evp-btn-retro{--b1:#7c3aed;--b2:#6d28d9}
  .evp-btn-presse,.leaflet-container a.evp-btn-presse{--b1:#c2410c;--b2:#9a3412}
  .evp-btn-temoin,.leaflet-container a.evp-btn-temoin{--b1:#15803d;--b2:#166534}
  .evp-btn-page,.leaflet-container a.evp-btn-page{--b1:#475569;--b2:#334155}
  /* Rangée des actions secondaires : sur téléphone, « Revoir le feu » sur toute la largeur au-dessus de Presse | Témoigner ;
     sur ordinateur, les trois sur une ligne ; vide (aucune action) : aucune place prise. */
  .evp-actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:6px}
  .evp-actions:empty{display:none}
  .evp-actions .evp-btn,.leaflet-container .evp-actions a.evp-btn{margin:0;padding:8px 10px}
  .evp-actions .evp-btn-retro{grid-column:1/-1}
  .evp-actions>.evp-btn:only-child,.evp-actions>.evp-btn[hidden]+.evp-btn:last-child:nth-child(2){grid-column:1/-1}
  html[data-desk] .evp-actions{display:flex;flex-wrap:wrap}
  html[data-desk] .evp-actions .evp-btn,html[data-desk] .leaflet-container .evp-actions a.evp-btn{flex:1 1 auto;width:auto;padding:8px;gap:5px}
  /* Fiche latérale : « Fiche complète » et « Revoir le feu » côte à côte, mêmes boutons pleins. */
  .d-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-top:10px}
  .d-actions .evp-btn,.leaflet-container .d-actions a.evp-btn{margin:0}
  /* BULLE D'UN FEU (.evpop-feu) : bandeau fin (badge de statut compact, nom lisible, précision du statut en petit),
     corps sur une grille de 4/8 px, faits clés en tête, liens « Comprendre » et rythme de relecture en petit en bas.
     Largeur : 380 px sur ordinateur, l'écran moins 12 px de chaque côté sur téléphone (bulles grandes, 14/10/2026). */
  .evpop-feu-wrap .leaflet-popup-content-wrapper{max-width:min(calc(100vw - 24px),420px)}
  html[data-desk] .evpop-feu-wrap .leaflet-popup-content-wrapper{max-width:380px}
  html[data-desk] .evpop-feu-wrap .leaflet-popup-content{min-width:352px}
  .evpop-feu .evp-head,html[data-desk] .evpop-feu .evp-head{align-items:flex-start;gap:10px;padding:10px 48px 10px 12px}
  html[data-desk] .evpop-feu .evp-head{padding:12px 52px 12px 16px}
  .evpop-feu .evp-ic{width:28px;height:28px;margin-top:1px}
  .evpop-feu .evp-ht small{display:contents}
  .evp-badge{order:0;align-self:flex-start;max-width:100%;padding:2px 8px;border-radius:999px;background:rgba(255,255,255,.2);
    box-shadow:inset 0 0 0 1px rgba(255,255,255,.24);font-size:10.5px;font-weight:700;letter-spacing:.05em;line-height:16px;text-transform:uppercase}
  .evp-sep{display:none}
  .evpop-feu .evp-ht b,html[data-desk] .evpop-feu .evp-ht b{order:1;margin-top:4px;font-size:16px;font-weight:700;letter-spacing:-.01em;line-height:1.25}
  .evp-suite{order:2;margin-top:2px;font-size:12px;font-weight:500;line-height:1.35;letter-spacing:0;text-transform:none;opacity:.94}
  .evpop-feu .evp-body{padding:10px 14px 12px}
  html[data-desk] .evpop-feu .evp-body{padding:12px 16px 14px}
  .evpop-feu .evp-body>:first-child{margin-top:0}
  .evpop-feu .evp-row,html[data-desk] .evpop-feu .evp-row{margin:4px 0 0;font-size:12.5px;line-height:1.4;color:var(--muted)}
  .evpop-feu .evp-row.evp-verif{color:#047857}
  :root[data-theme="dark"] .evpop-feu .evp-row.evp-verif{color:#34d399}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .evpop-feu .evp-row.evp-verif{color:#34d399}}
  .evpop-feu .evp-fait,html[data-desk] .evpop-feu .evp-fait{margin-top:6px;font-size:14px;font-weight:700;color:var(--txt)}
  .evpop-feu .evp-dates .evp-date{margin-top:2px;font-size:12px;line-height:1.4;color:var(--muted)}
  .evpop-feu .evp-dates .evp-date:first-child{margin-top:4px}
  .evpop-feu .evp-note,html[data-desk] .evpop-feu .evp-note{display:block;margin-top:12px;font-size:12.5px;line-height:1.45;color:var(--txt);opacity:.88}
  .evpop-feu .moy-titre{margin-top:12px;font-size:10.5px}
  .evpop-feu .moy-cases{margin:4px 0 0}
  .evpop-feu .moy-case{padding:6px 8px;border-radius:8px;gap:2px}
  .evpop-feu .moy-case-v{font-size:16px}
  .evpop-feu .fiches-utiles{margin-top:10px;font-size:11.5px;line-height:1.5;color:var(--muted)}
  .evpop-feu .fiches-utiles a{font-weight:600}
  .evpop-feu .evp-rythme{margin-top:10px;padding-top:8px;border-top:1px solid var(--line);font-size:11px;line-height:1.45;color:var(--muted)}
  /* Croix discrète : pastille de 32 px dans le bandeau, sans anneau, zone de toucher de 40 px. */
  .leaflet-container .evpop-feu-wrap a.leaflet-popup-close-button{top:8px;right:8px;width:32px;height:32px;background:rgba(255,255,255,.16);box-shadow:none}
  .leaflet-container .evpop-feu-wrap a.leaflet-popup-close-button::after{content:"";position:absolute;inset:-4px;border-radius:50%}
  .leaflet-container .evpop-feu-wrap a.leaflet-popup-close-button:hover,.leaflet-container .evpop-feu-wrap a.leaflet-popup-close-button:focus-visible{background:rgba(255,255,255,.3)}
  .leaflet-container .evpop-feu-wrap a.leaflet-popup-close-button:focus-visible{outline:2px solid #fff;outline-offset:1px}
  /* HAUTEUR (bulles grandes, 14/10/2026, 12 h 05, fondateur : « elle ne s'ouvre pas en grand, on doit beaucoup scroller ») :
     plus de plafond à 460 px. app.js (_evpAppliquerGeo) pose sur chaque bulle de feu la hauteur EXACTE disponible entre le
     bas de l'en-tête et le haut réel du volet du bas (replié ou rangé en barre mini), moins une marge et la pointe ; le
     corps ne défile que si le contenu dépasse. Valeurs ci-dessous : repli avant le calcul (volet replié à --peek sur
     téléphone, fenêtre moins les marges sur ordinateur). La note longue est repliée sur 4 lignes (« Lire la suite »). */
  html:not([data-desk]) .evpop-feu-wrap{--pop-max-h:max(300px,calc(100vh - var(--peek) - 96px))}
  @supports (height:100dvh){html:not([data-desk]) .evpop-feu-wrap{--pop-max-h:max(300px,calc(100dvh - var(--peek) - 96px))}}
  html[data-desk] .evpop-feu-wrap{--pop-max-h:max(320px,calc(100vh - 140px))}
  html:not([data-desk]) .evpop-feu .evp-note.evp-replie{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;line-clamp:4;overflow:hidden}
  .evp-suite-btn{all:unset;box-sizing:border-box;display:inline-flex;align-items:center;min-height:32px;margin:0 0 -4px;font-size:12px;font-weight:600;color:var(--accent);cursor:pointer;-webkit-tap-highlight-color:transparent}
  .evp-suite-btn:focus-visible{outline:2px solid var(--evp-focus);outline-offset:2px;border-radius:4px}
  .ac-info img{max-height:170px;object-fit:cover}
  /* Photo d'un appareil (06/10/2026, « photos floues ») : vignette LARGE (Planespotters, 420 px) à la largeur de la fiche ;
     petite vignette (airport-data, 150 px) à sa TAILLE RÉELLE, jamais étirée. L'image et la légende mènent à la page
     de la photo (conditions de Planespotters : lien simple sur la vignette, photographe nommé à côté). */
  .ac-photo{margin:4px 0 2px}
  .ac-photo-a{display:block;line-height:0;border-radius:8px}
  .ac-photo img{display:block;width:100%;height:auto;border-radius:8px}
  .ac-photo-reelle img{width:auto;max-width:100%;margin:0 auto}
  .ac-photo figcaption{margin-top:3px}
  .ac-photo figcaption a{color:inherit;text-decoration:underline;text-underline-offset:2px;white-space:nowrap}
  /* Appareil cité dans une bulle (zone de travail, badge d'intervention, moyens observés d'un feu) : ouvre sa fiche. */
  .ac-fiche-lien{all:unset;cursor:pointer;color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;padding:2px 0;border-radius:4px}
  .ac-fiche-lien:hover{text-decoration-thickness:2px}
  .ac-fiche-lien:focus-visible{outline:2px solid var(--accent,#4a9bec);outline-offset:2px}
  .evp-garde{display:flex;align-items:flex-start;gap:7px;font-size:11px;line-height:1.4;color:#92500b;
    background:rgba(245,158,11,.12);border-radius:8px;padding:6px 9px;margin-top:9px}
  .evp-garde svg{flex:0 0 auto;margin-top:1px}
  .evp-date{font-size:11px;color:#9aa0aa;margin-top:8px}
  /* Avertissement ambre (garde) : le texte #92500b (brun sombre) devient illisible sur le
     fond ambre translucide POSÉ SUR panneau sombre → on l'éclaircit en thème sombre. */
  :root[data-theme="dark"] .evp-garde{color:#f2b559}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .evp-garde{color:#f2b559}}

  /* ── FLAMME DE FOYER (amas) · silhouette animée posée sur la cellule la plus chaude ──
     Les cellules satellite restent des POINTS (pas de surcharge) ; seul le CENTRE de chaque amas
     porte une flamme · même tracé que le logo de l'app (cohérence de marque), dégradé cuit dans le
     SVG. Animation = transform/opacity UNIQUEMENT (composité GPU, zéro repaint), coupée en mode
     léger et si le système demande moins d'animations. Ancre à la POINTE BASSE : la flamme « pousse »
     depuis le point chaud, elle ne le recouvre pas. */
  .fire-flame{pointer-events:auto}
  .fire-flame .fscale{position:absolute;inset:0;transform-origin:50% 100%}
  /* Halo de chaleur DERRIÈRE la flamme : c'est lui qui donne la « dimension » · sans lui, la
     silhouette se fondait dans les points jaunes et la zone brûlée rouge (retour utilisateur).
     Radial doux qui respire lentement (transform/opacity seulement). */
  /* Durées PILOTÉES par l'intensité de l'amas (variables CSS posées par drawFires) : un petit foyer
     respire lentement, un feu violent s'agite davantage · bornées côté JS (jamais < 1,4 s : l'œil doit
     lire « feu vif », pas « alarme stroboscopique »). */
  .fire-flame .fglow{position:absolute;left:-32%;top:-18%;width:164%;height:164%;border-radius:50%;
    background:radial-gradient(circle at 50% 62%,rgba(255,170,40,.55) 0%,rgba(255,110,20,.32) 38%,rgba(226,52,13,0) 68%);
    transform-origin:50% 62%;animation:fflGlow var(--fgd,2.5s) ease-in-out infinite}
  /* Corps de flamme : PAS de rotation (le balancement pendulaire faisait « décoration », pas feu).
     Une RESPIRATION verticale discrète (scaleY, origine à la base) + le cœur interne qui scintille
     en opacité, légèrement déphasé : c'est le langage visuel d'une vraie flamme calme. 3 nœuds
     animés par marqueur, transform/opacity uniquement → composité GPU, fluide sur tout téléphone. */
  .fire-flame .ffl{position:absolute;inset:0;transform-origin:50% 96%;
    filter:drop-shadow(0 0 6px rgba(255,120,20,.7)) drop-shadow(0 1px 2px rgba(40,8,0,.4));
    animation:fflBreath var(--fbd,2.1s) ease-in-out infinite}
  .fire-flame svg{position:absolute;inset:0;width:100%;height:100%}
  .fire-flame .fin{transform-origin:50% 94%;animation:fflCore var(--fcd,1.4s) ease-in-out infinite}
  @keyframes fflGlow{0%,100%{transform:scale(1);opacity:.7}50%{transform:scale(1.12);opacity:1}}
  @keyframes fflBreath{0%,100%{transform:scaleY(1)}50%{transform:scaleY(1.045)}}
  @keyframes fflCore{0%,100%{opacity:.82;transform:scaleY(1)}55%{opacity:1;transform:scaleY(1.07)}}
  body.leger .fire-flame .ffl,body.leger .fire-flame .fin,body.leger .fire-flame .fglow{animation:none}
  @media (prefers-reduced-motion:reduce){.fire-flame .ffl,.fire-flame .fin,.fire-flame .fglow{animation:none}}
  /* ÉTATS VISUELS DU FEU (2026-08-21) : même flamme recolorée + (dés)animée selon le statut, pour lire
     l'évolution d'un coup d'œil. en_cours = orange animé (défaut) ; fixé = ambre ; maîtrisé = vert statique ;
     éteint = gris estompé statique (conservé 48 h puis retiré progressivement). Recoloration par filter
     (le dégradé SVG n'est pas variabilisable) ; .flame-static coupe l'animation (feu qui ne menace plus). */
  .fire-flame.flame-st-fixe .fscale,.fire-flame.flame-st-contenu .fscale{filter:hue-rotate(26deg) saturate(1.05)}
  .fire-flame.flame-st-maitrise .fscale{filter:hue-rotate(96deg) saturate(1.15) brightness(1.03)}
  .fire-flame.flame-st-suspect .fscale{filter:saturate(.5) brightness(1.06);opacity:.62}
  /* ÉTEINT v2 (2026-08-26, retour fondateur : « les flammes grises ne se voient pas ») : le grisé
     estompé disparaissait sur le fond satellite. Repère MÉMORIEL propre : pastille blanche nette
     + silhouette de flamme gris ardoise, statique, sans halo (fglow coupé) — lisible sur tout fond,
     clairement « feu terminé » (méga-feux conservés à vie + fenêtre 48 h des feux éteints). */
  .fire-flame.flame-st-eteint .fglow{display:none}
  .fire-flame.flame-st-eteint::before{content:"";position:absolute;left:50%;top:44%;width:118%;height:118%;transform:translate(-50%,-50%);background:rgba(255,255,255,.94);border:1.5px solid rgba(96,108,126,.6);border-radius:50%;box-shadow:0 1px 4px rgba(20,30,50,.28)}
  .fire-flame.flame-st-eteint .fscale{filter:grayscale(1) brightness(.66) contrast(1.1);opacity:1;transform:scale(.8);transform-origin:50% 88%}
  .fire-flame.flame-static .ffl,.fire-flame.flame-static .fin,.fire-flame.flame-static .fglow{animation:none}
  /* FEU STRUCTUREL (bâtiment/toiture/véhicule, flag backend `structurel`, 2026-08-26) : à dissocier
     d'un vrai feu de VÉGÉTATION d'un coup d'œil — flamme réduite et désaturée, halo coupé, petite
     pastille maison (⌂) à la base. Le panache de fumée modèle forêt est aussi coupé (app.js). */
  /* DÉTECTION SATELLITE NON CONFIRMÉE (2026-08-26) : amas ≥ 25 MW cumulés mais ni corroboré par un
     foyer déclaré ni franchement puissant → rond orange pulsant discret au lieu de la flamme
     alarmante. Le pulse dit « point chaud à confirmer », pas « incendie majeur ». */
  .aero-drop .adc{position:absolute;left:50%;top:50%;width:10px;height:10px;transform:translate(-50%,-50%) rotate(45deg);background:#1f8fd6;border:2px solid #fff;border-radius:2px;box-shadow:0 1px 4px rgba(0,0,0,.5)}
  .aero-drop .adr{position:absolute;left:50%;top:50%;width:26px;height:26px;transform:translate(-50%,-50%);border:1.5px dashed rgba(31,143,214,.85);border-radius:50%;pointer-events:none}
  body.leger .aero-drop .adr{opacity:.45}
  .det-hot .dhc{position:absolute;left:50%;top:50%;width:11px;height:11px;transform:translate(-50%,-50%);background:#ff8a1f;border:2px solid #fff;border-radius:50%;box-shadow:0 1px 4px rgba(0,0,0,.5)}
  .det-hot .dhr{position:absolute;left:50%;top:50%;width:11px;height:11px;transform:translate(-50%,-50%);border:2px solid rgba(255,138,31,.8);border-radius:50%;animation:dhPulse 2.2s ease-out infinite;pointer-events:none}
  @keyframes dhPulse{0%{width:11px;height:11px;opacity:.9}100%{width:34px;height:34px;opacity:0}}
  body.leger .det-hot .dhr{animation:none;opacity:.35}
  @media (prefers-reduced-motion:reduce){.det-hot .dhr{animation:none;opacity:.35}}
  .fire-flame.flame-urbain .fglow{display:none}
  .fire-flame.flame-urbain .fscale{filter:saturate(.4) brightness(.96);transform:scale(.78);transform-origin:50% 88%}
  .fire-flame.flame-urbain::after{content:"\2302";position:absolute;left:62%;bottom:-2px;width:13px;height:13px;background:rgba(255,255,255,.94);border:1px solid rgba(96,108,126,.55);border-radius:50%;font-size:9px;line-height:12px;text-align:center;color:#334155;font-weight:700;pointer-events:none}
  /* Flamme d'un SIGNALEMENT citoyen (« à confirmer ») : MÊME flamme animée qu'un foyer satellite, mais
     posée sur un petit anneau pointillé blanc à sa base + légère désaturation → l'utilisateur voit un
     vrai feu, tout en comprenant qu'il n'est pas (encore) confirmé officiellement. Honnêteté visuelle. */
  .fire-flame.sig-flame .ffl{filter:drop-shadow(0 0 5px rgba(255,150,40,.6)) drop-shadow(0 1px 2px rgba(40,8,0,.4)) saturate(.9)}
  .fire-flame.sig-flame .fscale::after{content:"";position:absolute;left:50%;bottom:0;width:14px;height:5px;transform:translateX(-50%);border:1.5px dashed rgba(255,255,255,.82);border-radius:50%;pointer-events:none}

  /* Bouton d'ouverture + tiroir latéral (calques/aérien/légende) */
  /* Languette verticale sur le bord gauche → ouvre le tiroir */
  .drawerbtn{position:absolute;right:0;top:46%;transform:translateY(-50%);z-index:1350;
    background:var(--panel);/* opaque (ex-backdrop-filter retiré : artefact de compositing au zoom+déplacement sur la carte) */
    border:1px solid var(--line);border-right:0;border-radius:13px 0 0 13px;
    padding:15px 8px;font-size:11.5px;font-weight:800;color:var(--txt);box-shadow:-3px 2px 14px rgba(20,30,50,.18);cursor:pointer;
    writing-mode:vertical-rl;text-orientation:mixed;letter-spacing:.04em;transition:opacity .2s ease}
  /* Gardée comme les autres règles sombres (13/10/2026, audit B-15) : en thème clair FORCÉ sur un système sombre, la
     languette restait sombre au milieu d'une interface claire. */
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .drawerbtn{background:rgba(20,26,38,.55);color:#eef}}
  :root[data-theme="dark"] .drawerbtn{background:rgba(20,26,38,.55);color:#eef}
  /* Appel du regard à l'ouverture : la languette sort trois fois de quelques pixels, puis s'immobilise
     DÉFINITIVEMENT. Elle ne boucle pas, volontairement : sur une app de sécurité, un élément qui bouge en
     permanence entre en concurrence avec les vrais signaux d'alerte (pastille d'évacuation, barre de
     proximité) qui, eux, pulsent pour une raison. Le mouvement dit « je suis là », pas « urgence ».
     Seul `transform` est animé (composité par le GPU, aucun repaint) → gratuit même sur téléphone faible. */
  @keyframes tabPeek{
    0%,4%,16%,30%,42%,62%,74%,100%{transform:translate(0,-50%)}
    9%,35%{transform:translate(-9px,-50%)}
    67%{transform:translate(-6px,-50%)}
  }
  .drawerbtn.peek{animation:tabPeek 5.4s cubic-bezier(.34,1.35,.5,1) .9s 1 both}
  /* Réglage système « animations réduites » : on n'insiste pas. */
  @media (prefers-reduced-motion:reduce){.drawerbtn.peek{animation:none}}
  /* Animation continue du bouton Rétrospective : voir #modeSeg .segnav (retroFlame/retroFlicker),
     remplace l'ancien appel du regard ponctuel (3 nudges puis stop), jugé trop discret. */
  #drawer:not(.closed)~.drawerbtn{opacity:0;pointer-events:none}
  /* Mobile : sheet ouvert → on cache l'onglet Légende (sinon il chevauche le sheet) */
  @media (max-width:1099px){#app:has(#sheet:not(.collapsed)) .drawerbtn{opacity:0;pointer-events:none}}
  /* Sens INVERSE, même principe : tiroir ouvert → le panneau du bas et les boutons de période
     s'effacent complètement (pas juste repliés · leur pastille de rappel « Situation » restait
     visible dans le coin, à côté du tiroir tout juste ouvert, comme si les deux étaient ouverts
     à la fois). :has() depuis #app plutôt qu'un combinateur ~ : indépendant de l'ordre des
     éléments dans le DOM, même idiome que la règle juste au-dessus. */
  @media (max-width:1099px){
    #app:has(#drawer:not(.closed)) #sheet,
    #app:has(#drawer:not(.closed)) #firmsCtl,
    #app:has(#drawer:not(.closed)) #horizonSeg{opacity:0;pointer-events:none;transition:opacity .2s ease}
  }
  /* 30/09/2026 (fondateur : « le volet de la carte inondation est mieux et plus large : le même ici ») : largeur, lignes
     pleine largeur avec interrupteur, tailles de texte reprises de la carte des inondations. */
  #drawer{position:absolute;top:0;right:0;left:auto;bottom:0;width:min(330px,88vw);max-width:88vw;z-index:1400;
    background:var(--panel);border-left:1px solid var(--line);box-shadow:-8px 0 40px rgba(20,30,50,.22);display:flex;flex-direction:column;
    transition:transform .28s cubic-bezier(.22,1,.36,1);padding-top:calc(env(safe-area-inset-top) + 6px)}
  #drawer.closed{transform:translateX(103%)}
  /* Sur mobile, le tiroir passait SOUS le header visuellement (top:0, z-index supérieur) · il le
     recouvrait au lieu de glisser proprement en dessous. `--h-header` est la hauteur RÉELLE
     mesurée en JS (ResizeObserver), pas devinée : elle change avec la safe-area, la présence
     d'une barre d'onglets, la taille de police système. Le repli 56px ne sert qu'avant la toute
     première mesure (quelques ms au chargement). Desktop inchangé (le header y est plus bas). */
  @media (max-width:1099px){#drawer{top:var(--h-header,56px)}}
  .drawer-head{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid var(--line);font-size:14px}
  /* Icône de calques empilés (le sujet du volet), dessinée au trait comme le reste de l'interface.
     `currentColor` : elle suit la couleur du titre, donc les thèmes clair et sombre sans règle en plus. */
  .drawer-head .dh-ic{width:17px;height:17px;flex:0 0 auto;margin-right:7px;vertical-align:-3px;display:inline-block;opacity:.9}
  .drawer-head b{display:flex;align-items:center;min-width:0}
  .drawer-head .x{cursor:pointer;color:var(--muted);font-size:21px;line-height:1;padding:0 4px}
  /* Déplacé en TÊTE du tiroir (badge de version + fréquentation visibles sans défiler) :
     le bord de séparation passe donc du haut au bas, et le rappel de comment mise en marge
     disparaît puisque rien ne le précède plus. */
  .drawer-ver{text-align:center;padding:5px 0 12px;margin-bottom:6px;border-bottom:1px solid var(--line)}
  .vtag{display:inline-block;font-size:10.5px;font-weight:800;letter-spacing:.05em;color:var(--muted);
    background:var(--panel2);border:1px solid var(--line);border-radius:20px;padding:3px 11px}
  /* Badge « stable » : SÉPARÉ du numéro de build, qui lui reste technique et change à chaque
     déploiement. On ne veut pas laisser croire que chaque numéro de build est une promesse de
     stabilité · seul ce badge, posé à la main après une session de correctifs conséquente,
     l'affirme. Vert discret, pas d'animation : une info de confiance, pas une alerte. */
  .vtag-stable{display:inline-block;font-size:10px;font-weight:800;letter-spacing:.04em;
    color:#fff;background:#16a34a;border:1px solid #15803d;
    border-radius:20px;padding:3px 9px;margin-left:5px}
  /* max(20px, …) et non une simple addition : la barre système Android à 3 boutons occupe
     réellement de la place, mais `env(safe-area-inset-bottom)` y renvoie 0 (piège déjà rencontré
     sur ce projet, cf. rétrospective) · sans le plancher, le bas du tiroir se retrouverait sous
     la barre sans que rien ne le compense. iOS (safe-area non nulle) en profite aussi. */
  .drawer-body{overflow-y:auto;padding:12px 14px max(20px,calc(env(safe-area-inset-bottom) + 14px));display:flex;flex-direction:column;gap:11px;-webkit-overflow-scrolling:touch}
  .dsec{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:800;margin-top:3px}
  .airbtn{background:linear-gradient(180deg,#2b8fd6,#1f7ae0);color:#fff;border:0;border-radius:11px;padding:11px 12px;font-size:13px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:8px;box-shadow:0 3px 10px rgba(31,122,224,.28)}
  .airbtn .n{background:rgba(255,255,255,.28);border-radius:10px;padding:1px 7px;font-size:11px;min-width:18px;text-align:center}
  .dlegend{display:flex;flex-direction:column;gap:9px;font-size:12px;line-height:1.45;color:var(--muted)}
  .dlegend b{color:var(--txt)} .dlegend i{color:var(--muted)}
  .dlegend .lg{display:inline-block;width:17px;height:12px;border-radius:3px;vertical-align:-1px;margin-right:2px}
  .dlegend .lgi{display:inline-flex;align-items:center;width:28px;flex:0 0 auto;vertical-align:-3px}
  .dlegend>div{display:flex;align-items:flex-start;gap:2px}
  /* Toast in-app (confirmations) · remplace les notifications système pour l'UI */
  #toast{position:fixed;left:50%;bottom:calc(84px + env(safe-area-inset-bottom));transform:translate(-50%,20px);
    max-width:88vw;background:#111826;color:#f2f4f8;border:1px solid #263041;border-radius:12px;
    padding:11px 15px;font:600 13px/1.4 system-ui,sans-serif;box-shadow:0 8px 28px rgba(0,0,0,.4);
    z-index:6000;opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;text-align:center}
  #toast.show{opacity:1;transform:translate(-50%,0)}
  /* Bulle d'accueil de « Signaler », ancrée au bouton (app.js, bulleSignaler) : mêmes couleurs que le toast, flèche
     calée sur le centre du bouton (--fleche). */
  .sig-coach{position:fixed;z-index:6000;max-width:min(290px,calc(100vw - 16px));background:#111826;color:#f2f4f8;
    border:1px solid #263041;border-radius:12px;padding:10px 13px;font-size:13px;font-weight:600;line-height:1.4;
    box-shadow:0 8px 28px rgba(0,0,0,.4);opacity:0;transform:translateY(6px);transition:opacity .25s,transform .25s;cursor:pointer}
  .sig-coach.show{opacity:1;transform:none}
  .sig-coach::after{content:"";position:absolute;left:var(--fleche,50%);bottom:-7px;width:12px;height:12px;background:#111826;
    border-right:1px solid #263041;border-bottom:1px solid #263041;transform:translateX(-50%) rotate(45deg)}
  .sig-coach.dessous::after{bottom:auto;top:-7px;transform:translateX(-50%) rotate(225deg)}
  @media (prefers-reduced-motion:reduce){.sig-coach{transition:none}}
  /* Bannière « bienvenue depuis l'ancien domaine » (2026-08-18) — mobile-first, en barre pleine largeur
     tout en haut. flex-wrap : sur petit écran, si le bouton fermer ne rentre plus à côté du texte, il
     passe à la ligne au lieu d'écraser/tronquer le message (testé à 360px, le plus étroit courant). */
  #migreBanner{position:fixed;top:0;left:0;right:0;z-index:6500;display:none;flex-wrap:wrap;align-items:center;
    gap:10px;padding:calc(10px + env(safe-area-inset-top)) 14px 10px;background:var(--accent);color:#fff;
    box-shadow:var(--shadow);font:600 13px/1.4 system-ui,sans-serif}
  #migreBanner.show{display:flex}
  #migreBanner .mb-txt{flex:1 1 220px;min-width:0}
  #migreBanner .mb-txt b{font-weight:800}
  #migreBanner .mb-close{flex:0 0 auto;background:rgba(255,255,255,.22);border:0;color:#fff;width:30px;height:30px;
    border-radius:50%;font-size:17px;line-height:1;cursor:pointer}
  #migreBanner .mb-close:active{background:rgba(255,255,255,.35)}
  @media (max-width:420px){ #migreBanner{font-size:12.5px} }
  /* Bloc « Trafic » (fermetures) en tête du fil Actu */
  .na.tf{cursor:pointer}
  .na.tf .thumb.tf-ic{display:flex;align-items:center;justify-content:center;font-size:22px;background:var(--tc,#b23a2e);color:#fff}
  /* Pastille ou étiquette masquée par le désencombrement (voir _desencombrerPastilles, app.js). */
  .fv-encombre{display:none !important}
  .tf-more{padding:7px 14px;font-size:12px;color:var(--muted)}
  /* Liste déroulante des fermetures/événements routiers (fil Actu, 17/09/2026). */
  .tf-block{border:1px solid rgba(120,130,150,.18);border-radius:12px;overflow:hidden;margin:0 0 10px}
  .tf-head{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;background:rgba(120,130,150,.07);border:0;cursor:pointer;color:var(--txt);font:inherit;text-align:left}
  .tf-head:active{background:rgba(120,130,150,.14)}
  .tf-hic{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:8px;background:var(--tc,#b23a2e);color:#fff;font-size:15px;flex:0 0 auto}
  .tf-htxt{flex:1;min-width:0;font-size:13px;font-weight:800}
  .tf-chev{transition:transform .2s;color:var(--muted);font-size:13px;flex:0 0 auto}
  .tf-head.open .tf-chev{transform:rotate(180deg)}
  .tf-list{max-height:min(46vh,340px);overflow-y:auto;-webkit-overflow-scrolling:touch}
  .tf-row{display:flex;align-items:center;gap:9px;width:100%;padding:8px 12px;border:0;border-top:1px solid rgba(120,130,150,.12);background:transparent;cursor:pointer;color:var(--txt);font:inherit;text-align:left}
  .tf-row:active{background:rgba(120,130,150,.12)}
  .tf-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
  .tf-rl{flex:0 0 auto;font-size:12.5px;white-space:nowrap}
  .tf-rloc{flex:1;min-width:0;font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right}
  /* Popups carte (bulles) responsive : ne débordent jamais l'écran, texte qui s'enroule */
  /* Villes menacées = pastille bordée blanche + icône 🏠 (jamais confondue avec un foyer). Rouge pulsé = imminent. */
  .town-mk{background:none;border:0}
  .town-pin{width:20px;height:20px;border-radius:50%;border:2px solid #fff;box-shadow:0 1px 3px rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;font-size:11px;line-height:1}
  .town-pin-evac{animation:townpulse 1.5s ease-in-out infinite}
  /* Commune PROCHE d'un foyer mais PAS sous le vent : elle doit être VISIBLE (sinon elle semble « oubliée »
     par l'app) sans jamais ressembler à une alerte. D'où : plus petite, gris ardoise, translucide, bordure
     discrète, aucune pulsation, et pas d'étiquette permanente (le nom n'apparaît qu'au survol/clic). */
  .town-pin-calm{width:14px;height:14px;border-radius:50%;border:1.5px solid rgba(255,255,255,.75);
    background:#64748b;opacity:.62;box-shadow:0 1px 2px rgba(0,0,0,.45);display:flex;align-items:center;
    justify-content:center;font-size:8px;line-height:1}
  .town-pin-calm:hover{opacity:.95}
  /* Repère « Ma maison » : bleu franc, jamais rouge/ambre (couleurs réservées au DANGER) pour qu'on ne
     confonde pas son domicile avec une commune menacée. */
  .home-pin{width:28px;height:28px;border-radius:50%;border:2.5px solid #fff;background:#2b6cff;
    box-shadow:0 2px 6px rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;font-size:14px;line-height:1}
  .home-mk{cursor:pointer}
  @keyframes townpulse{0%,100%{box-shadow:0 1px 3px rgba(0,0,0,.5),0 0 0 0 rgba(255,59,48,.55)}60%{box-shadow:0 1px 3px rgba(0,0,0,.5),0 0 0 9px rgba(255,59,48,0)}}
  /* Nom de la ville affiché en permanence à côté de l'icône (lisible sur satellite) */
  .leaflet-tooltip.town-name-tip{background:none;border:0;box-shadow:none;padding:0;color:#fff;font-weight:700;font-size:11px;
    text-shadow:0 0 3px #000,0 1px 2px #000,0 0 5px #000;white-space:nowrap}
  .leaflet-tooltip.town-name-tip::before{display:none}
  /* Vue nationale (plusieurs feux en même temps) : texte resserré pour limiter le chevauchement entre
     étiquettes voisines. Rien n'est masqué, la pastille de danger reste pleinement visible à tout zoom. */
  body.zoom-far-labels .leaflet-tooltip.town-name-tip{font-size:8.5px}
  /* Surlignage de la ligne sélectionnée dans la liste Villes (au clic sur le marqueur) */
  .town.town-hl{animation:townhl 2.1s ease}
  @keyframes townhl{0%,100%{background:transparent}12%,55%{background:rgba(245,158,11,.22);box-shadow:inset 3px 0 0 #f59e0b}}
  /* Un <path> SVG cliquable (zone brûlée, pare-feu…) reçoit :focus au clic → le navigateur dessine un outline
     RECTANGULAIRE autour de sa bounding-box (jamais la forme du tracé) = « 2e contour carré » parasite. On le retire :
     le retour visuel reste la popup + l'épaississement au survol du VRAI contour. */
  /* Clavier (13/10/2026, audit MO-22) : le contour reste retiré au clic et sur les tracés SVG (rectangle parasite), mais
     un marqueur atteint au clavier (:focus-visible) montre un anneau, sinon on ne voit pas quel feu est sélectionné. */
  .leaflet-container svg path:focus,.leaflet-interactive:focus:not(:focus-visible),.leaflet-marker-icon:focus:not(:focus-visible){outline:none!important}
  .leaflet-marker-icon:focus-visible{outline:3px solid #2563eb!important;outline-offset:3px;border-radius:50%}
  .tab:focus-visible,#drawerX:focus-visible,#detailX:focus-visible,.gal-cell:focus-visible,.temoin-card:focus-visible,.soli-nav a:focus-visible{outline:3px solid #2563eb;outline-offset:2px}
  .leaflet-popup-content-wrapper{max-width:min(84vw,300px);border-radius:12px}
  html[data-desk] .leaflet-popup-content-wrapper{max-width:330px}
  .leaflet-popup-content{margin:10px 14px;font-size:13px;line-height:1.45;word-break:break-word;overflow-wrap:anywhere}
  .leaflet-popup-content b{word-break:break-word}
  @media (max-width:520px){.leaflet-popup-content{font-size:12.5px;margin:9px 12px}}
  /* Pastilles trafic (DATEX II) · lisibles sur satellite comme sur clair */
  .tp{position:relative;width:26px;height:26px;display:flex;align-items:center;justify-content:center}
  .tp .tp-ic svg{display:block}
  .tp .tp-ic{width:20px;height:20px;border-radius:50%;background:var(--tc);border:2px solid #fff;
    box-shadow:0 1px 3px rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;font-size:11px;line-height:1}
  .tp .tp-rd{position:absolute;top:20px;left:50%;transform:translateX(-50%);background:var(--tc);color:#fff;
    font:700 8.5px/1.3 system-ui,sans-serif;padding:0 3px;border-radius:3px;white-space:nowrap;box-shadow:0 1px 2px rgba(0,0,0,.4)}
  .tp-hot .tp-ic{animation:tpp 1.5s infinite}
  @keyframes tpp{0%{box-shadow:0 0 0 0 rgba(226,52,13,.55)}70%{box-shadow:0 0 0 8px rgba(226,52,13,0)}100%{box-shadow:0 0 0 0 rgba(226,52,13,0)}}
  #drawer .seg{width:100%;flex-shrink:0} #drawer .seg button{flex:1}
  #drawer .dsec[hidden],#drawer #layerSeg[hidden]{display:none!important}
  /* Carte info avion au survol */
  .leaflet-tooltip.ac-tip{background:rgba(20,26,38,.93);color:#fff;border:0;border-radius:9px;font-size:12px;line-height:1.5;padding:7px 10px;box-shadow:var(--shadow-lg);white-space:nowrap}
  .leaflet-tooltip.ac-tip b{color:#fff}
  .leaflet-tooltip.ac-tip:before{border-top-color:rgba(20,26,38,.93)}

  /* Contrôles carte */
  /* ⚠️ Le décalage suit la hauteur RÉELLE du header (--hdr-h, posée en JS par ResizeObserver, cf.
     app.js) plutôt qu'un nombre de pixels deviné. Sur desktop le header s'agrandit (onglets remontés
     + widgets météo), et un chiffre figé le recouvrait à moitié (constaté build 467 : le sélecteur
     d'horizon n'apparaissait plus que par une mince tranche orange sous le header, capture user). */
  .mapctl{position:absolute;left:12px;top:calc(env(safe-area-inset-top) + var(--hdr-h,74px) + 10px);z-index:1000;display:flex;flex-direction:column;gap:8px;max-width:calc(100vw - 72px)}
  /* La barre des périodes TIENT toujours dans la largeur (pas de scroll) : les boutons se répartissent
     et se compriment si besoin (flex-shrink) → les 7 échéances restent visibles d'un coup sur mobile. */
  .horizons{overflow:hidden;scrollbar-width:none}
  .horizons::-webkit-scrollbar{display:none}
  .horizons button{flex:1 1 auto;min-width:0;white-space:nowrap}
  .seg,.horizons{display:flex;background:var(--panel);border:1px solid var(--line);border-radius:11px;overflow:hidden;box-shadow:var(--shadow)}
  .seg button{background:transparent;color:var(--muted);border:0;padding:8px 11px;font-size:12px;font-weight:600;cursor:pointer}
  .seg button.on{background:var(--fire);color:#fff}
  .topline{display:flex;gap:8px;align-items:center;flex-wrap:wrap;max-width:calc(100vw - 72px)}
  .airtop{background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:8px 11px;font-size:12px;font-weight:700;color:var(--txt);box-shadow:var(--shadow);cursor:pointer;white-space:nowrap;display:flex;align-items:center;gap:6px}
  .airtop .n{background:#1f7ae0;color:#fff;border-radius:10px;padding:1px 6px;font-size:10px;min-width:16px;text-align:center}
  /* Hauteur alignée sur les boutons de zoom +/- (30px, demande user) : padding et interligne resserrés
     pour que les 2 lignes (période + heure) tiennent dans le même gabarit compact. */
  .horizons button{background:transparent;color:var(--muted);border:0;padding:4px 6px;font-size:10.5px;font-weight:700;cursor:pointer;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;line-height:1}
  .horizons button.on{background:linear-gradient(180deg,var(--fire2),var(--fire));color:#fff}
  /* Heure réelle projetée (maintenant + N h) sous chaque période. */
  .horizons button .hh{font-size:8.8px;font-weight:600;opacity:.72;letter-spacing:.01em}
  .horizons button.on .hh{opacity:.95}
  /* Bascule Satellite / Prévention = pastille FLOTTANTE bas-droite. Desktop : à gauche du sheet (400px).
     Mobile : au-dessus du bottom-sheet replié, icônes seules (compact), et DISPARAÎT quand le sheet s'ouvre. */
  /* overflow:visible (⚠️ .seg est en overflow:hidden pour arrondir la pilule) : sans lui, le
     dépliant des fonds · positionné AU-DESSUS de la pilule · était rogné et invisible (constaté). */
  #modeSeg{position:absolute;z-index:1000;right:calc(var(--sheetW,400px) + 12px);bottom:16px;transition:opacity .2s;overflow:visible}
  /* overflow:visible prive la pilule de son rognage d'angles : on rend les arrondis aux enfants
     de bord (premier bouton / lien rétro) pour retrouver exactement la silhouette d'origine. */
  #modeSeg>button[data-mode="sat"]{border-radius:10px 0 0 10px}
  #modeSeg>.segnav{border-radius:0 10px 10px 0}
  /* Dépliant des FONDS DE CARTE ancré sur la pastille Satellite : déjà en vue satellite, un clic
     déplie l'éventail (miniatures réelles) au-dessus de la barre ; ailleurs, le clic bascule en
     satellite comme avant. Chevron discret dans la pastille = « il y a un dépliant ici ». */
  #modeSeg .bs-chev{display:inline-block;margin-left:3px;transition:transform .22s ease;font-size:9px;transform:translateY(-.5px)}
  #modeSeg.bs-open .bs-chev{transform:rotate(180deg) translateY(.5px)}
  #bsList{position:absolute;left:0;bottom:calc(100% + 8px);display:flex;flex-direction:column;gap:6px;
    background:var(--panel);border:1px solid var(--line);border-radius:15px;padding:8px;
    box-shadow:0 8px 26px rgba(5,8,16,.55);
    opacity:0;transform:translateY(8px) scale(.97);pointer-events:none;transition:.2s ease}
  #modeSeg.bs-open #bsList{opacity:1;transform:none;pointer-events:auto}
  #bsList button{display:flex;align-items:center;gap:9px;background:none;border:0;border-radius:11px;
    padding:4px 12px 4px 4px;cursor:pointer;color:var(--txt);font-size:12.5px;font-weight:700;text-align:left;white-space:nowrap}
  #bsList button:hover{background:var(--panel2)}
  .bs-thumb{width:34px;height:34px;border-radius:9px;background-size:cover;background-position:center;
    border:1px solid rgba(255,255,255,.18);flex:0 0 auto}
  #bsList button.on .bs-thumb{outline:2px solid var(--accent);outline-offset:1px}
  #bsList button.on{color:var(--accent)}
  @media (max-width:1099px){
    #bsList button{min-height:44px;font-size:13.5px}
    #bsList .bs-thumb{width:38px;height:38px}
    /* La languette verticale du tiroir (« Afficher / masquer ») chevauchait le dépliant des fonds
       ouvert (constaté sur mobile) : elle s'efface tant qu'il est déplié, et revient à sa fermeture. */
    #app:has(#modeSeg.bs-open) #drawerBtn{opacity:0;pointer-events:none;transition:opacity .15s}
  }
  #modeSeg button,#modeSeg .segnav{white-space:nowrap;font-size:11.5px;padding:8px 11px;display:inline-flex;align-items:center;gap:5px}
  /* Entrée vers la rétrospective : même gabarit que les modes, mais teinte braise et jamais
     d'état « actif » · c'est une navigation, pas un mode de carte. */
  /* Bouton PLEIN, pas du texte coloré : en ambre sur le fond clair de la pastille, le libellé
     passait inaperçu · illisible en plein jour, et rien n'indiquait qu'on pouvait cliquer.
     Un aplat dégradé braise + texte blanc se lit à coup sûr sur les deux thèmes, et le
     distingue nettement des deux MODES de carte à sa gauche : ici on navigue, on ne bascule pas
     un affichage. Le liseré à gauche marque cette frontière. */
  #modeSeg .segnav{
    text-decoration:none;font-weight:800;letter-spacing:.01em;
    background:linear-gradient(135deg,#ef3b24,#cf1512);color:#fff;
    border-radius:8px;margin-left:4px;box-shadow:0 2px 8px rgba(207,21,18,.34);
    animation:retroFlame 1.5s ease-in-out 2}
  /* Appel au clic plus visible (demande fondateur 2026-08-18) : lueur façon braise + icône qui palpite,
     2 cycles de 1,5 s (~3 s au total) puis arrêt DÉFINITIF — même philosophie que la languette du volet
     (pas de boucle infinie, le mouvement permanent concurrencerait les vraies alertes de sécurité). */
  @keyframes retroFlame{
    0%,100%{box-shadow:0 2px 8px rgba(207,21,18,.34)}
    50%{box-shadow:0 2px 8px rgba(207,21,18,.34),0 0 18px 5px rgba(239,59,36,.55)}
  }
  @media (prefers-reduced-motion:reduce){ #modeSeg .segnav{animation:none} }
  #modeSeg .segnav .mi{font-size:11px;transform:translateY(.5px);display:inline-block;
    animation:retroFlicker 1.5s ease-in-out 2}
  @keyframes retroFlicker{0%,100%{transform:translateY(.5px) scale(1)}50%{transform:translateY(.5px) scale(1.22)}}
  @media (prefers-reduced-motion:reduce){ #modeSeg .segnav .mi{animation:none} }
  #modeSeg .segnav:hover{filter:brightness(1.08)}
  #modeSeg .segnav:active{transform:scale(.97)}
  #modeSeg .mi{font-size:13px;line-height:1}
  @media (max-width:1099px){
    #modeSeg{right:12px;bottom:calc(env(safe-area-inset-bottom) + var(--peek) + 8px)}/* volet replié (--peek, #sheet.collapsed) + 8 px : il dépassait de 2 px sous le volet (26/09/2026) *//* DESCENDU (2026-08-15) juste au-dessus du sheet pour libérer la carte ; caché quand la jauge de temps (firms/pluie) s'affiche → plus de chevauchement */
    #modeSeg .ml{display:none}
    #modeSeg button,#modeSeg .segnav{padding:9px 12px}
    #modeSeg .mi{font-size:16px}
    #app:has(#sheet:not(.collapsed)) #modeSeg,
    #app:has(#sheet:not(.collapsed)) #firmsCtl{opacity:0;pointer-events:none}
    #app:has(#sheet:not(.collapsed)) .mapctl{opacity:0;pointer-events:none;transition:opacity .2s}
    /* Sheet OUVERT (désormais presque plein écran, demande fondateur 2026-08-19) : le zoom +/− et la
       pastille satellite 24/48 h dépassaient sur la mince bande de carte restante — masqués aussi. */
    #app:has(#sheet:not(.collapsed)) .leaflet-control-zoom,
    #app:has(#sheet:not(.collapsed)) .ctl-appareil,
    #app:has(#sheet:not(.collapsed)) .firewin-map{opacity:0;pointer-events:none;transition:opacity .2s}
    #app:has(#sheet:not(.collapsed)) .ctl-appareil{visibility:hidden;transition:opacity .2s,visibility 0s .2s}
  }
  #modeSeg button.on[data-mode="sat"]{background:#1e40af;color:#fff}
  #modeSeg button.on[data-mode="thermal"]{background:linear-gradient(90deg,#fb923c,#7c3aed);color:#fff}
  /* Bleu · blanc · rouge (24/09/2026, demande fondateur) : satellite bleu, thermomètre BLANC dans les deux
     thèmes (il se fondait dans le fond sombre), rétrospective rouge. Actif, le thermomètre garde son dégradé. */
  #modeSeg>button[data-mode="thermal"]:not(.on){background:#fff;color:#475569}
  /* Satellite NON actif (mode prévention) : il restait transparent sur la carte depuis que la pilule n'a plus de
     fond propre (25/09/2026, signalé fondateur). Le segment garde son bleu, légèrement éteint. */
  #modeSeg>button[data-mode="sat"]:not(.on){background:#2b4ec4;color:#dbe4ff}
  /* Pilule sans contour ni fond propre : les trois boutons pleins dessinent seuls la silhouette. Le liseré
     1 px et le fond blanc du .seg dépassaient en traits clairs autour du bleu et du rouge (thème clair). */
  #modeSeg.seg{border:0;background:transparent;border-radius:10px}
  body[data-radius] #modeSeg.seg{border-radius:var(--ui-radius)!important}
  #modeSeg>.segnav{margin-left:0;box-shadow:none}
  /* Assombrissement du FOND en mode prévention : filter cible UNIQUEMENT le pane des tuiles (basemap).
     Les labels de villes sont déplacés dans labelsPane (hors tile-pane) → ils restent lisibles ; le halo
     (thermalPane) et les foyers (overlayPane) sont au-dessus, donc jamais assombris. */
  /* Filtre porté par les TUILES, pas par le pane : le pane est déplacé par transform à chaque
     image de zoom/pan, et un filter dessus impose une recomposition GPU continue (carte noire
     et scintillante sur Android). Une tuile est une image statique : le filtre est calculé une
     fois puis réutilisé. Rendu identique, coût sans commune mesure. */
  body.thermal .leaflet-tile{filter:brightness(.64) contrast(1.02)}
  /* Légende persistante du mode prévention (anti-confusion). */
  /* 12/10/2026 (audit H-1) : un style en ligne display:none masquait la légende depuis sa mise en ligne, si bien que sa
     place n'avait jamais été vérifiée : en bas à gauche, elle passait sous le badge « Passage », le bouton d'attribution et,
     sur téléphone, sous la poignée du volet. Elle se pose en haut à gauche, sous la pastille 24 h / 48 h. */
  #thermalLegend{position:absolute;left:12px;top:calc(140px + env(safe-area-inset-top));z-index:1000;display:none;align-items:center;gap:6px;flex-wrap:wrap;
    background:rgba(15,20,32,.86);color:#eef;border:1px solid rgba(255,255,255,.14);border-radius:10px;padding:6px 10px;font-size:11px;max-width:calc(100vw - 24px);box-shadow:var(--shadow)}
  @media (min-width:1100px){#thermalLegend{top:calc(var(--hdr-h,56px) + 98px);max-width:calc(100vw - var(--sheetW,400px) - 90px)}}
  body.thermal #thermalLegend{display:flex}
  #thermalLegend .tl-grad{width:64px;height:9px;border-radius:5px;flex:0 0 auto;background:linear-gradient(90deg,#1e40af,#22d3ee,#fde047,#fb923c,#ef4444,#7c3aed)}
  #thermalLegend .tl-sep{opacity:.5} #thermalLegend .tl-fire{filter:drop-shadow(0 0 2px #fff)}
  @media (max-width:1099px){#app:has(#sheet:not(.collapsed)) #thermalLegend{display:none!important}}
  /* Carte « pourquoi à risque » : puce de niveau colorée + lignes de chiffres. */
  .risk-chip{display:inline-block;padding:3px 10px;border-radius:20px;color:#fff;font-weight:800;font-size:12.5px;vertical-align:middle}
  #thermalCardBody .rk-rows{margin:9px 0 4px;display:flex;flex-direction:column;gap:5px;font-size:12.5px}
  #thermalCardBody .rk-rows b{color:var(--txt)} #thermalCardBody .rk-why{color:var(--muted);font-size:12px;margin-top:6px}
  #thermalCardBody .rk-advice{margin-top:9px;padding:8px 10px;border-radius:9px;background:var(--panel2);font-size:12.5px}
  #thermalCardBody .rk-honesty{margin-top:9px;color:var(--muted);font-size:11px;border-top:1px solid var(--line);padding-top:8px}
  #thermalCardBody .rk-loc{font-weight:800;font-size:13px;margin:1px 0 7px}
  #thermalCardBody .rk-age{color:#d97706;font-size:11px;font-weight:700}
  #thermalCardBody .rk-precision{margin-top:6px;color:var(--muted);font-size:11px}
  /* Foyer FIRMS RÉEL en mode prévention : anneau blanc + pulsation → inconfondable avec un halo météo. */
  body.thermal .firms-core{animation:firmsPulse 1.6s ease-in-out infinite}
  @keyframes firmsPulse{0%,100%{stroke-opacity:1}50%{stroke-opacity:.35}}

  /* Panneau : bottom-sheet mobile / colonne latérale desktop */
  #sheetResize{display:none}
  #sheetFsBtn{display:none}
  @media (min-width:1100px){#sheetFsBtn{display:flex}}
  /* Plein écran carte : DESKTOP UNIQUEMENT (le mobile a déjà le mode paysage plein écran ;
     languette mobile retirée sur demande fondateur 2026-08-19). */
  /* ── 3e état MOBILE « mini » (fondateur 2026-08-19) : glisser la poignée vers le BAS depuis l'état
     replié fait descendre le volet jusqu'à la seule barre grise (30px, bande réduite le 24/09) → carte quasi plein écran en
     portrait. Tap ou glissé vers le haut = retour au peek normal. Les contrôles ancrés au-dessus du
     volet (Satellite/Rétro, Signaler, badge Passage, alertes, jauges, rose des vents) descendent
     d'autant, alignés sur les mêmes écarts qu'en état replié. */
  @media (max-width:1099px){
    #sheet.collapsed.mini{transform:translateY(calc(100% - 30px - env(safe-area-inset-bottom)))}
    /* MINI FAÇON VOLET iOS (fondateur 24/09/2026, variante B choisie sur captures : « propre, épuré, pro, pas
       gros ») : bande fine sur toute la largeur en verre dépoli (fond translucide + flou, comme Apple Plans),
       coins arrondis, filet clair en haut, ombre douce ; la barre 120 × 6 au centre. Toute la bande est la zone
       de toucher et de glissé, prolongée de 14 px au-dessus (::after) pour l'attraper sans viser. */
    #sheet.collapsed.mini{background:rgba(255,255,255,.72);-webkit-backdrop-filter:blur(20px) saturate(1.6);
      backdrop-filter:blur(20px) saturate(1.6);border-top:.5px solid rgba(15,23,42,.12);border-radius:14px 14px 0 0;
      box-shadow:0 -4px 20px rgba(15,23,42,.14)}
    #sheet.collapsed.mini>*:not(#grip){visibility:hidden}
    #sheet.collapsed.mini #grip{position:relative;height:30px}
    #sheet.collapsed.mini #grip::before{width:96px;height:4px;background:rgba(60,60,67,.26)}
    #sheet.collapsed.mini #grip::after{content:"";position:absolute;left:0;right:0;top:-14px;bottom:0}
    #app:has(#sheet.collapsed.mini) #modeSeg{bottom:calc(env(safe-area-inset-bottom) + 44px)}
    #app:has(#sheet.collapsed.mini) .sat-info{bottom:calc(env(safe-area-inset-bottom) + 44px)}
    #app:has(#sheet.collapsed.mini) #sigFab{bottom:calc(94px + env(safe-area-inset-bottom))}
    #app:has(#sheet.collapsed.mini) .proxbar{bottom:calc(48px + env(safe-area-inset-bottom))}
    #app:has(#sheet.collapsed.mini) .rain-ctl{bottom:calc(44px + env(safe-area-inset-bottom))}
    #app:has(#sheet.collapsed.mini) .prog-ctl{bottom:calc(76px + env(safe-area-inset-bottom))}
    #app:has(#sheet.collapsed.mini) .vent-hud{bottom:calc(142px + env(safe-area-inset-bottom))}
    /* Barre mini (13/10/2026, audit H-7) : carte partenaire au-dessus de Signaler (94 px + 36 px), fiche au ras de la barre. */
    #app:has(#sheet.collapsed.mini) .sponsor-card{bottom:calc(138px + env(safe-area-inset-bottom))}
    /* Volet replié sur un écran bas (740 px) : l'onglet des calques (centré à 46 %, 145 px de haut) descendait sur Signaler,
       désormais posé à --peek + 48 px. Il remonte juste ce qu'il faut (bas de l'onglet 8 px au-dessus de Signaler). */
    #app:has(#sheet.collapsed:not(.mini)) .drawerbtn{top:min(46%, calc(100% - var(--peek) - 48px - 36px - 8px - 73px - env(safe-area-inset-bottom)))}
    #app:has(#sheet.collapsed.mini) #detail{bottom:calc(44px + env(safe-area-inset-bottom))}
    #app:has(#sheet:not(.collapsed)) #detail{bottom:calc(14px + env(safe-area-inset-bottom))}
    /* Volet ouvert : la carte partenaire et le crédit de la carte s'effacent comme Signaler (ils couvraient la recherche). */
    #app:has(#sheet:not(.collapsed)) .sponsor-card,body:has(#sheet:not(.collapsed)) .attrib-carte{opacity:0;pointer-events:none}
    /* Barre mini : au-dessus de Signaler (94 px + 36 px), pas sur la bascule Satellite (audit MO-9, 13/10/2026). */
    body:has(#sheet.collapsed.mini){--fv-float-bottom:calc(138px + env(safe-area-inset-bottom, 0px))}
  }
  #sheet{position:absolute;left:0;right:0;bottom:0;z-index:1100;background:var(--panel);
    border-top:1px solid var(--line);border-radius:18px 18px 0 0;box-shadow:0 -8px 34px rgba(20,30,50,.14);
    display:flex;flex-direction:column;transition:transform .28s cubic-bezier(.22,1,.36,1);
    /* HAUTEUR FIXE, volontairement pas `max-height` seul : sans hauteur imposée le volet épouse le contenu
       de l'onglet actif, donc son bord haut sautait à chaque changement d'onglet (Animaux en cours de
       chargement ≈ 38 % de l'écran, la légende de Comprendre ≈ 88 %). Le contenu défile désormais À
       L'INTÉRIEUR (.sheet-body est déjà en overflow-y:auto), et le cadre ne bouge plus. La hauteur repliée
       en dépend aussi : `translateY(100% - 160px)` n'est stable que si 100% ne varie pas. */
    /* Hauteur ouverte = quasi plein écran (fondateur 2026-08-19, 2e relèvement) : le bord haut
       vient à 14px SOUS le header. La zone de la barre des périodes est recouverte, sans gêne :
       cette barre est de toute façon MASQUÉE quand le volet est ouvert (règle .mapctl plus haut).
       → le maximum d'informations visibles par onglet sans défiler. --sheetH est partagé avec
       --fv-float-bottom (bannières flottantes) pour que les deux restent alignés à jamais.
       La remise à zéro du défilement au changement d'onglet (openTab, .sheet-body.scrollTop=0)
       est CALCULÉE SUR LE CONTENU, pas sur cette hauteur — aucun risque en la changeant. */
    height:var(--sheetH);min-height:calc(var(--fv-height) * .6);max-height:calc(var(--fv-height) - 58px);padding-bottom:calc(env(safe-area-inset-bottom) + 22px)}
  body{--sheetH:calc(var(--fv-height) - env(safe-area-inset-top, 0px) - var(--hdr-h,74px) - 14px)}
  /* PWA standalone Android : la barre gestuelle recouvre le bas → on remonte le contenu replié
     de la hauteur de la safe-area pour que les KPI ne soient pas tronqués derrière la barre de nav. */
  /* 176px (160 réglé à l'œil par le fondateur 2026-08-19, valeur finale) : le peek replié montre les
     chiffres et une bonne partie des libellés des 4 cards KPI. Qui veut la carte quasi nue glisse
     la poignée vers le BAS → état « mini » (barre grise seule, 30px). */
  /* --peek (08/10/2026) : hauteur du volet replié, partagée avec #modeSeg, --fv-float-bottom et le glisser (app.js). 280 px depuis
     le badge météo : le repli montre le badge entier (il remplace la rangée des quatre tuiles). Le volet se range de toute façon
     en barre « mini » 1,6 s après le chargement, la carte au repos n'y perd rien. */
  :root{--peek:280px}
  #sheet.collapsed{transform:translateY(calc(100% - var(--peek) - env(safe-area-inset-bottom)))}
  /* Zone de préhension/fermeture large et évidente (tap facile pour ouvrir/fermer) */
  #grip{display:flex;align-items:center;justify-content:center;height:40px;width:100%;touch-action:none;cursor:pointer;flex:0 0 auto}
  #grip::before{content:"";width:96px;height:4px;border-radius:999px;background:#cbd3e0;transition:.2s}
  #sheet:not(.collapsed) #grip::before{background:#aeb8c8}
  /* MODE PAYSAGE MOBILE = plein écran carte (demande user 2026-08-13). En paysage sur un TÉLÉPHONE
     (hauteur ≤ 600px ; les tablettes, plus hautes ≥ ~744px, gardent l'UI complète), on masque le header
     (glisse vers le haut) et on escamote le sheet (glisse vers le bas, seul le grip de 30px dépasse pour
     pouvoir le rappeler). ⚠️ Seuil remonté 500→600px le 2026-08-15 : les grands téléphones (Galaxy S26
     Ultra…) dépassent 500px de haut en paysage, donc l'optim ne se déclenchait JAMAIS chez eux (header +
     tous les toggles restaient → carte encombrée, plainte user). Retour en portrait = tout revient normal
     (aucune classe JS, purement piloté par l'orientation → zéro risque). */
  header{transition:transform .32s cubic-bezier(.22,1,.36,1),opacity .25s ease}
  /* PAYSAGE MOBILE = plein écran carte. Header masqué + sheet réduit à sa poignée. Comme le header
     disparaît, tous les contrôles ancrés « droite » remontaient et se chevauchaient (zoom, Signaler,
     onglet légende). On les ré-empile proprement : zoom puis Signaler en HAUT-droite, l'onglet légende
     ancré en BAS-droite (jamais collé au haut de page), et le volet légende devient un panneau FLOTTANT
     avec marges (ne part plus du haut). Les TOGGLES posés sur la carte (barre d'horizons, bascule
     Satellite/Prévention, fenêtre FIRMS 24/48 h) sont MASQUÉS pour une carte nette — on les retrouve
     en portrait (demande user 2026-08-15). */
  @media (orientation:landscape) and (max-height:600px){
    header{transform:translateY(-100%);opacity:0;pointer-events:none}
    #sheet.collapsed{transform:translateY(calc(100% - 30px - env(safe-area-inset-bottom)))}
    .leaflet-top.leaflet-right{top:calc(env(safe-area-inset-top) + 4px)!important;right:8px!important}/* 4 px (8 avant le 14/10/2026) : les deux groupes finissent à 180 px (zone d'appui à 188), l'onglet des calques commence à 191 px sur 360 px de haut */
    /* Signaler passe à GAUCHE de la colonne zoom, Ma position, Ma maison (14/10/2026) : sous elle, il descendait sur
       l'onglet des calques des téléphones bas (360 px de haut). Haut aligné sur la colonne (4 px + 10 px de marge), 8 px à
       gauche des groupes, larges de 38 px (8 px du bord, 10 px de marge). */
    #sigFab{top:calc(env(safe-area-inset-top) + 14px)!important;bottom:auto!important;right:70px!important}
    .drawerbtn{top:auto!important;bottom:30px!important;transform:none!important;padding:12px 7px;border-radius:13px 0 0 13px}
    #drawer{top:8px!important;bottom:8px!important;border-radius:14px 0 0 14px}
    #drawer.closed{transform:translateX(calc(100% + 10px))}
    /* Toggles sur la carte masqués en paysage téléphone (carte plein écran nette). */
    .mapctl,#modeSeg,#fireWinMap{display:none!important}
    /* Volet replié réduit à sa poignée (30 px) : ce qui se posait au-dessus de --peek (280 px) partait hors de l'écran,
       en haut (carte partenaire, fiche d'un feu, alerte, bannières). Tout redescend au ras de la poignée (13/10/2026,
       audit H-7 et MO-30). `html body` : passe devant la règle générale de --fv-float-bottom, plus bas dans la page. */
    .sponsor-card,#detail,.proxbar{bottom:calc(44px + env(safe-area-inset-bottom))!important}
    html body,html body:has(#sheet.collapsed.mini){--fv-float-bottom:calc(44px + env(safe-area-inset-bottom, 0px))}
  }
  /* COLONNE DE DROITE, TÉLÉPHONE ET TABLETTE (14/10/2026, soir). Fondateur : « Ils sont passés où, les boutons + et − du
     zoom ? » (la v11.57 l'effaçait sous 750 px de haut). Le zoom reste affiché à TOUTES les tailles. Deux groupes de boutons
     de 36 px (dessin de la carte des inondations, plus bas) : [+ / −] de safe + 68 à safe + 143 px, [Ma position / Ma
     maison] de safe + 159 à safe + 234 px (zone d'appui jusqu'à 242 px). L'onglet des calques ne remonte jamais au-dessus :
     son haut reste dessous (centre à safe + 318 px pour l'onglet de 145 px), et il descend plus bas s'il le faut. Rien ne
     recouvre la frise des horizons, Signaler, la rose des vents ni le volet. */
  @media (max-width:1099px){
    #app .drawerbtn{top:max(calc(env(safe-area-inset-top) + 318px), 46%)}
    #app:has(#sheet.collapsed:not(.mini)) .drawerbtn{top:max(calc(env(safe-area-inset-top) + 318px), min(46%, calc(100% - var(--peek) - 48px - 36px - 8px - 73px - env(safe-area-inset-bottom))))}
    /* Volet replié : la carte du partenaire et les bannières flottantes, posées sur toute la largeur juste au-dessus de
       Signaler, passaient sous l'onglet des calques, et sur les écrans bas sous la colonne (à 360 × 640, la carte du
       partenaire couvrait Ma position et Ma maison, vérifié en ligne le 14/10/2026). Elles s'arrêtent avant la bande de
       droite (62 px du bord : colonne de 44 px, ses 10 px de marge, 8 px d'écart). En barre mini, elles sont sous l'onglet. */
    #app:has(#sheet.collapsed:not(.mini)) .sponsor-card,
    body:has(#sheet.collapsed:not(.mini)) :is(.fv-float,#installBanner,#renameBanner,#retroBanner,#galBanner,#donBanner,#featBanner,#petsBanner){right:62px}
  }
  /* Volet replié (280 px) sur un écran de moins de 763 px de haut (hors téléphone en paysage, réglé à part) : l'onglet posé
     sous la colonne descend plus bas que le haut de Signaler. Signaler et la bascule Satellite / Prévention / Rétrospective
     passent alors à sa gauche (42 px du bord : 29 px d'onglet, 9 px de son appel du regard à l'ouverture, 4 px d'écart). En barre mini (le volet s'y range seul 2,2 s
     après l'ouverture), ils sont bien plus bas et reviennent au bord. */
  @media (max-width:1099px) and (orientation:portrait) and (max-height:762px),(max-width:1099px) and (min-height:601px) and (max-height:762px){
    #app:has(#sheet.collapsed:not(.mini)) #sigFab,#app:has(#sheet.collapsed:not(.mini)) #modeSeg{right:42px}
  }
  /* Moins de 678 px de haut (360 × 640, 375 × 667) : l'onglet de 145 px ne tient plus entre la colonne et le volet replié.
     Il se resserre (106 px), haut toujours 8 px sous la colonne (centre à safe + 298 px) ; il tient jusqu'à 639 px. */
  @media (max-width:1099px) and (orientation:portrait) and (max-height:677px),(max-width:1099px) and (min-height:601px) and (max-height:677px){
    #app .drawerbtn{padding:6px 5px;font-size:10px;letter-spacing:.01em}
    #app .drawerbtn,#app:has(#sheet.collapsed:not(.mini)) .drawerbtn{top:calc(env(safe-area-inset-top) + 298px)}
  }
  /* Moins de 639 px de haut : l'onglet garde son pictogramme seul (calques, 44 px de haut, nom accessible inchangé),
     centre à safe + 267 px ; il tient jusqu'à 577 px. */
  @media (max-width:1099px) and (orientation:portrait) and (max-height:638px),(max-width:1099px) and (min-height:601px) and (max-height:638px){
    #app .drawerbtn{font-size:0;letter-spacing:0;padding:0;width:30px;height:44px;writing-mode:horizontal-tb}
    #app .drawerbtn::before{content:"";display:block;width:18px;height:18px;margin:13px auto;background:currentColor;
      -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'><path d='M12 3 2 8l10 5 10-5z'/><path d='m2 12.5 10 5 10-5'/><path d='m2 16.5 10 5 10-5'/></svg>") center/contain no-repeat;
      mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'><path d='M12 3 2 8l10 5 10-5z'/><path d='m2 12.5 10 5 10-5'/><path d='m2 16.5 10 5 10-5'/></svg>") center/contain no-repeat}
    #app .drawerbtn,#app:has(#sheet.collapsed:not(.mini)) .drawerbtn{top:calc(env(safe-area-inset-top) + 267px)}
  }
  .tabs{display:flex;gap:6px;padding:3px 12px 9px;overflow-x:auto;scrollbar-width:none;scroll-snap-type:x proximity;flex:0 0 auto}
  .tabs::-webkit-scrollbar{display:none}
  .tab{position:relative;display:inline-flex;align-items:center;background:var(--panel2);border:1px solid var(--line);color:var(--muted);border-radius:22px;
    padding:7px var(--tpx,14px);font-size:12px;font-weight:700;white-space:nowrap;cursor:pointer;flex:0 0 auto;transition:background .15s,color .15s,box-shadow .15s,transform .1s;scroll-snap-align:start}
  .tab .tc{display:none}
  /* TÉLÉPHONE (13/10/2026, audit B-16) : à 360 et 390 px, l'onglet Villes (et son compteur d'alertes) tombait hors de
     l'écran. Marges resserrées et « Progr. » pour Progression ; le libellé entier reste lu par les lecteurs d'écran. */
  @media (max-width:819px){
    .tabs{gap:5px;padding-left:10px;padding-right:10px}
    #sheet .tab{--tpx:10px}
    #sheet .tab[data-p="progression"] .tc{display:inline}
    #sheet .tab[data-p="progression"] .tl{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
  }
  .tab:not(.on):active{transform:scale(.96)}
  .tab.on{background:var(--fire-on);color:#fff;border-color:var(--fire-on);box-shadow:0 4px 13px rgba(234,74,18,.34)}
  .tab .n{display:inline-block;min-width:16px;text-align:center;margin-left:6px;font-size:10px;font-weight:800;
    background:var(--danger);color:#fff;border-radius:10px;padding:1px 5px}
  .tab.on .n{background:rgba(255,255,255,.28)}
  /* Pastille « Villes » : le fond est posé EN INLINE par le JS (rouge/orange si alerte, bleu-gris si 0),
     mais le texte héritait de `var(--muted)` (règle header.has-tabs) → chiffre SOMBRE peu lisible sur le
     fond coloré (demande user 2026-08-15, thème clair ET sombre). L'id gagne en spécificité → texte blanc
     forcé sur tous les états ; le fond inline restant coloré, le contraste est bon dans les deux thèmes. */
  #tnVilles{color:#fff!important;text-shadow:0 1px 1px rgba(0,0,0,.35)}
  /* Icônes d'onglets · jeu vectoriel monochrome, un SEUL gabarit (viewBox 24, trait 2.1) pour que toutes
     aient la même épaisseur et la même taille optique. Les emoji ne le permettaient pas : chaque glyphe a sa
     propre chasse (🏘️ débordait de la pastille, 📰 s'y perdait) et sa propre palette, qui jurait avec l'orange.
     La pastille est portée par ::before, le glyphe par ::after posé par-dessus : ainsi le glyphe est peint en
     `background-color` à travers un masque, donc UNE seule définition d'icône suffit pour les deux états —
     c'est la couleur qui change (gris au repos, blanc sur l'onglet actif), pas le fichier. */
  /* Site touristique évacué : anneau rouge continu, distinct du halo pulsé des communes menacées. */
  .town-pin.site-evac{box-shadow:0 0 0 3px rgba(200,30,30,.85),0 2px 6px rgba(0,0,0,.3)}
  /* Ambre = évacuation PRÉVENTIVE : distincte du rouge, pour ne pas exagérer la situation du site. */
  /* Repère PARTENAIRE : bandeau blanc qui porte un ou plusieurs logos côte à côte (adresse partagée). */
  /* Calque activé mais en attente de zoom : à demi éteint, avec une loupe. L'utilisateur voit que son
     choix est pris en compte et qu'il manque juste de la proximité, plutôt que de croire à une panne. */
  /* Marqueur STATIQUE : la loupe signale « ce calque apparaît en zoomant » et ne bouge JAMAIS.
     Elle était posée/retirée au fil du zoom : le tiroir se réorganisait sous les doigts pendant
     qu'on le lisait. L'état réel reste porté par l'infobulle, qui ne déplace rien. */
  /* Repère zoom en SVG (plus d'émoji, 26/09/2026) : petite loupe posée juste avant l'interrupteur. */
  /* Calque qui n'apparaît qu'en zoomant : petite loupe en SVG posée dans le coin de sa pastille d'icône
     (26/09/2026 : l'ancienne loupe était un émoji, et ::after porte désormais l'interrupteur). */
  #toggleSeg .toggles button.zoom-min::before{background-image:var(--ic),url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%2711%27%20fill%3D%27%23fff%27%2F%3E%3Ccircle%20cx%3D%2710.5%27%20cy%3D%2710.5%27%20r%3D%275%27%20fill%3D%27none%27%20stroke%3D%27%23333%27%20stroke-width%3D%272.6%27%2F%3E%3Cpath%20d%3D%27m14.3%2014.3%204.2%204.2%27%20stroke%3D%27%23333%27%20stroke-width%3D%272.8%27%20stroke-linecap%3D%27round%27%2F%3E%3C%2Fsvg%3E");
    background-size:12.5px 12.5px,10px 10px;background-position:center,right -1px bottom -1px;background-repeat:no-repeat}
  /* Écussons des grands axes (vecteur ROUTE 500, vue large) : couleurs de la carte IGN, autoroute violette,
     nationale rouge, départementale principale jaune ; posés par-dessus la ligne, jamais dessous. */
  .rv-ecu-wrap{background:none!important;border:0!important}
  .rv-ecu{position:absolute;left:0;top:0;transform:translate(-50%,-50%);display:inline-block;font:700 10.5px/1 system-ui,-apple-system,"Segoe UI",sans-serif;
    padding:2.5px 5px;border-radius:5px;border:1.5px solid #fff;color:#fff;background:#7b6ee6;box-shadow:0 1px 3px rgba(0,0,0,.55);white-space:nowrap;letter-spacing:.2px}
  .rv-ecu-N{background:#d63a2f}
  .rv-ecu-D,.rv-ecu-M{background:#f0c33c;color:#1f1f1f}
  /* Vue régionale (vecteur, z < 10) : plus petit encore (fondateur : « carte incendie, pas un GPS »). */
  .rv-ecu-petit{font-size:9px;padding:2px 4px;border-width:1px}
  /* Pastilles trafic en vue régionale (z < 11) : toutes les catégories, juste plus petites (fondateur 21/09/2026 :
     « remets la signalisation comme avant avec les panneaux, juste moins gros »). */
  .trf-loin .traffic-ic .tp{transform:scale(.68);transform-origin:center}
  #toggleSeg button.zoom-attente{opacity:1}
  .partner-pin{display:flex;align-items:center;justify-content:center;gap:3px;height:26px;padding:0 4px;
    background:var(--panel);border:1.5px solid var(--fire,#e2340d);border-radius:8px;box-shadow:0 1px 5px rgba(0,0,0,.24)}
  .town-pin.site-prev{box-shadow:0 0 0 3px rgba(217,119,6,.85),0 2px 6px rgba(0,0,0,.3)}
  .tab::before{content:"";display:inline-block;width:22px;height:22px;border-radius:50%;
    background:rgba(120,124,140,.22);margin-right:7px;flex:0 0 auto}
  .tab.on::before{background:rgba(255,255,255,.24)}
  /* Le glyphe est peint en --txt et non en --muted : à 13 px un trait gris sur pastille grise se lisait mal,
     alors que l'étiquette à côté reste en --muted. Trait épaissi et masque agrandi dans la même intention. */
  .tab::after{content:"";position:absolute;left:var(--tpx,14px);top:50%;width:22px;height:22px;transform:translateY(-50%);
    background-color:var(--txt);opacity:.82;pointer-events:none;
    -webkit-mask:var(--ic) center/14px 14px no-repeat;mask:var(--ic) center/14px 14px no-repeat}
  .tab.on::after{background-color:var(--panel);opacity:1}
  .tab[data-p="situation"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M8.5%2014.5A2.5%202.5%200%200%200%2011%2012c0-1.38-.5-2-1-3-1.07-2.14-.22-4.05%202-6%20.5%202.5%202%204.9%204%206.5%202%201.6%203%203.5%203%205.5a7%207%200%201%201-14%200c0-1.15.43-2.29%201-3a2.5%202.5%200%200%200%202.5%202.5Z'/%3E%3C/svg%3E")}
  .tab[data-p="actu"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M4%2022h16a2%202%200%200%200%202-2V4a2%202%200%200%200-2-2H8a2%202%200%200%200-2%202v16a2%202%200%200%201-2%202Zm0%200a2%202%200%200%201-2-2v-9c0-1.1.9-2%202-2h2'/%3E%3Cpath%20d='M18%2014h-8M15%2018h-5M10%206h8v4h-8Z'/%3E%3C/svg%3E")}
  .tab[data-p="villes"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M3%2021h18M5%2021V9l7-5%207%205v12M10%2021v-6h4v6'/%3E%3C/svg%3E")}
  .tab[data-p="progression"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M3%203v16a2%202%200%200%200%202%202h16'/%3E%3Cpath%20d='m19%209-5%205-4-4-3%203'/%3E%3C/svg%3E")}
  .tab[data-p="soli"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M16%2021v-2a4%204%200%200%200-4-4H6a4%204%200%200%200-4%204v2'/%3E%3Ccircle%20cx='9'%20cy='7'%20r='4'/%3E%3Cpath%20d='M22%2021v-2a4%204%200%200%200-3-3.87M16%203.13a4%204%200%200%201%200%207.75'/%3E%3C/svg%3E")}
  .tab[data-p="stats"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M4%2020V10M10%2020V4M16%2020v-6M22%2020H2'/%3E%3C/svg%3E")}
  .tab[data-p="galerie"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14.5%204h-5L7%207H4a2%202%200%200%200-2%202v9a2%202%200%200%200%202%202h16a2%202%200%200%200%202-2V9a2%202%200%200%200-2-2h-3Z'/%3E%3Ccircle%20cx='12'%20cy='13'%20r='3'/%3E%3C/svg%3E")}
  .tab[data-p="animaux"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='black'%20stroke='none'%3E%3Cellipse%20cx='5.3'%20cy='11.2'%20rx='2.2'%20ry='2.9'/%3E%3Cellipse%20cx='9.6'%20cy='7.4'%20rx='2.3'%20ry='3.1'/%3E%3Cellipse%20cx='14.4'%20cy='7.4'%20rx='2.3'%20ry='3.1'/%3E%3Cellipse%20cx='18.7'%20cy='11.2'%20rx='2.2'%20ry='2.9'/%3E%3Cpath%20d='M12%2012.6c3.1%200%205.7%202.3%205.7%204.8%200%202-1.7%203.2-3.6%202.7-1.4-.3-2.8-.3-4.2%200-1.9.5-3.6-.7-3.6-2.7%200-2.5%202.6-4.8%205.7-4.8Z'/%3E%3C/svg%3E")}
  .tab[data-p="infos"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M15%2014c.2-1%20.7-1.7%201.5-2.5%201-.9%201.5-2.2%201.5-3.5A6%206%200%200%200%206%208c0%201%20.2%202.2%201.5%203.5.8.8%201.3%201.5%201.5%202.5'/%3E%3Cpath%20d='M9%2018h6M10.5%2022h3'/%3E%3C/svg%3E")}
  .tab[data-p="partners"]{--ic:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.35'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M19%2014c1.5-1.46%203-3.21%203-5.5A5.5%205.5%200%200%200%2016.5%203c-1.76%200-3%20.5-4.5%202-1.5-1.5-2.74-2-4.5-2A5.5%205.5%200%200%200%202%208.5c0%202.3%201.5%204.05%203%205.5l7%207Z'/%3E%3C/svg%3E")}
  /* Flèches de navigation des onglets · cachées par défaut (mobile = swipe), affichées sur desktop. */
  .tabsbar{position:relative}
  /* Onglets qui débordent : fondu du côté où d'autres onglets attendent (classes posées par app.js au défilement). */
  .tabs.fade-d{-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 30px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 30px),transparent)}
  .tabs.fade-g{-webkit-mask-image:linear-gradient(90deg,transparent,#000 30px);mask-image:linear-gradient(90deg,transparent,#000 30px)}
  .tabs.fade-g.fade-d{-webkit-mask-image:linear-gradient(90deg,transparent,#000 30px,#000 calc(100% - 30px),transparent);mask-image:linear-gradient(90deg,transparent,#000 30px,#000 calc(100% - 30px),transparent)}
  .tabnav{display:none;cursor:pointer}
  /* Onglets remontés dans le header (desktop uniquement, via classe .has-tabs posée en JS) : ils occupent
     l'espace vide central du header au lieu de chevaucher le panneau de droite. Header TOUJOURS clair → couleurs
     d'onglets forcées lisibles sur fond blanc (indépendant du thème). Mobile n'a jamais .has-tabs → intact. */
  header.has-tabs{gap:10px}
  /* flex:0 0 auto + nowrap : avec `0 1 auto`, la barre d'onglets (flex:1) comprimait le titre à
     ~78 px → « France Incendie » se coupait/repliait sur desktop. Le titre garde sa largeur
     naturelle · les onglets, eux, savent défiler. */
  header.has-tabs .htitle{flex:0 0 auto}
  header.has-tabs .htitle h1{white-space:nowrap}
  /* ⚠️ display:flex OBLIGATOIRE ici : sans lui .tabsbar reste un bloc normal, et ses 3 enfants
     (flèche ‹, flèche ›, rangée d'onglets) s'empilent chacun sur sa propre ligne au lieu de tenir
     sur UNE rangée (constaté 820-1099 px et au-delà dès que les onglets débordent · capture user,
     menu « tout buggé »). Cette règle est desktop-only (`header.has-tabs`), sans condition de
     largeur : elle couvre tous les paliers, y compris la bande 1100-1320 px ci-dessous. */
  header.has-tabs .tabsbar{display:flex;align-items:center;flex:1 1 auto;min-width:0;margin:0 2px}
  /* ONGLETS ENTIERS DANS LE BANDEAU (08/10/2026, fondateur : « le bandeau header sur desktop doit être entier,
     responsive, pas avoir besoin de scrolling »). Sur ordinateur (≥ 1100 px) plus aucun défilement ni flèches.
     app.js (« Onglets entiers dans le bandeau ») MESURE la place et réduit ONGLET PAR ONGLET, jamais tout ou rien :
     d'abord tabs-c1 sur le header (compact : sous-titre du h1 masqué, marges et pastilles resserrées), puis, du
     moins important au plus important, un onglet à la fois en libellé court (.t-c) puis en icône seule (.t-i,
     info-bulle et aria-label) ; l'onglet actif garde son libellé, les compteurs restent. Deuxième rangée pleine
     largeur (tabs-2r) seulement si, même tout en icônes, ça ne tient pas. Rien sous 1100 px (tiroir du bas). */
  header.has-tabs.tabs-c1{gap:8px;padding-left:12px;padding-right:12px}
  /* Le bloc titre prenait la largeur de sa ligne d'état (« MàJ 19:42 · 30 pts · dernière détection… », ~300 px) : bornée, elle se tronque. */
  header.has-tabs.tabs-c1 .htitle{max-width:200px}
  header.has-tabs.tabs-c1 .h1kw{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
  header.has-tabs.tabs-c1 .tabs{gap:4px}
  header.has-tabs.tabs-c1 .tab{--tpx:9px}
  header.has-tabs.tabs-c1 .tab::before{width:20px;height:20px;margin-right:5px}
  header.has-tabs.tabs-c1 .tab::after{width:20px;height:20px}
  header.has-tabs.tabs-c1 .live{max-width:120px;overflow:hidden;padding:5px 8px}
  header.has-tabs .tab.t-c .tc{display:inline}
  header.has-tabs .tab.t-c .tc+.tl{display:none}
  header.has-tabs .tab.t-i .tl,header.has-tabs .tab.t-i .tc{display:none}
  header.has-tabs .tab.t-i::before{margin-right:0}
  header.has-tabs .tab.t-i .n{margin-left:5px}
  header.has-tabs.tabs-2r{flex-wrap:wrap;row-gap:6px;padding-bottom:7px}
  header.has-tabs.tabs-2r .tabsbar{flex:1 0 100%;order:9;margin:0;min-width:0}
  /* flex:1 1 auto + min-width:0 OBLIGATOIRES : sans eux, un flex-item garde sa largeur de contenu
     (min-width:auto par défaut) et DÉBORDE du header au lieu de se contraindre puis défiler · les
     derniers onglets étaient alors juste ROGNÉS, inatteignables même par un scroll tactile/souris
     (constaté : scrollWidth==clientWidth, aucun débordement interne détecté → flèches jamais affichées). */
  header.has-tabs .tabs{flex:1 1 auto;min-width:0;padding:0;overflow-x:auto;justify-content:flex-start;gap:6px}
  /* Flèches ‹ › : cachées SEULEMENT quand tout tient · la classe .tabs-overflow (posée par le JS
     quand les onglets débordent) les affiche, à TOUTE largeur desktop (l'ancien !important les
     tuait même sur les petits écrans de portable où elles sont indispensables). */
  header.has-tabs .tabnav{display:none}
  header.has-tabs.tabs-overflow .tabnav{display:flex;position:static;width:26px;height:30px;align-items:center;justify-content:center}
  header.has-tabs .tab{background:var(--panel2);border-color:var(--line);color:var(--muted);padding-top:5px;padding-bottom:5px}
  header.has-tabs .tab.on{background:var(--fire-on);border-color:var(--fire-on);color:#fff}
  header.has-tabs .tab .n{background:rgba(128,140,160,.20);color:var(--muted)}
  header.has-tabs .tab.on .n{background:rgba(255,255,255,.28);color:#fff}
  .sheet-head{display:flex;gap:9px;padding:0 14px 11px;flex:0 0 auto}
  .kpi{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:13px;padding:10px 8px;text-align:center;display:flex;flex-direction:column;justify-content:center;align-items:center}
  .kpi .v{font-size:19px;font-weight:800;line-height:1}
  .kpi .v .vsub{display:block;font-size:10px;font-weight:600;color:var(--muted);margin-top:3px;line-height:1.2}
  .kpi .l{font-size:11px;color:var(--muted);margin-top:5px;text-transform:uppercase;letter-spacing:.04em;font-weight:600}
  /* Note secondaire des cartes Vent/Danger/Température (comble le vide façon carte Foyers). Desktop
     seulement : sur mobile les 4 cartes étroites deviendraient trop hautes → masquée, le centrage
     vertical suffit alors à équilibrer. */
  .kpi-note{margin-top:6px;font-size:11px;line-height:1.25;color:var(--muted);max-width:150px;font-weight:600}
  @media (max-width:1099px){.kpi-note{display:none}}
  /* Mobile : rangée KPI compacte et UNIFORME (la note satellite + le toggle gonflaient
     la 1re card → hauteurs inégales + troncature dans le peek replié de 132px). */
  @media (max-width:560px){
    .fw-note{display:none}
    .sheet-head{gap:7px;padding:0 12px 10px;align-items:stretch}
    .kpi{padding:8px 5px;border-radius:11px;justify-content:flex-start;gap:3px}
    .kpi .v{font-size:18px}
    .kpi .l{font-size:8.5px;margin-top:2px;letter-spacing:.02em;line-height:1.15}
    .kpi .v .vsub{font-size:9px;margin-top:2px}
    .firewin{margin-top:5px}
    .firewin button{padding:3px 9px;font-size:11px}
  }
  /* ── BADGE MÉTÉO ET MÉTÉO 10 JOURS (08/10/2026, repris de la carte des inondations, thème feu) ─────────────────
     Le haut du volet devient une colonne : badge météo pleine largeur, puis la tuile Foyers actifs en ligne.
     Performance des portables (PR #57/#58) : aucune animation permanente, aucun flou d'arrière-plan ; seules la
     glissière d'ouverture du panneau et la lueur du squelette (le temps du chargement) bougent, et le mode léger
     comme le mouvement réduit les coupent. Texte blanc du badge : 5,5:1 au moins sur la teinte la plus claire. */
  .sheet-head{flex-direction:column;gap:8px}
  .kpi.kpi-foyers{flex-direction:row;flex-wrap:wrap;justify-content:flex-start;gap:4px 10px;padding:8px 12px;text-align:left}
  .kpi.kpi-foyers .v{font-size:18px}
  .kpi.kpi-foyers .v .vsub{display:block;margin:4px 0 0;font-size:10px} /* sa propre ligne : « 2 » puis « 39 pts » se lisait « 239 pts » (audit H-9) */
  /* 13/10/2026 (audit H-9, suite) : centré sur la hauteur des deux lignes, « FOYERS ACTIFS » tombait au bout de la ligne des
     détections (« 24 h FOYERS ACTIFS ») ; il se pose désormais à hauteur du chiffre. */
  .kpi.kpi-foyers{align-items:flex-start}
  .kpi.kpi-foyers .l{margin-top:4px}
  .kpi.kpi-foyers .firewin{margin:0 0 0 auto}
  .kpi.kpi-foyers .fw-note{flex:1 0 100%;margin-top:2px}
  .mb-hote{margin:0;min-width:0}
  .mb{position:relative;display:grid;grid-template-columns:minmax(0,1fr);gap:8px;width:100%;min-height:150px;margin:0;padding:11px 13px;
    border:1px solid rgba(255,255,255,.08);border-radius:16px;color:#fff;text-align:left;font:inherit;cursor:pointer;overflow:hidden;isolation:isolate;
    background:linear-gradient(150deg,var(--mb-a,#ef6a1e) 0%,var(--mb-b,#c9440f) 58%,var(--mb-c,#8a2c0b) 100%);box-shadow:0 6px 18px rgba(120,40,10,.18);
    transition:box-shadow .15s}
  .mb::before{content:"";position:absolute;right:-40px;top:-60px;width:190px;height:190px;border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.16),rgba(255,255,255,0) 68%);z-index:-1;pointer-events:none}
  .mb:hover{box-shadow:0 8px 24px rgba(120,40,10,.26)}
  .mb:focus-visible{outline:3px solid var(--fire);outline-offset:2px}
  .mb-amb-nuageux{--mb-a:#d9732b;--mb-b:#a84a1a;--mb-c:#6e3012}
  .mb-amb-couvert{--mb-a:#66717f;--mb-b:#4b5563;--mb-c:#374151}
  .mb-amb-pluie{--mb-a:#3d5579;--mb-b:#2c3f5f;--mb-c:#1f2b45}
  .mb-amb-brouillard{--mb-a:#5a6779;--mb-b:#4a5567;--mb-c:#3a4352}
  .mb-amb-neige{--mb-a:#3f6aa3;--mb-b:#345a8c;--mb-c:#2a476f}
  .mb-amb-orage{--mb-a:#4a3d74;--mb-b:#2c2550;--mb-c:#17142e}
  .mb-amb-nuit{--mb-a:#3a2a4a;--mb-b:#22182e;--mb-c:#0f0a16}
  .mb-amb-nuit-couvert{--mb-a:#3b3a4e;--mb-b:#23222f;--mb-c:#111017}
  .mb-amb-nuit-pluie{--mb-a:#283754;--mb-b:#182237;--mb-c:#0c121f}
  .mb-haut{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:5px 8px;min-width:0;padding-right:22px}
  .mb-lieu{display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:100%;font-size:11.5px;font-weight:800;letter-spacing:.02em;color:rgba(255,255,255,.94)}
  .mb-lieu svg{flex:0 0 auto}
  .mb-lieu span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* Heure de la lecture (14/10/2026) : ne rétrécit jamais, c'est le nom du lieu qui cède. */
  .mb-lieu span.mb-lecture{flex:0 0 auto;overflow:visible;font-weight:700;opacity:.82}
  .mb-lieu span.mb-lecture::before{content:"·";margin-right:6px}
  .mb-mdf{flex:0 0 auto;padding:3px 9px;border-radius:99px;background:var(--mdf,#eab308);color:#fff;font-size:11px;font-weight:800;white-space:nowrap;box-shadow:0 2px 8px rgba(0,0,0,.18);text-shadow:0 1px 1px rgba(0,0,0,.25)}
  .mb-milieu{display:flex;align-items:center;gap:10px;min-width:0}
  .mb-temp{flex:0 0 auto;font-size:42px;font-weight:800;line-height:1;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
  .mb-tx{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1 1 auto}
  .mb-cond{font-size:14.5px;font-weight:800;line-height:1.2}
  .mb-sous{font-size:11.5px;font-weight:600;line-height:1.35;color:rgba(255,255,255,.9)}
  .mb-sous span{white-space:nowrap}
  .mb-ic{flex:0 0 auto;line-height:0;filter:drop-shadow(0 4px 10px rgba(0,0,0,.25))}
  .mb-ic .mt-ic{display:block;overflow:visible}
  .mb-feu{display:grid;grid-template-columns:1.25fr 1fr 1fr;gap:6px;min-width:0}
  .mb-c{display:flex;flex-direction:column;gap:1px;min-width:0;padding:6px 8px;border-radius:10px;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.14)}
  .mb-c small{font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;opacity:.88;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mb-c b{display:flex;align-items:center;gap:5px;font-size:14.5px;font-weight:800;line-height:1.15;font-variant-numeric:tabular-nums;white-space:nowrap}
  .mb-c i{font-style:normal;font-size:11px;font-weight:600;opacity:.92;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mb-c .mt-fleche{display:inline-grid;place-items:center;width:18px;height:18px;border-radius:50%;background:rgba(255,255,255,.22);flex:0 0 auto}
  .mb-c-danger.n-high b{color:#ffd166}.mb-c-danger.n-very-high b,.mb-c-danger.n-extreme b{color:#ffb4a2}
  .mb-c-danger.n-very-high,.mb-c-danger.n-extreme{background:rgba(255,255,255,.22);border-color:rgba(255,255,255,.35)}
  .mb-bas{display:flex;align-items:center;gap:7px;min-width:0;padding:6px 10px;border-radius:10px;background:rgba(255,255,255,.13);font-size:11.5px;font-weight:700;line-height:1.3}
  .mb-bas svg{flex:0 0 auto}
  .mb-bas span{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .mb-mouille,.mb-alerte{background:rgba(255,255,255,.2)}
  .mb-alerte-sec-vente{background:rgba(255,196,60,.28);border:1px solid rgba(255,214,120,.45)}
  .mb-chev{position:absolute;right:8px;top:9px;transform:rotate(-90deg);line-height:0;opacity:.85}
  .mb-cache{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .mb-squelette{cursor:progress;border-color:var(--line);box-shadow:none;background:linear-gradient(90deg,var(--panel2) 0%,var(--panel) 50%,var(--panel2) 100%);background-size:200% 100%;animation:mt-lueur 1.3s linear infinite}
  .mb-squelette::before{display:none}
  .mb-sq{display:block;border-radius:8px;background:color-mix(in srgb,var(--muted) 18%,transparent)}
  /* Hauteurs des rangées du badge dessiné (mesurées le 14/10/2026 : 15, 52, 63 et 27 px ; téléphone 15, 44, 59 et 24 px). */
  .mb-sq-1{width:46%;height:15px}.mb-sq-2{width:62%;height:52px;border-radius:10px}.mb-sq-3{width:100%;height:63px;border-radius:11px}.mb-sq-4{width:100%;height:27px;border-radius:9px}
  @media (max-width:1099px){.mb-sq-2{height:44px}.mb-sq-3{height:59px}.mb-sq-4{height:24px}}
  .mb-indispo{min-height:0;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:10px;padding:10px 34px 10px 12px;color:var(--muted);background:var(--panel2);border-color:var(--line);box-shadow:none}
  .mb-indispo::before{display:none}
  .mb-indispo-tx{font-size:12.5px;font-weight:700}
  .mb-indispo-ic{line-height:0;opacity:.8}
  @keyframes mt-lueur{from{background-position:100% 0}to{background-position:-100% 0}}
  body.leger .mb-squelette,body.leger .mt-sq{animation:none}
  @media (prefers-reduced-motion:reduce){.mb-squelette,.mt-sq{animation:none}.mb,.mt-panneau,.mt-voile,.mt-fleche,.mt-jour-chev{transition:none!important}}
  body.leger :is(.mt-panneau,.mt-voile,.mt-fleche,.mt-jour-chev){transition:none!important}
  /* Téléphone : le volet replié montre le badge entier (il remplace la rangée des quatre tuiles que montrait l'ancien repli). */
  @media (max-width:1099px){
    .mb{min-height:0;gap:6px;padding:9px 11px;border-radius:14px}
    .mb-temp{font-size:34px}
    .mb-cond{font-size:13.5px}
    .mb-sous{font-size:11px}
    .mb-ic .mt-ic{width:44px;height:44px}
    .mb-c{padding:4px 7px}
    .mb-c b{font-size:13.5px}
    .mb-bas{padding:5px 9px;font-size:11px}
    .mb-bas span{-webkit-line-clamp:1}
  }
  /* ── REPLI DE L'EN-TÊTE AU DÉFILEMENT (09/10/2026, fondateur : « ce serait bien que le haut du sheet, météo etc., se replie
     au scroll pour laisser de l'espace »). Téléphone seulement : quand le contenu du volet défile, le badge météo et la tuile
     Foyers actifs s'effacent et laissent une seule ligne compacte (#voletCompact : température, ciel, vent, danger, foyers) ;
     la rangée d'onglets reste collée sous la poignée. app.js lit scrollTop et pose --repli (0 à 1) et la hauteur de
     .sheet-head, une écriture par image : aucune transition ni animation, le défilement mène tout, la remontée redéploie.
     La ligne compacte reprend la teinte du badge (classe mb-amb-*, posée par app.js). Un appui dessus ramène le contenu
     en haut. Mode léger et mouvement réduit : repli en deux états, sans dégradé (app.js). */
  .vc{display:none}
  @media (max-width:1099px){
    #sheet.repli .sheet-head{position:relative;box-sizing:border-box;overflow:hidden}
    #sheet.repli .sheet-head>.mb-hote,#sheet.repli .sheet-head>.kpi-foyers{opacity:calc(1 - var(--repli,0) * 1.6);transform:translateY(calc(var(--repli,0) * -12px))}
    #sheet.repli-fin .sheet-head>.mb-hote,#sheet.repli-fin .sheet-head>.kpi-foyers{visibility:hidden}
    #sheet.repli .vc{display:flex;position:absolute;left:12px;right:12px;top:0;height:36px;align-items:center;gap:6px;margin:0;padding:0 8px 0 11px;
      border:1px solid var(--line);border-radius:12px;background:var(--panel2);color:var(--txt);font:inherit;text-align:left;cursor:pointer;
      opacity:clamp(0, var(--repli,0) * 2 - 1, 1);pointer-events:none}
    #sheet.repli-fin .vc{pointer-events:auto}
    #sheet.repli .vc[class*="mb-amb-"]{background:linear-gradient(90deg,var(--mb-a,#ef6a1e),var(--mb-b,#c9440f));color:#fff;border-color:rgba(255,255,255,.14);box-shadow:0 3px 10px rgba(120,40,10,.16)}
    .vc-meteo{flex:1 1 auto;min-width:0;font-size:11.5px;font-weight:700;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
    .vc-foyers{flex:0 0 auto;display:inline-flex;align-items:center;gap:4px;padding:2px 7px;border-radius:99px;background:var(--panel);border:1px solid var(--line);
      font-size:8.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--muted);white-space:nowrap}
    .vc-foyers b{font-size:11.5px;font-weight:800;color:var(--fire2);letter-spacing:0;font-variant-numeric:tabular-nums}
    #sheet.repli .vc[class*="mb-amb-"] .vc-foyers{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.2);color:rgba(255,255,255,.92)}
    #sheet.repli .vc[class*="mb-amb-"] .vc-foyers b{color:#fff}
    .vc-chev{flex:0 0 auto;line-height:0;opacity:.8}
    .vc:focus-visible{outline:3px solid var(--fire);outline-offset:2px}
  }

  /* Panneau « Météo 10 jours » : feuille plein écran sur téléphone, volet de 440 px à droite sur ordinateur (par-dessus
     le volet d'informations). Bandeau « Maintenant » en dégradé selon le temps, SANS décor animé ; bande heure par heure
     (courbe des températures, pluie, vent et rafales, humidité) ; 10 jours en barres min-max sur une échelle commune,
     avec le repère « sèche et ventée ». */
  .mt-panneau{--mt-fort:#c2410c;--mt-nuit:rgba(30,41,90,.055);--mt-ombre:0 1px 2px rgba(20,30,50,.05),0 8px 24px rgba(20,30,50,.06);--mt-sec:#b45309;--mt-eau:#1d6fd8}
  :root[data-theme="dark"] .mt-panneau{--mt-fort:#fdba74;--mt-nuit:rgba(148,163,255,.06);--mt-ombre:none;--mt-sec:#fbbf24;--mt-eau:#7dd3fc}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .mt-panneau{--mt-fort:#fdba74;--mt-nuit:rgba(148,163,255,.06);--mt-ombre:none;--mt-sec:#fbbf24;--mt-eau:#7dd3fc}}
  .mt-voile{position:fixed;inset:0;z-index:1430;background:rgba(8,12,20,.45);opacity:0;transition:opacity .25s ease}
  .mt-voile.ouvert{opacity:1}
  .mt-panneau{position:fixed;z-index:1440;left:0;right:0;bottom:0;top:calc(env(safe-area-inset-top) + 8px);display:flex;flex-direction:column;
    background:var(--bg);color:var(--txt);border-radius:24px 24px 0 0;box-shadow:0 -10px 40px rgba(0,0,0,.25);transform:translateY(102%);
    transition:transform .32s cubic-bezier(.2,.8,.2,1);overflow:hidden}
  .mt-panneau.ouvert{transform:none}
  @media (min-width:900px){
    .mt-panneau{left:auto;top:0;width:440px;border-radius:0;transform:translateX(102%);border-left:1px solid var(--line);box-shadow:-12px 0 40px rgba(0,0,0,.18)}
    .mt-voile{background:rgba(8,12,20,.16)}
    .mt-poignee{display:none}
  }
  .mt-tete{position:relative;flex:0 0 auto;display:flex;align-items:flex-start;gap:10px;padding:18px 12px 8px 18px;background:var(--panel)}
  .mt-poignee{position:absolute;top:7px;left:50%;width:40px;height:5px;margin-left:-20px;border-radius:9px;background:#cbd3e0}
  .mt-tete-tx{flex:1 1 auto;min-width:0}
  .mt-surtitre{display:block;font-size:11.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--fire)}
  .mt-titre{margin:2px 0 1px;font-size:24px;font-weight:800;letter-spacing:-.02em;line-height:1.15;color:var(--txt);text-transform:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mt-sous{display:block;font-size:12.5px;color:var(--muted)}
  .mt-x{flex:0 0 auto;width:42px;height:42px;border-radius:50%;border:1px solid var(--line);background:var(--panel2);color:var(--txt);display:grid;place-items:center;cursor:pointer}
  .mt-puces{flex:0 0 auto;display:flex;gap:8px;padding:2px 16px 12px;background:var(--panel);border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none}
  .mt-puce{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;min-height:36px;padding:6px 13px;border-radius:999px;border:1px solid var(--line);background:var(--panel);color:var(--txt);font-size:13px;font-weight:700;cursor:pointer}
  .mt-puce.on{background:var(--fire);border-color:var(--fire);color:#fff}
  .mt-corps{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:12px 12px calc(28px + env(safe-area-inset-bottom))}
  .mt-corps:focus{outline:none}
  .mt-section{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:14px;margin-bottom:12px;box-shadow:var(--mt-ombre)}
  .mt-h3{display:flex;align-items:center;gap:6px;margin:0 0 10px;font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:800}
  .mt-ic{display:block;overflow:visible}
  .mt-hero{overflow:hidden;color:#fff;border:0;padding:18px 16px 14px;background:linear-gradient(165deg,#f0742a 0%,#d2480f 58%,#8f2d0b 100%);box-shadow:0 10px 30px rgba(140,45,10,.22)}
  .mt-amb-nuageux{background:linear-gradient(165deg,#d9742c 0%,#a84a1a 55%,#6e3012 100%)}
  .mt-amb-couvert{background:linear-gradient(165deg,#6b7a92 0%,#4b5870 60%,#36415a 100%)}
  .mt-amb-pluie{background:linear-gradient(165deg,#4b6488 0%,#2f4163 60%,#1f2b45 100%)}
  .mt-amb-brouillard{background:linear-gradient(165deg,#6f7d90 0%,#535f72 60%,#3e4858 100%)}
  .mt-amb-neige{background:linear-gradient(165deg,#5b84bd 0%,#436a9f 60%,#2f4d7a 100%)}
  .mt-amb-orage{background:linear-gradient(165deg,#4c3f75 0%,#2c2550 60%,#17142e 100%)}
  .mt-amb-nuit{background:linear-gradient(165deg,#43304f 0%,#241a30 60%,#0f0a16 100%)}
  .mt-amb-nuit-couvert{background:linear-gradient(165deg,#3f3e52 0%,#25242f 60%,#111017 100%)}
  .mt-amb-nuit-pluie{background:linear-gradient(165deg,#283754 0%,#172036 60%,#0b111e 100%)}
  .mt-hero-haut{display:flex;align-items:center;justify-content:space-between;gap:6px}
  .mt-hero-tx{min-width:0}
  .mt-hero-etiquette{display:inline-block;font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;opacity:.9;padding:3px 9px;border-radius:99px;background:rgba(255,255,255,.16)}
  .mt-hero-temp{font-size:80px;font-weight:200;line-height:.95;letter-spacing:-.05em;margin:6px 0 2px -3px;font-variant-numeric:tabular-nums;text-shadow:0 4px 20px rgba(0,0,0,.15)}
  .mt-hero-cond{font-size:19px;font-weight:700;letter-spacing:-.01em}
  .mt-hero-sous{font-size:13.5px;opacity:.92;margin-top:3px}
  .mt-hero-ic{flex:0 0 auto;margin-right:-6px}
  .mt-hero-ic svg{width:112px;height:112px;filter:drop-shadow(0 10px 18px rgba(0,0,0,.28))}
  .mt-tuiles{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}
  .mt-tuile{min-width:0;padding:10px 12px;border-radius:14px;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.2)}
  .mt-tuile-e{display:flex;align-items:center;gap:5px;font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;opacity:.88}
  .mt-tuile-v{display:flex;align-items:center;gap:6px;margin-top:4px;font-size:19px;font-weight:700;letter-spacing:-.01em;font-variant-numeric:tabular-nums}
  .mt-tuile-d{display:block;margin-top:2px;font-size:12px;opacity:.9;line-height:1.3}
  .mt-tuile.mt-danger.n-high .mt-tuile-v{color:#ffd166}.mt-tuile.mt-danger.n-very-high .mt-tuile-v,.mt-tuile.mt-danger.n-extreme .mt-tuile-v{color:#ffb4a2}
  .mt-fleche{display:inline-grid;place-items:center}
  .mt-tuile .mt-fleche{width:24px;height:24px;border-radius:50%;background:rgba(255,255,255,.2)}
  .mt-forets-jours{display:flex;flex-wrap:wrap;gap:8px}
  .mt-forets-niv{display:inline-flex;flex-direction:column;gap:2px;padding:8px 12px;border-radius:12px;border:1px solid var(--mdf);background:color-mix(in srgb,var(--mdf) 12%,var(--panel))}
  .mt-forets-niv b{font-size:12px;color:var(--muted);font-weight:700}
  .mt-forets-niv span{font-size:14px;font-weight:800;color:var(--mdf)}
  .mt-lien{margin-top:10px;display:inline-flex;align-items:center;gap:6px;min-height:34px;padding:5px 12px;border-radius:999px;border:1px solid var(--line);background:var(--panel);color:var(--fire);font-size:12.5px;font-weight:800;cursor:pointer}
  .mt-pluie-phrase{margin:0;font-size:16px;font-weight:700;letter-spacing:-.01em}
  .mt-pluie-phrase.mouille{color:var(--mt-eau)}
  .mt-quarts{margin-top:10px;display:grid;grid-template-columns:repeat(8,1fr);align-items:end;gap:5px;height:58px;padding:6px;border-radius:14px;background:var(--panel2)}
  .mt-quart{display:flex;align-items:flex-end;height:100%}
  .mt-quart i{display:block;width:100%;border-radius:6px 6px 2px 2px;background:var(--line)}
  .mt-quart.mouille i{background:linear-gradient(180deg,#7dd3fc,#2563eb)}
  .mt-quarts-reperes{display:flex;justify-content:space-between;margin-top:5px;padding:0 6px;font-size:11.5px;color:var(--muted);font-variant-numeric:tabular-nums}
  .mt-note{display:block;margin:6px 0 0;font-size:12.5px;color:var(--muted);line-height:1.45}
  .mt-aucune{margin:0;font-size:14px}
  .mt-alertes-liste{list-style:none;margin:0;padding:0;display:grid;gap:8px}
  .mt-alerte{display:grid;grid-template-columns:34px 1fr;align-items:center;gap:6px 10px;padding:10px 12px;border-radius:14px;background:var(--panel2);border:1px dashed var(--line)}
  .mt-alerte-tx{min-width:0}
  :is(.mt-alerte-orage,.mt-alerte-vent-violent,.mt-alerte-sec-vente){border-style:solid;border-color:var(--mt-fort)}
  .mt-alerte-sec-vente{background:color-mix(in srgb,var(--mt-fort) 10%,var(--panel2))}
  .mt-alerte-tx b{display:block;font-size:14.5px}
  .mt-alerte-tx span{display:block;font-size:13px;color:var(--muted)}
  .mt-avert{margin:10px 0 0;font-size:12px;font-style:italic;color:var(--muted);line-height:1.45}
  .mt-piste-cadre{margin:0 -14px;padding:0 14px 8px;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scroll-padding:0 14px}
  .mt-piste-cadre:focus-visible{outline:2px solid var(--fire);outline-offset:-2px;border-radius:12px}
  .mt-piste{position:relative;display:flex}
  .mt-courbe{position:absolute;left:0;top:68px;z-index:1;pointer-events:none;overflow:visible;color:var(--fire)}
  .mt-courbe-t text{font-size:13.5px;font-weight:800;fill:var(--txt);paint-order:stroke;stroke:var(--panel);stroke-width:3px;font-variant-numeric:tabular-nums}
  .mt-col{position:relative;flex:0 0 58px;width:58px;display:flex;flex-direction:column;align-items:center;border-radius:12px}
  .mt-col.nuit{background:var(--mt-nuit);border-radius:0}
  .mt-col.minuit::before{content:'';position:absolute;left:0;top:2px;bottom:4px;border-left:1.5px dashed var(--line)}
  .mt-col-jour{align-self:flex-start;height:16px;padding-left:6px;font-size:11.5px;font-weight:800;color:var(--txt);white-space:nowrap;z-index:2}
  .mt-col-h{height:18px;font-size:12.5px;font-weight:600;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
  .mt-col.maint .mt-col-h{color:var(--fire);font-weight:800}
  .mt-col-ic{height:34px;display:grid;place-items:center}
  .mt-col-courbe{height:70px}
  .mt-col-pluie{display:flex;align-items:flex-end;width:22px;height:30px;border-bottom:1px solid var(--line)}
  .mt-col-pluie i{display:block;width:100%;border-radius:5px 5px 1px 1px;background:linear-gradient(180deg,#7dd3fc,#2563eb)}
  .mt-col-mm{height:16px;margin-top:2px;font-size:11.5px;font-weight:800;color:var(--mt-eau);font-variant-numeric:tabular-nums}
  .mt-col-mm.vide{color:var(--muted);opacity:.5}
  .mt-col-vent{display:flex;align-items:center;gap:2px;height:20px;margin-top:4px;font-size:12.5px}
  .mt-col-vent .mt-fleche{color:var(--muted)}
  .mt-col-raf{height:15px;font-size:11px;color:var(--muted)}
  .mt-col-raf.fort{color:var(--mt-fort);font-weight:800}
  .mt-col-hum{height:15px;font-size:11px;color:var(--muted)}
  .mt-col-hum.sec{color:var(--mt-sec);font-weight:800}
  .mt-piste-cadre.sans-pluie :is(.mt-col-pluie,.mt-col-mm){display:none}
  .mt-legende{display:flex;flex-wrap:wrap;gap:6px 14px;margin:8px 0 0;font-size:11.5px;color:var(--muted)}
  .mt-legende span::before{content:'';display:inline-block;width:8px;height:8px;margin-right:5px;border-radius:2px;background:#2563eb;vertical-align:0}
  .mt-legende .mt-leg-vent::before{border-radius:50%;background:var(--muted)}
  .mt-legende .mt-leg-hum::before{border-radius:50%;background:var(--mt-sec)}
  .mt-jours-liste{list-style:none;margin:0 -6px;padding:0}
  .mt-jour + .mt-jour{border-top:1px solid var(--line)}
  .mt-jour.sec-oui{box-shadow:inset 3px 0 0 var(--mt-sec)}
  .mt-jour.sec-tres{box-shadow:inset 3px 0 0 var(--mt-fort);background:color-mix(in srgb,var(--mt-fort) 6%,transparent)}
  .mt-jour-tete{width:100%;display:grid;grid-template-columns:minmax(64px,92px) 34px 30px minmax(40px,1fr) 30px 12px;align-items:center;gap:1px 6px;padding:10px 6px 9px;border:0;border-radius:14px;background:none;color:inherit;text-align:left;cursor:pointer;-webkit-tap-highlight-color:transparent}
  .mt-jour-tete:hover{background:var(--panel2)}
  .mt-jour-tete:focus-visible{outline:2px solid var(--fire);outline-offset:-2px}
  .mt-jour-nom{font-size:14.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .mt-jour-ic{display:grid;place-items:center}
  .mt-jour-min{text-align:right;font-size:15px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
  .mt-jour-max{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums}
  .mt-barre{position:relative;height:7px;border-radius:99px;background:var(--panel2);box-shadow:inset 0 0 0 1px var(--line)}
  .mt-barre-plage{position:absolute;top:0;bottom:0;border-radius:99px}
  .mt-barre-point{position:absolute;top:50%;width:11px;height:11px;margin:-5.5px 0 0 -5.5px;border-radius:50%;background:#fff;border:2.5px solid var(--txt);box-shadow:0 1px 4px rgba(0,0,0,.3)}
  .mt-jour-chev{display:grid;place-items:center;color:var(--muted);transition:transform .25s ease}
  .mt-jour.ouvert .mt-jour-chev{transform:rotate(180deg)}
  .mt-jour-infos{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:4px 12px;font-size:12px;color:var(--muted)}
  .mt-jour-infos span{display:inline-flex;align-items:center;gap:3px}
  .mt-jour-infos .mt-fleche{color:var(--muted)}
  .mt-info-pluie.mouille{color:var(--mt-eau);font-weight:600}
  .mt-info-vent.fort{color:var(--mt-fort);font-weight:800}
  .mt-info-hum.sec{color:var(--mt-sec);font-weight:800}
  .mt-info-sec{padding:1px 8px;border-radius:99px;background:color-mix(in srgb,var(--mt-sec) 14%,var(--panel));color:var(--mt-sec);font-weight:800}
  .mt-info-sec.tres{background:color-mix(in srgb,var(--mt-fort) 16%,var(--panel));color:var(--mt-fort)}
  .mt-note-sec{display:flex;align-items:flex-start;gap:6px;font-style:normal}
  .mt-note-sec svg{flex:0 0 auto;margin-top:2px;color:var(--mt-sec)}
  .mt-jour-detail{padding:0 6px 12px}
  .mt-jour-resume{margin:0 0 8px;font-size:13px;color:var(--muted)}
  .mt-jour-detail .mt-piste-cadre{margin:0 -8px;padding:0 8px 6px}
  .mt-pied{padding:4px 6px 12px;font-size:12px;line-height:1.45;color:var(--muted)}
  .mt-pied a{color:var(--fire);font-weight:700}
  .mt-pied p{margin:6px 0 0}
  .mt-sq{margin-bottom:12px;border-radius:18px;border:1px solid var(--line);background:linear-gradient(90deg,var(--panel) 0%,var(--panel2) 50%,var(--panel) 100%);background-size:200% 100%;animation:mt-lueur 1.3s linear infinite}
  .mt-sq-hero{height:300px}.mt-sq-ligne{height:110px}.mt-sq-bande{height:250px}.mt-sq-liste{height:440px}
  .mt-erreur{display:flex;flex-direction:column;align-items:center;text-align:center;padding:48px 20px}
  .mt-erreur-t{margin:10px 0 4px;font-size:18px;font-weight:800}
  .mt-erreur-d{margin:0 0 16px;font-size:14px;color:var(--muted)}
  .mt-reessayer{display:inline-flex;align-items:center;gap:8px;min-height:46px;padding:10px 20px;border:0;border-radius:14px;background:var(--fire);color:#fff;font-weight:800;cursor:pointer}

  /* ── Onboarding assistant (1re visite) ─────────────────────────────────────────────────────── */
  #tourOverlay{position:fixed;inset:0;z-index:6000;display:none}
  #tourOverlay.show{display:block}
  /* Voile SANS flou (08/10/2026) : un backdrop-filter plein écran est recalculé à chaque image tant que la carte
     s'anime dessous (vent, avions, pastilles) ; sur PC portable en rendu logiciel la carte tombait à 6-10 images/s
     pendant la visite de bienvenue, donc pour tout nouveau visiteur. Voile un peu plus dense à la place. */
  #tourOverlay.scrim{background:rgba(8,12,20,.62)}
  .tour-spot{position:fixed;border-radius:14px;border:2.5px solid #ff8a1f;
    box-shadow:0 0 0 9999px rgba(8,12,20,.55),0 0 0 5px rgba(255,138,31,.35);
    transition:all .35s ease;pointer-events:none}
  .invit-modal{position:fixed;inset:0;z-index:6000;display:flex;align-items:center;justify-content:center;background:rgba(8,12,20,.62);padding:20px}
  .invit-modal[hidden]{display:none}
  .invit-card{background:var(--panel,#fff);color:var(--txt,#111);border-radius:20px;padding:22px 20px 16px;max-width:420px;width:100%;box-shadow:0 18px 50px rgba(0,0,0,.4);text-align:center;animation:tourIn .3s ease}
  .invit-ic{width:54px;height:54px;margin:0 auto 12px;border-radius:16px;display:grid;place-items:center;background:linear-gradient(135deg,#0b1a3a,#1d4ed8);color:#fff;box-shadow:0 4px 14px rgba(29,78,216,.35);overflow:hidden}
  .invit-ic img{width:54px;height:54px;border-radius:16px;display:block}
  .invit-card h2{margin:0 0 8px;font-size:19px;line-height:1.25;letter-spacing:-.2px}
  .invit-card p{margin:0 0 16px;font-size:14px;line-height:1.45;color:var(--muted,#555)}
  .invit-go{display:block;padding:12px 16px;border-radius:12px;background:linear-gradient(135deg,#1d4ed8,#2563eb);color:#fff;font-weight:700;text-decoration:none;font-size:14.5px;box-shadow:0 6px 18px rgba(37,99,235,.3)}
  .invit-later{margin-top:6px;background:none;border:0;color:var(--muted,#666);font-size:13px;padding:9px;cursor:pointer;font-family:inherit}
  .tour-card{position:fixed;left:16px;right:16px;bottom:calc(20px + env(safe-area-inset-bottom));
    max-width:420px;margin:0 auto;background:var(--panel);border-radius:18px;padding:16px 16px 13px;
    box-shadow:0 12px 40px rgba(0,0,0,.35);animation:tourIn .3s ease;
    transition:top .25s ease,bottom .25s ease,left .25s ease,right .25s ease}
  @keyframes tourIn{from{transform:translateY(14px);opacity:0}to{transform:none;opacity:1}}
  .tour-head{display:flex;align-items:center;gap:10px;margin-bottom:7px}
  .tour-avatar{flex:0 0 auto;width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;
    background:linear-gradient(135deg,#ff8a1f,#e2340d);box-shadow:0 3px 10px rgba(226,52,13,.35)}
  .tour-head b{font-size:15.5px;letter-spacing:-.2px;color:var(--txt)}
  .tour-tcol{display:flex;flex-direction:column;gap:3px;min-width:0}
  .tour-badge{align-self:flex-start;font-size:9.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#e2340d;background:rgba(226,52,13,.1);border:1px solid rgba(226,52,13,.35);border-radius:7px;padding:1.5px 7px}
  #tourText{margin:0;font-size:13.5px;line-height:1.55;color:var(--txt);opacity:.92}
  .tour-dots{display:flex;gap:5px;margin:11px 0 10px}
  .tour-dots span{width:7px;height:7px;border-radius:50%;background:var(--line);transition:all .25s}
  .tour-dots span.on{background:#ff5a1f;width:18px;border-radius:5px}
  .tour-actions{display:flex;gap:9px}
  .tour-skip{flex:0 0 auto;background:transparent;border:0;color:var(--muted);font-size:12.5px;font-weight:700;padding:10px 10px;cursor:pointer}
  .tour-next{flex:1;background:linear-gradient(135deg,#ff8a1f,#e2340d);color:#fff;border:0;border-radius:12px;
    padding:11px 14px;font-size:14px;font-weight:800;cursor:pointer;box-shadow:0 4px 14px rgba(226,52,13,.32)}
  .tour-next:active{filter:brightness(.94)}
  @media (min-width:1100px){.tour-card{left:auto;right:24px;bottom:24px}}
  /* Sélecteur 24 h / 48 h des détections satellite (carte KPI Foyers) · parité NASA FIRMS.
     BIEN VISIBLE (demande user : « on ne le voit pas ») : boutons francs, actif en couleur feu. */
  .firewin{display:inline-flex;gap:0;margin-top:7px;border:1.5px solid var(--fire2);border-radius:9px;overflow:hidden;box-shadow:0 1px 3px rgba(226,52,13,.18)}
  .firewin button{min-height:24px;background:transparent;border:0;color:var(--fire-txt);font-size:11px;font-weight:800;padding:4px 10px;cursor:pointer;line-height:1;letter-spacing:.01em}
  .firewin button.on{background:var(--fire-on);color:#fff}
  /* Légende sous le sélecteur 24/48 h : lève la confusion « prévision » (retour user : les gens
     croyaient à une projection à 24-48 h, alors que ce sont des DÉTECTIONS satellite passées). */
  .fw-note{margin-top:4px;font-size:11px;line-height:1.25;color:var(--muted);max-width:158px;font-weight:600}
  /* Info-bulle affichée AU CLIC/TAP sur le toggle 24/48 h (le title ne s'ouvre qu'au survol desktop,
     et le pill flottant de la carte n'a pas de place pour une légende). Auto-masquée après ~4,5 s. */
  .fw-tip{position:fixed;z-index:1200;display:none;background:rgba(17,20,26,.96);color:#fff;font-size:11px;line-height:1.3;font-weight:600;padding:7px 10px;border-radius:9px;box-shadow:0 6px 20px rgba(0,0,0,.32);pointer-events:none;max-width:230px}
  .fw-tip::after{content:"";position:absolute;left:50%;bottom:-6px;transform:translateX(-50%);border:6px solid transparent;border-top-color:rgba(17,20,26,.96);border-bottom:0}
  /* Version SUR LA CARTE : pill opaque lisible sur l'imagerie satellite. Mobile = EN HAUT À GAUCHE,
     juste sous la barre des périodes (demande user) ; desktop = à droite sous les boutons de zoom. */
  .firewin-map{position:absolute;left:12px;top:calc(78px + env(safe-area-inset-top));z-index:1055;
    background:var(--panel);border-color:var(--fire2);box-shadow:0 2px 10px rgba(0,0,0,.3);margin-top:0;align-items:center}
  .firewin-map .fw-ic{font-size:12px;padding:0 2px 0 7px}
  .firewin-map button{padding:6px 10px;font-size:11.5px}
  /* Desktop : la pastille 24/48 h doit rester SUR LA CARTE, pas derrière le panneau de situation
     (~400 px). On l'aligne dans la même colonne d'outils que le zoom (right:412px, top:72px) et
     #modeSeg (right:412px, bottom:16px), juste SOUS le zoom. Un right:10px la cachait sous le panneau. */
  /* Desktop : 24/48 h EN HAUT À GAUCHE, SOUS la barre période (#horizonSeg), pas à droite près du panneau
     (chevauchait le panneau de situation + son tooltip · demande fondateur 2026-08-17). left:12px aligne sur
     la barre période ; top:118px la pose juste dessous sans chevauchement. */
  @media (min-width:1100px){.firewin-map{left:12px;right:auto;top:calc(var(--hdr-h,56px) + 62px)}}   /* sous la frise, bandeau d'une ou deux rangées (audit MO-8) */
  /* sheet-body = colonne flex : les panes normaux gardent leur hauteur (la sheet-body scrolle) ; le pane Assistant
     remplit la hauteur restante pour épingler son composer en bas (voir plus bas). */
  .sheet-body{overflow-y:auto;padding:2px 16px 22px;-webkit-overflow-scrolling:touch;flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
  .pane{display:none} .pane.on{display:block}
  .sheet-body>.pane.on{flex:0 0 auto}
  /* Pane Assistant = colonne flex qui remplit la sheet : SEULE .chat-scroll défile, le composer reste épinglé en bas. */
  .sheet-body>.pane.on[data-p="ia"]{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}
  .chat-scroll{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}
  .block{background:var(--panel2);border:1px solid var(--line);border-radius:13px;padding:13px 14px;margin-bottom:11px}
  /* Emplacement publicitaire (rempli par fvAds). Thème-aware via les vars. Masqué tant que vide. */
  .fv-ad{margin:11px 0;border:1px solid var(--line);border-radius:13px;background:var(--panel2);overflow:hidden}
  .fv-ad:empty{display:none;border:0;margin:0}
  .fv-ad-lbl{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);padding:5px 10px 0;font-weight:700}
  .fv-ad ins.adsbygoogle{display:block;min-height:90px}
  .fv-ad-house{display:flex;align-items:center;gap:11px;padding:13px 14px;text-decoration:none;color:var(--txt);cursor:pointer}
  .fv-ad-house .fv-ic{font-size:23px;line-height:1;flex:0 0 auto}
  .fv-ad-house .fv-b{font-weight:800;font-size:13.5px;display:block}
  .fv-ad-house .fv-s{font-size:11.5px;color:var(--muted);line-height:1.45;margin-top:2px;display:block}
  .fv-ad-house:hover{background:rgba(234,74,18,.06)}
  .block h3{margin:0 0 7px;font-size:11.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);display:flex;align-items:center;gap:6px;font-weight:700}
  .block p{margin:0;font-size:14.5px;line-height:1.55}
  /* Vidéo filmée en PORTRAIT (téléphone) : ratio 9/16 conservé partout, largeur capée à 340px et
     centrée plutôt qu'étirée pleine largeur · sinon elle deviendrait un pavé démesurément haut sur
     desktop/tablette (panneau ~400px de large). */
  .video-portrait{position:relative;width:100%;max-width:340px;margin:0 auto;aspect-ratio:9/16;border-radius:11px;overflow:hidden;background:#000;box-shadow:var(--shadow)}
  .video-portrait iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
  .block.now{background:linear-gradient(180deg,var(--now-tint),var(--panel2));border-color:rgba(234,74,18,.35)}
  .block.now h3{color:var(--fire)} .block.next h3{color:var(--accent)}
  /* Bloc éditorial crawlable (#seoEdito, pane Situation) : typographie sobre sur les variables du thème,
     aucun positionnement fixed/absolute, aucune animation · suit thème clair/sombre et body[data-radius] via .block. */
  .seo-edito{margin-top:6px}
  .seo-edito h2{margin:0 0 8px;font-size:16px;line-height:1.3;font-weight:800;color:var(--txt);letter-spacing:0}
  .seo-edito h3{margin:12px 0 5px}
  .seo-edito p,.seo-edito li{margin:0;font-size:13px;line-height:1.6;color:var(--txt)}
  .seo-edito ul{margin:0;padding-left:18px}
  .seo-edito li+li{margin-top:4px}
  .seo-edito a{color:var(--accent);text-decoration:none;font-weight:700}
  .seo-edito a:hover,.seo-edito a:focus-visible{text-decoration:underline}
  /* Bandeau d'état global (haut du volet Situation) : vert calme / orange vigilance / rouge alerte.
     Thème clair uniquement (comme le reste de l'app) · pas d'override sombre (sinon incohérent). */
  .statusbar{margin:0 0 10px;padding:10px 13px;border-radius:12px;font-size:13px;font-weight:700;line-height:1.45}
  .statusbar[hidden]{display:none}
  .statusbar.green{background:#e7f7ec;color:#12703a;border:1px solid #b7e6c6}
  .statusbar.amber{background:#fff4e0;color:#8a5200;border:1px solid #ffdfa6}
  .statusbar.red{background:#ffe9e6;color:#a51f16;border:1px solid #ffc4bd}
  :root[data-theme="dark"] .statusbar.green{background:rgba(22,163,74,.16);color:#86e0a6;border-color:rgba(22,163,74,.4)}
  :root[data-theme="dark"] .statusbar.amber{background:rgba(224,138,0,.16);color:#f0c479;border-color:rgba(224,138,0,.4)}
  :root[data-theme="dark"] .statusbar.red{background:rgba(225,29,29,.16);color:#ff9d92;border-color:rgba(225,29,29,.42)}
  @media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .statusbar.green{background:rgba(22,163,74,.16);color:#86e0a6;border-color:rgba(22,163,74,.4)}:root:not([data-theme="light"]) .statusbar.amber{background:rgba(224,138,0,.16);color:#f0c479;border-color:rgba(224,138,0,.4)}:root:not([data-theme="light"]) .statusbar.red{background:rgba(225,29,29,.16);color:#ff9d92;border-color:rgba(225,29,29,.42)}}
  .statusbar .sb-main{font-weight:800}
  /* CTA de signalement citoyen — affiché uniquement dans le bandeau CALME (vert). Pastille cliquable. */
  .statusbar .sb-cta{margin-top:7px;display:inline-flex;align-items:center;gap:6px;cursor:pointer;font-weight:800;padding:6px 11px;border-radius:20px;background:rgba(18,112,58,.12);border:1px solid rgba(18,112,58,.28);transition:background .15s,transform .1s}
  .statusbar .sb-cta:hover{background:rgba(18,112,58,.2)} .statusbar .sb-cta:active{transform:scale(.97)}
  :root[data-theme="dark"] .statusbar .sb-cta{background:rgba(134,224,166,.14);border-color:rgba(134,224,166,.34)}
  @media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .statusbar .sb-cta{background:rgba(134,224,166,.14);border-color:rgba(134,224,166,.34)}}
  .statusbar .sb-note{font-size:11px;font-weight:600;opacity:.9;margin-top:4px}
  .statusbar .sb-news{font-size:12px;font-weight:700;margin-top:6px;padding-top:6px;border-top:1px solid rgba(0,0,0,.10);cursor:pointer}
  .statusbar .sb-news:active{opacity:.7}
  /* Encart IA (synthèse « maintenant » + explication progression) sous le texte déterministe. */
  /* Éclairage IA · même langage « carte » que les popups .evpop : bandeau dégradé à médaillon,
     corps aéré, note en pied séparée d'un filet. Le bloc n'est plus un simple encart pastel. */
  .ai-reason{margin-top:10px;padding:0;border-radius:14px;overflow:hidden;background:var(--panel2);
    border:1px solid var(--line);box-shadow:0 2px 10px rgba(8,12,24,.18);font-size:13px;line-height:1.55}
  .ai-reason-h{display:flex;align-items:center;gap:8px;font-weight:800;font-size:12px;color:#fff;
    letter-spacing:.3px;text-transform:uppercase;padding:8px 12px;margin:0;
    background:linear-gradient(135deg,#312e81,#4f46e5)}
  .ai-reason-h .arh-ic{flex:0 0 auto;width:20px;height:20px;border-radius:6px;display:inline-flex;
    align-items:center;justify-content:center;background:rgba(255,255,255,.16)}
  .ai-reason-h .arh-ic svg{width:12.5px;height:12.5px}
  .ai-reason p{margin:0;padding:10px 12px 8px;color:var(--txt)}
  .ai-reason-dis{margin:0;padding:7px 12px 9px;font-size:11px;color:var(--muted);font-style:italic;
    border-top:1px solid var(--line)}
  /* App = thème clair uniquement (vars --panel/--txt restent claires même en mode sombre OS) :
     l'encart reste clair et lisible, pas d'override sombre (sinon fond sombre + texte sombre = illisible). */
  /* Badges d'état en APLAT PLEIN. Les teintes translucides à 12 % se lisaient mal sur un fond de carte
     clair et donnaient un niveau de danger qui semblait délavé. Les tons sont volontairement PROFONDS :
     du blanc sur un vert ou un orange vif ne passe pas le contraste AA à cette taille de texte (11,5 px
     gras n'est pas du « grand texte » au sens WCAG), alors que ces trois-là le passent. */
  .badge{display:inline-block;font-size:11.5px;font-weight:800;padding:3px 10px;border-radius:20px;
    color:#fff;letter-spacing:.01em;border:1px solid rgba(0,0,0,.10)}
  .b-danger{background:#c81e1e;box-shadow:0 1px 4px rgba(200,30,30,.35)}
  .b-warn{background:#c2620a;box-shadow:0 1px 4px rgba(194,98,10,.32)}
  .b-ok{background:#15803d;box-shadow:0 1px 4px rgba(21,128,61,.30)}
  /* ONGLET VILLES (20/09/2026) : guide de lecture, sections, cartes par commune au vocabulaire des cartes Situation. */
  .vil-guide{border:1px solid var(--line);border-radius:12px;background:var(--panel);padding:10px 12px;margin:0 0 10px}
  .vil-guide-t{display:flex;align-items:center;gap:7px;font-size:13.5px;font-weight:800;color:var(--txt);margin:0 0 7px}
  .vil-guide-t svg{width:15px;height:15px;color:var(--fire);flex:0 0 auto}
  .vil-guide-l{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
  .vil-guide-l li{display:flex;gap:8px;align-items:flex-start;font-size:12.5px;line-height:1.45;color:var(--txt);min-width:0}
  .vil-guide-l li svg{flex:0 0 auto;width:15px;height:15px;margin-top:2px;color:var(--muted)}
  .vil-guide-l li b{font-weight:800}
  .vil-guide-l li.vil-guide-warn{color:var(--danger);font-weight:600;border-top:1px solid var(--line);padding-top:7px;margin-top:2px}
  .vil-guide-l li.vil-guide-warn svg{color:var(--danger)}
  :root[data-theme="dark"] .vil-guide-l li.vil-guide-warn{color:#ff9d92}
  @media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .vil-guide-l li.vil-guide-warn{color:#ff9d92}}
  .vil-sec{display:flex;align-items:center;gap:6px;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:800;margin:10px 2px 6px}
  .vil-sec:first-child{margin-top:2px}
  .vil-sec svg{width:13px;height:13px;flex:0 0 auto}
  .vil-sec .n{background:var(--panel2);border:1px solid var(--line);border-radius:999px;padding:0 7px;font-size:10.5px;color:var(--txt)}
  .vil-note{font-size:11.5px;color:var(--muted);line-height:1.5;margin:6px 2px 0}
  .vil-suivi{border:1px solid var(--line);border-radius:12px;background:var(--panel);padding:10px 12px;margin:0 0 10px}
  .vil-suivi-t{display:flex;align-items:center;gap:7px;font-size:13.5px;font-weight:800;color:var(--txt);margin:0 0 4px}
  .vil-suivi-t svg{width:15px;height:15px;color:var(--accent);flex:0 0 auto}
  .vil-suivi-p{margin:0 0 8px;font-size:12px;color:var(--muted);line-height:1.45}
  .town-search{margin:0 0 8px}
  .town-search input{width:100%;box-sizing:border-box;background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:10px 13px;font-size:13.5px;color:var(--txt);outline:none;transition:.15s}
  .town-search input:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(31,122,224,.12)}
  .town-search input::placeholder{color:var(--muted)}
  .town.mini{padding:8px 8px 8px 12px;margin-bottom:6px;background:var(--panel2)}
  #suiviList .town:last-child{margin-bottom:0}
  .town{display:flex;align-items:center;gap:10px;padding:10px 10px 10px 12px;background:var(--panel);border:1px solid var(--line);border-radius:12px;margin-bottom:7px;cursor:pointer;transition:border-color .15s,transform .15s;min-width:0}
  .town:hover,.town:focus-visible{border-color:var(--accent);outline:none}
  .town:active{transform:scale(.99)}
  .town.evac{border-color:rgba(200,30,30,.45);background-color:var(--panel);background-image:linear-gradient(90deg,rgba(225,29,29,.07),var(--panel))}
  .town .m{flex:1;min-width:0}
  .town .nm{font-weight:800;font-size:13.5px;line-height:1.3;color:var(--txt);overflow-wrap:anywhere}
  .town .nm small{color:var(--muted);font-weight:500;font-size:11.5px}
  .town .meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:5px}
  .town .vbadge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;font-size:10.5px;font-weight:800;color:#fff;text-transform:uppercase;letter-spacing:.03em;white-space:nowrap;line-height:1.5}
  .town .vbadge svg{width:11px;height:11px}
  .vb-flammes{background:#d97706}.vb-evac{background:#c81e1e}.vb-prox{background:#b45309}.vb-fumee{background:#5b6b82}
  .town .delai{font-size:12.5px;font-weight:800;color:var(--txt);white-space:nowrap}
  .town .d{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;font-size:12px;color:var(--muted);margin-top:5px;line-height:1.45;min-width:0}
  .town .d .spf-i>svg{width:13px;height:13px}
  .town .aqi-badge{cursor:pointer;user-select:none}
  .town .aqi-detail{margin-top:6px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:7px 9px;font-size:11.5px;line-height:1.5;color:var(--txt)}
  .town .aqi-detail[hidden]{display:none}
  .town .aqi-adv{color:var(--fire);font-weight:600;margin-top:3px}
  .town .aqi-src{color:var(--muted);font-size:11px;margin-top:3px}
  .town .bell{flex:0 0 auto;width:38px;height:38px;border-radius:11px;border:1px solid var(--line);background:var(--panel2);
    font-size:17px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.15s;line-height:1}
  .town .bell:hover{border-color:#ff5a1f}
  /* Liste des avions (#airList) : même gabarit .town avec icône, colonne altitude/vitesse. */
  .town .ic{font-size:21px;flex:0 0 auto}
  .town .eta{text-align:right;font-size:13px;font-weight:800;flex:0 0 auto}
  .town .eta small{display:block;font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;margin-top:2px}
  .smoke-badge{display:inline-block;font-size:10px;padding:1px 6px;border-radius:20px;font-weight:700;vertical-align:1px;background:rgba(120,124,140,.16);color:var(--muted);white-space:nowrap}
  .smoke-badge.soon{background:rgba(234,74,18,.13);color:var(--fire)}
  .smoke-badge.here{background:rgba(225,29,29,.15);color:var(--danger)}
  .town .bell.on{background:linear-gradient(135deg,#ff8a3d,#ff3b30);border-color:transparent;box-shadow:0 3px 10px rgba(255,90,31,.4);animation:bellpulse 2s ease-in-out infinite}
  @keyframes bellpulse{0%,100%{box-shadow:0 3px 10px rgba(255,90,31,.35)}50%{box-shadow:0 3px 16px rgba(255,90,31,.7)}}
  /* Fil d'actualité */
  .news-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
  .news-head b{font-size:15px}
  .news-t{font-size:11px;color:var(--muted);margin-left:8px;font-weight:500}
  #newsReload{width:32px;height:32px;border-radius:9px;border:1px solid var(--line);background:var(--panel2);color:var(--txt);cursor:pointer;font-size:15px}
  #newsReload.spin{animation:hspin .8s linear infinite;pointer-events:none;opacity:.6}
  .offaccts{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
  .offaccts a{font-size:11.5px;font-weight:600;text-decoration:none;color:var(--txt);background:var(--panel2);border:1px solid var(--line);
    border-radius:20px;padding:5px 10px;white-space:nowrap;transition:.12s}
  .offaccts a:hover{border-color:#ff5a1f}
  .na{display:flex;gap:11px;padding:10px;background:var(--panel2);border:1px solid var(--line);border-radius:13px;margin-bottom:9px;
    text-decoration:none;color:inherit;transition:.12s;align-items:flex-start}
  .na:hover{border-color:#ff5a1f;transform:translateY(-1px)}
  .na .thumb{flex:0 0 auto;width:58px;height:58px;border-radius:10px;object-fit:cover;background:var(--panel);border:1px solid var(--line)}
  .na .thumb.fav{padding:13px;object-fit:contain;background:var(--panel)}
  .na .nb{flex:1;min-width:0}
  .na .nb .nt{font-weight:700;font-size:13.5px;line-height:1.32;color:var(--txt);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
  .na .nb .nd{font-size:12px;color:var(--muted);margin-top:3px;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .na .nb .nm{font-size:11px;color:var(--muted);margin-top:5px;display:flex;gap:7px;align-items:center;flex-wrap:wrap}
  .na .nb .nm .src{font-weight:700;color:#ff5a1f}
  .na .nb .nm .ago{background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:1px 7px}
  /* Fil chronologique : séparateurs de période */
  .news-sep{display:flex;align-items:center;gap:10px;margin:14px 2px 9px}
  .news-sep:first-child{margin-top:2px}
  .news-sep::after{content:"";flex:1;height:1px;background:var(--line)}
  .news-sep span{font-size:11.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);white-space:nowrap}
  /* Carte article + bloc Résumé IA */
  .na-item{margin-bottom:9px}
  .na-item .na{margin-bottom:0}
  .nsum{margin-top:6px}
  .nsum-btn{appearance:none;border:1px solid var(--line);background:var(--panel);color:var(--txt);font-size:11.5px;font-weight:700;
    padding:5px 11px;border-radius:20px;cursor:pointer;transition:.12s;display:inline-flex;align-items:center;gap:5px}
  .nsum-btn:hover{border-color:#ff5a1f;color:#ff5a1f}
  .nsum-btn:disabled{opacity:.6;cursor:default}
  .nsum-btn.open{background:rgba(255,90,31,.12);border-color:#ff5a1f;color:#ff5a1f}
  .nsum-body{margin-top:7px;background:var(--panel);border:1px solid var(--line);border-left:3px solid #ff5a1f;border-radius:10px;padding:9px 11px}
  .nsum-txt{font-size:12.5px;line-height:1.5;color:var(--txt)}
  .nsum-approx{font-size:11px;color:var(--muted);margin-bottom:5px}
  .nsum-err{font-size:12px;color:var(--muted)}
  .nsum-load{display:flex;gap:5px;padding:2px 0}
  .nsum-load span{width:6px;height:6px;border-radius:50%;background:#ff5a1f;opacity:.4;animation:nsdot 1s infinite}
  .nsum-load span:nth-child(2){animation-delay:.15s}
  .nsum-load span:nth-child(3){animation-delay:.3s}
  @keyframes nsdot{0%,100%{opacity:.3;transform:translateY(0)}50%{opacity:1;transform:translateY(-3px)}}
  .empty{color:var(--muted);font-size:13.5px;text-align:center;padding:26px 10px;line-height:1.55}
  /* Chat assistant IA */
  .chat{display:flex;flex-direction:column;gap:9px;padding:2px 0 8px}
  .chat .msg{max-width:88%;padding:10px 13px;border-radius:15px;font-size:14px;line-height:1.55;word-wrap:break-word}
  .chat .bot{background:var(--panel2);border:1px solid var(--line);border-bottom-left-radius:5px;align-self:flex-start}
  .chat .me{background:linear-gradient(180deg,var(--fire2),var(--fire));color:#fff;border-bottom-right-radius:5px;align-self:flex-end}
  .chat .bot b{color:var(--fire)}
  .chat .typing{color:var(--muted);font-style:italic;font-size:13px}
  .chat-sugg{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 9px}
  .chat-sugg button{background:var(--panel);border:1px solid var(--line);color:var(--accent);border-radius:20px;padding:6px 11px;font-size:12px;font-weight:600;cursor:pointer}
  /* Barre composer (dictée + champ + envoi) : collée en bas, alignée verticalement, séparée du fil par un filet. */
  .chat-input{display:flex;gap:8px;align-items:center;flex:0 0 auto;background:var(--panel);border-top:1px solid var(--line);padding:10px 0}
  .chat-input input{flex:1;min-width:0;background:var(--panel2);border:1px solid var(--line);border-radius:22px;padding:11px 15px;font-size:14px;color:var(--txt);outline:none;transition:border-color .15s}
  .chat-input input:focus{border-color:var(--fire2);box-shadow:0 0 0 3px rgba(224,74,29,.12)}
  .chat-input button{flex:0 0 auto;width:44px;height:44px;display:inline-flex;align-items:center;justify-content:center;line-height:1;border:0;border-radius:50%;background:var(--fire);color:#fff;font-size:16px;cursor:pointer;transition:filter .15s,transform .1s}
  .chat-input button:hover{filter:brightness(1.06)}
  .chat-input button:active{transform:scale(.94)}
  #chatSend{box-shadow:0 3px 9px rgba(224,74,29,.35)}
  #chatMic{background:var(--panel2)!important;border:1px solid var(--line)!important;color:var(--txt)!important}
  #chatMic.rec{background:var(--danger)!important;color:#fff!important;animation:hspin 1s linear reverse infinite}
  .chat-opts{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:2px 0 8px;font-size:12px}
  .chat-opts .lbl{color:var(--muted);font-weight:600}
  .langseg{display:flex;background:var(--panel);border:1px solid var(--line);border-radius:10px;overflow:hidden}
  .langseg button{background:transparent;border:0;padding:6px 9px;font-size:11.5px;font-weight:700;color:var(--muted);cursor:pointer}
  .langseg button.on{background:var(--fire);color:#fff}
  .areadbtn{background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:6px 11px;font-size:11.5px;font-weight:700;color:var(--muted);cursor:pointer}
  .areadbtn.on{background:var(--accent);color:#fff;border-color:var(--accent)}
  .chat .bot .rd{background:none;border:0;color:var(--accent);cursor:pointer;font-size:13px;padding:0;margin-left:6px}
  /* Rendu riche des réponses de l'assistant (liens, listes, titres, bouton d'appel d'urgence) */
  .chat .bot a{color:var(--accent);text-decoration:underline;text-underline-offset:2px;word-break:break-word}
  .chat .bot .tel{display:inline-flex;align-items:center;gap:3px;background:var(--danger);color:#fff;text-decoration:none;padding:1px 9px;border-radius:20px;font-weight:800;font-size:12px;letter-spacing:.02em}
  .chat .bot .md-ul{margin:5px 0;padding-left:4px;list-style:none}
  .chat .bot .md-ul li{position:relative;padding-left:17px;margin:4px 0}
  .chat .bot .md-ul li::before{content:"🔸";position:absolute;left:0;top:1px;font-size:9px}
  .chat .bot .md-h{font-weight:800;margin:8px 0 3px;color:var(--fire);font-size:13.5px;letter-spacing:-.01em}
  .chat .bot .md-p{margin:3px 0}
  .chat .bot .md-sp{height:7px}
  .chat .bot code{background:var(--panel);border:1px solid var(--line);border-radius:5px;padding:0 5px;font-size:12.5px;font-family:ui-monospace,monospace}
  .chat-input button:disabled{opacity:.5}
  .legend{display:grid;grid-template-columns:auto 1fr;gap:8px 11px;align-items:center;font-size:12.5px}
  .legend{align-items:start}
  .legend .sw{width:28px;height:18px;border-radius:4px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;margin-top:1px}
  .legend .lbl{color:var(--muted)}
  .legend .lbl b{color:var(--txt)}
  .disclaimer{font-size:11.5px;color:var(--muted);line-height:1.5;margin-top:2px}
  /* Bannière d'alerte de proximité (foyer proche de la position mémorisée) */
  .proxbar{position:absolute;left:12px;right:12px;bottom:calc(var(--peek) + 2px + env(safe-area-inset-bottom));z-index:1160;
    background:rgba(224,138,0,.96);color:#fff;padding:10px 14px;border-radius:12px;font-size:13px;font-weight:600;box-shadow:var(--shadow-lg);text-align:center}
  .prox-x{position:absolute;top:5px;right:7px;background:rgba(255,255,255,.20);border:0;color:#fff;
    width:26px;height:26px;border-radius:50%;font-size:14px;line-height:1;cursor:pointer;font-weight:700}
  .prox-x:hover{background:rgba(255,255,255,.34)}
  .proxbar{position:absolute;padding-right:36px}
  .proxbar.urgent{background:rgba(225,29,29,.97);animation:proxpulse 1.6s infinite}
  @keyframes proxpulse{0%,100%{box-shadow:0 0 0 0 rgba(225,29,29,.45)}60%{box-shadow:0 0 0 9px rgba(225,29,29,0)}}
  @media (min-width:1100px){.proxbar{left:12px;right:auto;max-width:360px;bottom:24px}}
  /* Toast « nouveau point chaud » : boutons pill modernes + croix ronde (fini le bouton système « Windows 98 »). */
  .proxbtn{border:0;border-radius:10px;background:rgba(255,255,255,.22);color:#fff;font-weight:700;font-size:12.5px;
    padding:7px 13px;cursor:pointer;transition:background .15s,transform .1s,box-shadow .15s;-webkit-tap-highlight-color:transparent}
  .proxbtn:hover{background:rgba(255,255,255,.34)}
  .proxbtn:active{transform:scale(.94)}
  #modeInvite{display:flex;flex-wrap:wrap;align-items:center;gap:9px;text-align:left;box-shadow:0 10px 30px rgba(20,30,50,.28)}
  #modeInvite .pi-txt{flex:1 1 150px;min-width:0;line-height:1.35}
  #modeInvite #miGo{background:var(--panel);color:#c2410c;font-weight:800;box-shadow:0 2px 7px rgba(0,0,0,.14)}
  #modeInvite #miGo:hover{background:var(--panel);filter:brightness(.97)}
  #modeInvite #miX{width:30px;height:30px;padding:0;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:13px;background:rgba(255,255,255,.16);flex:0 0 auto;margin-left:auto}
  #modeInvite #miX:hover{background:rgba(255,255,255,.32)}
  /* Halo pulsant sur LE nouveau point chaud (au clic « Voir en direct ») */
  .hotspot-hl .hs-ring{position:absolute;left:-18px;top:-18px;width:36px;height:36px;border-radius:50%;border:3px solid #ff5a1f;animation:hspulse 1.5s ease-out infinite}
  .hotspot-hl .hs-ring2{animation-delay:.75s}
  .hotspot-hl .hs-dot{position:absolute;left:-6px;top:-6px;width:12px;height:12px;border-radius:50%;background:#ff5a1f;box-shadow:0 0 10px 2px rgba(255,90,31,.9)}
  @keyframes hspulse{0%{transform:scale(.4);opacity:1}100%{transform:scale(2);opacity:0}}
  .hs-tip{background:#ff5a1f!important;color:#fff!important;border:0!important;font-weight:700!important;font-size:11.5px!important;box-shadow:0 3px 10px rgba(0,0,0,.28)!important}
  .hs-tip::before{border-top-color:#ff5a1f!important}
  .hs-tip-x{display:inline-block;margin-left:6px;opacity:.85;font-weight:800}
  /* Badge horodatage du radar pluie (animé) · centré en haut de la carte, non cliquable. */
  /* Contrôle radar pluie · barre en BAS de la carte (ne chevauche pas les périodes en haut). */
  .rain-ctl{position:absolute;left:50%;transform:translateX(-50%);bottom:calc(var(--peek) + 8px + env(safe-area-inset-bottom));
    z-index:1150;display:none;align-items:center;gap:9px;background:rgba(15,20,30,.97);color:#eaf1ff;
    padding:8px 13px;border-radius:26px;box-shadow:0 6px 22px rgba(0,0,0,.42);white-space:nowrap;
    /* opaque (ex-backdrop-filter retiré : recompositing du flou au-dessus de la carte animée = flash au clic/pan) */
    border:1px solid rgba(255,255,255,.12);
    width:max-content;max-width:92vw}
  .rain-ctl.show{display:flex}
  /* ── Lecteur pluie : bouton et curseur redessines (2026-08-30) ────────────────────────────
     Le bouton affichait les caracteres « ▶ » et « ⏸ », dont le rendu depend de la police du
     telephone (taille, alignement, parfois emoji couleur). On passe a deux SVG, l'un ou l'autre
     selon l'etat, pour un rendu identique partout. */
  .rain-btn{display:inline-flex;align-items:center;justify-content:center;line-height:0;padding:0}
  .rain-btn .ic-pause{display:none}
  .rain-btn.en-lecture .ic-play{display:none}
  .rain-btn.en-lecture .ic-pause{display:inline-block}
  .rain-btn:active{transform:scale(.93)}
  .rain-btn{transition:transform .1s,filter .15s}
  .rain-btn:hover{filter:brightness(1.08)}

  /* Curseur en DEUX PARTIES : bleu jusqu'au dernier releve radar reel, rouge au-dela, avec un
     trait vertical a la frontiere. Au-dela de ce repere, ce n'est plus une observation mais une
     projection : l'interface doit le dire sans qu'on ait a lire une legende. */
  .rain-slider{--rain-coupe:100%}
  .rain-slider.a-projection{
    background:linear-gradient(90deg,
      #3b82f6 0, #3b82f6 var(--rain-coupe),
      #ffffff calc(var(--rain-coupe) + 0px), #ffffff calc(var(--rain-coupe) + 2px),
      #e0453a calc(var(--rain-coupe) + 2px), #e0453a 100%) !important;
  }
  /* Pastille de temps teintee pendant la projection, pour que l'etat soit lisible meme curseur
     hors du champ de vision. */
  .rain-ctl.proj .rain-lbl{color:#ff9a86;font-weight:700}
  /* DEBORDEMENT DU LIBELLE DE PROJECTION (corrige 2026-08-30) ─────────────────────────────────
     La pastille est en `nowrap` et le libelle etait en `flex:0 0 auto` : le texte de projection,
     bien plus long que l'heure habituelle, sortait de la pastille et se faisait couper en plein
     mot sur telephone. On autorise desormais le libelle a retrecir, et le detail du deplacement
     ne s'affiche qu'au-dela de 760 px, largeur a partir de laquelle il tient en entier. En
     dessous, il reste « Projection +50 min · estimation » : la mention qui compte, celle qui dit
     que ce n'est pas une observation, n'est JAMAIS celle qu'on sacrifie. */
  .rain-ctl.proj .rain-lbl{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}
  .rl-cle,.rl-plus{display:none}
  .rl-court{display:inline}
  @media (min-width:520px){ .rl-court{display:none} .rl-cle{display:inline} }
  @media (min-width:760px){ .rl-plus{display:inline} }
  /* Le curseur cede quelques pixels au libelle sur les ecrans etroits : mieux vaut une piste de
     lecture un peu plus courte qu'un mot coupe. */
  @media (max-width:520px){ .rain-ctl .rain-track{min-width:74px} }
  .rain-ctl.proj .rain-em{opacity:.55}
  /* FONDU ENTRE DEUX IMAGES RADAR. Sa durée est calée sur la cadence de lecture (RAIN_CADENCE,
     420 ms depuis le radar OPERA à 5 min) : l'image sortante s'efface pendant exactement le temps où
     l'entrante apparaît, donc sans temps mort ni palier. Un fondu plus court que la cadence redonnerait
     la saccade. */
  .rain-tile{transition:opacity .42s linear}
  .rain-tile-proj{transition:opacity .42s linear,transform .42s linear}
  /* Chargement en cours : le bouton pulse doucement pour dire « ça arrive », plutôt que de
     rester inerte pendant que les tuiles se téléchargent. */
  @keyframes rainAttente{0%,100%{opacity:1}50%{opacity:.45}}
  .rain-btn.en-attente{animation:rainAttente 1s ease-in-out infinite}
  /* CHEVAUCHEMENT « Signaler » / curseur de pluie (2026-08-30, signalé user). La barre de pluie
     est centrée et large (jusqu'à 92vw), le bouton « Signaler » est ancré à droite à la même
     hauteur : sur un écran de téléphone les deux se recouvrent. Tant que le curseur de pluie est
     ouvert, on masque « Signaler » — il réapparaît des qu'on referme la pluie, et le signalement
     reste accessible depuis la fiche satellite. Choix volontaire plutôt qu'un jeu de décalages
     fragiles, qui se seraient décalés à nouveau au moindre changement de hauteur de barre. */
  @media (max-width:768px){
    /* (2026-09-21) Le bouton Signaler n'est plus masqué par la jauge pluie : il remonte au-dessus (voir bloc « jauges »). */
  }
  .rain-btn{background:var(--fire);color:#fff;border:0;width:30px;height:30px;border-radius:50%;
    font-size:12px;cursor:pointer;flex:0 0 auto;display:flex;align-items:center;justify-content:center;line-height:1}
  /* La piste est enveloppée (.rain-track) pour porter le repère « maintenant » : le curseur natif ne peut pas
     dessiner une barre hors de sa piste. La position du repère est un nombre 0..1 (--rain-now) appliqué sur la
     course réelle du pouce (16 px de large). */
  .rain-track{position:relative;flex:1 1 auto;min-width:100px;max-width:180px;display:flex;align-items:center;--rain-now:-1}
  .rain-slider{width:100%;min-width:0;accent-color:#5aa9ff;cursor:pointer;height:4px}
  .rain-now{position:absolute;top:50%;left:calc(8px + (100% - 16px) * var(--rain-now));width:3px;height:16px;margin:-8px 0 0 -1.5px;border-radius:2px;
    background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.55);pointer-events:none;display:none}
  .rain-track.a-maintenant .rain-now{display:block}
  .rain-em{flex:0 0 auto}
  .rain-lbl{font-size:11.5px;font-weight:700;flex:0 0 auto;min-width:104px;text-align:right}
  /* Heure + ATTRIBUTION du radar (EUMETNET OPERA, CC BY 4.0, 25/09/2026) sur deux lignes : la seconde, en petit,
     tient dans la hauteur du bouton de lecture, le lecteur ne grandit pas (la pile du bas est mesurée). Masquée
     en mode prévision (+2 h…+12 h), qui vient d'Open-Meteo et non du radar. */
  .rain-txt{display:flex;flex-direction:column;align-items:flex-end;flex:0 0 auto;line-height:1.2}
  .rain-src{font-size:8.5px;font-weight:600;color:#9fb0c8;text-decoration:none;white-space:nowrap;letter-spacing:.01em}
  .rain-src:hover,.rain-src:focus-visible{text-decoration:underline;color:#cfdbec}
  .rain-ctl.fc .rain-src{display:none}
  /* Téléphone : le nuage (décoratif) cède sa place à l'attribution, qui ne doit jamais être rognée ni
     déborder sur le curseur (mesuré à 390 px : 24 px manquaient). Il revient en mode prévision. */
  @media (max-width:520px){ .rain-ctl:not(.fc) .rain-em{display:none} }
  /* Mode prévision (horizons +2h→+12h) : pas de curseur/lecture, juste le libellé + l'échelle couleurs. */
  .rain-ctl.fc .rain-track,.rain-ctl.fc .rain-btn{display:none}
  .rain-fcleg{display:none;width:64px;height:9px;border-radius:5px;flex:0 0 auto;
    background:linear-gradient(90deg,#8ec9ff,#3b82f6,#22c55e,#eab308,#f97316,#ef4444)}
  .rain-ctl.fc .rain-fcleg{display:inline-block}
  .rain-ctl.fc .rain-lbl{min-width:auto}
  /* Lecteur de progression estimée · même famille visuelle que le lecteur pluie, en plus haut (3 lignes). */
  /* Posé AU-DESSUS du lecteur pluie (146 px) pour que les deux puissent cohabiter sans se recouvrir. */
  .prog-ctl-supprime{position:absolute;left:50%;transform:translateX(-50%);bottom:calc(206px + env(safe-area-inset-bottom));
    z-index:1150;display:none;flex-direction:column;gap:4px;background:rgba(15,20,30,.97);
    padding:7px 10px;border-radius:13px;border:1px solid rgba(255,255,255,.12);
    box-shadow:0 4px 18px rgba(0,0,0,.35);color:#eaf0f8;max-width:min(94vw,430px)}
  .prog-ctl.show{display:flex}
  .prog-row{display:flex;align-items:center;gap:9px}
  .prog-info{justify-content:space-between;font-size:11px}
  .prog-warn{color:#ffb27a;font-weight:700}
  .prog-vit{color:#b9c6d8;font-weight:700;white-space:nowrap}
  .prog-leg{gap:11px;font-size:11px;color:#a9b8cc;flex-wrap:wrap}
  .prog-leg span{display:inline-flex;align-items:center;gap:4px}
  .pl{width:16px;height:10px;flex:0 0 auto;display:block}   /* symboles SVG : voir la légende du lecteur */
  /* Mobile : place comptée. Le lecteur se resserre, la légende passe sur une ligne défilable plutôt que
     de pousser le bloc en hauteur et de recouvrir les commandes du bas. */
  @media (max-width:560px){
    .prog-ctl{bottom:calc(var(--peek) + 30px + env(safe-area-inset-bottom));max-width:96vw;padding:6px 8px;gap:3px}
    .prog-row{gap:7px}
    .prog-info{font-size:11px}
    .prog-vit{font-size:11px}
    .prog-leg{font-size:8.5px;gap:7px;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch}
    .prog-leg span{white-space:nowrap}
    .rain-lbl{min-width:78px;font-size:10.5px}
    .prog-ctl .rain-slider{min-width:70px}
  }
  /* Écran très bas (paysage sur téléphone) : on remonte encore pour ne pas manger la carte. */
  @media (max-height:460px){.prog-ctl{bottom:calc(96px + env(safe-area-inset-bottom))}}
  /* Lecteur replié : ne restent que la lecture et l'heure. */
  .prog-tgl{transform:rotate(90deg)}
  .prog-ctl.replie .prog-tgl{transform:rotate(0deg)}
  .prog-ctl.replie .prog-info,.prog-ctl.replie .prog-leg,.prog-ctl.replie .rain-slider{display:none}
  .prog-ctl.replie{padding:5px 8px;gap:0}
  /* Lecteur pluie replié : même geste que celui de la progression. */
  .rain-ctl.replie .rain-track,.rain-ctl.replie .rain-fcleg{display:none}
  .rain-ctl.replie{padding:5px 8px}
  .rain-ctl .prog-tgl{margin-left:2px}
  /* Tant que le lecteur est ouvert, la rose remonte AU-DESSUS de lui : mesuré, les deux se recouvraient
     de 13 px sur un écran de 390 px. */
  @media (max-width:560px){
    body.prog-active .vent-hud{bottom:calc(300px + env(safe-area-inset-bottom))}
    body.prog-active .prog-ctl.replie ~ #ventHud,
    body.prog-active:has(.prog-ctl.replie) .vent-hud{bottom:calc(260px + env(safe-area-inset-bottom))}
  }
  /* Bandeau « feu détecté à proximité » de la fiche de risque. Placé avant l'indice météo et nettement
     plus voyant : un feu qui brûle à côté prime sur une prévision de conditions. */
  .thermal-fire{background:rgba(225,29,29,.10);border:1px solid rgba(225,29,29,.32);border-radius:10px;
    padding:8px 10px;margin:8px 0 2px;font-size:12.5px;font-weight:700;color:#c62828;line-height:1.45}
  .thermal-fire span{display:block;font-weight:500;font-size:11px;color:var(--muted);margin-top:3px}
  .rain-pop{font-size:13px;line-height:1.55}
  .rain-pop-src{color:var(--muted);font-size:11px}
  /* Popup trafic : section précise + source vérifiable */
  .traffic-pop .evp-body{font-size:13px;line-height:1.5}
  .traffic-pop .tpop-sec{margin-top:5px;font-size:12px;color:var(--txt);background:var(--panel2);border-radius:8px;padding:5px 8px;line-height:1.4}
  .traffic-pop .tpop-warn{color:var(--muted);font-style:italic;background:none;padding:5px 0}
  .traffic-pop .tpop-src{margin-top:7px;font-size:11px;color:var(--muted)}
  .traffic-pop .tpop-src a{color:var(--fire2);font-weight:700;text-decoration:none}
  /* Repère discret « dernier passage satellite » sur la carte (bas-gauche) · se cache à l'ouverture du sheet. */
  /* bottom:200px = AU-DESSUS de la barre pluie (146px+~48px) → pas de chevauchement quand les deux sont affichés. */
  /* ── Rose des vents + échelle de force (bas gauche, au-dessus du badge satellite) ──
     Même logique d'ancrage et même règle d'effacement que `.sat-info` : sur mobile, quand le panneau est
     ouvert il occupe le bas de l'écran, donc tout ce qui flotte au-dessus de la carte doit s'effacer,
     sinon ça se superpose au contenu du panneau. */
  .vent-hud{position:absolute;left:12px;bottom:calc(252px + env(safe-area-inset-bottom));z-index:1140;
    display:none;align-items:center;gap:9px;padding:6px 10px 6px 7px;border-radius:13px;
    background:rgba(12,16,24,.60);backdrop-filter:blur(9px);-webkit-backdrop-filter:blur(9px);
    border:1px solid rgba(255,255,255,.11);box-shadow:0 4px 16px rgba(0,0,0,.28);color:#eaf0f8}
  .vent-hud.show{display:flex}
  .vh-rose{width:38px;height:38px;flex:0 0 auto}
  .vh-txt{display:flex;flex-direction:column;line-height:1.18;white-space:nowrap}
  .vh-txt b{font-size:13px;font-weight:800;letter-spacing:.01em}
  .vh-txt span{font-size:10.5px;color:#b9c6d8}
  .vh-ech{display:flex;flex-direction:column;gap:3px;margin-left:4px;padding-left:9px;
    border-left:1px solid rgba(255,255,255,.13)}
  /* Le dégradé REPREND EXACTEMENT la palette du calque (VENT_PALETTE dans app.js), bornée à 75 km/h.
     Si l'une des deux change, l'autre doit suivre · une échelle qui ment sur les couleurs de la carte est
     pire que pas d'échelle du tout. */
  .vh-bar{width:104px;height:8px;border-radius:4px;background:linear-gradient(90deg,
    rgb(46,58,138) 0%, rgb(30,110,190) 6.7%, rgb(22,158,172) 13.3%, rgb(58,178,92) 20%,
    rgb(148,198,60) 26.7%, rgb(232,192,48) 40%, rgb(240,140,38) 53.3%, rgb(224,70,46) 73.3%,
    rgb(178,40,92) 100%)}
  .vh-lbl{display:flex;justify-content:space-between;font-size:9px;color:#a9b8cc;letter-spacing:.02em}
  /* Bascule de la rose des vents. Cible tactile de 30 px : on la presse dehors, souvent d'une main. */
  .vh-tgl{flex:0 0 auto;width:30px;height:30px;margin-left:1px;padding:0;border:0;border-radius:9px;
    background:rgba(255,255,255,.07);color:#cdd9e8;font-size:17px;font-weight:800;line-height:1;
    cursor:pointer;display:flex;align-items:center;justify-content:center;
    transform:rotate(90deg);transition:transform .18s ease,background .18s ease}
  .vh-tgl:hover{background:rgba(255,255,255,.15)}
  .vent-hud.replie .vh-tgl{transform:rotate(0deg)}
  /* Replié = LA ROSE SEULE (la flèche porte déjà la direction). Vitesse et sens en toutes lettres
     n'apparaissent qu'au dépli : c'est ce qui rend le badge assez petit pour ne gêner personne. */
  .vent-hud.replie .vh-txt{display:none}
  .vent-hud.replie{padding:4px 4px 4px 5px;gap:3px}
  /* `!important` indispensable : l'échelle est pilotée par un style.display INLINE (posé au basculement du
     fond coloré), qui l'emporterait sur une simple règle de classe. */
  .vent-hud.replie .vh-ech{display:none!important}
  @media (prefers-reduced-motion:reduce){.vh-tgl{transition:none}}
  /* MOBILE · le badge doit rester une indication de coin d'écran, pas un bloc qui mange la carte.
     Sur un téléphone, la carte fait déjà moins de la moitié de l'écran quand le panneau est ouvert :
     tout pixel pris par un widget est un pixel de terrain en moins. Version compacte, échelle retirée
     (elle est descriptive, pas vitale ; la rose et la valeur suffisent à décider). */
  @media (max-width:1099px){
    .vent-hud{gap:7px;padding:4px 8px 4px 5px;border-radius:11px}
    .vh-rose{width:28px;height:28px}
    .vh-rose svg{width:28px;height:28px}
    .vh-txt b{font-size:11.5px}
    .vh-txt span{font-size:9.5px}
  .vh-tgl{width:26px;height:26px;font-size:15px;border-radius:8px}
    .vh-ech{display:none}
  }
  @media (min-width:1100px){.vent-hud{bottom:64px;left:12px}}
  @media (max-width:1099px){#app:has(#sheet:not(.collapsed)) .vent-hud{display:none!important}}
  @media (max-width:400px){.vh-ech{display:none}} /* écran étroit : la rose prime, l'échelle passe à la trappe */
  .sat-info{position:absolute;left:12px;bottom:calc(var(--peek) + 8px + env(safe-area-inset-bottom));z-index:1140;
    display:none;background:rgba(15,20,30,.95);color:#c7d2e0;font-size:10.5px;font-weight:600;
    padding:5px 10px;border-radius:16px;box-shadow:0 3px 12px rgba(0,0,0,.35);
    /* opaque (ex-backdrop-filter retiré : même artefact de recompositing au-dessus de la carte animée) */
    border:1px solid rgba(255,255,255,.09);
    max-width:calc(100vw - 24px);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sat-info.show{display:block}
  .sat-info{cursor:pointer}
  @media (min-width:1100px){.sat-info{bottom:16px;left:12px}}
  @media (max-width:1099px){#app:has(#sheet:not(.collapsed)) .sat-info{display:none!important}}
  /* Carte d'info satellite (au clic sur le badge) */
  .sat-card{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2000;display:none;
    width:min(90vw,340px);max-height:82vh;overflow-y:auto;background:var(--panel);color:var(--txt);
    border:1px solid var(--line);border-radius:16px;padding:16px 18px 14px;box-shadow:0 14px 44px rgba(0,0,0,.5);
    font-size:12.5px;line-height:1.5}
  .sat-card.show{display:block}
  .sat-tech{margin-top:8px;border-top:1px solid var(--line);padding-top:7px}
  .sat-tech summary{cursor:pointer;font-weight:700;font-size:12px;color:var(--muted)}
  .sat-tech[open] summary{color:var(--txt);margin-bottom:5px}
  .sat-card-t{font-size:14.5px;font-weight:800;margin-bottom:8px;padding-right:20px}
  .sat-card p{margin:7px 0} .sat-card ul{margin:6px 0;padding-left:17px} .sat-card li{margin-bottom:5px}
  .sat-card-last{color:var(--muted);border-top:1px solid var(--line);padding-top:9px;margin-top:9px!important}
  .sat-card-x{position:absolute;top:7px;right:11px;background:none;border:0;color:var(--muted);font-size:22px;cursor:pointer;line-height:1}
  /* Signalement citoyen dans la carte infos : bouton mesuré (pas un CTA géant), file de curation. */
  .sat-report{margin-top:11px;padding-top:11px;border-top:1px solid var(--line)}
  .sat-report button{display:inline-flex;align-items:center;gap:6px;background:linear-gradient(180deg,var(--fire2),var(--fire));color:#fff;border:0;border-radius:11px;padding:9px 15px;font-size:13px;font-weight:800;cursor:pointer;box-shadow:var(--shadow)}
  .sat-report button:active{transform:translateY(1px)}
  .sat-report p{margin:7px 0 0;font-size:11px;line-height:1.4;color:var(--muted)}
  /* Bottom-sheet de signalement (remplace confirm() natif) : deux choix explicites, mobile-friendly. */
  .sig-sheet{position:fixed;inset:0;z-index:2600;display:none;align-items:flex-end;justify-content:center;background:rgba(0,0,0,.45)}
  .sig-sheet.show{display:flex}
  .sig-card{width:100%;max-width:460px;background:var(--panel2);border-radius:16px 16px 0 0;padding:16px 16px calc(16px + env(safe-area-inset-bottom,0px));box-shadow:0 -8px 30px rgba(0,0,0,.4);animation:sigUp .2s ease}
  @keyframes sigUp{from{transform:translateY(24px);opacity:.4}to{transform:none;opacity:1}}
  .sig-t{font-size:15px;font-weight:800;margin-bottom:6px}
  .sig-d{font-size:11.5px;line-height:1.45;color:var(--muted);margin:0 0 12px}
  /* Preuve sociale (signalements du mois) dans la feuille de signalement. */
  .sig-comm{font-size:12px;font-weight:700;color:#12703a;background:rgba(18,112,58,.1);border:1px solid rgba(18,112,58,.24);border-radius:10px;padding:8px 11px;margin:0 0 12px}
  :root[data-theme="dark"] .sig-comm{color:#86e0a6;background:rgba(134,224,166,.12);border-color:rgba(134,224,166,.3)}
  @media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .sig-comm{color:#86e0a6;background:rgba(134,224,166,.12);border-color:rgba(134,224,166,.3)}}
  .sig-opt{display:block;width:100%;text-align:left;background:linear-gradient(180deg,var(--fire2),var(--fire));color:#fff;border:0;border-radius:12px;padding:12px 14px;font-size:14px;font-weight:800;cursor:pointer;margin-bottom:9px}
  .sig-opt:active{transform:translateY(1px)}
  .sig-cancel{display:block;width:100%;background:transparent;color:var(--muted);border:1px solid var(--line);border-radius:12px;padding:10px;font-size:13px;font-weight:700;cursor:pointer}
  /* Contrôle temporel du calque « Points bruts » : play + slider + période (24h/48h/10j), overlay bas-centre. */
  .firms-ctl{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(150px + env(safe-area-inset-bottom,0px));z-index:1100;display:none;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:6px 9px;box-shadow:var(--shadow);max-width:min(94vw,440px)}
  .firms-ctl.show{display:flex}
  .firms-play{background:linear-gradient(180deg,var(--fire2),var(--fire));color:#fff;border:0;border-radius:9px;width:32px;height:32px;font-size:13px;cursor:pointer;flex:0 0 auto;line-height:1}
  .firms-slider{flex:1 1 80px;min-width:60px;accent-color:var(--fire2)}
  .firms-seg{display:flex;border:1px solid var(--line);border-radius:9px;overflow:hidden;flex:0 0 auto}
  .firms-seg button{background:transparent;border:0;color:var(--muted);font-size:11px;font-weight:800;padding:5px 7px;cursor:pointer;white-space:nowrap}
  .firms-seg button.on{background:var(--fire2);color:#fff}
  .firms-lbl{font-size:11px;font-weight:700;color:var(--txt);white-space:nowrap;flex:0 0 auto;min-width:56px;text-align:right}
  /* Mobile : le sheet du bas garde un peek de 132px → on place le contrôle AU-DESSUS (sinon chevauchement).
     Il se masque de toute façon quand le sheet est déplié (#app:has(#sheet:not(.collapsed)) #firmsCtl). */
  @media (max-width:1099px){.firms-ctl{bottom:calc(150px + env(safe-area-inset-bottom,0px));gap:6px;padding:5px 7px}.firms-lbl{min-width:46px;font-size:10px}}
  /* Modale légale (réutilise .sat-card) : un peu plus large + scroll interne si l'écran est court. */
  .legal-card{max-width:min(94vw,520px);max-height:82vh;overflow-y:auto;font-size:12.5px;line-height:1.5}
  .legal-card p{margin:9px 0}
  .legal-card a{color:var(--accent);font-weight:700;text-decoration:none} .legal-card a:hover{text-decoration:underline}
  .legal-card .legal-warn{background:rgba(226,52,13,.08);border:1px solid rgba(226,52,13,.28);border-radius:10px;padding:9px 11px}
  .legal-contact{margin-top:11px;text-align:center}
  .legal-mail{display:inline-block;background:var(--accent);color:#fff!important;padding:9px 15px;border-radius:11px;font-weight:800;text-decoration:none!important}
  /* Liens légal + contact du bloc « Réalisé avec » (onglet Situation). */
  .madeby-legal{display:flex;flex-wrap:wrap;gap:9px;justify-content:center;align-items:center;margin-top:13px;padding-top:12px;border-top:1px dashed var(--line)}
  .mb-lk{display:inline-flex;align-items:center;gap:7px;background:var(--panel2);border:1px solid var(--line);color:var(--txt);border-radius:11px;padding:9px 14px;font-size:12px;font-weight:700;cursor:pointer;text-decoration:none;line-height:1;transition:transform .14s,box-shadow .14s,border-color .14s;box-shadow:0 1px 2px rgba(20,30,50,.05)}
  .mb-lk:hover{border-color:var(--accent);transform:translateY(-1px);box-shadow:0 4px 11px rgba(20,30,50,.13)}
  .mb-lk:active{transform:translateY(0)}
  /* PIED DE L'ONGLET SITUATION · trois actions de même famille, mises au même niveau de soin que le reste.
     Les emoji du libellé sont remplacés par la même famille d'icônes vectorielles que les onglets, chacune
     dans sa pastille ronde : un pied de page reste le dernier endroit qu'on regarde, ce n'est pas une raison
     pour qu'il ait l'air bâclé. Cible de touche portée à 46 px de haut (recommandation mobile). */
  .madeby-legal .mb-lk{padding:11px 16px 11px 12px;font-size:12.5px;min-height:46px;border-radius:13px;gap:10px}
  .mb-lk .mb-ic{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:rgba(120,124,140,.18);position:relative}
  .mb-lk .mb-ic::after{content:"";position:absolute;inset:0;background-color:currentColor;opacity:.9;
    -webkit-mask:var(--mbi) center/14px 14px no-repeat;mask:var(--mbi) center/14px 14px no-repeat}
  .mb-contact .mb-ic{background:rgba(255,255,255,.26)}
  .mb-soutien{color:var(--fire,#e2340d);font-weight:800}
  .mb-soutien .mb-ic{background:rgba(226,52,13,.14)}
  @media (max-width:420px){ .madeby-legal{flex-direction:column;align-items:stretch}
    .madeby-legal .mb-lk{justify-content:flex-start;width:100%} }
  .mb-legal{--mbi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.1'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V8Z'/%3E%3Cpath%20d='M14%202v6h6M16%2013H8M16%2017H8M10%209H8'/%3E%3C/svg%3E")}
  .mb-contact{--mbi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.1'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Crect%20x='2'%20y='4'%20width='20'%20height='16'%20rx='2'/%3E%3Cpath%20d='m22%207-8.97%205.7a1.94%201.94%200%200%201-2.06%200L2%207'/%3E%3C/svg%3E")}
  .mb-soutien{--mbi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.1'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M10%202v2M14%202v2M16%208a1%201%200%200%201%201%201v8a4%204%200%200%201-4%204H7a4%204%200%200%201-4-4V9a1%201%200%200%201%201-1h12Z'/%3E%3Cpath%20d='M17%209h1a3%203%200%200%201%200%206h-1'/%3E%3Cpath%20d='M6%202v2'/%3E%3C/svg%3E")}
  /* Icônes des liens éditoriaux (sinon pastille pleine faute de masque --mbi) : bouclier=prévention, info=à propos, livre ouvert=méthodologie/sources */
  .mb-guides{--mbi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.1'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M12%202%204%205v6c0%205%208%209%208%209s8-4%208-9V5z'/%3E%3Cpath%20d='m9%2011%202%202%204-4'/%3E%3C/svg%3E")}
  .mb-about{--mbi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.1'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='12'%20r='10'/%3E%3Cpath%20d='M12%2016v-4'/%3E%3Cpath%20d='M12%208h.01'/%3E%3C/svg%3E")}
  .mb-method{--mbi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.1'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M2%205h7a3%203%200%200%201%203%203v11a2.5%202.5%200%200%200-2.5-2.5H2z'/%3E%3Cpath%20d='M22%205h-7a3%203%200%200%200-3%203v11a2.5%202.5%200%200%201%202.5-2.5H22z'/%3E%3C/svg%3E")}

  /* Badge Contact : fond bleu → texte + icône TOUJOURS blancs (un style de lien global écrasait la couleur → texte bleu illisible). */
  .mb-contact,.mb-contact:link,.mb-contact:visited,.mb-contact:hover,.mb-contact:active{background:linear-gradient(135deg,#3b82f6,#1d4ed8);border:0;color:#fff !important;box-shadow:0 3px 10px rgba(37,99,235,.35);text-decoration:none}
  .mb-contact svg,.mb-contact *{color:#fff !important;fill:currentColor}
  .mb-contact:hover{filter:brightness(1.07);transform:translateY(-1px);box-shadow:0 6px 16px rgba(37,99,235,.45)}
  /* Opt-in push risque météo (onglet Villes) */
  .risk-push-card{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:10px 12px;margin:0 0 10px}
  .risk-push-card .rp-row{display:flex;gap:9px;align-items:flex-start;font-size:12.5px;cursor:pointer;line-height:1.4}
  .risk-push-card .rp-row input{margin-top:2px;flex:0 0 auto;width:16px;height:16px;accent-color:var(--accent)}
  .risk-push-card .rp-sub{margin-top:7px;font-size:12px;color:var(--muted)}
  .risk-push-card .rp-note{margin-top:7px;font-size:11px;color:var(--muted);border-top:1px dashed var(--line);padding-top:7px}
  /* LECTEURS CENTRÉS SUR LA CARTE (29/09/2026, passe design) : sur ordinateur, la jauge satellite se centrait sur la
     FENÊTRE (panneau compris) et le lecteur pluie sur une carte supposée large de « 100 % − 400 px » : deux centres
     différents, lecteurs décalés l'un de l'autre, et le lecteur pluie mordait sur la carte partenaire. Les deux se
     centrent sur la carte réelle (fenêtre moins le panneau, --sheetW réglable), ou sur la fenêtre en plein écran. */
  @media (min-width:1100px){
    .rain-ctl{bottom:24px;left:calc((100% - var(--sheetW,400px)) / 2)}
    .firms-ctl{left:calc((100vw - var(--sheetW,400px)) / 2)}
    body.fs-map .rain-ctl{left:50%}
    body.fs-map .firms-ctl{left:50%}
  }
  /* Mobile : sheet ouvert → cacher la barre pluie (sinon elle chevauche le panneau du bas). */
  @media (max-width:1099px){#app:has(#sheet:not(.collapsed)) .rain-ctl{display:none!important}}
  .offlinks{display:flex;flex-wrap:wrap;gap:7px;margin-top:9px}
  .offlinks a{background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:7px 11px;font-size:12px;font-weight:700;color:var(--accent);text-decoration:none;box-shadow:var(--shadow)}
  .offlinks a:active{transform:scale(.97)}
  .foot{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--muted);padding-top:8px;gap:8px}
  button.act{background:var(--fire-on);color:#fff;border:0;border-radius:11px;padding:10px 14px;font-weight:800;font-size:13.5px;cursor:pointer;box-shadow:0 3px 10px rgba(234,74,18,.28)}
  button.act.install-cta{width:100%;background:var(--accent);box-shadow:0 3px 10px rgba(31,122,224,.28)}
  .install-block .ios-hint{font-size:13px;line-height:1.6;color:var(--txt)}
  button.ghost{background:var(--panel);color:var(--txt);border:1px solid var(--line);border-radius:11px;padding:9px 12px;font-size:12.5px;font-weight:600;cursor:pointer}
  .row{display:flex;gap:9px;align-items:center;flex-wrap:wrap}
  /* Card d'info foyer AU-DESSUS de la languette légende (z 1350) → sa croix est toujours cliquable, pas cachée derrière. */
  /* Fiche ancrée au-dessus du volet replié (--peek), au ras de la barre mini quand le volet est rangé (audit H-7 et H-14, 13/10/2026) :
     à 146 px fixes elle débordait de 134 px sur le volet replié. Ouvrir une fiche sur téléphone range le volet en barre mini. */
  #detail{position:absolute;left:12px;right:12px;bottom:calc(var(--peek) + 14px + env(safe-area-inset-bottom));z-index:1360;
    background:var(--panel,var(--panel));border:1px solid var(--line);border-radius:15px;padding:14px 15px;box-shadow:var(--shadow-lg);display:none;
    max-height:min(66vh,540px);overflow-y:auto;overscroll-behavior:contain}
  #detail.show{display:block}
  /* Bannière « Installer l'app » (PWA) · au-dessus de la barre du bas, masquée si une card détail est ouverte */
  /* BANNIÈRES FLOTTANTES · ancrage AU-DESSUS du volet, jamais par-dessus.
     Les trois (installation, opt-in notifications, annonce animaux) étaient collées au bas de l'écran,
     exactement là où le volet commence : elles le chevauchaient. Une variable unique porte le décalage et
     suit l'état du volet ; comme chaque règle lit la MÊME variable, la spécificité (#id contre .classe)
     ne peut plus créer de divergence entre les trois. Ne marche que parce que le volet a une hauteur
     FIXE : sans elle, `72dvh` ne correspondrait à rien de réel. */
  /* --peek + 95 px (13/10/2026, audit MO-9) : au-dessus de Signaler (--peek + 48 px) et de la bascule Satellite, que les
     bannières recouvraient (même hauteur que la carte partenaire, règle .sponsor-card). */
  body{--fv-float-bottom:calc(var(--peek) + 95px + env(safe-area-inset-bottom, 0px))}
  /* Sheet OUVERT = quasi plein écran depuis le relèvement 2026-08-19 : « au-dessus » n'existe plus
     (la bannière mordait sur le header). Elle se pose donc EN BAS de l'écran, par-dessus le pied du
     volet, comme une bannière classique — lisible, fermable, ne cache ni header ni onglets. */
  body:has(#sheet:not(.collapsed)){--fv-float-bottom:calc(14px + env(safe-area-inset-bottom, 0px))}
  .fv-float{position:fixed;left:10px;right:10px;bottom:calc(var(--fv-float-bottom) + var(--fv-ad-bottom));z-index:5200;
    transition:bottom .28s cubic-bezier(.22,1,.36,1)}
  @media (min-width:1100px){
    /* Le volet devient la colonne de droite (400px) : plus rien à enjamber en hauteur, on se décale en largeur. */
    body,body:has(#sheet:not(.collapsed)){--fv-float-bottom:calc(14px + env(safe-area-inset-bottom, 0px))}
    .fv-float{left:12px;right:calc(var(--sheetW,400px) + 12px);max-width:420px}
  }
  #installBanner,#renameBanner,#retroBanner,#galBanner,#donBanner,#featBanner{position:fixed;left:12px;right:12px;bottom:calc(var(--fv-float-bottom) + var(--fv-ad-bottom));z-index:1370;
    background:var(--panel);border:1px solid var(--line);border-radius:15px;padding:11px 12px;box-shadow:var(--shadow-lg);
    display:none;align-items:center;gap:11px;animation:ibUp .35s ease}
  #installBanner.show,#renameBanner.show,#retroBanner.show,#galBanner.show,#donBanner.show,#featBanner.show{display:flex}
  #installBanner .ib-ic,#renameBanner .ib-ic,#retroBanner .ib-ic,#galBanner .ib-ic,#donBanner .ib-ic,#featBanner .ib-ic{flex:0 0 auto;width:40px;height:40px;border-radius:11px;display:flex;align-items:center;justify-content:center;font-size:22px;border:0;color:#fff}
  /* Médaillon COLORÉ par bannière (fond dégradé plein, tracé blanc) : les icônes au trait sur fond
     transparent faisaient pâle · la surface colorée les ancre, comme les pastilles du tiroir. */
  /* Logo France Incendie (icône de l'application, 08/10/2026, fondateur : « le vrai logo avec la flamme ») : image
   telle quelle, ni teinte ni déformation, coins arrondis comme une icône d'écran d'accueil. */
#installBanner .ib-ic{background:transparent;box-shadow:0 2px 8px rgba(0,0,0,.28);overflow:hidden;padding:0}
#installBanner .ib-ic img{display:block;width:40px;height:40px;object-fit:contain;border-radius:11px}
  #renameBanner .ib-ic{background:linear-gradient(135deg,#b45309,#f59e0b);box-shadow:0 2px 8px rgba(245,158,11,.35)}
#retroBanner .ib-ic, #featBanner .ib-ic{background:linear-gradient(135deg,#c2410c,#f97316);box-shadow:0 2px 8px rgba(249,115,22,.35)}
  #galBanner .ib-ic{background:linear-gradient(135deg,#a16207,#e8b64a);box-shadow:0 2px 8px rgba(232,182,74,.35)}
  #donBanner .ib-ic{background:linear-gradient(135deg,#be123c,#fb7185);box-shadow:0 2px 8px rgba(251,113,133,.35)}
  #installBanner .ib-tx,#renameBanner .ib-tx,#retroBanner .ib-tx,#galBanner .ib-tx,#donBanner .ib-tx,#featBanner .ib-tx{flex:1;min-width:0}
/* Titre seulement (enfant direct) depuis le 13/10/2026 (audit MO-9) : `.ib-tx b` touchait aussi les <b> de la consigne
   d'installation (« Partager », « Sur l'écran d'accueil »), cassée en cinq à six lignes sur Safari et Firefox. */
#installBanner .ib-tx>b, #renameBanner .ib-tx>b, #retroBanner .ib-tx>b, #galBanner .ib-tx>b, #donBanner .ib-tx>b, #featBanner .ib-tx>b{display:block;font-size:13px;color:var(--txt);font-weight:800}
#installBanner .ib-tx>span, #renameBanner .ib-tx>span, #retroBanner .ib-tx>span, #galBanner .ib-tx>span, #donBanner .ib-tx>span, #featBanner .ib-tx>span{display:block;font-size:11px;color:var(--muted);line-height:1.35;margin-top:1px}
#installBanner .ib-go, #retroBanner .ib-go, #galBanner .ib-go, #donBanner .ib-go, #featBanner .ib-go{flex:0 0 auto;background:var(--accent);color:#fff;border:none;border-radius:10px;padding:9px 14px;font-size:12.5px;font-weight:800;cursor:pointer;white-space:nowrap}
#installBanner .ib-go:active, #retroBanner .ib-go:active, #galBanner .ib-go:active, #donBanner .ib-go:active, #featBanner .ib-go:active{opacity:.85}
  /* Le bouton de la bannière rétrospective est un LIEN : il faut donc neutraliser le
     soulignement et forcer l'alignement, que le style bouton ne portait pas. */
#retroBanner .ib-go, #featBanner .ib-go{display:inline-flex;align-items:center;text-decoration:none;
    background:linear-gradient(135deg,var(--fire),#f26b1f)}
#installBanner .ib-x, #renameBanner .ib-x, #retroBanner .ib-x, #galBanner .ib-x, #donBanner .ib-x, #featBanner .ib-x{flex:0 0 auto;background:none;border:none;color:var(--muted);font-size:20px;cursor:pointer;padding:2px 6px;line-height:1;align-self:flex-start}
  #installBanner.ios .ib-go{display:none}
  @keyframes ibUp{from{transform:translateY(18px);opacity:0}to{transform:translateY(0);opacity:1}}
  #app:has(#detail.show) #installBanner,#app:has(#detail.show) #renameBanner,#app:has(#detail.show) #retroBanner,#app:has(#detail.show) #galBanner,#app:has(#detail.show) #donBanner,#app:has(#detail.show) #featBanner{display:none!important}
  /* Bannière « animaux perdus » (demande fondateur 01/08) : mêmes règles que ses sœurs, ISOLÉES pour ne
     pas toucher aux autres. Médaillon + bouton ROSE (couleur de l'onglet Animaux). Une seule bannière à
     l'écran à la fois (système `occupe`), responsive : pleine largeur mobile, 360px bas-droite desktop. */
  #petsBanner{position:fixed;left:12px;right:12px;bottom:calc(var(--fv-float-bottom) + var(--fv-ad-bottom));z-index:1370;
    background:var(--panel);border:1px solid var(--line);border-radius:15px;padding:11px 12px;box-shadow:var(--shadow-lg);
    display:none;align-items:center;gap:11px;animation:ibUp .35s ease}
  #petsBanner.show{display:flex}
  #petsBanner .ib-ic{flex:0 0 auto;width:40px;height:40px;border-radius:11px;display:flex;align-items:center;justify-content:center;border:0;background:linear-gradient(135deg,#be185d,#ef7bb0);box-shadow:0 2px 8px rgba(239,123,176,.35)}
  #petsBanner .ib-tx{flex:1;min-width:0}
  #petsBanner .ib-tx b{display:block;font-size:13px;color:var(--txt);font-weight:800}
  #petsBanner .ib-tx span{display:block;font-size:11px;color:var(--muted);line-height:1.35;margin-top:1px}
  #petsBanner .ib-go{flex:0 0 auto;background:linear-gradient(135deg,#be185d,#ef7bb0);color:#fff;border:none;border-radius:10px;padding:9px 14px;font-size:12.5px;font-weight:800;cursor:pointer;white-space:nowrap}
  #petsBanner .ib-go:active{opacity:.85}
  #petsBanner .ib-x{flex:0 0 auto;background:none;border:none;color:var(--muted);font-size:20px;cursor:pointer;padding:2px 6px;line-height:1;align-self:flex-start}
  #app:has(#detail.show) #petsBanner{display:none!important}
  #detail .x{position:absolute;top:5px;right:6px;color:var(--muted);cursor:pointer;font-size:20px;line-height:1;padding:5px 9px;border-radius:8px}
  #detail .x:active{background:var(--panel2)}
  /* Quand la card d'info est ouverte, on ESCAMOTE la languette légende (elles se chevauchaient sur mobile). Réapparaît à la fermeture. */
  #app:has(#detail.show) .drawerbtn{opacity:0;pointer-events:none}
  #detail h4{margin:0 0 7px;font-size:14.5px}
  #detail .kv{font-size:13.5px;color:var(--muted);line-height:1.65}
  #detail .kv b{color:var(--txt)}
  /* Point de situation (rapport presse au clic sur un foyer) · carte moderne. */
  .d-ai{margin-top:12px}
  /* Passe en CARTE dès qu'il y a un contenu (chargement ou rapport), pas pour le simple bouton. */
  .d-ai:has(.d-ai-body),.d-ai:has(.d-ai-load){background:var(--panel2);border:1px solid var(--line);border-radius:14px;padding:13px 14px;box-shadow:0 2px 10px rgba(20,30,50,.06)}
  .d-ai-h{display:flex;align-items:center;gap:7px;font-weight:800;font-size:13px;color:var(--fire);margin:0 0 9px;padding-bottom:8px;border-bottom:1px solid var(--line)}
  .d-ai-load{font-size:12.5px;color:var(--muted);display:flex;align-items:center;gap:8px}
  .d-ai-load::before{content:"";width:14px;height:14px;border:2px solid var(--line);border-top-color:var(--fire);border-radius:50%;animation:dai-spin .8s linear infinite;flex:0 0 auto}
  @keyframes dai-spin{to{transform:rotate(360deg)}}
  .d-ai-body{font-size:13px;line-height:1.6;color:var(--txt)}
  .d-ai-body b{color:var(--fire2);font-weight:800}   /* intitulés **Localisation**/**État du feu**… en accent */
  .d-ai-body .md-p{margin:5px 0}
  .d-ai-body .md-h{font-weight:800;color:var(--fire);margin:9px 0 3px;font-size:13px}
  .d-ai-body .md-ul{margin:5px 0}
  .d-ai-src{margin-top:11px;padding-top:9px;border-top:1px dashed var(--line);font-size:11px;color:var(--muted);display:flex;flex-wrap:wrap;gap:6px;align-items:center}
  .d-ai-src a{color:var(--accent);background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:3px 9px;text-decoration:none;max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:border-color .15s}
  .d-ai-src a:hover{border-color:var(--accent)}
  .d-ai-dis{margin-top:9px;font-size:11px;color:var(--muted);font-style:italic;line-height:1.45}
  .d-ai-btn{width:100%;padding:11px 12px;border:1px solid var(--line);border-radius:12px;background:var(--panel2);
    color:var(--fire);font-size:12.5px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:7px;transition:background .15s,border-color .15s,transform .1s}
  .d-ai-btn:hover{background:rgba(234,74,18,.12);border-color:rgba(234,74,18,.35)}
  .d-ai-btn:active{transform:scale(.98)}
  /* Badges de carte à largeur VARIABLE (statut officiel des feux). Leaflet ne peut pas les
     centrer lui-même : sans iconSize connu, il pose le COIN HAUT-GAUCHE sur les coordonnées,
     ce qui décalait la pastille de la moitié de sa largeur · mesuré à 41 px, soit plusieurs
     centaines de mètres à l'échelle du Bassin. On centre donc le contenu sur le point. */
  .fs-badge>span{position:absolute;left:0;top:0;transform:translate(-50%,-50%)}
  /* Vue nationale : la pastille de STATUT reste toujours affichée (jamais masquée, elle porte
     l'info la plus sensible de l'appli) mais se resserre pour moins recouvrir les libellés voisins.
     !important nécessaire : la taille/le padding sont posés en inline dans le divIcon (drawFirestatus). */
  body.zoom-far-labels .fs-badge>span{font-size:9px!important;padding:2px 6px!important}

  /* ── Partenaires / soutiens locaux ── */
  .prt-card{display:flex;gap:12px;align-items:flex-start;background:var(--panel2);border:1px solid var(--line);border-radius:13px;padding:12px 13px;margin-bottom:10px}
  .prt-card.or{border-color:#e0b000;background:linear-gradient(180deg,var(--gold-tint),var(--panel2));box-shadow:0 3px 12px rgba(224,176,0,.15)}
  .prt-card .prt-logo{flex:0 0 auto;width:54px;height:54px;border-radius:11px;object-fit:contain;background:var(--panel);border:1px solid var(--line)}
  .prt-card .prt-logo.ph{display:flex;align-items:center;justify-content:center;font-size:22px;color:var(--muted);font-weight:800}
  .prt-card .prt-body{min-width:0;flex:1}
  .prt-card .prt-name{font-weight:800;font-size:13.5px;color:var(--txt);display:flex;align-items:center;gap:6px;flex-wrap:wrap}
  .prt-badge{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.03em;padding:2px 7px;border-radius:20px}
  .prt-badge.or{background:#e0b000;color:#fff} .prt-badge.argent{background:#9aa3af;color:#fff} .prt-badge.bronze{background:#c1794a;color:#fff}
  .prt-card .prt-city{font-size:11.5px;color:var(--muted);margin-top:1px}
  .prt-card .prt-blurb{font-size:12.5px;color:var(--txt);line-height:1.45;margin-top:5px}
  .prt-card .prt-links{display:flex;gap:8px;flex-wrap:wrap;margin-top:7px}
  .prt-card .prt-links a{font-size:11.5px;font-weight:700;color:var(--accent);text-decoration:none;background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:3px 9px}
  .prt-card .prt-links a:hover{border-color:var(--accent)}
  .prt-sec-h{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin:14px 0 8px}
  .prt-cta{background:var(--panel2);border:1px dashed var(--line);border-radius:14px;padding:14px;margin-top:6px;text-align:center}
  .prt-cta-h{font-weight:800;font-size:14px;color:var(--txt)}
  .prt-cta-p{font-size:12.5px;color:var(--muted);line-height:1.5;margin:6px 0 10px}
  .prt-tiers{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin-bottom:12px}
  .prt-tier{flex:1 1 92px;min-width:92px;background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:9px 8px}
  .prt-tier .t-name{font-size:11px;font-weight:800;color:var(--txt)} .prt-tier .t-price{font-size:16px;font-weight:900;color:var(--fire)} .prt-tier .t-sub{font-size:11px;color:var(--muted)}
  .prt-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;border:0;border-radius:11px;background:var(--fire);color:#fff;font-size:12.5px;font-weight:800;padding:11px 16px;cursor:pointer;text-decoration:none;transition:filter .15s,transform .1s;margin:3px}
  .prt-btn:hover{filter:brightness(1.06)} .prt-btn:active{transform:scale(.97)}
  .prt-btn-ghost{background:var(--panel);color:var(--fire);border:1px solid var(--line)}
  .prt-form{background:var(--panel2);border:1px solid var(--line);border-radius:14px;padding:14px;margin-top:12px}
  .prt-field{margin-bottom:10px;display:flex;flex-direction:column;gap:4px}
  .prt-field label{font-size:11.5px;font-weight:700;color:var(--muted)}
  .prt-field input,.prt-field textarea{background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:9px 11px;font-size:13px;color:var(--txt);outline:none;font-family:inherit;width:100%;box-sizing:border-box}
  .prt-field input:focus,.prt-field textarea:focus{border-color:var(--fire2)}
  .prt-row{display:flex;gap:9px}.prt-row .prt-field{flex:1}
  .prt-logo-prev img{max-height:46px;max-width:120px;margin-top:6px;border:1px solid var(--line);border-radius:8px;background:var(--panel)}
  /* Bouton fichier custom (le natif était moche) */
  .prt-file{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .prt-file input[type=file]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}
  .prt-file-btn{display:inline-flex;align-items:center;gap:7px;background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:9px 13px;font-size:12.5px;font-weight:700;color:var(--fire);cursor:pointer;transition:border-color .15s,background .15s;white-space:nowrap}
  .prt-file-btn:hover{border-color:var(--fire);background:rgba(234,74,18,.12)}
  .prt-file-name{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:150px}
  /* Don particulier · soutenir l'app */
  .mb-soutien{color:var(--fire,#e2340d);font-weight:700}
  .prt-donate{background:linear-gradient(180deg,var(--now-tint),var(--panel2));border:1px solid var(--line);border-radius:14px;padding:14px;margin-top:6px;text-align:center}
  .prt-donate-h{font-weight:800;font-size:14px;color:var(--txt)}
  .prt-donate-p{font-size:12.5px;color:var(--muted);line-height:1.5;margin:6px 0 11px}
  .prt-amounts{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin-bottom:10px}
  .prt-amt{border:1.5px solid var(--line);background:var(--panel);border-radius:11px;padding:9px 14px;font-size:14px;font-weight:800;color:var(--txt);cursor:pointer;transition:border-color .15s,background .15s}
  .prt-amt.sel{border-color:var(--fire);background:rgba(234,74,18,.12);color:var(--fire)}
  .prt-amt-custom{width:96px;text-align:center}
  .prt-donate .prt-btn{margin-top:2px}
  .prt-tierpick{display:flex;gap:8px;flex-wrap:wrap}
  .prt-tierpick label{flex:1 1 90px;border:1.5px solid var(--line);border-radius:10px;padding:8px;text-align:center;cursor:pointer;font-size:11.5px;font-weight:700;transition:border-color .15s,background .15s}
  .prt-tierpick label.sel{border-color:var(--fire);background:rgba(234,74,18,.12)}
  .prt-tierpick input{position:absolute;opacity:0;width:0;height:0}
  .prt-tierpick .tp-price{display:block;font-size:15px;font-weight:900;color:var(--fire)}
  .prt-legal{font-size:11px;color:var(--muted);line-height:1.5;margin:8px 0}
  .prt-actions{display:flex;gap:8px;margin-top:4px}
  .prt-msg{font-size:12px;margin-top:9px;line-height:1.45}
  /* Bouton d'activation générale des alertes : volontairement le seul élément « plein » de l'onglet, pour
     qu'un utilisateur qui a raté l'abonnement au premier lancement le repère sans le chercher. */
  /* ── Animaux perdus et trouvés ─────────────────────────────────────────────────────────────────────
     Volontairement sobre : une carte = une bête, une photo, un badge d'espèce, et surtout des actions qui
     PARTENT (appeler, écrire, y aller). Pas d'ornement : quand on cherche son chien, on veut composer le
     numéro en un doigt, pas lire une fiche. Tout est dimensionné pour le pouce sur mobile. */
  .pet-loc{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 0}
  .pet-loc button{flex:1 1 auto;min-width:110px;min-height:38px;background:var(--card,#151a23);
    border:1px solid var(--line);color:var(--muted);border-radius:10px;padding:8px 10px;font-size:12.5px;
    font-weight:700;cursor:pointer}
  .pet-loc button.on{background:#c81e1e;border-color:#c81e1e;color:#fff}
  .pet-loc-info.set{color:#4ade80;font-weight:700}
  /* Sélection d'un point : le réticule est fixe au centre de la carte, la carte glisse dessous. */
  #petPickUi{position:fixed;inset:0;z-index:4800;pointer-events:none}
  /* Pendant la sélection, le panneau est masqué : replié il dépassait encore et la barre se posait dessus.
     On veut la carte entière pour viser, rien d'autre à l'écran. */
  body.pet-picking #sheet{display:none}
  body.pet-picking #proxAlert{display:none!important}
  #petPickCross{position:absolute;left:50%;top:50%;width:46px;height:46px;margin:-46px 0 0 -23px;
    pointer-events:none;background:no-repeat center/contain
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 46 46'><path d='M23 44c0 0-15-14.5-15-25a15 15 0 1 1 30 0c0 10.5-15 25-15 25z' fill='%23c81e1e' stroke='white' stroke-width='2.5'/><circle cx='23' cy='19' r='5.5' fill='white'/></svg>");
    filter:drop-shadow(0 3px 6px rgba(0,0,0,.45))}
  #petPickBar{position:absolute;left:10px;right:10px;bottom:calc(env(safe-area-inset-bottom, 0px) + 14px);
    pointer-events:auto;background:var(--panel,#0f1520);color:var(--txt,#e8edf5);border:1px solid var(--line);
    border-radius:15px;box-shadow:0 8px 28px rgba(0,0,0,.32);padding:11px 12px;display:flex;
    align-items:center;gap:9px;max-width:520px;margin:auto}
  .ppb-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .ppb-txt b{font-size:13.5px}
  .ppb-txt span{font-size:11.5px;color:var(--muted);line-height:1.35}
  /* ⚠️ Ne PAS utiliser var(--card) ici : la barre suit --panel, et selon le thème les deux ne sont pas du
     même côté du contraste. On héritait alors d'un texte sombre sur un fond sombre, bouton illisible.
     `color:inherit` reprend la couleur de la barre, donc lisible en clair comme en sombre. */
  .ppb-b{flex:0 0 auto;min-height:38px;border-radius:10px;padding:9px 15px;font-size:12.5px;font-weight:800;
    cursor:pointer;background:transparent;border:1px solid var(--line);color:inherit}
  .ppb-b:hover{background:rgba(127,127,127,.12)}
  .ppb-b.ok{background:#15803d;border-color:#15803d;color:#fff}
  @media (max-width:400px){ #petPickBar{flex-wrap:wrap} .ppb-txt{flex:1 0 100%;margin-bottom:4px} .ppb-b{flex:1} }
  /* Zone d'intervention aérienne : volontairement DIFFÉRENTE d'un foyer satellite (cyan, pointillés, avion)
     pour qu'on ne puisse pas confondre une inférence avec une détection. */
  .aero-pin{background:none;border:none}
  .aero-pin div{width:38px;height:38px;border-radius:50%;background:#0b3d4a;border:2.5px solid #12b8d8;
    box-shadow:0 2px 10px rgba(18,184,216,.45);display:flex;align-items:center;justify-content:center;
    font-size:17px;cursor:pointer;position:relative;animation:aeropulse 2s infinite}
  @keyframes aeropulse{0%,100%{box-shadow:0 0 0 0 rgba(18,184,216,.5)}60%{box-shadow:0 0 0 12px rgba(18,184,216,0)}}
  /* Variante « en mission » (violet, famille des moyens non bombardiers) : orbite d'observation /
     coordination, guet. Même onde, autre couleur → ne se confond pas avec l'intervention (cyan). */
  .aero-pin-mission div{background:#241f4a;border-color:#8a7fd4;box-shadow:0 2px 10px rgba(138,127,212,.45);animation:aeropulse-mission 2s infinite}
  .aero-pin-mission .n{background:#8a7fd4;color:#14102e}
  .aero-pin-exo div{background:#241f4a;border-color:#8a7fd4;box-shadow:0 2px 10px rgba(138,127,212,.45);animation:none}
  .aero-pin-exo .n{background:#8a7fd4;color:#14102e}
  .exo-pin{background:none;border:none}
  .exo-pin div{width:26px;height:26px;border-radius:50%;background:#241f4a;border:2px solid #8a7fd4;display:flex;align-items:center;justify-content:center;font-size:14px;box-shadow:0 2px 8px rgba(0,0,0,.35)}
  .aero-pin-foyer div,.aero-pin-passe div{display:flex;align-items:center;justify-content:center}
  .aero-pin-passe div svg,.aero-pin-foyer div svg{width:58%;height:58%}
  .aero-pin-passe div{border-style:dashed;animation-duration:3.2s;opacity:.92}
  /* Patrouille de surveillance probable (06/10/2026) : famille « guet » (violet), pointillés, sans onde : ce n'est pas un feu.
     Double classe : l'emporte sur `.aero-pin div` (couleur d'icône) et `.aero-pin .n` (pastille), déclarées plus bas, et
     les variantes claires ci-dessous l'emportent sur le disque blanc du thème clair (sans elles, le marqueur de patrouille
     ressemblait à une intervention ordinaire dans le thème par défaut). */
  .aero-pin.aero-pin-patrouille div{background:#241f4a;border-color:#8a7fd4;color:#ede9fe;box-shadow:0 2px 10px rgba(138,127,212,.35);animation:none;opacity:.85}
  .aero-pin.aero-pin-patrouille .n{background:#8a7fd4;color:#14102e}
  @keyframes aeropulse-mission{0%,100%{box-shadow:0 0 0 0 rgba(138,127,212,.5)}60%{box-shadow:0 0 0 12px rgba(138,127,212,0)}}
  .aero-pin .n{position:absolute;top:-5px;right:-5px;background:#12b8d8;color:#04222a;font-size:10px;
    font-weight:800;min-width:17px;height:17px;border-radius:9px;display:flex;align-items:center;
    justify-content:center;padding:0 3px}
  .aero-pop b{font-size:13.5px} .aero-pop p{font-size:12px;line-height:1.45;margin:5px 0}
  .aero-pin-live{text-align:center;pointer-events:none!important}
  .aero-pin-live .aero-live-orb{position:absolute;inset:0;width:42px;height:42px;box-sizing:border-box;background:transparent;pointer-events:none}
  .aero-live-label{position:absolute;left:21px;top:64px;transform:translate(-50%,-50%);display:inline-block;max-width:106px;padding:3px 7px;border-radius:6px;background:#082832;color:#d2f8ff;border:1px solid #12b8d8;font-size:10px;font-weight:800;line-height:14px;white-space:nowrap;box-shadow:0 2px 8px #0006;pointer-events:auto;cursor:pointer}
  .aero-pin-mission .aero-live-label{background:#241f4a;border-color:#8a7fd4;color:#ede9fe}
  @media(prefers-reduced-motion:reduce){.aero-pin div{animation:none!important}}
  /* Contraste des badges d'intervention aérienne (24/09/2026, signalé fondateur) : l'avion prenait la couleur du
     texte de la page, donc SOMBRE sur le disque bleu nuit en thème clair. Couleur d'icône explicite en sombre ;
     en thème clair, disque blanc, anneau cyan foncé, avion bleu canard, étiquette claire. */
  .aero-pin div{color:#e0fbff}
  .aero-pin-mission div{color:#ede9fe}
  :root[data-theme="light"] .aero-pin div{background:#fff;border-color:#0891b2;color:#0e7490;box-shadow:0 2px 10px rgba(8,145,178,.35)}
  :root[data-theme="light"] .aero-pin-mission div{background:#f5f3ff;border-color:#6d5fd0;color:#5b4bb7;box-shadow:0 2px 10px rgba(109,95,208,.35)}
  :root[data-theme="light"] .aero-pin.aero-pin-patrouille div{background:#f5f3ff;border-color:#6d5fd0;color:#5b4bb7;box-shadow:0 2px 10px rgba(109,95,208,.35)}
  :root[data-theme="light"] .aero-pin.aero-pin-patrouille .n{background:#6d5fd0;color:#fff}
  :root[data-theme="light"] .aero-live-label{background:#fff;color:#0e4f5c;border-color:#0891b2;box-shadow:0 2px 8px rgba(15,23,42,.18)}
  :root[data-theme="light"] .aero-pin-mission .aero-live-label{background:#f5f3ff;color:#3b2f7a;border-color:#6d5fd0}
  @media (prefers-color-scheme:light){
    :root:not([data-theme="dark"]) .aero-pin div{background:#fff;border-color:#0891b2;color:#0e7490;box-shadow:0 2px 10px rgba(8,145,178,.35)}
    :root:not([data-theme="dark"]) .aero-pin-mission div{background:#f5f3ff;border-color:#6d5fd0;color:#5b4bb7;box-shadow:0 2px 10px rgba(109,95,208,.35)}
    :root:not([data-theme="dark"]) .aero-pin.aero-pin-patrouille div{background:#f5f3ff;border-color:#6d5fd0;color:#5b4bb7;box-shadow:0 2px 10px rgba(109,95,208,.35)}
    :root:not([data-theme="dark"]) .aero-pin.aero-pin-patrouille .n{background:#6d5fd0;color:#fff}
    :root:not([data-theme="dark"]) .aero-live-label{background:#fff;color:#0e4f5c;border-color:#0891b2;box-shadow:0 2px 8px rgba(15,23,42,.18)}
    :root:not([data-theme="dark"]) .aero-pin-mission .aero-live-label{background:#f5f3ff;color:#3b2f7a;border-color:#6d5fd0}
  }
  .aero-pop ul{margin:4px 0 0 16px;padding:0;font-size:11.5px;line-height:1.5}
  .aero-pop .aero-warn{color:#fbbf24;font-weight:700;font-size:11.5px;margin-top:7px}
  /* Badge « moyens aériens engagés » superposé sur un foyer DÉJÀ DÉCLARÉ (distinct de
     .aero-pin qui signale un feu NON déclaré) : même code couleur cyan, discret. */
  .aero-foyer-badge{background:none;border:none}
  .aero-foyer-badge div{width:22px;height:22px;border-radius:50%;background:#0b3d4a;border:2px solid #12b8d8;
    box-shadow:0 1px 6px rgba(18,184,216,.5);display:flex;align-items:center;justify-content:center;
    color:#12b8d8;position:relative}
  .aero-foyer-badge .n{position:absolute;top:-4px;right:-4px;background:#12b8d8;color:#04222a;font-size:9px;
    font-weight:800;min-width:14px;height:14px;border-radius:7px;display:flex;align-items:center;
    justify-content:center;padding:0 2px}
  /* ── Animaux perdus et trouvés ─────────────────────────────────────────────────────────────────────
     ⚠️ NE JAMAIS utiliser var(--card) ici : cette variable N'EXISTE PAS dans le thème, donc le repli sombre
     codé en dur s'appliquait toujours, y compris en thème clair où --txt vaut #18202e. Résultat : noms et
     descriptions en texte sombre sur fond sombre, illisibles. On s'en tient aux tokens réels du thème
     (--panel, --panel2, --txt, --muted, --line), qui suivent le clair comme le sombre. */
  .pet-filters{display:flex;gap:6px;margin:10px 0 9px;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px}
  .pet-fchip{flex:0 0 auto;background:var(--panel2);border:1px solid var(--line);color:var(--muted);
    border-radius:20px;padding:6px 13px;font-size:12.5px;font-weight:700;cursor:pointer;white-space:nowrap}
  .pet-fchip.on{background:#c81e1e;border-color:#c81e1e;color:#fff}
  .pet-card{display:flex;gap:11px;background:var(--panel2);border:1px solid var(--line);color:var(--txt);
    border-radius:13px;padding:11px;margin-bottom:9px;overflow:hidden}
  /* Annonce ciblée depuis la carte : liseré et halo brefs, pour que l'œil la trouve sans la chercher. */
  .pet-card.cible{border-color:#c81e1e;box-shadow:0 0 0 3px rgba(200,30,30,.20);animation:petcible 2.4s ease-out}
  @keyframes petcible{0%{box-shadow:0 0 0 0 rgba(200,30,30,.45)}70%{box-shadow:0 0 0 10px rgba(200,30,30,0)}}
  .pet-ph.zoom{cursor:zoom-in}
  .pet-card.reunited{opacity:.75;border-color:rgba(21,128,61,.45)}
  .pet-ph{width:76px;height:76px;flex:0 0 auto;border-radius:10px;object-fit:cover;background:var(--line)}
  .pet-ph.noimg{display:flex;align-items:center;justify-content:center;font-size:32px}
  .pet-b{flex:1;min-width:0}   /* min-width:0 = indispensable, sinon le texte long élargit la carte */
  .pet-head{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
  .pet-name{font-weight:800;font-size:14.5px;color:var(--txt)}
  .pet-esp-b{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:800;color:#fff;
    padding:2px 8px;border-radius:20px;letter-spacing:.01em}
  .pet-esp-b.chien{background:#b45309} .pet-esp-b.chat{background:#7c3aed}
  .pet-esp-b.cheval{background:#0f766e} .pet-esp-b.volaille{background:#c2410c}
  .pet-esp-b.betail{background:#4d7c0f} .pet-esp-b.nac{background:#be185d}
  .pet-esp-b.oiseau{background:#0369a1} .pet-esp-b.autre{background:#475569}
  .pet-st{display:inline-block;font-size:10.5px;font-weight:800;padding:2px 8px;border-radius:20px;color:#fff}
  .pet-st.lost{background:#c81e1e} .pet-st.found{background:#c2620a} .pet-st.reunited{background:#15803d}
  /* La ligne lieu + date déborde vite (adresses longues) : on la tronque proprement sur une ligne. */
  .pet-meta{font-size:11.5px;color:var(--muted);margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pet-desc{font-size:12.5px;line-height:1.45;margin-top:5px;color:var(--txt);overflow-wrap:anywhere}
  /* Les actions prenaient trois rangées, plus de place que l'information elle-même. Le contact reste
     pleine largeur (c'est LE geste utile), le reste passe en puces compactes sur une seule ligne. */
  .pet-acts{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
  .pet-act{display:inline-flex;align-items:center;gap:5px;min-height:34px;padding:6px 10px;border-radius:9px;
    font-size:12px;font-weight:700;text-decoration:none;border:1px solid var(--line);
    background:var(--panel);color:var(--txt);cursor:pointer;white-space:nowrap}
  .pet-act.call{background:#15803d;border-color:#15803d;color:#fff;flex:1 1 100%;justify-content:center;
    min-height:40px;font-size:13.5px}
  .pet-act.mail{background:#0369a1;border-color:#0369a1;color:#fff;flex:1 1 100%;justify-content:center;
    min-height:40px;font-size:13px;overflow:hidden;text-overflow:ellipsis}
  .pet-act.sec{font-size:11.5px;padding:5px 9px;min-height:30px;color:var(--muted)}
  .pet-act:active{transform:translateY(1px)}
  .pet-seg,.pet-esp,.pet-loc{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 0}
  .pet-seg button,.pet-esp button,.pet-loc button{flex:1 1 auto;min-width:100px;min-height:38px;
    background:var(--panel2);border:1px solid var(--line);color:var(--txt);border-radius:10px;
    padding:8px 10px;font-size:12.5px;font-weight:700;cursor:pointer}
  .pet-seg button.on,.pet-esp button.on,.pet-loc button.on{background:#c81e1e;border-color:#c81e1e;color:#fff}
  .pet-loc-info.set{color:#15803d;font-weight:700}
  .pet-consent{display:flex;align-items:flex-start;gap:8px;font-size:11.5px;line-height:1.45;
    color:var(--muted);margin:9px 0 0;cursor:pointer;background:rgba(200,30,30,.06);
    border:1px solid rgba(200,30,30,.22);border-radius:10px;padding:9px 10px}
  .pet-consent input{margin-top:2px;flex:0 0 auto;width:17px;height:17px;accent-color:#c81e1e}
  @media (max-width:400px){ .pet-ph{width:64px;height:64px} }
  .gen-notif-card{background:linear-gradient(135deg,rgba(225,29,29,.10),rgba(225,29,29,.04));
    border:1px solid rgba(225,29,29,.28);border-radius:12px;padding:11px;margin:0 0 9px}
  .gen-notif-btn{width:100%;border:0;border-radius:10px;background:#c81e1e;color:#fff;font-weight:800;
    font-size:14px;padding:11px 12px;cursor:pointer;box-shadow:0 2px 8px rgba(200,30,30,.30);
    transition:filter .15s ease,transform .08s ease}
  .gen-notif-btn:hover{filter:brightness(1.08)} .gen-notif-btn:active{transform:translateY(1px)}
  .gen-notif-btn.on{background:#15803d;box-shadow:0 2px 8px rgba(21,128,61,.28)}
  /* Bloqué / non supporté : gris neutre (ni rouge « à activer », ni vert « actif ») + curseur normal. */
  .gen-notif-btn.blocked{background:#4b5563;box-shadow:none}
  .gen-notif-btn.blocked:hover{filter:none}
  .gen-notif-btn[disabled]{opacity:.6;cursor:default}
  /* Le bleu clair codé en dur (#93c5fd) venait d'un fond sombre : sur la carte claire il devenait presque
     illisible. Pastille sobre pilotée par les jetons du thème, avec un chevron qui pivote à l'ouverture pour
     dire d'un coup d'œil si le panneau est déplié. */
  .gen-notif-more{margin-top:10px;background:var(--panel2);border:1px solid var(--line);color:var(--txt);
    font-size:12px;font-weight:700;cursor:pointer;padding:9px 13px;border-radius:99px;
    display:inline-flex;align-items:center;gap:7px;min-height:38px;transition:background .15s}
  .gen-notif-more::after{content:"";width:8px;height:8px;border-right:2px solid currentColor;
    border-bottom:2px solid currentColor;transform:rotate(45deg) translate(-1px,-1px);transition:transform .2s}
  .gen-notif-more[aria-expanded="true"]::after{transform:rotate(-135deg) translate(-2px,-2px)}
  .gen-notif-more:active{background:var(--line)}
  .gen-notif-prefs{margin-top:10px;border-top:1px solid var(--line);padding-top:4px}
  /* RÉGLAGES D'ALERTES · une ligne = pastille ronde + libellé + interrupteur.
     Avant : une pile de cases à cocher avec l'emoji collé dans le texte, sans hiérarchie ni surface de
     touche. L'emoji a été retiré des libellés (dans les 5 langues) et remplacé par la même famille d'icônes
     vectorielles que les onglets, pour que tout l'écran parle le même langage graphique.
     La case reste dans le DOM avec le MÊME id : tout le JavaScript existant continue de la lire, seul
     l'habillage change. Elle est masquée visuellement mais reste focalisable au clavier. */
  .np-row{display:flex;align-items:center;gap:11px;font-size:12.5px;line-height:1.35;padding:10px 2px;
    cursor:pointer;border-top:1px solid var(--line);min-height:44px}
  .np-row:first-of-type{border-top:0}
  .np-ic{flex:0 0 auto;width:30px;height:30px;border-radius:50%;background:rgba(120,124,140,.20);position:relative}
  .np-ic::after{content:"";position:absolute;inset:0;background-color:var(--txt);opacity:.8;
    -webkit-mask:var(--npi) center/16px 16px no-repeat;mask:var(--npi) center/16px 16px no-repeat}
  .np-tx{flex:1 1 auto;min-width:0}
  /* Case native masquée mais toujours présente et focalisable (accessibilité + JS inchangé). */
  .np-row input[type=checkbox]{position:absolute;opacity:0;width:1px;height:1px;margin:0;pointer-events:none}
  .np-sw{flex:0 0 auto;width:40px;height:23px;border-radius:99px;background:rgba(120,124,140,.34);
    position:relative;transition:background .18s}
  .np-sw::after{content:"";position:absolute;top:2.5px;left:2.5px;width:18px;height:18px;border-radius:50%;
    background:var(--panel);box-shadow:0 1px 3px rgba(0,0,0,.28);transition:transform .18s}
  .np-row input:checked~.np-sw{background:var(--fire,#e2340d)}
  .np-row input:checked~.np-sw::after{transform:translateX(17px)}
  .np-row input:focus-visible~.np-sw{outline:2px solid var(--fire,#e2340d);outline-offset:2px}
  .np-sub .np-tx{color:var(--muted);font-size:12px}
  .np-note{font-size:11px;line-height:1.45;color:var(--muted);margin-top:10px;border-top:1px dashed var(--line);padding-top:9px}
  .np-fire{--npi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M8.5%2014.5A2.5%202.5%200%200%200%2011%2012c0-1.38-.5-2-1-3-1.07-2.14-.22-4.05%202-6%20.5%202.5%202%204.9%204%206.5%202%201.6%203%203.5%203%205.5a7%207%200%201%201-14%200c0-1.15.43-2.29%201-3a2.5%202.5%200%200%200%202.5%202.5Z'/%3E%3C/svg%3E")}
  .np-esc{--npi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m3%2017%206-6%204%204%208-8'/%3E%3Cpath%20d='M17%207h4v4'/%3E%3C/svg%3E")}
  .np-air{--npi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M17.7%207.7A2.5%202.5%200%201%201%2019.5%2012H2'/%3E%3Cpath%20d='M9.6%204.6A2%202%200%201%201%2011%208H2'/%3E%3Cpath%20d='M12.6%2019.4A2%202%200%201%200%2014%2016H2'/%3E%3C/svg%3E")}
  .np-status{--npi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M12%209v4M12%2017h.01'/%3E%3Cpath%20d='M10.3%203.9%201.8%2018a2%202%200%200%200%201.7%203h17a2%202%200%200%200%201.7-3L13.7%203.9a2%202%200%200%200-3.4%200Z'/%3E%3C/svg%3E")}
  .np-news{--npi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M4%2022h16a2%202%200%200%200%202-2V4a2%202%200%200%200-2-2H8a2%202%200%200%200-2%202v16a2%202%200%200%201-2%202Zm0%200a2%202%200%200%201-2-2v-9c0-1.1.9-2%202-2h2'/%3E%3Cpath%20d='M18%2014h-8M15%2018h-5M10%206h8v4h-8Z'/%3E%3C/svg%3E")}
  .np-risk{--npi:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14%204.5V14a4%204%200%201%201-4%200V4.5a2%202%200%201%201%204%200Z'/%3E%3Cpath%20d='M12%2016.5h.01'/%3E%3C/svg%3E")}
  .gen-notif-note{font-size:11.5px;line-height:1.45;color:var(--muted);margin-top:8px}
  .gen-notif-state{font-size:11.5px;font-weight:700;color:#4ade80;margin-top:7px}
  .prt-msg.err{color:var(--danger)} .prt-msg.ok{color:#16a34a} .prt-msg.warn{color:#fbbf24}
  /* Mur des donateurs particuliers (prénom + cœur, jamais de montant) */
  .prt-wall{margin-top:12px;background:var(--panel2);border:1px solid var(--line);border-radius:14px;padding:13px}
  .prt-wall-h{font-size:13px;font-weight:800;margin-bottom:9px}
  .prt-wall-list{display:flex;flex-wrap:wrap;gap:7px}
  .prt-donor{display:inline-flex;align-items:center;gap:5px;background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:4px 11px;font-size:12px;font-weight:600;color:var(--txt)}
  .prt-donor .h{color:#e11d48}
  /* ── Galerie citoyenne ── */
  .gal-zones{display:flex;flex-wrap:wrap;gap:7px;margin:11px 0 4px}
  .gal-zones:empty{display:none}
  /* Téléphone : une QUINZAINE de zones sur plusieurs lignes mangeaient un tiers de l'écran avant la
     première photo. Une seule ligne qui défile, la barre de défilement masquée pour rester propre. */
  @media (max-width:560px){
    .gal-zones{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin:9px 0 4px;padding-bottom:2px}
    .gal-zones::-webkit-scrollbar{display:none}
    .gal-zchip{flex:0 0 auto;font-size:11.5px;padding:4px 10px}
  }
  .gal-zchip{background:var(--panel2);border:1px solid var(--line);border-radius:20px;padding:4px 11px;font-size:12px;font-weight:700;cursor:pointer;transition:.12s;white-space:nowrap}
  .gal-zchip:hover{border-color:var(--fire)}
  .gal-zchip.on{background:var(--fire);color:#fff;border-color:var(--fire)}
  .gal-zchip .c{opacity:.7;font-weight:600;margin-left:3px}
  .gal-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;margin-top:10px}
  .gal-sep{grid-column:1/-1;display:flex;align-items:center;gap:10px;margin:8px 2px 2px;font-size:11.5px;font-weight:800;letter-spacing:.03em;text-transform:uppercase;color:var(--muted)}
  .gal-sep::after{content:"";flex:1;height:1px;background:var(--line)}
  .gal-cell.press .zn.press{background:linear-gradient(transparent,rgba(0,0,0,.78));font-size:9px}
  .gal-cell.press::after{content:"↗";position:absolute;top:5px;right:6px;color:#fff;font-size:12px;font-weight:800;text-shadow:0 1px 4px rgba(0,0,0,.8)}
  .gal-cell{position:relative;aspect-ratio:1;border-radius:12px;overflow:hidden;background:var(--panel2);border:1px solid var(--line);cursor:pointer}
  .gal-cell img,.gal-cell video{width:100%;height:100%;object-fit:cover;display:block}
  .gal-cell .play{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:26px;color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.7);pointer-events:none}
  .gal-cell .zn{position:absolute;left:0;right:0;bottom:0;padding:3px 6px;font-size:9.5px;font-weight:700;color:#fff;background:linear-gradient(transparent,rgba(0,0,0,.72));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* Aperçus en VIGNETTES et non en pleine taille : avec l'envoi multiple, empiler 10 aperçus de 190 px
     repoussait le bouton « Envoyer » à un demi-écran de scroll (signalé 2026-07-28). Grille compacte +
     hauteur totale bornée avec scroll interne → le bouton reste TOUJOURS visible sous le formulaire. */
  .gal-prev{margin-top:9px;display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:6px;
    max-height:168px;overflow-y:auto}
  .gal-prev:empty{display:none;margin-top:0}
  .gal-prev img,.gal-prev video{width:100%;height:72px;object-fit:cover;border-radius:8px;display:block;
    background:#0d1017;border:1px solid var(--line)}
  /* Retirer une sélection AVANT l'envoi (erreur de choix) : bouton ✕ en surimpression sur chaque
     vignette, jamais un aperçu figé sans retour possible. */
  .gal-prev-item{position:relative}
  .gal-prev-x{position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;border:0;
    background:rgba(20,20,26,.72);color:#fff;font-size:12px;font-weight:800;line-height:1;cursor:pointer;
    display:flex;align-items:center;justify-content:center;padding:0;box-shadow:0 1px 3px rgba(0,0,0,.5)}
  .gal-prev-x:hover{background:#e2340d}
  .gal-hint{font-size:11px;color:var(--muted);margin-top:6px;line-height:1.45}
  /* Barre de progression d'envoi : plafonds relevés (jusqu'à 1 Go vidéo) → un envoi peut durer
     plusieurs minutes, un simple texte statique donnait l'impression que l'appli était figée. */
  .gal-progress{margin-top:9px;height:7px;border-radius:4px;background:var(--panel2);
    border:1px solid var(--line);overflow:hidden}
  .gal-progress-bar{height:100%;width:0%;border-radius:4px;background:linear-gradient(90deg,var(--fire2),var(--fire));
    transition:width .2s linear}
  /* Phase « compression côté serveur » : pas de pourcentage connaissable (la requête a fini
     d'envoyer les octets, on attend juste la réponse) → barre animée indéterminée. */
  .gal-progress.indeterminate .gal-progress-bar{width:35%!important;animation:galProgIndet 1.1s ease-in-out infinite}
  @keyframes galProgIndet{0%{transform:translateX(-100%)}100%{transform:translateX(285%)}}
  .gal-select{width:100%;background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:9px 11px;font-size:13px;color:var(--txt)}
  /* Sélecteur de zone France entière (recherche live geo.api.gouv.fr) + repère carte manuel.
     Remplace le <select> à ~20 communes Gironde/Landes en dur : une contribution hors de cette
     zone forçait la position GPS, refusée si l'utilisateur la refusait ou si le GPS échouait. */
  .gal-zonebox{position:relative}
  .gal-zone-input{width:100%;background:var(--panel);border:1px solid var(--line);border-radius:9px;
    padding:9px 34px 9px 11px;font-size:13px;color:var(--txt);outline:none;font-family:inherit;box-sizing:border-box}
  .gal-zone-input:focus{border-color:var(--fire2)}
  .gal-zone-clear{position:absolute;right:6px;top:50%;transform:translateY(-50%);background:none;border:0;
    color:var(--muted);font-size:16px;cursor:pointer;padding:4px;line-height:1;display:none}
  .gal-zonebox.has-value .gal-zone-clear{display:block}
  .gal-zone-drop{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:40;background:var(--panel);
    border:1px solid var(--line);border-radius:11px;box-shadow:0 8px 26px rgba(5,8,16,.35);
    max-height:260px;overflow-y:auto;display:none}
  .gal-zonebox.open .gal-zone-drop{display:block}
  .gal-zone-drop .gzd-sec{padding:7px 12px 3px;font-size:11px;font-weight:800;text-transform:uppercase;
    letter-spacing:.05em;color:var(--muted)}
  .gal-zone-drop button{display:block;width:100%;text-align:left;background:none;border:0;padding:8px 12px;
    font-size:13px;color:var(--txt);cursor:pointer;font-family:inherit}
  .gal-zone-drop button:hover,.gal-zone-drop button.hi{background:var(--panel2)}
  .gal-zone-drop .gzd-empty{padding:10px 12px;font-size:12.5px;color:var(--muted)}
  /* « Autre / ma position » (14/10/2026) : toujours proposé en fin de liste, séparé des communes ; il demande la position
     et montre la commune trouvée avant l'envoi (encadré .gal-zone-pinned). */
  .gal-zone-drop button.gzd-autre{display:flex;align-items:center;gap:6px;border-top:1px solid var(--line);font-weight:700}
  .gal-zone-pin-btn{display:flex;align-items:center;gap:6px;width:100%;justify-content:center;margin-top:7px;
    background:var(--panel2);border:1px dashed var(--line);border-radius:9px;padding:8px 11px;font-size:12.5px;
    font-weight:700;color:var(--txt);cursor:pointer;font-family:inherit}
  .gal-zone-pin-btn:hover{border-color:var(--fire2)}
  .gal-zone-pinned{display:none;align-items:center;gap:8px;margin-top:7px;padding:8px 11px;border-radius:9px;
    background:color-mix(in srgb,var(--fire2) 12%,var(--panel2));font-size:12.5px;font-weight:700}
  .gal-zone-pinned.show{display:flex}
  .gal-zone-pinned button{background:none;border:0;color:var(--muted);font-size:15px;cursor:pointer;margin-left:auto;padding:2px 4px}
  /* Bandeau plein écran pendant le placement du repère : instruction claire, annulable. */
  #galPinBanner{position:fixed;left:12px;right:12px;top:calc(env(safe-area-inset-top) + 12px);z-index:2100;
    display:none;align-items:center;gap:10px;background:var(--panel);border:1px solid var(--fire2);
    border-radius:13px;padding:11px 14px;box-shadow:0 8px 26px rgba(5,8,16,.45);font-size:13px;font-weight:700}
  #galPinBanner.show{display:flex}
  #galPinBanner button{background:var(--fire2);color:#fff;border:0;border-radius:9px;padding:7px 12px;
    font-size:12.5px;font-weight:800;cursor:pointer;white-space:nowrap;flex:0 0 auto}
  @media (max-width:520px){.gal-zone-drop{max-height:44vh}}
  /* Zone « Autre » : la case GPS n'est plus optionnelle, on le signale visuellement au lieu de le découvrir au refus */
  .gal-geo-req{color:#fca5a5;font-weight:700}
  .gal-geo{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--muted);margin-top:8px;cursor:pointer}
  .gal-geo input{width:auto}
  /* Lightbox plein écran */
  .gal-lb{position:fixed;inset:0;z-index:6000;background:rgba(0,0,0,.92);display:none;align-items:center;justify-content:center;flex-direction:column;padding:16px}
  .gal-lb.on{display:flex}
  .gal-lb img,.gal-lb video{max-width:100%;max-height:78vh;border-radius:12px}
  /* Ouverture d'une photo sans clignotement : la vignette (déjà en cache, même ratio que l'original) tient le
     cadre dès le premier rendu, l'original se fond par-dessus une fois décodé. Voir galLightbox() dans app.js. */
  .gal-lb .lb-media{position:relative;display:inline-block;line-height:0;border-radius:12px;overflow:hidden;max-width:100%}
  /* C'est la VIGNETTE qui fixe le cadre, et elle doit donc occuper exactement la place que prendra l'original.
     D'où `height:78vh` (et non `max-height`) : sans ça elle tient ses 350 px natifs et le cadre saute au
     moment du remplacement · le défaut qu'on cherche justement à supprimer. Ratio identique des deux côtés
     (ffmpeg `scale=…:-2`), donc la boîte calculée est la même. Une photo plus petite que 78vh se retrouve
     agrandie, ce qui est le comportement attendu d'une visionneuse plein écran. */
  .gal-lb .lb-thumb{height:78vh;width:auto;max-width:100%;transform:scale(1.03);filter:blur(7px)} /* le scale masque les bords du flou */
  .gal-lb .lb-media.ready .lb-thumb{opacity:0;transition:opacity .3s ease}
  .gal-lb .lb-full{opacity:0;transition:opacity .3s ease}
  .gal-lb .lb-media:not(.solo) .lb-full{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain}
  .gal-lb .lb-media.ready .lb-full{opacity:1}
  .gal-lb .lb-wait{position:absolute;left:50%;top:50%;width:30px;height:30px;margin:-15px 0 0 -15px;border-radius:50%;border:3px solid rgba(255,255,255,.3);border-top-color:#fff;animation:lbspin .8s linear infinite}
  .gal-lb .lb-media.ready .lb-wait{display:none}
  @keyframes lbspin{to{transform:rotate(360deg)}}
  @media (prefers-reduced-motion:reduce){.gal-lb .lb-wait{animation:none}.gal-lb .lb-full,.gal-lb .lb-media.ready .lb-thumb{transition:none}}
  .gal-lb .cap{color:#fff;font-size:13.5px;margin-top:12px;text-align:center;max-width:640px;line-height:1.5}
  .gal-lb .cap .zn{display:block;color:#ff8a5c;font-weight:700;font-size:12px;margin-bottom:4px}
  /* Filigrane DISCRET (nom du site) sur nos médias — affichage seul (visionneuse + vignettes). */
  .gal-lb .lb-wm{position:absolute;right:8px;bottom:7px;z-index:2;color:rgba(255,255,255,.6);font-size:10.5px;font-weight:700;letter-spacing:.02em;text-shadow:0 1px 3px rgba(0,0,0,.85);pointer-events:none}
  .gal-cell .gal-wm{position:absolute;top:4px;left:6px;z-index:1;color:rgba(255,255,255,.5);font-size:7.5px;font-weight:700;text-shadow:0 1px 2px rgba(0,0,0,.9);pointer-events:none;letter-spacing:.01em}
  /* Rotation de la photo (par pas de 90°) dans la visionneuse. */
  .gal-lb .lb-media{transition:transform .22s ease}
  .gal-lb .lb-media.rot90{transform:rotate(90deg)}
  .gal-lb .lb-media.rot180{transform:rotate(180deg)}
  .gal-lb .lb-media.rot270{transform:rotate(270deg)}
  .gal-lb .lb-rotate{position:absolute;top:16px;right:70px;z-index:3;width:40px;height:40px;border-radius:50%;background:rgba(0,0,0,.55);border:1px solid rgba(255,255,255,.22);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent}
  .gal-lb .lb-rotate:hover{background:rgba(0,0,0,.78)}
  /* Flèches précédent / suivant. */
  .gal-lb .lb-nav{position:fixed;top:50%;transform:translateY(-50%);z-index:3;width:46px;height:46px;border-radius:50%;background:rgba(0,0,0,.5);border:1px solid rgba(255,255,255,.22);color:#fff;font-size:30px;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent;padding-bottom:3px}
  .gal-lb .lb-nav:hover{background:rgba(0,0,0,.78)}
  .gal-lb .lb-prev{left:12px}
  .gal-lb .lb-next{right:12px}
  @media (max-width:560px){ .gal-lb .lb-nav{width:40px;height:40px;font-size:26px} .gal-lb .lb-prev{left:6px} .gal-lb .lb-next{right:6px} .gal-lb .lb-rotate{right:64px} }
  .gal-lb .x{position:absolute;top:14px;right:16px;z-index:3;font-size:26px;color:#fff;cursor:pointer;background:rgba(0,0,0,.55);width:46px;height:46px;border-radius:50%;display:flex;align-items:center;justify-content:center;-webkit-tap-highlight-color:transparent}
  /* Réactions · barre de la visionneuse. Boutons hauts de 40 px : on les presse dehors, au téléphone,
     souvent d'une seule main. */
  .gal-lb .rx-bar{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap;justify-content:center}
  .gal-lb .rx-btn{display:inline-flex;align-items:center;gap:6px;min-height:40px;padding:8px 14px;border-radius:999px;border:1px solid rgba(255,255,255,.22);background:rgba(255,255,255,.08);color:#fff;font-weight:700;line-height:1;cursor:pointer}
  .gal-lb .rx-btn .e{font-size:18px}
  .gal-lb .rx-btn .n{font-size:13px;opacity:.9;min-width:6px}
  .gal-lb .rx-btn:hover{background:rgba(255,255,255,.16)}
  .gal-lb .rx-btn.on{background:#ff8a5c;border-color:#ff8a5c;color:#111}
  .gal-lb .rx-btn:active{transform:scale(.96)}
  /* Réactions dans les POPUPS (fil du feu, .evpop) ET la FICHE du feu (#dBody) : mêmes réactions que la
     galerie, theme-aware. La fiche n'héritait d'AUCUN style → boutons bruts + compteur sombre sur panneau
     sombre (invisible). Sélecteurs partagés pour un rendu identique et contrasté partout. */
  .evpop .rx-bar,#dBody .rx-bar{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
  .evpop .rx-btn,#dBody .rx-btn{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:999px;border:1px solid var(--line);background:var(--panel2);color:var(--txt);font-size:11px;font-weight:700;line-height:1;cursor:pointer}
  .evpop .rx-btn .e,#dBody .rx-btn .e{font-size:14px;display:inline-flex}
  .evpop .rx-btn .n,#dBody .rx-btn .n{font-size:11px;font-weight:800;opacity:.85;min-width:5px;color:inherit}   /* compteur (nombre de clics) — hérite de la couleur du bouton (lisible off ET on) */
  .evpop .rx-btn.on,#dBody .rx-btn.on{background:var(--fire2);border-color:var(--fire2);color:#fff}
  .evpop .rx-btn:active,#dBody .rx-btn:active{transform:scale(.96)}
  /* Réactions SOUS UNE PHOTO de la fiche d'un feu : la colonne fait ~150 px sur un téléphone de
     390 px. Aux mesures générales, la quatrième réaction passait à la ligne et chaque carte
     gagnait une rangée pour rien. On resserre ICI seulement, sans toucher aux autres barres.
     Les boutons gardent une zone tactile confortable (hauteur 26 px + marge de la carte). */
  #dBody .fs-photos-feu .rx-bar{gap:3px;margin-top:5px;flex-wrap:nowrap}
  #dBody .fs-photos-feu .rx-btn{padding:4px 6px;gap:3px;flex:0 1 auto;min-width:0}
  #dBody .fs-photos-feu .rx-btn .e{font-size:13px}
  @media (prefers-reduced-motion:reduce){.gal-lb .rx-btn:active{transform:none}}
  /* Badge de la grille : LECTURE SEULE. `pointer-events:none` est indispensable · le clic sur une vignette
     doit ouvrir la photo, jamais être intercepté. Placé en haut à GAUCHE : `.zn` occupe le bas et
     `.gal-cell.press::after` le coin haut droit. */
  .gal-cell .gal-rx{position:absolute;top:5px;left:5px;padding:2px 7px;border-radius:999px;background:rgba(0,0,0,.62);color:#fff;font-size:10px;font-weight:800;line-height:1.6;pointer-events:none}
  /* Pastille photos sur la carte */
  .gal-pin{background:none;border:none}
  /* La pastille photo gardait 34 px à TOUS les niveaux de zoom : dézoomé sur la région, une dizaine de
     pastilles se chevauchaient et masquaient les foyers, c'est-à-dire l'information vitale. Elle suit
     désormais l'échelle de la carte (variable --gal-scale posée au zoomend), comme un vrai marqueur
     cartographique : discrète de loin, pleinement lisible de près. */
  .gal-pin div{transform:scale(var(--gal-scale,1));transform-origin:50% 50%;transition:transform .18s ease;
    width:34px;height:34px;border-radius:50%;background:var(--panel);border:2px solid var(--fire);box-shadow:0 2px 8px rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center;font-size:16px;cursor:pointer}
  /* Photos : pictogramme vectoriel couleur du feu (currentColor) ; les pastilles d'animaux gardent leur emoji d'espèce. */
  .gal-pin div{color:var(--fire)}
  /* PASTILLE COMMUNE des points d'intérêt (app.js, _pastille, 29/09/2026) : disque de la couleur du calque, liseré
     blanc de 2 px, ombre douce, pictogramme vectoriel blanc. Points d'eau, entraide, pare-feux ; même dessin que les
     pastilles accueil / retour. */
  .fv-pastille{box-sizing:border-box;border-radius:50%;border:2px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.42);
    display:flex;align-items:center;justify-content:center;cursor:pointer}
  .fv-pastille svg{flex:0 0 auto;display:block}
  .gal-pin .b{position:absolute;top:-6px;right:-6px;background:var(--fire);color:#fff;font-size:10px;font-weight:800;min-width:17px;height:17px;border-radius:9px;display:flex;align-items:center;justify-content:center;padding:0 3px}
  /* Carte sponsor à l'ouverture (gatée sécurité, fermable) */
  /* Au-dessus de Signaler (--peek + 48 px, 36 px de haut) depuis le 13/10/2026 (audit H-7) : à 150 px, la carte couvrait les
     onglets du volet replié (un appui sur Situation ouvrait l'onglet Partenaires) et le champ de recherche du volet ouvert. */
  .sponsor-card{position:absolute;left:12px;right:12px;bottom:calc(var(--peek) + 95px + env(safe-area-inset-bottom));z-index:1150;background:var(--panel);
    border:1px solid var(--line);border-radius:14px;box-shadow:0 12px 34px rgba(20,30,50,.24);padding:12px 13px;display:flex;gap:11px;align-items:center}
  @media (min-width:1100px){.sponsor-card{left:12px;right:auto;max-width:340px;bottom:24px}}
  .sponsor-card .sp-logo{flex:0 0 auto;width:44px;height:44px;border-radius:10px;object-fit:contain;background:var(--panel);border:1px solid var(--line)}
  .sponsor-card .sp-logo.ph{display:flex;align-items:center;justify-content:center;font-size:20px}
  .sponsor-card .sp-body{min-width:0;flex:1}
  .sponsor-card .sp-tag{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
  .sponsor-card .sp-name{font-weight:800;font-size:13px;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sponsor-card .sp-blurb{font-size:11.5px;color:var(--muted);line-height:1.35;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
  .sponsor-card .sp-x{flex:0 0 auto;width:28px;height:28px;border-radius:50%;border:1px solid var(--line);background:var(--panel2);color:var(--muted);cursor:pointer;font-size:13px;display:inline-flex;align-items:center;justify-content:center;align-self:flex-start}
  .leaflet-popup-content-wrapper{background:var(--panel);color:var(--txt);border-radius:12px;box-shadow:var(--shadow)}
  .leaflet-container{background:#dfe5ee;font:inherit}
  .leaflet-control-zoom a{background:var(--panel)!important;color:var(--txt)!important;border-color:var(--line)!important}
  /* DEUX GROUPES, DESSIN DE LA CARTE DES INONDATIONS (14/10/2026, soir ; fondateur : « reprends le même design des boutons + et
     −, position et maison que sur la carte des inondations »). Relevé sur la carte des inondations (public/style.css et en
     ligne, 390 × 844 et 1280 × 800) : [+ / −] (zoom de Leaflet) puis [Ma position / Ma maison] (app.js, ControleAppareil),
     chacun en pilule : fond du panneau, filet de 1 px #7d8799 (#78818b en sombre), ombre du panneau, rayon 13 px pour le
     zoom et 10 px pour l'autre groupe, filet fin --line entre les deux boutons, icônes au trait de 2 px en 18 px, couleur du
     texte (blanches en sombre) ; 36 px sur téléphone et tablette (signes + et − en 20 px), 30 px sur ordinateur ; 10 px
     entre les groupes (16 px au toucher, voir plus bas) ; aucun effet au survol, léger enfoncement à l'appui, contour
     bleu de 2 px au clavier. Le réglage « Arrondis » ne les change pas (comme sur la carte des inondations par défaut). */
  .leaflet-bar.leaflet-control-zoom,.leaflet-bar.ctl-appareil{border:1px solid #7d8799!important;box-shadow:var(--shadow)!important;background:var(--panel);background-clip:border-box}
  :root[data-theme="dark"] :is(.leaflet-bar.leaflet-control-zoom,.leaflet-bar.ctl-appareil){border-color:#78818b!important}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) :is(.leaflet-bar.leaflet-control-zoom,.leaflet-bar.ctl-appareil){border-color:#78818b!important}}
  .leaflet-bar.leaflet-control-zoom,body[data-radius] .leaflet-bar.leaflet-control-zoom{border-radius:13px!important}
  .leaflet-bar.ctl-appareil,body[data-radius] .leaflet-bar.ctl-appareil{border-radius:10px!important}
  .leaflet-bar.leaflet-control-zoom a,body[data-radius] .leaflet-bar.leaflet-control-zoom a{border-radius:0!important}
  .leaflet-bar.leaflet-control-zoom a:first-child,body[data-radius] .leaflet-bar.leaflet-control-zoom a:first-child{border-radius:12px 12px 0 0!important}
  .leaflet-bar.leaflet-control-zoom a:last-child,body[data-radius] .leaflet-bar.leaflet-control-zoom a:last-child{border-radius:0 0 12px 12px!important}
  .leaflet-top .leaflet-control.ctl-appareil{margin-top:10px}
  .ctl-appareil button{position:relative;display:grid;place-items:center;width:26px;height:26px;padding:0;margin:0;border:0;border-bottom:1px solid var(--line);
    border-radius:0;background:var(--panel);color:var(--txt);cursor:pointer;font:inherit;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
  .leaflet-touch .ctl-appareil button{width:30px;height:30px}
  .ctl-appareil button:first-child{border-radius:9px 9px 0 0}
  .ctl-appareil button:last-child{border-bottom:0;border-radius:0 0 9px 9px}
  .ctl-appareil button:active{transform:scale(.94)}
  .ctl-appareil button:focus{outline:none}
  .ctl-appareil button:focus-visible,.leaflet-control-zoom a:focus-visible{outline:2px solid var(--accent);outline-offset:-3px;z-index:1}
  .ctl-appareil button svg{display:block;pointer-events:none}
  .leaflet-control-zoom a{-webkit-tap-highlight-color:transparent;touch-action:manipulation}
  @media (max-width:1099px){
    .leaflet-touch .leaflet-bar.leaflet-control-zoom a{width:36px;height:36px;line-height:36px;font-size:20px}
    .leaflet-bar.ctl-appareil button{width:36px;height:36px}
  }
  /* Au toucher, cibles de 44 × 44 px sans grossir le dessin : la zone d'appui (::after) déborde de 4 px de chaque côté et de
     8 px vers l'extérieur du groupe ; 16 px entre les deux groupes (10 sur la carte des inondations) pour que le − et Ma
     position aient chacun leurs 8 px, sans se chevaucher. */
  @media (any-pointer:coarse){
    .leaflet-top .leaflet-control.ctl-appareil{margin-top:16px}
    .leaflet-control-zoom a{position:relative}
    .leaflet-control-zoom a::after,.ctl-appareil button::after{content:"";position:absolute;left:-4px;right:-4px;top:0;bottom:0}
    .leaflet-control-zoom a:first-child::after,.ctl-appareil button:first-child::after{top:-8px}
    .leaflet-control-zoom a:last-child::after,.ctl-appareil button:last-child::after{bottom:-8px}
  }
  #btnPositionCarte[aria-busy="true"] svg{animation:ctlCherche 1s ease-in-out infinite}
  @keyframes ctlCherche{50%{opacity:.35}}
  @media (prefers-reduced-motion:reduce){#btnPositionCarte[aria-busy="true"] svg{animation:none;opacity:.55}}
  /* Réticule en mode « Ma maison » : épingle bleue à maison (couleur du repère), textes propres à la maison. */
  #homePickTitle,#homePickSub{display:none}
  #petPickUi.mode-maison #petPickTitle,#petPickUi.mode-maison #petPickWhere{display:none}
  #petPickUi.mode-maison #homePickTitle,#petPickUi.mode-maison #homePickSub{display:block}
  #petPickUi.mode-maison #petPickCross{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 46 46'><path d='M23 44c0 0-15-14.5-15-25a15 15 0 1 1 30 0c0 10.5-15 25-15 25z' fill='%232b6cff' stroke='white' stroke-width='2.5'/><path d='M16.5 19.6 23 14.4l6.5 5.2v6.6a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1z' fill='white'/></svg>")}
  /* Pendant la pose, la carte entière sert à viser : rien d'autre que la colonne de droite (Ma position aide à viser). */
  body.home-picking :is(.fv-float,#sponsorCard,#detail,#sigFab,#modeSeg,#satInfo,#fireWinMap,.mapctl,#drawerBtn,#ventHud,#toggleSeg,.attrib-carte){visibility:hidden;pointer-events:none}
  /* Le zoom passe sous le bandeau glass (sinon caché en haut à droite). 58 px (60 avant le 14/10/2026) : le haut du zoom
     s'aligne à 2 px sous le haut de la frise des horizons, comme sur la carte des inondations. */
  .leaflet-top.leaflet-right{top:calc(env(safe-area-inset-top) + 58px)}
  .wind-arrow{filter:drop-shadow(0 1px 2px rgba(0,0,0,.35))}
  /* Aéronefs de secours sur la carte */
  .ac-icon{text-align:center;transition:opacity .4s ease}
  .ac-lbl{font-size:9.5px;font-weight:800;color:#fff;background:rgba(20,26,38,.72);border-radius:5px;
    padding:0 4px;margin-top:1px;white-space:nowrap;display:inline-block;letter-spacing:.02em;line-height:1.5}
  body.zoom-far-labels .ac-lbl{font-size:7.5px;padding:0 3px}
  /* Pastille de phase sous l'indicatif (25/09/2026) : décollage vert pâle, approche / atterrissage bleu pâle,
     sol / roulage gris. Masquée en vue large, où elle surchargerait la carte. */
  .ac-phase-l{line-height:1}
  .ac-phase{font-size:8.5px;font-weight:800;color:#0f172a;background:#e2e8f0;border-radius:5px;padding:0 4px;margin-top:1px;
    white-space:nowrap;display:inline-block;letter-spacing:.01em;line-height:1.5;box-shadow:0 1px 2px rgba(0,0,0,.35)}
  .ac-phase-decollage{background:#bbf7d0}
  .ac-phase-approche,.ac-phase-atterrissage{background:#bfdbfe}
  body.zoom-far-labels .ac-phase-l{display:none}
  /* Symboles des aérodromes et héliports (25/09/2026) : SVG, liseré blanc et ombre, lisibles sur tous les fonds. */
  .aerod-ic{background:none;border:none;cursor:pointer}
  .aerod-ic svg{display:block;filter:drop-shadow(0 1px 1.5px rgba(0,0,0,.5))}
  .aerod-P,.aerod-E,.aerod-H{opacity:.92}
  /* Le flux de vent est décoratif : il ne doit jamais capter les clics (sinon il bloque l'UI et le tap carte). */
  /* ⚠️ CONTRASTE DU VENT · le vrai problème n'est PAS l'opacité des filets, c'est le FOND.
     Les filets sont blancs et très transparents (c'est ce qui leur donne l'aspect « air » plutôt que
     « goutte », cf. le bloc velocityLayer dans app.js). Sur la mer sombre ils ressortent ; sur le satellite
     clair (sable, champs, villes) ils se noient, parce qu'un blanc à 25 % posé sur un fond déjà lumineux ne
     crée presque aucun écart. Monter l'opacité les rendrait visibles MAIS ramènerait l'aspect goutte.
     `screen` résout ça sans toucher aux réglages : le calque ÉCLAIRCIT ce qu'il y a dessous au lieu de s'y
     superposer, donc chaque filet reste un souffle lumineux quel que soit le fond. C'est le comportement
     d'un flux d'air réel, qui diffuse la lumière au lieu de masquer le paysage.
     Le fond CLAIR est exclu : y éclaircir du quasi-blanc ne donnerait rien (l'attribut data-fond est posé
     par majFondCarte()). `screen` est supporté par tous les navigateurs ; si jamais il ne l'était pas, la
     déclaration serait ignorée et on retomberait simplement sur l'affichage précédent. */
  canvas.velocity-overlay{pointer-events:none!important;mix-blend-mode:screen}
  body[data-fond="clair"] canvas.velocity-overlay{mix-blend-mode:normal}
  /* Fumée : respiration lente + phases variées pour un rendu vivant */
  @keyframes smokedrift{0%,100%{opacity:.72}50%{opacity:1}}
  .smoke-anim{animation:smokedrift 10s ease-in-out infinite;will-change:opacity}
  /* Pendant un zoom Leaflet, on FIGE l'animation de fumée : sinon les repaints d'opacité derrière le
     backdrop-filter du header le font sauter/scintiller. Reprend à la fin du zoom. */
  .zooming .smoke-anim{animation:none!important}
  /* PENDANT LE ZOOM : on CACHE la fumée (SVG). La mise à l'échelle d'un gros polygone SVG à chaque frame de
     zoom est très coûteuse (re-rasterisation) → c'était le « saute dans la forêt » (zones foyers+fumée). Elle
     réapparaît instantanément à la fin du zoom. (Au pan simple = translation GPU, on la garde visible.) */
  /* On NE cache PLUS la fumée pendant le zoom : l'ancien hide/réapparition la faisait CLIGNOTER à chaque
     action (« crise d'épilepsie »). Elle reste visible ; seule son opacité s'atténue en douceur au zoom
     rapproché (transition ci-dessous) pour ne pas masquer les foyers. */
  /* PLAN SOMBRE (06/10/2026) : les tuiles du plan clair (Esri World Topo Map) assombries. Réglé sur captures aux zooms
     France, région et commune : fond ≈ #21211f, libellés gris clair (contraste ≈ 10:1), routes et rivières lisibles mais
     plus discrètes que les foyers, avions et tracés, qui restent ce qu'on voit en premier. Hors mode léger seulement
     (en mode léger, le plan sombre est le fond Esri Dark Gray sans filtre, voir app.js FondSombre). */
  .fond-sombre{filter:invert(1) hue-rotate(180deg) saturate(.4) brightness(1.25) contrast(.82)}
  /* ROUTES sur fond SOMBRE : les tuiles routières (IGN + Esri) sont pensées pour un fond clair → sur
     dark_all (fonds « dark »/« thermique ») elles sont trop peu contrastées, quasi invisibles dézoomé
     (retour fondateur 2026-08-24). On les ÉCLAIRCIT au filtre CSS pour qu'elles tranchent sur le noir,
     comme les routes du fond clair. Aucun filtre sur les fonds clair/satellite (déjà lisibles). */
  /* Fonds sombres : on éclaircit les lignes des tuiles IGN pour qu'elles ressortent (les numéros, eux, sont des
     éléments DOM .rv-ecu, jamais filtrés). */
  body[data-fond="dark"] .road-ov,
  body[data-fond="thermique"] .road-ov{filter:brightness(1.85) contrast(1.1)}
  .smoke-poly{transition:opacity .45s ease}
  /* Dissipation PROGRESSIVE, seulement au zoom RAPPROCHÉ (z13+). ≤ z12 : fumée pleine (elle suit le vent,
     dense et vivante). z13 : à peine estompée (garde la vie/anim) · z14 : moitié · z15+ : ténue (voir le sol). */
  .zoom-s13 .smoke-poly{opacity:.7!important}
  .zoom-s14 .smoke-poly{opacity:.45!important;animation:none!important}
  .zoom-s15 .smoke-poly{opacity:.22!important;animation:none!important}
  /* SOURCES DE LA CARTE (06/10/2026, volet le 14/10/2026) : bouton « ⓘ » compact posé par app.js à droite de la pastille
     « Passage », jamais sur une commande ; il ouvre le volet « Sources de la carte » (état des sources, crédits et licences).
     Sa pastille dit l'état global calculé par le serveur. Effacé pendant qu'une bulle est ouverte. */
  .attrib-carte{position:fixed;left:-9999px;top:-9999px;z-index:1141;font:500 11px/1.4 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
  .attrib-carte.attrib-sans-place{visibility:hidden}
  .attrib-btn{position:relative;display:grid;place-items:center;width:26px;height:26px;padding:0;border-radius:50%;border:1px solid var(--line);
    background:var(--panel);color:var(--muted);font:700 15px/1 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;cursor:pointer;
    box-shadow:0 2px 8px rgba(0,0,0,.22)}
  .attrib-btn:focus-visible{outline:2px solid var(--accent,#4a9bec);outline-offset:2px}
  .attrib-btn .attrib-pastille{position:absolute;top:-3px;right:-3px;width:8px;height:8px;border:2px solid var(--panel);box-sizing:content-box}
  body.popup-open .attrib-carte{opacity:0;pointer-events:none;transition:opacity .18s ease}
  /* POPUP LISIBLE, surtout MOBILE (fondateur 02/08) : à l'ouverture d'une popup carte, on efface les
     commandes qui la recouvrent (tiroir de calques OUVERT, bouton « Afficher/masquer », barre de mode
     Satellite/Prévention/Rétrospective). Restauré à la fermeture. Leaflet auto-pan garde déjà la popup
     cadrée ; ceci dégage juste l'UI par-dessus. Desktop : on n'y touche pas (assez de place). */
  @media (max-width:820px){
    body.popup-open #drawer:not(.closed),
    body.popup-open #drawerBtn,
    body.popup-open #modeSeg,
    body.popup-open #fireWinMap,
    body.popup-open #firmsCtl,
    body.popup-open #horizonSeg,
    body.popup-open #sigFab,
    body.popup-open #satInfo,
    body.popup-open #ventHud,
    body.popup-open .leaflet-control-zoom,
    body.popup-open .ctl-appareil,
    /* Annonces et bannières flottantes du bas (nouveautés, installation, dons, galerie…) : posées au-dessus de la
       carte, elles recouvraient le bas d'une bulle ouverte, ses boutons compris (vérifié à 390 px le 06/10/2026). */
    body.popup-open .fv-float,
    body.popup-open #installBanner,
    body.popup-open #renameBanner,
    body.popup-open #retroBanner,
    body.popup-open #galBanner,
    body.popup-open #donBanner,
    body.popup-open #featBanner,
    body.popup-open #petsBanner,
    /* Carte du partenaire : même place en bas d'écran, elle masquait les boutons de la fiche d'un appareil (vérifié
       en ligne à 390 px, 06/10/2026). Elle revient dès la fermeture de la bulle. */
    body.popup-open #sponsorCard{opacity:0;pointer-events:none;transition:opacity .18s ease}
  }
  /* Bulle d'accueil de « Signaler » (premier lancement, 8 s) : retirée dès qu'une bulle de la carte s'ouvre, qu'elle
     recouvrait (06/10/2026). Sur téléphone, elle pointait en plus un bouton effacé par la règle ci-dessus. */
  body.popup-open .sig-coach{display:none}
  /* ⚠️ NE PAS couper le backdrop-filter du header pendant le zoom : le remettre/couper à chaque pas de zoom
     le faisait CLIGNOTER (stroboscope, risque épilepsie). Il reste constant. La fluidité vient du canvas foyers. */
  /* Indice GPU : le pane des overlays (canvas foyers + velocity) est promu sur sa propre couche. */
  /* (Pas de will-change sur le pane overlay : promu en couche, il aggravait l'artefact de compositing du header.) */
  .smoke-anim:nth-of-type(4n){animation-delay:-3s} .smoke-anim:nth-of-type(4n+1){animation-delay:-6s} .smoke-anim:nth-of-type(4n+2){animation-delay:-8s}
  /* ── MODE LÉGER (téléphones d'entrée de gamme type Galaxy A15, ou « économiseur de données ») ──
     On coupe les animations DÉCORATIVES qui tournent en permanence. Deux sont particulièrement chères :
     - le logo `flick` anime un `filter:drop-shadow` → repaint du header à CHAQUE frame, par-dessus une carte
       elle-même animée (le compositeur refait le travail en double) ;
     - `smokedrift` fait varier l'opacité de grands polygones SVG (`will-change:opacity`) → repaints de très
       grande surface.
     ⚠️ On NE touche PAS aux animations qui PORTENT UNE INFORMATION DE DANGER (pastille d'évacuation,
     barre de proximité urgente, point « live », halo de foyer sélectionné) : elles restent, en mode léger
     comme ailleurs. Alléger le décor, jamais l'alerte. */
  body.leger header .logo svg{animation:none;filter:none}
  body.leger .smoke-anim{animation:none;will-change:auto;opacity:.85}
  body.leger .town .bell.on{animation:none}
  body.leger .tp-hot .tp-ic{animation:none}
  body.leger.thermal .firms-core{animation:none}
  /* Pulsations permanentes des avions en vol, du point « direct » et du bouton Signaler (08/10/2026) : une onde
     box-shadow se repeint à chaque image, sans fin, et oblige à recomposer la carte dessous (sur PC portable en
     rendu logiciel, ce sont elles qui gardaient le moteur de rendu occupé carte au repos). Mode léger et
     « réduire les animations » : pastilles fixes, liseré et couleur inchangés. */
  body.leger .aero-pin div,body.leger .aero-pin-mission div,body.leger header .live .dot::after,
  body.leger #sigFab.sig-pulse::after,body.leger #sigFab.sig-hi::after,body.leger .town .bell.on{animation:none}
  body.leger header .live .dot::after{opacity:0}
  body.leger #ventHud{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(12,16,24,.86)}
  @media (prefers-reduced-motion:reduce){
    .aero-pin div,.aero-pin-mission div,header .live .dot::after,#sigFab.sig-pulse::after,#sigFab.sig-hi::after,.town .bell.on,
    .tp-hot .tp-ic,header .logo svg{animation:none}
    header .live .dot::after{opacity:0}
  }
  #cfg{position:absolute;inset:0;z-index:2000;background:rgba(24,32,46,.6);display:none;align-items:center;justify-content:center;padding:20px}
  #cfg.show{display:flex}
  .card{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:22px;max-width:420px;width:100%;box-shadow:var(--shadow-lg)}
  .card h2{margin:0 0 6px;font-size:17px}
  .card p{font-size:13px;color:var(--muted);line-height:1.5;margin:0 0 12px}
  .card input{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:12px;color:var(--txt);font-size:14px;margin-bottom:12px}
  .card a{color:var(--accent);font-weight:600}

  /* Grand écran (14/10/2026, audit B-21) : le volet n'est plus bloqué à 400 px à partir de 1920 px. Largeur par défaut
     proportionnelle (24 % de l'écran, de 400 à 520 px) ; une largeur réglée à la poignée (fv-sheet-w, style en ligne)
     l'emporte toujours. */
  @media (min-width:1920px){:root{--sheetW:clamp(400px,24vw,520px)}}
  /* ── Desktop / tablette large : panneau latéral droit ── */
  @media (min-width:1100px){
    /* Le header ne couvre QUE la carte (s'arrête au panneau de droite) */
    header{right:var(--sheetW,400px);border-bottom-right-radius:14px}
    /* height:auto OBLIGATOIRE ici : la hauteur fixe du mobile l'emporterait sur `bottom:0` (avec top+bottom+
       height, c'est height qui gagne) et la colonne de droite serait tronquée à 72 % de l'écran. */
    #sheet{left:auto;right:0;top:0;bottom:0;width:var(--sheetW,400px);height:auto;min-height:0;max-height:none;border-radius:0;
      border-top:0;border-left:1px solid var(--line);box-shadow:-8px 0 34px rgba(20,30,50,.1);transform:none!important}
    /* La carte se COMPRESSE au lieu de courir sous le panneau : agrandir le panneau agrandit
       vraiment la zone d'information sans amputer le centre de la carte (invalidateSize côté JS). */
    #map{margin-right:var(--sheetW,400px)}
    /* Poignée d'étirement sur le bord gauche du panneau (drag = régler --sheetW, cf. app.js). */
    #sheetResize{display:block;position:absolute;left:-5px;top:0;bottom:0;width:12px;cursor:col-resize;z-index:30}
    #sheetResize::after{content:"";position:absolute;left:4px;top:50%;transform:translateY(-50%);width:4px;height:52px;border-radius:2px;background:var(--line)}
    #sheetResize:hover::after,#sheetResize.drag::after{background:var(--fire)}
    /* ── Mode PLEIN ÉCRAN CARTE (demande fondateur 2026-08-19) : le panneau glisse hors écran, la
       carte reprend toute la largeur. Piloté par body.fs-map (bouton languette #sheetFsBtn, cf.
       app.js). Tout ce qui est ancré sur --sheetW est re-collé au bord droit. Le tiroir Légende
       garde une largeur fixe (il dépend de --sheetW en mode normal). */
    /* top : SOUS le toggle zoom +/− (zoom = top:72px dans la carte, ~64px de haut → on passe à 150px
       sous le header pour ne jamais le chevaucher, constaté fondateur 2026-08-19). */
    /* 14/10/2026 : 186 px (150 avant), sous la colonne Ma position, Ma maison ajoutée sous le zoom (bas à 167 px, zone
       d'appui comprise à 181 px) ; l'onglet des calques descend d'autant (312 px). */
    #sheetFsBtn{position:absolute;top:calc(env(safe-area-inset-top) + var(--hdr-h,84px) + 186px);right:var(--sheetW,400px);z-index:1150;
      display:flex;align-items:center;justify-content:center;width:26px;height:44px;
      background:var(--panel);color:var(--txt);border:1px solid var(--line);border-right:0;
      border-radius:11px 0 0 11px;font-size:15px;font-weight:800;cursor:pointer;
      box-shadow:-4px 2px 12px rgba(20,30,50,.12);transition:right .25s ease}
    #sheetFsBtn:hover{color:var(--fire)}
    body.fs-map #sheetFsBtn{right:0}
    body.fs-map #sheet{transform:translateX(calc(100% + 44px))!important}
    body.fs-map #map{margin-right:0}
    body.fs-map header{right:0;border-bottom-right-radius:0}
    body.fs-map .drawerbtn{right:0}
    body.fs-map #drawer{width:400px;max-width:400px}
    body.fs-map #modeSeg{right:12px}
    body.fs-map #sigFab{right:24px}
    body.fs-map .fv-float{right:12px}
    #sheet.collapsed{transform:none!important}
    /* Desktop : le sheet est un panneau LATÉRAL droit → on arrondit les coins GAUCHES (spécificité renforcée
       pour battre la règle « coins hauts » mobile globale). */
    html body[data-radius] #sheet{ border-radius:var(--ui-radius) 0 0 var(--ui-radius)!important }
    /* Le tiroir Légende occupe TOUTE la colonne droite (même largeur que le panneau) → il le
       recouvre proprement au lieu de laisser le panneau Situation dépasser sur sa gauche. */
    #drawer{width:var(--sheetW,400px);max-width:var(--sheetW,400px)}
    #grip{display:none}
    .tabs{padding-top:16px}
    /* Desktop : flèches ‹ › de navigation des onglets (souris) + place pour elles. */
    .tabs{padding-left:36px;padding-right:36px}
    .tabnav{display:flex;position:absolute;top:16px;height:34px;width:28px;z-index:6;
      align-items:center;justify-content:center;background:var(--panel);color:var(--txt);
      border:1px solid var(--line);border-radius:11px;font-size:17px;font-weight:700;padding:0;
      box-shadow:0 2px 8px rgba(20,30,50,.12);transition:opacity .15s}
    .tabnav.prev{left:8px}
    .tabnav.next{right:8px}
    .tabnav[disabled]{opacity:0;pointer-events:none}
    .sheet-body{flex:1;min-height:0}
    #detail{left:12px;right:auto;width:360px;bottom:24px}
    /* Sur grand écran, une bande de 1400 px pour trois lignes de texte est absurde : elle
       barre la carte. La bannière de renommage héritait des styles mobiles sans cette règle —
       mesurée à 98 % de la fenêtre. Elle suit désormais le même cadrage que l'installation. */
    #installBanner,#renameBanner,#retroBanner,#galBanner,#donBanner,#petsBanner{left:auto;right:16px;bottom:16px;width:360px}
    /* Annonce ANIMAUX « Nouveau : animaux perdus et trouvés » (#petAnnonce, créée en JS avec .fv-float +
       inline max-width:520/margin:auto) : en desktop elle héritait du cadrage bas et s'écrasait en colonne
       de ~264 px de haut (capture fondateur 01/08 : « pas bien affichée sur desktop »). On la centre EN HAUT
       sous le header (56 px), large et HORIZONTALE (≈90 px), dans la colonne centrale libre (timeline à
       gauche, zoom + volet à droite) sans chevaucher personne. !important pour battre le style inline et la
       classe .fv-float ; centrage via left/right:0 + margin auto (pas de transform → animation intacte). */
    #petAnnonce{left:0!important;right:0!important;margin-left:auto!important;margin-right:auto!important;top:calc(var(--hdr-h,56px) + 12px)!important;bottom:auto!important;max-width:none!important;width:min(600px,calc(100vw - 40px))!important}
    /* #featBanner était OUBLIÉ ici → il gardait sa pleine largeur mobile et passait SOUS la bannière de
       droite (galBanner). On le cadre en BAS-GAUCHE (coin opposé) : plus aucun chevauchement desktop. */
    #featBanner{left:16px;right:auto;bottom:16px;width:360px}
    /* Desktop : les bannières pleine-largeur mobiles (installation, don) chevauchaient le panneau
       latéral (right:12px fixe, constaté en étirant le panneau 2026-08-19). Même cadrage que
       featBanner : posées SUR LA CARTE, largeur bornée, jamais sur le panneau. */
    #installBanner,#donBanner{left:16px;right:auto;width:380px;max-width:380px}
    .mapctl{top:calc(env(safe-area-inset-top) + var(--hdr-h,84px) + 10px)}
    /* Zoom : sous le header + à gauche du panneau (jamais recouvert) */
    /* Positions calées sur la hauteur RÉELLE du bandeau (--hdr-h, mesurée en JS) depuis le 13/10/2026 (audit MO-8) : avec
       deux rangées d'onglets (91 px), le « + » du zoom passait à moitié sous le bandeau, la fenêtre 24 h / 48 h couvrait
       « Maintenant » et « +2h » de la frise, et l'onglet des calques recouvrait le bouton » (agrandir la carte). Valeurs
       identiques à avant avec un bandeau d'une rangée (56 px) : zoom 72 px, fenêtre 118 px. */
    .leaflet-top.leaflet-right{right:12px;top:calc(var(--hdr-h,56px) + 16px)}
    .drawerbtn{right:var(--sheetW,400px);top:max(46%, calc(var(--hdr-h,56px) + 312px))}
  }
/* ÉTAT DES SOURCES (14/10/2026) : MÊME COMPOSANT sur la carte des feux (bouton ⓘ, « Sources de la carte ») et sur la carte
   des inondations (pilule « Sources ») ; seul l'habillage du bouton diffère. Une pastille par source, état calculé par le
   serveur. Couleur jamais seule (libellé + heure relative) ; textes d'état à 4,5:1 au moins en clair et en sombre ;
   halo léger pour vert et orange, pulsation douce pour le rouge SEULEMENT, coupée en mouvement réduit. */
:root { --es-vert: #16a34a; --es-orange: #f59e0b; --es-rouge: #e5322d; --es-gris: #94a3b8;
  --es-vert-txt: #15803d; --es-orange-txt: #b45309; --es-rouge-txt: #b91c1c; --es-voile: rgba(8, 12, 20, .5); }
:root[data-theme="dark"] { --es-vert-txt: #4ade80; --es-orange-txt: #fbbf24; --es-rouge-txt: #fca5a5; --es-gris: #7c8799; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --es-vert-txt: #4ade80; --es-orange-txt: #fbbf24; --es-rouge-txt: #fca5a5; --es-gris: #7c8799; } }
.es-pastille { display: inline-block; flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--es-gris); vertical-align: middle; }
.es-pastille.es-vert { background: var(--es-vert); box-shadow: 0 0 0 3px rgba(22, 163, 74, .2); }
.es-pastille.es-orange { background: var(--es-orange); box-shadow: 0 0 0 3px rgba(245, 158, 11, .24); }
.es-pastille.es-rouge { background: var(--es-rouge); box-shadow: 0 0 0 3px rgba(229, 50, 45, .24); animation: es-pouls 2.4s ease-out infinite; }
@keyframes es-pouls { 0% { box-shadow: 0 0 0 0 rgba(229, 50, 45, .55); } 70% { box-shadow: 0 0 0 7px rgba(229, 50, 45, 0); } 100% { box-shadow: 0 0 0 0 rgba(229, 50, 45, 0); } }
@media (prefers-reduced-motion: reduce) { .es-pastille.es-rouge { animation: none; } }
:root:is(.mouvement-reduit, .leger) .es-pastille.es-rouge, body.leger .es-pastille.es-rouge { animation: none; } /* mouvement réduit ou mode léger des deux cartes */
.es-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.es-voile { position: fixed; inset: 0; z-index: 1999; background: var(--es-voile); }
.es-voile[hidden], .es-volet[hidden] { display: none; }
.es-volet { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 2000; box-sizing: border-box;
  width: min(calc(100vw - 24px), 440px); max-height: min(calc(100dvh - 32px), 760px); overflow: auto; overscroll-behavior: contain;
  background: var(--panel); color: var(--txt); border: 1px solid var(--line); border-radius: 20px; padding: 18px 18px 14px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .38), 0 2px 8px rgba(0, 0, 0, .12);
  font-family: inherit; font-size: 13.5px; line-height: 1.45; text-align: left; -webkit-font-smoothing: antialiased; }
.es-x { position: absolute; top: 13px; right: 13px; width: 32px; height: 32px; padding: 0; border-radius: 50%; border: 1px solid var(--line);
  background: var(--panel2); color: var(--muted); cursor: pointer; display: grid; place-items: center; line-height: 1; }
.es-x:hover { color: var(--txt); }
.es-x:focus-visible { outline: 2px solid var(--es-vert-txt); outline-offset: 2px; }
.es-tete { padding-right: 40px; }
.es-surtitre { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.es-titre { display: block; margin: 3px 0 0; font-size: 19px; font-weight: 800; letter-spacing: -.015em; line-height: 1.2; color: var(--txt); }
.es-synthese { display: flex; align-items: center; gap: 12px; margin: 14px 0 4px; padding: 11px 13px; border-radius: 14px; background: var(--panel2); border: 1px solid var(--line); }
.es-synthese.es-vert { background: rgba(22, 163, 74, .07); border-color: rgba(22, 163, 74, .26); }
.es-synthese.es-orange { background: rgba(245, 158, 11, .08); border-color: rgba(245, 158, 11, .34); }
.es-synthese.es-rouge { background: rgba(229, 50, 45, .07); border-color: rgba(229, 50, 45, .32); }
.es-synthese .es-pastille { width: 11px; height: 11px; }
.es-synthese-txt { min-width: 0; }
.es-synthese-txt b { display: block; font-size: 13.5px; font-weight: 750; color: var(--txt); }
.es-synthese-txt small { display: block; margin-top: 1px; font-size: 11.5px; color: var(--muted); }
.es-famille { margin-top: 14px; }
.es-famille h3 { margin: 0 0 3px; padding: 0; font-size: 10.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.es-famille ul { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.es-ligne { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; column-gap: 11px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.es-nom-bloc { min-width: 0; }
.es-nom { display: block; font-size: 13.5px; font-weight: 650; color: var(--txt); overflow-wrap: anywhere; }
.es-rythme { display: block; margin-top: 1px; font-size: 11.5px; color: var(--muted); }
.es-etat { text-align: right; white-space: nowrap; }
.es-libelle { display: block; font-size: 12.5px; font-weight: 700; color: var(--muted); }
.es-ligne.es-vert .es-libelle { color: var(--es-vert-txt); }
.es-ligne.es-orange .es-libelle { color: var(--es-orange-txt); }
.es-ligne.es-rouge .es-libelle { color: var(--es-rouge-txt); }
.es-age { display: block; margin-top: 1px; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.es-pied { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line); font-size: 12px; line-height: 1.5; color: var(--muted); }
.es-pied-t { display: block; margin-bottom: 4px; font-size: 10.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.es-pied p { margin: 6px 0; }
.es-pied b { color: var(--txt); }
.es-credit { margin: 9px 0 0; }
.es-credit b { display: block; font-size: 11.5px; }
.es-credit > span, .es-credit > a { display: block; }
.es-pied a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
@media (max-width: 380px) { .es-volet { padding: 16px 14px 12px; } .es-ligne { column-gap: 9px; } .es-nom { font-size: 13px; } }
