/* ─────────────────────────────────────────────────────────────────────────────
   Kerya DZ — Design system CSS
   Variables → Reset → Layout → Sidebar → Header → Cards → Tables → Forms →
   Badges → Modals → Chat → Timeline → Misc components → Login → Responsive
───────────────────────────────────────────────────────────────────────────── */

/* ── 1. CSS Variables ──────────────────────────────────────────────────────── */
:root {
  /* Brand — emerald green */
  --brand-50:  #ecfdf5;
  --brand-100: #d1fae5;
  --brand-200: #a7f3d0;
  --brand-300: #6ee7b7;
  --brand-400: #34d399;
  --brand-500: #10b981;
  --brand-600: #059669;
  --brand-700: #047857;
  --brand-800: #065f46;
  --brand-900: #064e3b;

  /* Slate neutrals */
  --slate-50:  #f8fafc;
  --slate-100: #f1f5f9;
  --slate-200: #e2e8f0;
  --slate-300: #cbd5e1;
  --slate-400: #94a3b8;
  --slate-500: #64748b;
  --slate-600: #475569;
  --slate-700: #334155;
  --slate-800: #1e293b;
  --slate-900: #0f172a;

  /* Accent colors */
  --amber-50:  #fffbeb;
  --amber-100: #fef3c7;
  --amber-200: #fde68a;
  --amber-400: #fbbf24;
  --amber-500: #f59e0b;
  --amber-600: #d97706;
  --amber-700: #b45309;

  --blue-50:  #eff6ff;
  --blue-100: #dbeafe;
  --blue-400: #60a5fa;
  --blue-500: #3b82f6;
  --blue-600: #2563eb;
  --blue-700: #1d4ed8;

  --violet-50:  #f5f3ff;
  --violet-100: #ede9fe;
  --violet-400: #a78bfa;
  --violet-500: #8b5cf6;
  --violet-600: #7c3aed;
  --violet-700: #6d28d9;

  --rose-50:  #fff1f2;
  --rose-100: #ffe4e6;
  --rose-400: #fb7185;
  --rose-500: #f43f5e;
  --rose-600: #e11d48;
  --rose-700: #be123c;

  /* Semantic */
  --line:    var(--slate-200);
  --ink:     var(--slate-900);
  --muted:   var(--slate-500);
  --surface: #ffffff;
  --bg:      var(--slate-50);

  /* Shadows */
  --sh-sm:  0 1px 2px 0 rgb(0 0 0 / .05);
  --sh-md:  0 4px 6px -1px rgb(0 0 0 / .07), 0 2px 4px -2px rgb(0 0 0 / .05);
  --sh-lg:  0 10px 15px -3px rgb(0 0 0 / .08), 0 4px 6px -4px rgb(0 0 0 / .04);
  --sh-xl:  0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .06);

  /* Layout */
  --sidebar-w:   240px;
  --sidebar-col: 64px;
  --header-h:    60px;
  --page-max:    1400px;
  --radius:      14px;
  --radius-sm:   9px;
  --radius-lg:   18px;

  /* Neutral aliases used by charts/maps so they can be themed (default = light). */
  --card:        #ffffff;
  --chart-grid:  var(--slate-200);
  --chart-label: var(--slate-500);
  --map-popup-bg:#ffffff;
  --map-popup-fg:#1e293b;
}

/* ── Dark theme ─────────────────────────────────────────────────────────────
   Toggled via <html data-theme="dark">. We remap the slate neutral ramp (light
   ↔ dark) so every component using var(--slate-*) as a surface/text adapts with
   no per-component change, then override the semantic + accent-tint tokens. */
[data-theme="dark"] {
  --slate-50:  #0b0f17;
  --slate-100: #151a23;
  --slate-200: #232a36;
  --slate-300: #323b49;
  --slate-400: #5b6675;
  --slate-500: #8a94a3;
  --slate-600: #aab3c0;
  --slate-700: #c8cfd9;
  --slate-800: #e2e7ee;
  --slate-900: #f5f7fa;

  /* Tinted accent backgrounds → dark equivalents (badges, pills). */
  --brand-50:  #0e2a20;
  --brand-100: #123a2b;
  --amber-50:  #2a2410;
  --amber-100: #3a3216;
  --blue-50:   #12233a;
  --blue-100:  #16304d;
  --violet-50: #201a3a;
  --violet-100:#2a2350;
  --rose-50:   #331420;
  --rose-100:  #45182a;

  /* Semantic */
  --line:    #2a3340;
  --ink:     #f1f5f9;
  --muted:   #94a3b8;
  --surface: #161b24;
  --bg:      #0b0f17;

  --card:        #161b24;
  --chart-grid:  #2a3340;
  --chart-label: #94a3b8;
  --map-popup-bg:#161b24;
  --map-popup-fg:#f1f5f9;

  /* Deeper shadows for separation on dark surfaces. */
  --sh-sm:  0 1px 2px 0 rgb(0 0 0 / .4);
  --sh-md:  0 4px 6px -1px rgb(0 0 0 / .5), 0 2px 4px -2px rgb(0 0 0 / .4);
  --sh-lg:  0 10px 15px -3px rgb(0 0 0 / .55), 0 4px 6px -4px rgb(0 0 0 / .4);
  --sh-xl:  0 20px 25px -5px rgb(0 0 0 / .6), 0 8px 10px -6px rgb(0 0 0 / .5);
}

/* Leaflet popups follow the theme. */
[data-theme="dark"] .leaflet-popup-content-wrapper,
[data-theme="dark"] .leaflet-popup-tip { background: var(--map-popup-bg); color: var(--map-popup-fg); }

/* OSM only ships one (light) tile style — approximate a dark basemap with a filter instead of
   a second tile URL. Driven by [data-theme], so it also reacts to a live theme toggle, unlike
   the old CARTO dark_all/light_all pick which was fixed at map-mount time. */
[data-theme="dark"] .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(0.95) contrast(0.9); }

/* ── 2. Reset ──────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { font-size: 14px; }

body {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
  min-height: 100vh;
}

a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
input, textarea, select { font-family: inherit; font-size: inherit; }
ul, ol { list-style: none; }
img, svg { display: block; }

/* ── 3. App Layout ─────────────────────────────────────────────────────────── */
.app {
  display: flex;
  min-height: 100vh;
}

.main {
  flex: 1;
  min-width: 0;
  margin-left: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  transition: margin-left .22s ease;
}

.sidebar.collapsed ~ .main,
.app:has(.sidebar.collapsed) .main {
  margin-left: var(--sidebar-col);
}

.page {
  flex: 1;
  padding: 24px;
  overflow: auto;
}

.page-wide {
  max-width: var(--page-max);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgb(0 0 0 / .35);
  z-index: 40;
}
.backdrop.show { display: block; }

/* ── 4. Sidebar ────────────────────────────────────────────────────────────── */
.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--sidebar-w);
  background: var(--slate-900);
  display: flex;
  flex-direction: column;
  z-index: 50;
  transition: width .22s ease, transform .22s ease;
  overflow: hidden;
}

.sidebar.collapsed { width: var(--sidebar-col); }

/* Brand */
.side-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 18px 16px 14px;
  border-bottom: 1px solid rgb(255 255 255 / .06);
  white-space: nowrap;
  flex-shrink: 0;
}
.brand-mark {
  width: 36px; height: 36px;
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}
.brand-meta .name {
  font-size: 15px; font-weight: 800; color: #fff; display: block;
}
.brand-meta .role {
  font-size: 11px; color: var(--slate-400); display: block; margin-top: 1px;
}

/* Nav sections */
.side-section { padding: 8px 10px 0; }
.side-section-label {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--slate-500);
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 10px 6px 6px;
  white-space: nowrap;
  overflow: hidden;
}

