*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ─── Themes ─────────────────────────────────────────────────────────────── */
/* Tokens alignés sur livraison-vaultwarden/CLAUDE_IMPLEMENTATION.md (design
   system fourni par le graphiste). Les noms de variables historiques sont
   conservés (utilisés inline dans app.js) — seules leurs valeurs changent. */
:root {
  --bg: #F8FAFC;
  --surface: #FFFFFF;
  --surface2: #EEF2F6;
  --surface3: #E2E8F0;
  --border: #D7E0EA;
  --bg-header: rgba(248, 250, 252, 0.92);
  --primary: #155579;
  --primary-light: #40C9D9;
  --primary-glow: rgba(21, 85, 121, 0.16);
  --text: #0F172A;
  --text-muted: #64748B;
  --text-subtle: #94A3B8;
  --green: #16A34A;
  --green-bg: rgba(22, 163, 74, 0.1);
  --red: #DC2626;
  --red-bg: rgba(220, 38, 38, 0.09);
  --yellow: #B45309;
  --yellow-bg: rgba(245, 158, 11, 0.12);
  --blue: #1D4ED8;
  --blue-bg: rgba(29, 78, 216, 0.09);
  --row-hover: rgba(15, 23, 42, 0.035);
  --shadow-modal: 0 20px 60px rgba(15, 23, 42, 0.12), 0 0 0 1px rgba(15, 23, 42, 0.04);
  --shadow-toast: 0 8px 24px rgba(15, 23, 42, 0.1);
  --cell-id-bg: rgba(21, 85, 121, 0.08);
}

[data-theme="dark"] {
  --bg: #071421;
  --surface: #0B1D2D;
  --surface2: #102638;
  --surface3: #16324A;
  --border: #294154;
  --bg-header: rgba(7, 20, 33, 0.92);
  --primary: #157B9B;
  --primary-light: #40C9D9;
  --primary-glow: rgba(21, 123, 155, 0.28);
  --text: #EAF1F7;
  --text-muted: #9DB0C1;
  --text-subtle: #71889F;
  --green: #22C55E;
  --green-bg: rgba(34, 197, 94, 0.14);
  --red: #EF4444;
  --red-bg: rgba(239, 68, 68, 0.14);
  --yellow: #F59E0B;
  --yellow-bg: rgba(245, 158, 11, 0.16);
  --blue: #58A6FF;
  --blue-bg: rgba(88, 166, 255, 0.12);
  --row-hover: rgba(255, 255, 255, 0.035);
  --shadow-modal: 0 24px 80px rgba(0, 0, 0, 0.55);
  --shadow-toast: 0 8px 32px rgba(0, 0, 0, 0.4);
  --cell-id-bg: rgba(64, 201, 217, 0.14);
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.45;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* ─── Accessibilité — focus clavier visible partout ─────────────────────── */
:focus-visible {
  outline: 2px solid var(--primary-light);
  outline-offset: 2px;
}

/* ─── Header ─────────────────────────────────────────────────────────────── */
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 32px;
  height: 64px;
  background: var(--bg-header);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 14px;
}

.logo-small {
  width: 38px;
  height: 38px;
  background: var(--primary);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Nom + dépôt côte à côte, séparés par un filet vertical (cf. maquette) */
.app-identity {
  display: flex;
  align-items: center;
  gap: 12px;
}

.app-name {
  font-size: 18px;
  font-weight: 700;
  color: var(--primary);
}
[data-theme="dark"] .app-name { color: var(--text); }

.app-identity-sep {
  width: 1px;
  height: 20px;
  background: var(--border);
}

.app-repo {
  font-size: 13px;
  color: var(--text-muted);
}

.header-sep {
  width: 1px;
  height: 22px;
  background: var(--border);
}

.header-logout {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  transition: color 0.15s;
}
.header-logout:hover { color: var(--text); }

.user-chevron { color: var(--text-subtle); flex-shrink: 0; }

.header-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.user-info {
  display: flex;
  align-items: center;
  gap: 10px;
}

.avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid var(--border);
}

/* ─── Theme toggle ───────────────────────────────────────────────────────── */
.theme-switch-group {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-muted);
}

.theme-icon-static { flex-shrink: 0; }

.theme-switch {
  position: relative;
  width: 34px;
  height: 18px;
  padding: 0;
  background: var(--primary);
  border: none;
  border-radius: 999px;
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 0.2s ease;
}

.theme-switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: white;
  transition: transform 0.2s ease;
}
[data-theme="dark"] .theme-switch-knob {
  transform: translateX(16px);
}

/* ─── Icônes d'en-tête (GitHub, déconnexion) — icône seule, sans cadre ──── */
.header-icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  transition: color 0.15s;
}
.header-icon-btn:hover { color: var(--text); }

