/**
 * public/css/homelab-scene.css
 *
 * Feuille dediee a la scene 3D de topologie (public/js/homelab-scene.js).
 * Fichier separe plutot que fusionne dans la constante STYLE de
 * services/layout.js (cf. cadrage "a ton jugement, une seule source de
 * verite CSS") : cette scene n'apparait que sur 2 pages (accueil publique
 * et /admin/topologie), le reste du site n'a jamais besoin de charger ces
 * regles - inutile de les injecter inconditionnellement dans TOUTES les
 * pages via services/layout.js. Reutilise en revanche les variables CSS
 * globales deja definies par services/layout.js (--bg/--ok/--amber/
 * --danger/--mono/--text-dim/--text-faint, cf. son STYLE) plutot que de
 * les dupliquer : une seule palette de couleurs pour tout le site, cette
 * feuille est toujours chargee APRES ce <style> inline (cf. renderPage()),
 * les variables sont donc deja en portee sur :root.
 *
 * `--danger-hex`/`--ok-hex`/`--amber-hex` ne sont PAS necessaires ici :
 * les couleurs Three.js (nombres hexadecimaux) sont posees cote JS
 * (public/js/homelab-scene.js, constante COLOR) - cette feuille ne gere
 * QUE l'habillage HTML/CSS autour du <canvas> (HUD, labels, fallback).
 */

.topo-section {
  width: 100%;
  background: var(--scene-bg); /* identique au fond de la scene 3D elle-meme (cf. THEME.<theme>.bg dans homelab-scene.js) - continuite visuelle avec --bg, volontairement une valeur legerement differente mais imperceptible a l'oeil (cf. sa doc, services/layout.js) */
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  /* position:relative INCONDITIONNEL (chantier "polish v2 UX/UI -
     correctif accueil trop long") - necessaire UNIQUEMENT pour
     .topo-caption--overlay ci-dessous (ancre son position:absolute au
     coin de CE conteneur, pas de la fenetre) ; totalement inoffensif
     pour /admin/topologie (jamais en mode compact, cf.
     services/topologySection.js) - une figure en flux normal reste en
     flux normal, position:relative sans decalage ne change RIEN a son
     rendu. Pas besoin d'une regle separee/conditionnelle. */
  position: relative;
}

.topo-stage {
  position: relative;
  width: 100%;
  height: 70vh;
  min-height: 420px;
  overflow: hidden;
}

/* Scene compacte (chantier "polish v2 UX/UI - correctif accueil trop
   long", 2026-09-17) - UNIQUEMENT la page d'accueil (cf.
   services/topologySection.js::renderTopologySection, `compact`) :
   demande explicite de Kevyn en conditions reelles, "bouton d'appel a
   l'action invisible sans scroll" -> ~56vh/520px maximum au lieu de
   70vh/aucun plafond. /admin/topologie (jamais en mode compact) garde sa
   scene pleine hauteur - page dediee, rien a gagner a la retrecir la-bas.
   min-height abaisse en proportion (70vh/420px -> 56vh/360px, meme
   ratio) - reste un plancher pour les tres petites fenetres desktop,
   jamais applique en dessous de 640px (cf. media query mobile plus bas,
   qui definit SA PROPRE hauteur, deja plus petite que ce plancher). */
.topo-stage--compact {
  height: 56vh;
  min-height: 360px;
  max-height: 520px;
}

.topo-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: none; /* le drag/pinch pilote la camera lui-meme, cf. homelab-scene.js */
}
.topo-stage canvas.dragging { cursor: grabbing; }

