
/* palette corporate SdV : reprise des couleurs de marque du site institutionnel
   (https://www.sdv.fr/, variables --wp--preset--color--* de son theme.json) plutot que la
   precedente palette "salle machine" (planche technique / ardoise+ambre). Le site vitrine est
   lui-meme en theme sombre par defaut (base #071729) - le mode sombre ci-dessous en est donc la
   reprise directe ; le mode clair est une adaptation (le site vitrine n'en propose pas) sur les
   memes teintes (primary #1d6389) assombries pour rester lisibles sur fond clair.
   --accent-contrast reste distinct de --text : le bleu primaire clair passe en texte blanc, mais
   le bleu primary-light sombre a besoin d'un texte fonce pour rester lisible dessus. */
:root {
  --bg: #eef2f6;
  --surface: #ffffff;
  --surface-raised: #f4f6f8;
  --border: #cdd7e0;
  --border-strong: #8aa3b8;
  --text: #0d283e;
  --text-dim: #4a6178;
  --accent: #1d6389;
  --accent-hover: #164d6b;
  --accent-tint: #dce9f1;
  --accent-contrast: #ffffff;
  --danger: #9a3355;
  --danger-tint: #f2dde3;
  --success: #1f6e5c;
  --mark-bg: #fff3a0;
  --mark-text: #000000;
  --font: 'Sora', ui-sans-serif, system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", Consolas, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #071729;
    --surface: #0d283e;
    --surface-raised: #12314a;
    --border: #184d6b;
    --border-strong: #2d6a8c;
    --text: #dfe1e3;
    --text-dim: #8aa3b8;
    --accent: #5e97b7;
    --accent-hover: #79aecb;
    --accent-tint: #16374f;
    --accent-contrast: #071c2b;
    --danger: #d8637f;
    --danger-tint: #3a1520;
    --success: #4bc2a8;
    --mark-bg: #6b5314;
    --mark-text: #ffe9a8;
  }
}
:root[data-theme="dark"] {
  --bg: #071729;
  --surface: #0d283e;
  --surface-raised: #12314a;
  --border: #184d6b;
  --border-strong: #2d6a8c;
  --text: #dfe1e3;
  --text-dim: #8aa3b8;
  --accent: #5e97b7;
  --accent-hover: #79aecb;
  --accent-tint: #16374f;
  --accent-contrast: #071c2b;
  --danger: #d8637f;
  --danger-tint: #3a1520;
  --success: #4bc2a8;
  --mark-bg: #6b5314;
  --mark-text: #ffe9a8;
}

/* Specific styles for Chrome */
@media screen and (-webkit-min-device-pixel-ratio:0) {
  select {
    /* Chrome-specific styles here */
    font-size: 12px;
  }
}

/* Specific styles for Firefox */
@supports (-moz-appearance:none) {
  select {
    /* Firefox-specific styles here */
    font-size: 11px;
    * { margin: 0; padding: 0; }
  }
}

html          {overflow-y: scroll;} /* barre verticale toujours reservee : ouvrir/fermer une description
                                        (ajout de contenu en flux normal) ne doit pas faire apparaitre/
                                        disparaitre la barre et donc changer la largeur dispo des graphes
                                        (redessin en cascade via le plugin de resize de Flot) */
body          {
  font-family: var(--font);
  font-size: 12pt;
  color: var(--text);
  margin: 0;
  background: var(--bg);
}
a             {color: var(--accent); text-decoration: underline;}
a:hover       {color: var(--accent-hover);}
select {
    width: 250px;
    box-sizing: content-box;
}
/* dans la sidebar, les select suivent sa largeur (compacte) plutot qu'une largeur fixe pensee
   pour l'ancienne colonne 300px - cf .sidebar select plus bas. */

.button {
  position: relative;
  display: block;
  width: 180px;
  height: 32px;
  border-radius: 3px;
  background-color: var(--accent);
  border: solid 1px var(--accent-hover);
  color: var(--accent-contrast);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
  transition: background-color .1s ease-in-out;
}
.button:hover {
  background-color: var(--accent-hover);
  transition: background-color .1s ease-in-out;
}

/* liste a lignes cliquables au-dessus des <select multiple> "selecthost"/"selectgraph" (cachees,
   cf sync_checklist_from_select() dans js/sdv-graphs-gui.js) - le multi-select natif exige
   ctrl/cmd+clic pour selectionner plusieurs entrees, un piege d'ergonomie peu decouvrable. Un
   clic sur une ligne bascule sa selection (surlignage bleu), pas de case a cocher visible. */