/* ─── Buttons — hauteur 36px, rayon 8px (design system) ─────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 16px;
  border-radius: 8px;
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  border: none;
  text-decoration: none;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--primary);
  color: white;
}
.btn-primary:hover:not(:disabled) {
  filter: brightness(1.12);
}

.btn-save {
  background: var(--primary-light);
  color: #062430;
}
.btn-save:hover:not(:disabled) {
  filter: brightness(1.08);
}
.btn-save:disabled {
  background: var(--surface3);
  color: var(--text-subtle);
}

.btn-ghost {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.btn-ghost:hover {
  background: var(--surface2);
  color: var(--text);
  border-color: var(--surface3);
}

/* Rouge plein (variante "Danger" du design system, maquette 08) */
.btn-danger {
  background: var(--red);
  color: #fff;
  border: 1px solid var(--red);
}
.btn-danger:hover:not(:disabled) { filter: brightness(1.08); }
.btn-danger:disabled {
  background: var(--red-bg);
  color: var(--red);
  border-color: rgba(220, 38, 38, 0.2);
}

/* Contour orange sur fond transparent (cf. "Nouveau token admin", maquette 04) */
.btn-warning {
  background: transparent;
  color: var(--yellow);
  border: 1px solid var(--yellow);
}
.btn-warning:hover:not(:disabled) {
  background: var(--yellow-bg);
}

.btn-icon {
  height: 36px;
  padding: 0 10px;
  background: var(--surface2);
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 13px;
}
.btn-icon:hover { background: var(--surface3); color: var(--text); }
.btn-icon.admin:hover { background: var(--blue-bg); color: var(--blue); border-color: rgba(29, 78, 216, 0.3); }

/* Dans le tableau, les actions sont des carrés sur fond transparent, et
   la suppression est rouge en permanence (cf. maquette). */
.td-actions .btn-icon { background: transparent; }
.td-actions .btn-icon:hover { background: var(--surface2); }
.btn-icon.delete { color: var(--red); border-color: rgba(220, 38, 38, 0.25); }
.btn-icon.delete:hover { background: var(--red-bg); color: var(--red); border-color: rgba(220, 38, 38, 0.4); }

/* Boutons d'action du tableau (Modifier/Admin/Supprimer) : carrés, icône
   seule — cf. maquette 02-dashboard-clair. */
.btn-icon.icon-only {
  width: 36px;
  padding: 0;
  justify-content: center;
}

/* ─── Main ───────────────────────────────────────────────────────────────── */
.main {
  max-width: 1520px;
  margin: 0 auto;
  padding: 32px 24px;
}

/* ─── Stats ──────────────────────────────────────────────────────────────── */
.stats-bar {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 32px;
}

.stat-card {
  display: flex;
  align-items: center;
  gap: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 24px;
  transition: border-color 0.2s, background-color 0.2s;
}
.stat-card:hover { border-color: var(--primary-light); }

.stat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  flex-shrink: 0;
}
.stat-icon-1 { background: rgba(21, 85, 121, 0.12); color: var(--primary); }
.stat-icon-2 { background: rgba(64, 201, 217, 0.16); color: var(--primary-light); }
.stat-icon-3 { background: rgba(124, 92, 252, 0.14); color: #7C5CFC; }

.stat-text { flex: 1; min-width: 0; }

.stat-chart {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-subtle);
  flex-shrink: 0;
}

.stat-value {
  font-size: 28px;
  font-weight: 700;
  line-height: 1.15;
  margin-bottom: 4px;
}
.stat-value.green { color: var(--green); }
.stat-label {
  font-size: 13px;
  color: var(--text-muted);
}

/* ─── Toolbar ────────────────────────────────────────────────────────────── */
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
}

.search-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.search-icon {
  position: absolute;
  left: 13px;
  color: var(--text-subtle);
  pointer-events: none;
}

.search-input {
  height: 40px;
  padding: 0 14px 0 36px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  width: 300px;
  transition: all 0.2s ease;
  outline: none;
}
.search-input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-glow);
}
.search-input::placeholder { color: var(--text-subtle); }

.section-title {
  font-size: 20px;
  line-height: 28px;
  font-weight: 600;
}

.toolbar-actions {
  display: flex;
  gap: 10px;
  flex-shrink: 0;
}

/* ─── Unsaved banner ─────────────────────────────────────────────────────── */
.unsaved-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: var(--yellow-bg);
  border: 1px solid rgba(180, 83, 9, 0.25);
  border-radius: 8px;
  color: var(--yellow);
  font-size: 13px;
  margin-bottom: 16px;
}

.btn-discard-changes {
  margin-left: auto;
  flex-shrink: 0;
  padding: 5px 12px;
  background: transparent;
  border: 1px solid var(--yellow);
  border-radius: 6px;
  color: var(--yellow);
  font-family: 'Inter', sans-serif;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
}
.btn-discard-changes:hover {
  background: var(--yellow);
  color: white;
}

/* ─── Table ──────────────────────────────────────────────────────────────── */
.table-wrapper {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  transition: background-color 0.2s ease;
}

.clients-table {
  width: 100%;
  border-collapse: collapse;
}

.clients-table th {
  padding: 12px 16px;
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
}