/* BUG REEL constate en production (2026-09-05, rapporte par Kevyn : "je
   ne vois que la legende/HUD, ni le canvas ni le PNG de secours") : sans
   cette regle, `.topo-stage canvas { display:block }` ci-dessus est une
   declaration AUTEUR "normale", qui l'emporte TOUJOURS sur la regle par
   defaut du navigateur `[hidden] { display:none }` (declaration
   USER-AGENT "normale") - dans la cascade CSS, l'ORIGINE d'une
   declaration prime sur sa specificite (une regle auteur normale bat
   toujours une regle user-agent normale, quelle que soit sa
   specificite comparee). Consequence concrete : `canvas.hidden = true`
   pose par showFallback() (cf. services/topologySection.js) n'avait
   AUCUN EFFET VISUEL, le canvas restait affiche (vide/noir, WebGL
   indisponible ou init en echec) - ET, meme sans ce premier probleme,
   l'image de secours (#topo-fallback, meme bug de cascade sur
   .topo-fallback-img ci-dessous) se serait de toute facon retrouvee
   poussee hors du cadre visible par le flux normal du document (le
   canvas, jamais reellement masque, occupe deja 100% de la hauteur de
   .topo-stage - qui a overflow:hidden). Resultat net : plus rien de
   visible dans la scene, seuls les elements en position:absolute (HUD,
   hint, labels) restaient affiches - exactement le bug rapporte.
   `!important` volontaire ici : meme registre que le seul autre
   `!important` du site (prefers-reduced-motion, services/layout.js) -
   restaurer un comportement natif du navigateur qu'une regle de style
   neutralise sans le vouloir. */
.topo-stage canvas[hidden] { display: none !important; }

.topo-fallback-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Meme bug de cascade que .topo-stage canvas[hidden] ci-dessus, sur
   l'image de secours elle-meme (qui porte l'attribut `hidden` DES LE
   rendu serveur - cf. services/topologySection.js) : sans cette regle,
   #topo-fallback restait "display:block" (donc visuellement present
   dans le flux, pousse hors du cadre par le canvas au-dessus, cf. doc
   ci-dessus) AVANT MEME que le JS ne s'execute, et
   `fallback.hidden = false` (cote JS, showFallback()) n'avait de toute
   facon aucun effet propre supplementaire. */
.topo-fallback-img[hidden] { display: none !important; }

/* ---------- Labels HTML projetes (Vector3.project, cf. homelab-scene.js) ---------- */
.topo-labels {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.topo-label {
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(-50%, -100%);
  pointer-events: none;
  white-space: nowrap;
  font-family: var(--mono, monospace);
  font-size: 0.76rem;
  color: var(--text-dim);
  opacity: 0.85;
  transition: color 0.2s ease, opacity 0.2s ease;
}
.topo-label-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 6px;
  background: var(--ok);
  vertical-align: 1px;
}
.topo-label[data-status="warn"] .topo-label-dot { background: var(--amber); }
.topo-label[data-status="down"] .topo-label-dot {
  background: var(--danger);
  animation: topo-blink 1s steps(2) infinite;
}
.topo-label[data-status="unknown"] .topo-label-dot,
.topo-label[data-status="reserved"] .topo-label-dot { background: var(--text-faint); }
@keyframes topo-blink { 50% { opacity: 0.15; } }

/* opacity:0 + visibility:hidden (PAS un simple display:none) - demande
   explicite (Kevyn, capture d'ecran reelle : le panneau de detail
   "transparaissait" hors survol/tap). visibility:hidden garantit qu'il
   ne recoit jamais d'interaction ni ne "transparait" visuellement (une
   opacite proche de 0 par un bug de cascade resterait, comme
   [hidden] plus haut dans ce fichier, un piege deja rencontre sur cette
   scene - display:none seul avait deja cet effet en theorie, mais cette
   double garde ne depend d'aucune propriete "display" qu'une regle
   ulterieure pourrait re-neutraliser). position absolute + top/left
   fixes : evite que le passage display:none -> block (desormais
   visibility:hidden -> visible) ne fasse "sauter" la mise en page du
   label parent au moment du survol. */
.topo-label-detail {
  position: absolute;
  left: 0;
  top: 100%;
  opacity: 0;
  visibility: hidden;
  color: var(--text);
  font-size: 0.7rem;
  margin-top: 4px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  background: rgba(var(--scene-bg-rgb), 0.9);
  text-align: left;
  line-height: 1.5;
  transition: opacity 0.15s ease, visibility 0.15s ease;
}
.topo-label-hot,
.topo-label-pinned { color: var(--text); opacity: 1; }
.topo-label-hot .topo-label-detail,
.topo-label-pinned .topo-label-detail { opacity: 1; visibility: visible; }
.topo-label-down { color: var(--danger); }
.topo-label-warn { color: var(--amber); }
.topo-label-core { color: var(--amber); }
/* opacity relevee (0.45 -> 0.6) : constate trop discret sur capture
   d'ecran reelle, l'emplacement reserve devenait difficile a reperer -
   reste neanmoins visuellement en retrait (italique + opacite reduite)
   par rapport aux noeuds reels. */
