@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

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

/* ══════════════════════════════════════
   DESIGN TOKENS
   ══════════════════════════════════════

   Le beige Ergopix est une identité, pas un défaut : il reste. Ce qui a changé,
   c'est l'écart entre les valeurs. L'ancienne palette posait --bg à #f7f6f3 et
   --surface à #ffffff — trois points de luminance d'écart, une carte ne se
   détachait pas de son fond et l'écran se lisait comme une seule feuille.

   Trois leviers, dans cet ordre d'importance :
   1. creuser l'écart fond / surface, pour que l'élévation existe ;
   2. rendre les bordures visibles (elles l'étaient à peine) ;
   3. saturer les couleurs sémantiques, qui portent les statuts.

   L'olive n'a pas bougé d'un cran. C'est la marque.
   ══════════════════════════════════════ */
:root {
  /* Neutres — papier chaud, mais avec de la profondeur */
  --bg:           #efeee8;
  --surface:      #ffffff;
  --surface-alt:  #f8f7f3;
  --text:         #17170f;
  --text-secondary: #55544c;
  --muted:        #8d8c83;
  --border:       #dbd8cd;
  --border-light: #e8e6dd;

  /* Accents — l'olive Ergopix, inchangée ; --accent est réécrite par
     organisation dans la mise en page, --accent-strong suit. */
  --accent:       #8a9a5b;
  --accent-hover: #737f4a;
  --accent-light: #f1f4e6;
  --accent-ring:  rgba(138,154,91,0.28);

  /* Sémantiques — plus franches : ce sont elles qui portent les statuts,
     et un statut délavé ne se lit pas d'un coup d'œil. */
  --blue:         #3f88d4;
  --blue-light:   #e9f2fc;
  --green:        #1f9a55;
  --green-light:  #e7f6ed;
  --danger:       #dc3345;
  --danger-light: #fdeef0;
  --warning:      #e2960f;
  --warning-light:#fdf5e3;

  /* Sizing */
  --radius-sm:    7px;
  --radius-md:    11px;
  --radius-lg:    15px;
  --radius-xl:    20px;

  /* Élévation en deux couches : un contact net près de l'objet, une diffusion
     large et douce en dessous. Une ombre à une seule couche paraît collée. */
  --shadow-sm:    0 1px 2px rgba(23,23,15,0.05), 0 1px 3px rgba(23,23,15,0.04);
  --shadow-md:    0 2px 4px rgba(23,23,15,0.04), 0 8px 22px rgba(23,23,15,0.07);
  --shadow-lg:    0 4px 8px rgba(23,23,15,0.05), 0 18px 48px rgba(23,23,15,0.12);

  /* Ombre révélant qu'une liste défile encore de ce côté. */
  --scroll-shadow: rgba(23, 23, 15, 0.14);

  /* Transition */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; transition: color 0.2s var(--ease); }
a:hover { color: var(--accent-hover); }

/* ══════════════════════════════════════
   NAVBAR
   ══════════════════════════════════════ */
.navbar {
  background: var(--surface) !important;
  border-bottom: 1px solid var(--border);
  padding: 0 32px;
  height: 60px;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(12px);
  background: rgba(255,255,255,0.92) !important;
  box-shadow: none;
}

.navbar .container-fluid { max-width: 100%; padding: 0; }

.navbar-brand {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 20px;
  font-weight: 400;
  color: var(--text) !important;
  letter-spacing: -0.02em;
}

.navbar .navbar-nav .nav-link {
  color: var(--text-secondary) !important;
  font-size: 13px;
  font-weight: 500;
  padding: 8px 14px !important;
  border-radius: var(--radius-sm);
  transition: all 0.2s var(--ease);
}

.navbar .navbar-nav .nav-link:hover {
  color: var(--accent) !important;
  background: var(--accent-light);
}

.navbar .navbar-nav .nav-link.active { color: var(--accent) !important; }

/* Libellé réservé au menu déplié : dans la barre, l'icône se suffit. */
.nav-link__label { display: none; }

.navbar-toggler { border-color: var(--border) !important; padding: 4px 8px; flex-shrink: 0; }
.navbar-toggler:focus { box-shadow: none; }
.navbar-toggler-icon {
  filter: none; width: 1.2em; height: 1.2em;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(90,89,85,1)' stroke-linecap='round' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") !important;
}

@media (max-width: 991.98px) {
  .navbar { height: auto; padding: 10px 16px; }
  .navbar .container-fluid { flex-wrap: wrap; }
  .navbar-collapse {
    background: var(--surface);
    border-top: 1px solid var(--border-light);
    margin-top: 10px;
    padding: 12px 0 8px;
  }
  .navbar-collapse .navbar-nav { gap: 2px; }
  .navbar-collapse .nav-link { padding: 10px 12px !important; }
}

.dropdown-menu {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 6px;
  background: var(--surface);
}

.dropdown-item {
  font-size: 13px;
  padding: 7px 14px;
  border-radius: var(--radius-sm);
  color: var(--text);
  transition: all 0.15s var(--ease);
}

.dropdown-item:hover { background: var(--accent-light); color: var(--accent); }

/* ══════════════════════════════════════
   MAIN
   ══════════════════════════════════════ */
main.container-fluid { flex: 1; padding: 24px 32px; max-width: 100%; }

/* ══════════════════════════════════════
   HEADINGS
   ══════════════════════════════════════ */
h1, h2 {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text);
}

h5, h6 { font-weight: 600; font-size: 13px; letter-spacing: 0.02em; color: var(--text); }

/* Page header compat : h1 + actions sur la même ligne */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  gap: 12px;
  flex-wrap: wrap;
}
.page-header h1 { margin: 0; }
.page-header .actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* ══════════════════════════════════════
   CARDS
   ══════════════════════════════════════ */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.card-header {
  background: var(--surface-alt);
  border-bottom: 1px solid var(--border-light);
  padding: 12px 20px;
}

.card-header h5, .card-header h6 { margin: 0; }

.card-body { padding: 20px; }

/* ══════════════════════════════════════
   BUTTONS
   ══════════════════════════════════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 18px;
  border: none;
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  transition: all 0.2s var(--ease);
  white-space: nowrap;
}

.btn-dark,
.btn-primary {
  background: var(--accent);
  color: #fff;
  border: none;
  box-shadow: 0 1px 2px rgba(138,154,91,0.3);
}

.btn-dark:hover,
.btn-primary:hover {
  background: var(--accent-hover);
  box-shadow: 0 2px 8px rgba(138,154,91,0.3);
  transform: translateY(-1px);
  color: #fff;
}

.btn-outline-dark {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
}
.btn-outline-dark:hover {
  background: var(--surface-alt);
  border-color: var(--text-secondary);
  color: var(--text);
}

.btn-outline-secondary {
  background: var(--surface);
  color: var(--text-secondary);
  border: 1px solid var(--border);
}
.btn-outline-secondary:hover {
  background: var(--surface-alt);
  border-color: var(--text-secondary);
  color: var(--text);
}

.btn-outline-danger {
  background: var(--danger-light);
  color: var(--danger);
  border: 1px solid rgba(217,68,82,0.2);
}
.btn-outline-danger:hover {
  background: var(--danger);
  color: #fff;
  border-color: var(--danger);
}

.btn-outline-warning {
  background: var(--warning-light);
  color: var(--warning);
  border: 1px solid rgba(229,163,56,0.2);
}
.btn-outline-warning:hover {
  background: var(--warning);
  color: #fff;
}

.btn-outline-info {
  background: var(--blue-light);
  color: var(--blue);
  border: 1px solid rgba(106,155,204,0.2);
}
.btn-outline-info:hover {
  background: var(--blue);
  color: #fff;
}

.btn-outline-success {
  background: var(--green-light);
  color: var(--green);
  border: 1px solid rgba(61,154,95,0.2);
}
.btn-outline-success:hover {
  background: var(--green);
  color: #fff;
}

.btn-success {
  background: var(--green);
  color: #fff;
  border: none;
  box-shadow: 0 1px 2px rgba(61,154,95,0.3);
}
.btn-success:hover {
  background: #2e8550;
  color: #fff;
  transform: translateY(-1px);
}

.btn-sm { padding: 5px 12px; font-size: 12px; border-radius: var(--radius-sm); }
.btn-lg { padding: 10px 24px; font-size: 14px; }

/* Compat : .btn-secondary devient outline-secondary */
.btn-secondary {
  background: var(--surface);
  color: var(--text-secondary);
  border: 1px solid var(--border);
}
.btn-secondary:hover {
  background: var(--surface-alt);
  border-color: var(--text-secondary);
  color: var(--text);
}