/* Spécificité alignée sur `.clients-table th` (qui impose text-align: left),
   sinon le libellé restait collé à gauche pendant que les boutons, eux,
   étaient bien centrés. */
.clients-table th.th-actions { text-align: center; }

.th-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.th-sortable:hover { color: var(--text); }
.sort-icon {
  display: inline-block;
  margin-left: 4px;
  font-size: 10px;
  color: var(--text-subtle);
  vertical-align: middle;
}
.th-sortable.sort-active .sort-icon { color: var(--primary-light); }

.clients-table td {
  padding: 12px 16px;
  font-size: 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

.clients-table tbody tr { height: 56px; }
.clients-table tbody tr:last-child td { border-bottom: none; }

.clients-table tbody tr {
  transition: background 0.12s;
}
.clients-table tbody tr:hover { background: var(--row-hover); }

/* ─── Vue compacte ───────────────────────────────────────────────────────── */
.clients-table.compact tbody tr { height: 40px; }
.clients-table.compact td { padding: 6px 16px; font-size: 13px; }
.clients-table.compact .status-badge { padding: 2px 8px; font-size: 11px; }
.clients-table.compact .btn-icon { height: 28px; padding: 0 8px; }
.clients-table.compact .btn-icon.icon-only { width: 28px; padding: 0; }

.cell-id {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
}

.cell-muted {
  font-size: 13px;
  color: var(--text-subtle);
}

/* Invitations en attente : visibles mais nettement secondaires, pour qu'on
   ne les confonde pas avec le nombre d'utilisateurs réels juste à côté. */
.user-pending {
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--yellow);
  background: var(--yellow-bg);
  cursor: help;
}

.cell-domain-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: 13px;
  text-decoration: none;
  transition: color 0.15s;
}
.domain-ext-icon { color: var(--text-subtle); flex-shrink: 0; }
.cell-domain-link:hover .domain-ext-icon { color: var(--blue); }
.cell-domain-link:hover {
  color: var(--blue);
  text-decoration: underline;
}

/* Pas de display:flex sur la <td> : ça la sort du flux table-cell et
   désaligne les colonnes. On aligne via un conteneur interne. */
/* Même padding horizontal que l'en-tête : avec 8px ici et 16px sur le <th>,
   le libellé "Actions" et les boutons n'étaient pas centrés sur le même axe. */
.td-actions {
  white-space: nowrap;
}

.row-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.loading-cell {
  text-align: center;
  color: var(--text-muted);
  padding: 48px 16px !important;
}

.empty-cell {
  text-align: center;
  color: var(--text-muted);
  padding: 60px 16px !important;
  font-size: 14px;
}

/* ─── Pagination ─────────────────────────────────────────────────────────── */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  flex-wrap: wrap;
}

.pagination-info {
  font-size: 12px;
  color: var(--text-muted);
}

.pagination-pages {
  display: flex;
  align-items: center;
  gap: 4px;
}

.pagination-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 8px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-muted);
  font-family: 'Inter', sans-serif;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}
.pagination-btn:hover:not(:disabled) { background: var(--surface2); color: var(--text); }
.pagination-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pagination-btn.active {
  background: var(--primary);
  color: white;
  border-color: var(--primary);
}

.view-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-muted);
  font-family: 'Inter', sans-serif;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}
.view-toggle:hover { background: var(--surface2); color: var(--text); }

/* ─── Status badge ───────────────────────────────────────────────────────── */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
.status-badge .dot {
  /* La maquette (02/03-dashboard) affiche des pastilles pleines sans puce —
     le marquage reste dans le DOM (état "actif" identifiable autrement que
     par la couleur seule, cf. accessibilité) mais n'est plus affiché. */
  display: none;
}

.badge-ok { background: var(--green-bg); color: var(--green); }
.badge-ok .dot { background: var(--green); animation: pulse 2s infinite; }

.badge-missing { background: var(--red-bg); color: var(--red); }
.badge-missing .dot { background: var(--red); }

.badge-running { background: var(--green-bg); color: var(--green); }
.badge-running .dot { background: var(--green); animation: pulse 2s infinite; }

.badge-stopped { background: var(--yellow-bg); color: var(--yellow); }
.badge-stopped .dot { background: var(--yellow); }

.badge-loading { background: var(--surface2); color: var(--text-muted); }
.badge-loading .dot { background: var(--text-muted); animation: pulse 1s infinite; }

.badge-unknown { background: var(--surface2); color: var(--text-subtle); }
.badge-unknown .dot { background: var(--text-subtle); }

.badge-error { background: var(--red-bg); color: var(--red); }
.badge-error .dot { background: var(--red); }

.badge-info { background: var(--blue-bg); color: var(--blue); }

/* ─── Colonne Version — badge de statut + numéro(s) en texte simple,
   "Mettre à jour" en lien (cf. maquette 02-dashboard-clair) ────────────── */
