/* =====================================================================
   DZ EXPRESS — feuille de style unique.

   Direction : chaleureuse et lisible. Fond gris tres clair, cartes
   blanches arrondies posees dessus, ombres douces, rouge profond en
   signature. L'information respire, les zones cliquables sont franches.

   Bidirectionnel : les proprietes logiques (inline-start/end) portent le
   passage LTR <-> RTL sans feuille separee.
   ===================================================================== */

:root {
  /* Rouge de marque, du plus sombre au plus clair */
  /* La teinte de la plateforme.
   *
   * Elle etait rouge. Le rouge est la couleur de l'erreur : sur un ecran
   * qu'on regarde huit heures par jour, il met en alerte permanente, et il
   * ne reste plus rien pour signaler ce qui va vraiment mal — un colis
   * bloque, une migration en echec. Un bleu ardoise tient le meme role
   * — barre laterale, boutons d'action, onglet ouvert — sans crier, et
   * rend au rouge son seul emploi : l'alerte.
   *
   * Tout part d'ici : changer ces sept lignes retourne l'application
   * entiere, parce que rien n'ecrit une couleur en dur ailleurs. */
  --brand-900: #10192b;
  /* Les deux sombres du site public, tirees de l'encre et non de la teinte :
     le site garde la meme allure quelle que soit la couleur choisie. */
  /* La lueur de selection et de focus : elle etait figee sur l'ancien
     rouge et ne suivait plus la teinte choisie. Injectee avec la palette. */
  --brand-glow: rgba(42, 74, 117, .35);
  /* Repli si la palette n'est pas injectee (page servie sans reglages). */
  --action:      #c62828;
  --action-dark: #9e1f1f;
  --pub-dark:   #17202e;
  --pub-dark-2: #22304a;
  --brand-800: #17253d;
  --brand-700: #1e3252;
  --brand:     #2a4a75;
  --brand-600: #24406685;
  --brand-600: #244066;
  --brand-100: #e8eef6;
  --brand-050: #f5f8fc;

  /* Le rouge ne sert plus qu'a l'alerte. */
  --danger:    #c62828;
  --danger-100:#fdecea;

  --ink:      #1f2430;
  --ink-2:    #384152;
  --muted:    #6b7280;
  --muted-2:  #8a92a3;
  --line:     #e6e8ee;
  --line-2:   #f0f2f6;
  --bg:       #f4f6f9;
  --surface:  #ffffff;
  --ok:       #12805c;
  --ok-bg:    #e8f6f0;
  --warn:     #b7791f;
  --warn-bg:  #fdf6e3;

  --font:    "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-ar: "Noto Kufi Arabic", "Poppins", system-ui, sans-serif;
  --mono:    ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s6: 24px; --s8: 32px; --s12: 48px;

  /* Angles nets : huit pixels sur un bouton de 36 de haut, c'est presque
     une pilule. Quatre suffisent a adoucir sans donner l'air d'un jouet. */
  --r-sm:   4px;
  --r:      14px;
  --r-lg:   20px;
  --r-pill: 999px;

  --sh-sm: 0 1px 2px rgba(23, 28, 40, .06), 0 1px 3px rgba(23, 28, 40, .08);
  --sh:    0 2px 6px rgba(23, 28, 40, .05), 0 8px 24px rgba(23, 28, 40, .07);
  --sh-lg: 0 8px 20px rgba(23, 28, 40, .09), 0 24px 48px rgba(23, 28, 40, .10);

  --sidebar-w: 264px;
  --header-h:  68px;

  /* Alias de compatibilite : plusieurs vues posent encore ces variables
     dans un style en ligne. Les conserver evite des bordures invisibles
     et des couleurs manquantes apres la refonte. */
  --accent:   var(--brand);
  --rule:     1px solid var(--line);
  --thin:     1px solid var(--line-2);
  --divider:  var(--line);
  --hairline: var(--line-2);
  --n-200:    #f0f2f6;
  --n-300:    #e3e7ee;
  --n-400:    #cfd5e0;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* Les navigateurs mobiles retardent le clic pour guetter un double-tap.
   touch-action le leur interdit : les boutons repondent immediatement. */
a, button, .btn, .chip, .nav-item, .seg-opt, select, summary, [role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}
body[dir="rtl"] { font-family: var(--font-ar); }

h1, h2, h3, h4, h5 {
  font-weight: 700; line-height: 1.2; letter-spacing: -.015em;
  margin: 0 0 var(--s2); color: var(--ink);
}
h1 { font-size: 28px; }
h2 { font-size: 23px; }
h3 { font-size: 18px; }
h4 { font-size: 16px; }

a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-700); }

::selection { background: var(--brand-glow); }
:focus { outline: none; }
:focus-visible { outline: 3px solid var(--brand-glow); outline-offset: 2px; border-radius: var(--r-sm); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #d3d8e2; border-radius: var(--r-pill); border: 2px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: #bcc3d0; }

/* ---------------------------------------------------------------- */
/* Utilitaires                                                       */
.kicker {
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); font-weight: 600; margin-bottom: var(--s1);
}
.mono { font-family: var(--mono); letter-spacing: .01em; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.tiny  { font-size: 11.5px; }
.strong { font-weight: 600; }
.num { font-variant-numeric: tabular-nums; }
.hr { border: 0; border-top: 1px solid var(--line); margin: var(--s6) 0; }
.grayscale { filter: grayscale(1); }
.nowrap { white-space: nowrap; }
.right { text-align: end; }
.center { text-align: center; }
.flex { display: flex; align-items: center; gap: var(--s3); }
.flex-1 { flex: 1; min-width: 0; }
.wrap { flex-wrap: wrap; }
.stack > * + * { margin-top: var(--s4); }
.hide { display: none !important; }
.ar-sub {
  display: block; font-family: var(--font-ar); font-size: 11px;
  opacity: .6; direction: rtl; margin-top: 1px;
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- */
/* Grille de l'application                                           */
.app { display: flex; min-height: 100vh; }

/* Une barre laterale blanche.
   Elle etait un aplat sombre a la couleur de la marque : cela impose une
   teinte a tout l'ecran et fait de la navigation la chose la plus voyante
   de la page, alors qu'on la parcourt une fois et qu'on travaille ensuite
   dans le contenu. En blanc, elle se tient a sa place ; le trait qui la
   separe suffit a la delimiter. */
.sidebar {
  width: var(--sidebar-w); flex: 0 0 var(--sidebar-w);
  display: flex; flex-direction: column;
  background: var(--surface); color: var(--ink);
  border-inline-end: 1px solid var(--line);
  position: sticky; top: 0; height: 100vh;
}
.sidebar-head { padding: 22px 20px 18px; border-bottom: 1px solid var(--line); }
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.brand-mark {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: 10px;
  background: var(--brand); display: grid; place-items: center;
  box-shadow: inset 0 -2px 6px rgba(0, 0, 0, .18);
}
.brand-mark::after {
  content: ""; width: 15px; height: 15px; border-radius: 50%;
  border: 2.5px solid #fff; border-inline-end-color: transparent; transform: rotate(-35deg);
}
.brand-logo { height: 34px; width: auto; max-width: 170px; display: block; border-radius: 6px; }
.brand-name { font-weight: 700; font-size: 18px; letter-spacing: -.02em; line-height: 1; }
.sidebar .brand-name { color: var(--ink); }
.brand-sub {
  margin-top: 6px; font-size: 11px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}

.nav { flex: 1; overflow-y: auto; padding: 12px 12px 18px; }
.nav::-webkit-scrollbar-thumb { background: var(--line); border-color: transparent; }
/* Les intitules de groupe — Reseau, Exploitation — decoupent le menu.
   En dix pixels gris pale ils passaient inapercus, et la barre se lisait
   comme une seule longue liste. Plus grands, en gras et dans la teinte de
   la plateforme, ils redonnent au menu ses paliers : on saute d'un groupe
   a l'autre sans lire chaque ligne. */
/* Les intitules ne suivent pas la teinte de la plateforme.
   Je les avais mis dans « brand-700 » : sur une installation ou l'accent
   est reste rouge, ils repassaient au rouge — et c'est justement ce qu'on
   voulait retirer. Un titre de section n'a pas a changer de couleur avec
   la charte : il se lit en encre, point. */
.nav-group {
  padding: 20px 10px 8px; font-size: 13px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink); font-weight: 800;
}
.nav-item {
  width: 100%; display: flex; align-items: center; gap: 10px; text-align: start;
  border: 0; background: none; color: var(--ink-2); cursor: pointer;
  font: inherit; text-decoration: none; padding: 10px 12px;
  border-radius: var(--r-sm); margin-bottom: 2px;
  transition: background .15s, color .15s;
}
.nav-item:hover { background: var(--line-2); color: var(--ink); }
/* Le module ouvert : un gris franc, pas la couleur de la marque. Elle
   servait deja aux boutons d'action ; la voir aussi dans le menu faisait
   deux appels a l'oeil pour deux choses sans rapport. */
.nav-item.is-active { background: var(--line-2); color: var(--ink); box-shadow: none; font-weight: 600; }
.nav-label { display: block; font-size: 14px; font-weight: 500; }
.nav-item.is-active .nav-label { font-weight: 600; }
.nav-count {
  font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 5px;
  background: var(--line-2); color: var(--muted); font-variant-numeric: tabular-nums;
}
.nav-item.is-active .nav-count { background: var(--line); color: var(--ink-2); }

.sidebar-foot {
  border-top: 1px solid var(--line); padding: 14px 16px;
  display: flex; align-items: center; gap: 10px;
}
.avatar {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: 50%;
  background: var(--brand); color: #fff;
  display: grid; place-items: center; font-size: 13px; font-weight: 600;
}
.sidebar-foot .flex-1 > div:first-child { color: var(--ink); }
.sidebar-foot .muted { color: var(--muted); }

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

.topbar {
  min-height: var(--header-h); padding: 14px 28px;
  display: flex; align-items: center; gap: var(--s4);
  background: var(--surface); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 30;
}
.topbar h1 { margin: 0; font-size: 21px; }
.content { padding: 26px 28px 60px; }

/* ---------------------------------------------------------------- */
/* Boutons                                                           */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  padding: 11px 20px; border: 1px solid transparent; border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  text-decoration: none; box-shadow: var(--sh-sm);
  transition: background .15s, color .15s, box-shadow .15s, transform .08s;
}
.btn:hover { box-shadow: var(--sh); color: var(--ink); }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn.is-disabled { opacity: .5; pointer-events: none; }

/* Le bouton d'action ne suit pas la teinte reglable.
   Il etait peint dans « brand » : sur une installation ou l'accent est
   reste rouge, « Session de scan », « Ajouter un colis » ou « Enregistrer »
   repassaient au rouge — la couleur de l'erreur sur les gestes les plus
   courants de la journee. Un bouton de commande est un bouton de commande :
   il se lit en encre, quelle que soit la charte. */
