/* ── Layout ─────────────────────────────────────────────── */

.app-shell { height: 100vh; overflow-x: hidden; overflow-y: auto; display: flex; flex-direction: row; }

/* ── Sidebar ────────────────────────────────────────────── */

.sidebar {
  --sidebar-w: 240px;
  --sidebar-w-collapsed: 64px;
  width: var(--sidebar-w);
  flex: 0 0 auto;
  background: var(--surface); border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
  transition: width var(--dur-base) var(--ease-standard);
}
.sidebar.sidebar-collapsed { width: var(--sidebar-w-collapsed); }
.sidebar.sidebar-collapsed .sidebar-link-label,
.sidebar.sidebar-collapsed .sidebar-user,
.sidebar.sidebar-collapsed .sidebar-footer-btn span.sidebar-link-label { display: none; }
.sidebar.sidebar-collapsed .sidebar-link,
.sidebar.sidebar-collapsed .sidebar-group-summary { justify-content: center; }
.sidebar.sidebar-collapsed .sidebar-group { position: relative; }
.sidebar.sidebar-collapsed .sidebar-group-panel {
  position: absolute; left: calc(100% + var(--space-2)); top: 0;
  min-width: 200px; width: max-content; max-width: 260px;
  align-items: stretch; padding: var(--space-2);
  background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); z-index: 200;
}
.sidebar.sidebar-collapsed .sidebar-group-panel-title {
  display: block; color: var(--muted); font-size: var(--text-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em;
  padding: var(--space-1) var(--space-2) var(--space-2);
  margin-bottom: var(--space-1); border-bottom: 1px solid var(--border);
}
.sidebar.sidebar-collapsed:has(.sidebar-group[open]) { overflow: visible; }
.sidebar.sidebar-collapsed .sidebar-nav:has(.sidebar-group[open]) { overflow: visible; }

.sidebar-brand {
  height: 56px; flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-3);
  padding: 0 var(--space-4); border-bottom: 1px solid var(--border);
  font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600;
  white-space: nowrap; overflow: hidden;
}
.sidebar-brand-mark {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: var(--radius-sm);
  background: var(--accent); color: var(--on-accent); display: flex; align-items: center; justify-content: center;
  font-size: var(--text-sm); font-weight: 700;
}
.sidebar-brand-label span { color: var(--accent); }

.sidebar-nav {
  flex: 1 1 auto; overflow-y: auto; display: flex; flex-direction: column;
  gap: 2px; padding: var(--space-3) var(--space-2);
}

.sidebar-link, .sidebar-sublink, .sidebar-group-summary {
  display: flex; align-items: center; gap: var(--space-3);
  text-decoration: none; color: var(--muted); font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  cursor: pointer; white-space: nowrap; list-style: none;
  border-left: 3px solid transparent;
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
  /* .sidebar-sublink est aussi posé sur des <button> (voir
     portee_switcher.rs) — reset du chrome natif, sans effet sur les <a>
     existants (déjà nus par défaut). */
  appearance: none; background: none; border-top: none; border-right: none; border-bottom: none;
  font: inherit; text-align: left; width: 100%;
}
.sidebar-link:hover, .sidebar-sublink:hover, .sidebar-group-summary:hover { color: var(--text); background: var(--surface2); }
.sidebar-link[aria-current="page"], .sidebar-sublink[aria-current="page"], .sidebar-sublink.active {
  color: var(--text); background: var(--surface2); border-left-color: var(--accent);
}
.sidebar-group-summary::-webkit-details-marker { display: none; }
.sidebar-group-summary::marker { content: ""; }
.sidebar-group[open] .sidebar-group-summary, .sidebar-group-summary.active { color: var(--text); }
.sidebar-group-summary.active { border-left-color: var(--accent); }
.sidebar-link-icon { flex: 0 0 auto; display: flex; font-size: var(--text-lg); }
.sidebar-lock { flex: 0 0 auto; display: flex; margin-left: auto; font-size: var(--text-xs); opacity: .7; }

/* ── Sélecteur de portée (Tenant/Magasin, voir portee.rs) ──────────── */
.sidebar-portee-zone {
  padding: var(--space-2); border-bottom: 1px solid var(--border);
}
.sidebar-portee-chevron { flex: 0 0 auto; margin-left: auto; font-size: var(--text-xs); opacity: .6; display: flex; }
.sidebar-portee-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Le libellé du magasin courant peut être long ("Boutique Demo") : sans
   min-width:0 sur ce flex item, l'ellipsis ci-dessus n'a aucun effet et le
   rail replié (icônes seules) déborde. */
.sidebar-portee .sidebar-group-summary { min-width: 0; }
.sidebar-portee .sidebar-group-summary > .sidebar-portee-label { min-width: 0; flex: 1 1 auto; }
/* Groupement par enseigne (Tenant > Enseigne > Magasin) dans le panneau du
   sélecteur de portée — même patron que .store-multiselect-enseigne-nom. */