.sdv-checklist {
  width: 100%;
  height: 220px;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  background-color: var(--surface-raised);
  border-radius: 3px;
  border: 1px solid var(--border);
  box-sizing: border-box;
  padding: 2px;
}
.sdv-checklist-row {
  display: block;
  padding: 1px 6px;
  line-height: 1.3;
  color: var(--text);
  font-size: 11px;
  cursor: pointer;
  border-left: 3px solid transparent;
  /* colonne compacte : un nom d'hote/graphe trop long defile horizontalement plutot que de
     forcer une barre de defilement sur toute la liste - on tronque avec "..." (le libelle
     complet reste visible via l'attribut title, cf sync_checklist_from_select() dans
     js/sdv-graphs-gui.js). */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sdv-checklist-row:hover {
  background-color: var(--surface);
}
.sdv-checklist-row-selected {
  background-color: var(--accent-tint);
  border-left-color: var(--accent);
  font-weight: bold;
}
/* listes serveurs/graphiques : au survol, la checklist s'elargit pour afficher les noms en
   entier (plutot que tronques par .sdv-checklist-row) et faciliter le clic sur la bonne ligne.
   .sdv-checklist-hoverbox reserve la hauteur normale (position:relative + hauteur fixe) pour que
   rien ne bouge dans la colonne quand la checklist passe en position:absolute au survol - sans
   cette reservation, la colonne se recroquevillerait des la sortie du flux normal. */
.sdv-checklist-hoverbox {
  position: relative;
}
#selecthost-checklist:hover,
#selectgraph-checklist:hover {
  position: absolute;
  top: 0;
  left: 0;
  width: max-content;
  min-width: 100%;
  max-width: min(420px, calc(100vw - 24px));
  z-index: 30;
  box-shadow: 0 4px 14px rgba(0,0,0,0.35);
}
/* surlignage des correspondances de recherche (picker hotes/graphiques) - via variables de
   theme, pas un jaune fixe (--mark-bg/--mark-text) : un jaune vif identique en clair et en
   sombre est confortable sur fond blanc mais eblouissant/agressif une fois pose sur le bleu
   marine du mode sombre, d'ou un ton plus assourdi cote sombre. color explicite (pas
   "inherit") : le texte de la ligne passe en clair sur fond sombre, ce qui rendrait un mark
   jaune illisible sans texte adapte au fond du mark lui-meme. */
mark {
  background-color: var(--mark-bg);
  color: var(--mark-text);
}

div.sticky {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  padding: 0px;
  background-color: var(--surface);
  border: 0px solid var(--border-strong);
  border-bottom-width: 1px;
  width: 100%;
  height: 24px;
  z-index: 1000;
  color: var(--text);
  font-family: var(--font); font-size: 12pt;
}

.legendColorBox div div
{
    border-width: 3px !important;
}

/* bouton "Personnaliser la selection" / "Terminer..." de la barre sticky - seul controle pour
   entrer/sortir du mode de choix, pour tous les fichiers/hotes affiches a la fois (cf
   toggle_all_subgraph_pickers() dans js/gui/subgraph_layout.js et js/gui/render.js) - aucun
   bouton equivalent n'est repete par fichier. La bascule tous/selection est un interrupteur
   distinct (cf .sdv-sticky-view-switch plus bas) avec un vocabulaire different pour ne pas se
   confondre avec ce bouton. */
/* lien "Réinitialiser" a cote du label "Graphiques :" dans la sidebar (cf reset_graph_selection()
   dans js/gui/picker.js) : discret (petit, muted) plutot qu'un vrai bouton, puisque l'action reste
   secondaire face au picker de graphes lui-meme juste en dessous. */
.sdv-graph-reset-link {
  margin-left: 8px;
  font-weight: normal;
  font-size: 11px;
  color: var(--text-dim) !important;
  text-decoration: underline;
  cursor: pointer;
}
.sdv-graph-reset-link:hover {
  color: var(--accent) !important;
}

.sdv-sticky-picker-toggle {
  cursor: pointer;
  font-weight: bold;
  color: var(--accent-contrast) !important;
  background-color: var(--accent);
  padding: 3px 10px;
  border-radius: 3px;
  border: 1px solid var(--accent-hover);
  font-family: var(--font);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-decoration: none !important;
}
.sdv-sticky-picker-toggle:hover {
  background-color: var(--accent-hover);
}
/* interrupteur "Tous / Selection" (cf sg_subgraph_view_mode, view_switch_html dans
   feed_sticky(), js/gui/render.js) : 2 etats toujours visibles cote a cote, l'etat actif mis en
   avant comme dans .sdv-sticky-menu-item-active plus bas mais sans menu a ouvrir - c'est
   l'action de loin la plus utilisee des reglages secondaires, elle doit rester a un seul clic. */
.sdv-sticky-view-switch {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow: hidden;
}
.sdv-sticky-view-switch-item {
  display: inline-block;
  cursor: pointer;
  font-weight: bold;
  color: var(--text-dim) !important;
  background-color: transparent;
  padding: 3px 10px;
  font-family: var(--font);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-decoration: none !important;
}
.sdv-sticky-view-switch-item:hover {
  background-color: var(--accent-tint);
  color: var(--accent) !important;
}
.sdv-sticky-view-switch-item-active {
  background-color: var(--accent);
  color: var(--accent-contrast) !important;
  cursor: default;
}
.sdv-sticky-view-switch-item-active:hover {
  background-color: var(--accent);
  color: var(--accent-contrast) !important;
}

