/* =====================================================
   CS-VPN — thème sombre et mise en page à barre latérale
   Palette proche du noir profond, contraste élevé, traits
   fins et angles peu arrondis.
   ===================================================== */

:root {
  color-scheme: dark;

  --bg: #000000;
  --surface: #0c0c0e;
  --surface-2: #141418;
  --surface-3: #1b1b20;

  --border: #232329;
  --border-strong: #33333b;

  --text: #ffffff;
  --text-dim: #8b8b93;
  --text-faint: #5a5a63;

  --ok: #4ade80;
  --warn: #fbbf24;
  --danger: #f87171;

  --sidebar-w: 248px;
  --radius: 6px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: Inter, "Segoe UI", ui-sans-serif, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { text-decoration: none; color: inherit; }

/* =====================================================
   MISE EN PAGE
   ===================================================== */

.app {
  display: flex;
  min-height: 100vh;
}

.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-content {
  padding: 28px 32px 56px;
  max-width: 1400px;
  width: 100%;
}

@media (max-width: 900px) {
  .app-content { padding: 20px 16px 48px; }
}

/* =====================================================
   BARRE LATÉRALE
   ===================================================== */

.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 22px 20px 26px;
}

.sidebar-mark {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Le logo « tunnel » (SVG) porte sa propre tuile et son dégradé : le conteneur
   ne met donc ni fond ni bordure, il ne fait que dimensionner l'image. */
.sidebar-mark img,
.sidebar-mark svg {
  width: 100%;
  height: 100%;
  display: block;
}

.sidebar-name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
}

.nav-section {
  padding: 0 12px;
  margin-bottom: 20px;
}

.nav-label {
  padding: 0 10px 8px;
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 11px;
  margin-bottom: 2px;
  border-radius: var(--radius);
  font-size: 13.5px;
  color: var(--text-dim);
  transition: background-color .15s ease, color .15s ease;
  cursor: pointer;
  border: 0;
  background: transparent;
  width: 100%;
  text-align: left;
  font-family: inherit;
}

.nav-item:hover { background: var(--surface-2); color: var(--text); }

.nav-item.active {
  background: var(--surface-3);
  color: var(--text);
  font-weight: 500;
}

.nav-item.active::before {
  content: "";
  position: absolute;
  left: -12px;
  top: 7px;
  bottom: 7px;
  width: 2px;
  background: var(--text);
  border-radius: 0 2px 2px 0;
}

.nav-item svg { width: 16px; height: 16px; flex-shrink: 0; opacity: .85; }

.nav-item.danger { color: var(--danger); }
.nav-item.danger:hover { background: rgba(248, 113, 113, .1); color: var(--danger); }

.nav-badge {
  margin-left: auto;
  font-size: 9px;
  letter-spacing: .1em;
  padding: 2px 6px;
  border-radius: 3px;
  background: var(--surface-3);
  color: var(--text-dim);
  border: 1px solid var(--border);
}

.sidebar-foot { margin-top: auto; padding: 12px; }

/* =====================================================
   BARRE SUPÉRIEURE
   ===================================================== */

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 32px;
  border-bottom: 1px solid var(--border);
  background: rgba(0, 0, 0, .7);
  backdrop-filter: blur(10px);
  position: sticky;
  top: 0;
  z-index: 30;
}

@media (max-width: 900px) {
  .topbar { padding: 12px 16px; }
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 12.5px;
  color: var(--text-dim);
}

.chip strong { color: var(--text); font-weight: 600; }

.topbar-spacer { flex: 1; }

.icon-btn {
  width: 36px;
  height: 36px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}

.icon-btn:hover { border-color: var(--border-strong); color: var(--text); }

.sidebar-toggle { display: none; }

@media (max-width: 900px) {
  .sidebar {
    position: fixed;
    z-index: 60;
    transition: transform .22s ease;
  }
  /* L'état fermé est conditionné à l'absence de `.open` : deux règles
     concurrentes sur `transform` prêtent à confusion dans la cascade. */
  .sidebar:not(.open) { transform: translateX(-100%); }
  .sidebar.open { transform: translateX(0); }
  .sidebar-toggle { display: flex; }
  .sidebar-scrim {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .6);
    z-index: 50;
  }
}