/* ══════════════════════════════════════
   BADGES
   ══════════════════════════════════════ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 100px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
}

.badge.bg-warning, .badge.text-bg-warning {
  background: var(--warning-light) !important;
  color: var(--warning) !important;
  border: 1px solid rgba(229,163,56,0.2);
}

.badge.bg-success, .badge.text-bg-success {
  background: var(--green-light) !important;
  color: var(--green) !important;
  border: 1px solid rgba(61,154,95,0.2);
}

.badge.bg-secondary, .badge.text-bg-secondary {
  background: var(--surface-alt) !important;
  color: var(--muted) !important;
  border: 1px solid var(--border);
}

.badge.bg-dark, .badge.text-bg-dark {
  background: var(--text) !important;
  color: #fff !important;
}

.badge.bg-info, .badge.text-bg-info {
  background: var(--blue-light) !important;
  color: var(--blue) !important;
  border: 1px solid rgba(106,155,204,0.2);
}

.badge.bg-danger, .badge.text-bg-danger {
  background: var(--danger-light) !important;
  color: var(--danger) !important;
  border: 1px solid rgba(217,68,82,0.2);
}

.badge.bg-light { background: var(--surface) !important; color: var(--text) !important; }

/* Compat : badge-status historiques */
.badge-status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 100px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
}
.badge-status.status-success { background: var(--green-light); color: var(--green); border: 1px solid rgba(61,154,95,0.2); }
.badge-status.status-pending { background: var(--warning-light); color: var(--warning); border: 1px solid rgba(229,163,56,0.2); }
.badge-status.status-error   { background: var(--danger-light);  color: var(--danger);  border: 1px solid rgba(217,68,82,0.2); }

/* ══════════════════════════════════════
   TABLES
   ══════════════════════════════════════ */
.table { font-size: 13px; }

.table th {
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  border-bottom: 1px solid var(--border-light);
  padding: 10px 16px;
  background: var(--surface-alt);
}

.table td {
  vertical-align: middle;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border-light);
  color: var(--text);
}

.table-hover > tbody > tr:hover > td { background: var(--surface-alt); }

.table-sm th, .table-sm td { padding: 8px 12px; }

/* ══════════════════════════════════════
   FORMS
   ══════════════════════════════════════ */
.form-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 5px;
  color: var(--text);
  letter-spacing: 0.02em;
}

label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 5px;
  color: var(--text);
  letter-spacing: 0.02em;
}

.form-control,
.form-select {
  padding: 9px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: 13px;
  background: var(--surface);
  color: var(--text);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
  width: 100%;
}

.form-control:focus,
.form-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(138,154,91,0.12);
}

.form-control::placeholder { color: var(--muted); }

.form-control-sm,
.form-select-sm {
  padding: 6px 10px;
  font-size: 12px;
  border-radius: var(--radius-sm);
}

textarea.form-control { resize: vertical; min-height: 60px; }

.form-text { font-size: 11px; color: var(--muted); margin-top: 4px; }

.form-check-input { border-color: var(--border); }
.form-check-input:checked { background-color: var(--accent); border-color: var(--accent); }
.form-check-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(138,154,91,0.12); }

/* ══════════════════════════════════════
   ALERTS
   ══════════════════════════════════════ */
.alert {
  padding: 12px 16px;
  border-radius: var(--radius-md);
  font-size: 13px;
  line-height: 1.5;
}

.alert-danger { background: var(--danger-light); border: 1px solid rgba(217,68,82,0.2); color: var(--danger); }
.alert-success { background: var(--green-light); border: 1px solid rgba(61,154,95,0.2); color: var(--green); }
.alert-info { background: var(--blue-light); border: 1px solid rgba(106,155,204,0.2); color: var(--blue); }
.alert-warning { background: var(--warning-light); border: 1px solid rgba(229,163,56,0.2); color: var(--warning); }

/* ══════════════════════════════════════
   DASHBOARD CARDS
   ══════════════════════════════════════ */
.card.text-bg-dark {
  background: var(--text) !important;
  border-color: var(--text);
}

.card.text-bg-warning {
  background: var(--warning-light) !important;
  color: var(--warning) !important;
  border: 1px solid rgba(229,163,56,0.2);
}
.card.text-bg-warning .card-title { color: var(--warning); }
.card.text-bg-warning .card-text { color: var(--text-secondary); }

.card.text-bg-info {
  background: var(--blue-light) !important;
  color: var(--blue) !important;
  border: 1px solid rgba(106,155,204,0.2);
}
.card.text-bg-info .card-title { color: var(--blue); }
.card.text-bg-info .card-text { color: var(--text-secondary); }

.card.text-bg-secondary {
  background: var(--surface-alt) !important;
  color: var(--text) !important;
  border: 1px solid var(--border);
}
.card.text-bg-secondary .card-title { color: var(--text); }
.card.text-bg-secondary .card-text { color: var(--text-secondary); }

.card.text-bg-success {
  background: var(--green-light) !important;
  color: var(--green) !important;
  border: 1px solid rgba(61,154,95,0.2);
}
.card.text-bg-success .card-title { color: var(--green); }
.card.text-bg-success .card-text { color: var(--text-secondary); }

.card .card-title {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 28px;
  font-weight: 700;
}

/* ══════════════════════════════════════
   EMPTY STATES
   ══════════════════════════════════════ */
.empty-state {
  text-align: center;
  padding: 48px 20px;
  color: var(--muted);
}
.empty-state .emoji { font-size: 36px; margin-bottom: 10px; }
.empty-state p { font-size: 14px; margin: 0; }

/* ══════════════════════════════════════
   KBD
   ══════════════════════════════════════ */
kbd {
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 11px;
  font-family: inherit;
  color: var(--text-secondary);
  box-shadow: 0 1px 0 var(--border);
}

/* ══════════════════════════════════════
   MODALS
   ══════════════════════════════════════ */
.modal-content {
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
}

.modal-header {
  border-bottom: 1px solid var(--border-light);
  padding: 20px 24px 16px;
}

.modal-title {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 20px;
  font-weight: 700;
}

.modal-body { padding: 20px 24px; }
.modal-footer { border-top: 1px solid var(--border-light); padding: 16px 24px 20px; }