.sidebar-portee-enseigne {
  color: var(--muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .03em;
  padding: var(--space-2) var(--space-3) 0;
}
.sidebar-sublink-indent { padding-left: calc(var(--space-3) + var(--space-4)); }
.sidebar-group-panel {
  display: flex; flex-direction: column; gap: 2px;
  padding-left: var(--space-5); margin-top: 2px;
}
/* Masqué quand la sidebar est dépliée : le libellé du groupe est déjà
   visible juste au-dessus, dans le sommaire (voir .sidebar-group-panel-title
   plus bas pour le rail replié, où ce n'est plus le cas). */
.sidebar-group-panel-title { display: none; }

.sidebar-footer {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-top: 1px solid var(--border);
}

/* Centre de notifications (voir components/notifications.rs) — dans le
   pied de sidebar plutôt que `.sidebar-brand` (overflow: hidden, clipperait
   le panneau) : ouvre vers le haut puisqu'il est en bas de la colonne. */
.notification-center { position: relative; list-style: none; }
.notification-center > summary { list-style: none; cursor: pointer; }
.notification-center > summary::-webkit-details-marker { display: none; }
.notification-bell {
  display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  position: relative; width: 100%; padding: var(--space-1) var(--space-2);
  border-radius: var(--radius); color: var(--muted); font-size: var(--text-lg);
}
.notification-bell:hover { background: var(--surface2); color: var(--text); }
.notification-count {
  position: absolute; top: -2px; right: calc(50% - 20px);
  font-size: 10px; padding: 0 .35rem; line-height: 1.4;
}
.notification-panel {
  position: absolute; bottom: 100%; left: 0; z-index: 200; margin-bottom: var(--space-2);
  background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-2); min-width: 280px; max-width: 320px;
  max-height: 360px; overflow-y: auto; box-shadow: var(--shadow-lg);
}
.notification-empty { color: var(--muted); font-size: var(--text-sm); margin: var(--space-2); }
.notification-list { display: flex; flex-direction: column; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }
.notification-item {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2);
}
.notification-item-head { margin-bottom: var(--space-1); }
.notification-message { font-size: var(--text-sm); margin: 0 0 var(--space-1); }
.notification-link { font-size: var(--text-xs); }
.sidebar-collapse-toggle {
  align-self: flex-end; background: transparent; border: none; color: var(--muted);
  cursor: pointer; padding: var(--space-1); border-radius: var(--radius-sm); display: flex;
  transition: color var(--dur-fast), background var(--dur-fast);
}
.sidebar-collapse-toggle:hover { color: var(--text); background: var(--surface2); }
.sidebar-user { display: flex; flex-direction: column; font-size: var(--text-sm); padding: 0 var(--space-2); overflow: hidden; }
.sidebar-user-name { color: var(--text); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user-meta { color: var(--muted); font-size: var(--text-xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-footer-btn { display: flex; align-items: center; justify-content: center; gap: var(--space-2); }

#btn-logout, .btn-logout {
  background: var(--surface2); border: 1px solid var(--border);
  color: var(--muted); padding: var(--space-1) var(--space-3); border-radius: var(--radius);
  cursor: pointer; font-size: var(--text-xs);
  transition: color var(--dur-fast), border-color var(--dur-fast);
}
.btn-logout:hover { color: var(--red); border-color: var(--red); }

.container {
  flex: 1 1 auto; max-width: min(1600px, 96vw); margin: 0 auto; padding: var(--space-5); width: 100%;
  height: 100vh; overflow-x: hidden; overflow-y: auto; display: flex; flex-direction: column;
}

/* ── Login ──────────────────────────────────────────────── */

.login-screen {
  display: flex; align-items: center; justify-content: center; min-height: 100vh;
  /* Lueur radiale discrète autour de la boîte — seule touche de signature
     de cet écran, tout le reste reste sobre (voir DECISIONS_IDENTITE_VISUELLE.md §3). */
  background:
    radial-gradient(600px circle at 50% 40%, var(--accent-dim), transparent 70%),
    var(--bg);
}
.login-box {
  background: var(--surface); border: 1px solid var(--border);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius); padding: var(--space-6); width: 360px;
  box-shadow: var(--shadow-lg);
}
.login-box h2 {
  margin-bottom: var(--space-5); font-size: var(--text-xl);
  letter-spacing: .01em;
}

/* ── Champs ─────────────────────────────────────────────── */

.field { display: flex; flex-direction: column; gap: .4rem; margin-bottom: var(--space-4); }
.field label { font-size: var(--text-xs); color: var(--muted); }
.field input, .field select, .field textarea {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text); padding: .55rem .75rem; font-size: var(--text-base);
  outline: none; font-family: inherit;
  transition: border-color var(--dur-fast) var(--ease-standard);
  /* Un <select> a une largeur intrinsèque basée sur son option la plus
     longue (ex. libellés de taux de TVA) : sans width/box-sizing
     explicites, il ignore le rétrécissement de son .field parent et fait
     déborder .field-row, puis la modale entière (voir .field-row .field
     ci-dessous pour l'autre moitié du correctif). */
  width: 100%; box-sizing: border-box;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); }