/* =====================================================
   TITRES ET PANNEAUX
   ===================================================== */

.page-title {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 0 0 6px;
}

.page-sub {
  color: var(--text-dim);
  font-size: 13.5px;
  margin: 0 0 26px;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 20px;
}

.panel-title {
  font-size: 15px;
  font-weight: 600;
  margin: 0 0 4px;
}

.panel-sub {
  font-size: 12.5px;
  color: var(--text-dim);
  margin: 0 0 16px;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin-bottom: 22px;
}

.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
}

.stat-label {
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 10px;
}

.stat-value { font-size: 26px; font-weight: 600; letter-spacing: -.02em; }

/* =====================================================
   BOUTONS ET CHAMPS
   ===================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 15px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, opacity .15s ease;
}

.btn:hover { background: var(--surface-2); }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.btn-primary {
  background: var(--text);
  color: #000;
  border-color: var(--text);
  font-weight: 600;
}

.btn-primary:hover { background: #d8d8dc; border-color: #d8d8dc; }

.btn-sm { padding: 5px 11px; font-size: 12px; }
.btn-danger { border-color: rgba(248, 113, 113, .35); color: var(--danger); }
.btn-danger:hover { background: rgba(248, 113, 113, .1); }

input, select, textarea {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  padding: 9px 12px;
  font-size: 13.5px;
  font-family: inherit;
  outline: none;
  width: 100%;
  transition: border-color .15s ease;
}

input:focus, select:focus, textarea:focus { border-color: var(--border-strong); }
input::placeholder { color: var(--text-faint); }

label { display: block; font-size: 12px; color: var(--text-dim); margin-bottom: 6px; }

.field { margin-bottom: 14px; }

.search-wrap { position: relative; max-width: 420px; margin-bottom: 16px; }
.search-wrap input { padding-left: 34px; }
.search-wrap span {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-faint);
  font-size: 13px;
}

/* =====================================================
   TABLEAUX
   ===================================================== */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

table { border-collapse: collapse; width: 100%; min-width: 640px; }

thead th {
  text-align: left;
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 500;
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  white-space: nowrap;
}

tbody td {
  padding: 12px 14px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--surface-2); }

.t-right { text-align: right; }
.t-dim { color: var(--text-dim); }
.t-ok { color: var(--ok); }
.t-warn { color: var(--warn); }
.t-danger { color: var(--danger); }
.row-actions { display: flex; gap: 7px; justify-content: flex-end; align-items: center; flex-wrap: wrap; }

/* Repli en fiches quand le tableau n'a plus la place de s'afficher en colonnes.

   Un tableau à six colonnes réclame 640 px. En dessous il défile latéralement,
   ce qui met TOUTE la colonne Actions hors écran, joignable par un glissement
   que rien n'annonce hormis une fine barre. Chaque ligne devient donc une
   fiche, chaque cellule une paire étiquette / valeur, et les boutons prennent
   la largeur.

   La bascule est posée par le JavaScript (`is-cards`) et non par une requête
   média : la place disponible dépend aussi de la barre latérale, pas seulement
   de la largeur de la fenêtre. À 950 px barre ouverte il ne reste que 594 px —
   un seuil sur la fenêtre seule laisserait ce cas cassé.

   Réservé à `.table-cards` : les tableaux dont les cellules n'ont pas
   d'attribut `data-label` donneraient sinon des fiches sans intitulés. */
.table-cards.is-cards { overflow-x: visible; border: 0; }
.table-cards.is-cards table { display: block; min-width: 0; }
.table-cards.is-cards thead { display: none; }
.table-cards.is-cards tbody { display: block; }

.table-cards.is-cards tbody tr {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 10px;
}

.table-cards.is-cards tbody tr:last-child { margin-bottom: 0; }
.table-cards.is-cards tbody tr:hover { background: var(--surface); }

.table-cards.is-cards tbody td {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  text-align: left;
  padding: 9px 13px;
  border-bottom: 1px solid var(--border);
}