.version-cell {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.version-cell-outdated {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}

.version-cell-top {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.version-number {
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
}

.link-update-version {
  background: none;
  border: none;
  padding: 0;
  color: var(--blue);
  font-size: 12px;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
}
.link-update-version:hover:not(:disabled) { text-decoration: underline; }
.link-update-version:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  text-decoration: none;
}

.version-history-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 46vh;
  overflow-y: auto;
}

.version-history-item {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
}

/* Pastille de la frise chronologique (cf. maquette 06) */
.version-history-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--green);
  flex-shrink: 0;
}

.version-history-main { flex: 1; min-width: 0; }

.version-history-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--text);
}

.version-history-id {
  padding: 2px 8px;
  border-radius: 5px;
  background: var(--surface3);
  color: var(--text-muted);
  font-size: 11px;
}

.version-history-date {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 3px;
}

.version-history-change {
  color: var(--text);
  font-size: 14px;
  white-space: nowrap;
}

.btn-rollback {
  height: 32px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 500;
  background: var(--surface);
  flex-shrink: 0;
}

.version-history-gone {
  font-size: 12px;
  color: var(--text-subtle);
  font-style: italic;
  white-space: nowrap;
  flex-shrink: 0;
}

.modal-error { font-size: 14px; color: var(--red); padding: 20px 0; }

/* Saisie de confirmation et bouton sur la même ligne, alignés en hauteur */
.orphan-confirm-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 300px;
}
.orphan-confirm-row .btn-danger { flex-shrink: 0; }
.orphan-confirm-row input {
  flex: 1;
  min-width: 0;
  height: 36px;
  padding: 0 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  outline: none;
}
.orphan-confirm-row input:focus {
  border-color: var(--red);
}
.orphan-confirm-row input:disabled { opacity: 0.5; cursor: not-allowed; }

.orphan-confirm-row .btn-danger { white-space: nowrap; }
.orphan-confirm-row .btn-danger:disabled { opacity: 0.55; }

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

/* ─── Spinner ────────────────────────────────────────────────────────────── */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  vertical-align: middle;
  margin-right: 6px;
}

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

/* ─── Modal ──────────────────────────────────────────────────────────────── */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  animation: fadeIn 0.15s ease;
}

@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

/* Confirmation ouverte par-dessus une autre modale : sans ça, la boîte de
   dialogue passerait dessous (même z-index, et elle est déclarée avant
   dans le document). */
.modal-overlay.on-top { z-index: 330; }

.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  width: 480px;
  max-width: 95vw;
  box-shadow: var(--shadow-modal);
  animation: slideUp 0.2s ease;
  /* Sans plafond de hauteur, une modale au contenu long (ex: beaucoup de
     données orphelines) déborde de l'écran : l'en-tête et son bouton de
     fermeture, ainsi que le pied de modale, deviennent inatteignables.
     Le corps défile, l'en-tête et le pied restent visibles. */
  max-height: 90vh;
  display: flex;
  flex-direction: column;
}

.modal-header, .modal-footer { flex-shrink: 0; }

.confirm-modal { width: 420px; }

/* Pastille ronde colorée devant le titre des confirmations (maquette 08) */
.confirm-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  flex-shrink: 0;
}
.confirm-icon svg { width: 17px; height: 17px; }
.confirm-icon-danger { background: var(--red-bg); color: var(--red); }
.confirm-icon-primary { background: var(--primary-glow); color: var(--primary); }
[data-theme="dark"] .confirm-icon-primary { color: var(--primary-light); }

.confirm-warning {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--red);
}
.confirm-warning svg { flex-shrink: 0; margin-top: 2px; }
.confirm-warning-alt { color: var(--yellow); }

/* Liste nominative des clients qu'une suppression massive retirerait : c'est
   en la lisant qu'on reconnaît un état de page corrompu, elle doit donc rester
   lisible même à une quinzaine d'identifiants. Hauteur bornée pour ne jamais
   pousser les boutons hors de la modale. */
.confirm-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-height: 132px;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
}
.confirm-list code {
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--surface);
  color: var(--red);
}
.confirm-list-more {
  align-self: center;
  font-size: 12px;
  color: var(--text-muted);
}

/* Modale large : la liste des données orphelines est un tableau à 6 colonnes */
.modal-wide { width: 1180px; }
.modal-md { width: 775px; }

.modal-title-with-icon {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
}

.search-input-full { width: 100%; }

.modal-intro {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-muted);
}

.modal-empty {
  font-size: 14px;
  color: var(--text-muted);
  padding: 20px 0;
}

/* Spécificité doublée : .modal-footer (défini plus bas) impose flex-end */
.modal-footer.modal-footer-split { justify-content: space-between; }

/* ─── Tableau des données orphelines ─────────────────────────────────────── */
.orphan-table-wrap {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow-x: auto;
}

.orphan-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.orphan-table th {
  text-align: left;
  padding: 12px 14px;
  font-weight: 600;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
  white-space: nowrap;
}

.orphan-table td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  white-space: nowrap;
}
.orphan-table tbody tr:last-child td { border-bottom: none; }

.orphan-client { color: var(--blue); font-weight: 500; }
.orphan-client-unknown { color: var(--text-subtle); font-style: italic; }
.orphan-id { color: var(--text-muted); }