/* Anneau de focus clavier (issue 9 de la revue UX, WCAG 2.4.11) — le seul
   changement de border-color ci-dessus est un signal trop faible sur ce
   thème sombre. `:focus-visible` (pas `:focus`) pour ne montrer l'anneau
   qu'à la navigation clavier, pas au clic souris. Volontairement
   `var(--accent)` directement et non `--accent-dim` (#3a2a18) : ce dernier
   est un fond sombre pour badges, bien trop proche de --bg/--surface pour
   se voir comme anneau de focus. */
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  box-shadow: 0 0 0 2px var(--accent);
}
.field textarea { resize: vertical; min-height: 5rem; font-family: monospace; font-size: var(--text-sm); }
.field-row { display: flex; gap: var(--space-4); }
/* min-width: 0 annule le min-width: auto par défaut des enfants flex —
   sans lui, un <select> à option longue empêche .field de rétrécir et
   fait déborder .field-row hors de la modale. */
.field-row .field { flex: 1; min-width: 0; }

.error { color: var(--red); font-size: var(--text-sm); margin-top: var(--space-2); min-height: 1rem; }

/* ── Boutons ────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; gap: .4rem;
  border: none; border-radius: var(--radius); padding: .55rem 1rem;
  font-size: var(--text-sm); font-weight: 500; cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-standard);
}
.btn:hover:not(:disabled) { opacity: .85; }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn-primary   { background: var(--accent); color: var(--on-accent); }
.btn-success   { background: var(--green); color: var(--on-success); }
.btn-danger    { background: var(--red); color: var(--on-accent); }
.btn-secondary { background: var(--surface2); color: var(--text); border: 1px solid var(--border); }
.btn-full { width: 100%; }

/* ── Section / cartes ───────────────────────────────────── */

.section { margin-bottom: var(--space-6); }
/* Bloc de regroupement/carte imbriqué qui contient LUI-MÊME la zone
   tabulaire principale de la vue, à côté d'autres blocs qui n'ont pas
   besoin de croître (ex. categories.rs "Éléments" sous "Paliers",
   ca/rapports.rs "Historique" sous "Magasins"/"Génération") — doit prendre
   l'espace restant du parent flex plutôt que sa hauteur de contenu, sinon
   .table-wrap (flex:1 1 auto ci-dessous) n'a rien sur quoi se baser pour
   calculer lignes_par_page. */
.table-section { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* `.section` sert aussi de simple bloc de regroupement imbriqué (ex.
   categories.rs "Paliers"/"Éléments", devices.rs "En attente"/"Bindés") —
   seule la .section RACINE de la vue routée (enfant direct de .container)
   doit devenir le conteneur flex-colonne à hauteur pleine qui laisse
   .card/.table-wrap se dimensionner sur l'espace réellement disponible
   (min-height: 0 nécessaire dans une chaîne flex) sans jamais déborder. */
.container > .section,
.container > .module-verrouille-wrap > .module-verrouille-contenu > .section {
  margin-bottom: 0; display: flex; flex-direction: column; height: 100%; min-height: 0;
}
.section-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-4); padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.section-header h1, .section-header h2 { font-size: var(--text-lg); font-weight: 600; }

.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--space-4); margin-bottom: var(--space-3);
  box-shadow: var(--shadow-sm);
}

.empty {
  text-align: center; color: var(--muted); padding: var(--space-6) var(--space-4);
}
.empty-icon { font-size: 2rem; margin-bottom: var(--space-2); }

/* ── Paramètres > Modules (activation métier, distincte du paiement) ── */

.cards-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-3);
}
.coupling-notes {
  margin: var(--space-2) 0 0; padding-left: var(--space-4);
  color: var(--muted); font-size: var(--text-sm);
}
.module-locked-note {
  display: flex; align-items: center; gap: var(--space-2);
  margin: var(--space-2) 0 0; color: var(--muted); font-size: var(--text-sm);
}

/* Interrupteur (checkbox stylée) — plus lisible qu'une simple case à cocher
   pour un état actif/inactif binaire, voir views/parametres/modules.rs. */
.switch {
  position: relative; display: inline-flex; align-items: center; gap: var(--space-2);
  cursor: pointer;
}
.switch input[type="checkbox"] {
  appearance: none; width: 2.5rem; height: 1.4rem; border-radius: 999px;
  background: var(--border); border: none; cursor: pointer; position: relative;
  transition: background var(--dur-fast);
}
.switch input[type="checkbox"]::before {
  content: ""; position: absolute; top: .15rem; left: .15rem;
  width: 1.1rem; height: 1.1rem; border-radius: 50%; background: var(--surface);
  transition: transform var(--dur-fast) var(--ease-standard);
}
.switch input[type="checkbox"]:checked { background: var(--accent); }
.switch input[type="checkbox"]:checked::before { transform: translateX(1.1rem); }
.switch input[type="checkbox"]:disabled { opacity: .5; cursor: not-allowed; }

/* ── Réception de marchandise (Stock, multi-lignes) ─────────────── */