/* menu deroulant "Trier ▾" de la sticky bar (cf toggle_sticky_menu()/feed_sticky() dans
   js/gui/render.js) : regroupe le choix entre etats mutuellement exclusifs (par hote/par graphe)
   derriere un bouton discret. */
.sdv-sticky-menu {
  position: relative;
  display: inline-block;
}
.sdv-sticky-menu-btn {
  cursor: pointer;
  font-weight: bold;
  color: var(--text-dim);
  background-color: transparent;
  padding: 3px 10px;
  border-radius: 3px;
  border: 1px solid var(--border);
  font-family: var(--font);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.sdv-sticky-menu-btn:hover {
  background-color: var(--surface-raised);
  color: var(--text);
}
/* auto-reload actif (cf feed_sticky() dans js/gui/render.js) : le bouton lui-meme reste visible
   en permanence (pas seulement son panneau deroulant) pour rappeler que le suivi live tourne,
   meme le panneau ferme - meme traitement visuel que .sdv-sticky-menu-item-active. Le fond sert
   aussi de barre de progression avant le prochain tick (cf update_auto_reload_progress() dans
   js/gui/render.js) : la variable --ar-progress (posee en style inline sur le bouton par JS,
   100% a 0%) fait reculer la teinte "active" de droite a gauche au fil du temps - remplace une
   barre separee sous le bouton (premiere version), qui desalignait la ligne de boutons de la
   sticky bar avec les autres a sa gauche (hauteur en plus rien que pour ce bouton). */
.sdv-sticky-menu-btn-active {
  background-color: var(--surface);
  background-image: linear-gradient(to right, var(--accent-tint) var(--ar-progress, 100%), var(--surface) var(--ar-progress, 100%));
  transition: background-image 0.25s linear;
  color: var(--accent);
  border-color: var(--accent);
}
.sdv-sticky-menu-btn-active:hover {
  color: var(--accent);
}
.sdv-sticky-menu-panel {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 4px;
  display: flex;
  flex-direction: column;
  min-width: 220px;
  padding: 4px;
  background-color: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
  text-align: left;
  z-index: 2000;
}
.sdv-sticky-menu-item {
  display: block;
  padding: 6px 10px;
  color: var(--text) !important;
  font-weight: normal;
  text-transform: none;
  letter-spacing: normal;
  font-size: 12px;
  white-space: nowrap;
  border-radius: 3px;
  text-decoration: none !important;
}
.sdv-sticky-menu-item:hover {
  background-color: var(--accent-tint);
}
/* reglage actuellement actif : mis en avant plutot que cliquable, pour montrer l'etat courant
   sans laisser croire qu'un clic ferait quelque chose (cf commentaire sur menu_items dans
   feed_sticky(), js/gui/render.js). Le groupement d'hotes reste cliquable meme actif (c'est un
   simple on/off, pas un choix entre plusieurs entrees exhaustives comme le tri), d'ou le
   curseur pointeur laisse actif sur .sdv-sticky-menu-item quelle que soit sa nature. */
.sdv-sticky-menu-item-active {
  background-color: var(--accent-tint);
  color: var(--accent) !important;
  font-weight: bold;
}
span.sdv-sticky-menu-item-active {
  cursor: default;
}
/* taux d'auto-reload indisponible pour la fenetre affichee actuelle (> 24h, cf feed_sticky() dans
   js/gui/render.js) : grise et non cliquable, distinct de .sdv-sticky-menu-item-active (qui reste
   colore/en avant car c'est un etat choisi, pas une option indisponible). */
.sdv-sticky-menu-item-disabled {
  color: var(--text-dim) !important;
  opacity: 0.5;
  cursor: not-allowed;
}
.sdv-sticky-menu-item-disabled:hover {
  background-color: transparent;
}
/* bouton "Auto-reload" quand la fenetre affichee depasse 24h (cf feed_sticky() dans
   js/gui/render.js) : distinct de l'etat de repos normal pour que la raison de l'indisponibilite
   soit visible sans avoir besoin de survoler le bouton ou d'ouvrir son menu. */
.sdv-sticky-menu-btn-unavailable {
  color: var(--text-dim);
  opacity: 0.6;
  cursor: not-allowed;
}
.sdv-sticky-menu-btn-unavailable:hover {
  background-color: transparent;
  color: var(--text-dim);
}

/* mode "regrouper par sous-graphe" (cf draw_sdv_graphs()/apply_subgraph_group_order() dans
   js/sdv-graphs-gui.js) : un wrapper flex par fichier, ses enfants directs sont les conteneurs
   par hote passes en display:contents - leurs propres cartes deviennent alors des flex-items du
   wrapper, reordonnables individuellement via "order" (assigne par render_subgraphs()) sans
   jamais deplacer de noeuds DOM. */
.sdv-subgraph-group {
  display: flex;
  flex-direction: column;
}
.sdv-subgraph-group-host {
  display: contents;
}

/* separateur affiche entre chaque fichier/section lorsque plusieurs grilles de choix se
   suivent (cf render_subgraph_picker() dans js/sdv-graphs-gui.js) - couleur/fond distincts du
   corps blanc de la carte pour bien marquer la coupure avant la grille suivante. */
.sdv-subgraph-picker-section-title {
  font-size: 13px;
  font-weight: bold;
  color: var(--text-dim);
  background-color: var(--surface-raised);
  padding: 6px 8px;
  margin: 0 0 8px 0;
  border-top: 1px solid var(--border);
  border-bottom: 2px solid var(--accent);
}

/* grille de miniatures cliquables (mode "choix des sous-graphes") - 4 colonnes pour voir un
   maximum de sous-graphes d'un coup pendant la selection, degrade a moins de colonnes sur
   ecran etroit (meme seuil que .sidebar plus haut). */
.sdv-subgraph-picker-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 6px;
}
@media (max-width: 860px) {
  .sdv-subgraph-picker-grid { grid-template-columns: repeat(2, 1fr); }
}
.sdv-subgraph-picker-cell {
  position: relative;
  cursor: pointer;
  background-color: var(--surface);
  border-radius: 3px;
  padding: 4px;
  box-sizing: border-box;
  border: 2px solid transparent;
}
.sdv-subgraph-picker-cell:hover {
  border-color: var(--border-strong);
}
.sdv-subgraph-picker-cell-selected {
  border-color: var(--success);
}
.sdv-subgraph-picker-cell-selected:hover {
  border-color: var(--success);
}
.sdv-subgraph-picker-cell-unselected {
  border-color: var(--danger);
  opacity: 0.45;
}
.sdv-subgraph-picker-cell-unselected:hover {
  border-color: var(--danger);
}
.sdv-subgraph-picker-canvas {
  /* plus grande qu'avant : sans graduations/libelles d'axe (cf draw_subgraph_thumbnail() dans
     js/sdv-graphs-gui.js) l'espace ainsi libere revient au trace lui-meme. */
  height: 120px;
}
.sdv-subgraph-picker-caption {
  font-size: 10px;
  color: var(--text-dim);
  text-align: center;
  margin-top: 2px;
  /* le titre du sous-graphe doit rester entierement lisible pendant la selection - on prefere
     le voir passer sur plusieurs lignes plutot que le tronquer avec "..." */
  white-space: normal;
  line-height: 1.2;
}
.sdv-subgraph-picker-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 14px;
  height: 14px;
  line-height: 14px;
  text-align: center;
  font-size: 9px;
  color: #fff;
  border-radius: 50%;
}
.sdv-subgraph-picker-badge-selected {
  background-color: var(--success);
}
.sdv-subgraph-picker-badge-unselected {
  background-color: var(--danger);
}

