/* ================= Charte EDF + Material 3 ================= */
:root{
  --edf-blue:#1057C8; --edf-blue-dark:#001A70; --edf-blue-light:#1089FF;
  --edf-orange:#FF861D; --edf-orange-deep:#FE5815; --edf-yellow:#FFB210;
  --edf-green-light:#88D910; --edf-green:#4F9E30;
  --edf-grey-dark:#333333; --edf-grey:#E0E0E0; --edf-grey-bg:#F8F7F7;

  --bg:var(--edf-grey-bg); --surface:#FFFFFF; --surface-2:#FFFFFF; --surface-var:#EFF3FA;
  --on-bg:var(--edf-grey-dark); --on-surface:var(--edf-grey-dark); --on-surface-var:#5A5A5A;
  --primary:var(--edf-blue); --on-primary:#FFFFFF;
  --primary-container:#DCE7FA; --on-primary-container:#00276B;
  --outline:#C4C7CC; --outline-var:var(--edf-grey);
  --ok:#4F9E30; --ok-container:#E4F5D2; --on-ok-container:#4F9E30;
  --ko:#FE5815; --ko-container:#FFE3D0; --on-ko-container:#FE5815;
  --elev1:0 1px 2px rgba(0,0,0,.3),0 1px 3px 1px rgba(0,0,0,.10);
  --elev2:0 1px 2px rgba(0,0,0,.3),0 2px 6px 2px rgba(0,0,0,.12);
  --elev3:0 4px 8px 3px rgba(0,0,0,.15),0 1px 3px rgba(0,0,0,.3);
  --radius:20px;
}
html[data-theme="dark"]{
  --bg:#101418; --surface:#1B2129; --surface-2:#232A34; --surface-var:#242C38;
  --on-bg:#E4E6EA; --on-surface:#E4E6EA; --on-surface-var:#Aeb4bd;
  --primary:#9BC2FF; --on-primary:#00276B;
  --primary-container:#0A3E8F; --on-primary-container:#D6E3FF;
  --outline:#4A5158; --outline-var:#3A4148;
  --ok:#88D910; --ok-container:#28430F; --on-ok-container:#88D910;
  --ko:#FF861D; --ko-container:#5C2000; --on-ko-container:#FF861D;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
body{margin:0;background:var(--bg);color:var(--on-bg);
  font-family:"EDF 2020","Segoe UI",Arial,sans-serif;font-size:15px;line-height:1.45;
  transition:background .3s,color .3s}
/* Taille du texte (Préférences) : zoom proportionnel du contenu principal.
   Volontairement limité à #zoomWrap (hors en-tête et bandeau note) car la
   propriété CSS "zoom" casse position:sticky sur ses ancêtres dans Chromium. */
html[data-fontsize="sm"] #zoomWrap{zoom:0.9}
html[data-fontsize="lg"] #zoomWrap{zoom:1.15}
h1,h2,h3,.bold{font-weight:700}
.msr{font-family:'Material Symbols Rounded';font-weight:normal;font-style:normal;
  font-size:22px;line-height:1;display:inline-block;vertical-align:middle;
  -webkit-font-smoothing:antialiased;user-select:none;
  font-variation-settings:'FILL' 0,'wght' 400,'GRAD' 0,'opsz' 24}
button{font-family:inherit}

/* ---------- Header ---------- */
header{position:sticky;top:0;z-index:50;background:var(--edf-blue);color:#fff;box-shadow:var(--elev2)}
/* Bug corrigé : le titre était centré dans l'espace RESTANT entre le logo et
   les boutons de droite (flex:1), pas dans le header entier - vu que ces deux
   groupes n'ont pas la même largeur, le titre paraissait décalé. Avec une
   grille à 3 colonnes dont les deux colonnes latérales se partagent l'espace
   à parts égales (minmax(auto,1fr)), le titre reste vraiment au centre du
   header, quelle que soit la largeur du logo ou des boutons de droite. */
header .headertop{display:grid;grid-template-columns:minmax(auto,1fr) auto minmax(auto,1fr);
  align-items:center;gap:12px;padding:10px 16px}
header .logo{height:34px;cursor:pointer;justify-self:start}
header .titlewrap{justify-self:center;display:flex;align-items:center;justify-content:center;gap:2px;min-width:0}
header .title{flex:0 1 auto;text-align:center;font-size:19px;font-weight:700;letter-spacing:.3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
header .headerright{justify-self:end;display:flex;align-items:center;gap:12px;min-width:0}
header .clock{font-variant-numeric:tabular-nums;font-size:15px;font-weight:700;opacity:.95;min-width:70px;text-align:right}
.iconbtn{background:transparent;border:none;color:inherit;width:42px;height:42px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s}
.iconbtn:hover{background:rgba(255,255,255,.14)}
.iconbtn.on-surface{color:var(--on-surface-var)}
.iconbtn.on-surface:hover{background:rgba(128,128,128,.15)}

/* ---------- Icône "notes masquées" (toolbar, à côté du compte à rebours) ---------- */
.notes-wrap{position:relative}
.plantname-wrap{position:relative;display:flex;align-items:center;gap:6px;min-width:0}
.plantname-wrap h2{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.notes-btn{position:relative;cursor:pointer}
.notes-badge{position:absolute;top:-4px;right:-4px;min-width:16px;height:16px;padding:0 3px;
  border-radius:8px;background:var(--edf-orange-deep);color:#fff;font-size:10px;font-weight:700;
  line-height:16px;text-align:center;box-shadow:0 0 0 2px var(--bg)}
/* Toast flottant ancré sous l'icône (option B) : pas de pop-up plein écran, se
   ferme au clic extérieur, animation d'ouverture en fondu + léger glissement. */
.notes-pop{position:absolute;top:calc(100% + 10px);right:0;width:290px;max-width:80vw;
  background:var(--surface);color:var(--on-surface);border-radius:16px;box-shadow:var(--elev3);
  padding:14px;z-index:70;display:none;opacity:0;transform:translateY(-6px) scale(.97);
  transition:opacity .16s ease,transform .16s ease}
.notes-pop.show{display:flex;flex-direction:column}
.notes-pop.open{opacity:1;transform:translateY(0) scale(1)}
.notes-pop-title{font-weight:700;font-size:13px;text-transform:uppercase;letter-spacing:.4px;
  color:var(--edf-orange-deep);margin-bottom:10px}
.notes-pop-item{display:flex;align-items:center;gap:8px;padding:7px 0;font-size:13.5px}
.notes-pop-item+.notes-pop-item{border-top:1px solid rgba(128,128,128,.18)}
.notes-pop-item .msr{font-size:18px;flex:0 0 auto}
/* Note globale admin+ : orange. Note de centrale : bleu (comme le bandeau Notes). */
.notes-pop-item.global{color:var(--edf-orange-deep)}
.notes-pop-item.global .msr{color:var(--edf-orange-deep)}
html[data-theme="dark"] .notes-pop-item.global,
html[data-theme="dark"] .notes-pop-item.global .msr{color:var(--edf-orange)}
.notes-pop-item.plant{color:var(--edf-blue)}
.notes-pop-item.plant .msr{color:var(--edf-blue)}
html[data-theme="dark"] .notes-pop-item.plant,
html[data-theme="dark"] .notes-pop-item.plant .msr{color:#9BC2FF}
/* Alerte indisponibilité programmée à venir (15 min avant), vert - la même
   teinte tonale que Codex/Ouvert ailleurs dans l'appli, déjà adaptée au
   mode sombre via --on-ok-container (pas besoin de redéfinition dédiée). */
.notes-pop-item.upcoming{color:var(--on-ok-container)}
.notes-pop-item.upcoming .msr{color:var(--on-ok-container)}
/* Texte défilant si trop large (même principe que le bandeau note). Aucun
   cadre/contour : ce sont de simples span/div, pas des champs de saisie. */
.notes-pop-item .txtwrap{flex:1;min-width:0;overflow:hidden;white-space:nowrap;
  border:none;outline:none;background:transparent}
.notes-pop-item .txtwrap .txt{display:inline-block;white-space:nowrap;
  border:none;outline:none;background:transparent}
.notes-pop-item .txtwrap.scrolling .txt{display:inline-flex;animation:noteMarquee 9s linear infinite}
.notes-pop-item .txtwrap.scrolling .txt .seg{padding-right:40px;white-space:nowrap;border:none}

/* ---------- Filtre Chronologie (icône loupe, à gauche du nom de centrale) ---------- */
/* Repris à zéro (démos validées) : même chrome que "Notes masquées" (.notes-pop),
   ancré à gauche cette fois (près du bord de l'écran). L'icône reprend la même
   couleur que le titre de la centrale (var(--edf-blue) / #9BC2FF en sombre) au
   lieu du gris "on-surface" utilisé par les autres icônes secondaires. */
.evt-filter-wrap{position:relative}
.evt-filter-btn{color:var(--edf-blue)}
.evt-filter-btn:hover{background:rgba(16,87,200,.1)}
html[data-theme="dark"] .evt-filter-btn{color:#9BC2FF}
html[data-theme="dark"] .evt-filter-btn:hover{background:rgba(155,194,255,.14)}
/* Indicateur "filtre(s) actif(s)" (option C retenue, démos validées) : simple
   pastille discrète sur l'icône loupe, sans chiffre - visible dès qu'au moins
   une unité (ou les Notes) est masquée pour la centrale affichée. */
.evtf-dot{position:absolute;top:6px;right:6px;width:9px;height:9px;border-radius:50%;
  background:var(--edf-blue);box-shadow:0 0 0 2px var(--bg);display:none}
html[data-theme="dark"] .evtf-dot{background:#9BC2FF}
.evtf-dot.show{display:block}
/* Position par défaut avant calcul JS (centrage réel géré par
   clampEvtFilterPop() dans script.js, appelé à chaque ouverture). */
.evt-filter-pop{left:0;right:auto}
.evt-filter-pop .notes-pop-title{display:flex;align-items:center;gap:6px;color:var(--on-primary-container);
  margin-bottom:6px}
.evt-filter-pop .notes-pop-title.codex{color:var(--on-ok-container)}
.evt-filter-pop .notes-pop-title.notes{color:var(--on-ko-container)}
.evt-filter-pop .notes-pop-title:not(:first-child){margin-top:12px}
.evt-filter-pop .notes-pop-title .msr{font-size:17px}
/* Option A (retenue) : grille de chips à cadre individuel par groupe - Salle de
   commande en bleu tonal, Codex en vert tonal (mêmes teintes que Paramètres/
   bouton Actualiser), et désormais un 3e groupe "Notes" avec un chip unique
   pleine largeur "Notes de la centrale" (teinte "ko"/orange, déjà utilisée
   ailleurs dans l'appli pour les notes/alertes). */
.evtf-chips{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.evtf-chip{border:1px solid var(--primary-container);background:var(--surface);color:var(--on-primary-container);
  border-radius:10px;padding:6px 10px;font-size:12.5px;font-weight:600;cursor:pointer;text-align:center;
  font-family:inherit}
.evtf-chip.sel{background:var(--primary-container);color:var(--on-primary-container);border-color:var(--primary-container)}
.evtf-chip.codex{border-color:var(--ok-container);color:var(--on-ok-container)}
.evtf-chip.codex.sel{background:var(--ok-container);color:var(--on-ok-container);border-color:var(--ok-container)}
.evtf-chip.notes{border-color:var(--ko-container);color:var(--on-ko-container)}
.evtf-chip.notes.sel{background:var(--ko-container);color:var(--on-ko-container);border-color:var(--ko-container)}
.evtf-chip.full{grid-column:1/-1}
.evtf-empty{grid-column:1/-1;font-size:12px;color:var(--on-surface-var)}

/* ---------- Bannière dégradé ---------- */
/* Vue "Chronologie" (3e apparence) : flux unique, toutes unités mélangées,
   ordonné par heure, avec séparateurs de jour (démo "Ligne + points" validée). */
.events-zone{margin-top:6px}
.events-zone .evt-day{font-size:12.5px;font-weight:700;color:var(--on-surface-var);text-transform:uppercase;
  letter-spacing:.04em;margin:22px 0 10px;display:flex;align-items:center;gap:10px}
.events-zone .evt-day:first-child{margin-top:0}
.events-zone .evt-day::after{content:"";flex:1;height:1px;background:var(--outline)}
/* Option B retenue : pas de trait/point, l'icône du type d'unité porte elle-même
   la couleur de la nature de l'évènement (bleu EDF par défaut, vert/orange sinon). */
.events-zone .evt-item{background:var(--surface);border-radius:12px;box-shadow:var(--elev1);
  padding:11px 14px;margin-bottom:10px;display:flex;align-items:flex-start;gap:10px}
.events-zone .evt-item .ic{font-size:22px;color:var(--edf-blue);margin-top:1px;flex:0 0 auto}
.events-zone .evt-item.ok .ic{color:var(--ok)}
.events-zone .evt-item.ko .ic{color:var(--ko)}
.events-zone .evt-item .body{flex:1;min-width:0}
.events-zone .evt-item .unit{font-weight:700;font-size:13.5px}
.events-zone .evt-item .desc{font-size:13px;color:var(--on-surface-var);margin-top:1px}
.events-zone .evt-item .time{font-size:11.5px;color:var(--on-surface-var);white-space:nowrap;margin-top:2px}
.events-zone .evt-item .evt-del{width:32px;height:32px;flex:0 0 auto;margin:-4px -6px -4px 0}
.events-zone .evt-item .evt-del .msr{font-size:19px}
.events-zone .evt-more{display:flex;margin:14px auto 0}

#offlineBanner{display:none;background:var(--edf-orange-deep);color:#fff;padding:8px 16px;
  font-size:13.5px;align-items:center;gap:8px;flex-wrap:wrap}
#offlineBanner.show{display:flex}
#offlineBanner .offline-lastsync{margin-left:auto;opacity:.85;font-size:12.5px}

/* ---------- Note générale de la centrale / note globale admin+ ---------- */
/* Élément statique dans le flux normal (ne reste pas accroché au header
   pendant le défilement) : bandeau arrondi, bleu pour la note de centrale,
   orange (.global) pour la note globale admin+ qui la remplace le cas échéant. */
.plant-note{display:flex;align-items:center;gap:10px;background:var(--primary-container);
  color:var(--on-primary-container);font-size:13.5px;border-radius:14px;min-height:24px;
  padding:10px 14px;margin-bottom:14px;box-shadow:var(--elev1)}
.plant-note.global{background:var(--ko-container);color:var(--on-ko-container)}
/* Alerte indisponibilité programmée à venir (vert) : même encadrement,
   affichée en plus de la note de centrale/globale (bandeau séparé). */
.plant-note.upcoming{background:var(--ok-container);color:var(--on-ok-container)}
.plant-note .msr{font-size:20px;flex:0 0 auto}
/* Boutons du bandeau (édition / fermeture) : sur fond clair (bleu ou orange),
   un survol blanchâtre (.iconbtn par défaut) serait invisible : survol sombre. */
.plant-note .iconbtn{width:34px;height:34px}
.plant-note .iconbtn:hover{background:rgba(0,0,0,.1)}
/* Si le texte est plus large que l'espace disponible, il défile en boucle
   plutôt que de passer à la ligne ou d'être coupé (voir applyNoteMarquee()). */
.plant-note-textwrap{flex:1;min-width:0;overflow:hidden;white-space:nowrap}
.plant-note-textwrap #plantNoteText{display:inline-block;white-space:nowrap}
.plant-note-textwrap.scrolling #plantNoteText{display:inline-flex;animation:noteMarquee 10s linear infinite}
.plant-note-textwrap.scrolling #plantNoteText .seg{padding-right:48px;white-space:nowrap}
@keyframes noteMarquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  .plant-note-textwrap.scrolling #plantNoteText{animation:none}
  .plant-note-textwrap{text-overflow:ellipsis}
}
/* Panneau de gestion des notes de centrale (Gestion) : statique dans le flux,
   pas un pop-up. Ouvert/fermé via le crayon du bandeau. Chaque note s'y
   modifie directement (champ texte), plusieurs peuvent être en file d'attente. */
/* Mêmes couleurs que le bandeau "Notes" (bleu) pour rester cohérent. */
.notes-manage{background:var(--primary-container);color:var(--on-primary-container);border-radius:14px;
  padding:12px 14px;margin:-4px 0 14px;box-shadow:var(--elev1)}
.notes-manage-title{display:flex;align-items:center;gap:8px;font-weight:400;margin-bottom:4px}
.notes-manage .hint{color:inherit;opacity:.75}
.notes-manage .unititem input{background:var(--surface);color:var(--on-surface)}
.notes-manage-item{display:flex;align-items:center;gap:8px;margin:6px 0}
.notes-manage-item input{flex:1;min-width:0;background:var(--surface);color:var(--on-surface);
  border:1px solid var(--outline);border-radius:12px;padding:8px 12px;font-size:14px;
  font-family:inherit;min-width:0}
.notes-manage-item button{flex:0 0 auto;color:inherit}
.notes-manage .iconbtn:hover{background:rgba(0,0,0,.1)}

/* ---------- Layout ---------- */
main{max-width:1200px;margin:0 auto;padding:16px}
.toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px}
.toolbar h2{margin:0;font-size:20px;color:var(--edf-blue)}
html[data-theme="dark"] .toolbar h2{color:#9BC2FF}
.toolbar .spacer{flex:1}
.countdown{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;
  border-radius:50%;background:var(--ok-container);border:2px solid var(--ok-container);color:var(--on-ok-container);
  font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;flex:0 0 auto;box-sizing:border-box;
  transition:background .2s,color .2s,border-color .2s}
.countdown.paused{background:var(--surface-var);border-color:var(--surface-var);color:var(--on-surface-var);opacity:.8}
.countdown.notes-btn{background:var(--ko-container);border-color:var(--ko-container);color:var(--on-ko-container)}
.section-title{display:flex;align-items:center;gap:8px;margin:22px 0 10px;font-size:16px;font-weight:700;color:var(--on-surface-var)}
.section-title.sdc,.section-title.sdc .msr,
.section-title.codex,.section-title.codex .msr{color:var(--edf-blue)}
html[data-theme="dark"] .section-title.sdc,html[data-theme="dark"] .section-title.sdc .msr,
html[data-theme="dark"] .section-title.codex,html[data-theme="dark"] .section-title.codex .msr{color:#9BC2FF}
/* L'auto-margin (qui pousse le groupe de boutons contre le bord droit) est
   porté par le bouton "ordre par défaut" plutôt que par "Ajouter" : les deux
   sont toujours affichés/masqués ensemble (profil admin), donc le bouton
   "Ajouter" reste ainsi immédiatement collé à droite de "ordre par défaut"
   (bug corrigé : l'auto-margin sur "Ajouter" seul créait un grand vide entre
   les deux boutons, qui n'étaient donc pas visuellement adjacents). */
.section-title .reorder-default-btn{margin-left:auto}
/* Bouton "Ranger l'ordre par défaut" (page principale, option A - démo
   validée) : icône "menu" au repos. Une fois le mode réorganisation activé,
   l'icône devient "check" (valider), en bleu (sans encadrement). */
.reorder-default-btn.active{background:var(--primary-container);color:var(--on-primary-container)}
.reorder-default-btn.save{background:var(--primary-container);color:var(--on-primary-container)}
/* Cartes en mode réorganisation de l'ordre par défaut : contour en
   pointillés pour signaler que le glisser-déposer ne modifie plus l'ordre
   personnel de cet appareil mais l'ordre par défaut partagé. */
.cards-zone.reorder-default .card{border:1.5px dashed var(--primary);border-radius:var(--radius)}

/* ---------- Boutons M3 ---------- */
.btn{border:none;border-radius:999px;padding:10px 22px;font-size:14px;font-weight:600;
  cursor:pointer;display:inline-flex;align-items:center;gap:8px;transition:box-shadow .15s,background .15s;
  min-height:40px}
.btn .msr{font-size:19px}
.btn.filled{background:var(--primary);color:var(--on-primary)}
.btn.filled:hover{box-shadow:var(--elev1)}
.btn.tonal{background:var(--primary-container);color:var(--on-primary-container)}
.btn.outlined{background:transparent;color:var(--primary);border:1px solid var(--outline)}
.btn.text{background:transparent;color:var(--primary);padding:10px 14px}
.btn.danger{background:var(--ko-container);color:var(--on-ko-container)}
.btn:disabled{opacity:.45;cursor:not-allowed}

/* ---------- Segmented buttons ---------- */
.seg{display:flex;width:100%;border:1px solid var(--outline);border-radius:999px;overflow:hidden}
.seg button{flex:1;background:transparent;border:none;padding:9px 6px;font-size:13.5px;font-weight:600;
  color:var(--on-surface);cursor:pointer;display:flex;align-items:center;justify-content:center;gap:6px;
  border-left:1px solid var(--outline)}
.seg button:first-child{border-left:none}
.seg button.sel{background:var(--primary-container);color:var(--on-primary-container)}
.seg button .msr{font-size:18px}
.seg button:disabled{opacity:.4;cursor:not-allowed}

/* ---------- Chips ---------- */
.chip{border:1px solid var(--outline);background:transparent;color:var(--on-surface);
  border-radius:10px;padding:6px 14px;font-size:13px;font-weight:600;cursor:pointer;
  display:inline-flex;align-items:center;gap:6px}
.chip.sel{background:var(--primary-container);border-color:transparent;color:var(--on-primary-container)}

/* ---------- Cartes ---------- */
#cards{display:grid;gap:14px}
#cards.cols{grid-template-columns:repeat(auto-fill,minmax(270px,1fr))}
#cards.rows{grid-template-columns:1fr}
/* Design 10 - Transition douce entre thème clair et sombre : le fond et le
   texte des cartes/modales changent en fondu plutôt qu'instantanément
   (le fond de page, lui, l'était déjà via la règle body ci-dessus). */
.card{background:var(--surface);border-radius:var(--radius);box-shadow:var(--elev1);
  padding:16px;position:relative;overflow:hidden;border:2px solid transparent;
  transition:box-shadow .2s,border-color .2s,background-color .3s ease,color .3s ease;
  display:flex;flex-direction:column;min-height:0}

/* Design 3 - Carte en cours d'édition sur un autre appareil (présence D1,
   voir PRESENCE/pingPresence()). Best-effort : dépend d'un ping toutes les
   ~60s, pas d'un signal instantané. */
.card.locked-elsewhere{border-style:dashed;border-color:var(--edf-blue)}
.card .who{display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--edf-blue);margin-top:8px}
/* Fonctionnalité 4 - Compteur approximatif d'appareils connectés (admin+) */
.conn-chip{display:inline-flex;align-items:center;gap:6px;background:var(--surface-var);
  color:var(--on-surface-var);border-radius:999px;padding:5px 12px;font-size:12.5px;font-weight:600}
.conn-chip .dot{width:8px;height:8px;border-radius:50%;background:var(--ok);flex:0 0 auto}
.card .who .msr{font-size:14px}
html[data-theme="dark"] .card.locked-elsewhere{border-color:#9BC2FF}
html[data-theme="dark"] .card .who{color:#9BC2FF}

/* Design 6 - Numéro de tranche en filigrane (repérage rapide sur un mur d'écrans),
   coin haut-droit de la carte. Le statut RP/AN-GV/etc. a été déplacé dans la
   ligne du badge (statusrow) pour ne plus passer par-dessus. */
.card .watermark{position:absolute;top:-14px;right:-6px;font-size:88px;font-weight:800;
  color:var(--on-surface);opacity:.05;line-height:1;user-select:none;pointer-events:none;z-index:0}
html[data-theme="dark"] .card .watermark{opacity:.08}
.cols .card{height:225px;overflow:hidden}   /* taille fixe = gabarit "indisponible" */
.cols .card.editing{height:225px}
.rows .card:not(.min){min-height:118px}
.rows .card.editing{height:230px;overflow:hidden}   /* hauteur fixe : les boutons Annuler/Suivant ne bougent pas entre les 3 étapes, y compris pour Codex */
.card:hover{box-shadow:var(--elev2)}
.card.fav-ok{border-color:var(--edf-green)}
.card.fav-ko{border-color:var(--edf-orange-deep)}
.card.dragging{opacity:.97;box-shadow:var(--elev3);z-index:60;cursor:grabbing;
  transition:box-shadow .15s;pointer-events:none}   /* pas de rotation/mise à l'échelle : évite le flou du texte pendant le déplacement */
.card-placeholder{border:2px dashed var(--outline);border-radius:var(--radius);
  background:var(--surface-var);opacity:.6}
.cols .card-placeholder{height:225px}
.rows .card-placeholder{min-height:118px}
.card .head{display:flex;align-items:center;gap:8px}
.card .head h3{margin:0;font-size:16.5px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card .head h3[contenteditable]{cursor:text;border-bottom:1px dashed var(--outline);white-space:normal}
.card .head h3[contenteditable]:focus{outline:none;border-bottom-color:var(--primary)}
.drag-handle{cursor:grab;color:var(--on-surface-var);touch-action:none}
.drag-handle:active{cursor:grabbing}
.dot{width:13px;height:13px;border-radius:50%;flex:0 0 auto}
.dot.ok{background:var(--edf-green);animation:breatheOk 2.4s ease-in-out infinite}
.dot.ko{background:var(--edf-orange-deep);animation:breatheKo 2.4s ease-in-out infinite}
@keyframes breatheOk{
  0%,100%{box-shadow:0 0 0 3px color-mix(in srgb,var(--edf-green) 28%,transparent);transform:scale(1)}
  50%{box-shadow:0 0 0 9px color-mix(in srgb,var(--edf-green) 8%,transparent);transform:scale(1.12)}}
@keyframes breatheKo{
  0%,100%{box-shadow:0 0 0 3px color-mix(in srgb,var(--edf-orange-deep) 28%,transparent);transform:scale(1)}
  50%{box-shadow:0 0 0 9px color-mix(in srgb,var(--edf-orange-deep) 8%,transparent);transform:scale(1.12)}}
@media (prefers-reduced-motion:reduce){.dot.ok,.dot.ko{animation:none}}
/* État de la tranche (RP, AN/GV, AN/RRA, API, APR, RCD) : au niveau du titre,
   Salle de commande uniquement. Bug corrigé (Option 2) : une marge à droite
   le décale légèrement vers la gauche pour qu'il ne passe plus sous le
   numéro de tranche en filigrane (coin haut-droit de la carte). */
.reactor-state-select{flex:0 0 auto;width:auto;min-width:0;padding:3px 6px;font-size:11.5px;
  font-weight:700;border-radius:8px;background:var(--surface-var);color:var(--on-surface-var);
  border:1px solid var(--outline);margin-right:34px}
.reactor-state-badge{flex:0 0 auto;font-size:11px;font-weight:700;padding:3px 8px;border-radius:999px;
  background:var(--surface-var);color:var(--on-surface-var);white-space:nowrap;margin-right:34px}
/* Bug corrigé : en mode ligne, le bouton agrandir/rétrécir était collé au bord
   droit de la carte, sous le filigrane. Décalé (uniquement quand un statut de
   tranche est affiché avant lui) pour rester entre le statut et le filigrane. */
.reactor-state-select ~ .minbtn, .reactor-state-badge ~ .minbtn{margin-right:34px}
/* Bug corrigé : en mode ligne, le bouton garde son écart avec le filigrane
   (ci-dessus), mais le statut de tranche se rapproche de lui plutôt que de
   garder le même grand écart qu'en mode colonnes (où rien ne le suit). */
.rows .reactor-state-select{margin-right:8px}
.rows .reactor-state-badge{margin-right:8px}
.badge{border-radius:999px;padding:4px 12px;font-size:12.5px;font-weight:700;display:inline-flex;align-items:center;gap:5px}
.badge.ok{background:var(--ok-container);color:var(--on-ok-container)}
.badge.ko{background:var(--ko-container);color:var(--on-ko-container)}
.card .body{margin-top:10px;font-size:13.5px;color:var(--on-surface-var);display:flex;flex-direction:column;gap:5px;flex:1}
.card .body .line{display:flex;align-items:center;gap:7px}
.card .body .msr{font-size:17px}
.card .updated{font-size:11.5px;color:var(--on-surface-var);opacity:.8;text-align:left}
.card .actions{margin-top:10px;display:flex;gap:8px;flex-wrap:wrap}
.statusrow{margin-top:8px}
.cardfoot{display:flex;justify-content:flex-end;gap:2px;margin-top:auto;align-items:center}
.card.min .body,.card.min .actions,.card.min .statusrow,.card.min .cardfoot{display:none}
.star{color:var(--on-surface-var)}
.star.sel{color:var(--edf-yellow);font-variation-settings:'FILL' 1}
/* Notification par tranche/Codex (icône à gauche du favori, visible quand les
   notifications sont activées dans Paramètres) : allumée = notifie normalement,
   éteinte = coupée juste pour cette unité (navigateur + son). */
.unitnotif{color:var(--on-surface-var)}
.unitnotif.sel{color:var(--edf-blue)}
html[data-theme="dark"] .unitnotif.sel{color:#9BC2FF}
.progbtn.sel{color:var(--edf-blue)}
html[data-theme="dark"] .progbtn.sel{color:#9BC2FF}

/* ---------- Indisponibilités programmées (icône "event_repeat", pied de card Tranche) ---------- */
.sched-slot{display:flex;flex-direction:column;gap:8px;background:var(--surface-var);border-radius:12px;
  padding:9px 10px;margin-bottom:8px}
.sched-slot .sched-row1{display:flex;align-items:center;gap:8px}
.sched-slot .sched-row2{display:flex;align-items:center;gap:8px;padding-left:44px}
.sched-slot input[type="text"]{flex:1;min-width:0;background:var(--surface);color:var(--on-surface);
  border:1px solid var(--outline);border-radius:8px;padding:7px 10px;font-size:13px;font-family:inherit}
.sched-slot input[type="time"]{background:var(--surface);color:var(--on-surface);border:1px solid var(--outline);
  border-radius:8px;padding:6px 8px;font-size:13px;font-family:inherit}
.sched-slot .sep{color:var(--on-surface-var);font-size:12px}
.sched-toggle{width:36px;height:20px;border-radius:999px;background:var(--outline);position:relative;
  border:none;cursor:pointer;flex:0 0 auto;padding:0}
.sched-toggle.on{background:var(--ok)}
.sched-toggle::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;
  background:#fff;transition:left .15s}
.sched-toggle.on::after{left:18px}
.sched-empty{font-size:12.5px;color:var(--on-surface-var);background:var(--surface-var);border-radius:10px;
  padding:10px 12px;margin-bottom:10px}

/* ---------- Carte édition ---------- */
.editcard{background:var(--surface-var);border-radius:var(--radius);box-shadow:var(--elev1);
  padding:16px;display:flex;flex-direction:column;gap:12px;animation:pop .18s ease-out}
@keyframes pop{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.editcard label{font-size:12.5px;font-weight:700;color:var(--on-surface-var)}
.editcard input[type=text],.editcard input[type=time],.editcard input[type=number]{
  background:var(--surface);color:var(--on-surface);border:1px solid var(--outline);
  border-radius:12px;padding:10px 12px;font-size:14px;font-family:inherit;width:100%}
.editcard .row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.hint{font-size:12.5px;color:var(--on-surface-var)}

/* ---------- Édition dans la carte ---------- */
.editform{
  display:flex;flex-direction:column;gap:12px;flex:1;min-height:0;animation:pop .18s ease-out}
.editform label{font-size:12.5px;font-weight:700;color:var(--on-surface-var)}
.editform input[type=text],.editform input[type=time],.editform input[type=number]{
  background:var(--surface-var);color:var(--on-surface);border:1px solid var(--outline);
  border-radius:12px;padding:10px 12px;font-size:14px;font-family:inherit;width:100%}
.editform .row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
/* Calendrier hebdomadaire Codex : chips des 7 jours + édition du jour sélectionné */
.daychips{display:flex;gap:5px;flex-wrap:wrap}
.daychip{width:28px;height:28px;flex:0 0 auto;border-radius:50%;border:1.5px solid var(--ok-container);
  background:var(--surface);color:var(--on-ok-container);font-size:11.5px;font-weight:700;font-family:inherit;
  padding:0;cursor:pointer;display:flex;align-items:center;justify-content:center;
  transition:background .15s,color .15s,border-color .15s,box-shadow .15s}
.daychip.off{color:var(--on-ko-container);border-color:var(--ko-container)}
.daychip.sel{background:var(--ok-container);box-shadow:0 0 0 2px var(--ok)}
.daychip.off.sel{background:var(--ko-container);box-shadow:0 0 0 2px var(--ko)}
.dayedit{padding:0}
.dayedit .row{gap:8px;flex-wrap:nowrap}
.dayedit input[type=time]{padding:6px 8px;font-size:12.5px;border-radius:10px}

/* ---------- Sections préférences / admin ---------- */
.prefsec{background:var(--surface-var);border-radius:16px;padding:12px 14px;margin:12px 0}
.prefsec .phead{display:flex;align-items:center;gap:8px;font-weight:700;font-size:13.5px;
  color:var(--primary);margin-bottom:10px}
.prefsec .phead .msr{font-size:19px}
.unititem{display:flex;align-items:center;gap:8px;margin:6px 0}
.unititem input{flex:1;background:var(--surface);color:var(--on-surface);border:1px solid var(--outline);
  border-radius:12px;padding:8px 12px;font-size:14px;font-family:inherit;min-width:0}
/* Liste des notes globales en file d'attente (une seule affichée à la fois). */
#globalNotesList{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.globalnote-item{display:flex;align-items:center;gap:8px;background:var(--surface);
  border-radius:10px;padding:7px 10px;font-size:13.5px}
.globalnote-item .txt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.globalnote-item button{flex:0 0 auto}
/* La note actuellement affichée (la première non masquée de la file) : même
   hauteur d'encadrement que les autres champs du panneau ("Sans expiration"
   et "Ajouter" une note) - bug corrigé, l'encadrement était plus petit (padding
   et police réduits) que le reste, ce qui cassait l'alignement visuel. Reste
   distingué des notes en file d'attente par une bordure au lieu d'une taille. */
.globalnote-item.current{padding:10px 12px;font-size:14px;border-radius:12px;
  border:1px solid var(--primary)}


/* Les rangées d'actions des panneaux d'Administration (.row simple, hors .editform/.editcard/
   .dayedit qui ont déjà leur propre display:flex) doivent rester en ligne (bouton + select...). */
.prefsec .row{display:flex;align-items:center;flex-wrap:wrap}

/* ---------- Modal ---------- */
.scrim{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;z-index:100;
  align-items:center;justify-content:center;padding:16px}
.scrim.show{display:flex}
.modal{background:var(--surface);border-radius:28px;box-shadow:var(--elev3);max-width:460px;width:100%;
  max-height:88vh;overflow:auto;padding:22px;animation:pop .18s ease-out;
  transition:background-color .3s ease,color .3s ease}
.modal h2{margin:0 0 4px;font-size:20px;color:var(--edf-blue)}
html[data-theme="dark"] .modal h2{color:#9BC2FF}
.modal .sub{font-size:13px;color:var(--on-surface-var);margin-bottom:14px}
.modal .field{margin:14px 0}
.modal .modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}
.favlist{display:flex;flex-direction:column;gap:4px;max-height:200px;overflow:auto}
.favlist .item{display:flex;align-items:center;gap:8px;padding:6px 4px;border-radius:12px}
.favlist .item span.name{flex:1}
.plantlist .item{display:flex;align-items:center;gap:8px;padding:6px 4px}
.plantlist .item span{flex:1}
select{background:var(--surface);color:var(--on-surface);border:1px solid var(--outline);
  border-radius:12px;padding:10px 12px;font-size:14px;width:100%;font-family:inherit}
input[type=password]{background:var(--surface);color:var(--on-surface);border:1px solid var(--outline);
  border-radius:12px;padding:10px 12px;font-size:15px;width:100%;font-family:inherit}
.switch{position:relative;width:50px;height:30px;flex:0 0 auto}
.switch input{opacity:0;width:0;height:0}
.switch .tr{position:absolute;inset:0;border-radius:999px;background:var(--outline-var);
  border:2px solid var(--outline);transition:.2s;cursor:pointer}
.switch .tr::before{content:"";position:absolute;left:4px;top:4px;width:18px;height:18px;border-radius:50%;
  background:var(--on-surface-var);transition:.2s}
.switch input:checked + .tr{background:var(--primary);border-color:var(--primary)}
.switch input:checked + .tr::before{background:var(--on-primary);transform:translateX(20px)}

/* ---------- Footer ---------- */
#appFooter{text-align:center;margin-top:26px;padding:14px 0 6px;font-size:12px;color:var(--on-surface-var);opacity:.75}
/* En mobile, le numéro de version passe sur sa propre ligne sous le crédit
   (nom devenu plus long avec 2 auteurs) ; inchangé (une seule ligne) au-delà
   de 640px. */
@media (max-width:640px){
  #appFooter .footer-sep{display:none}
  #appFooter .footer-version{display:block;margin-top:2px}
}

/* ---------- Snackbar ---------- */
#snackbar{position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(80px);
  background:var(--edf-blue);color:#fff;border-radius:8px;padding:12px 18px;font-size:14px;
  box-shadow:var(--elev3);z-index:200;opacity:0;transition:.25s;max-width:90vw;
  display:flex;gap:10px;align-items:center;justify-content:center;text-align:center}
#snackbar.show{opacity:1;transform:translateX(-50%)}
#snackbar #snackIcon{font-size:20px;flex:0 0 auto}
#snackbar #snackText{flex:1}
#snackbar .act{color:var(--edf-yellow);font-weight:700;cursor:pointer;white-space:nowrap}

@media (max-width:640px){
  header .clock{display:none}
  header .title{font-size:16px}
  main{padding:12px}
  #refreshBtn{padding:0;width:40px;justify-content:center}
  #refreshBtn .btn-label{display:none}
}

/* ---------- F7 - Indicateur de rôle ---------- */
.role-badge{flex:0 0 auto;font-size:11.5px;font-weight:700;padding:5px 10px;border-radius:999px;
  letter-spacing:.2px;white-space:nowrap}
.role-badge.ro{background:rgba(255,255,255,.16);color:#fff}
.role-badge.op{background:var(--ok-container);color:var(--on-ok-container)}
.role-badge.admin{background:var(--primary-container);color:var(--on-primary-container)}
.role-badge.plus{background:var(--ko-container);color:var(--on-ko-container)}
@media (max-width:640px){ .role-badge{display:none} }

/* ---------- D3 - Micro-animation changement de statut ---------- */
/* Ne touche pas à l'animation continue "respiration" des points ok/ko : cible
   uniquement la carte (contour), en un seul passage (pas infini). */
.card.status-changed{animation:statusPulse .9s ease-out}
@keyframes statusPulse{
  0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--primary) 45%,transparent)}
  70%{box-shadow:0 0 0 14px color-mix(in srgb,var(--primary) 0%,transparent)}
  100%{box-shadow:var(--elev1)}
}
@media (prefers-reduced-motion:reduce){ .card.status-changed{animation:none} }

/* ---------- Design 5 - Transition douce sur le contenu qui change ---------- */
/* Complète le halo ci-dessus (D3) : le badge + les détails (durée restante,
   horaires...) qui viennent de changer apparaissent en fondu avec un léger
   déplacement, au lieu d'un rafraîchissement instantané. */
.statusrow.flip-in, .body.flip-in{animation:flipIn .32s ease-out}
@keyframes flipIn{
  0%{opacity:0; transform:translateY(-4px)}
  100%{opacity:1; transform:translateY(0)}
}
@media (prefers-reduced-motion:reduce){ .statusrow.flip-in, .body.flip-in{animation:none} }

/* ---------- D6 - Skeleton loading ---------- */
.cards-zone.syncing{opacity:.5;transition:opacity .15s;pointer-events:none}
.skeleton-card{gap:10px}
.skeleton-card .sk{background:linear-gradient(90deg,var(--surface-var) 25%,var(--outline-var) 37%,var(--surface-var) 63%);
  background-size:400% 100%;border-radius:8px;animation:skShimmer 1.4s ease infinite}
.skeleton-card .sk-title{height:18px;width:55%;margin-bottom:6px}
.skeleton-card .sk-badge{height:22px;width:90px;border-radius:999px;margin-bottom:14px}
.skeleton-card .sk-line{height:12px;width:80%;margin-bottom:8px}
@keyframes skShimmer{0%{background-position:100% 0}100%{background-position:0 0}}
@media (prefers-reduced-motion:reduce){ .skeleton-card .sk{animation:none} }

/* ---------- D7 - Illustration état vide ---------- */
.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
  padding:36px 20px;color:var(--on-surface-var);text-align:center}
.empty-state p{margin:0;font-size:14px}

/* ---------- Chronologie : squelette de chargement (option C retenue) ----------
   Affiché uniquement tant que loadEvents() n'a pas encore répondu (voir
   EVENTS_LOADING dans script.js), pour ne plus afficher à tort "Rien à
   afficher ici pour le moment." pendant ce court instant. */
.evt-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  padding:60px 20px;color:var(--on-surface-var)}
.evt-spinner{width:34px;height:34px;border-radius:50%;border:3px solid var(--outline-var);
  border-top-color:var(--edf-blue);animation:evtSpin .8s linear infinite}
@keyframes evtSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){ .evt-spinner{animation:none} }


/* ---------- E1 - Aide raccourcis clavier ---------- */
.shortcut-item{display:flex;align-items:center;gap:12px;padding:8px 0;font-size:13.5px}
.shortcut-item+.shortcut-item{border-top:1px solid rgba(128,128,128,.18)}
.shortcut-item .key{flex:0 0 auto;min-width:64px;text-align:center;font-family:monospace;font-weight:700;
  font-size:12px;background:var(--surface-var);border:1px solid var(--outline);border-radius:8px;padding:4px 8px}

/* ---------- E4 - Glisser-déposer tactile amélioré ---------- */
/* Cible tactile agrandie (44px min., recommandation d'accessibilité) sans
   changer la taille visuelle de l'icône ni la mécanique (Pointer Events déjà
   en place, touch-action:none déjà présent). */
.drag-handle{padding:11px;margin:-11px;border-radius:50%;touch-action:none}
.drag-handle:active{background:rgba(128,128,128,.15)}

/* ---------- F10 - Webhook : cases à cocher ---------- */
.checkline{display:flex;align-items:center;gap:8px;font-size:13.5px;margin:8px 2px;cursor:pointer}
.checkline input{width:16px;height:16px;flex:0 0 auto}

/* ---------- Design #2 - Vue focus plein écran (double-clic sur une card) ---------- */
.card{cursor:pointer}
.focus-card{max-width:560px;padding:36px;position:relative;overflow:hidden}
.focus-card .head{display:flex;align-items:center;gap:12px;margin-bottom:18px}
.focus-card .dot{width:20px;height:20px;flex:0 0 auto}
.focus-card h2{margin:0;font-size:30px;flex:1;color:var(--on-surface)}
.focus-card .badge{font-size:16px;padding:8px 18px;border-radius:999px;font-weight:700}
.focus-card .badge.ok{background:var(--ok-container);color:var(--on-ok-container)}
.focus-card .badge.ko{background:var(--ko-container);color:var(--on-ko-container)}
.focus-card .body .line{display:flex;align-items:center;gap:8px;font-size:16px;margin-top:14px;color:var(--on-surface-var)}
.focus-card .msr{font-size:26px}
/* Fermer + Notifications rejoignent la ligne "Mis à jour le..." (bas-droite),
   plus aucun bouton en position flottante/absolue. */
.focus-card .footline{display:flex;align-items:center;gap:6px;margin-top:16px}
.focus-card .footline .hint{flex:1;margin-top:0}
.focus-card .footline .iconbtn{width:34px;height:34px}
/* Design 6 - Numéro de tranche en filigrane, repris dans la grande card
   (coin haut-droit, comme sur les petites cards) : rien pour les Codex. */
.focus-card .watermark{position:absolute;top:-18px;right:-8px;font-size:130px;font-weight:800;
  color:var(--on-surface);opacity:.05;line-height:1;user-select:none;pointer-events:none;z-index:0}
html[data-theme="dark"] .focus-card .watermark{opacity:.08}
.focus-card .head,.focus-card .badge,.focus-card .body,.focus-card .focusExtra,.focus-card .hint{position:relative;z-index:1}

/* Vue focus (v2.2) : Téléphone + Informations (selon Disponible/Indisponible
   ou Ouvert/Fermé), édition au clic sur le crayon, réservée à Opérateur+. */
.focusExtra{margin-top:18px;padding-top:16px;border-top:1px dashed var(--outline)}
.focusFieldRow{display:flex;align-items:center;gap:10px;margin-top:12px}
.focusFieldRow:first-child{margin-top:0}
.focusFieldRow .msr{font-size:20px;color:var(--on-surface-var);flex:0 0 auto}
.focusField{flex:1;min-width:0}
.focusFieldLabel{font-size:11.5px;text-transform:uppercase;letter-spacing:.03em;color:var(--on-surface-var);margin-bottom:3px}
.focusFieldVal{font-size:15px;color:var(--on-surface);word-break:break-word}
.focusFieldVal.muted{color:var(--on-surface-var);font-style:italic}
.focusFieldRow input[type=tel],.focusFieldRow textarea{
  background:var(--surface);color:var(--on-surface);border:1px solid var(--outline);
  border-radius:10px;padding:8px 10px;font-size:14px;width:100%;font-family:inherit
}
.focusFieldRow textarea{resize:vertical;min-height:52px;margin-top:4px}
.focusSubtabs{display:flex;gap:6px;margin-bottom:2px}
.focusSubtab{background:transparent;border:1px solid var(--outline);color:var(--on-surface-var);
  padding:4px 12px;border-radius:999px;cursor:pointer;font-size:12.5px;font-weight:600}
.focusSubtab.sel{background:var(--primary-container);color:var(--on-primary-container);border-color:transparent}