.reception-lignes { display: flex; flex-direction: column; gap: var(--space-4); }
.reception-ligne {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2);
}
.reception-resultats {
  list-style: none; margin: var(--space-1) 0 0; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius);
  max-height: 180px; overflow-y: auto;
}
.reception-resultats li { border-bottom: 1px solid var(--border); }
.reception-resultats li:last-child { border-bottom: none; }
.reception-resultats .btn-link {
  display: block; width: 100%; text-align: left; padding: var(--space-2) var(--space-3);
  background: none; border: none; color: var(--text); cursor: pointer; font-size: var(--text-sm);
}
.reception-resultats .btn-link:hover { background: var(--surface); }
.reception-article-choisi {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
}
.reception-creation-inline {
  background: var(--surface); border: 1px dashed var(--border); border-radius: var(--radius);
  padding: var(--space-3);
}

/* ── Badges ─────────────────────────────────────────────── */

.badge {
  display: inline-block; padding: .15rem .55rem; border-radius: 999px;
  font-size: var(--text-xs); font-weight: 600;
}
.badge-accent    { background: var(--accent-dim);   color: var(--accent); }
.badge-green   { background: var(--green-dim);  color: var(--green); }
.badge-orange  { background: var(--orange-dim); color: var(--orange); }
.badge-red     { background: var(--red-dim);    color: var(--red); }
.badge-dedie     { background: var(--accent-dim);   color: var(--accent); }
.badge-itinerant { background: var(--orange-dim); color: var(--orange); }
.badge-pending   { background: var(--orange-dim); color: var(--orange); }
.badge-bound     { background: var(--green-dim);  color: var(--green); }

/* ── Onglets (sélecteur d'échelle produit) ──────────────── */

.tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--border); margin-bottom: var(--space-4); }
.tab {
  background: none; border: none; color: var(--muted); cursor: pointer;
  padding: var(--space-2) var(--space-4); font-size: var(--text-sm);
  border-bottom: 2px solid transparent;
  transition: color var(--dur-fast), border-color var(--dur-fast) var(--ease-standard);
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--text); border-bottom-color: var(--accent); }

/* ── Table ──────────────────────────────────────────────── */

/* flex:1/min-height:0 — occupe tout l'espace restant sous les filtres/
   onglets d'une vue, c'est cette hauteur mesurée (voir
   components/table_layout.rs, use_lignes_par_page) qui détermine combien
   de lignes afficher pour ne jamais déborder. */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); flex: 1 1 auto; min-height: 0; }

.pagination {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--space-3); margin-top: var(--space-3); flex: 0 0 auto;
}
.pagination-controls { display: flex; align-items: center; gap: var(--space-3); }
.pagination-info { color: var(--muted); font-size: var(--text-sm); }
table.data-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.data-table th {
  text-align: left; color: var(--muted); font-weight: 600; font-size: var(--text-xs);
  text-transform: uppercase; letter-spacing: .04em;
  padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.data-table td {
  padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border);
}
.data-table tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: var(--surface2); }
.data-table .num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.data-table .actions-col { text-align: right; white-space: nowrap; }

/* ── Modal ──────────────────────────────────────────────── */

.modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(0,0,0,.6); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
}
.modal {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-5); width: 480px; max-width: calc(100vw - 2rem);
  max-height: calc(100vh - 4rem); overflow-y: auto;
}
/* Formulaires à plusieurs colonnes par ligne (voir Modal.large) — même
   plafond de largeur viewport/hauteur que .modal, juste plus large. */
.modal.modal-lg { width: 900px; }
.modal h3 { font-size: var(--text-lg); margin-bottom: var(--space-4); }
.modal-actions { display: flex; justify-content: flex-end; gap: var(--space-3); margin-top: var(--space-4); }

/* ── Toast (notification éphémère, issues 2/7) ─────────────── */

.toast {
  position: fixed; bottom: var(--space-5); right: var(--space-5); z-index: 2000;
  max-width: 360px; padding: var(--space-3) var(--space-4);
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface3); color: var(--text);
  font-size: var(--text-sm); box-shadow: var(--shadow-lg);
  border-left: 3px solid var(--muted);
  animation: toast-in var(--dur-base) var(--ease-standard);
}
/* Succès (issue 2) : liseré vert. Info/avertissement (issue 7, accès
   refusé notamment) : liseré cuivre — ni vert (faux positif de succès), ni
   rouge (pas une erreur bloquante), juste une notification à lire. */
.toast-succes { border-left-color: var(--green); }
.toast-info   { border-left-color: var(--accent); }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Module verrouillé (entitlement) ───────────────────────── */

/* height:100%/flex passthrough — plusieurs vues (clients, campagnes,
   offres, segments, simulateur) ont leur .section racine enveloppée ici
   plutôt qu'enfant direct de .container ; sans ce passthrough, la chaîne
   flex plein écran (voir .container > .section ci-dessus) s'arrêterait à
   ce wrapper et le contenu déborderait. */