#appAlertModal .modal-content,
#appConfirmModal .modal-content {
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.modal-icon-wrap {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-icon-wrap.icon-info { background: var(--blue-light); color: var(--blue); }
.modal-icon-wrap.icon-success { background: var(--green-light); color: var(--green); }
.modal-icon-wrap.icon-danger { background: var(--danger-light); color: var(--danger); }
.modal-icon-wrap.icon-warning { background: var(--warning-light); color: var(--warning); }

#appConfirmModal .btn-danger-confirm {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}
#appConfirmModal .btn-danger-confirm:hover { background: #c13040; border-color: #c13040; }

/* ══════════════════════════════════════
   TOAST
   ══════════════════════════════════════ */
#appToast {
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
#appToast.toast-success { background: var(--green); color: #fff; }
#appToast.toast-error { background: var(--danger); color: #fff; }
#appToast.toast-info { background: var(--text); color: #fff; }

/* ══════════════════════════════════════
   SPINNER
   ══════════════════════════════════════ */
.spinner-border { color: var(--accent); }

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
.spin { display: inline-block; animation: spin 1s linear infinite; }

/* ══════════════════════════════════════
   DARK MODE
   ══════════════════════════════════════ */
/* Le sombre suit la même logique : plus d'écart entre les plans, et un fond
   descendu assez bas pour que les surfaces se détachent. L'ancien #1a1a1e /
   #242428 laissait dix points de luminance entre le fond et les cartes ; ça ne
   suffit pas quand tout l'écran est fait de cartes. */
[data-theme="dark"] {
  --bg:           #121216;
  --surface:      #1c1c21;
  --surface-alt:  #23232a;
  --text:         #eceae5;
  --text-secondary: #a6a49c;
  --muted:        #76756d;
  --border:       #32323b;
  --border-light: #282830;

  --accent-light: rgba(138,154,91,0.16);
  --accent-ring:  rgba(138,154,91,0.34);
  --blue-light:   rgba(63,136,212,0.16);
  --green-light:  rgba(31,154,85,0.16);
  --danger-light: rgba(220,51,69,0.16);
  --warning-light: rgba(226,150,15,0.16);

  --scroll-shadow: rgba(0, 0, 0, 0.5);

  --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
  --shadow-md: 0 2px 6px rgba(0,0,0,0.35), 0 10px 28px rgba(0,0,0,0.45);
  --shadow-lg: 0 6px 14px rgba(0,0,0,0.4), 0 22px 56px rgba(0,0,0,0.55);
}

[data-theme="dark"] body { background: var(--bg); color: var(--text); }
[data-theme="dark"] .navbar { background: rgba(36,36,40,0.95) !important; border-bottom-color: var(--border); }
[data-theme="dark"] .card { background: var(--surface); border-color: var(--border); }
[data-theme="dark"] .card-header { background: var(--surface-alt); border-bottom-color: var(--border); }
[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select {
  background: var(--surface-alt);
  border-color: var(--border);
  color: var(--text);
}
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .form-select:focus {
  background: var(--surface);
  border-color: var(--accent);
  color: var(--text);
}
[data-theme="dark"] .table th { background: var(--surface-alt); color: var(--muted); border-bottom-color: var(--border); }
[data-theme="dark"] .table td { color: var(--text); border-bottom-color: var(--border); }
[data-theme="dark"] .table-hover > tbody > tr:hover > td { background: var(--surface-alt); }
[data-theme="dark"] .dropdown-menu { background: var(--surface); border-color: var(--border); }
[data-theme="dark"] .dropdown-item { color: var(--text); }
[data-theme="dark"] .dropdown-item:hover { background: var(--accent-light); color: var(--accent); }
[data-theme="dark"] .modal-content { background: var(--surface); border-color: var(--border); }
[data-theme="dark"] .btn-outline-dark,
[data-theme="dark"] .btn-secondary {
  border-color: var(--border);
  color: var(--text);
  background: var(--surface-alt);
}
[data-theme="dark"] .btn-outline-dark:hover,
[data-theme="dark"] .btn-secondary:hover { background: var(--border); }
[data-theme="dark"] .btn-outline-secondary {
  border-color: var(--border);
  color: var(--text-secondary);
  background: var(--surface-alt);
}
[data-theme="dark"] .btn-outline-secondary:hover { background: var(--border); color: var(--text); }
[data-theme="dark"] .bg-light { background: var(--bg) !important; }
[data-theme="dark"] .text-muted { color: var(--muted) !important; }
[data-theme="dark"] .text-secondary { color: var(--text-secondary) !important; }
[data-theme="dark"] kbd { background: var(--surface-alt); border-color: var(--border); color: var(--text-secondary); }
[data-theme="dark"] .list-group-item { background: var(--surface); border-color: var(--border); color: var(--text); }
[data-theme="dark"] .btn-close { filter: invert(1); }
[data-theme="dark"] .form-check-input { background-color: var(--surface-alt); border-color: var(--border); }
[data-theme="dark"] .form-check-input:checked { background-color: var(--accent); border-color: var(--accent); }
[data-theme="dark"] .navbar-toggler-icon { filter: invert(1); }
@media (max-width: 991.98px) {
  [data-theme="dark"] .navbar-collapse { background: var(--surface); border-top-color: var(--border); }
}

/* ══════════════════════════════════════
   MOBILE
   ══════════════════════════════════════ */
@media (max-width: 767.98px) {
  main.container-fluid { padding: 16px; }
  h1, h2 { font-size: 22px; }
  .btn { padding: 6px 12px; font-size: 12px; }
  .btn-lg { padding: 8px 16px; font-size: 13px; }
  .btn-sm { padding: 4px 8px; font-size: 11px; }
  td .btn-sm { padding: 3px 6px; font-size: 11px; }
  .table td, .table th { padding: 8px 10px; font-size: 12px; }
  .card-body { padding: 14px; }
  .card-header { padding: 10px 14px; }
}

/* ══════════════════════════════════════
   PRINT
   ══════════════════════════════════════ */
@media print {
  .navbar, .btn, .no-print { display: none !important; }
  .card { box-shadow: none; border: 1px solid #ddd; }
}

/* ══════════════════════════════════════
   DARK MODE — correctifs
   ──────────────────────────────────────
   Ces règles comblent des trous du design system partagé : elles valent pour
   tous les outils Ergopix, pas seulement pour celui-ci. À remonter dans le
   skill ergopix-tool (design/app.css).

   Cause racine : le bloc dark d'origine redéfinit les variables maison
   (--bg, --text, --surface…) mais laisse intactes celles de Bootstrap.
   Résultat, .card garde --bs-body-color (gris foncé) et .table garde
   --bs-table-bg (blanc) : texte illisible et lignes blanches sur fond sombre.
   ══════════════════════════════════════ */

/* 1. Neutraliser les variables Bootstrap — corrige d'un coup tous les
      composants qui les consomment, plutôt que de les rattraper un à un. */
[data-theme="dark"] {
  --bs-body-bg:          var(--bg);
  --bs-body-color:       var(--text);
  --bs-emphasis-color:   var(--text);
  --bs-secondary-color:  var(--text-secondary);
  --bs-secondary-bg:     var(--surface-alt);
  --bs-tertiary-bg:      var(--surface-alt);
  --bs-border-color:     var(--border);
  --bs-heading-color:    var(--text);
}

/* 2. Tableaux : Bootstrap peint chaque cellule avec --bs-table-bg, blanc par
      défaut. Le rendre transparent laisse passer le fond de la carte. */
[data-theme="dark"] .table {
  --bs-table-bg:            transparent;
  --bs-table-color:         var(--text);
  --bs-table-striped-bg:    var(--surface-alt);
  --bs-table-striped-color: var(--text);
  --bs-table-hover-bg:      var(--surface-alt);
  --bs-table-hover-color:   var(--text);
  --bs-table-border-color:  var(--border);
}
[data-theme="dark"] .table > :not(caption) > * > * {
  background-color: transparent;
  color: var(--text);
}

/* 3. .card n'héritait pas de la couleur de texte du thème. */
[data-theme="dark"] .card { color: var(--text); }
[data-theme="dark"] .card-header { color: var(--text); }

/* 4. text-bg-dark utilise --text comme FOND. En sombre, --text est presque
      blanc : la carte devenait blanche avec du texte blanc dessus. On
      s'aligne sur le traitement des autres cartes de statistiques —
      fond teinté, chiffre en accent. */
[data-theme="dark"] .card.text-bg-dark {
  background: var(--surface-alt) !important;
  border-color: var(--border);
  color: var(--text) !important;
}
[data-theme="dark"] .card.text-bg-dark .card-title { color: var(--accent); }
[data-theme="dark"] .card.text-bg-dark .card-text  { color: var(--text-secondary); }

/* 5. Même problème sur le badge, mais un badge est petit : l'inversion
      franche (fond clair, texte sombre) y est lisible et garde la
      sémantique « marqueur fort ». */
[data-theme="dark"] .badge.bg-dark,
[data-theme="dark"] .badge.text-bg-dark {
  background: var(--text) !important;
  color: var(--bg) !important;
}

/* 6. --muted sur --surface-alt tombait sous le seuil de contraste. */
[data-theme="dark"] .badge.bg-secondary,
[data-theme="dark"] .badge.text-bg-secondary {
  color: var(--text-secondary) !important;
}

/* 7. Le toast d'information reprenait --text en fond : même inversion. */
[data-theme="dark"] #appToast.toast-info {
  background: var(--surface-alt);
  color: var(--text);
  border: 1px solid var(--border);
}

/* 8. Divers composants Bootstrap non couverts. */
[data-theme="dark"] .form-control-color { background: var(--surface-alt); }
[data-theme="dark"] .alert-dismissible .btn-close { filter: invert(1) grayscale(1); }
[data-theme="dark"] .dropdown-divider { border-top-color: var(--border); }
[data-theme="dark"] .dropdown-item.active,
[data-theme="dark"] .dropdown-item:active {
  background: var(--accent-light);
  color: var(--accent);
}
[data-theme="dark"] code { color: var(--accent); }

/* ══════════════════════════════════════
   MODE CLAIR — correctif
   L'élément actif d'un dropdown restait sur le bleu Bootstrap par défaut,
   seule tache de bleu dans une interface bâtie sur --accent.
   ══════════════════════════════════════ */
.dropdown-item.active,
.dropdown-item:active {
  background: var(--accent-light);
  color: var(--accent);
}

/* Ascenseur des zones défilantes : blanc par défaut sur WebKit. */
[data-theme="dark"] .table-responsive,
[data-theme="dark"] .overflow-auto {
  scrollbar-color: var(--border) var(--surface);
}

/* ──────────────────────────────────────────────────────────
   Contenu traduit
   Le marqueur doit se remarquer sans se voir : il signale une
   traduction automatique, il n'est pas une action à faire.
   ────────────────────────────────────────────────────────── */

.translated {
    display: inline;
}

.translated__toggle {
    border: 0;
    background: none;
    padding: 0 0 0 .35rem;
    color: var(--muted);
    font-size: .8em;
    line-height: 1;
    vertical-align: baseline;
    cursor: pointer;
}

.translated__toggle:hover {
    color: var(--accent);
}

/* Original affiché : le marqueur passe en plein accent pour qu'on sache
   d'un coup d'œil qu'on ne lit plus la traduction. */
.translated__toggle.is-source {
    color: var(--accent);
}

.translated__text--source {
    color: var(--muted);
    font-style: italic;
}

/* Sous un champ modifiable : la traduction est là pour lecture seule. */
.translated__hint {
    display: block;
    margin-top: .35rem;
    color: var(--muted);
    font-size: .8125rem;
    line-height: 1.4;
}

.translated__hint .bi {
    margin-right: .25rem;
}

/* ──────────────────────────────────────────────────────────
   Coquille : colonne de projets + contenu
   ────────────────────────────────────────────────────────── */

/* Hauteur de la navbar, seule mesure dont la coquille a besoin. La déclarer
   ici plutôt que de la répéter en calc() : elle change avec le rembourrage de
   la barre, et il ne doit y avoir qu'un endroit à corriger. */
:root {
    --navbar-h: 60px;
}

.app-shell {
    display: flex;
    align-items: stretch;
    /* `body` est déjà une colonne flex en `min-height: 100vh` : laisser la
       coquille prendre la place restante évite toute soustraction. Le
       `calc(100vh - var(--navbar-h))` d'avant se trompait d'un pixel dès que
       la barre en mesurait 61 au lieu de 60 — assez pour faire apparaître une
       barre de défilement de page sur un écran court. */
    flex: 1 1 auto;
}

.app-main {
    flex: 1 1 auto;
    /* Sans min-width, un tableau large pousse le contenu et écrase la
       colonne : un enfant flex ne descend pas sous sa largeur intrinsèque. */
    min-width: 0;
}

.app-sidebar {
    flex: 0 0 236px;
    width: 236px;
    position: sticky;
    top: 0;
    max-height: 100vh;
    overflow-y: auto;
    padding: 1rem .5rem 1.25rem;
    border-right: 1px solid var(--border);
    background: var(--surface);
}

.app-shell.is-collapsed .app-sidebar {
    display: none;
}

.app-sidebar__head {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: 0 .5rem .6rem;
    margin-bottom: .35rem;
    border-bottom: 1px solid var(--border-light);
}

.app-sidebar__heading {
    flex: 1 1 auto;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--muted);
}

.app-sidebar__action,
.app-sidebar__switch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--muted);
    text-decoration: none;
    cursor: pointer;
}