.table-cards.is-cards tbody td::before {
  content: attr(data-label);
  flex: 0 0 auto;
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Les actions occupent toute la largeur de la fiche, sans étiquette. */
.table-cards.is-cards tbody td.cell-actions {
  display: block;
  padding: 11px 13px;
  border-bottom: 0;
}

.table-cards.is-cards tbody td.cell-actions::before { content: none; }
.table-cards.is-cards .row-actions { justify-content: flex-start; }
.table-cards.is-cards .row-actions .btn { flex: 1 1 auto; }

/* L'état « aucun appareil » n'est pas une fiche. */
.table-cards.is-cards tbody tr.row-empty td {
  display: block;
  text-align: center;
  border-bottom: 0;
}

.table-cards.is-cards tbody tr.row-empty td::before { content: none; }

/* Fiche repliée.

   Au repos, seuls le nom et le statut restent visibles ; le reste se déplie au
   clic. Sans ça, dix appareils font dix fiches de cinq lignes et cinq boutons,
   et la liste devient impraticable au doigt. */
.table-cards.is-cards tbody tr:not(.row-empty) { cursor: pointer; }

.table-cards.is-cards tbody tr:not(.row-empty):not(.is-open)
  td:not([data-label="Nom"]):not([data-label="Statut"]) {
  display: none;
}

/* Repliée, la fiche se termine sur le statut : plus de trait de séparation. */
.table-cards.is-cards tbody tr:not(.is-open) td[data-label="Statut"] {
  border-bottom: 0;
}

/* Le nom est collé au chevron plutôt que centré entre l'étiquette et lui. */
.table-cards.is-cards td[data-label="Nom"] > div { margin-left: auto; }

.table-cards.is-cards td[data-label="Nom"]::after {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  margin-bottom: 3px;
  border-right: 1.5px solid var(--text-faint);
  border-bottom: 1.5px solid var(--text-faint);
  transform: rotate(45deg);
  transition: transform .18s ease;
}

.table-cards.is-cards tbody tr.is-open td[data-label="Nom"]::after {
  transform: rotate(-135deg);
}

/* =====================================================
   ALERTES ET FENÊTRES MODALES
   ===================================================== */

.alert {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 15px;
  font-size: 13px;
  margin-bottom: 18px;
}

.alert.ok { border-color: rgba(74, 222, 128, .3); background: rgba(74, 222, 128, .07); color: var(--ok); }
.alert.bad { border-color: rgba(248, 113, 113, .3); background: rgba(248, 113, 113, .07); color: var(--danger); }

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(0, 0, 0, .78);
  backdrop-filter: blur(4px);
}

.modal {
  width: 100%;
  max-width: 520px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px;
  max-height: 88vh;
  overflow-y: auto;
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}

.modal-head h3 { margin: 0; font-size: 16px; font-weight: 600; }

.modal-close {
  background: none;
  border: 0;
  color: var(--text-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}

.modal-close:hover { color: var(--text); }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }

pre {
  margin: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--text-dim);
  max-height: 340px;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.hidden { display: none !important; }

/* =====================================================
   ÉCRAN DE CHARGEMENT
   ===================================================== */

.loading {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
}

.spinner {
  width: 30px;
  height: 30px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--text);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* =====================================================
   PAGES D'AUTHENTIFICATION
   ===================================================== */

.auth-wrap {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1fr;
}

@media (max-width: 940px) {
  .auth-wrap { grid-template-columns: 1fr; }
  .auth-aside { display: none; }
}

.auth-aside {
  border-right: 1px solid var(--border);
  padding: 56px 48px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--surface);
}

.auth-panel {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
}

.auth-card { width: 100%; max-width: 400px; }

.auth-list { list-style: none; padding: 0; margin: 28px 0 0; }

.auth-list li {
  color: var(--text-dim);
  font-size: 13.5px;
  padding: 9px 0 9px 20px;
  position: relative;
}

.auth-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 17px;
  width: 6px;
  height: 1px;
  background: var(--text-faint);
}

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: #45454f; }

input:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--bg) inset !important;
  -webkit-text-fill-color: var(--text) !important;
  transition: background-color 9999s ease-in-out 0s;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ============ AIDE SOUS UN CHAMP ============ */