.topo-label-reserved { opacity: 0.6; font-style: italic; }

/* ---------- Hint d'interaction (survol du canvas) ---------- */
.topo-legend i {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 5px; vertical-align: 0;
}

.topo-hint {
  position: absolute;
  right: 20px;
  top: 16px;
  color: var(--text-faint);
  font-family: var(--mono, monospace);
  font-size: 0.72rem;
  text-align: right;
}

/* ---------- Legende (chantier "polish v2 UX/UI") ----------
   <figcaption> EN FLUX NORMAL sous .topo-stage (jamais en position:absolute
   par-dessus le canvas, contrairement a l'ancien .topo-hud) - corrige la
   legende "flottante et mal positionnee" signalee au cadrage. Meme
   registre visuel que le reste du site (bg-panel/border, cf.
   services/layout.js) plutot que le fond flou/semi-transparent de
   l'ancien HUD (qui n'a plus de raison d'etre : il ne recouvre plus rien
   qu'il faudrait laisser deviner en transparence). */
.topo-caption {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
  padding: 16px 20px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-top: none; /* continuite visuelle directe avec .topo-section juste au-dessus */
  font-family: var(--mono, monospace);
}
.topo-caption-text { flex: 1 1 260px; min-width: 0; }
.topo-caption h3 {
  font-size: 0.82rem;
  font-weight: 600;
  margin: 0 0 4px;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.topo-caption p {
  margin: 0;
  font-size: 0.78rem;
  color: var(--text-dim);
}
.topo-caption .topo-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0;
  font-size: 0.72rem;
  color: var(--text-dim);
  flex: 0 0 auto;
}
/* Lien "How this scene works ->" (sceneLinkHtml, cf. services/topologySection.js) -
   meme regle globale "a" que le reste du site (services/layout.js) pour
   la couleur/soulignement, juste une taille coherente avec le reste de
   cette legende (sinon herite de la taille de police par defaut du
   document, trop grande ici). */
.topo-caption .topo-scene-link { margin: 0; flex: 0 0 100%; font-size: 0.78rem; }

/* ---------- Legende en overlay (accueil UNIQUEMENT, chantier "polish v2
   UX/UI - correctif accueil trop long", 2026-09-17) ----------
   Modificateur de .topo-caption ci-dessus (jamais un remplacement - tout
   le reste du bloc, y compris .topo-caption-text/.topo-legend/
   .topo-scene-link, reste heritee telle quelle) : sort la legende du
   flux normal et l'ancre en survol semi-transparent au coin bas-gauche
   de la scene, DANS le cadre de .topo-stage (jamais au-dela, cf.
   `right`/`bottom` calcules pour ne jamais depasser les bords du canvas
   meme sur les tres petits ecrans - la largeur reste bornee par
   `right: 16px` plutot qu'un simple `max-width` fixe). Fond
   semi-transparent (rgba(var(--scene-bg-rgb), ...), pas var(--bg-panel)
   opaque) - MEME teinte que le reste de la charte (--scene-bg, cf.
   .topo-section et sa doc dans services/layout.js) a 88% d'opacite :
   assez pour rester lisible par-dessus n'importe quel contenu 3D en
   arriere-plan (contrainte du cadrage "lisible sans gener la scene"),
   jamais totalement opaque (contrairement au flux normal ci-dessus, qui
   n'avait pas cette contrainte - rien en dessous a laisser deviner).
   `z-index` explicite : la legende est un ELEMENT SUIVANT le canvas dans
   le DOM (cf. services/topologySection.js, jamais nichee DANS
   .topo-stage - seul son CSS change ici), donc deja peinte par-dessus
   par l'ordre naturel du document, mais un remontage futur du HTML ne
   doit pas pouvoir faire disparaitre la legende derriere le canvas sans
   qu'un revert CSS explicite s'en aperçoive. */