/* message affiche a la place des sous-graphes quand la vue "Selection" (cf sg_subgraph_view_mode,
   render_no_selection_hint() dans js/gui/subgraph_layout.js) ne trouve rien a montrer pour un
   fichier - pour ne pas laisser croire a une panne face a une zone silencieusement vide. */
.sdv-no-selection-hint {
  background-color: var(--surface-raised);
  border: 1px dashed var(--border-strong);
  border-radius: 4px;
  padding: 16px;
  margin-bottom: 6px;
  color: var(--text-dim);
  font-size: 13px;
  text-align: center;
}
.sdv-no-selection-hint p {
  margin: 6px 0;
}
.sdv-no-selection-hint a {
  color: var(--accent) !important;
  cursor: pointer;
}

/* bouton deplier/replier le detail par partition (cf detail_tag_regex dans graph_definition/*.php,
   render_detail_toggle()/toggle_detail_subgraphs() dans js/gui/subgraph_layout.js) - un seul par
   fichier, toujours pousse apres tous les sous-graphes visibles de tous les hotes (cf order=999999
   dans apply_subgraph_group_order()). Meme pastille que .sdv-sticky-menu-btn (menu "Trier" de la
   barre sticky) plutot qu'un lien souligne brut, pour rester dans le meme vocabulaire visuel que
   les autres petits controles secondaires de l'appli. */
.sdv-detail-toggle {
  margin: 4px 0 14px 0;
  text-align: center;
}
.sdv-detail-toggle-btn {
  display: inline-block;
  cursor: pointer;
  font-weight: bold;
  color: var(--text-dim);
  background-color: transparent;
  padding: 3px 10px;
  border-radius: 3px;
  border: 1px solid var(--border);
  font-family: var(--font);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-decoration: none !important;
}
.sdv-detail-toggle-btn:hover {
  background-color: var(--surface-raised);
  color: var(--text) !important;
}