.module-verrouille-wrap { position: relative; height: 100%; display: flex; flex-direction: column; min-height: 0; }
.module-verrouille-contenu { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.module-verrouille-contenu.is-verrouille {
  filter: blur(4px); opacity: .5; pointer-events: none; user-select: none;
  min-height: 240px;
}
.module-verrouille-message {
  position: absolute; inset: 0; z-index: 10;
  display: flex; align-items: center; justify-content: center; padding: var(--space-4);
}
.module-verrouille-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-6); max-width: 360px; text-align: center;
  box-shadow: 0 4px 24px rgba(0,0,0,.15);
}
.module-verrouille-card .icon { width: 2rem; height: 2rem; color: var(--muted); margin-bottom: var(--space-3); }
.module-verrouille-card h3 { font-size: var(--text-lg); margin-bottom: var(--space-2); }
.module-verrouille-card p { color: var(--muted); font-size: var(--text-sm); }

/* ── Nomenclature (paliers, sélecteur en cascade, tags) ────── */

.palier-row { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.palier-depth { color: var(--muted); font-size: var(--text-xs); min-width: 5rem; }
.palier-row input { flex: 1; max-width: 260px; }
.error-inline { color: var(--red); font-size: var(--text-xs); }
.cascade-select { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.cascade-select-level { display: flex; flex-direction: column; gap: .3rem; flex: 1; min-width: 140px; }
.cascade-select-level label { font-size: var(--text-xs); color: var(--muted); }
.tag-chips { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-2); }
.tag-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
  padding: .2rem .3rem .2rem .7rem; font-size: var(--text-xs);
}
.tag-chip button {
  background: none; border: none; color: var(--muted); cursor: pointer;
  font-size: var(--text-sm); line-height: 1; padding: 0 .3rem;
}
.tag-chip button:hover { color: var(--red); }

/* ── Divers ─────────────────────────────────────────────── */

.spinner {
  width: 24px; height: 24px; border-radius: 50%;
  border: 3px solid var(--border); border-top-color: var(--accent);
  animation: spin .8s linear infinite; margin: var(--space-5) auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

.chain-status { display: flex; align-items: center; gap: var(--space-3); }
.chain-ok  { color: var(--green); }
.chain-err { color: var(--red); }

.pairing-code-display { text-align: center; padding: var(--space-5) 0; }
.pairing-code-display .code {
  font-family: var(--font-mono);
  font-size: 2.2rem; font-weight: 700; letter-spacing: .15em; color: var(--accent);
}
.pairing-code-display .expires { color: var(--muted); font-size: var(--text-sm); margin-top: var(--space-2); }
.pairing-code-display .countdown { font-size: var(--text-sm); margin-top: var(--space-1); }

/* ── Tableau de bord ────────────────────────────────────── */

.dashboard-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-4); padding-bottom: var(--space-3); border-bottom: 1px solid var(--border);
}
.dashboard-toolbar h1 { font-size: var(--text-lg); font-weight: 600; margin-right: auto; }

.date-presets { display: flex; gap: var(--space-2); }
.date-presets .btn.active { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }

/* Bloc HT/TTC — pilule à 2 boutons accolés partageant une bordure commune :
   distincte visuellement du bloc de vue métier (.view-toggle) ci-dessous,
   les deux étaient auparavant confondus (même classe .date-presets que les
   raccourcis de dates). */
.unit-toggle {
  display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
}
.unit-toggle .btn {
  border-radius: 0; border: none; border-right: 1px solid var(--border);
  background: transparent; color: var(--muted);
}
.unit-toggle .btn:last-child { border-right: none; }
.unit-toggle .btn.active { background: var(--accent); color: var(--on-accent); }

/* Bloc Direction/Magasin/Comptable — pilule à fond englobant, pattern
   différent du bloc HT/TTC pour rester distinguable au premier coup d'œil. */
.view-toggle {
  display: inline-flex; gap: 2px; padding: 2px;
  background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius);
}
.view-toggle .btn { border: none; border-radius: var(--radius-sm); background: transparent; color: var(--muted); }
.view-toggle .btn.active { background: var(--accent); color: var(--on-accent); }

.date-range { display: flex; align-items: center; gap: var(--space-2); }
.date-range-input {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text); padding: .45rem .6rem; font-size: var(--text-sm); font-family: inherit;
}
.date-range-sep { color: var(--muted); }

.btn-ghost { background: transparent; color: var(--muted); }
.btn-ghost:hover:not(:disabled) { background: var(--surface); color: var(--text); opacity: 1; }

/* Calendrier de sélection de plage — même esprit que .store-multiselect-panel
   (popover positionné en absolu sous le déclencheur), mais visibilité
   pilotée par un signal Rust (voir calendar_range.rs) plutôt que <details>,
   pour pouvoir se refermer au second clic. */