.app-sidebar__action:hover,
.app-sidebar__switch:hover {
    background: var(--accent-light);
    color: var(--accent);
}

.app-sidebar__switch {
    margin-right: .25rem;
    flex: 0 0 auto;
}

/* ── Dossiers ──
   Deuxième niveau typographique : plus petit et plus espacé que les projets,
   pour qu'un coup d'œil sépare le rangement du contenu. */

.sidebar-folder + .sidebar-folder {
    margin-top: .85rem;
}

.sidebar-folder__head {
    display: flex;
    align-items: center;
    gap: .45rem;
    width: 100%;
    padding: .3rem .5rem;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--muted);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    text-align: left;
    cursor: pointer;
}

.sidebar-folder__head:hover { color: var(--text-secondary); }

.sidebar-folder__title {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-folder__chevron {
    font-size: 8px;
    transition: transform .15s ease;
}

.sidebar-folder.is-collapsed .sidebar-folder__chevron {
    transform: rotate(-90deg);
}

.sidebar-folder.is-collapsed .sidebar-folder__list {
    display: none;
}

.sidebar-folder__list {
    list-style: none;
    margin: .15rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

/* ── Projets ──
   Premier niveau : c'est la seule chose qu'on vient chercher ici. */

/* La bordure est posée sur TOUTES les lignes, transparente par défaut : sans
   elle, l'état actif ajoutait 2px de hauteur et toute la liste sautait d'un
   cran à chaque navigation. Une classe d'état ne doit jamais changer la boîte,
   seulement sa peinture. */
.sidebar-project {
    --tint: var(--muted);
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .4rem .5rem;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
}

.sidebar-project:hover {
    background: var(--bg);
    color: var(--text);
}

/* Vignette à initiales : elle remplace l'icône générique, qui se répétait à
   l'identique sur chaque ligne et n'apprenait donc rien. Même traitement que
   les pastilles de statut — teinte mélangée à la surface, pas un aplat. */
.sidebar-project__tile {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 6px;
    background: color-mix(in srgb, var(--tint) 16%, var(--surface));
    color: color-mix(in srgb, var(--tint) 78%, var(--text));
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .02em;
    transition: background .15s var(--ease), color .15s var(--ease);
}

.sidebar-project__name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-project__count {
    flex: 0 0 auto;
    min-width: 19px;
    padding: 1px 6px;
    border-radius: 9px;
    color: var(--muted);
    font-size: 10.5px;
    font-weight: 600;
    text-align: center;
}

/* Projet ouvert : une surface qui se soulève, pas un simple lavis. C'est
   l'élément le plus important de la colonne, il doit se lire en premier. */
.sidebar-project.is-current {
    background: var(--surface);
    color: var(--text);
    font-weight: 600;
    box-shadow: var(--shadow-sm);
    border-color: var(--border-light);
}

.sidebar-project.is-current .sidebar-project__tile {
    background: var(--tint);
    color: #fff;
}

.sidebar-project.is-current .sidebar-project__count {
    background: var(--accent-light);
    color: var(--accent);
}

.app-sidebar__empty {
    padding: .5rem;
    color: var(--muted);
    font-size: 12px;
}

.app-sidebar__all {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-top: 1rem;
    padding: .5rem;
    border-top: 1px solid var(--border-light);
    padding-top: .75rem;
    color: var(--muted);
    font-size: 12px;
    font-weight: 500;
    text-decoration: none;
}

.app-sidebar__all span { flex: 1 1 auto; }

.app-sidebar__all-chevron {
    font-size: 9px;
    opacity: 0;
    transform: translateX(-3px);
    transition: opacity .15s var(--ease), transform .15s var(--ease);
}

.app-sidebar__all:hover { color: var(--accent); }

.app-sidebar__all:hover .app-sidebar__all-chevron {
    opacity: 1;
    transform: none;
}

/* Sous 992px la colonne mangerait l'écran : elle se replie et s'ouvre
   par-dessus le contenu, comme un tiroir. */
@media (max-width: 991.98px) {
    .app-sidebar {
        position: fixed;
        /* Sous la navbar, pas par-dessus : le tiroir recouvrirait le bouton
           qui sert à le refermer. */
        top: var(--navbar-h);
        left: 0;
        bottom: 0;
        z-index: 1035;
        max-height: none;
        box-shadow: var(--shadow-lg, 0 10px 30px rgba(0, 0, 0, .18));
    }

    /* Voile : il assombrit la page et donne une cible de fermeture évidente. */
    .app-shell.is-open::after {
        content: '';
        position: fixed;
        inset: var(--navbar-h) 0 0 0;
        z-index: 1030;
        background: rgba(0, 0, 0, .35);
    }

    .app-shell:not(.is-open) .app-sidebar {
        display: none;
    }
}

/* ══════════════════════════════════════
   MODERNISATION — hiérarchie, élévation, mise au point
   ══════════════════════════════════════ */

/* ── Typographie ──
   L'ancienne échelle tenait en deux tailles : 26px pour les titres, 14px pour
   tout le reste. Sans palier intermédiaire, rien ne hiérarchise une page — d'où
   l'impression de bloc uniforme. */

h1, h2 {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.15;
}

h3 { font-size: 20px; font-weight: 650; letter-spacing: -0.02em; }
h4 { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }

/* Les chiffres qui changent en place — compteurs, badges, totaux — doivent
   avoir des glyphes de largeur constante, sinon la mise en page tressaute à
   chaque mise à jour. */
.badge,
.board-group__count,
.sidebar-project__count,
.task-row__meta,
.stat-card__value {
  font-variant-numeric: tabular-nums;
}

::selection {
  background: var(--accent-light);
  color: var(--text);
}

/* ── Mise au point clavier ──
   Un anneau d'accent visible, sur tout ce qui prend le focus. Le contour par
   défaut du navigateur disparaissait sous les bordures arrondies. */

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.form-control:focus,
.form-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

/* ── Élévation ──
   Une carte cliquable se soulève au survol : c'est le signal le moins coûteux
   qu'un élément est vivant. Réservé aux cartes qui mènent quelque part — une
   carte d'information qui bouge sous la souris ment. */

.card { transition: box-shadow .18s var(--ease), transform .18s var(--ease), border-color .18s var(--ease); }

a > .card,
.card.is-interactive {
  cursor: pointer;
}

a > .card:hover,
.card.is-interactive:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: var(--border);
}

/* ── Barre de navigation ──
   Le verre dépoli n'a de sens que si quelque chose passe dessous : on l'assume
   avec une saturation, sinon le flou grise le contenu au lieu de le tamiser. */

.navbar {
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: var(--border-light);
}

[data-theme="dark"] .navbar { background: rgba(18,18,22,0.85) !important; }

/* ── Barres de défilement ──
   Celle du système, en clair sur fond beige, tranche brutalement. */

@supports (scrollbar-width: thin) {
  .app-sidebar,
  .task-panel,
  .dropdown-menu {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
  }
}

/* ── Colonne latérale ──
   Elle borde tout l'écran : sa surface doit se distinguer du contenu sans
   entrer en concurrence avec lui. Un fond légèrement en retrait, pas blanc. */

.app-sidebar {
  background: var(--surface-alt);
  border-right-color: var(--border-light);
}

.sidebar-project {
  transition: background .14s var(--ease), color .14s var(--ease);
}

/* ── Pastilles de statut ──
   Le contour prend l'essentiel du travail de lecture ; le fond ne fait que
   teinter. Un aplat plus dense écraserait le texte de la ligne. */

.status-pill {
  font-weight: 600;
  letter-spacing: -0.005em;
  transition: filter .14s var(--ease), box-shadow .14s var(--ease);
}

button.status-pill:not(:disabled):hover {
  filter: saturate(1.15);
  box-shadow: var(--shadow-sm);
}

/* ══════════════════════════════════════
   MICRO-ANIMATIONS

   Une animation sert à expliquer un changement d'état, pas à décorer. Chacune
   de celles qui suivent répond à une question que l'utilisateur se pose :
   « où est passée ma tâche ? », « qu'est-ce qui vient d'apparaître ? »,
   « ce chiffre a-t-il bougé ? ».

   Ce qui n'est PAS animé, et volontairement : le filtrage. Il se déclenche à
   chaque frappe au clavier ; y mettre du mouvement produit du scintillement,
   pas de l'information.
   ══════════════════════════════════════ */

/* Le respect de la préférence système passe avant tout le reste. Un utilisateur
   sujet au mal des transports n'a pas à subir nos transitions. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Apparition d'une ligne ──
   Une tâche créée par l'ajout rapide apparaît en bas d'une colonne, souvent
   hors du regard. Le glissement dit où elle a atterri. */
@keyframes ergopixRowIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.task-row.is-entering {
  animation: ergopixRowIn 0.22s var(--ease) both;
}

/* ── Arrivée après un changement de colonne ──
   Changer le statut déplace la ligne. Sans signal, elle disparaît d'un endroit
   et réapparaît ailleurs : le lavis d'accent suit le regard. */
/* Un lavis seul, sans filet interne : en Kanban la ligne est arrondie et le
   filet épouserait le rayon, ce qui donne une barre tordue. */
@keyframes ergopixArrive {
  0%   { background: var(--accent-light); }
  100% { background: transparent; }
}

.task-row.is-arriving {
  animation: ergopixArrive 1.1s var(--ease) both;
}

/* ── Compteur qui change ──
   Un chiffre qui se remplace en silence ne se remarque pas. */
@keyframes ergopixBump {
  0%   { transform: none; }
  35%  { transform: scale(1.28); }
  100% { transform: none; }
}

.is-bumping {
  animation: ergopixBump 0.32s var(--ease);
  display: inline-block;
}

/* ── Retour tactile ──
   Un bouton qui s'enfonce confirme le clic avant même la réponse du serveur. */
.btn:active:not(:disabled),
.status-pill:active:not(:disabled),
.sidebar-project:active,
.app-sidebar__action:active,
.app-sidebar__switch:active {
  transform: scale(0.97);
}

.btn, .status-pill, .sidebar-project {
  transition: transform 0.09s var(--ease), background 0.15s var(--ease),
              color 0.15s var(--ease), border-color 0.15s var(--ease),
              box-shadow 0.15s var(--ease);
}

/* Le survol soulève déjà le bouton principal : sans neutralisation, le clic
   le soulève au lieu de l'enfoncer. */
.btn-dark:active:not(:disabled),
.btn-primary:active:not(:disabled) {
  transform: scale(0.97) translateY(0);
}

/* ── Tiroir de la colonne latérale ──
   Sous 992 px elle se superpose au contenu : elle doit venir de son bord,
   sinon elle paraît surgir de nulle part. */
@keyframes ergopixDrawerIn {
  from { transform: translateX(-100%); }
  to   { transform: none; }
}

@media (max-width: 991.98px) {
  .app-shell.is-open .app-sidebar {
    animation: ergopixDrawerIn 0.2s var(--ease) both;
  }

  .app-shell.is-open::after {
    animation: ergopixFadeIn 0.2s var(--ease) both;
  }
}

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

/* ══════════════════════════════════════
   FIL DU TABLEAU DE BORD
   ══════════════════════════════════════ */

.feed {
  position: sticky;
  top: calc(var(--navbar-h) + 16px);
}

.feed .card-body { max-height: 62vh; overflow-y: auto; }

.feed__unread {
  background: var(--accent) !important;
  color: #fff !important;
  font-variant-numeric: tabular-nums;
}

.feed__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--border-light);
}