/* tooltip maison au survol d'un graphe (toutes les series a l'heure survolee) - cf
   show_multiseries_tooltip() dans js/sdv-graphs-gui.js, remplace le tooltip mono-serie du
   plugin jquery.flot.tooltip.js (desactive dans draw_graph()). Couleur de texte explicite,
   independante du "color: white" global de la page (cf commentaire dans
   js/flot-plugins/jquery.flot.tooltip.js sur le meme piege). */
.sdv-graph-tooltip {
  display: none;
  position: absolute;
  /* doit rester au-dessus de la carte en plein ecran (zIndex:99999, cf toggle_fullscreen()
     dans js/gui/render.js) - le tooltip est un enfant de <body>, pas de la carte, donc sans
     ca il se retrouvait empile derriere elle des que le graphe passait en plein ecran. */
  z-index: 100000;
  background-color: #fff;
  color: #222;
  border: 1px solid #111;
  border-radius: 3px;
  padding: 6px 10px;
  font-size: 12px;
  font-family: arial, Helvetica, sans-serif;
  white-space: nowrap;
  pointer-events: none;
}
.sdv-graph-tooltip-date {
  font-weight: bold;
  margin-bottom: 4px;
  border-bottom: 1px solid #ddd;
  padding-bottom: 2px;
}
.sdv-graph-tooltip-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.sdv-graph-tooltip-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  flex-shrink: 0;
  border: 1px solid rgba(0,0,0,0.3);
}

/* tooltip explicatif thematise (boutons/liens de la sticky bar, du toolbar de graphe, de la
   sidebar...) : remplace l'attribut title= natif du navigateur, dont le popup noir/blanc ne suit
   jamais le theme clair/sombre de la page (cf :root / [data-theme] en haut de fichier). Le texte
   est porte par data-tooltip et affiche via ::after au survol/focus - conserver aria-label en
   parallele sur les elements sans texte visible (ex: bouton sidebar "«") pour garder un nom
   accessible, data-tooltip seul n'etant pas lu par les lecteurs d'ecran. Ne pas utiliser sur des
   elements dans un conteneur a overflow:hidden/auto (ex: .sdv-checklist-row) : le popup y serait
   tronque, garder title= natif dans ce cas. */
[data-tooltip] {
  position: relative;
}
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  background-color: var(--surface-raised);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  padding: 5px 8px;
  font-size: 11px;
  font-weight: normal;
  text-transform: none;
  letter-spacing: normal;
  font-family: var(--font);
  white-space: normal;
  width: max-content;
  max-width: 260px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
  z-index: 100001;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .12s ease;
}
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
  opacity: 1;
  visibility: visible;
}
/* variante pour un element colle en haut a droite de l'ecran (ex: .sdv-theme-toggle, top:8px;
   right:8px) : le popup par defaut (au-dessus, centre) sortirait alors du viewport par le haut
   et par la droite - celui-ci s'affiche en dessous et aligne a droite sur le bord du bouton. */
[data-tooltip].sdv-tooltip-below-right::after {
  top: 100%;
  bottom: auto;
  left: auto;
  right: 0;
  transform: translateY(6px);
}
/* variante pour un element colle en bas a droite d'une carte de graphe (ex: .sdv-graph-toolbar,
   bottom:4px;right:4px) : le popup par defaut (au-dessus, centre) deborderait a droite du
   viewport (carte quasi collee au bord droit) et provoquerait une barre de defilement
   horizontale permanente (l'element est visibility:hidden, pas display:none, donc toujours
   compte dans le flux/overflow du document). */
[data-tooltip].sdv-tooltip-above-right::after {
  left: auto;
  right: 0;
  transform: translateY(-6px);
}

/* indicateur de chargement (requetes data.php en vol, cf update_loading_indicator() dans
   js/gui/render.js) - juste a gauche du bouton de theme (.sdv-theme-toggle, top:8px;right:8px;
   30x30), meme gabarit pour former un seul groupe de controles overlay en haut a droite. Une
   simple icone qui tourne (.sdv-spinner) plutot que le texte "Chargement..." d'origine : plus
   compact, se lit au premier coup d'oeil sans avoir a lire un mot a chaque requete. */
.loading {
  display: none;
  position: fixed;
  top: 8px;
  right: 42px;
  z-index: 100001;
  width: 30px;
  height: 30px;
  background-color: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
}
.sdv-spinner {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: sdv-spin 0.7s linear infinite;
}
@keyframes sdv-spin {
  to { transform: rotate(360deg); }
}

/* --- mise en page sans frameset : sidebar (ex-menu.php+copyright.php) + zone de graphes
   (ex-draw_graphs.php) cote a cote, remplace <frameset cols="300,*"> --- */
.app {
  display: grid;
  /* les 2 sous-sections (hotes/filtres, graphiques) sont empilees verticalement dans la
     sidebar (cf .sidebar-columns) et non plus cote a cote - une seule colonne pleine
     largeur n'a plus besoin des 440px reserves pour loger 2 sous-colonnes ~205px chacune. */
  grid-template-columns: 260px 1fr;
  align-items: start;
}
/* la sidebar empile ses 2 sous-sections verticalement : hotes/filtres (recherche, serveurs,
   periode, niveau) puis liste des graphiques en dessous - l'ordre suit celui du HTML. */