.calendar-range { position: relative; display: inline-block; }
.calendar-range-panel {
  position: absolute; top: 100%; left: 0; z-index: 200; margin-top: var(--space-1);
  background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-3); width: 310px;
  box-shadow: var(--shadow-lg);
}
.calendar-shortcuts {
  display: flex; flex-wrap: wrap; gap: var(--space-2); border-bottom: 1px solid var(--border);
  padding-bottom: var(--space-2); margin-bottom: var(--space-2);
}
.calendar-shortcuts .btn { flex: 1 1 28%; padding: .35rem .4rem; font-size: var(--text-xs); white-space: nowrap; }
.calendar-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-2); font-size: var(--text-sm); font-weight: 600;
}
.calendar-header .btn { padding: .2rem .6rem; }
.calendar-weekdays, .calendar-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center;
}
.calendar-weekdays span { color: var(--muted); font-size: var(--text-xs); padding: var(--space-1) 0; }
.calendar-day {
  background: transparent; border: none; color: var(--text); border-radius: var(--radius-sm);
  padding: var(--space-1) 0; cursor: pointer; font-size: var(--text-sm); font-family: inherit;
}
.calendar-day:hover:not(.calendar-day-empty) { background: var(--surface); }
.calendar-day-empty { cursor: default; }
.calendar-day.today { border: 1px solid var(--accent); }
.calendar-day.selected { background: var(--accent); color: var(--on-accent); }
.calendar-day.in-range { background: var(--accent-dim); }

.filter-note {
  color: var(--muted); font-size: var(--text-xs); margin-bottom: var(--space-3);
  padding: var(--space-2) var(--space-3); background: var(--surface2); border-radius: var(--radius-sm);
}

.color-dot {
  display: inline-block; width: .6rem; height: .6rem; border-radius: 50%;
  margin-right: var(--space-2); vertical-align: middle;
}

/* Multi-sélection de magasins — même pattern <details>/<summary> que .sidebar-group. */
.store-multiselect { position: relative; }
.store-multiselect > summary { list-style: none; }
.store-multiselect > summary::-webkit-details-marker { display: none; }
.store-multiselect-panel {
  position: absolute; top: 100%; left: 0; z-index: 200; margin-top: var(--space-1);
  background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-2); display: flex; flex-direction: column; gap: var(--space-1);
  min-width: 220px; max-height: 320px; overflow-y: auto;
  box-shadow: var(--shadow-lg);
}
.store-multiselect-item {
  display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm); cursor: pointer;
}
.store-multiselect-item:hover { background: var(--surface); }
.store-multiselect-all { border-bottom: 1px solid var(--border); margin-bottom: var(--space-1); padding-bottom: var(--space-2); }
/* Groupement par enseigne (Tenant > Enseigne > Magasin) — l'en-tête n'est
   pas cliquable (juste un repère visuel), les magasins du groupe sont
   indentés dessous pour signaler leur appartenance. */
.store-multiselect-enseigne-nom {
  color: var(--muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .03em;
  padding: var(--space-1) var(--space-2) 0; margin-top: var(--space-1);
}
.store-multiselect-item-indent { padding-left: calc(var(--space-2) + 1rem); }

.kpi-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-4); margin-bottom: var(--space-5);
}
.kpi-tile {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-4); box-shadow: var(--shadow-sm);
  animation: kpi-tile-in var(--dur-base) var(--ease-standard);
}
@keyframes kpi-tile-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
/* Bande secondaire sous le hero du dashboard CA (.hero-ca) — mêmes tuiles,
   présence visuelle volontairement réduite puisque le chiffre principal
   est déjà porté par le hero (voir DECISIONS_IDENTITE_VISUELLE.md §3). */
.kpi-row-secondary { margin-bottom: var(--space-4); }
.kpi-row-secondary .kpi-tile { box-shadow: none; padding: var(--space-3); }
.kpi-row-secondary .kpi-label { font-size: var(--text-sm); margin-bottom: var(--space-2); }
.kpi-label {
  color: var(--text); font-size: var(--text-lg); font-weight: 700;
  line-height: var(--leading-tight); margin-bottom: var(--space-3);
}
.kpi-value { font-family: var(--font-mono); font-size: var(--text-2xl); font-weight: 700; line-height: var(--leading-tight); font-variant-numeric: tabular-nums; }
.kpi-block-row {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: var(--text-sm); font-variant-numeric: tabular-nums;
  padding: .15rem 0;
}
.kpi-block-row .kpi-block-label { color: var(--muted); }
.kpi-block-row .kpi-block-value { font-family: var(--font-mono); font-weight: 600; }
.kpi-delta {
  display: inline-flex; align-items: center; gap: .2rem;
  font-size: var(--text-xs); margin-top: var(--space-2); font-variant-numeric: tabular-nums;
  padding: .1rem .5rem; border-radius: 999px;
}
.kpi-delta .icon { font-size: .9em; }
.kpi-delta-up   { color: var(--green); background: var(--green-dim); }
.kpi-delta-down { color: var(--red);   background: var(--red-dim); }

/* Hero CA du dashboard (ca/dashboard.rs) — le chiffre du jour porte l'écran
   plutôt que d'être une tuile KPI parmi d'autres ; signature de cet écran
   (voir DECISIONS_IDENTITE_VISUELLE.md §3). Reste une simple .card, juste
   surmontée de ce bloc. */