.field-hint {
  margin: 7px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-faint);
}

/* ============ ENTRÉE DE NAVIGATION À VENIR ============ */
/* L'onglet reste visible et cliquable : il annonce ce qui arrive, et sa page
   explique quoi. Le griser au point de le rendre illisible reviendrait à le
   cacher. */
.nav-soon {
  margin-left: auto;
  padding: 2px 6px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* ============ LISTE DES ROUTEURS JOIGNABLES (POSTE DE TRAVAIL) ============ */
.reach-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.reach-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  font-size: 13px;
}
.reach-item code {
  color: var(--text);
  font-size: 12.5px;
}

/* ============ RETOUR DU BOUTON « COPIER » ============ */
/* Le libellé change déjà en « Copié ! » ; la couleur le confirme d'un coup
   d'œil, sans obliger à lire. */
.btn.btn-ok {
  border-color: rgba(74, 222, 128, .45);
  color: var(--ok);
}
.btn.btn-ko {
  border-color: rgba(248, 113, 113, .45);
  color: var(--danger);
}

/* ============ PAGE DOCUMENTATION ============ */
.doc-steps {
  margin: 0;
  padding-left: 20px;
  color: var(--text-dim);
  font-size: 13.5px;
  line-height: 1.75;
}
.doc-steps li { margin-bottom: 8px; }
.doc-steps li strong,
.doc-list li strong { color: var(--text); font-weight: 600; }

.doc-list {
  margin: 0;
  padding-left: 18px;
  color: var(--text-dim);
  font-size: 13.5px;
  line-height: 1.75;
}
.doc-list li { margin-bottom: 6px; }

/* Repère visuel d'un élément d'interface cité dans le texte : le lecteur
   retrouve le mot exact qu'il doit chercher à l'écran. */
.ui {
  display: inline-block;
  padding: 1px 6px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 12.5px;
  white-space: nowrap;
}

.doc-note {
  margin: 14px 0 0;
  padding: 12px 14px;
  border-left: 2px solid var(--border-strong);
  background: var(--surface-2);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-dim);
}
.doc-note strong { color: var(--text); }

.doc-toc {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 26px;
}
.doc-toc a {
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-dim);
  font-size: 12.5px;
}
.doc-toc a:hover { border-color: var(--border-strong); color: var(--text); }

/* ============ LIENS DE COMMUNAUTÉ ============ */
.link-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
}
.link-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  transition: border-color .15s ease;
}
a.link-card:hover { border-color: var(--border-strong); }

.link-card-title {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.link-card-title svg { width: 17px; height: 17px; flex-shrink: 0; }
.link-card-sub { font-size: 12.5px; line-height: 1.6; color: var(--text-dim); }

/* Une entrée non encore configurée reste visible : elle annonce ce qui vient,
   au lieu de laisser un trou que personne ne comprend. */
.link-card.soon { opacity: .55; }
.link-card.soon .link-card-title::after {
  content: "Bientôt";
  margin-left: auto;
  padding: 2px 6px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--text-faint);
}

/* ============ DOMAINES MIKHMONAI ============ */
.domain-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.domain-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.domain-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.domain-name { font-size: 15px; font-weight: 600; color: var(--text); word-break: break-all; }

.domain-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 14px;
  font-size: 12.5px;
  color: var(--text-dim);
}
.domain-facts dt { color: var(--text-faint); }
.domain-facts dd { margin: 0; color: var(--text-dim); }

/* Le badge routeurs doit être lisible d'un coup d'œil : c'est le chiffre que
   le technicien regarde en premier. */
.domain-count { font-variant-numeric: tabular-nums; color: var(--text); }

.domain-actions { display: flex; flex-wrap: wrap; gap: 8px; }

.badge-statut {
  padding: 3px 8px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.badge-statut.online { border-color: rgba(74,222,128,.4); color: var(--ok); }
.badge-statut.provisioning { border-color: rgba(251,191,36,.4); color: var(--warn); }
.badge-statut.expired,
.badge-statut.suspended { border-color: rgba(248,113,113,.4); color: var(--danger); }