.sidebar-columns {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1 1 auto;
  min-height: 0;
}
.sidebar-col {
  /* taille naturelle par defaut (ne pousse ni ne rogne son contenu) - seule .sidebar-col-graphs
     ci-dessous absorbe l'espace restant, cf commentaire dessus. */
  flex: 0 0 auto;
  min-width: 0;
}
/* colonne "Graphiques" seule : s'adapte a l'espace restant sous la colonne "Serveurs" (taille
   fixe au-dessus) pour que la sidebar tienne dans les 100vh de .sidebar sans jamais depasser le
   bas de l'ecran. Comme la checklist "Serveurs" (cf scroll_checklist_row_into_view() dans
   js/gui/picker.js), elle garde son propre ascenseur une fois reduite a son plancher
   (min-height ci-dessous) : on ne peut pas se permettre de rendre des graphes inatteignables en
   les recroquevillant sans scroll. */
.sidebar-col-graphs {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  /* sans ce clip, quand l'espace dispo tombe sous le plancher (min-height:60px) de la
     hoverbox ci-dessous, le contenu deborde en dehors de la boite de .sidebar (position:sticky,
     height:100vh) au lieu d'y rester confine - ca fait "fuir" la liste de graphes hors de la
     sidebar (rendue en dessous) et casse le ciblage du scroll (la molette finit par faire
     defiler la page entiere plutot que la checklist). */
  overflow: hidden;
}
.sidebar-col-graphs-header {
  flex: 0 0 auto;
}
.sidebar-col-graphs .sdv-checklist-hoverbox {
  flex: 1 1 auto;
  min-height: 60px;
}
#selectgraph-checklist {
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
}
/* masquage complet de la sidebar (pas seulement le tiroir mobile existant, cf media query
   plus bas) - utile une fois qu'on veut toute la largeur pour les graphes. sdv_set_cookie()/
   sdv_get_cookie() (js/sdv-graphs-gui.js) persistent l'etat entre visites. */
.app.sidebar-collapsed {
  grid-template-columns: 0 1fr;
}
.app.sidebar-collapsed .sidebar {
  display: none;
}
.sidebar-collapse-btn {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 5;
  background-color: var(--surface-raised);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  width: 20px;
  height: 20px;
  line-height: 18px;
  text-align: center;
  cursor: pointer;
  font-size: 13px;
  padding: 0;
}
.sidebar-collapse-btn:hover {
  background-color: var(--surface);
}
.sidebar-expand-btn {
  display: none;
  position: fixed;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1002;
  background-color: var(--accent);
  color: var(--accent-contrast);
  border: none;
  border-radius: 0 3px 3px 0;
  padding: 10px 5px;
  cursor: pointer;
  font-size: 13px;
}
.sidebar-expand-btn:hover {
  background-color: var(--accent-hover);
}
.app.sidebar-collapsed .sidebar-expand-btn {
  display: block;
}
.sidebar {
  /* place explicitement en 1ere colonne de la grille .app - indispensable maintenant que la
     colonne peut retomber a 0 (sidebar-collapsed) : des qu'un item precedent (.sidebar-scrim,
     display:none par defaut) sort du flux, le placement automatique glisserait sinon "main"
     dans cette 1ere colonne au lieu de la 2e (1fr). */
  grid-column: 1;
  background-color: var(--surface);
  border: 1px solid var(--border-strong);
  padding: 8px;
  box-sizing: border-box;
  /* colle en haut du viewport tant que la page defile (usuel pour une sidebar) et ne depasse
     jamais le bas de l'ecran : hauteur bloquee a 100vh (coherent avec top:0) plutot que de suivre
     le defilement normal de la page. Pas d'ascenseur interne non plus - display:flex + les
     min-height:0/flex sur .sidebar-columns/.sidebar-col/.sdv-checklist plus bas laissent les
     listes hotes/graphiques (.sdv-checklist) se comprimer pour que tout tienne dans cette hauteur. */
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-self: start;
  /* position:sticky cree son propre contexte d'empilement meme avec z-index:auto (comme
     position:fixed) - sans z-index explicite ici, ce contexte reste au niveau "0" de la grille
     .app et se retrouve alors en DESSOUS de <main> (les cartes de sous-graphes, elles aussi au
     niveau "0"), qui vient juste apres dans le DOM : les popups internes a la sidebar (checklist
     hotes/graphes au survol, z-index:30 - cf #selecthost-checklist:hover plus haut) restaient
     alors caches derriere les graphes des qu'ils debordaient visuellement de la colonne sidebar,
     quel que soit leur z-index interne (il ne compte que par rapport aux AUTRES elements internes
     a ce contexte, jamais contre l'exterieur). z-index explicite ici sort tout le sous-arbre
     sidebar (popups compris) du niveau "0" et le place au-dessus, sans toucher au plein ecran
     d'un graphe (zIndex:99999, cf toggle_fullscreen() dans js/gui/render.js) qui reste largement
     au-dessus.
  */
  z-index: 10;
  /* colonne compacte : police reduite par rapport au corps de page (12pt, pense pour les
     titres/legendes des graphes) - les libelles de la sidebar (hote, select, checklist) restent
     lisibles a 11px tout en laissant plus de place utile aux graphes. */
  font-size: 11px;
}
/* bloc "Compte: ..." (texte + <b>/<small>/<hr> en flux inline normal, genere en PHP juste avant
   #formu) - doit rester un item flex UNIQUE de .sidebar (display:flex depuis le fix hauteur
   ci-dessus), sinon chacun de ses enfants directs (noeuds de texte, <b>, <small>, <hr>) devient
   lui-meme un item flex empile verticalement (flex-direction:column) au lieu de se suivre sur la
   meme ligne comme du texte normal - c'est ce qui causait "Compte:"/"admin"/"all"/"(0)" chacun
   sur sa propre ligne. */