.hero-ca-figure { margin-bottom: var(--space-4); }
.hero-ca-label {
  display: block; color: var(--muted); font-size: var(--text-sm);
  margin-bottom: var(--space-1);
}
.hero-ca-value {
  font-family: var(--font-display); font-size: var(--text-3xl); font-weight: 600;
  line-height: var(--leading-tight); font-variant-numeric: tabular-nums;
}
.hero-ca-figure .kpi-delta { margin-top: var(--space-2); margin-left: 0; }

.chart-title { font-size: var(--text-base); font-weight: 600; margin-bottom: var(--space-3); color: var(--text); }

.chart-empty { color: var(--muted); font-size: var(--text-sm); text-align: center; padding: var(--space-5) 0; }

/* Courbe */
.chart-viz { position: relative; }
.chart-svg { width: 100%; height: clamp(140px, 32vw, 220px); display: block; overflow: visible; }
.chart-baseline { stroke: var(--chart-baseline); stroke-width: 1; }
.chart-grid-line { stroke: var(--chart-grid); stroke-width: 1; stroke-dasharray: 2 4; }
.chart-area {
  fill: var(--series-color); fill-opacity: 0; stroke: none;
  animation: chart-area-in var(--dur-base) var(--ease-standard) calc(var(--dur-base) * 2) forwards;
}
.chart-line {
  fill: none; stroke: var(--series-color); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 2000; stroke-dashoffset: 2000;
  animation: chart-line-draw calc(var(--dur-base) * 3) var(--ease-standard) forwards;
}
@keyframes chart-line-draw { to { stroke-dashoffset: 0; } }
@keyframes chart-area-in { to { fill-opacity: .12; } }
.chart-crosshair { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 3; }
.chart-marker { fill: var(--series-color); stroke: var(--surface); stroke-width: 2; }
.chart-x-labels {
  display: flex; justify-content: space-between; color: var(--muted);
  font-size: var(--text-xs); margin-top: var(--space-1);
}
.chart-tooltip {
  position: absolute; top: 0; transform: translate(-50%, -100%);
  background: var(--surface3); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3); font-size: var(--text-xs); white-space: nowrap;
  pointer-events: none; box-shadow: var(--shadow-md);
  animation: chart-tooltip-in var(--dur-fast) var(--ease-standard);
}
.chart-tooltip::after {
  content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: var(--surface3);
}
@keyframes chart-tooltip-in {
  from { opacity: 0; transform: translate(-50%, -95%); }
  to   { opacity: 1; transform: translate(-50%, -100%); }
}
.chart-tooltip-label { color: var(--muted); }
.chart-tooltip-value { font-family: var(--font-mono); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Heatmap jour × heure */
.heatmap-viz { margin-top: var(--space-2); }
.heatmap-grid { display: grid; gap: 2px; align-items: center; }
.heatmap-day-label {
  font-size: var(--text-xs); color: var(--muted); text-align: center;
  padding-bottom: var(--space-1);
}
.heatmap-hour-label {
  font-size: var(--text-xs); color: var(--muted); text-align: right; padding-right: var(--space-2);
}
.heatmap-cell {
  /* align-self: stretch — .heatmap-grid a align-items: center pour centrer
     verticalement les libellés texte (qui ont une hauteur intrinsèque),
     mais ça s'applique par défaut à tous les items de la grille : une
     cellule vide (pas de contenu, pas de hauteur fixée) s'effondre alors à
     hauteur 0 et devient invisible malgré son opacity. */
  align-self: stretch;
  background: var(--series-1); border-radius: 3px; cursor: default;
  opacity: calc(0.08 + var(--intensite, 0) * 0.92);
  transition: opacity var(--dur-fast) var(--ease-standard), outline-color var(--dur-fast) var(--ease-standard);
}
.heatmap-cell:hover { outline: 2px solid var(--series-1); outline-offset: -1px; }
.heatmap-tooltip-zone { min-height: 2.75rem; margin-top: var(--space-2); }
.chart-tooltip-static { position: static; transform: none; display: inline-block; }
.chart-tooltip-static::after { display: none; }

.chart-table-details { margin-top: var(--space-4); }
.chart-table-details summary { cursor: pointer; color: var(--muted); font-size: var(--text-sm); }
/* Exception volontaire au "pas de scroll" : contenu secondaire replié par
   défaut (<details>), ouvert à la demande — un scroll interne borné est
   acceptable ici, contrairement aux listes principales qui sont paginées. */
.chart-table-details .table-wrap { margin-top: var(--space-3); flex: 0 0 auto; max-height: 40vh; overflow-y: auto; }

/* Rapports BI en libre-service */
.bi-picker {
  display: flex; flex-wrap: wrap; gap: var(--space-6);
  margin-top: var(--space-3);
}
.bi-picker-titre { font-size: var(--text-sm); color: var(--muted); margin-bottom: var(--space-2); }
.bi-checkbox {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) 0; cursor: pointer; font-size: var(--text-sm);
}
.bi-actions { margin-top: var(--space-4); }
.bi-job-status { margin-top: var(--space-3); }