/* ─── Encart d'avertissement (suppression irréversible) ──────────────────── */
.irreversible-notice {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-muted);
}
.irreversible-notice > svg { color: var(--primary); flex-shrink: 0; margin-top: 1px; }

.irreversible-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
}

.irreversible-text { font-size: 12px; line-height: 1.6; }

@keyframes slideUp {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 20px 24px;
  border-bottom: 1px solid var(--border);
}

.modal-header h3 { font-size: 16px; line-height: 24px; font-weight: 600; }

.modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  transition: all 0.15s;
  flex-shrink: 0;
}
.modal-close:hover { background: var(--surface2); color: var(--text); }

.modal-body {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 16px 24px;
  border-top: 1px solid var(--border);
}

/* ─── Form ───────────────────────────────────────────────────────────────── */
.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-group label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.required { color: var(--red); }

.form-group input,
.form-group select {
  height: 40px;
  padding: 0 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  transition: border-color 0.15s, box-shadow 0.15s;
  outline: none;
}

/* Chevron personnalisé (la flèche native diffère d'un navigateur à l'autre) */
.form-group select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 38px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

.field-lock {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface2);
  color: var(--text-subtle);
  flex-shrink: 0;
}
.form-group input:focus,
.form-group select:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-glow);
  background: var(--surface);
}
.form-group input::placeholder { color: var(--text-subtle); }
.form-group input:disabled,
.form-group select:disabled { opacity: 0.6; cursor: not-allowed; }

.input-with-action {
  display: flex;
  gap: 8px;
}

.input-with-action input {
  flex: 1;
}

.btn-action-input {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.15s;
}

.btn-action-input:hover {
  background: var(--surface3);
  color: var(--text);
  border-color: var(--surface3);
}

.btn-action-input:active {
  transform: scale(0.95);
}

.btn-action-input.spinning svg {
  animation: spinOnce 0.45s ease-out;
}

@keyframes spinOnce {
  from { transform: rotate(0deg); }
  to { transform: rotate(-360deg); }
}

.field-hint {
  font-size: 12px;
  line-height: 16px;
  color: var(--text-muted);
}

/* ─── Infobulles ─────────────────────────────────────────────────────────── */
/* Positionnée en fixed et rattachée au <body> : dans le tableau, un
   positionnement relatif serait rogné par overflow-x du conteneur. */
.tooltip {
  position: fixed;
  z-index: 400;
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--text);
  color: var(--surface);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(3px);
  transition: opacity 0.12s ease, transform 0.12s ease;
  box-shadow: var(--shadow-toast);
}
.tooltip.show { opacity: 1; transform: translateY(0); }

/* ─── Toast ──────────────────────────────────────────────────────────────── */
/* Fond opaque (var(--surface)) et non une teinte translucide : par-dessus
   l'overlay assombri d'une modale, un fond à 10% d'opacité laissait
   transparaître l'arrière-plan et le message devenait illisible.
   z-index au-dessus des modales (200) et de leur overlay. */
.toast {
  position: fixed;
  bottom: 28px;
  right: 28px;
  z-index: 360; /* au-dessus des modales et des confirmations */
  display: none;
  align-items: flex-start;
  gap: 12px;
  width: 380px;
  max-width: calc(100vw - 32px);
  padding: 14px 16px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.22);
  transform: translateY(16px);
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
[data-theme="dark"] .toast { box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55); }

.toast.show {
  display: flex;
  transform: translateY(0);
  opacity: 1;
}

.toast-icon { display: flex; flex-shrink: 0; margin-top: 1px; }
.toast-body { flex: 1; min-width: 0; }
.toast-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 2px;
}
.toast-message {
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.toast-close {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  padding: 0;
  background: none;
  border: none;
  border-radius: 5px;
  color: var(--text-subtle);
  cursor: pointer;
  transition: all 0.15s;
}
.toast-close:hover { background: var(--surface2); color: var(--text); }

.toast.success { border-left-color: var(--green); }
.toast.success .toast-icon { color: var(--green); }
.toast.error { border-left-color: var(--red); }
.toast.error .toast-icon { color: var(--red); }
.toast.info { border-left-color: var(--blue); }
.toast.info .toast-icon { color: var(--blue); }

/* ─── Deploy Panel ───────────────────────────────────────────────────────── */
/* Hauteur fixe (et non max-height) : le panneau ne doit pas grandir au fur
   et à mesure que les étapes arrivent — la structure complète est posée dès
   l'ouverture et garde ses dimensions du début à la fin. */
.deploy-modal {
  width: 900px;
  height: 86vh;
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.deploy-elapsed {
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ─── Progression globale ────────────────────────────────────────────────── */
.deploy-progress {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.deploy-progress-label {
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
}
.deploy-progress-track {
  flex: 1;
  height: 6px;
  border-radius: 999px;
  background: var(--surface3);
  overflow: hidden;
}
.deploy-progress-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--primary-light);
  transition: width 0.4s ease;
}

.deploy-pipeline-title {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 24px 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  flex-shrink: 0;
}

/* ─── Onglets des jobs ───────────────────────────────────────────────────── */
.deploy-tabs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0;
  margin: 14px 24px 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  flex-shrink: 0;
}

.deploy-tab {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: var(--surface);
  border: none;
  border-bottom: 3px solid transparent;
  cursor: pointer;
  text-align: left;
  font-family: 'Inter', sans-serif;
  transition: background 0.15s;
}
.deploy-tab + .deploy-tab { border-left: 1px solid var(--border); }
.deploy-tab:hover { background: var(--surface2); }
.deploy-tab.active {
  background: var(--green-bg);
  border-bottom-color: var(--primary-light);
}
[data-theme="dark"] .deploy-tab.active { background: rgba(64, 201, 217, 0.08); }

.deploy-tab-icon { display: flex; align-items: center; flex-shrink: 0; }
.tab-icon-ok { color: var(--green); display: flex; }
.tab-icon-ko { color: var(--red); display: flex; }
.tab-icon-idle {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--border); display: block;
}