.sidebar-account {
  flex: 0 0 auto;
}
/* #formu, direct enfant flex de .sidebar, enveloppe .sidebar-columns - sans ces regles il garde
   sa taille naturelle (flex:0 1 auto par defaut) et .sidebar-columns n'a alors rien a comprimer,
   meme avec son propre flex:1 1 auto (cf .sidebar-columns plus bas) : la contrainte de hauteur
   doit se propager a chaque niveau flex de la chaine, pas seulement au dernier. */
.sidebar > form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
.sidebar select {
  width: 100%;
  box-sizing: border-box;
}
/* recherche + selects periode/niveau de la sidebar : meme habillage que les autres controles
   (border-radius:6px/border #AAAAAA en dur auparavant, remplace par les tokens de theme). */
.sdv-input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--surface-raised);
  color: var(--text);
  font-family: var(--font);
  padding: 4px 6px;
}
/* table-layout:fixed : ces tables n'ont qu'une seule colonne (une mise en page historique, pas
   un tableau de donnees), mais leur "width=99%" en dur + le layout "auto" par defaut du
   navigateur les laissait se dimensionner sur le contenu le plus large de la cellule (ex. le
   texte non coupe de .sdv-checklist-toolbar) plutot que sur l'espace reellement dispo dans la
   sous-colonne flex - ca poussait toute la sidebar en depassement horizontal. En layout fixe la
   largeur vient uniquement du conteneur, jamais du contenu. */
.sidebar table { margin: 0; table-layout: fixed; width: 100%; }
.sidebar .button {
  width: 100%;
  height: 26px;
  border-radius: 3px;
  font-size: 12px;
}
main {
  grid-column: 2;
  min-width: 0;
  padding: 0 6px;
}
/* bouton overlay clair/sombre/systeme (cf sdv_cycle_theme() dans js/gui/cookies_level.js) -
   toujours visible en haut a droite du viewport, y compris pendant qu'un graphe est en plein
   ecran (zIndex:99999, cf toggle_fullscreen() dans js/gui/render.js) ou que le tooltip de graphe
   est affiche (z-index:100000, cf .sdv-graph-tooltip plus haut) : c'est un controle global de la
   page, pas propre a un graphe. */
.sdv-theme-toggle {
  position: fixed;
  top: 8px;
  right: 8px;
  z-index: 100001;
  width: 30px;
  height: 30px;
  padding: 0;
  background-color: var(--surface-raised);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  font-size: 15px;
  line-height: 28px;
  text-align: center;
  cursor: pointer;
}
.sdv-theme-toggle:hover {
  background-color: var(--surface);
}
.menu-toggle {
  display: none;
  position: fixed;
  top: 8px;
  left: 8px;
  /* superieur au z-index de .sidebar (1003, cf @media plus bas) : sidebar et menu-toggle
     partagent le meme coin haut-gauche, sinon le tiroir ouvert masque et intercepte les clics
     sur le bouton qui devrait pourtant permettre de le refermer. */
  z-index: 1004;
  background-color: var(--accent);
  color: var(--accent-contrast);
  border: none;
  border-radius: 3px;
  padding: 6px 10px;
  font-size: 13px;
  cursor: pointer;
  font-family: var(--font);
}
.sidebar-scrim {
  display: none;
}

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  /* une seule colonne ici - sans ce reset, "grid-column:2" (cf regle main plus haut) creerait
     une colonne implicite en trop et decalerait le contenu. */
  .sidebar, main { grid-column: 1; }
  .menu-toggle { display: inline-block; }
  /* le repli complet de la sidebar est une fonctionnalite de bureau - sur mobile le tiroir
     (menu-toggle/scrim ci-dessus) remplit deja ce role. */
  .sidebar-collapse-btn, .sidebar-expand-btn { display: none !important; }
  .sidebar {
    position: fixed;
    inset: 0 0 0 0;
    z-index: 1003;
    width: min(320px, 82vw);
    height: 100vh;
    overflow-y: auto;
    box-shadow: 2px 0 12px rgba(0,0,0,0.35);
    transform: translateX(-105%);
    transition: transform 0.18s ease-out;
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-scrim.open {
    display: block;
    position: fixed;
    inset: 0 0 0 0;
    background: rgba(0,0,0,0.4);
    z-index: 1002;
  }
  main { padding-top: 46px; }
}