.nav { display: flex; flex-direction: column; gap: 2px; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 10px;
  border-radius: 9px;
  color: var(--slate-400);
  font-size: 13.5px;
  font-weight: 500;
  white-space: nowrap;
  transition: background .12s, color .12s;
  width: 100%;
  text-align: left;
}
.nav-item:hover { background: rgb(255 255 255 / .06); color: #fff; }
.nav-item.active { background: var(--brand-700); color: #fff; }

.nav-item .ico { flex-shrink: 0; display: flex; }
.nav-item .label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.sidebar.collapsed .nav-item .label,
.sidebar.collapsed .side-section-label,
.sidebar.collapsed .brand-meta { display: none; }

.nav-count {
  font-size: 11px;
  font-weight: 700;
  background: var(--rose-500);
  color: #fff;
  border-radius: 99px;
  padding: 1px 6px;
  min-width: 18px;
  text-align: center;
}

/* Sidebar footer */
.side-foot {
  border-top: 1px solid rgb(255 255 255 / .06);
  padding: 12px 10px;
  flex-shrink: 0;
}
.side-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
  white-space: nowrap;
}
/* min-width:0 annule le min-width:auto par défaut d'un enfant flex : sans lui, un email long
   forçait .su-meta à sa largeur de contenu, poussant .side-logout (flex-shrink:0) hors du
   cadre — que .sidebar{overflow:hidden} coupait purement et simplement. */
.su-meta { min-width: 0; flex: 1; }
.su-meta .n,
.su-meta .e { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.su-meta .n { font-size: 13px; font-weight: 700; color: #fff; }
.su-meta .e { font-size: 11.5px; color: var(--slate-400); margin-top: 1px; }
.sidebar.collapsed .su-meta,
.sidebar.collapsed .side-logout { display: none; }

.side-logout {
  margin-left: auto;
  color: var(--slate-500);
  padding: 6px;
  border-radius: 8px;
  transition: color .12s, background .12s;
  flex-shrink: 0;
}
.side-logout:hover { color: var(--rose-400); background: rgb(239 68 68 / .08); }

/* ── 5. Header ─────────────────────────────────────────────────────────────── */
.header {
  height: var(--header-h);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  position: sticky;
  top: 0;
  z-index: 30;
  flex-shrink: 0;
}

.collapse-btn, .menu-btn {
  color: var(--slate-500);
  padding: 7px;
  border-radius: 8px;
  transition: background .12s, color .12s;
  display: flex;
}
.collapse-btn:hover, .menu-btn:hover { background: var(--slate-100); color: var(--ink); }
.menu-btn { display: none; }

.page-title h1 { font-size: 16px; font-weight: 800; color: var(--ink); line-height: 1.2; }
.page-title .sub { font-size: 12px; color: var(--muted); display: block; }

.spacer { flex: 1; }

.header-search {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 12px;
  border-radius: 9px;
  background: var(--slate-100);
  border: 1px solid transparent;
  transition: border-color .15s, background .15s;
  width: 220px;
  color: var(--slate-500);
}
.header-search:focus-within {
  background: var(--surface);
  border-color: var(--brand-400);
  outline: none;
}
.header-search input {
  border: none;
  background: transparent;
  outline: none;
  flex: 1;
  font-size: 13px;
  color: var(--ink);
  min-width: 0;
}
.header-search input::placeholder { color: var(--slate-400); }

.icon-btn {
  width: 36px; height: 36px;
  border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  color: var(--slate-500);
  position: relative;
  transition: background .12s, color .12s;
}
.icon-btn:hover { background: var(--slate-100); color: var(--ink); }
.icon-btn .dot {
  position: absolute;
  top: 7px; right: 7px;
  width: 8px; height: 8px;
  border-radius: 99px;
  background: var(--rose-500);
  border: 2px solid #fff;
}

.header-avatar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px 4px 4px;
  border-radius: 10px;
  transition: background .12s;
  color: var(--ink);
}
.header-avatar:hover { background: var(--slate-100); }
.ha-meta .n { font-size: 13px; font-weight: 700; }
.ha-meta .r { font-size: 11px; color: var(--muted); }

/* Role switch (prototype) */
.role-switch {
  display: flex;
  background: var(--slate-100);
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
}
.role-switch button {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--slate-500);
  transition: background .12s, color .12s;
}
.role-switch button.on {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--sh-sm);
}

/* ── 6. Cards ──────────────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--sh-sm);
}

.card-pad { padding: 16px 18px; }

.card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
}

.ch-ico {
  width: 38px; height: 38px;
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.ch-ico.blue   { background: var(--blue-50);   color: var(--blue-600); }
.ch-ico.green  { background: var(--brand-50);  color: var(--brand-700); }
.ch-ico.amber  { background: var(--amber-50);  color: var(--amber-600); }
.ch-ico.violet { background: var(--violet-50); color: var(--violet-600); }
.ch-ico.rose   { background: var(--rose-50);   color: var(--rose-600); }

.ch-text { flex: 1; min-width: 0; }
.ch-title { font-size: 14px; font-weight: 800; color: var(--ink); }
.ch-sub { font-size: 12px; color: var(--muted); margin-top: 1px; }

/* Stat cards */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

.statcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--sh-sm);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.sc-ico {
  width: 44px; height: 44px;
  border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.sc-ico.blue   { background: var(--blue-600);   color: #fff; }
.sc-ico.green  { background: var(--brand-700);  color: #fff; }
.sc-ico.amber  { background: var(--amber-500);  color: #fff; }
.sc-ico.violet { background: var(--violet-600); color: #fff; }
.sc-ico.rose   { background: var(--rose-600);   color: #fff; }
.sc-ico.gray   { background: var(--slate-500);  color: #fff; }

.sc-value {
  font-size: 32px;
  font-weight: 800;
  letter-spacing: -.5px;
  color: var(--ink);
  line-height: 1;
}
.sc-label { font-size: 13px; font-weight: 600; color: var(--slate-600); margin-top: 3px; }
.sc-meta { font-size: 12px; color: var(--muted); margin-top: 2px; }
.sc-trend {
  display: flex; align-items: center; gap: 4px;
  font-size: 12px; font-weight: 700;
  margin-top: 2px;
}
.sc-trend.up { color: var(--brand-600); }
.sc-trend.down { color: var(--rose-500); }

/* Two-column grid helper */
.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

/* ── 7. Buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border-radius: 9px;
  font-size: 13px;
  font-weight: 600;
  border: 1px solid transparent;
  transition: background .12s, border-color .12s, opacity .12s, box-shadow .12s;
  white-space: nowrap;
  flex-shrink: 0;
  cursor: pointer;
}
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:focus-visible { outline: 2px solid var(--brand-400); outline-offset: 2px; }

.btn-primary {
  background: var(--brand-700);
  color: #fff;
  border-color: var(--brand-700);
}
.btn-primary:hover:not(:disabled) { background: var(--brand-800); border-color: var(--brand-800); }

.btn-secondary {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--line);
  box-shadow: var(--sh-sm);
}
.btn-secondary:hover:not(:disabled) { background: var(--slate-50); border-color: var(--slate-300); }

.btn-danger {
  background: var(--rose-50);
  color: var(--rose-600);
  border-color: var(--rose-200);
}
.btn-danger:hover:not(:disabled) { background: var(--rose-100); border-color: var(--rose-300); }

.btn-success {
  background: var(--brand-600);
  color: #fff;
  border-color: var(--brand-600);
}
.btn-success:hover:not(:disabled) { background: var(--brand-700); }

.btn-ghost {
  background: transparent;
  color: var(--slate-600);
  border-color: transparent;
}
.btn-ghost:hover:not(:disabled) { background: var(--slate-100); color: var(--ink); }

.btn-sm  { height: 30px; padding: 0 10px; font-size: 12px; border-radius: 7px; gap: 4px; }
.btn-lg  { height: 44px; padding: 0 20px; font-size: 15px; border-radius: 11px; }
.btn-icon { width: 36px; padding: 0; }
.btn-icon.sm { width: 30px; }
.btn-block { width: 100%; }

/* Loading spinner in button */
.btn-spinner {
  width: 14px; height: 14px;
  border: 2px solid rgb(255 255 255 / .3);
  border-top-color: #fff;
  border-radius: 99px;
  animation: spin .6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── 8. Badges ─────────────────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 99px;
  white-space: nowrap;
}
.badge-dot {
  width: 6px; height: 6px;
  border-radius: 99px;
  flex-shrink: 0;
}

.badge.green  { background: var(--brand-50);  color: var(--brand-700); }
.badge.amber  { background: var(--amber-100); color: var(--amber-700); }
.badge.blue   { background: var(--blue-50);   color: var(--blue-700); }
.badge.violet { background: var(--violet-50); color: var(--violet-700); }
.badge.rose   { background: var(--rose-50);   color: var(--rose-700); }
.badge.gray   { background: var(--slate-100); color: var(--slate-600); }

.badge.green  .badge-dot { background: var(--brand-500); }
.badge.amber  .badge-dot { background: var(--amber-500); }
.badge.blue   .badge-dot { background: var(--blue-500); }
.badge.violet .badge-dot { background: var(--violet-500); }
.badge.rose   .badge-dot { background: var(--rose-500); }
.badge.gray   .badge-dot { background: var(--slate-400); }

/* Chip / tab filter */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--slate-600);
  background: var(--surface);
  border: 1px solid var(--line);
  transition: background .12s, color .12s, border-color .12s;
  cursor: pointer;
}
.chip:hover { background: var(--slate-50); border-color: var(--slate-300); }
.chip.on, .chip.active {
  background: var(--brand-700);
  color: #fff;
  border-color: var(--brand-700);
}
.chip-count {
  font-size: 11px;
  font-weight: 800;
  background: rgb(0 0 0 / .12);
  border-radius: 99px;
  padding: 1px 6px;
}
.chip.on .chip-count { background: rgb(255 255 255 / .2); }
.chip-alert { width: 6px; height: 6px; border-radius: 99px; background: var(--rose-500); }

/* Segmented control */
.seg {
  display: flex;
  background: var(--slate-100);
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
}
.seg button {
  height: 28px;
  padding: 0 10px;
  border-radius: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--slate-500);
  transition: background .12s, color .12s, box-shadow .12s;
  display: flex; align-items: center; gap: 4px;
}
.seg button:hover { color: var(--ink); }
.seg button.on {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--sh-sm);
}

/* ── 9. Form elements ──────────────────────────────────────────────────────── */
.flabel {
  font-size: 13px;
  font-weight: 600;
  color: var(--slate-700);
  display: block;
  margin-bottom: 6px;
}
.fhint { font-size: 12px; color: var(--muted); margin-top: 4px; }
.ferr  { font-size: 12px; color: var(--rose-600); margin-top: 4px; }

.input {
  width: 100%;
  height: 38px;
  padding: 0 12px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: 13.5px;
  transition: border-color .15s, box-shadow .15s;
  outline: none;
}
.input:focus { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50); }
.input.error { border-color: var(--rose-400); }
.input.has-lead { padding-left: 38px; }
.input.has-trail { padding-right: 38px; }

.input-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.input-wrap .lead {
  position: absolute;
  left: 11px;
  color: var(--slate-400);
  pointer-events: none;
  display: flex;
}
.input-wrap .trail {
  position: absolute;
  right: 8px;
  color: var(--slate-400);
  padding: 4px;
  border-radius: 6px;
  transition: color .12s;
  display: flex;
}
.input-wrap .trail:hover { color: var(--ink); }

.textarea {
  width: 100%;
  min-height: 80px;
  padding: 10px 12px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: 13.5px;
  resize: vertical;
  outline: none;
  transition: border-color .15s;
  line-height: 1.5;
}
.textarea:focus { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50); }
.textarea.error { border-color: var(--rose-400); }

.select-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.select-wrap select {
  width: 100%;
  height: 38px;
  padding: 0 32px 0 12px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: 13.5px;
  appearance: none;
  outline: none;
  cursor: pointer;
  transition: border-color .15s;
}
.select-wrap select:focus { border-color: var(--brand-500); }
.select-wrap .chev {
  position: absolute; right: 10px;
  color: var(--slate-400);
  pointer-events: none;
  display: flex;
}

/* Checkbox */
.checkbox {
  width: 16px; height: 16px;
  border-radius: 4px;
  border: 1.5px solid var(--slate-300);
  background: var(--surface);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background .12s, border-color .12s;
  flex-shrink: 0;
}
.checkbox.checked { background: var(--brand-700); border-color: var(--brand-700); }

/* ── 10. Table ─────────────────────────────────────────────────────────────── */
.tbl-wrap { overflow-x: auto; }

.tbl {
  width: 100%;
  border-collapse: collapse;
}
.tbl th {
  padding: 10px 14px;
  text-align: left;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  background: var(--slate-50);
}
.tbl td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  font-size: 13.5px;
  vertical-align: middle;
}
.tbl tbody tr:last-child td { border-bottom: none; }
.tbl tr.clickable { cursor: pointer; }
.tbl tr.clickable:hover td { background: var(--slate-50); }