.feed__item:last-child { border-bottom: none; }

/* Non lue : un filet d'accent, pas un aplat. Le fil se consulte, il ne doit
   pas ressembler à une liste d'alertes. */
.feed__item.is-unread {
  background: var(--accent-light);
  box-shadow: inset 2px 0 0 var(--accent);
}

.feed__avatar {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  font-size: 10px;
  border: none;
}

.feed__body { flex: 1 1 auto; min-width: 0; }

.feed__line {
  font-size: 12.5px;
  color: var(--text-secondary);
  line-height: 1.35;
}

.feed__task {
  display: block;
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.feed__task:hover { color: var(--accent); }

.feed__meta {
  display: block;
  color: var(--muted);
  font-size: 11.5px;
}

.feed__pill {
  flex: 0 0 auto;
  min-width: 0;
  font-size: 10px;
  padding: 2px 8px;
  cursor: default;
  align-self: center;
}

.feed__empty {
  margin: 0;
  padding: 24px 16px;
  color: var(--muted);
  font-size: 12.5px;
  text-align: center;
}

/* ══════════════════════════════════════
   RECHERCHE GLOBALE
   ══════════════════════════════════════ */

.search-trigger {
    display: flex;
    align-items: center;
    gap: .5rem;
    height: 32px;
    padding: 0 .5rem 0 .7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg);
    color: var(--muted);
    font-family: inherit;
    font-size: 12.5px;
    cursor: pointer;
    transition: border-color .15s var(--ease), color .15s var(--ease), background .15s var(--ease);
}