.deploy-tab-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.deploy-tab-head { display: flex; align-items: center; gap: 8px; }
.deploy-tab-name { font-size: 15px; font-weight: 600; color: var(--text); }
.deploy-tab-meta { font-size: 12px; color: var(--text-muted); }

/* ─── Panneau des étapes (seule zone défilante avec la console) ──────────── */
.deploy-steps-panel {
  display: flex;
  flex-direction: column;
  /* Ne descend jamais sous la hauteur d'un en-tête + une étape : sinon,
     quand la console est ouverte, la zone se comprimait jusqu'à disparaître
     et le bloc token se retrouvait coupé. */
  flex: 1 1 auto;
  min-height: 124px;
  margin: 14px 24px 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.deploy-steps-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  flex-shrink: 0;
}
.deploy-steps-title { font-size: 15px; font-weight: 600; color: var(--text); }
.deploy-steps-meta { font-size: 13px; color: var(--text-muted); white-space: nowrap; }

.deploy-steps-body {
  overflow-y: auto;
  min-height: 0;
  flex: 1;
  padding: 0 12px 12px;
}

/* Grille compacte deux colonnes une fois le job terminé */
.deploy-steps-body.is-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 10px;
  align-content: start;
}
.deploy-steps-body.is-grid .deploy-step {
  border: 1px solid var(--border);
  border-radius: 8px;
}
.deploy-steps-body.is-grid .deploy-step + .deploy-step { border-top: 1px solid var(--border); }

.deploy-title-block {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.deploy-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Icône de statut à la taille du titre (elle était nettement trop petite) */
#deployStatusIcon { display: flex; align-items: center; flex-shrink: 0; }
#deployStatusIcon svg { width: 23px; height: 23px; }
#deployStatusIcon .deploy-spinner { width: 21px; height: 21px; }

.deploy-subtitle {
  font-size: 12px;
  color: var(--text-muted);
  margin-left: 26px;
}

.deploy-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* Aligné sur les autres boutons du design system : même hauteur, même
   rayon, même graisse — il jurait avec le reste de l'en-tête. */
.btn-cancel-deploy {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-muted);
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
}
.btn-cancel-deploy svg { flex-shrink: 0; }
.btn-cancel-deploy:hover:not(:disabled) {
  background: var(--red-bg);
  border-color: rgba(220, 38, 38, 0.35);
  color: var(--red);
}
.btn-cancel-deploy:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.deploy-spinner {
  width: 16px;
  height: 16px;
  border-width: 2px;
  flex-shrink: 0;
}

.deploy-body {
  padding: 8px 24px 8px;
  overflow-y: auto;
  flex: 1;
  min-height: 80px;
}

.deploy-searching {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 28px 0;
  color: var(--text-muted);
  font-size: 14px;
}

/* Chaque job dans sa propre carte bordée (cf. maquette 05-deploiement) */
.job-group {
  margin-bottom: 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.job-group .steps-list {
  border-top: 1px solid var(--border);
}

.job-group-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--surface2);
}