/* Pages hors application principale (formulaire de login, page compte self-service
   account.php) - mise en page carte centree plutot que le tableau brut d'origine, memes
   tokens de theme que le reste de l'appli (clair/sombre/systeme via .sdv-theme-toggle). */
.sdv-auth-page {
  min-height: 100vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 48px 20px;
  box-sizing: border-box;
}
.sdv-auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 28px 32px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
  box-sizing: border-box;
}
.sdv-auth-card + .sdv-auth-card { margin-top: 16px; }
.sdv-auth-card h1, .sdv-auth-card h2, .sdv-auth-card h3 {
  margin: 0 0 18px;
  font-size: 17px;
  color: var(--text);
  font-weight: 700;
}
.sdv-auth-card p { color: var(--text-dim); font-size: 13px; line-height: 1.5; }
.sdv-auth-field { margin-bottom: 16px; }
.sdv-auth-field label {
  display: block;
  margin-bottom: 6px;
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.sdv-auth-field input[type=text], .sdv-auth-field input[type=password] {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 10px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
}
.sdv-auth-field input:focus { outline: none; border-color: var(--accent); }
.sdv-auth-card .button { width: 100%; margin-top: 4px; }
.sdv-auth-card form + form { margin-top: 10px; }
.sdv-auth-msg {
  padding: 10px 12px;
  border-radius: 4px;
  margin-bottom: 18px;
  font-size: 13px;
}
.sdv-auth-msg.error   { background: var(--danger-tint); border: 1px solid var(--danger); color: var(--text); }
.sdv-auth-msg.success { background: var(--accent-tint); border: 1px solid var(--accent); color: var(--text); }
.sdv-auth-secret {
  display: block;
  font-family: var(--mono);
  font-size: 14px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  word-break: break-all;
  margin-bottom: 10px;
}
.sdv-auth-uri { font-size: 12px; word-break: break-all; }
.sdv-auth-hint { font-size: 12px; color: var(--text-dim); }
/* fond toujours blanc, y compris en theme sombre : un QR code a faible contraste (--surface
   sombre derriere des modules "noirs" transparents) devient difficile a scanner. */
.sdv-auth-qrcode {
  display: inline-block;
  background: #ffffff;
  padding: 12px;
  border-radius: 6px;
  margin-bottom: 12px;
  line-height: 0;
}
.sdv-auth-qrcode svg { display: block; width: 180px; height: 180px; }
.sdv-auth-codes {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 12px;
}
.sdv-auth-codes li {
  font-family: var(--mono);
  font-size: 13px;
  text-align: center;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 4px;
}
/* Liste des cles FIDO2 enregistrees (account.php) - une carte compacte par cle, distincte de
   .sdv-auth-codes (grille monospace centree, pensee pour les codes de recuperation, jamais
   adaptee a une ligne label+date+formulaire de suppression). */
.sdv-fido2-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.sdv-fido2-credential {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
}
.sdv-fido2-credential-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sdv-fido2-credential-label { font-size: 14px; font-weight: 600; color: var(--text); word-break: break-word; }
.sdv-fido2-credential-date { font-size: 12px; color: var(--text-dim); }
.sdv-fido2-credential-delete { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.sdv-fido2-credential-delete input[type=password] {
  box-sizing: border-box;
  width: 160px;
  padding: 7px 9px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font);
  font-size: 13px;
}
.sdv-fido2-credential-delete input[type=password]:focus { outline: none; border-color: var(--accent); }
.sdv-fido2-credential-delete .button { width: auto; margin-top: 0; padding: 7px 14px; font-size: 13px; }

.sdv-auth-back { display: inline-block; margin-bottom: 16px; font-size: 13px; color: var(--text-dim); }
.sdv-auth-account-summary { font-size: 13px; color: var(--text-dim); margin-bottom: 22px; }
.sdv-auth-account-summary b { color: var(--text); }

/* Vue d'ensemble de l'etat de securite du compte (account.php) : pastilles compactes plutot
   que d'obliger a lire chaque carte pour savoir si le TOTP/FIDO2 sont actifs. */
.sdv-badge-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.sdv-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}
.sdv-badge::before { content: ''; width: 7px; height: 7px; border-radius: 50%; }
.sdv-badge-on { background: var(--accent-tint); color: var(--text); }
.sdv-badge-on::before { background: var(--accent); }
.sdv-badge-off { background: var(--surface-raised); color: var(--text-dim); border: 1px solid var(--border); }
.sdv-badge-off::before { background: var(--text-dim); }