.search-trigger:hover {
    border-color: var(--accent);
    background: var(--surface);
    color: var(--text-secondary);
}

.search-trigger__label { min-width: 118px; text-align: left; }

.search-trigger__kbd {
    padding: 1px 5px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--surface);
    color: var(--muted);
    font-family: inherit;
    font-size: 10.5px;
}

/* Sous 1200 px la barre de navigation est déjà pleine : le déclencheur se
   réduit à sa loupe, le raccourci clavier reste. */
@media (max-width: 1199.98px) {
    .search-trigger__label,
    .search-trigger__kbd { display: none; }
    .search-trigger { padding: 0 .55rem; }
}

/* ── Palette ── */

body.has-palette { overflow: hidden; }

.palette {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding: 10vh 1rem 1rem;
}

.palette__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(23, 23, 15, .38);
    backdrop-filter: blur(2px);
}

.palette__panel {
    position: relative;
    width: min(620px, 100%);
    max-height: 70vh;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    animation: ergopixPaletteIn .16s var(--ease) both;
}

@keyframes ergopixPaletteIn {
    from { opacity: 0; transform: translateY(-8px) scale(.985); }
    to   { opacity: 1; transform: none; }
}

.palette__field {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .85rem 1rem;
    border-bottom: 1px solid var(--border-light);
    color: var(--muted);
}

.palette__input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    background: none;
    color: var(--text);
    font-family: inherit;
    font-size: 15px;
    outline: none;
}

.palette__input::-webkit-search-cancel-button { -webkit-appearance: none; }

.palette__close {
    border: 0;
    background: none;
    padding: 0;
    cursor: pointer;
}

.palette__close kbd {
    padding: 2px 6px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--bg);
    color: var(--muted);
    font-family: inherit;
    font-size: 10.5px;
}

.palette__results {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: .35rem;
}

.palette__group {
    padding: .6rem .75rem .3rem;
    color: var(--muted);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.palette__item {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .5rem .75rem;
    border-radius: var(--radius-md);
    color: var(--text);
    font-size: 13.5px;
    text-decoration: none;
}

/* Un seul état de sélection, piloté au clavier comme à la souris : deux
   surlignages concurrents laisseraient croire que Entrée ouvre celui du
   pointeur. */
.palette__item.is-active {
    background: var(--accent-light);
    color: var(--text);
}

.palette__label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.palette__label mark {
    padding: 0;
    background: none;
    color: var(--accent);
    font-weight: 700;
}

.palette__context {
    flex: 0 0 auto;
    max-width: 40%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--muted);
    font-size: 11.5px;
}

.palette__pill {
    flex: 0 0 auto;
    min-width: 0;
    padding: 1px 8px;
    font-size: 10px;
    cursor: inherit;
}

.palette__tag {
    flex: 0 0 auto;
    padding: 1px 7px;
    border-radius: 100px;
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--muted);
    font-size: 10px;
    font-weight: 600;
}

.palette__tag.is-archived {
    background: var(--warning-light);
    border-color: color-mix(in srgb, var(--warning) 32%, var(--surface));
    color: var(--warning);
}

.palette__hint {
    margin: 0;
    padding: 1.75rem 1rem;
    color: var(--muted);
    font-size: 12.5px;
    text-align: center;
}

/* ══════════════════════════════════════
   FILTRE DE STATUTS DE « MES TÂCHES »
   Une puce par statut : elle porte le compte et sert d'interrupteur. Un
   chiffre qu'on ne peut pas suivre n'explique rien.
   ══════════════════════════════════════ */

.status-filter {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 1.1rem;
}