.th-in { display: flex; align-items: center; gap: 4px; cursor: pointer; }
.tbl th.sortable:hover .th-in { color: var(--ink); }

/* ── Tableau à colonnes fixes ────────────────────────────────────────────────
   Le tableau des réservations portait 13 colonnes et laissait le navigateur
   répartir la largeur : chaque cellule se tassait, les noms se coupaient au
   milieu. `table-fixed` + largeurs déclarées rendent la mise en page prévisible,
   et `.truncate` coupe proprement avec une infobulle plutôt qu'en écrasant. */
.tbl-fixed { table-layout: fixed; }
.tbl-fixed td { overflow: hidden; }

/* ── Défilement horizontal plutôt que troncature ──────────────────────────────
   `table-layout: fixed` + `width: 100%` forçait le tableau à tenir dans la largeur
   disponible : les largeurs de colonnes déclarées étaient alors comprimées au prorata,
   et comme `.tbl-fixed td` porte `overflow: hidden`, le contenu était coupé net —
   typiquement le dernier bouton d'action d'une ligne, purement et simplement inatteignable.

   `min-width` rend au tableau sa largeur naturelle (la somme des colonnes déclarées).
   Dès que la fenêtre est plus étroite, c'est `.tbl-wrap { overflow-x: auto }` qui prend
   le relais et laisse faire défiler la ligne latéralement. Rien n'est plus jamais coupé :
   tout reste atteignable, au prix d'un défilement. */
.tbl-scroll { min-width: 1180px; }

/* La colonne d'actions ne se comprime pas et ne coupe pas : c'est la seule dont le contenu
   est cliquable, donc la seule où une troncature retire une fonctionnalité. */
.tbl-fixed td.cellactions { overflow: visible; }
.cellactions .row { justify-content: flex-end; flex-wrap: nowrap; }
.cellactions .btn { flex: 0 0 auto; white-space: nowrap; }

/* Indice visuel : sans lui, rien ne signale qu'il reste des colonnes à droite. */
.tbl-wrap { scrollbar-width: thin; }

/* En-tête collant : sur 40 lignes, on ne sait plus quelle colonne on lit. */
.tbl thead th { position: sticky; top: 0; z-index: 2; }

/* Cellule sur deux niveaux : information principale + contexte en petit.
   C'est ce qui permet de passer de 13 colonnes à 8 sans rien perdre. */
.cellstack { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cellstack .sub { font-size: 11.5px; color: var(--muted); line-height: 1.3; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.celluser .cu-meta { min-width: 0; }

/* Affichage compact : ~30 % de lignes visibles en plus, sans rien masquer. */
.tbl-dense td { padding: 7px 10px; font-size: 12.5px; }
.tbl-dense th { padding: 7px 10px; }
.tbl-dense .cellstack .sub { font-size: 11px; }

/* Menu « Colonnes » */
.col-menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 50;
  min-width: 220px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: 0 12px 30px rgba(15, 23, 42, .13);
}
.col-menu-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px;
  font-size: 13.5px; cursor: pointer; user-select: none;
}
.col-menu-row:hover { background: var(--slate-50); }
.col-menu-sep { height: 1px; margin: 5px 8px; background: var(--line); }

.tbl-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--muted);
}

.pager { display: flex; gap: 4px; }
.pager button {
  width: 30px; height: 30px;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 600;
  color: var(--slate-500);
  transition: background .12s;
}
.pager button:hover { background: var(--slate-100); }
.pager button.on { background: var(--brand-700); color: #fff; }
.pager button:disabled { opacity: .3; }

/* Cell helpers */
.celluser { display: flex; align-items: center; gap: 10px; }
.cu-meta .n { font-size: 13.5px; font-weight: 700; }
.cu-meta .e { font-size: 12px; color: var(--muted); margin-top: 1px; }

.cellnum { text-align: right; font-weight: 700; }
.tbl th.cellnum { text-align: right; }
.nowrap { white-space: nowrap; }
.mono { font-family: 'SF Mono', 'Fira Code', monospace; letter-spacing: -.02em; }
.strong { font-weight: 700; }
.muted { color: var(--muted); }
.n { font-weight: 700; }
.e { font-size: 12px; color: var(--muted); }

/* ── 11. Avatar ────────────────────────────────────────────────────────────── */
.av, .avatar {
  border-radius: 99px;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800;
  font-size: 13px;
  color: #fff;
  flex-shrink: 0;
  user-select: none;
  overflow: hidden;
  text-transform: uppercase;
  line-height: 1;
  letter-spacing: -.03em;
}
.av.square, .avatar.sq { border-radius: 10px; }
.avatar img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}
.av-emerald { background: var(--brand-600); }
.av-blue    { background: var(--blue-600); }
.av-amber   { background: var(--amber-500); }
.av-violet  { background: var(--violet-600); }
.av-rose    { background: var(--rose-500); }
.av-slate   { background: var(--slate-500); }

/* ── 12. Request / Request card ────────────────────────────────────────────── */
.req {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--surface);
  transition: border-color .15s, box-shadow .15s;
}
.req.urgent { border-color: var(--amber-300); background: var(--amber-50); }

.req-body { flex: 1; min-width: 0; }
.req-top {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 6px; margin-bottom: 4px;
}
.req-top .n { font-size: 14px; font-weight: 800; }
.req-top .ref { font-size: 12px; color: var(--muted); }
.req-top .urgent-tag {
  display: flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 700;
  color: var(--amber-700);
  background: var(--amber-100);
  padding: 2px 7px;
  border-radius: 99px;
}
.req-veh { font-size: 13px; color: var(--slate-600); margin-bottom: 5px; }
.req-meta {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 6px; font-size: 12.5px; color: var(--muted);
}
.req-meta .amt { font-weight: 700; color: var(--ink); }
.sep { width: 3px; height: 3px; border-radius: 99px; background: var(--slate-300); }
.req-actions { display: flex; gap: 8px; margin-top: 10px; }

/* ── 13. Toolbar ───────────────────────────────────────────────────────────── */
.toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.page-greeting h2 { font-size: 20px; font-weight: 800; letter-spacing: -.3px; }
.gdate { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

/* ── 14. Modal ─────────────────────────────────────────────────────────────── */
.modal-overlay {
  position: fixed; inset: 0;
  background: rgb(0 0 0 / .4);
  z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  animation: fadeIn .15s ease;
}
@keyframes fadeIn { from { opacity: 0; } }

.modal {
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--sh-xl);
  width: 100%;
  max-width: 480px;
  max-height: 90vh;
  display: flex; flex-direction: column;
  animation: slideUp .2s ease;
}
.modal.wide { max-width: 700px; }
@keyframes slideUp { from { transform: translateY(12px); opacity: 0; } }