/* Graphique en étoile — comparaison de magasins */
.radar-summary { cursor: pointer; list-style: none; }
.radar-summary::-webkit-details-marker { display: none; }
.radar-section-body { margin-top: var(--space-4); }
.radar-viz { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.radar-svg { width: 100%; max-width: 420px; height: auto; overflow: visible; }
.radar-grid-ring { fill: none; stroke: var(--chart-grid); stroke-width: 1; }
.radar-axis { stroke: var(--chart-grid); stroke-width: 1; }
.radar-axis-label { fill: var(--muted); font-size: 10px; }
.radar-polygon {
  fill: var(--series-color); fill-opacity: .18; stroke: var(--series-color); stroke-width: 2; stroke-linejoin: round;
  transition: fill-opacity var(--dur-fast) var(--ease-standard), stroke-width var(--dur-fast) var(--ease-standard);
}
.radar-polygon-active { fill-opacity: .32; stroke-width: 3; }
.radar-vertex { fill: var(--series-color); stroke: var(--surface); stroke-width: 1.5; }
.radar-legend { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; }
.radar-legend-item {
  display: flex; align-items: center; font-size: var(--text-xs); font-weight: 600;
  background: var(--surface2); border-radius: 999px; padding: .15rem .6rem .15rem .5rem;
}
.store-multiselect-max-note { color: var(--muted); font-size: var(--text-xs); padding: var(--space-1) var(--space-2); }

/* ── Responsive ─────────────────────────────────────────── */

/* Repli automatique de la sidebar en rail d'icônes en-dessous de 1200px,
   indépendamment de la préférence persistée (`.sidebar-collapsed`) — la
   place manque avant même que l'utilisateur n'ait besoin de la replier
   manuellement. */
@media (max-width: 1200px) {
  .sidebar:not(.sidebar-collapsed) { width: var(--sidebar-w-collapsed); }
  .sidebar:not(.sidebar-collapsed) .sidebar-link-label,
  .sidebar:not(.sidebar-collapsed) .sidebar-user,
  .sidebar:not(.sidebar-collapsed) .sidebar-footer-btn span.sidebar-link-label { display: none; }
  .sidebar:not(.sidebar-collapsed) .sidebar-link,
  .sidebar:not(.sidebar-collapsed) .sidebar-group-summary { justify-content: center; }
  .sidebar:not(.sidebar-collapsed) .sidebar-group { position: relative; }
  .sidebar:not(.sidebar-collapsed) .sidebar-group-panel {
    position: absolute; left: calc(100% + var(--space-2)); top: 0;
    min-width: 200px; width: max-content; max-width: 260px;
    align-items: stretch; padding: var(--space-2);
    background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow-lg); z-index: 200;
  }
  .sidebar:not(.sidebar-collapsed) .sidebar-group-panel-title {
    display: block; color: var(--muted); font-size: var(--text-xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: .04em;
    padding: var(--space-1) var(--space-2) var(--space-2);
    margin-bottom: var(--space-1); border-bottom: 1px solid var(--border);
  }
  .sidebar:not(.sidebar-collapsed):has(.sidebar-group[open]) { overflow: visible; }
  .sidebar:not(.sidebar-collapsed) .sidebar-nav:has(.sidebar-group[open]) { overflow: visible; }
}

@media (max-width: 900px) {
  .container { padding: var(--space-3); max-width: 100vw; }
  .dashboard-toolbar { flex-direction: column; align-items: stretch; }
  .dashboard-toolbar h1 { margin-right: 0; }
  .kpi-row { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
  .store-multiselect-panel { position: static; box-shadow: none; margin-top: var(--space-2); }
}

@media (max-width: 600px) {
  .kpi-value { font-size: 1.4rem; }
  .data-table th, .data-table td { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
  .date-presets { flex-wrap: wrap; }
  .date-range { flex-wrap: wrap; }
}

/* ── Sélecteur de droits (users.rs) ─────────────────────── */
/* Groupé par catégorie (mêmes libellés que la sidebar), une ligne par
   ressource avec lecture/écriture au même niveau (icônes oeil/crayon)
   plutôt qu'une case à cocher par droit — plus rapide à parcourir. */

.permission-category {
  color: var(--muted); font-weight: 600; font-size: var(--text-xs);
  text-transform: uppercase; letter-spacing: .04em;
  margin: var(--space-4) 0 var(--space-2);
}
.permission-category:first-child { margin-top: 0; }

.permission-table { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.permission-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border);
}
.permission-row:last-child { border-bottom: none; }
.permission-row-label { font-size: var(--text-sm); }
.permission-row-checks { display: flex; gap: var(--space-4); flex-shrink: 0; }

.permission-check {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: var(--text-xs); color: var(--muted); cursor: pointer; white-space: nowrap;
}
.permission-check:has(input:checked) { color: var(--text); font-weight: 600; }