.topo-caption--overlay {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 16px;
  z-index: 2;
  width: fit-content;
  max-width: calc(100% - 32px);
  gap: 6px 20px;
  padding: 10px 14px;
  background: rgba(var(--scene-bg-rgb), 0.88);
  border-radius: 3px;
}
.topo-caption--overlay .topo-caption-text { flex: 1 1 200px; }
.topo-caption--overlay h3 { font-size: 0.74rem; }
.topo-caption--overlay p { font-size: 0.72rem; }
.topo-caption--overlay .topo-legend { font-size: 0.68rem; gap: 8px; }
.topo-caption--overlay .topo-scene-link { font-size: 0.72rem; }

/* Mobile (<640px) : la scene compacte descend deja a 50vh/280px (regle
   mobile existante plus bas dans ce fichier) - l'overlay grignoterait
   une part trop importante d'un canvas deja petit s'il gardait titre +
   description + legende + lien en entier. La description (texte le
   moins essentiel : le titre et la legende de couleurs suffisent a
   comprendre la scene sans elle) est masquee sous ce seuil - meme
   discipline que .topo-hint ci-dessus ("molette pour zoomer" retire au
   toucher, information non critique retiree plutot que renduee
   illisible en la retrecissant encore). */
@media (max-width: 640px) {
  .topo-caption--overlay { left: 10px; right: 10px; bottom: 10px; padding: 8px 10px; }
  .topo-caption--overlay p { display: none; }
}

/* ---------- Debug (?debug=1 ou panneau admin, cf. homelab-scene.js) ---------- */
.topo-debug {
  position: absolute;
  left: 20px;
  top: 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-width: 60%;
}
/* Meme bug de cascade que .topo-stage canvas[hidden]/.topo-fallback-img[hidden]
   ci-dessus - #topo-debug porte `hidden` par defaut (cf.
   services/topologySection.js, deactive tant que `?debug=1` n'est pas
   fourni) : sans override, "display:flex" restait applique en
   permanence. Inoffensif en pratique tant que le conteneur est vide
   (aucun bouton injecte), mais meme cause racine - corrige par
   coherence et pour eviter tout futur effet de bord (ex: si le
   conteneur venait a recevoir un fond/une bordure visible). */
.topo-debug[hidden] { display: none !important; }
.topo-debug-btn {
  font-family: var(--mono, monospace);
  font-size: 0.68rem;
  color: var(--text-dim);
  background: rgba(var(--scene-bg-rgb), 0.75);
  border: 1px solid var(--border);
  padding: 5px 9px;
  cursor: pointer;
}
.topo-debug-btn:hover { border-color: var(--ok); color: var(--text); }
.topo-debug-btn.on { color: var(--danger); border-color: var(--danger); }

/* ---------- Mobile (<640px, meme seuil que services/layout.js) ---------- */
@media (max-width: 640px) {
  .topo-stage { height: 50vh; min-height: 280px; }
  /* La legende (.topo-caption) vit desormais SOUS la scene, en flux
     normal (cf. sa doc plus haut) - elle ne recouvre plus jamais le
     canvas, donc plus besoin de la reduire agressivement sur mobile
     (ancien comportement, quand le HUD flottait par-dessus un canvas
     deja petit) : simple padding resserre pour l'ecran etroit. */
  .topo-caption { padding: 14px; gap: 10px 20px; }
  .topo-hint { display: none; } /* "molette pour zoomer" n'a pas de sens au toucher */
  /* Labels VM affiches uniquement au tap sur mobile (pas de survol,
     cf. homelab-scene.js qui desactive le raycast de survol sous 640px) -
     .topo-label-hot ne peut donc plus etre applique en dessous de ce
     seuil, seul .topo-label-pinned (tap) reste actif. */
}

@media (prefers-reduced-motion: reduce) {
  /* La boucle JS ralentit deja le mouvement (x0.25, cf. homelab-scene.js) -
     ne JAMAIS couper : pas de regle "animation:none" ici, contrairement
     au reste du site (services/layout.js) qui coupe purement les
     animations CSS. Le clignotement des points "down" ci-dessus
     (@keyframes topo-blink) reste donc actif meme en reduced-motion -
     coherent avec le cadrage explicite de ce chantier ("ne jamais
     couper"). */
}