.modal-head {
  display: flex; align-items: center; gap: 12px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--line);
}
.modal-ico {
  width: 40px; height: 40px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.modal-ico.blue   { background: var(--blue-50);   color: var(--blue-600); }
.modal-ico.green  { background: var(--brand-50);  color: var(--brand-700); }
.modal-ico.amber  { background: var(--amber-50);  color: var(--amber-600); }
.modal-ico.rose   { background: var(--rose-50);   color: var(--rose-600); }

.modal-title { font-size: 16px; font-weight: 800; }
.modal-desc  { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

.modal-close {
  margin-left: auto;
  color: var(--slate-400);
  padding: 6px;
  border-radius: 8px;
  transition: background .12s, color .12s;
  flex-shrink: 0;
}
.modal-close:hover { background: var(--slate-100); color: var(--ink); }

.modal-body { padding: 18px 20px; overflow-y: auto; flex: 1; }
.modal-foot {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--line);
}

/* KV (key-value) in modals */
.kv { display: flex; align-items: flex-start; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--slate-100); }
.kv:last-child { border-bottom: none; }
.kv .k { font-size: 12.5px; color: var(--muted); flex-shrink: 0; width: 120px; }
.kv .v { font-size: 13px; font-weight: 600; }
/* Money rows: the label takes the space it needs and the amount is pushed right, so a
   long label ("Frais de service collectés du client") no longer wraps inside 120px. */
.kv-money { justify-content: space-between; align-items: baseline; }
.kv-money .k { width: auto; flex-shrink: 1; padding-right: 12px; }
.kv-money .v { flex-shrink: 0; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Tuile chiffrée « libellé / montant / précision », empilée verticalement.
   NE PAS réutiliser `.kv` pour ça : `.kv` est une LIGNE clé-valeur (`display:flex` en
   direction `row`). Les trois enfants d'une tuile s'y retrouvaient côte à côte, top-alignés
   malgré des corps de 11,5 / 20 / 11 px — d'où le décalage visible entre le libellé, le
   montant et le décompte sur l'écran Abonnement. Les styles en ligne surchargeaient bien le
   padding et la bordure, mais rien ne surchargeait `display`. */
.roi-tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
}
.roi-tile .roi-label { font-size: 11.5px; }
.roi-tile .roi-value { font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums; }
.roi-tile .roi-hint  { font-size: 11px; }

/* ── 15. Dropdown ──────────────────────────────────────────────────────────────
   (Rien ici : le composant Dropdown de ui.jsx est intégralement en styles inline et
   n'émet aucune className. Les règles .dropdown-wrap / .dropdown-menu / .dd-item / .dd-sep
   qui figuraient à cet endroit ne matchaient donc rien — supprimées. C'est aussi pourquoi
   « agrandir les emojis du picker » via .bubble-actions .dropdown-menu button restait sans
   effet ; les réactions ont maintenant leur propre composant, voir .reaction-bar.) */

/* ── 16. Toast ─────────────────────────────────────────────────────────────── */
.toast-stack {
  position: fixed;
  bottom: 20px; right: 20px;
  z-index: 300;
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}