.job-group-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.job-group-time {
  margin-left: auto;
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Pas de hauteur plafonnée ici : une liste d'étapes qui défile à
   l'intérieur d'un corps de modale déjà défilant donne deux barres
   imbriquées. Chaque job s'affiche en entier, le corps défile si besoin. */
.steps-list {
  display: flex;
  flex-direction: column;
}

.deploy-step {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  font-size: 14px;
  border-radius: 8px;
}
.deploy-step + .deploy-step { border-top: 1px solid var(--border); }
.deploy-step.step-running { background: var(--green-bg); }
[data-theme="dark"] .deploy-step.step-running { background: rgba(64, 201, 217, 0.08); }

.step-status {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 13px;
  font-weight: 600;
}

.step-spinner {
  width: 13px;
  height: 13px;
  border: 2px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

.step-name { flex: 1; }
.step-time { font-size: 12px; color: var(--text-muted); white-space: nowrap; }

.deploy-logs-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* Vue logs agrandie : grande modale dédiée, console pleine hauteur */
.logs-full-modal {
  width: 1200px;
  height: 88vh;
  max-height: 88vh;
}
.logs-full-body {
  flex: 1;
  min-height: 0;
  display: flex;
  padding: 16px 24px;
}

.step-success { color: var(--green); }
.step-success .step-status svg { stroke: var(--green); }
.step-failure { color: var(--red); }
.step-running { color: var(--primary); }
.step-pending { color: var(--text-subtle); }
.step-skipped { color: var(--text-subtle); font-style: italic; }

.deploy-error-msg {
  padding: 24px 0;
  color: var(--red);
  font-size: 14px;
}

/* ─── Logs section ───────────────────────────────────────────────────────── */
.deploy-logs-section {
  border-top: 1px solid var(--border);
  margin-top: 14px;
  padding: 0 24px;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Console ouverte : la zone des étapes se réduit à une étape visible (avec
   son défilement) et la console occupe l'espace libéré, comme sur la
   maquette. Les deux zones restent bornées, donc token et pied de modale
   ne sont jamais poussés hors du cadre. */
/* Console ouverte : on gagne un peu de hauteur et on réduit la zone des
   étapes, sinon la console se retrouve écrasée à deux lignes. */
.deploy-modal.logs-open { height: 92vh; max-height: 92vh; }
.deploy-modal.logs-open .deploy-steps-panel { flex: 0 0 106px; }
.deploy-modal.logs-open .deploy-logs-section { flex: 1 1 auto; }

/* Écrans peu hauts : on récupère quelques dizaines de pixels plutôt que de
   laisser la modale déborder (constaté sous 800px de haut). */
/* Écrans peu hauts : la maquette a été dessinée pour une fenêtre haute, il
   faut récupérer de la place pour que la console reste lisible. */
@media (max-height: 900px) {
  .deploy-modal { height: 94vh; max-height: 94vh; }
  .deploy-modal.logs-open { height: 96vh; max-height: 96vh; }
  .deploy-modal.logs-open .deploy-steps-panel { flex: 0 0 92px; }
  /* Le titre du pipeline est redondant avec les onglets juste en dessous :
     on le sacrifie en premier quand la console est ouverte. */
  .deploy-modal.logs-open .deploy-pipeline-title { display: none !important; }
  .deploy-tab { padding: 9px 14px; }
  .deploy-token { padding: 10px 24px; }
  .deploy-steps-panel, .deploy-tabs { margin-top: 10px; }
  .deploy-logs-section { margin-top: 10px; }
}

.deploy-logs-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 12px 0;
  flex-shrink: 0;
}

.deploy-logs-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  background: none;
  border: none;
  color: var(--text-muted);
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: color 0.15s;
}
.deploy-logs-toggle:hover { color: var(--text); }

.logs-chevron {
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
.logs-chevron.is-open { transform: rotate(180deg); }

/* Hauteur fixe : sans plafond, le <pre> grandit avec le volume de logs et
   fait déborder la modale (la zone des étapes disparaissait). La console
   garde les proportions de la maquette et défile à l'intérieur. */
/* Pas de hauteur fixe : la console prend l'espace que lui laisse la
   colonne, entre un minimum lisible et la hauteur de la maquette. */
/* min-height: 0 et non une valeur plancher : sur un écran court, un
   minimum imposé force la console au-delà de la place disponible et elle
   déborde sur le bloc token. Elle se réduit donc autant que nécessaire —
   le bouton "Agrandir" reste là pour lire confortablement. */
.deploy-logs-content {
  padding-bottom: 12px;
  flex: 1 1 auto;
  min-height: 96px;
  max-height: 316px;
  display: flex;
  overflow: hidden;
}

/* Console : bloc sombre avec sa propre barre de défilement */
.log-console {
  position: relative;
  flex: 1;
  min-height: 0;
  background: #0B1622;
  border: 1px solid #1E3145;
  border-radius: 10px;
  overflow: hidden;
  display: flex;
}

.log-download {
  position: absolute;
  top: 10px;
  right: 12px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  background: rgba(11, 22, 34, 0.85);
  border: 1px solid #294154;
  border-radius: 6px;
  color: #C7D6E4;
  font-family: 'Inter', sans-serif;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s;
}
.log-download:hover { background: #16324A; }

/* ─── Coloration syntaxique des logs ─────────────────────────────────────── */
/* inline et non block : le <pre> conserve le "\n" entre les lignes (pour que
   la copie et le téléchargement récupèrent le texte brut), un display:block
   ajouterait un second saut de ligne et doublerait l'interligne. */
.log-line { display: inline; }
.log-ts { color: #5F7891; }          /* horodatage : en retrait */
.log-line.is-error   { color: #FF9B9B; }
.log-line.is-warn    { color: #F5C26B; }
.log-line.is-success { color: #7EE3A9; }
.log-line.is-cmd     { color: #C3A8F7; }
.log-line.is-group   { color: #7FB6DE; }

/* Le viewer défile à l'intérieur de la console (fond porté par .log-console) */
.log-viewer {
  flex: 1;
  min-height: 0;
  margin: 0;
  padding: 14px;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  line-height: 1.7;
  color: #C7D6E4;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ─── Token section ──────────────────────────────────────────────────────── */
.deploy-token {
  border-top: 1px solid var(--border);
  padding: 14px 24px;
  flex-shrink: 0;
}

/* Message d'attente : réserve la place du bloc token avant la réussite */
.token-waiting {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface2);
  color: var(--text-muted);
  font-size: 13px;
}
.token-waiting svg { color: var(--primary-light); flex-shrink: 0; }

.deploy-footer { justify-content: space-between; }
/* La note disparaît une fois le déploiement terminé : "Fermer" doit rester
   ancré à droite plutôt que de glisser à gauche. */
.deploy-footer .btn { margin-left: auto; }

.deploy-footer-note {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-muted);
}
.deploy-footer-note svg { flex-shrink: 0; }

.token-section-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 12px;
  color: var(--text);
}

.token-item {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 8px;
}

.token-client-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.token-item-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.token-loading {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-muted);
  font-size: 13px;
}

.token-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
}

/* Le token tient sur une seule ligne (il défile horizontalement si
   nécessaire) plutôt que de casser en plusieurs lignes. */
.token-value {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0 12px;
  height: 38px;
  color: var(--text);
  white-space: nowrap;
  overflow-x: auto;
  letter-spacing: 0.02em;
}

.btn-copy-token {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  background: var(--surface3);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-muted);
  font-size: 12px;
  font-family: 'Inter', sans-serif;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
  flex-shrink: 0;
}
.btn-copy-token:hover {
  background: var(--primary);
  color: white;
  border-color: var(--primary);
}

.token-hint {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--yellow);
  margin-top: 8px;
}

.token-not-found {
  font-size: 13px;
  color: var(--text-muted);
}

.token-pending {
  font-size: 13px;
  color: var(--text-subtle);
  font-style: italic;
}

/* ─── Responsive ─────────────────────────────────────────────────────────── */
/* Le produit est pensé pour le bureau : sous 1200px le tableau défile
   horizontalement plutôt que d'écraser ses 9 colonnes (cf. guide, §20). */
.table-wrapper { overflow-x: auto; }
/* Largeur plancher : en dessous, les 9 colonnes se tassent et coupent les
   noms/domaines en deux. On préfère un défilement horizontal (cf. §20). */
.clients-table { min-width: 1180px; }
.clients-table td:nth-child(2),
.cell-domain-link { white-space: nowrap; }

@media (max-width: 1280px) {
  .main { padding: 24px 16px; }
  .search-input { width: 240px; }
}

@media (max-width: 1100px) {
  /* La barre d'outils passe sous le titre : on garde la recherche pleine
     largeur et les actions alignées à droite. */
  .toolbar {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .toolbar-left { gap: 12px; }
  .search-input { width: 100%; }
  .toolbar-left .search-wrap { flex: 1; }
  .toolbar-actions { justify-content: flex-end; flex-wrap: wrap; }
}

@media (max-width: 900px) {
  .header { padding: 0 16px; }
  /* Le dépôt et le nom d'utilisateur sont secondaires : on les masque
     avant de tasser les contrôles interactifs. */
  .app-repo, .app-identity-sep, .header-sep { display: none; }
  .stats-bar { grid-template-columns: 1fr; gap: 12px; margin-bottom: 24px; }
  .stat-card { padding: 14px 18px; }
  .stat-value { font-size: 24px; }
}

@media (max-width: 700px) {
  .main { padding: 16px 12px; }
  .app-name { font-size: 15px; }
  #userName, .user-chevron { display: none; }
  .header-logout { font-size: 0; gap: 0; }
  .header-logout svg { font-size: 17px; }
  .theme-icon-static { display: none; }

  .section-title { font-size: 18px; }
  .toolbar-actions { gap: 8px; }
  .toolbar-actions .btn { flex: 1 1 auto; justify-content: center; }

  /* Modales quasi plein écran, pied de modale empilable */
  .modal, .modal-wide, .modal-md, .confirm-modal, .deploy-modal {
    width: 100%;
    max-width: 100%;
    max-height: 100vh;
    border-radius: 0;
    border: none;
  }
  .modal-overlay { align-items: stretch; }
  .modal-body { padding: 16px; }
  .modal-header, .modal-footer { padding: 14px 16px; }
  .modal-footer { flex-wrap: wrap; }
  .modal-footer .btn { flex: 1 1 auto; justify-content: center; }
  .modal-footer.modal-footer-split { gap: 8px; }

  .pagination { justify-content: center; }
  .pagination-info { width: 100%; text-align: center; }
}

@media (max-width: 480px) {
  .toolbar-actions .btn { width: 100%; }
  .deploy-header-actions { flex-direction: column-reverse; align-items: flex-end; gap: 4px; }
}