.status-filter__chip {
    --pill: var(--muted);
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 32px;
    padding: 0 12px;
    border: 1px solid color-mix(in srgb, var(--pill) 34%, var(--surface));
    border-radius: 100px;
    background: color-mix(in srgb, var(--pill) 13%, var(--surface));
    color: color-mix(in srgb, var(--pill) 78%, var(--text));
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity .14s var(--ease), filter .14s var(--ease);
}

.status-filter__chip:hover { filter: saturate(1.2); }

/* Masqué : la puce s'efface sans disparaître — il faut pouvoir la rallumer,
   et voir d'un coup d'œil ce qu'on a mis de côté. */
.status-filter__chip.is-off {
    border-color: var(--border);
    background: none;
    color: var(--muted);
    opacity: .55;
    text-decoration: line-through;
}

.status-filter__count {
    font-variant-numeric: tabular-nums;
    opacity: .75;
}

/* ══════════════════════════════════════
   COMPTEURS DE « MON TRAVAIL »
   Trois nombres qu'on ne peut pas suivre n'expliquent rien : ce sont des
   filtres sur la liste qu'ils décrivent.
   ══════════════════════════════════════ */

.stat-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 1.25rem;
}

.stat-card {
    --tone: var(--muted);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 14px 18px;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
    text-align: left;
    cursor: pointer;
    transition: transform .15s var(--ease), box-shadow .15s var(--ease), border-color .15s var(--ease);
}

.stat-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: color-mix(in srgb, var(--tone) 40%, var(--border));
}

/* Actif : la teinte envahit la carte. Elle dit à la fois « c'est ce que tu
   regardes » et « reclique pour tout revoir ». */
.stat-card.is-active {
    border-color: color-mix(in srgb, var(--tone) 45%, var(--surface));
    background: color-mix(in srgb, var(--tone) 9%, var(--surface));
}

.stat-card--open    { --tone: var(--accent); }
.stat-card--waiting { --tone: var(--warning); }
.stat-card--done    { --tone: var(--green); }

.stat-card__value {
    color: var(--tone);
    font-size: 26px;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
}

.stat-card__label {
    color: var(--text-secondary);
    font-size: 12.5px;
    font-weight: 500;
}

@media (max-width: 575.98px) {
    .stat-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
    .stat-card { padding: 10px 12px; }
    .stat-card__value { font-size: 20px; }
    .stat-card__label { font-size: 11px; }
}

/* La ligne entière est cliquable : le curseur doit le dire. */
.task-row.is-linked { cursor: pointer; }

/* ══════════════════════════════════════
   BARRE DE NAVIGATION — côté droit
   La pastille de non-lues déborde de la cloche par construction
   (`translate-middle`) : sans respiration autour, elle empiète sur le
   sélecteur de langue et la ligne paraît serrée.
   ══════════════════════════════════════ */

.navbar .navbar-nav.ms-auto { gap: 4px; }

/* Les commandes en icône seule n'ont pas besoin du rembourrage horizontal des
   entrées de menu, mais elles ont besoin d'une cible tactile carrée. */
.navbar .navbar-nav.ms-auto > .nav-item > .nav-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 38px;
    padding: 8px 10px !important;
}

/* La cloche porte sa pastille : on lui laisse la place de déborder à droite
   sans mordre sur sa voisine. */
#notifBell { margin-right: 6px; }

#notifCount {
    /* `top-0 start-100` de Bootstrap la colle au coin ; quelques pixels de
       retrait la ramènent sur l'icône plutôt qu'à côté. */
    inset-block-start: 2px !important;
    inset-inline-start: 78% !important;
}

@media (max-width: 991.98px) {
    /* Menu déplié : les entrées reprennent leur pleine largeur, la pastille
       n'a plus de voisine à bousculer. */
    .navbar .navbar-nav.ms-auto { gap: 0; }
    .navbar .navbar-nav.ms-auto > .nav-item > .nav-link {
        justify-content: flex-start;
        min-width: 0;
        padding: 8px 14px !important;
    }
    #notifBell { margin-right: 0; }
}

/* ══════════════════════════════════════
   MOBILE
   Point de rupture unique à 768px : en dessous, on est à une main sur un
   téléphone tenu à la verticale, et les règles changent de nature — ce n'est
   pas la même mise en page en plus petit.
   ══════════════════════════════════════ */

@media (max-width: 767.98px) {

    /* ── Respiration ──
       32px de marge latérale sur 375px de large, c'est 17% de l'écran donné
       au vide. */
    main.container-fluid { padding: 16px 14px 24px; }

    h1, h2 { font-size: 22px; letter-spacing: -0.02em; }
    h3 { font-size: 17px; }

    /* ── En-tête d'écran ──
       Titre et actions s'empilent : côte à côte, le titre se retrouvait dans
       une colonne de 130px et « Refonte site vitrine » tombait sur trois
       lignes pendant que les boutons occupaient le reste. */
    .page-head { flex-direction: column; gap: 12px; }
    .page-head > .col,
    .page-head > .col-auto { flex: 1 1 auto; width: 100%; max-width: 100%; }

    /* ── Hauteur minimale des commandes ──
       Un doigt fait environ 9 mm, soit ~44 px ; sous 40 on vise à côté une fois
       sur trois. Cette règle était écrite écran par écran — et laissait donc
       toujours un écran derrière : « Projets » gardait ses boutons à 33 px et
       « Activité » douze commandes entre 25 et 32. Une règle de base, et les
       exceptions par-dessus, plutôt que l'inverse.

       Les variantes `-sm` de Bootstrap sont visées explicitement : leur
       rembourrage est plus faible que celui de la classe de base, donc la
       spécificité seule ne suffirait pas à les rattraper. */
    .btn,
    .btn-sm,
    .form-control,
    .form-select,
    .form-control-sm,
    .form-select-sm { min-height: 40px; }

    /* Deux exceptions, et elles déclarent leur propre hauteur : les segments du
       sélecteur de vue (la piste qui les contient porte la cible tactile) et
       les commandes d'une ligne de tâche (voir `--tap` dans board.css). */
    .view-switch .btn,
    .task-row .btn { min-height: 0; }

    /* Les libellés disparaissent, les icônes restent. La barre passait sinon
       sous l'écran, et « Paramètres » était littéralement inatteignable. */
    .board-actions .board-actions__label { display: none; }
    .board-actions .btn { padding-left: 12px; padding-right: 12px; }

    .feed__item .btn { min-width: 40px; }

    /* ── Un tableau à quatre colonnes n'entre pas dans 375 px ──
       Le flux d'activité tenait dans un conteneur à défilement horizontal :
       la page ne débordait pas, mais on lisait « Où » en poussant le tableau
       de côté, colonne par colonne. Chaque ligne devient un bloc, et les
       quatre cellules se répartissent sur trois rangs.

       Les quatre colonnes se désignent par leur rang plutôt que par une
       classe : l'ordre des `th` est déjà la définition du tableau, en ajouter
       une seconde en classes créerait deux vérités à tenir d'accord. */
    .table-stack thead { display: none; }
    .table-stack tbody,
    .table-stack tr,
    .table-stack td { display: block; width: auto; }

    .table-stack tr {
        display: grid;
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "quoi quand"
            "qui  qui"
            "ou   ou";
        gap: 4px 10px;
        padding: 12px 14px;
        border-bottom: 1px solid var(--border-light);
    }
    .table-stack tr:last-child { border-bottom: none; }

    .table-stack td { border: none; padding: 0; }
    .table-stack td:nth-child(1) { grid-area: quand; text-align: right; white-space: nowrap; }
    .table-stack td:nth-child(2) { grid-area: qui; }
    .table-stack td:nth-child(3) { grid-area: quoi; }
    .table-stack td:nth-child(4) { grid-area: ou; }

    /* L'état vide occupe une seule cellule en `colspan` : sans cette reprise,
       il se rangerait dans « quand », aligné à droite sur une demi-largeur. */
    .table-stack td[colspan] {
        grid-area: auto;
        grid-column: 1 / -1;
        text-align: left;
        white-space: normal;
    }

    /* Les deux commandes de la barre — tiroir de projets et menu — sont les
       premières qu'on touche en arrivant. Elles étaient à 26 et 34px. */
    .app-sidebar__switch,
    .navbar-toggler { min-width: 42px; min-height: 42px; }

    /* Le lien de retour « ← » est une cible de 21px collée au titre : on
       l'élargit sans changer sa place. */
    .page-head .d-flex > a[href^="/projets"] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 38px;
        min-height: 38px;
        margin-left: -8px;
    }

    /* Trois cartes côte à côte sur 375px donnent des chiffres illisibles. */
    .stat-row { gap: 6px; }
}