.btn-primary { background: var(--ink); color: #fff; border-color: var(--ink); }
.btn-primary:hover { background: #000; color: #fff; border-color: #000; }

.btn-ghost { background: transparent; box-shadow: none; border-color: var(--line); color: var(--muted); }
.btn-ghost:hover { background: var(--line-2); box-shadow: none; color: var(--ink); }

.btn-sm { padding: 8px 14px; font-size: 13px; border-radius: var(--r-sm); }
.btn-block { width: 100%; }
.btn-icon { padding: 9px; }
.btn-row { display: flex; gap: var(--s2); flex-wrap: wrap; }

/* ---------------------------------------------------------------- */
/* Pastilles de statut                                               */
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 11px; font-size: 12px; font-weight: 600;
  border-radius: 5px; white-space: nowrap; line-height: 1.5;
}
/* L'etiquette pleine sert a l'alerte — colis annule, collecte refusee :
   elle porte donc le rouge, et non la teinte de la plateforme. */
.tag-solid   { background: var(--danger, #c62828); color: #fff; }
.tag-soft    { background: var(--brand-100); color: var(--brand-700); }
.tag-neutral { background: var(--line-2); color: var(--ink-2); }
.tag-outline { background: transparent; color: var(--muted); box-shadow: inset 0 0 0 1px var(--line); }
.tag-ok      { background: var(--ok-bg); color: var(--ok); }
.tag-warn    { background: var(--warn-bg, #fdf3e0); color: var(--warn, #a05a00); }

/* ---------------------------------------------------------------- */
/* Cartes                                                            */
.grid { display: grid; gap: var(--s4); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-side      { grid-template-columns: minmax(0, 1fr) 330px; align-items: start; }
.grid-side-wide { grid-template-columns: minmax(0, 1fr) 380px; align-items: start; }

.panel {
  background: var(--surface); border-radius: var(--r);
  box-shadow: var(--sh-sm); overflow: hidden;
}
.panel-head {
  padding: 16px 20px; border-bottom: 1px solid var(--line-2);
  display: flex; align-items: center; gap: var(--s3);
}
.panel-head h3 { margin: 0; font-size: 16px; }
.panel-body { padding: 20px; }

.kpi {
  background: var(--surface); border-radius: var(--r); padding: 20px;
  box-shadow: var(--sh-sm); transition: box-shadow .18s, transform .18s;
}
@media (hover: hover) and (pointer: fine) {
  .kpi:hover  { box-shadow: var(--sh); transform: translateY(-2px); }
    .table tbody tr:hover { background: #fafbfd; }
  .bar:hover { background: #cfd5e0; }
}
.kpi-label {
  font-size: 12px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); font-weight: 600; margin-bottom: var(--s2);
}
.kpi-value {
  font-size: 32px; font-weight: 700; letter-spacing: -.03em; line-height: 1.1;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.kpi-delta { margin-top: var(--s2); font-size: 12.5px; color: var(--muted); }
.kpi-delta.is-alert { color: var(--danger, #c62828); font-weight: 600; }

/* ---------------------------------------------------------------- */
/* Tableaux                                                          */
.table-wrap {
  background: var(--surface); border-radius: var(--r);
  box-shadow: var(--sh-sm); overflow-x: auto;
  -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
/* Le cadre defile horizontalement, ce qui rogne tout ce qui deborde — donc
   le panneau du parcours, qu'il fallait aller chercher en faisant defiler.
   Pendant qu'un panneau est ouvert, le cadre cesse de rogner. */
.table-wrap.pop-open { overflow: visible; }
table.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table thead th {
  text-align: start; font-size: 11.5px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--muted); font-weight: 600; padding: 13px 18px;
  border-bottom: 1px solid var(--line); white-space: nowrap; background: #fbfcfd;
}
.table tbody td { padding: 14px 18px; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background .12s; }
.table .num { text-align: end; font-variant-numeric: tabular-nums; }
.table a { color: var(--ink); font-weight: 600; }
.table a:hover { color: var(--brand); }
/* Un lien habille en bouton garde les couleurs du bouton. La regle des
   liens de tableau, plus precise que celle des boutons, leur imposait la
   couleur de l'encre : un bouton sombre devenait noir sur noir —
   « Modifier » dans les wilayas, « Recevoir » dans la caisse des
   livreurs. */
.table a.btn-primary, .table a.btn-primary:hover { color: #fff; }
.table a.btn:not(.btn-primary):hover { color: var(--ink); }
.panel .table-wrap { box-shadow: none; border-radius: 0; }

.empty { padding: 54px 18px; text-align: center; color: var(--muted-2); }

/* ---------------------------------------------------------------- */
/* Formulaires                                                       */
/* Un champ doit pouvoir retrecir.
   Sans « min-width: 0 », un element de grille refuse de descendre sous la
   largeur de son contenu : une liste deroulante au libelle long, un champ
   au texte d'aide bavard, et la grille debordait de l'ecran au lieu de se
   replier. On voyait alors des colonnes ecrasees et une page qui defile de
   travers — sur telephone, la moitie du formulaire hors cadre. */
.field { margin-bottom: var(--s4); min-width: 0; }
.field .input, .field select, .field textarea { max-width: 100%; }
.field > label {
  display: block; font-size: 13px; font-weight: 600;
  color: var(--ink-2); margin-bottom: 6px;
}
.field .hint { font-size: 12.5px; color: var(--muted); margin-top: 5px; }
/* Un champ en faute se signale en rouge, pas dans la teinte du site. */
.field.is-error .input, .field.is-error select, .field.is-error textarea { border-color: var(--danger, #c62828); }
.field .error { font-size: 12.5px; color: var(--brand-700); margin-top: 5px; font-weight: 500; }

/* Les champs de saisie.
 *
 * « .input » ne suffisait pas : plusieurs formulaires ecrivent
 * « <input class="mono"> » ou « <input type="tel"> » sans cette classe, et
 * ces champs-la gardaient leur largeur naturelle — celle que le navigateur
 * leur donne, environ vingt caracteres. Dans une grille a deux colonnes sur
 * telephone, ils debordaient l'un sur l'autre.
 *
 * On vise donc le champ lui-meme, quelle que soit sa classe, en laissant de
 * cote ceux dont la largeur fait sens : cases a cocher, boutons radio,
 * interrupteurs et boutons. */
.input, select, textarea,
.field input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]) {
  width: 100%; padding: 11px 14px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px; appearance: none;
  transition: border-color .15s, box-shadow .15s;
}
.input::placeholder, textarea::placeholder { color: var(--muted-2); }
.input:hover, select:hover, textarea:hover { border-color: #d3d8e2; }
.input:focus, select:focus, textarea:focus {
  border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-glow);
}
textarea { min-height: 100px; resize: vertical; }
select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%236b7280' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
  padding-inline-end: 38px; cursor: pointer;
}
body[dir="rtl"] select { background-position: left 14px center; }

.check { display: flex; align-items: flex-start; gap: 10px; font-size: 14px; }
.check input { width: 18px; height: 18px; accent-color: var(--brand); margin-top: 2px; border-radius: 4px; }

.seg {
  display: inline-flex; padding: 4px; gap: 2px;
  background: var(--line-2); border-radius: var(--r-sm);
}
.seg-opt {
  padding: 8px 15px; font-size: 13px; font-weight: 600; cursor: pointer;
  border: 0; border-radius: 6px; background: none; color: var(--muted);
  font-family: inherit; transition: background .15s, color .15s;
}
.seg-opt:hover { color: var(--ink); }
.seg-opt.is-on { background: var(--surface); color: var(--ink); box-shadow: var(--sh-sm); }

.filters {
  display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center;
  margin-bottom: var(--s4);
}
/* Angles nets, pas des pilules.
   La forme arrondie a l'extreme dit « bouton d'application mobile » ; sur
   un outil de travail elle donne un air de jouet, et la rangee de pastilles
   se lit moins vite qu'une rangee d'onglets. Six pixels suffisent a
   adoucir. */
/* Le texte doit etre centre dans sa bulle.
   Sans « inline-flex » ni « align-items », un lien reste une boite en ligne :
   le texte s'aligne sur la ligne de base et remonte dans la pastille, d'un
   ou deux pixels — assez pour se voir des qu'il y en a plusieurs cote a
   cote. La hauteur minimale evite qu'une bulle courte soit plus plate que
   sa voisine. */
.chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 34px; line-height: 1;
  padding: 8px 15px; font-size: 13.5px; font-weight: 600; text-decoration: none;
  border-radius: 6px; background: var(--surface); color: var(--muted);
  box-shadow: var(--sh-sm); transition: background .15s, color .15s;
}
.chip:hover { color: var(--ink); }
.chip.is-on { background: var(--ink); color: #fff; }
.chip .n { opacity: .7; margin-inline-start: 5px; font-variant-numeric: tabular-nums; }

/* Barre d'etapes du colis.
   Elle suit le parcours de gauche a droite. Sur mobile elle defile
   horizontalement plutot que de passer a la ligne : le parcours se lit
   dans un sens, l'empiler sur quatre lignes en casse la lecture. */
.stagebar {
  display: flex; gap: var(--s2); align-items: center;
  margin-bottom: var(--s3); padding-bottom: var(--s2);
  overflow-x: auto; scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.stagebar .chip { flex: 0 0 auto; white-space: nowrap; }
/* Des onglets, pas des pastilles — et chacun sa couleur.
   La forme en bulle disait « bouton » : douze boutons ronds cote a cote
   donnaient un ecran de jeu, la ou l'on suit un parcours. Un onglet a
   angles droits, pose sur une ligne, dit ce qu'il est — une position dans
   une suite.

   La couleur, elle, dit la nature de l'etape : bleu pour ce qui roule,
   ambre pour ce qui attend une decision, vert pour ce qui est fini, gris
   pour ce qui n'a pas commence ou a quitte le parcours. On reconnait la
   zone de la barre avant d'en lire le libelle — et un agent qui travaille
   toujours au meme endroit y va d'un geste. Les fonds restent clairs :
   douze aplats francs cote a cote seraient illisibles. L'onglet ouvert,
   lui, prend la couleur pleine. */
.stagebar { border-bottom: 1px solid var(--line); gap: 3px; padding-bottom: 0; }
.stagebar .chip {
  flex: 0 0 auto; white-space: nowrap;
  border-radius: 3px 3px 0 0; box-shadow: none;
  padding: 9px 14px 8px; border-bottom: 2px solid transparent;
  margin-bottom: -1px; font-weight: 600;
  background: var(--line-2); color: var(--muted);
}
.stagebar .chip:hover { filter: brightness(.97); }

/* Les natures d'etape, et ce qu'elles disent a celui qui regarde.
   Gris : rien n'a commence, ou le colis a quitte le parcours. Ambre : on
   attend quelqu'un. Bleu : ca roule, personne n'a rien a faire. Indigo :
   c'est chez nous et ca attend un geste — le travail du jour. Vert : fini.
   Rouge : quelque chose n'a pas marche. */
.stagebar .chip.st-idle { background: var(--line-2);  color: var(--muted); }
.stagebar .chip.st-wait { background: #fdf6e3;        color: #b7791f; }
.stagebar .chip.st-road { background: #eaf1fb;        color: #2563a8; }
.stagebar .chip.st-hold { background: #eeeafb;        color: #5b46b8; }
.stagebar .chip.st-ok,
.stagebar .chip.st-done { background: var(--ok-bg);   color: var(--ok); }
.stagebar .chip.st-bad  { background: #fdecea;        color: #c62828; }
/* Anciennes classes, gardees le temps qu'un cache d'ecran se vide. */
.stagebar .chip.st-move { background: #eaf1fb;        color: #2563a8; }
.stagebar .chip.st-warn { background: #fdf6e3;        color: #b7791f; }

/* L'etape ouverte : la meme couleur, mais pleine. Le trait du bas la pose
   sur la ligne de base, comme l'onglet d'un classeur qu'on a tire. */
.stagebar .chip.is-on { color: #fff; border-bottom-color: transparent; }
.stagebar .chip.st-idle.is-on { background: #4b5563; }
.stagebar .chip.st-wait.is-on,
.stagebar .chip.st-warn.is-on { background: #b7791f; }
.stagebar .chip.st-road.is-on,
.stagebar .chip.st-move.is-on { background: #2563a8; }
.stagebar .chip.st-hold.is-on { background: #5b46b8; }
.stagebar .chip.st-ok.is-on,
.stagebar .chip.st-done.is-on { background: var(--ok); }
.stagebar .chip.st-bad.is-on  { background: #c62828; }

/* Le compteur se detache sur le fond colore de son onglet. */
.stagebar .chip .n {
  opacity: 1; font-weight: 700; padding: 1px 7px; border-radius: 3px;
  background: rgba(255, 255, 255, .72); color: inherit;
}
.stagebar .chip.is-on .n { background: rgba(255, 255, 255, .24); color: #fff; }
@media (max-width: 720px) {
  .stagebar { margin-inline: calc(var(--s4) * -1); padding-inline: var(--s4); }
}

/* Selecteur de langue */
.lang-select { display: inline-flex; align-items: center; flex: 0 0 auto; }
/* Angles droits comme les boutons voisins, et la largeur d'un code de
   langue : il occupait celle d'un nom complet qu'il n'affiche plus. */
.lang-select select {
  width: auto; min-width: 0; padding: 8px 30px 8px 12px;
  font-size: 13px; font-weight: 600; color: var(--ink-2);
  border-radius: var(--r-sm); background-color: var(--surface);
}
/* Le selecteur de langue etait blanc sur blanc depuis que le bandeau a
   change de fond : il devenait invisible. */
.pub-nav .lang-select select {
  background-color: var(--surface); border-color: var(--line);
  color: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23667085' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.pub-nav .lang-select select option { color: var(--ink); }

/* ---------------------------------------------------------------- */
/* Chronologie de suivi                                              */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li {
  display: grid; grid-template-columns: 64px 20px 1fr; gap: var(--s3);
  align-items: start; padding: 14px 0;
}
.tl-time { font-size: 12px; color: var(--muted); padding-top: 3px; font-variant-numeric: tabular-nums; }
.tl-rail { position: relative; height: 100%; }
.tl-dot {
  width: 11px; height: 11px; border-radius: 50%; background: #cfd5e0;
  margin-top: 5px; position: relative; z-index: 1;
  box-shadow: 0 0 0 3px var(--surface);
}
.tl-dot.is-now { background: var(--brand); box-shadow: 0 0 0 4px var(--brand-100); }
.tl-dot.is-future { background: #e3e7ee; }
.tl-rail::after {
  content: ""; position: absolute; inset-inline-start: 5px; top: 17px; bottom: -14px;
  width: 2px; background: var(--line);
}
.timeline li:last-child .tl-rail::after { display: none; }
.tl-title { font-weight: 600; font-size: 14.5px; }
.tl-place { font-size: 12.5px; color: var(--muted); display: block; }

/* ---------------------------------------------------------------- */
/* Barres et classements                                             */
.bars { display: flex; align-items: flex-end; gap: 8px; height: 150px; }
.bar-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.bar { background: #e3e7ee; width: 100%; border-radius: 6px 6px 0 0; }
.bar.is-now { background: var(--brand); }
.bar-label { font-size: 11.5px; color: var(--muted); margin-top: 8px; text-align: center; }

.rank { list-style: none; margin: 0; padding: 0; }
.rank li { padding: 11px 0; border-bottom: 1px solid var(--line-2); }
.rank li:last-child { border-bottom: 0; }
.rank-row { display: flex; align-items: baseline; gap: var(--s3); }
.rank-name { flex: 1; font-weight: 500; font-size: 14px; }
.rank-val { font-variant-numeric: tabular-nums; font-weight: 600; }
.rank-bar { height: 6px; background: var(--brand); margin-top: 7px; border-radius: var(--r-pill); min-width: 6px; }

/* ---------------------------------------------------------------- */
/* Messages                                                          */
.flash {
  border-radius: var(--r-sm); padding: 13px 17px; margin-bottom: var(--s4);
  font-size: 14px; box-shadow: var(--sh-sm); background: var(--surface);
  border-inline-start: 4px solid var(--line);
}
.flash-ok    { border-inline-start-color: var(--ok);    background: var(--ok-bg);    color: #0b5c43; }
.flash-error { border-inline-start-color: var(--brand); background: var(--brand-050); color: var(--brand-700); }
.flash-info  { border-inline-start-color: var(--muted-2); }

/* ---------------------------------------------------------------- */
/* Site public                                                       */
/* Le bandeau public prend l'encre, pas la teinte.
   Il derivait de la couleur d'accent : une teinte rouge donnait un bandeau
   rouge sur toute la largeur, et le site changeait d'allure a chaque
   reglage. L'encre est la meme sombre neutre que l'administration — la
   teinte reste, mais sur ce qui la merite : les boutons, les liens, les
   accents. */
/* Un bandeau blanc, une encre noire, un trait sous le lien actif.
   Il etait sombre et prenait la teinte : sur une couleur vive, tout le haut
   du site en prenait la couleur. Le blanc ne vieillit pas et laisse la
   teinte aux endroits qui la meritent. */
.pub-nav {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: var(--s4); padding: 0 32px; min-height: var(--header-h);
  background: #fff; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.pub-nav > .brand { justify-self: start; min-width: 0; color: var(--ink); }
.pub-nav .brand-name { color: var(--ink); }
.pub-links { display: flex; gap: var(--s6); align-items: center; justify-self: center; }
.pub-links a {
  color: var(--ink-2); font-size: 14.5px; font-weight: 500;
  white-space: nowrap; padding: 6px 0; position: relative;
}
.pub-links a:hover { color: var(--ink); }
.pub-links a::after {
  content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 2px;
  background: var(--ink); border-radius: 2px; transform: scaleX(0); transition: transform .18s;
}
.pub-links a:hover::after { transform: scaleX(1); }
.pub-links a.is-on { color: var(--ink); font-weight: 600; }
.pub-links a.is-on::after { transform: scaleX(1); }
.pub-links .pub-cta { display: none; }
.pub-actions { display: flex; align-items: center; gap: var(--s2); justify-self: end; }
/* Le bouton de connexion prenait la teinte : rouge sur une teinte rouge.
   Il prend l'encre, comme les boutons de l'administration. */
/* Ce qui appelle a l'action porte la couleur d'action : le bouton de
   connexion, ceux du site public, et les chiffres cles. Reglable d'un seul
   endroit, dans les parametres. */
.pub-account {
  white-space: nowrap; background: var(--action); color: #fff;
  /* Il heritait de la bordure des boutons ordinaires : un filet sombre
     autour d'un aplat colore, qui le faisait paraitre enfonce. */
  border-color: var(--action); box-shadow: none;
}
.pub-account:hover { background: var(--action-dark); color: #fff; border-color: var(--action-dark); }

/* Les boutons du site public : « Tarifs », « Suivre mon colis »,
   « Envoyer », « Se connecter » sur la page de connexion. */
/* Les boutons du site public et de la connexion. « .auth-card » visait une
   classe qui n'existe pas : la page de connexion s'appelle « .auth-pane »,
   et son bouton restait donc noir. */
.pub-nav ~ * .btn-primary,
.hero .btn-primary, .poster .btn, .site-form .btn-primary,
.auth-pane .btn-primary, .auth .btn-primary, .track-form .btn-primary {
  background: var(--action); color: #fff; border-color: var(--action);
}
.pub-nav ~ * .btn-primary:hover,
.hero .btn-primary:hover, .poster .btn:hover, .site-form .btn-primary:hover,
.auth-pane .btn-primary:hover, .auth .btn-primary:hover,
.track-form .btn-primary:hover {
  background: var(--action-dark); color: #fff; border-color: var(--action-dark);
}

/* Les chiffres de la page d'accueil. */
.hero ~ * .kpi-value, .section .kpi-value { color: var(--action); }

/* Bandeau d'accueil */
/* Meme chose pour le bandeau d'accueil. Le degrade finissait sur la teinte
   pure : avec un accent vif, tout le bas de l'image virait a cette couleur.
   Il reste un degrade — pour la profondeur — mais entre deux tons d'encre. */
/* Le bandeau d'accueil, sur fond clair.
   Un aplat sombre pleine largeur date, et il prenait la teinte : le bas de
   l'image virait a la couleur choisie. Un fond blanc casse, un titre en
   encre, un trait de separation : le texte se lit, et la teinte reste pour
   les boutons. */
.hero {
  padding: 72px 32px 84px;
  background: var(--bg); border-bottom: 1px solid var(--line);
  color: var(--ink); position: relative; overflow: hidden;
}
.hero::after {
  content: ""; position: absolute; inset-inline-end: -140px; top: -160px;
  width: 520px; height: 520px; border-radius: 50%;
  background: rgba(31, 36, 48, .03);
}
.hero-inner { width: 100%; margin: 0; position: relative; z-index: 1; }
.hero .kicker { color: var(--muted); }
.hero h1 {
  color: var(--ink); font-size: clamp(32px, 5vw, 56px); line-height: 1.12;
  letter-spacing: -.03em; max-width: 20ch; margin-bottom: var(--s4);
}
/* Le paragraphe du bandeau : encre adoucie, comme le reste du site. */
.hero p {
  font-size: clamp(16px, 1.4vw, 19px); color: var(--ink-2);
  max-width: 62ch; margin: 0 0 var(--s8);
}

/* Variantes de fond du bandeau : image, video, degrade anime */
.hero-media { background-repeat: no-repeat; }
.hero-video { position: relative; }
.hero-bg-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0; pointer-events: none;
}
.hero-overlay {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(120deg, #10141c 0%, rgba(16, 20, 28, .55) 100%);
}
.hero-animated {
  background-size: 220% 220%;
  animation: heroShift 18s ease-in-out infinite;
}
@keyframes heroShift {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}
/* Une animation de fond n'a pas sa place quand l'utilisateur demande le
   calme, ni sur un mobile ou elle coute de la batterie pour rien. */
@media (max-width: 860px) { .hero-animated { animation: none; background-size: cover; } }

/* Champ de suivi : la carte blanche posee sur le bandeau */
.track-box {
  background: var(--surface); border-radius: var(--r-lg);
  box-shadow: var(--sh-lg); width: 100%; max-width: 720px; overflow: hidden;
}
.track-box .panel-body { display: flex; gap: var(--s2); padding: 10px; align-items: center; }
.track-box .input {
  border: 0; box-shadow: none; font-size: 16px; padding: 14px 16px;
}
.track-box .input:focus { box-shadow: none; }
.track-box .btn { padding: 14px 26px; font-size: 15px; flex: 0 0 auto; }

.section { padding: 60px 32px; }
.section-inner { width: 100%; margin: 0; }
.section h2 { font-size: clamp(24px, 3vw, 34px); letter-spacing: -.025em; margin-bottom: var(--s6); }

.cells { display: grid; grid-template-columns: repeat(auto-fit, minmax(248px, 1fr)); gap: var(--s4); }
.cell {
  padding: 26px 24px; background: var(--surface);
  border-radius: var(--r); box-shadow: var(--sh-sm);
  transition: box-shadow .18s, transform .18s;
}
.cell h3 { font-size: 17px; margin-bottom: var(--s2); }
.cell p { font-size: 14px; color: var(--muted); margin: 0; }
.cell .kpi-value { color: var(--brand); }

/* L'affiche aux clients professionnels : fond clair, texte en encre.
   Elle etait un aplat de teinte pleine largeur — la couleur choisie s'y
   etalait sur toute la page d'accueil. */
.poster {
  margin: 0 32px 60px; padding: 56px 44px; border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line); color: var(--ink);
  box-shadow: var(--sh-sm);
}
.poster h2 { color: var(--ink); font-size: clamp(26px, 3.4vw, 40px); max-width: 20ch; }
.poster p { font-size: 16.5px; color: var(--ink-2); max-width: 56ch; }
/* Le bouton de l'affiche appelle a l'action comme les autres : il gardait
   l'encre d'une regle posee avant que la couleur d'action existe. */
.poster .btn {
  background: var(--action); color: #fff; border-color: var(--action);
}
.poster .btn:hover {
  background: var(--action-dark); color: #fff; border-color: var(--action-dark);
}

.footer { padding: 52px 32px 40px; background: var(--surface); border-top: 1px solid var(--line); font-size: 14px; }
.footer-inner {
  width: 100%; margin: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s8);
}
.footer h4 { font-size: 12px; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.footer a { display: block; color: var(--ink-2); padding: 4px 0; font-size: 14px; }
.footer a:hover { color: var(--brand); }
.footer .brand-name { color: var(--ink); }

/* ---------------------------------------------------------------- */
/* Cartographie                                                      */
/* Leaflet empile ses couches jusqu'a 800. Sans contexte dedie, elles */
/* passeraient devant le tiroir de navigation.                        */
.leaflet-container { z-index: 0; isolation: isolate; border-radius: var(--r); }
#map { position: relative; z-index: 0; }

/* ---------------------------------------------------------------- */
/* Menu mobile                                                       */
.nav-toggle {
  display: none; align-items: center; justify-content: center;
  width: 42px; height: 42px; flex: 0 0 42px; padding: 0;
  border: 0; border-radius: var(--r-sm); background: rgba(255, 255, 255, .14);
  cursor: pointer;
}
.topbar .nav-toggle { background: var(--line-2); }
/* Le bouton du menu, sur le bandeau blanc.
   Il etait un carre gris a l'icone blanche — invisible sur fond clair. Fond
   blanc borde, trait noir : il se lit, et il ne pese pas dans le bandeau. */
/* Le bouton du menu, sur le bandeau blanc.
   Ses trois traits sont dessines en CSS, pas en SVG : je visais des balises
   qui n'existent pas, et ils restaient blancs sur blanc. */
.pub-nav .nav-toggle {
  background: #fff; border: 1px solid var(--line); color: var(--ink);
}
.pub-nav .nav-toggle:hover { background: var(--line-2); }
.pub-nav .nav-toggle span,
.pub-nav .nav-toggle span::before,
.pub-nav .nav-toggle span::after { background: var(--ink); }
/* Ouvert, le trait du milieu s'efface pour former la croix. */
.pub-nav .nav-toggle[aria-expanded="true"] span { background: transparent; }
.nav-toggle span { display: block; width: 18px; height: 2px; background: #fff; border-radius: 2px; position: relative; }
.topbar .nav-toggle span, .topbar .nav-toggle span::before, .topbar .nav-toggle span::after { background: var(--ink-2); }
.nav-toggle span::before, .nav-toggle span::after {
  content: ""; position: absolute; inset-inline-start: 0; width: 18px; height: 2px;
  background: #fff; border-radius: 2px; transition: transform .18s, top .18s;
}
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after  { top: 6px; }
.nav-toggle[aria-expanded="true"] span { background: transparent; }
.nav-toggle[aria-expanded="true"] span::before { top: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] span::after  { top: 0; transform: rotate(-45deg); }

.scrim {
  position: fixed; inset: 0; z-index: 1500; background: rgba(23, 28, 40, .5);
  opacity: 0; pointer-events: none; transition: opacity .18s linear;
  will-change: opacity;
}
.scrim.is-on { opacity: 1; pointer-events: auto; }

/* ---------------------------------------------------------------- */
/* Etiquette colis (impression)                                      */
.label-sheet { width: 100mm; border: 2px solid #000; padding: 6mm; background: #fff; color: #000; border-radius: 0; }
.label-head { display: flex; justify-content: space-between; align-items: flex-start;
              border-bottom: 2px solid #000; padding-bottom: 4mm; margin-bottom: 4mm; }
.label-block { margin-bottom: 4mm; }
.label-block .k { font-size: 8pt; letter-spacing: .08em; text-transform: uppercase; color: #555; }
.label-block .v { font-size: 12pt; font-weight: 700; }
.label-cod { border: 2px solid #000; padding: 3mm; text-align: center; margin-top: 3mm; }
.label-cod .v { font-size: 18pt; font-weight: 800; }

@media print {
  .no-print, .sidebar, .topbar, .pub-nav, .footer, .scrim { display: none !important; }
  body { background: #fff; }
  .content { padding: 0; }
  .panel, .table-wrap, .kpi { box-shadow: none; }
  .label-sheet { border: 0; page-break-after: always; }
}

/* ---------------------------------------------------------------- */
/* Adaptation aux ecrans                                             */
@media (max-width: 1080px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-side, .grid-side-wide { grid-template-columns: minmax(0, 1fr); }
  .pub-links { gap: var(--s4); }
}

@media (max-width: 860px) {
  .nav-toggle { display: inline-flex; }

  /* Toute grille a colonnes fixes se replie sous 860 px.
   *
   * Le selecteur sur l'attribut de style attrapait aussi les grilles qui
   * portent leur propre largeur de repli — « minmax », « auto-fill »,
   * « auto-fit » : elles savent deja s'adapter, et les ecraser repliait des
   * formulaires qui se comportaient bien. Le commentaire etait aussi la en
   * double. */
  [style*="grid-template-columns"]:not([style*="minmax"]):not([style*="auto-fill"]):not([style*="auto-fit"]),
  .grid-2, .grid-3, .grid-4, .grid-side, .grid-side-wide {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  /* Les rangees de champs poses en ligne : elles gardaient leur largeur et
     poussaient la page de cote. */
  .filters, .btn-row, .toolbar { flex-wrap: wrap; }
  .filters > .input, .filters > select, .filters > .btn { max-width: 100%; }

  /* Un tableau ne se replie pas : il defile, dans son cadre et non avec la
     page entiere. */
  .table-wrap { max-width: 100% !important; }

  /* Tiroir de navigation. Trois zones : l'en-tete et le bloc compte
     gardent leur hauteur, seule la liste des modules defile. Le compte et
     la deconnexion restent donc toujours visibles. */
  .sidebar {
    position: fixed; top: 0; bottom: 0; inset-inline-start: 0;
    z-index: 1600;                       /* au-dessus de la carte et du voile */
    width: min(84vw, 300px); height: auto;
    transform: translateX(-100%);
    transition: transform .22s cubic-bezier(.32, .72, 0, 1);
    display: flex; flex-direction: column; overflow: hidden;
    /* La barre est repeinte a chaque image pendant l'ouverture : on
       previent le navigateur et on isole son rendu du reste de la page. */
    will-change: transform;
    contain: layout paint;
    box-shadow: 4px 0 24px rgba(23, 28, 40, .18);
  }
  /* En arabe, le tiroir sort du bord droit : il est donc range a droite,
     hors ecran. Mais « range » et « ouvert » se disputaient la meme
     propriete, et la regle de rangement gagnait — elle designe body, donc
     elle pese plus lourd que la simple classe d'ouverture. Resultat : en
     arabe sur telephone, le voile s'assombrissait, le bouton se changeait
     en croix, et aucun menu n'apparaissait. On donne a l'ouverture le meme
     poids dans les deux sens d'ecriture. */
  body[dir="rtl"] .sidebar {
    transform: translateX(100%);
    box-shadow: -4px 0 24px rgba(23, 28, 40, .18);
  }
  .sidebar.is-open,
  body[dir="rtl"] .sidebar.is-open { transform: translateX(0); }
  .sidebar-head { flex: 0 0 auto; }
  .sidebar .nav {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  }
  .sidebar-foot { flex: 0 0 auto; padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }

  /* Le titre du module fait doublon avec le menu et mange une ligne
     entiere sur un petit ecran. */
  .topbar h1, .topbar .kicker { display: none; }
  .topbar { padding: 12px 16px; min-height: 60px; }
  .topbar .lang-select { margin-inline-start: auto; }

  .content { padding: 18px 14px 40px; }

  /* En-tete public : marque a gauche, langue et menu a droite, liens
     deroulants en dessous. Le bouton de connexion descend dans le
     panneau : dans la barre, il debordait. */
  .pub-nav { display: flex; flex-wrap: wrap; padding: 10px 14px; gap: 10px; min-height: 0; }
  .pub-nav .brand-name { font-size: 16px; }
  .pub-nav .brand-logo, .pub-nav .brand-mark { height: 30px; width: 30px; flex-basis: 30px; }
  .pub-actions { margin-inline-start: auto; }
  .pub-account { display: none; }
  /* Le tiroir du telephone, sur fond blanc.
     Ses regles dataient du bandeau sombre : un filet blanc, un lien actif
     blanc sur un voile blanc, un bouton a la teinte. Sur fond clair, tout
     cela disparaissait ou jurait. */
  .pub-links {
    display: none; order: 9; width: 100%; flex-direction: column;
    gap: 0; justify-self: stretch;
    border-top: 1px solid var(--line); margin-top: 4px; padding: 4px 0 8px;
  }
  /* Ouvert, le tiroir se detache du bandeau : sans cet espace le premier
     lien se colle au trait de separation et parait en faire partie. */
  .pub-nav.is-open .pub-links { display: flex; padding-top: 10px; }
  .pub-links a { padding: 13px 4px; font-size: 15px; }
  .pub-links a::after { display: none; }
  /* La page ouverte se signale par un trait a gauche, pas par un aplat :
     le texte garde sa couleur, et l'oeil trouve la ligne au trait. */
  .pub-links a.is-on {
    color: var(--ink); font-weight: 600; padding-inline-start: 12px;
    border-inline-start: 3px solid var(--action); background: none;
  }
  .pub-links .pub-cta {
    display: block; margin-top: 10px; padding: 13px 16px; text-align: center;
    background: var(--action); color: #fff; border-radius: var(--r-sm); font-weight: 600;
  }

  .hero { padding: 44px 16px 52px; }
  .hero h1 { font-size: clamp(27px, 7vw, 34px); }
  .section { padding: 36px 16px; }
  .poster { margin: 0 16px 40px; padding: 36px 22px; }
  .footer { padding: 36px 16px 28px; }
  .track-box .panel-body { flex-direction: column; align-items: stretch; }
  .track-box .btn { width: 100%; }

  /* Tableaux replies en fiches lisibles au pouce */
  .table thead { display: none; }
  .table tbody tr {
    display: block; padding: 12px 4px; border-bottom: 1px solid var(--line);
  }
  .table tbody tr:last-child { border-bottom: 0; }
  .table tbody td {
    display: flex; justify-content: space-between; align-items: center;
    gap: var(--s3); padding: 7px 14px; border-bottom: 0; text-align: end;
  }
  .table tbody td::before {
    content: attr(data-label); font-size: 12px; color: var(--muted);
    font-weight: 600; text-align: start; flex: 0 0 auto;
  }
  .table .num { text-align: end; }
}

/* Reglages propres au tactile : moins d'ombres a recalculer, defilement
   natif sans lissage force. */
@media (max-width: 860px) {
  html { scroll-behavior: auto; }
  .panel, .kpi, .cell, .table-wrap, .chip { box-shadow: 0 1px 3px rgba(23, 28, 40, .08); }
  .kpi, .cell, .panel { transition: none; }
  .track-box { box-shadow: 0 6px 20px rgba(23, 28, 40, .14); }
  .hero::after { display: none; }        /* grand cercle flou inutile ici */
}

@media (max-width: 520px) {
  .lang-select select { min-width: 92px; padding: 7px 28px 7px 10px; font-size: 12.5px; }
  .kpi-value { font-size: 27px; }
  .content { padding: 14px 12px 32px; }
  .panel-body { padding: 16px; }
  .section h2 { font-size: 22px; }
}

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

/* ---------------------------------------------------------------------
   Bandeau d'installation de l'application livreur.

   Une bande fine sous l'en-tete, pas un panneau flottant : elle doit
   pouvoir rester affichee en permanence sans jamais couvrir un bouton ni
   masquer une ligne de la tournee.

   La premiere regle n'est pas decorative. Sans elle, .dv-install{display:flex}
   — regle du site — l'emporte sur le [hidden]{display:none} du navigateur,
   et l'attribut hidden ne masque plus rien.
   ------------------------------------------------------------------- */
.dv-install[hidden]{display:none !important}
.dv-install{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  background:#132433;color:#e8eef5;padding:7px 12px;
  font-size:12.5px;line-height:1.35}
.dv-install-txt{flex:1;min-width:150px}

.dv-install-btn{border:0;border-radius:7px;padding:5px 12px;font:inherit;font-weight:700;
  font-size:12.5px;background:#f0a500;color:#132433;cursor:pointer;white-space:nowrap}
.dv-install-btn:hover{background:#ffb81f}

/* Refus definitif : lisible, mais nettement moins appuye que le bouton —
   c'est une sortie, pas une action que l'on met en avant. */
.dv-install-off{background:none;border:0;padding:4px 2px;font:inherit;font-size:11.5px;
  color:#8fa3b8;text-decoration:underline;cursor:pointer;white-space:nowrap}
.dv-install-off:hover{color:#e8eef5}

.dv-install-ios{font-size:12px;opacity:.9}
.dv-install-x{background:none;border:0;color:#8fa3b8;font-size:19px;line-height:1;
  cursor:pointer;padding:0 2px}
.dv-install-x:hover{color:#fff}

/* Porte de retour. Discrete au point de ne pas se remarquer tant qu'on ne
   la cherche pas — mais elle est la, en bas de chaque page. */
.dv-install-back{display:block;margin:14px auto 4px;background:none;border:0;
  padding:6px 10px;font:inherit;font-size:11.5px;color:var(--muted-2,#8fa3b8);
  text-decoration:underline;cursor:pointer}
.dv-install-back:hover{color:var(--brand,#2a4a75)}
.dv-install-back[hidden]{display:none !important}
.da .dv-install-back,
.da-foot + .dv-install-back{color:rgba(255,255,255,.45)}

@media (max-width:360px){
  .dv-install{font-size:12px;padding:6px 10px}
  .dv-install-off{font-size:11px}
}

/* Lien d'inscription eteint : visible, mais clairement inactif. */
.is-off{opacity:.45;cursor:not-allowed;pointer-events:none;text-decoration:none}

/* ---------------------------------------------------------------------
   Selecteur d'agence de l'en-tete.

   Meme gabarit que le selecteur de langue, avec un etat « filtre » bien
   visible : tant qu'une agence est choisie, tous les chiffres de l'ecran
   sont partiels, et cela doit se voir au premier coup d'oeil.            */

.scope-select { display: inline-flex; align-items: center; flex: 0 1 auto; min-width: 0; }
.scope-select select {
  width: auto; max-width: 230px; min-width: 150px;
  padding: 8px 34px 8px 12px;
  font-size: 13px; font-weight: 600; color: var(--ink-2);
  /* Angles droits, comme le selecteur de langue a cote : deux champs
     voisins qui font le meme geste ne doivent pas avoir deux formes. */
  border-radius: var(--r-sm); background-color: var(--surface);
  text-overflow: ellipsis;
}
.scope-select.is-on select {
  border-color: var(--brand); color: var(--brand);
  background-color: var(--surface);           /* repli navigateurs anciens */
  background-color: color-mix(in srgb, var(--brand) 8%, var(--surface));
  box-shadow: 0 0 0 1px var(--brand) inset;
}

/* Le perimetre verrouille : meme forme que le selecteur qu'il remplace et
   que le choix de langue a cote. Un champ qui change de forme selon qu'on
   peut le modifier ou non donne l'impression de deux composants. */
.scope-fixed {
  display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto;
  padding: 8px 14px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--surface);
  font-size: 13px; font-weight: 600; color: var(--ink-2);
  max-width: 220px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.scope-dot {
  width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px;
  background: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-glow);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}

.scope-banner {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 16px; margin-bottom: var(--s4);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);              /* repli navigateurs anciens */
  background: var(--surface);
  border-color: color-mix(in srgb, var(--brand) 30%, var(--line));
  background: color-mix(in srgb, var(--brand) 6%, var(--surface));
  font-size: 13.5px; color: var(--ink-2);
}
.scope-banner strong { color: var(--brand); }

@media (max-width: 860px) {
  /* Sur mobile le titre disparait deja : la barre garde le menu, l'agence
     et la langue. L'agence prend la place restante, elle est le reglage
     que l'on change le plus souvent. */
  .topbar .scope-select { margin-inline-start: auto; flex: 1 1 auto; min-width: 0; }
  .topbar .scope-select select { width: 100%; max-width: none; min-width: 0; }
  .topbar .scope-select + .lang-select { margin-inline-start: 0; }
  .topbar .scope-fixed { margin-inline-start: auto; max-width: 46vw; }
}

@media (max-width: 520px) {
  .scope-select select { padding: 7px 26px 7px 10px; font-size: 12.5px; }
  .lang-select select  { min-width: 64px; }
  .scope-banner { padding: 9px 12px; font-size: 12.5px; }
}

/* Onglets en pilule (validations, securite).
   Ils vivaient dans un bloc <style> a l'interieur de securite.php : la vue
   des validations utilisait les memes classes sans ce bloc, et affichait
   donc deux boutons bruts, sans fond ni etat actif visible. Un style
   partage se declare une fois, ici. */
/* Un seul style d'onglets pour toute la plateforme.
   Il y en avait trois : une barre soulignee ici, un bloc gris arrondi la,
   des pastilles ailleurs — et chacun se comportait differemment quand on
   le selectionnait. Un ecran qu'on apprend une fois doit se relire partout.

   Ils sont bordes et joints, comme les touches d'un selecteur : le trait
   qui les separe dit ou finit l'un et ou commence l'autre. Poses sur un
   fond gris sans bordure, ils se lisaient comme un seul bloc, et l'on
   cherchait la limite entre deux libelles longs. */
.sec-tabs,
.tabs{display:inline-flex;gap:0;background:transparent;border:0;
  border-radius:0;padding:0;margin:0 0 18px;max-width:none;flex-wrap:wrap}
.sec-tab,
.tabs .tab{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  text-align:center;background:var(--surface);font:inherit;font-size:14px;
  font-weight:600;line-height:1.2;color:var(--ink-2);padding:10px 18px;
  border:1px solid var(--ink);border-radius:0;cursor:pointer;text-decoration:none;
  margin-inline-start:-1px;transition:background .15s,color .15s}
.sec-tab:first-child,
.tabs .tab:first-child{margin-inline-start:0;border-start-start-radius:4px;border-end-start-radius:4px}
.sec-tab:last-child,
.tabs .tab:last-child{border-start-end-radius:4px;border-end-end-radius:4px}
.sec-tab:hover,
.tabs .tab:hover{background:var(--line-2);color:var(--ink)}

/* L'onglet ouvert : encre pleine, texte blanc. Il se voit sans qu'on ait
   besoin d'une couleur de marque, qui sert deja aux boutons d'action. */
.sec-tab.on,
.tabs .tab.is-on{background:var(--ink);color:#fff;font-weight:700;
  border-color:var(--ink);position:relative;z-index:1}

/* Une ligne de point de depot.
   Le « display:flex » vivait dans l'attribut style de chaque label : ecrit
   la, il l'emporte sur le [hidden]{display:none} du navigateur, si bien que
   masquer la ligne ne masquait rien. Les points du reseau entier restaient
   donc affiches avant meme le choix de la wilaya. La regle porte le display,
   l'attribut le retire. */
.agLine{display:flex;gap:8px;align-items:center;font-weight:400;padding:2px 0}
.agLine[hidden]{display:none}

/* Les deux moities du suivi : expeditions et reception.
   Meme fond gris que les onglets de validation — c'est la meme nature de
   choix, un aiguillage entre deux vues d'un module — mais plus haut et plus
   large, parce qu'il ouvre l'ecran et commande tout ce qui suit. Le texte
   est centre : dans une pastille etroite, un libelle cale a gauche paraissait
   deborder. */
/* Les deux moities du suivi partagent le style commun, en un peu plus
   large : ce choix ouvre l'ecran et commande tout ce qui suit. */
.view-tabs{display:inline-flex;gap:0;margin:0 0 22px}
.view-tab{display:inline-flex;align-items:center;justify-content:center;
  min-width:150px;text-align:center;font-size:14.5px;font-weight:600;line-height:1.2;
  color:var(--ink-2);background:var(--surface);text-decoration:none;padding:11px 22px;
  border:1px solid var(--ink);border-radius:0;margin-inline-start:-1px;
  transition:background .15s,color .15s}
.view-tab:first-child{margin-inline-start:0;border-start-start-radius:4px;border-end-start-radius:4px}
.view-tab:last-child{border-start-end-radius:4px;border-end-end-radius:4px}
.view-tab:hover{background:var(--line-2);color:var(--ink)}
.view-tab.is-on{background:var(--ink);color:#fff;font-weight:700;
  border-color:var(--ink);position:relative;z-index:1}

/* Onglets de navigation interne (module wilayas, ecran tarifs). */
/* Les onglets ouvrent souvent la page, juste sous le titre de la barre du
   haut : sans marge, ils s'y collaient et la premiere ligne du contenu
   paraissait remontee. Un peu d'air au-dessus, et davantage en dessous pour
   detacher l'onglet actif de ce qu'il ouvre. */
/* L'ancienne barre soulignee a fusionne avec le style commun ci-dessus. */

/* ------------------------------------------------------------------ */
/* Un secret montre une seule fois.
   Le libelle et la cle se touchaient, et la cle se coupait au milieu d'un
   mot. Elle a desormais son propre cadre, une respiration autour, et une
   coupure caractere par caractere : sur un ecran etroit, une cle de
   quarante-quatre signes doit rester lisible d'un bout a l'autre. */
.secret-box { border-color: var(--ok, #1a7f37); }
.secret-title { font-weight: 700; font-size: 15px; margin-bottom: 14px; color: var(--ink, #201e1d); }

.secret-row {
  display: flex; align-items: stretch; gap: 10px; flex-wrap: wrap;
}
.secret-value {
  flex: 1 1 260px; min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15px; line-height: 1.6; letter-spacing: .3px;
  background: var(--surface, #faf9f7);
  border: 1px solid var(--line, #e6e9ee); border-radius: 8px;
  padding: 11px 13px;
  word-break: break-all; overflow-wrap: anywhere;
  user-select: all;            /* un clic selectionne tout, sans la souris */
}
.secret-copy { flex: 0 0 auto; align-self: center; }
.secret-note { margin: 12px 0 0; font-size: 13px; color: var(--muted, #6b7280); }

@media (max-width: 560px) {
  .secret-copy { width: 100%; }
}

/* Saisie qui ne correspond a aucun client : on le signale sans bloquer —
   une expedition ponctuelle sans expediteur reste legitime. */
.input.is-unmatched { border-color: var(--warn, #b7791f); }

/* ------------------------------------------------------------------ */
/* Liste deroulante a cases.
   Un « select multiple » natif se manipule au Ctrl+clic — personne ne le
   devine, et sur mobile il est inutilisable. Ce panneau s'ouvre au clic,
   montre le nombre de colis par ligne, et se ferme quand on clique
   ailleurs ou qu'on appuie sur Echap. */
.dropdown { position: relative; display: inline-block; }

.dropdown-panel {
  position: absolute; top: calc(100% + 6px); inset-inline-start: 0; z-index: 40;
  min-width: 280px; max-height: 340px; overflow-y: auto;
  background: #fff; border: 1px solid var(--line, #e6e9ee);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.12);
  padding: 6px;
}
.dropdown-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 7px; cursor: pointer;
  font-size: 14px; line-height: 1.3;
}
.dropdown-item:hover { background: var(--surface, #faf9f7); }
.dropdown-item input { margin: 0; flex: 0 0 auto; }

.dropdown-foot {
  display: flex; gap: 8px; align-items: center;
  padding: 10px 10px 4px; margin-top: 4px;
  border-top: 1px solid var(--line, #e6e9ee);
  position: sticky; bottom: 0; background: #fff;
}

@media (max-width: 560px) {
  .dropdown-panel { min-width: 240px; }
}

/* Barre de scan du suivi. Le champ reste large : une douchette y jette
   quinze caracteres d'un coup, et l'operateur doit voir ce qui est entre. */
.scanbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.scanbar .input { min-width: 220px; max-width: 320px; }
.scanbar .input:focus { border-color: var(--accent); }

/* Le colis qui vient d'etre scanne : un rappel visuel d'une seconde, pour
   confirmer sans interrompre l'enchainement. */
@keyframes scanFlash { from { background: var(--ok-bg, #e6f4ea); } to { background: transparent; } }
.table tbody tr.just-scanned { animation: scanFlash 1.6s ease-out; }

/* ------------------------------------------------------------------ */
/* Barres d'outils : tout a la meme hauteur.
 *
 * Les champs se dessinent en 11px/15px et les petits boutons en 8px/13px :
 * six pixels d'ecart, invisibles a l'oeil nu dans le code, evidents a
 * l'ecran des qu'on les met cote a cote. Chaque element d'une barre partage
 * donc la meme hauteur et le meme axe, quel que soit son type.
 */
.filters .input,
.filters select,
.filters .btn,
.filters .chip,
.scanbar .input,
.scanbar select,
.scanbar .btn {
  height: 38px;
  min-height: 38px;
  padding-block: 0;
  font-size: 14px;
  line-height: 1.2;
  align-self: center;
}

/* Les listes deroulantes portent un chevron : sans reserve a droite, le
   texte long passe dessous. Le sens suit la langue — a droite en francais,
   a gauche en arabe. */
.filters select,
.scanbar select {
  padding-inline-end: 30px;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-size: 5px 5px, 5px 5px;
  background-position: right 14px center, right 9px center;
  background-repeat: no-repeat;
}
[dir="rtl"] .filters select,
[dir="rtl"] .scanbar select {
  background-position: left 9px center, left 14px center;
}

/* Un champ ne s'etire plus a toute la largeur dans une barre : « width:100% »
   convient a un formulaire empile, pas a une ligne d'outils. */
.filters .input,
.filters select { width: auto; }

/* Bouton de copie d'un numero de suivi : discret dans la ligne, visible au
   survol, et qui confirme brievement au clic. */
.btn-copy {
  border: 0; background: transparent; cursor: pointer;
  padding: 2px 4px; margin-inline-start: 4px; border-radius: 4px;
  font-size: 13px; line-height: 1; opacity: .35;
  transition: opacity .15s, background .15s;
}
tr:hover .btn-copy { opacity: .75; }
.btn-copy:hover   { opacity: 1; background: var(--surface); }
.btn-copy.is-copied { opacity: 1; background: var(--ok-bg, #e6f4ea); }
.btn-copy.is-copied::after { content: " copie"; font-size: 11px; color: var(--ok, #1a7f37); }

/* ------------------------------------------------------------------ */
/* Navigation horizontale — grands ecrans                              */
/* ------------------------------------------------------------------ */
/* Une colonne de dix-huit entrees mange un cinquieme de la largeur en
   permanence, alors qu'on la parcourt une fois et qu'on travaille ensuite
   dans le contenu. Repliee en groupes, elle tient sur une ligne et rend la
   place aux tableaux, qui en ont besoin.

   Sous 860 pixels, la colonne reprend la main : un menu deroulant sous le
   pouce vaut mieux qu'une rangee d'onglets serres. Les deux lisent le meme
   menu, donc les memes droits — il n'y a pas deux listes a tenir. */
.topnav { display: none; }

@media (min-width: 861px) {
  .sidebar { display: none; }
  .topnav {
    display: flex; align-items: center; gap: 2px; flex-wrap: wrap;
    background: var(--surface); border-bottom: 1px solid var(--line);
    padding: 0 var(--s6); position: sticky; top: 0; z-index: 40;
  }
  /* Un trait entre les groupes.
     Colles, « Exploitation » et « Reseau » se lisaient comme une phrase :
     un filet vertical et un peu d'air disent que ce sont deux ensembles
     distincts, et l'oeil compte les groupes au lieu de lire les mots. */
  .topnav-grp {
    position: relative; margin-inline-start: 10px; padding-inline-start: 10px;
  }
  .topnav-grp::before {
    content: ""; position: absolute; inset-inline-start: 0; top: 12px; bottom: 12px;
    width: 1px; background: var(--line);
  }
  .topnav-grp:first-of-type { margin-inline-start: 6px; }

  /* Le compte, a droite : son nom et sa deconnexion. Il n'a pas de filet
     avant lui — il ne fait pas partie de la suite des modules. */
  .topnav-me { margin-inline-start: auto; }
  .topnav-me::before { display: none; }
  .topnav-me > summary { padding-block: 9px; }
  .topnav-me-name { max-width: 150px; overflow: hidden; text-overflow: ellipsis; }
  .avatar-sm { width: 28px; height: 28px; flex: 0 0 28px; font-size: 11px; }
  .topnav-grp > summary,
  .topnav-link {
    display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
    padding: 14px 16px; font-size: 14px; font-weight: 600; color: var(--ink-2);
    text-decoration: none; list-style: none; white-space: nowrap;
    border-bottom: 2px solid transparent; transition: background .15s, color .15s;
  }
  .topnav-grp > summary::-webkit-details-marker { display: none; }
  .topnav-grp > summary::after {
    content: ""; width: 6px; height: 6px; margin-inline-start: 2px;
    border-inline-end: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px); opacity: .55;
  }
  .topnav-grp > summary:hover,
  .topnav-link:hover { background: var(--line-2); color: var(--ink); }

  /* Le groupe ouvert : on sait ou l'on se trouve sans avoir a deplier. */
  .topnav-grp.is-active > summary,
  .topnav-link.is-active {
    color: var(--ink); border-bottom-color: var(--ink); font-weight: 700;
  }
  .topnav-grp[open] > summary { background: var(--line-2); color: var(--ink); }

  .topnav-menu {
    position: absolute; inset-inline-start: 0; top: 100%; min-width: 250px;
    background: var(--surface); border: 1px solid var(--ink); border-radius: 4px;
    box-shadow: var(--sh); padding: 5px; z-index: 50;
  }
  /* Le sous-titre d'un module dans une liste deroulante : il annonce les
   moities qui suivent, sans etre cliquable — on ne clique pas sur un
   regroupement. */
.topnav-sous {
  padding: 8px 12px 3px; font-size: 11px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--muted);
}
.topnav-sous + .topnav-item, .topnav-sous ~ .topnav-item { padding-inline-start: 22px; }

.topnav-item {
    display: flex; align-items: center; gap: 10px; padding: 9px 12px;
    border-radius: 3px; font-size: 14px; font-weight: 500;
    color: var(--ink-2); text-decoration: none;
  }
  .topnav-item:hover { background: var(--line-2); color: var(--ink); }
  .topnav-item.is-active { background: var(--ink); color: #fff; font-weight: 600; }
  .topnav-item.is-active .nav-count { background: rgba(255,255,255,.22); color: #fff; }

  /* La barre de titre se colle sous la navigation, sans marche. */
  .main > .topbar { border-top: 0; }
}

/* Meme chose dans la colonne, cote telephone. */
.nav-sous {
  padding: 10px 10px 2px; font-size: 11px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--muted);
}

/* ---------------------------------------------------------------- */
/* Remonter en haut — site public                                    */
.to-top {
  position: fixed; inset-inline-end: 20px; bottom: 20px; z-index: 40;
  width: 44px; height: 44px; display: inline-flex;
  align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: #fff; color: var(--ink); cursor: pointer;
  box-shadow: 0 4px 16px rgba(23, 28, 40, .14);
  transition: background .15s, transform .15s;
}
.to-top:hover { background: var(--line-2); transform: translateY(-2px); }
.to-top[hidden] { display: none; }
@media (max-width: 640px) {
  .to-top { inset-inline-end: 14px; bottom: 14px; width: 42px; height: 42px; }
}

/* ---------------------------------------------------------------- */
/* Reglages : des colonnes qui coulent                               */
/* Une grille a deux colonnes aligne ses rangees : un panneau court
   laisse sous lui le vide de son voisin le plus haut. Les colonnes CSS
   enchainent les panneaux et remplissent l'espace. */
.reglages-cols { column-count: 2; column-gap: var(--s4); }
.reglages-cols > .panel {
  /* Un panneau ne se coupe jamais entre deux colonnes. */
  break-inside: avoid; -webkit-column-break-inside: avoid; page-break-inside: avoid;
  display: inline-block; width: 100%; margin: 0 0 var(--s4);
}
@media (max-width: 1080px) { .reglages-cols { column-count: 1; } }

/* ---------------------------------------------------------------- */
/* Un panneau qu'on deplie                                           */
/* Le marqueur natif du navigateur se place mal dans un en-tete de
   panneau : on le remplace par un chevron a droite, qui pivote. */
details.panel > summary::-webkit-details-marker { display: none; }
details.panel > summary::after {
  content: ""; width: 9px; height: 9px; flex: 0 0 9px;
  border-inline-end: 2px solid var(--muted); border-block-end: 2px solid var(--muted);
  transform: rotate(-45deg); transition: transform .18s; margin-inline-start: 4px;
}
details.panel[open] > summary::after { transform: rotate(45deg); }
details.panel > summary:hover { background: var(--line-2); }

/* ---------------------------------------------------------------- */
/* Le statut en pastille, dans un tableau                            */
/* Les couleurs d'etape n'existaient que dans la barre d'onglets :
   une pastille posee ailleurs retombait sur le fond noir des puces
   actives. Elle a donc sa propre classe, avec les memes six tons — la
   colonne se lit alors comme la barre, sans en dependre. */
.etat-pill {
  display: inline-flex; align-items: center; justify-content: center;
  /* Angles droits et de l'air autour du texte : une pastille arrondie fait
     etiquette decorative, un rectangle fait donnee. */
  padding: 6px 12px; border-radius: var(--r-sm); white-space: nowrap;
  font-size: 12px; font-weight: 600; line-height: 1.35;
  background: var(--line-2); color: var(--muted);
}
.etat-pill.st-idle { background: var(--line-2); color: var(--muted); }
.etat-pill.st-wait,
.etat-pill.st-warn { background: #fdf6e3;      color: #b7791f; }
.etat-pill.st-road,
.etat-pill.st-move { background: #eaf1fb;      color: #2563a8; }
.etat-pill.st-hold { background: #eeeafb;      color: #5b46b8; }
.etat-pill.st-ok,
.etat-pill.st-done { background: var(--ok-bg); color: var(--ok); }
.etat-pill.st-bad  { background: #fdecea;      color: #c62828; }

/* ---------------------------------------------------------------- */
/* Carreaux de statistiques — tableau d'ensemble                     */
/* Le nombre d'abord, gros et lisible de loin ; l'etape en dessous.
   Ils reprennent les six tons des onglets : la couleur dit la phase
   sans qu'on lise le mot. Chaque carreau ouvre sa file. */
.stat-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.stat-tile {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 14px; border-radius: var(--r-sm);
  background: var(--line-2); color: var(--ink); text-decoration: none;
  border: 1px solid transparent; transition: transform .12s, box-shadow .12s;
}
.stat-tile:hover { transform: translateY(-1px); box-shadow: var(--sh-sm); color: var(--ink); }
.stat-n { font-size: 22px; font-weight: 700; line-height: 1.1; }
/* Un montant ne passe jamais a la ligne.
   « 360 000,00 » en gras a 22 pixels ne tenait pas dans une tuile de 132 :
   il se coupait en deux lignes, « 360 » puis « 000,00 ». Le chiffre prend
   desormais la taille que lui laisse sa tuile — 22 pixels quand il y a la
   place, jusqu'a 15 quand il n'y en a pas — et reste sur une ligne. Les
   chiffres a chasse fixe gardent les montants alignes d'une tuile a l'autre. */
.stat-tile { container-type: inline-size; }
.stat-tile .stat-n { white-space: nowrap; font-variant-numeric: tabular-nums;
                     font-size: clamp(15px, 13.5cqi, 22px); overflow: hidden; text-overflow: ellipsis; }
.stat-l { font-size: 11.5px; font-weight: 600; line-height: 1.25; opacity: .82; }

.stat-tile.st-idle { background: var(--line-2); color: var(--muted); }
.stat-tile.st-wait,
.stat-tile.st-warn { background: #fdf6e3;      color: #b7791f; }
.stat-tile.st-road,
.stat-tile.st-move { background: #eaf1fb;      color: #2563a8; }
.stat-tile.st-hold { background: #eeeafb;      color: #5b46b8; }
.stat-tile.st-ok,
.stat-tile.st-done { background: var(--ok-bg); color: var(--ok); }
.stat-tile.st-bad  { background: #fdecea;      color: #c62828; }

/* ---------------------------------------------------------------- */
/* Parcours deplie sous une ligne de tableau                         */
.etat-pill.etat-go { border: 0; cursor: pointer; font-family: inherit; }
.etat-pill.etat-go:hover { filter: brightness(.96); }
.etat-pill.etat-go.is-open { box-shadow: inset 0 0 0 2px currentColor; }
/* Le parcours, en panneau cale sous la pastille. */
.etat-pop {
  position: absolute; z-index: 30; inset-inline-start: 0; top: calc(100% + 6px);
  /* Assez haut pour huit mouvements sans defilement : un panneau qu'il
     faut faire defiler pour lire trois dates ne vaut pas mieux que la
     fiche qu'il remplace. */
  min-width: 290px; max-width: 400px; max-height: none;
  padding: 12px 14px; border-radius: var(--r-sm);
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 8px 24px rgba(23, 28, 40, .16);
  text-align: start; white-space: normal;
}
/* Pres du bord droit, il s'ouvre vers l'interieur. */
.table td:last-child .etat-pop,
.table td:nth-last-child(2) .etat-pop { inset-inline-start: auto; inset-inline-end: 0; }
.etat-tl { display: flex; flex-direction: column; gap: 5px; }
.etat-tl-l { font-size: 12.5px; line-height: 1.35; }
.etat-tl-d { font-family: var(--mono, monospace); font-size: 12px; color: var(--muted); }

/* ------------------------------------------------------------------ */
/*  Liste deroulante de recherche (client, expediteur).                */
/*                                                                     */
/*  Le « datalist » du navigateur imposait son rendu : texte blanc sur */
/*  fond blanc chez certains, et l'on ne voyait pas le client qu'on    */
/*  venait de trouver. Ici les couleurs sont les notres.              */
/* ------------------------------------------------------------------ */
.combo-list {
  position: absolute; z-index: 40; inset-inline: 0; top: calc(100% + 4px);
  margin: 0; padding: 4px; list-style: none;
  max-height: 260px; overflow-y: auto;
  background: var(--card, #fff); color: var(--ink, #1a1a1a);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  box-shadow: var(--sh-md, 0 8px 24px rgba(0,0,0,.12));
}
.combo-item {
  display: flex; align-items: baseline; gap: 8px;
  padding: 8px 10px; border-radius: var(--r-xs, 4px); cursor: pointer;
}
.combo-item:hover, .combo-item:focus { background: var(--brand-050, #f4f6f9); }
.combo-nom  { font-weight: 600; color: var(--ink, #1a1a1a); }
.combo-meta { font-size: 12px; color: var(--muted, #6b7280); }
.combo-vide { padding: 10px; font-size: 13px; color: var(--muted, #6b7280); }

/* ------------------------------------------------------------------ */
/*  Les trois chiffres de tete du tableau de bord.                     */
/*                                                                     */
/*  Serres, ils passaient pour des notes en marge — or ce sont les     */
/*  premiers qu'on regarde. Ils occupent donc la hauteur d'un panneau  */
/*  ordinaire, comme les blocs qu'ils remplacent.                      */
/* ------------------------------------------------------------------ */
.kpi-row .kpi-card { display: flex; flex-direction: column; }
.kpi-row .kpi-card .panel-body {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center; padding: var(--s5, 20px) var(--s4, 16px);
}
.kpi-big {
  font-size: 40px; font-weight: 700; line-height: 1.1;
  color: var(--ink); letter-spacing: -.02em;
}
.kpi-sub { margin-top: 8px; font-size: 13px; color: var(--muted); }

/* Pas de liseret de couleur sur ces trois panneaux.
 *
 * Il rappelait la nature du chiffre, mais trois bordures colorees en tete
 * de page attirent l'oeil avant les chiffres eux-memes — et l'on regarde
 * la couleur au lieu de lire. Les panneaux ordinaires n'en ont pas ; ceux-ci
 * non plus. */

@media (max-width: 720px) {
  .kpi-big { font-size: 32px; }
}

/* ==================================================================== */
/*  Mobile : ce qui ne peut pas retrecir doit defiler, pas deborder.     */
/*                                                                      */
/*  Audit de vingt ecrans : des tableaux poses sans leur cadre defilant, */
/*  des grilles en pixels, des largeurs minimales figees. Chacun poussait */
/*  la page de cote — et c'est la page entiere qui partait, pas          */
/*  seulement le bloc fautif : on perdait le menu et les boutons.        */
/*                                                                      */
/*  Plutot que de reprendre vingt vues, on borne ici. Rien n'est         */
/*  supprime : le contenu defile dans son propre cadre.                  */
/* ==================================================================== */
@media (max-width: 860px) {

  /* Un tableau garde ses colonnes lisibles et defile lateralement, dans
     son cadre. Pose sans cadre, il emportait la page. */
  .panel-body > table,
  .panel > table,
  main table:not(.table-wrap table) {
    display: block; width: 100%; overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Les grilles ecrites en dur dans une vue se replient — sauf celles qui
     savent deja s'adapter : « auto-fill », « auto-fit » et tout « minmax »,
     qui porte sa propre largeur de repli. Les replier de force gacherait la
     place et, pire, ecrasait des formulaires qui se comportaient bien. */
  [style*="grid-template-columns"]:not([style*="auto-fill"]):not([style*="auto-fit"]):not([style*="minmax"]) {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  /* Une largeur minimale figee au-dela de l'ecran se desserre — mais pas
     celle d'une colonne de grille, qui decide de la mise en page. La regle
     visait trop large : elle ecrasait aussi les « minmax(280px, 1fr) » des
     formulaires, et leurs champs se repliaient en une seule colonne des
     l'ouverture. */
  .table-wrap[style*="min-width"],
  table[style*="min-width"],
  .panel > [style*="min-width"] { min-width: 0 !important; }

  /* Rien ne depasse horizontalement : la derniere barriere, quand une
     vue future oubliera les regles ci-dessus. */
  html, body { overflow-x: hidden; }
  .panel, .panel-body, .field, .filters { max-width: 100%; }
  img, iframe, pre, code { max-width: 100%; }

  /* Les champs cote a cote passent l'un sous l'autre plutot que de se
     comprimer a trois caracteres. */
  .field > .input, .field > select, .field > textarea { width: 100%; }
}

/* Sur un telephone etroit, les paires de champs se defont aussi. */
@media (max-width: 520px) {
  .btn-row { flex-direction: column; align-items: stretch; }
  .btn-row > .btn { width: 100%; }
  .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tabs > .tab { white-space: nowrap; }
}

/* ==================================================================== */
/*  Mobile : les rangees de champs posees a la main.                     */
/*                                                                      */
/*  Plusieurs formulaires alignent leurs champs avec « display:flex »   */
/*  plutot qu'avec une grille, et leur donnent une largeur maximale en  */
/*  pixels — « max-width: 130px » pour un selecteur, « 260px » pour un  */
/*  mot de passe. Sur un telephone, ces largeurs ne retrecissent pas :  */
/*  les champs se chevauchent, et l'on ne peut plus rien saisir.        */
/*                                                                      */
/*  Les grilles etaient deja traitees ; ces rangees-la ne l'etaient     */
/*  pas, faute d'attribut « grid-template-columns » a reconnaitre.      */
/* ==================================================================== */
@media (max-width: 860px) {

  /* Une rangee de champs se replie plutot que de comprimer ses colonnes.
   *
   * « flex-wrap » plutot que « :has » : le premier est compris partout,
   * le second manque encore aux navigateurs un peu anciens — et un
   * formulaire illisible sur un vieux telephone reste illisible. Les
   * elements passent a la ligne quand ils ne tiennent plus, et restent
   * cote a cote quand il y a la place. */
  form [style*="display:flex"],
  form [style*="display: flex"] {
    flex-wrap: wrap !important;
  }

  /* Un champ dans une telle rangee prend toute la largeur disponible :
     sans cela il garderait sa taille naturelle, trop courte pour une
     saisie confortable. */
  form [style*="display:flex"] > .input,
  form [style*="display:flex"] > select,
  form [style*="display:flex"] > textarea,
  form [style*="display: flex"] > .input,
  form [style*="display: flex"] > select,
  form [style*="display: flex"] > textarea {
    flex: 1 1 100%;
    min-width: 0;
  }

  /* Les largeurs maximales en pixels a l'interieur d'un formulaire : sur
     un ecran de 360 px, « max-width: 340px » laisse le champ deborder de
     sa colonne des qu'une marge s'y ajoute. */
  form .field[style*="max-width"],
  form [style*="display:flex"] > [style*="max-width"],
  form [style*="display: flex"] > [style*="max-width"] {
    max-width: 100% !important;
  }

  /* Une case a cocher suivie de son intitule reste en ligne : la passer
     en colonne separerait la case de ce qu'elle coche. */
  form label[style*="display:flex"] {
    flex-direction: row !important;
    align-items: center !important;
  }
}

/* ==================================================================== */
/*  Mobile : un champ par ligne, sans exception.                        */
/*                                                                      */
/*  Les regles precedentes repliaient les grilles, et elles le font.    */
/*  Mais un champ pose sans conteneur de grille — ou dans une grille    */
/*  qu'une regle plus specifique retablit — se retrouvait encore a      */
/*  cote de son voisin, trop etroit pour qu'on y lise quoi que ce soit. */
/*                                                                      */
/*  Cette regle ferme le sujet : sous 700 px, tout bloc de formulaire   */
/*  occupe la largeur entiere, et le suivant passe dessous. Elle vient  */
/*  en dernier, donc elle l'emporte a specificite egale.                */
/* ==================================================================== */
@media (max-width: 700px) {

  /* Toute grille d'un formulaire : une seule colonne. */
  form .grid,
  form [class*="grid-"],
  .panel-body > .grid,
  .panel-body > [class*="grid-"] {
    display: block !important;
  }

  /* Chaque champ prend la ligne, et respire sous le precedent. */
  form .field,
  .panel-body .field {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    margin-bottom: 14px;
  }

  /* Le champ lui-meme remplit son bloc, quelle que soit sa classe. */
  form .field > input,
  form .field > select,
  form .field > textarea,
  .panel-body .field > input,
  .panel-body .field > select,
  .panel-body .field > textarea {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box;
  }

  /* Une case a cocher garde sa taille : l'etirer sur la largeur ferait
     un rectangle qu'on ne reconnait plus. */
  form .field > input[type="checkbox"],
  form .field > input[type="radio"],
  .panel-body .field > input[type="checkbox"],
  .panel-body .field > input[type="radio"] {
    width: auto !important;
  }
}

/* Les sous-onglets d'un ecran : plus petits que la barre principale, pour
   qu'on voie d'un coup d'oeil lequel navigue entre les ecrans et lequel
   navigue a l'interieur de celui qu'on regarde. */
.tabs-sm .tab { font-size: 13px; padding: 6px 12px; }
.tabs-sm .tab .n { font-size: 11px; }

/* ------------------------------------------------------------------ */
/*  Tete du tableau de bord : deux chiffres empiles, l'anneau a cote.  */
/* ------------------------------------------------------------------ */
.dash-top { align-items: stretch; }
.dash-stack { display: flex; flex-direction: column; gap: var(--s4, 16px); }
.dash-stack .kpi-card { flex: 1; }

.donut-body {
  display: flex; align-items: center; justify-content: center;
  gap: 28px; flex-wrap: wrap; padding: 20px 16px;
}
.donut { width: 180px; height: 180px; flex: none; }
.donut circle { transition: stroke-dasharray .4s ease; }
.donut-n { font-size: 24px; font-weight: 700; fill: var(--ink, #101828); }
.donut-l { font-size: 12px; fill: var(--muted, #667085); }

.donut-legend { list-style: none; margin: 0; padding: 0; min-width: 170px; }
.donut-legend li {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid var(--line, #eef1f5);
}
.donut-legend li:last-child { border-bottom: 0; }
.donut-dot { width: 11px; height: 11px; border-radius: 50%; flex: none; }

/* Sur telephone, l'anneau passe sous les deux chiffres et la legende sous
   l'anneau : cote a cote, ils se seraient ecrases mutuellement. */
@media (max-width: 860px) {
  .donut-body { flex-direction: column; gap: 16px; }
  .donut-legend { width: 100%; }
}

/* ------------------------------------------------------------------ */
/*  Fenetre de scan.                                                   */
/* ------------------------------------------------------------------ */

/* L'indicateur qui remplace le champ : on sait que la fenetre ecoute. */
.sp-ready {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 10px 14px;
  background: var(--brand-050, #f4f6f9); border: 1px solid var(--line, #e3e7ee);
  border-radius: var(--r-sm, 8px); font-size: 14px;
}
.sp-dot {
  width: 10px; height: 10px; border-radius: 50%; flex: none;
  background: #2e7d32; box-shadow: 0 0 0 0 rgba(46,125,50,.5);
  animation: sp-pulse 1.6s infinite;
}
@keyframes sp-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(46,125,50,.45); }
  70%  { box-shadow: 0 0 0 8px rgba(46,125,50,0); }
  100% { box-shadow: 0 0 0 0 rgba(46,125,50,0); }
}
@media (prefers-reduced-motion: reduce) { .sp-dot { animation: none; } }

/* Les deux tableaux : des traits nets entre les lignes, et chaque tableau
   encadre. Les traits fins de la table ordinaire se perdaient a distance
   d'ecran, la douchette a la main — on ne voyait plus ou finissait une
   ligne. */
.sp-table { border: 1px solid #c9d0db; border-radius: 8px; overflow: hidden; }
.sp-table thead th {
  background: #eef1f5; border-bottom: 2px solid #c9d0db;
  font-weight: 700; color: var(--ink, #101828);
}
.sp-table tbody td { border-bottom: 1px solid #d5dbe4; padding-top: 10px; padding-bottom: 10px; }
.sp-table tbody tr:last-child td { border-bottom: 0; }
.sp-table tbody tr:nth-child(even) td { background: #fafbfc; }
/* Le tableau des colis passes se distingue d'un liseret vert : on voit
   d'un coup d'oeil de quel cote un colis vient d'aller. */
.sp-done { border-color: #a5d6a7; }
.sp-done thead th { background: #e8f5e9; border-bottom-color: #a5d6a7; }

/* Le taux de reussite d'une ligne de rapport : le chiffre, et une barre
   dessous pour comparer les lignes d'un coup d'oeil. */
.rapport-taux { display: block; font-weight: 600; }
.rapport-barre {
  display: block; height: 5px; margin-top: 4px; margin-left: auto;
  width: 90px; max-width: 100%;
  background: #eef1f5; border-radius: 3px; overflow: hidden;
}
.rapport-barre i { display: block; height: 100%; background: #2e7d32; border-radius: 3px; }

/* ------------------------------------------------------------------ */
/*  Reception de la caisse d'un livreur.                               */
/* ------------------------------------------------------------------ */
.rec-caisse { position: sticky; top: 16px; }
.rec-ligne { display: flex; justify-content: space-between; align-items: baseline; font-size: 15px; }
.rec-ligne strong { font-size: 22px; }
/* Le montant compte se tape en grand : c'est le chiffre de la journee, et
   une erreur de frappe sur un petit champ passe inaperçue. */
.rec-montant { font-size: 22px; font-weight: 700; text-align: right; padding: 12px 14px; }
.rec-ecart { margin: 0 0 14px; padding: 10px 12px; border-radius: 8px; font-weight: 600; }
.rec-ecart.ok  { background: #e8f5e9; color: #2e7d32; }
.rec-ecart.bad { background: #fdecea; color: #c62828; }
@media (max-width: 860px) { .rec-caisse { position: static; } }

/* Le calcul d'un bordereau : une colonne de chiffres qui se lit comme une
   addition posee, le net souligne en bas. */
.calcul td { border: 0; padding: 7px 0; }
.calcul .num { white-space: nowrap; }
.calcul-net td { border-top: 2px solid var(--ink, #101828) !important;
                 font-weight: 700; font-size: 17px; padding-top: 10px; }

/* Le retour confirme, dans l'application du livreur : un geste sans retour
   arriere, qui se distingue de l'echec par sa couleur. */
.dv-retour { border-left: 4px solid #d84315; }
.dv-btn-retour { background: #d84315; color: #fff; border-color: #d84315; }
.dv-btn-retour:hover { background: #bf360c; color: #fff; }

/* ------------------------------------------------------------------ */
/*  Fonds : le suivi d'un transfert, etape par etape.                  */
/* ------------------------------------------------------------------ */
.fonds-etapes { list-style: none; margin: 0; padding: 0; }
.fonds-etapes li { display: flex; gap: 12px; padding: 0 0 16px; position: relative; }
.fonds-etapes li:not(:last-child)::before {
  content: ""; position: absolute; left: 6px; top: 16px; bottom: 0; width: 2px; background: #dde2ea; }
.fonds-etapes .pt { width: 14px; height: 14px; border-radius: 50%; flex: none; margin-top: 3px;
  border: 2px solid #c9d0db; background: #fff; position: relative; z-index: 1; }
.fonds-etapes li.fait .pt { background: #2e7d32; border-color: #2e7d32; }
.fonds-etapes li.fait:not(:last-child)::before { background: #a5d6a7; }
.ligne-total td { border-top: 2px solid var(--ink, #101828) !important; }

/* Un geste impossible reste visible, grise, avec sa raison dessous : un
   bouton qui disparait laisse croire que la fonction n'existe pas. */
.geste-bloque { opacity: .45; cursor: not-allowed; }
.geste-raison { display: block; max-width: 260px; margin: 4px 0 0 auto;
                font-size: 11px; line-height: 1.35; color: var(--muted, #667085); text-align: right;
                white-space: normal; }

/* Les gestes d'une facture : regler au guichet, emettre un avoir. */
.facture-geste { display: flex; gap: 6px; justify-content: flex-end; margin-top: 6px; }
.facture-geste .input { max-width: 170px; padding: 5px 8px; font-size: 12.5px; }
/* Gestes d'une facture (regler, avoir) : replies sous « Plus », la ligne reste lisible. */
.facture-plus{display:inline-block;position:relative;text-align:start}
.facture-plus>summary{list-style:none;cursor:pointer}
.facture-plus>summary::-webkit-details-marker{display:none}
.facture-plus-menu{position:absolute;inset-inline-end:0;z-index:20;background:var(--card,#fff);border:1px solid var(--line,#e5e7eb);
  border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.12);padding:10px;display:grid;gap:10px;width:240px}
.facture-plus-menu .facture-geste{display:grid;gap:6px;justify-content:stretch;margin:0}
.facture-plus-menu .facture-geste .input{max-width:none}


/* Les statistiques du tableau de bord et du suivi sur une seule ligne.
   Avec « En transit », la rangee comptait une tuile de trop et « Retours »
   passait a la ligne. Chaque rangee se partage desormais la largeur en
   autant de colonnes que de tuiles ; le chiffre s'adapte a sa tuile. Sur un
   ecran etroit, elle se replie, faute de place. */
.stat-grid.stat-ligne { grid-template-columns: repeat(var(--n, 7), minmax(0, 1fr)); }
.stat-grid.stat-ligne .stat-l { overflow-wrap: anywhere; }
@media (max-width: 900px) {
  .stat-grid.stat-ligne { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
}

/* Fenetre par-dessus la page (scan, ramassage, import, stockage) : un seul
   voile, defini une fois pour toutes les pages. */
.scan-modal{position:fixed;inset:0;z-index:80;padding:24px;background:rgba(15,18,25,.55);display:flex;align-items:flex-start;justify-content:center}
.scan-modal[hidden]{display:none}
@media (max-width:600px){.scan-modal{padding:10px}}
/* Un champ masque reste masque : une regle d'affichage plus haut l'emportait
   sur [hidden], et la commune restait visible en mode bureau (stop desk). */
.field[hidden]{display:none !important}

/* Les trois temps d'une navette : creee, partie, arrivee. */
.nav-steps { display: flex; gap: 0; list-style: none; margin: 0; padding: 0; }
.nav-steps li { position: relative; padding: 0 18px; text-align: center; min-width: 110px; }
.nav-steps li + li::before { content: ""; position: absolute; top: 9px; inset-inline-start: -30px; width: 60px; height: 2px; background: var(--line); }
.nav-steps li span { display: block; font-weight: 600; font-size: 13px; color: var(--muted); }
.nav-steps li span::before { content: ""; display: block; width: 12px; height: 12px; margin: 3px auto 6px; border-radius: 50%; background: var(--line); }
.nav-steps li small { display: block; font-size: 11.5px; color: var(--muted); }
.nav-steps li.is-done span { color: var(--ink); }
.nav-steps li.is-done span::before { background: var(--ok, #1f8a4c); }
.nav-steps li.is-now span { color: var(--ink); }
.nav-steps li.is-now span::before { background: #d4a017; box-shadow: 0 0 0 4px rgba(212,160,23,.18); }
@media (max-width: 640px) { .nav-steps li { min-width: 0; padding: 0 8px; } .nav-steps li + li::before { display: none; } }