.toast {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--sh-lg);
  padding: 12px 14px;
  max-width: 340px;
  pointer-events: all;
  animation: toastIn .22s ease;
}
@keyframes toastIn { from { opacity: 0; transform: translateY(10px); } }
.toast.success { border-left: 3px solid var(--brand-500); }
.toast.error   { border-left: 3px solid var(--rose-500); }
.toast.info    { border-left: 3px solid var(--blue-500); }
.toast-ico { flex-shrink: 0; margin-top: 1px; }
.toast-title { font-size: 13.5px; font-weight: 700; }
.toast-desc  { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

/* ── 17. Empty state ───────────────────────────────────────────────────────── */
.empty-state {
  display: flex; flex-direction: column; align-items: center;
  padding: 48px 20px;
  text-align: center;
  gap: 12px;
}
.es-ico {
  width: 56px; height: 56px; border-radius: 16px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 4px;
}
.es-ico.ok  { background: var(--brand-50);  color: var(--brand-600); }
.es-ico.err { background: var(--rose-50);   color: var(--rose-500); }
.es-ico.empty { background: var(--slate-100); color: var(--slate-400); }
.es-title { font-size: 15px; font-weight: 800; }
.es-desc  { font-size: 13px; color: var(--muted); max-width: 320px; }

/* ── 18. Chat / Messages ───────────────────────────────────────────────────── */
.chat-wrap {
  display: flex;
  height: calc(100vh - var(--header-h) - 48px - 32px);
  min-height: 500px;
}

.conv-list {
  width: 300px;
  flex-shrink: 0;
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.conv-search { padding: 12px; border-bottom: 1px solid var(--line); }

.conv {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 14px;
  cursor: pointer;
  border-bottom: 1px solid var(--line);
  transition: background .1s;
  position: relative;
}
.conv:hover { background: var(--slate-50); }
.conv.active { background: var(--brand-50); }

.conv-meta { flex: 1; min-width: 0; }
.conv-top { display: flex; justify-content: space-between; align-items: center; }
.conv-top .n { font-size: 13.5px; font-weight: 700; }
.conv-top .t { font-size: 11.5px; color: var(--muted); }
.conv-prev {
  font-size: 12.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-top: 3px;
}
.conv-unread {
  width: 9px; height: 9px;
  border-radius: 99px;
  background: var(--brand-500);
  flex-shrink: 0;
}

.thread { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.thread-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.th-meta .n { font-size: 14px; font-weight: 800; }
.th-meta .r {
  font-size: 12px; color: var(--muted);
  display: flex; align-items: center; gap: 4px;
  margin-top: 2px;
}
/* overflow-x explicite : `overflow-y: auto` force déjà l'axe X à `auto` (spec CSS), donc une
   bulle large + ses boutons d'action pouvaient faire apparaître une barre horizontale. Plus
   rien n'a besoin de déborder ici — le sélecteur de réactions est rendu en portal. */
.thread-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 20px 16px; display: flex; flex-direction: column; gap: 16px; }

.bubble-row { display: flex; flex-direction: column; }
.bubble-row.them { align-items: flex-start; }
.bubble-row.me  { align-items: flex-end; }

.bubble {
  max-width: 72%;
  /* `min-width: 0` autorise la bulle à descendre sous la taille intrinsèque de son contenu.
     Sans lui, un enfant à largeur imposée (la carte de position partagée, autrefois figée à
     240px) élargit la bulle au-delà du cadre : dans la colonne fixe de 360px du détail de
     réservation, le débordement était systématique. */
  min-width: 0;
  padding: 10px 14px;
  border-radius: 14px;
  font-size: 13.5px;
  line-height: 1.5;
}
.bubble-row.them .bubble {
  background: var(--slate-100);
  border-bottom-left-radius: 4px;
}
.bubble-row.me .bubble {
  background: var(--brand-700);
  color: #fff;
  border-bottom-right-radius: 4px;
}
.bubble-time { font-size: 11px; color: var(--muted); margin-top: 4px; }

/* ── Réponses citées + réactions (parité avec le chat mobile) ─────────────── */
.bubble-row { position: relative; }

.bubble-quote {
  max-width: 72%;
  min-width: 0;
  display: flex;
  align-items: stretch;
  margin-bottom: 4px;
  border-left: 3px solid var(--brand-600);
  border-radius: 8px;
  background: var(--slate-100);
  overflow: hidden;
}
.bubble-row.me .bubble-quote { border-left-color: var(--brand-400); }
/* `min-width: 0` : sans lui un texte long refuse de se tronquer dans un conteneur flex. */
.bq-body { min-width: 0; padding: 6px 10px; }
.bq-author { font-size: 11px; font-weight: 800; color: var(--brand-700); }
.bq-text {
  font-size: 12.5px; color: var(--muted); margin-top: 1px;
  display: flex; align-items: center; gap: 5px; min-width: 0;
}
.bq-text > span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bq-icon { flex: 0 0 auto; opacity: .8; }

.bubble-reactions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.reaction {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px;
  border-radius: 99px;
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: 12px;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.reaction:hover { background: var(--slate-100); }
.reaction.mine { background: var(--brand-50); border-color: var(--brand-600); }
.reaction b { font-size: 11px; font-weight: 800; color: var(--brand-700); }

/* Répondre / réagir : révélés au survol de la bulle, pour ne pas encombrer le fil.
   Les actions sont ancrées sur .bubble-wrap (qui épouse la largeur de la bulle) et NON sur
   .bubble-row, qui occupe 100 % du panneau — c'est ce qui les envoyait à l'extrême droite,
   loin de la bulle, sur les messages entrants. */
.bubble-wrap { position: relative; display: inline-flex; flex-direction: column; max-width: 72%; }
.bubble-row.them .bubble-wrap { align-items: flex-start; }
.bubble-row.me .bubble-wrap { align-items: flex-end; }
.bubble-wrap .bubble, .bubble-wrap .bubble-quote { max-width: 100%; }

.bubble-actions {
  position: absolute; top: 0;
  display: flex; gap: 2px;
  opacity: 0; pointer-events: none;
  transition: opacity .12s;
}
/* Côté extérieur de la bulle, à quelques pixels : jamais par-dessus le texte. */
.bubble-row.them .bubble-actions { left: 100%; margin-left: 6px; }
.bubble-row.me .bubble-actions { right: 100%; margin-right: 6px; }
.bubble-row:hover .bubble-actions,
.bubble-row .bubble-actions.open { opacity: 1; pointer-events: auto; }
.bubble-actions button {
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 99px;
  background: var(--surface); color: var(--muted);
  cursor: pointer;
}
.bubble-actions button:hover { color: var(--brand-700); border-color: var(--brand-600); }

/* Barre de réactions (portal sur <body>, position: fixed posée en JS) : une rangée
   horizontale sous la bulle, façon WhatsApp. Rendue hors du fil pour échapper au clip
   d'overflow de .thread-body — un z-index ne suffit pas à sortir d'un overflow. */
.reaction-bar {
  display: flex; align-items: center; gap: 2px;
  padding: 5px 6px;
  border-radius: 99px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--sh-lg);
  animation: reaction-bar-in .12s ease-out;
}
@keyframes reaction-bar-in {
  from { opacity: 0; transform: translateY(-4px) scale(.96); }
  to   { opacity: 1; transform: none; }
}
.reaction-bar-btn {
  width: 38px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent;
  border-radius: 99px;
  font-size: 22px; line-height: 1;
  cursor: pointer;
  transition: transform .1s, background .12s;
}
.reaction-bar-btn:hover { transform: scale(1.22); background: var(--slate-100); }
.reaction-bar-btn.on { background: var(--brand-50); }
@media (prefers-reduced-motion: reduce) {
  .reaction-bar { animation: none; }
  .reaction-bar-btn:hover { transform: none; }
}

/* Lecteur vocal en échec : le bouton reste actif (il relance le chargement). */
.voice-player.failed .voice-play { border-color: var(--rose); color: var(--rose); }

.reply-banner {
  display: flex; align-items: center; gap: 8px;
  margin: 0 16px 8px;
  padding: 8px 8px 8px 10px;
  border-left: 3px solid var(--brand-600);
  border-radius: 8px;
  background: var(--slate-100);
}
.rb-author { font-size: 11.5px; font-weight: 800; color: var(--brand-700); }
.rb-text {
  font-size: 12.5px; color: var(--muted); margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: flex; align-items: center; gap: 5px; min-width: 0;
}
.rb-close {
  flex-shrink: 0; width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--muted);
  border-radius: 7px; cursor: pointer;
}
.rb-close:hover { background: var(--slate-200); color: var(--ink); }

.thread-input {
  display: flex; gap: 8px; align-items: flex-end;
  padding: 12px 16px;
  border-top: 1px solid var(--line);
  flex-shrink: 0;
}
.ti-box { flex: 1; }

/* ── 19. Timeline ──────────────────────────────────────────────────────────── */
.tl { display: flex; flex-direction: column; gap: 0; }
.tl-item { display: flex; gap: 14px; }
.tl-rail { display: flex; flex-direction: column; align-items: center; }
.tl-dot {
  width: 11px; height: 11px;
  border-radius: 99px;
  background: var(--slate-300);
  flex-shrink: 0;
  margin-top: 4px;
}
.tl-dot.today { background: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-100); animation: tl-pulse 1.4s ease-in-out infinite; }
@keyframes tl-pulse { 0%, 100% { opacity: 1; box-shadow: 0 0 0 3px var(--brand-100); } 50% { opacity: 0.55; box-shadow: 0 0 0 6px var(--brand-50, #ecfdf5); } }
.tl-line { width: 2px; flex: 1; background: var(--slate-200); margin: 4px 0; min-height: 20px; }
.tl-content { padding-bottom: 20px; flex: 1; min-width: 0; }
.tl-when { font-size: 11.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px; }
.tl-main { display: flex; align-items: center; gap: 10px; background: var(--slate-50); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.tl-main + .tl-main { margin-top: 8px; }
.tl-main .m1 { font-size: 13.5px; font-weight: 700; }
.tl-main .m2 { font-size: 12.5px; color: var(--muted); }
.tl-end { margin-left: auto; font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 4px; }

/* ── 20. Quick links ───────────────────────────────────────────────────────── */
.qlinks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.qlink {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-align: left;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
}
.qlink:hover { border-color: var(--brand-300); box-shadow: var(--sh-md); }
.ql-ico { flex-shrink: 0; }
.ql-t { font-size: 14px; font-weight: 700; }
.ql-s { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.ql-arrow { margin-left: auto; color: var(--slate-300); }

/* ── 21. Vehicle photo placeholder ────────────────────────────────────────── */
.vphoto {
  border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
  position: relative;
  background: var(--slate-100);
}
.vphoto-tint { position: absolute; inset: 0; opacity: .18; }
.vphoto svg { position: relative; z-index: 1; }

/* Vehicle spec pill */
.vspec {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 600;
  color: var(--slate-600);
  background: var(--slate-100);
  border-radius: 7px;
  padding: 4px 9px;
}

/* ── 22. Detail page ───────────────────────────────────────────────────────── */
.detail-head {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 10px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.dh-ref { font-size: 16px; font-weight: 800; font-family: 'SF Mono', monospace; }

.detail-grid {
  display: grid;
  grid-template-columns: 1fr 360px;
  gap: 14px;
  align-items: start;
}

/* ── 23. Misc helpers ──────────────────────────────────────────────────────── */
.row { display: flex; align-items: center; }
.between { display: flex; align-items: center; justify-content: space-between; }
.banner-info {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px;
  background: var(--blue-50);
  border: 1px solid var(--blue-100);
  border-radius: 10px;
  font-size: 13px;
  color: var(--blue-700);
}
.banner-warn {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px;
  background: var(--amber-50);
  border: 1px solid var(--amber-200);
  border-radius: 10px;
  font-size: 13px;
  color: var(--amber-700);
}
.lf-banner {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  background: var(--rose-50);
  border: 1px solid var(--rose-200);
  border-radius: 9px;
  font-size: 13px;
  color: var(--rose-700);
  margin-bottom: 14px;
}

/* ── 24. Login page ────────────────────────────────────────────────────────── */
.login {
  display: flex;
  min-height: 100vh;
}

.login-left {
  flex: 1;
  background: var(--slate-900);
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 40px 48px;
  gap: 0;
}
.ll-grain {
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.03'/%3E%3C/svg%3E");
  opacity: .4;
  pointer-events: none;
}
.ll-routes {
  position: absolute; inset: 0;
  pointer-events: none;
}
.ll-routes svg { width: 100%; height: 100%; }
.ll-top {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: auto;
  position: relative;
}
.ll-brand { font-size: 20px; font-weight: 800; color: #fff; }
.ll-brand span { color: var(--brand-400); }
.ll-mid {
  position: relative;
  margin-top: auto;
  margin-bottom: 48px;
}
.ll-mid h1 {
  font-size: 36px; font-weight: 800; color: #fff;
  line-height: 1.15; letter-spacing: -.5px;
  margin-bottom: 16px;
}
.ll-mid p { font-size: 15px; color: var(--slate-400); line-height: 1.6; max-width: 400px; }
.ll-stats { display: flex; gap: 32px; position: relative; }
.ll-stat .v { font-size: 22px; font-weight: 800; color: #fff; }
.ll-stat .l { font-size: 13px; color: var(--slate-400); margin-top: 3px; }

.login-right {
  width: 480px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
  background: var(--surface);
}

.login-form {
  width: 100%;
  max-width: 380px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.lf-mark {
  display: flex;
  justify-content: center;
  margin-bottom: 8px;
}
.lf-mark .brand-mark { width: 48px; height: 48px; border-radius: 14px; font-size: 24px; }
.login-form h2 { font-size: 24px; font-weight: 800; text-align: center; letter-spacing: -.3px; }
.lf-sub { font-size: 14px; color: var(--muted); text-align: center; margin-top: -8px; }
.lf-row {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 13px;
}
.lf-remember { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.lf-forgot { color: var(--brand-700); font-weight: 600; }
.lf-foot { font-size: 13px; text-align: center; color: var(--muted); }
.lf-foot a { color: var(--brand-700); font-weight: 600; }
.lf-hint {
  display: flex; align-items: center; gap: 6px; justify-content: center;
  font-size: 12px; color: var(--slate-400);
}
/* Live password-policy checklist on the reset screen. */
.lf-rules {
  list-style: none; margin: -6px 0 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px;
}
.lf-rules li {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--muted); transition: color .15s;
}
.lf-rules li.ok { color: var(--brand-700); font-weight: 600; }
.lf-rule-dot {
  width: 14px; height: 14px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.lf-rule-dot::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: var(--slate-300);
}
/* Neutral informational note (e.g. "regardez vos spams"). */
.lf-note {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 11px 13px; border-radius: 10px;
  background: var(--blue-50); border: 1px solid var(--blue-100);
  color: var(--blue-700); font-size: 12.5px; line-height: 1.5;
}
.lf-note svg { flex-shrink: 0; margin-top: 1px; }

.phone-wrap {
  display: flex;
  border: 1px solid var(--line);
  border-radius: 9px;
  overflow: hidden;
  background: var(--surface);
  transition: border-color .15s;
}
.phone-wrap:focus-within { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50); }
.phone-wrap.err { border-color: var(--rose-500, #f43f5e); }
/* Le préfixe est devenu un <select> : il doit garder l'apparence d'une puce, pas d'un champ.
   `appearance:none` retire la flèche native (inutilisable au chevron près) ; le chevron est
   redessiné en image de fond pour rester lisible en thème sombre. */
.phone-select {
  appearance: none; -webkit-appearance: none;
  border: 0; border-right: 1px solid var(--line);
  color: inherit; cursor: pointer;
  padding-inline-end: 26px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2394a3b8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
}
[dir="rtl"] .phone-select { background-position: left 9px center; }
.phone-select:focus { outline: none; }
.phone-prefix {
  display: flex; align-items: center; gap: 6px;
  padding: 0 12px;
  background: var(--slate-50);
  border-right: 1px solid var(--line);
  font-size: 13.5px; font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}
.phone-wrap input {
  flex: 1;
  height: 38px;
  padding: 0 12px;
  border: none;
  outline: none;
  font-size: 13.5px;
  background: transparent;
}

/* ── 25. Skeleton ──────────────────────────────────────────────────────────── */
.sk {
  background: linear-gradient(90deg, var(--slate-200) 25%, var(--slate-100) 50%, var(--slate-200) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s ease infinite;
  border-radius: 6px;
  display: block;
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* ── 26. Area chart ────────────────────────────────────────────────────────── */
.area-chart { position: relative; width: 100%; user-select: none; }
.ac-hover { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--slate-300); pointer-events: none; }
.ac-val {
  position: absolute; top: 0;
  background: var(--ink);
  color: #fff;
  font-size: 12px; font-weight: 700;
  padding: 3px 7px;
  border-radius: 6px;
  transform: translateX(-50%);
  white-space: nowrap;
}

/* ── 27. Vehicle cards (fleet grid) ───────────────────────────────────────── */
.fleet {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
}
.vcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--sh-sm);
  transition: box-shadow .15s;
}
.vcard:hover { box-shadow: var(--sh-md); }
.vcard-photo {
  height: 160px;
  position: relative;
  overflow: hidden;
  background: var(--slate-100);
}
.vcard-photo > * { width: 100%; height: 100%; }
.vcard-overlay {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
}
.vcard-overlay.amber { background: rgb(245 158 11 / .15); }
.vcard-overlay.rose  { background: rgb(239 68 68 / .15); }
.vcard-status-mid {
  display: flex; align-items: center; gap: 6px;
  background: rgb(255 255 255 / .9);
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 12.5px;
  font-weight: 700;
}
.vcard-badge {
  position: absolute; top: 10px; left: 10px;
}
.vcard-fav {
  position: absolute; top: 8px; right: 8px;
  width: 30px; height: 30px;
  border-radius: 8px;
  background: rgb(255 255 255 / .9);
  display: flex; align-items: center; justify-content: center;
  color: var(--slate-500);
  transition: color .12s;
}
.vcard-fav:hover { color: var(--ink); }
.vcard-body { padding: 14px 16px; }
.vc-title { font-size: 15px; font-weight: 800; }
.vc-sub {
  font-size: 12.5px; color: var(--muted);
  display: flex; align-items: center; gap: 5px;
  margin-top: 3px;
}
.vcard-specs { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.vcard-foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--line);
}
.vcard-price { font-weight: 800; font-size: 16px; }
.vcard-price span { font-size: 12px; font-weight: 500; color: var(--muted); }
.vcard-rating {
  display: flex; align-items: center; gap: 4px;
  font-size: 13px; font-weight: 700;
}
.vcard-actions {
  display: flex; gap: 7px; margin-top: 12px; flex-wrap: wrap;
}

/* ── 28. Calendar ──────────────────────────────────────────────────────────── */
.cal-legend { display: flex; gap: 16px; }
.cal-legend .li { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; }
.sw { display: block; width: 24px; height: 14px; border-radius: 4px; }

.cal-grid {
  display: grid;
  /* minmax(0,1fr) (not the default minmax(auto,1fr)) so long nowrap event chips can't inflate
     a column's min-width and push the last columns (Sam/Dim) past the card edge, where
     overflow:hidden would clip them. */
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
}
.cal-dow {
  background: var(--slate-50);
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  padding: 10px 4px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.cal-cell {
  background: var(--surface);
  min-height: 90px;
  min-width: 0; /* allow the cell to shrink below its content so chips ellipsize instead of overflowing */
  padding: 8px;
  cursor: pointer;
  transition: background .1s;
  position: relative;
}
.cal-cell:hover { background: var(--slate-50); }
.cal-cell.out { background: var(--slate-50); cursor: default; }
.cal-cell.today .cal-num {
  background: var(--brand-700);
  color: #fff;
  border-radius: 99px;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
}
.cal-num {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 6px;
  display: inline-block;
  padding: 2px 4px;
}
.cal-cell.out .cal-num { color: var(--slate-300); }
.cal-ev {
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 4px;
  margin-bottom: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-left: 3px solid;
}
.cal-ev.confirmed { background: var(--brand-50);  border-left-color: var(--brand-600); color: var(--brand-800); }
.cal-ev.pending   { background: var(--amber-100); border-left-color: var(--amber-500); color: var(--amber-800); }
.cal-ev.blocked   { background: var(--slate-200); border-left-color: var(--slate-500); color: var(--slate-700); }
.cal-ev.more      { background: transparent; border-left-color: transparent; color: var(--muted); font-weight: 700; }

.cal-mini { display: grid; grid-template-columns: repeat(auto-fill, minmax(26px, 1fr)); gap: 3px; }
.cal-mini-cell {
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 600; border-radius: 4px;
  background: var(--slate-50); color: var(--muted); cursor: pointer;
}
.cal-mini-cell:hover { outline: 1.5px solid var(--slate-300); }
.cal-mini-cell.today { outline: 1.5px solid var(--brand-600); }
.cal-mini-cell.confirmed { background: var(--brand-50); color: var(--brand-800); }
.cal-mini-cell.pending   { background: var(--amber-100); color: var(--amber-800); }
.cal-mini-cell.blocked   { background: var(--slate-200); color: var(--slate-700); }

.day-sep {
  text-align: center;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 8px 0;
  position: relative;
}
.day-sep::before, .day-sep::after {
  content: '';
  position: absolute;
  top: 50%; width: 30%;
  height: 1px;
  background: var(--line);
}
.day-sep::before { left: 0; }
.day-sep::after  { right: 0; }

/* ── 29. Profile ───────────────────────────────────────────────────────────── */
.profile-grid {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 16px;
  align-items: start;
}
.id-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 28px 20px;
}
.id-logo-wrap {
  position: relative;
  margin-bottom: 14px;
}
.id-logo {
  width: 80px; height: 80px;
  border-radius: 22px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  color: #fff;
  box-shadow: 0 4px 16px rgba(0,0,0,.15);
}
.id-logo-overlay {
  position: absolute; inset: 0;
  border-radius: 22px;
  background: rgba(0,0,0,.4);
  display: flex; align-items: center; justify-content: center;
}
.spin-sm {
  width: 20px; height: 20px;
  border: 2px solid rgba(255,255,255,.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}

/* ── 30. Responsive ────────────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
  .sidebar {
    transform: translateX(-100%);
    width: var(--sidebar-w) !important;
  }
  .sidebar.open { transform: translateX(0); }
  .main { margin-left: 0 !important; }
  .menu-btn { display: flex; }
  .collapse-btn { display: none; }
  .detail-grid { grid-template-columns: 1fr; }
  .qlinks { grid-template-columns: 1fr; }
  .login-left { display: none; }
  .login-right { width: 100%; }
}

@media (max-width: 640px) {
  .page { padding: 14px; }
  .stat-grid { grid-template-columns: 1fr; }
  .grid-2 { grid-template-columns: 1fr !important; }
  .header-search { display: none; }
  .role-switch { display: none; }
  .ha-meta { display: none; }
  .chat-wrap { height: calc(100vh - var(--header-h) - 28px - 28px); }
  .conv-list { width: 100%; }
  .chat-wrap:not(.show-thread) .thread { display: none; }
  .chat-wrap.show-thread .conv-list { display: none; }
  .chat-wrap.show-thread .thread { display: flex; }
  #back-thread { display: flex !important; }
}

/* ─── Leaflet z-index fix (keep below modals at z-index 100) ───── */
.leaflet-pane,
.leaflet-control,
.leaflet-top,
.leaflet-bottom { z-index: 10 !important; }
.leaflet-map-pane { z-index: 10 !important; }
.leaflet-popup-pane { z-index: 15 !important; }
.leaflet-control-container { z-index: 15 !important; }

/* ─── Onboarding / Lessor signup ────────────────────────────────── */
.ob-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  padding: 24px;
}
.ob-card {
  width: 100%;
  max-width: 520px;
  background: var(--surface);
  border-radius: 20px;
  border: 1px solid var(--border);
  box-shadow: 0 4px 32px rgba(0,0,0,.07);
  overflow: hidden;
}
.ob-head {
  padding: 20px 24px 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
}
.ob-back-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  padding: 4px 6px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  transition: background .15s, color .15s;
}
.ob-back-btn:hover { background: var(--bg); color: var(--text); }
.ob-brand-name { font-weight: 800; font-size: 16px; color: var(--brand); }

/* Steps indicator */
.ob-steps {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 20px 24px;
  border-bottom: 1px solid var(--border);
}
.ob-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  flex: 1;
  position: relative;
}
.ob-step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 14px;
  left: calc(50% + 14px);
  right: calc(-50% + 14px);
  height: 2px;
  background: var(--border);
  transition: background .3s;
}
.ob-step.done:not(:last-child)::after { background: var(--brand); }
.ob-step-dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  background: var(--bg);
  border: 2px solid var(--border);
  color: var(--muted);
  transition: all .25s;
  z-index: 1;
}
.ob-step.active .ob-step-dot {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.ob-step.done .ob-step-dot {
  background: var(--brand-50);
  border-color: var(--brand);
  color: var(--brand);
}
.ob-step-label {
  font-size: 10px;
  color: var(--muted);
  font-weight: 500;
  white-space: nowrap;
}
.ob-step.active .ob-step-label { color: var(--brand); font-weight: 700; }

/* Body */
.ob-title {
  font-size: 18px;
  font-weight: 800;
  margin: 0 0 4px;
  color: var(--text);
}
.ob-sub {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 20px;
}
.ob-body {
  padding: 24px;
}
.ob-grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.ob-footer {
  padding: 16px 24px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
.ob-footer-2 {
  padding: 16px 24px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  gap: 10px;
}

/* Document upload rows */
.ob-doc-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  margin-bottom: 10px;
  background: var(--bg);
  transition: border-color .2s;
}
.ob-doc-row:hover { border-color: var(--brand-200); }
.ob-doc-ico {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--brand-50);
  color: var(--brand);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.ob-doc-ico.uploaded { background: #d1fae5; color: #059669; }
.ob-doc-info { flex: 1; min-width: 0; }
.ob-doc-label { font-size: 13.5px; font-weight: 700; color: var(--text); }
.ob-doc-hint { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.ob-doc-action { flex-shrink: 0; }
.ob-required { color: var(--rose, #F43F5E); font-size: 11px; font-weight: 600; margin-left: 4px; }

/* Info box */
.ob-info-box {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--brand-50);
  border: 1px solid var(--brand-200, #a7f3d0);
  font-size: 12.5px;
  color: var(--brand-700, #065f46);
  margin-bottom: 16px;
  line-height: 1.5;
}

/* Success screen */
.ob-success {
  text-align: center;
  padding: 12px 0 8px;
}
.ob-success-icon {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: linear-gradient(135deg, #d1fae5, #a7f3d0);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 20px;
  font-size: 36px;
}
.ob-steps-info {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 20px;
  text-align: left;
}
.ob-step-info {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px;
  border-radius: 10px;
  background: var(--bg);
  border: 1px solid var(--border);
}
.ob-step-info-ico {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  background: var(--brand-50);
  color: var(--brand);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

@media (max-width: 540px) {
  .ob-card { border-radius: 16px; }
  .ob-grid2 { grid-template-columns: 1fr; }
  .ob-step-label { display: none; }
  .ob-shell { padding: 12px; align-items: flex-start; padding-top: 16px; }
}

/* Chat typing indicator */
.typing-bubble { display: inline-flex; align-items: center; gap: 4px; padding: 12px 14px; }
.typing-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--muted, #94a3b8);
  display: inline-block;
  animation: typingBounce 1.2s infinite ease-in-out;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingBounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
  30% { transform: translateY(-4px); opacity: 1; }
}

/* Voice message player (chat) */
.voice-player { display: flex; align-items: center; gap: 10px; min-width: 200px; max-width: 260px; padding: 4px 2px; }
.voice-play {
  flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: none; cursor: pointer; color: #fff; background: var(--brand-600);
}
.voice-play:hover { background: var(--brand-700); }
.voice-play:disabled { opacity: 0.5; cursor: default; }
.bubble-row.me .voice-play { background: var(--surface); color: var(--brand-700); }
.voice-wave { flex: 1; display: flex; align-items: center; gap: 2px; height: 32px; cursor: pointer; }
.voice-bar {
  flex: 1; min-width: 2px; border-radius: 2px;
  background: var(--slate-300); transition: background .1s;
}
.voice-bar.on { background: var(--brand-500); }
.bubble-row.me .voice-bar { background: rgba(255,255,255,.4); }
.bubble-row.me .voice-bar.on { background: var(--surface); }
.voice-time { flex: 0 0 auto; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; min-width: 30px; text-align: right; }
.bubble-row.me .voice-time { color: rgba(255,255,255,.85); }

/* ── 24. Alias de classes émises par ui.jsx ────────────────────────────────────
   Plusieurs primitives de ui.jsx émettent des noms de classes qui n'ont jamais
   existé dans cette feuille : Field, EmptyState, les pastilles de badge, la
   valeur des StatCard, les titres de modale et les compteurs de chip
   retombaient donc sur le rendu brut du navigateur (ni marge, ni couleur, ni
   centrage). On aliase ici plutôt que de renommer dans ui.jsx : aucun risque de
   régression sur les écrans existants, et tous sont réparés d'un coup. */
.field { display: block; }
.field + .field { margin-top: 14px; }
.field > .flabel,
.field > label { font-size: 13px; font-weight: 600; color: var(--slate-700); display: block; margin-bottom: 6px; }
.field-err { font-size: 12px; color: var(--rose-600); margin-top: 4px; }
.field-hint { font-size: 12px; color: var(--muted); margin-top: 4px; }

.estate {
  display: flex; flex-direction: column; align-items: center;
  padding: 48px 20px; text-align: center; gap: 12px;
}
.estate h3 { font-size: 15px; font-weight: 700; color: var(--ink); }
.estate p  { font-size: 13px; color: var(--muted); max-width: 340px; line-height: 1.5; }
.e-ico {
  width: 56px; height: 56px; border-radius: 16px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 4px;
  background: var(--slate-100); color: var(--slate-400);
}
.estate.ok  .e-ico { background: var(--brand-50); color: var(--brand-600); }
.estate.err .e-ico { background: var(--rose-50);  color: var(--rose-500); }

.bdot { width: 6px; height: 6px; border-radius: 99px; flex-shrink: 0; }
.badge.green  .bdot { background: var(--brand-500); }
.badge.amber  .bdot { background: var(--amber-500); }
.badge.blue   .bdot { background: var(--blue-500); }
.badge.violet .bdot { background: var(--violet-500); }
.badge.rose   .bdot { background: var(--rose-500); }
.badge.gray   .bdot,
.badge.slate  .bdot { background: var(--slate-400); }
/* « slate » est utilisé comme variante de badge sans avoir jamais été définie. */
.badge.slate { background: var(--slate-100); color: var(--slate-600); }

.sc-val { font-size: 32px; font-weight: 800; letter-spacing: -.5px; color: var(--ink); line-height: 1; }

.mh-txt { min-width: 0; }
.mh-txt h3 { font-size: 16px; font-weight: 800; }
.mh-txt p  { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.modal-x {
  margin-left: auto; color: var(--slate-400); padding: 6px; border-radius: 8px;
  transition: background .12s, color .12s; flex-shrink: 0;
}
.modal-x:hover { background: var(--slate-100); color: var(--ink); }

.chip .ct {
  font-size: 11px; font-weight: 800;
  background: rgb(0 0 0 / .12); border-radius: 99px; padding: 1px 6px;
}
.chip.on .ct, .chip.active .ct { background: rgb(255 255 255 / .22); }

.input.err { border-color: var(--rose-400); }
.checkbox.on { background: var(--brand-700); border-color: var(--brand-700); }
.vthumb { border-radius: 10px; object-fit: cover; background: var(--slate-100); }

/* ── 25. Sections de formulaire dans les modales ──────────────────────────────
   Les modales denses (codes promo) regroupent les champs par thème plutôt que
   d'empiler huit champs à la suite. */
.form-section { padding-bottom: 18px; margin-bottom: 18px; border-bottom: 1px solid var(--line); }
.form-section:last-of-type { border-bottom: none; margin-bottom: 12px; padding-bottom: 0; }
.form-section-title {
  font-size: 11.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .5px; color: var(--muted); margin-bottom: 12px;
}
.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.form-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }
@media (max-width: 640px) {
  .form-grid-2, .form-grid-3 { grid-template-columns: 1fr; }
}

/* Aperçu live de l'effet d'un code promo, dans la modale de création. */
.promo-preview {
  padding: 12px 14px; border-radius: 10px;
  background: var(--brand-50); border: 1px solid var(--brand-100);
  align-self: stretch;
}

/* ─── Carrousel de périodes (Paiements loueur) ──────────────────────────────
   Le loueur choisit ici LE mois (ou la semaine, ou le jour) auquel se rapportent
   tous les chiffres de la page. La bande défile horizontalement : une année en
   granularité « jour » fait 365 puces, il ne peut donc pas s'agir d'une simple
   rangée de boutons qui déborde. */
.pc-track {
  display: flex; gap: 8px; overflow-x: auto; flex: 1;
  padding: 2px; scroll-behavior: smooth;
  scrollbar-width: thin;
}
.pc-track::-webkit-scrollbar { height: 6px; }
.pc-track::-webkit-scrollbar-thumb { background: var(--slate-200); border-radius: 99px; }

.pc-chip {
  flex: 0 0 auto; min-width: 104px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 8px 12px; border-radius: 12px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line);
  transition: background .15s, border-color .15s, transform .15s;
}
.pc-chip:hover { border-color: var(--brand-300); transform: translateY(-1px); }
.pc-chip .pc-lbl { font-size: 11.5px; font-weight: 700; color: var(--muted); white-space: nowrap; }
.pc-chip .pc-val { font-size: 13.5px; font-weight: 800; color: var(--ink); white-space: nowrap; }
.pc-chip.now { border-color: var(--brand-200); background: var(--brand-50); }
.pc-chip.future { opacity: .6; border-style: dashed; }
/* Période sans revenu mais avec des encaissements à confirmer : un 0 DA sec ne dit pas
   au loueur qu'il a une action à faire. */
.pc-chip.waiting { border-color: var(--amber-300, #fcd34d); background: var(--amber-50, #fffbeb); }
.pc-chip.waiting .pc-val { color: var(--amber-700); font-size: 12px; }
.pc-chip.on {
  background: var(--brand-700); border-color: var(--brand-700);
  box-shadow: 0 2px 8px rgba(4, 120, 87, .25);
}
.pc-chip.on .pc-lbl { color: rgba(255, 255, 255, .75); }
.pc-chip.on .pc-val { color: #fff; }

.pc-nav {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 9px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--line); color: var(--slate-600);
}
.pc-nav:hover:not(:disabled) { background: var(--slate-50); color: var(--ink); }
.pc-nav:disabled { opacity: .4; cursor: default; }

/* Lien texte inline (« Voir toute la période »). */
.lnk {
  background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; font-weight: 700; color: var(--brand-700); text-decoration: underline;
}
.lnk:hover { color: var(--brand-800); }

/* Ligne de totaux d'un tableau : elle répète les colonnes, donc elle doit se
   distinguer nettement de la dernière ligne de données. */
.tbl tfoot td {
  padding: 12px 14px; background: var(--slate-50);
  border-top: 2px solid var(--line); font-size: 13px;
}

/* ── Avis clients sur le profil loueur ──────────────────────────────────────
   Une ligne par avis : avatar + corps. `align-items: flex-start` parce qu'un
   commentaire long fait plusieurs lignes et que l'avatar doit rester en tête,
   pas se recentrer verticalement sur un pavé de texte. */
.review-row {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 14px 0; border-top: 1px solid var(--line);
}
.review-row:first-child { border-top: none; padding-top: 4px; }

/* ── Arabe : sens d'écriture ────────────────────────────────────────────────
   `dir="rtl"` est posé sur <html> par i18n.jsx, ce qui inverse déjà le flux du
   texte et des flexbox. Restent les endroits où le CSS fixe un côté EN DUR —
   c'est là, et seulement là, qu'il faut intervenir. */
[dir='rtl'] .review-row { text-align: right; }
[dir='rtl'] .tbl th, [dir='rtl'] .tbl td { text-align: right; }

/* La barre latérale est en `position: fixed; left: 0` et `.main` compense avec
   une marge gauche. Ni l'une ni l'autre ne suit `dir` — il faut donc retourner
   explicitement le couple, sinon en arabe le contenu passe SOUS la barre. */
[dir='rtl'] .sidebar { left: auto; right: 0; }
[dir='rtl'] .main { margin-left: 0; margin-right: var(--sidebar-w); }
[dir='rtl'] .sidebar.collapsed ~ .main,
[dir='rtl'] .app:has(.sidebar.collapsed) .main { margin-left: 0; margin-right: var(--sidebar-col); }

/* Un champ à icône de tête réserve sa place avec un padding GAUCHE et positionne
   l'icône à `left: 11px`. En RTL l'icône doit passer à droite, et le padding avec
   elle — sans quoi le texte saisi vient se glisser sous l'icône. */
[dir='rtl'] .input-wrap .lead { left: auto; right: 11px; }
[dir='rtl'] .input-wrap .trail { right: auto; left: 8px; }
[dir='rtl'] .input.has-lead { padding-left: 12px; padding-right: 38px; }
[dir='rtl'] .input.has-trail { padding-right: 12px; padding-left: 38px; }

/* ── Arabe, suite : ce que la traduction complète a rendu visible ───────────
   La première passe ne couvrait que la barre latérale, les tableaux et les champs à icône —
   à l'époque, seuls le profil et les avis étaient traduits. Maintenant que TOUT l'espace
   loueur l'est, les endroits qui figent un côté sautent aux yeux.

   Principe : on ne touche QUE ce qui code un côté en dur. Le reste (flex, grilles, `gap`,
   marges symétriques) suit déjà `dir` tout seul, et le « corriger » l'inverserait deux fois. */

/* Les toasts et les liserés d'accent portent leur couleur sur un bord GAUCHE. En arabe, la
   lecture commence à droite : le liseré doit y être, sinon il termine la ligne au lieu de
   l'ouvrir. */
[dir='rtl'] .toast.success,
[dir='rtl'] .toast.error,
[dir='rtl'] .toast.info { border-left: 0; border-right: 3px solid; }
[dir='rtl'] .toast.success { border-right-color: var(--brand-500); }
[dir='rtl'] .toast.error   { border-right-color: var(--rose-500); }
[dir='rtl'] .toast.info    { border-right-color: var(--blue-500); }

/* Citation d'un message et évènement de calendrier : même raisonnement. */
[dir='rtl'] .bubble-quote { border-left: 0; border-right: 3px solid var(--brand-600); }
[dir='rtl'] .bubble-row.me .bubble-quote { border-right-color: var(--brand-400); }
[dir='rtl'] .cal-ev { border-left: 0; border-right: 3px solid; }
[dir='rtl'] .cal-ev.confirmed { border-right-color: var(--brand-600); }
[dir='rtl'] .cal-ev.pending   { border-right-color: var(--amber-500); }
[dir='rtl'] .cal-ev.blocked   { border-right-color: var(--slate-500); }
[dir='rtl'] .cal-ev.more      { border-right-color: transparent; }

/* Les actions d'une bulle sont posées EN DEHORS d'elle, à `left: 100%` ou `right: 100%`
   selon l'auteur. `dir` inverse l'alignement des bulles mais pas ces valeurs : sans
   inversion, les boutons se retrouvent par-dessus le texte. */
[dir='rtl'] .bubble-row.them .bubble-actions { left: auto; right: 100%; margin-left: 0; margin-right: 6px; }
[dir='rtl'] .bubble-row.me   .bubble-actions { right: auto; left: 100%; margin-right: 0; margin-left: 6px; }

/* La puce d'indicatif et l'avatar de l'en-tête séparent leur voisin par un bord GAUCHE. */
[dir='rtl'] .phone-prefix,
[dir='rtl'] .phone-select { border-right: 0; border-left: 1px solid var(--line); }

/* `margin-left: auto` pousse un élément à l'extrémité — l'extrémité change de côté. */
[dir='rtl'] .tl-end,
[dir='rtl'] .ql-arrow { margin-left: 0; margin-right: auto; }
[dir='rtl'] .ob-required { margin-left: 0; margin-right: 4px; }

/* Colonnes de MONTANTS : elles restent alignées à droite en LTR pour que les unités se
   superposent. En RTL c'est la GAUCHE qui joue ce rôle — et la règle générique
   `[dir='rtl'] .tbl td { text-align: right }` les ramènerait à droite, d'où cette
   surcharge qui doit venir APRÈS elle. */
[dir='rtl'] .cellnum,
[dir='rtl'] .tbl th.cellnum { text-align: left; }
[dir='rtl'] .voice-time { text-align: left; }

/* Le séparateur de jour du chat dessine ses deux traits en absolu, un de chaque côté :
   symétrique, donc rien à inverser — mais le padding de la valeur monétaire de `.kv-money`,
   lui, est unilatéral. */
[dir='rtl'] .kv-money .k { padding-right: 0; padding-left: 12px; }