/* ══════════════════════════════════════
   BANDEAU DE CHANGEMENTS
   Il informe, il n'interrompt pas : rafraîchir un tableau pendant que
   quelqu'un déplace une carte ferait sauter son travail. Le geste reste à lui.
   ══════════════════════════════════════ */

.live-banner {
    position: fixed;
    left: 50%;
    bottom: 22px;
    z-index: 1060;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--surface));
    border-radius: 100px;
    background: var(--surface);
    color: var(--accent);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    box-shadow: var(--shadow-lg);
    cursor: pointer;
    animation: ergopixBannerIn .22s var(--ease) both;
}

@keyframes ergopixBannerIn {
    from { opacity: 0; transform: translate(-50%, 14px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}

.live-banner:hover { background: var(--accent-light); }

@media (prefers-reduced-motion: reduce) {
    .live-banner { animation: none; transform: translateX(-50%); }
}

@media (max-width: 767.98px) {
    .live-banner { bottom: 14px; font-size: 12.5px; padding: 10px 16px; }
}

/* ══════════════════════════════════════
   MENU PRINCIPAL DÉPLIÉ (mobile)

   Bootstrap empile les éléments de la barre tels quels : on se retrouvait avec
   des liens de 34px, un bouton de recherche flottant, une cloche dont la
   pastille chevauchait la ligne suivante, et une lune sans libellé. Ce n'est
   pas une barre en plus étroit — c'est une liste, et chaque entrée doit se
   lire et se toucher comme une ligne de liste.
   ══════════════════════════════════════ */

@media (max-width: 991.98px) {

    .navbar { padding: 0 14px; }

    .navbar-collapse {
        margin: 0 -14px;
        padding: 6px 8px 12px;
        border-top: 1px solid var(--border-light);
        background: var(--surface);
        max-height: calc(100vh - var(--navbar-h));
        overflow-y: auto;
    }

    /* Chaque entrée est une rangée : 48px, icône alignée, libellé visible. */
    .navbar .navbar-nav .nav-link,
    .navbar .navbar-nav .dropdown-toggle,
    .navbar .search-trigger {
        display: flex !important;
        align-items: center;
        gap: 12px;
        width: 100%;
        min-height: 48px;
        padding: 10px 12px !important;
        border-radius: var(--radius-md);
        font-size: 14px;
        text-align: left;
    }

    .nav-link__label { display: inline; }

    .navbar .navbar-nav .nav-link .bi,
    .navbar .search-trigger .bi {
        width: 20px;
        flex: 0 0 20px;
        font-size: 15px;
        text-align: center;
        margin: 0 !important;
    }

    /* La recherche cesse d'être une pastille flottante : c'est une entrée
       comme les autres, et le raccourci clavier n'a rien à faire là. */
    .navbar .search-trigger {
        border: 0;
        background: none;
        color: var(--text-secondary);
        font-weight: 500;
    }
    .navbar .search-trigger__label { display: inline; min-width: 0; }
    .navbar .search-trigger__kbd { display: none; }

    /* La pastille de non-lues quitte le coin de l'icône pour se ranger en fin
       de ligne : en absolu, elle mordait sur la rangée suivante. */
    #notifBell { position: relative; }
    #notifCount {
        position: static !important;
        transform: none !important;
        margin-left: auto;
    }

    /* Séparation entre la navigation et les outils. */
    .navbar .navbar-nav.ms-auto {
        margin-top: 6px;
        padding-top: 6px;
        border-top: 1px solid var(--border-light);
        gap: 0;
    }

    /* Les menus déroulants s'ouvrent dans le flux plutôt qu'en surimpression :
       un menu flottant dans un menu déjà déplié se superpose à lui-même. */
    .navbar .navbar-nav .dropdown-menu {
        position: static !important;
        transform: none !important;
        width: 100%;
        margin: 2px 0 6px;
        border-color: var(--border-light);
        box-shadow: none;
        background: var(--surface-alt);
    }

    .navbar .navbar-nav .dropdown-item { min-height: 44px; display: flex; align-items: center; }
}

/* ══════════════════════════════════════
   INVITE D'INSTALLATION
   ══════════════════════════════════════ */

/* Elle occupe le même coin que le bandeau de changements, mais les deux ne
   peuvent pas s'afficher ensemble : l'invite n'apparaît qu'une fois, au tout
   début, et le bandeau demande qu'il se soit passé quelque chose. Le cas ne
   vaut pas une mécanique d'empilement.

   Elle est neutre — surface et texte, pas d'accent — parce qu'elle propose,
   elle ne signale pas. Un bandeau coloré pour « voulez-vous installer ? »
   emprunte l'attention que méritent les vraies alertes. */
.pwa-install {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: 16px;
    z-index: 1055;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.pwa-install__icon { color: var(--accent); font-size: 18px; flex-shrink: 0; }

.pwa-install__text {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13px;
    color: var(--text);
}

.pwa-install .btn { flex-shrink: 0; }

/* Le lien de refus reste un lien : refuser une proposition ne se présente pas
   comme une action de même poids que l'accepter. */
.pwa-install .js-pwa-dismiss {
    color: var(--muted);
    text-decoration: none;
    padding-left: 4px;
    padding-right: 4px;
}
.pwa-install .js-pwa-dismiss:hover { color: var(--text); }

/* Sur écran large, l'invite n'a aucune raison de courir sur 1600 px. */
@media (min-width: 576px) {
    .pwa-install {
        left: auto;
        right: 22px;
        bottom: 22px;
        max-width: 460px;
    }
}

/* Une invite empilée verticalement laisse le texte respirer là où la largeur
   manque : à 375 px, « Installer Ergopix Tasks sur cet appareil ? » plus deux
   boutons sur une ligne donne trois mots par ligne et un bouton tronqué. */
@media (max-width: 400px) {
    .pwa-install {
        flex-wrap: wrap;
        row-gap: 8px;
    }
    .pwa-install__text { flex: 1 1 calc(100% - 28px); }
    .pwa-install .js-pwa-accept { margin-left: auto; }
}

/* ══════════════════════════════════════
   LOGOTYPE
   ══════════════════════════════════════ */

/* Le logotype précédent jouait sur le point de « ergopix.tasks » : gras avant,
   maigre après. « Lidaar » est un seul mot — il n'y a rien à couper, et deux
   graisses sur six lettres ne composent rien, elles se contredisent.

   Une classe, et non le style en ligne qu'il remplace : la marque apparaît sur
   deux mises en page, et deux copies d'une même déclaration finissent toujours
   par diverger. */
.wordmark {
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--text);
}

.wordmark--lg { font-size: 28px; }
