:root {
  --fond: #faf8f5;
  --surface: #ffffff;
  --bordure: #e4ddd3;
  --texte: #2b2622;
  --texte-discret: #7a7165;
  --accent: #8a6d3b;
  --accent-fonce: #6b5329;
  --danger: #a4373a;
  --rayon: 6px;
}

* { box-sizing: border-box; }

/* Sans ce !important, un élément avec `hidden` mais aussi une classe qui
   fixe `display` (ex. .barre-recherche, .barre-selection en display:flex)
   restait visible : les deux règles ont la même spécificité, et l'origine
   "auteur" l'emporte toujours sur la feuille de style du navigateur,
   `hidden` ou pas. Trouvé le 2026-07-21 en vérifiant le nouveau bloc de
   filtres avancés du catalogue, qui restait affiché après rechargement. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--fond);
  color: var(--texte);
  font-size: 15px;
  line-height: 1.45;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

header.entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.8rem 1.5rem;
  background: var(--surface);
  border-bottom: 1px solid var(--bordure);
}

header.entete .marque {
  font-weight: 600;
  font-size: 1.1rem;
  letter-spacing: 0.02em;
}

header.entete nav a {
  margin-right: 1.2rem;
  color: var(--texte);
  font-weight: 500;
}

header.entete .utilisateur {
  font-size: 0.9rem;
  color: var(--texte-discret);
  display: flex;
  align-items: center;
  gap: 0.8rem;
}

.bouton-recherche-globale {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* --- Recherche globale universelle (ADR-0061) --- */
.feuille-recherche-globale #resultats-recherche-globale {
  margin-top: 0.8rem;
  overflow-y: auto;
}
.message-recherche-globale {
  color: var(--texte-discret);
  font-size: 0.9rem;
  padding: 0.6rem 0.2rem;
}
.groupe-recherche-globale { margin-bottom: 0.4rem; }
.resultat-recherche-globale {
  display: flex;
  flex-direction: column;
  padding: 0.7rem 0.3rem;
  border-bottom: 1px solid var(--bordure);
  color: var(--texte);
  min-height: 44px;
  justify-content: center;
}
.resultat-recherche-globale:active { background: var(--surface-2, #f7f3ec); }
.resultat-titre { font-weight: 600; }
.resultat-sous-titre { font-size: 0.82rem; color: var(--texte-discret); }

main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 1.5rem;
}

/* --- Navigation mobile : barre d'onglets fixe en bas + feuille "Plus" ---
   Desktop (>900px) : nav horizontale classique dans le header, comme
   avant. La barre d'onglets et la feuille "Plus" sont totalement
   invisibles/inactives au-dessus de 900px — jamais les deux systèmes de
   navigation affichés en même temps. */
.barre-onglets { display: none; }
.fond-feuille { display: none; }
.feuille-plus { display: none; }

/* ── LA MARGE HAUTE, PAR SÉCURITÉ ────────────────────────────────────────
   La barre d'état est repassée en « default » (voir base.html) : le contenu
   ne devrait plus jamais passer dessous. Cette marge ne coûte rien — elle
   vaut 0 quand iOS ne réserve rien — et protège les cas de bord : paysage,
   encoche latérale, ou retour d'un futur « viewport-fit=cover ». */
body { padding-top: env(safe-area-inset-top, 0); }

@media (max-width: 900px) {
  header.entete { display: none; }

  .barre-onglets {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    background: var(--surface);
    border-top: 1px solid var(--bordure);
    padding-bottom: env(safe-area-inset-bottom, 0);
    box-shadow: 0 -1px 8px rgba(0,0,0,0.05);
  }
  .barre-onglets .onglet {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    padding: 0.5rem 0.2rem 0.45rem;
    border: none;
    background: transparent;
    color: var(--texte-discret);
    font-size: 0.68rem;
    font-weight: 500;
    min-height: 52px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .barre-onglets .onglet svg { width: 24px; height: 24px; }
  .barre-onglets .onglet.actif { color: var(--accent-fonce); }
  .barre-onglets .onglet:active { opacity: 0.55; }

  .fond-feuille {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(20,16,10,0.32);
    z-index: 41;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }
  body.feuille-ouverte .fond-feuille { opacity: 1; pointer-events: auto; }
  body.feuille-ouverte { overflow: hidden; }

  .feuille-plus {
    display: flex;
    flex-direction: column;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 42;
    background: var(--surface);
    border-radius: 18px 18px 0 0;
    padding: 0.6rem 1.2rem calc(1.2rem + env(safe-area-inset-bottom, 0));
    box-shadow: 0 -6px 24px rgba(0,0,0,0.18);
    max-height: 80vh;
    overflow-y: auto;
    transform: translateY(100%);
    transition: transform 0.26s cubic-bezier(0.32, 0.72, 0, 1);
  }
  .feuille-plus.ouverte { transform: translateY(0); }

  .poignee-feuille {
    width: 36px;
    height: 5px;
    border-radius: 3px;
    background: var(--bordure);
    margin: 0.3rem auto 0.9rem;
  }

  .feuille-plus a {
    padding: 0.9rem 0.2rem;
    border-bottom: 1px solid var(--bordure);
    color: var(--texte);
    font-weight: 500;
    min-height: 44px;
    display: flex;
    align-items: center;
  }
  .feuille-plus a:active { background: #f7f3ec; }

  /* Regroupement "Documents" / "Gestion" (audit navigation, 2026-08-04)
     — un simple intertitre, pas de nouveau composant, pour que la liste
     plate de 13 liens redevienne repérable en un coup d'œil. */
  .titre-groupe-feuille {
    padding: 0.8rem 0.2rem 0.3rem;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--texte-discret);
    font-weight: 600;
  }
  .titre-groupe-feuille:first-of-type { padding-top: 0.2rem; }

  .tiroir-utilisateur {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.8rem;
    padding-bottom: 0.9rem;
    margin-bottom: 0.3rem;
    border-bottom: 1px solid var(--bordure);
    color: var(--texte-discret);
    font-size: 0.9rem;
  }
  .tiroir-utilisateur span { font-weight: 600; color: var(--texte); }

  main { padding: 1rem 1rem calc(4.5rem + env(safe-area-inset-bottom, 0)); }

  /* Cibles tactiles confortables (44pt, recommandation Apple HIG) sur
     tout élément cliquable qui n'avait pas déjà cette garantie. */
  button, .bouton, .filtre-statut, select,
  input[type="text"], input[type="email"], input[type="password"] {
    min-height: 44px;
  }
  .filtre-statut { padding: 0.55rem 1rem; }
}

/* --- Feuille générique (bottom sheet), réutilisable partout ---
   Contrairement à `.feuille-plus` (menu "Plus", mobile uniquement), ce
   composant fonctionne à toutes les largeurs — utile pour une action
   ponctuelle (ex. création rapide d'article) accessible aussi bien sur
   iPhone que sur desktop. Toujours accompagné de son propre fond dédié
   (jamais celui du menu "Plus", pour éviter toute interférence entre
   deux feuilles indépendantes). */
.fond-feuille-generique {
  position: fixed;
  inset: 0;
  background: rgba(20,16,10,0.32);
  z-index: 50;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.fond-feuille-generique.ouvert { opacity: 1; pointer-events: auto; }

.feuille-generique {
  display: flex;
  flex-direction: column;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 51;
  background: var(--surface);
  border-radius: 18px 18px 0 0;
  padding: 0.6rem 1.2rem calc(1.2rem + env(safe-area-inset-bottom, 0));
  box-shadow: 0 -6px 24px rgba(0,0,0,0.18);
  max-height: 85vh;
  overflow-y: auto;
  transform: translateY(100%);
  transition: transform 0.26s cubic-bezier(0.32, 0.72, 0, 1);
}
.feuille-generique.ouvert { transform: translateY(0); }
@media (min-width: 600px) {
  /* Sur un écran assez large, une feuille plein-largeur collée en bas
     perd son sens (convention mobile) — centrée façon boîte de dialogue. */
  .feuille-generique {
    left: 50%;
    right: auto;
    bottom: 6vh;
    width: min(480px, 92vw);
    max-height: 88vh;
    border-radius: var(--rayon);
    transform: translate(-50%, 40px);
    opacity: 0;
    transition: transform 0.22s ease, opacity 0.22s ease;
  }
  .feuille-generique.ouvert { transform: translate(-50%, 0); opacity: 1; }
}
.feuille-generique h2 { margin-top: 0.3rem; }
.feuille-generique .champ { margin-bottom: 0.9rem; }
.feuille-generique .actions-feuille { display: flex; gap: 0.6rem; margin-top: 0.6rem; flex-wrap: wrap; }
.feuille-generique .actions-feuille button { flex: 1; min-width: 140px; }

/* --- Ligne d'article "carte", mobile-first (ADR-0052) ---
   Remplace le tableau horizontal pour les documents commerciaux : une
   ligne compacte (photo/référence/désignation/qté/prix/total visibles
   immédiatement), tout le reste (poids/métal/pierres/certificat/remise)
   s'ouvre dans une feuille du bas au tap — jamais un tableau qui déborde
   sur iPhone (client, 2026-07-30 : "je préfère une excellente expérience
   sur iPhone plutôt qu'une interface pensée d'abord pour PC"). */
.liste-lignes-document { display: flex; flex-direction: column; gap: 0.6rem; margin: 1rem 0; }
.ligne-carte {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.8rem;
  padding: 0.7rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  cursor: pointer;
  min-height: 44px;
  text-align: left;
  width: 100%;
}
/* ⚠️ `.ligne-carte` est un <button>, et un bouton N'HÉRITE PAS la couleur
   du texte de la page : il prend celle du système. La désignation s'affichait
   (elle a une couleur explicite) mais la RÉFÉRENCE devenait illisible —
   Emmanuel, 28/09/2026 : « il faut que j'aille dessus avec la souris pour me
   rendre compte de la référence ». Une ligne de bon dont on ne lit pas la
   référence ne sert à rien. */
.ligne-carte { color: var(--texte); }
.ligne-carte:active { background: #f7f3ec; }
.ligne-carte .origine-prix-ligne {
  font-size: 0.75rem; color: var(--texte-discret);
  border: 1px solid var(--bordure); border-radius: 999px;
  padding: 0 0.4rem; margin-left: 0.4rem; white-space: nowrap;
}
.ligne-carte .conteneur-photo-ligne {
  width: 48px; height: 48px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: #efe9df; border-radius: 6px; overflow: hidden;
}
.ligne-carte .conteneur-photo-ligne.sans-photo svg { width: 24px; height: 24px; opacity: 0.5; }
.ligne-carte .photo-ligne { width: 100%; height: 100%; object-fit: contain; }
.ligne-carte .photo-ligne-vide { width: 100%; height: 100%; }
.ligne-carte .corps-ligne { flex: 1; min-width: 0; overflow: hidden; }
.ligne-carte .reference-ligne { font-weight: 600; overflow-wrap: anywhere; }
.ligne-carte .designation-ligne { color: var(--texte-discret); font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Barre d'actions d'une pièce confiée (Rendu/Perdu/Vendre) — toujours sur
   sa propre ligne pleine largeur, jamais coincée à côté de la référence,
   pour ne jamais pouvoir se superposer au texte sur mobile (bug iPhone
   signalé le 2026-08-02). */
.actions-ligne-carte {
  flex: 1 1 100%;
  display: flex;
  gap: 0.5rem;
  margin-top: 0.4rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--bordure);
}
.actions-ligne-carte button { flex: 1; }
.ligne-carte .qte-prix-ligne { font-size: 0.85rem; color: var(--texte-discret); }
.ligne-carte .total-ligne { font-weight: 600; text-align: right; flex-shrink: 0; padding-left: 0.4rem; }
.ligne-carte .remise-ligne-tag { display: block; font-size: 0.75rem; color: var(--accent-fonce); font-weight: 500; }
.ligne-carte .chevron-ligne { color: var(--texte-discret); flex-shrink: 0; }

.feuille-ligne .groupe-pierre { display: flex; gap: 0.4rem; align-items: flex-end; margin-bottom: 0.6rem; }
.feuille-ligne .groupe-pierre .champ { flex: 1; min-width: 0; margin-bottom: 0; }
.feuille-ligne .groupe-pierre .champ input { width: 100%; box-sizing: border-box; }
.feuille-ligne .groupe-pierre .champ-carats { flex: 0 0 62px; }
.feuille-ligne .bouton-retirer-pierre { flex-shrink: 0; width: 36px; min-height: 36px; padding: 0; color: var(--danger); border-color: var(--danger); }
.feuille-ligne .separateur-section { border: none; border-top: 1px solid var(--bordure); margin: 1rem 0; }
.feuille-ligne .titre-section { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--texte-discret); margin-bottom: 0.6rem; }

.barre-recherche {
  display: flex;
  gap: 0.6rem;
  margin-bottom: 1.2rem;
  flex-wrap: wrap;
}

input[type="text"], input[type="password"], input[type="email"], input[type="number"], select {
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  font-size: 0.95rem;
  background: var(--surface);
  color: var(--texte);
}

input[type="text"]:focus, select:focus, input[type="password"]:focus, input[type="number"]:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* iPhone — anti-zoom : Safari iOS zoome AUTOMATIQUEMENT la page au focus de
   tout contrôle de saisie dont la police fait moins de 16px (les inputs de
   base sont à 0.95rem ≈ 15.2px, les textarea plus petits encore). On force
   16px sous 720px. Sélecteurs typés pour égaler la spécificité de la règle
   de base ci-dessus (0,1,1) — un simple `input` (0,0,1) perdrait la cascade
   malgré l'ordre source. Mesuré réellement sur la fiche client à 375px
   (2026-08-05) : tous les champs déclenchaient le zoom. Correctif transverse,
   bénéficie à tous les écrans (catalogue, documents, fournisseurs, clients). */
@media (max-width: 720px) {
  input[type="text"], input[type="password"], input[type="email"],
  input[type="number"], input[type="tel"], input[type="date"],
  input[type="search"], select, textarea { font-size: 16px; }
}

/* Un champ dans un `.champ` (formulaire vertical, feuilles génériques)
   remplit toujours toute la largeur disponible — sans cette règle, un
   input[type=number] garde sa largeur navigateur par défaut (~170px) et
   déborde silencieusement d'un conteneur flex plus étroit sur iPhone
   (trouvé en testant réellement la feuille d'édition de ligne, ADR-0052).
   Un style inline explicite (width=...) reste toujours prioritaire. */
.champ input, .champ select, .champ textarea { width: 100%; box-sizing: border-box; }

.recherche-principale { flex: 1; min-width: 200px; }

/* Bandeau d'environnement (ADR-0067) — bande fine, toujours visible en haut de
   chaque page, pour ne jamais confondre la démonstration avec la production.
   Texte blanc sur fond coloré : lisible en thème clair comme sombre. */
.bandeau-env {
  text-align: center;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.22rem 0.6rem;
  line-height: 1.3;
  color: #fff;
}
.bandeau-env-production { background: #1f7a4d; }     /* vert sobre */
.bandeau-env-demonstration { background: #c9741c; }  /* orange d'avertissement */
.bandeau-env-developpement { background: #64748b; }  /* gris neutre */
.bandeau-env-test { background: #7c3aed; }           /* violet — tests automatisés */


/* Marque « document d'essai » (2026-08-08) — un document d'apprentissage ne
   doit jamais être confondu avec un vrai document commercial/comptable, même
   en production. Rouge franc, comme le bandeau du PDF. */
.badge-essai {
  background: #b3261e;
  color: #fff;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* PILOTE : une vraie opération, hors du registre officiel (2026-09-10).
   Volontairement PAS rouge — le rouge de l'essai dit « ceci n'a pas eu lieu »,
   et ce serait faux ici. L'ocre situe sans dévaloriser. Le contraste sur blanc
   est de 5,4:1, au-dessus du seuil AA. */
.badge-pilote {
  background: #7a5a23;
  color: #fff;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* Bandeau d'alerte administrateur (ADR-0066 §5.3) — visible seulement quand une
   donnée de référence manque ; couleur selon la gravité. */
.bandeau-alerte-admin {
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
  font-weight: 500;
  text-align: center;
  color: #fff;
  background: #c9741c;
}
.bandeau-alerte-admin.grave { background: #b3261e; }
.bandeau-alerte-admin a { color: #fff; text-decoration: underline; }

/* --- Informations confidentielles (2026-08-09) ---
   Le déclencheur est volontairement DISCRET : un petit cadenas gris, sans
   libellé ni encadré. Devant un client, rien ne doit signaler qu'une partie de
   la fiche lui est cachée. Cible tactile de 44px malgré sa petite taille. */
.bouton-cadenas {
  background: transparent;
  border: none;
  color: var(--texte-discret);
  padding: 0.5rem;
  min-height: 44px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.45;
  cursor: pointer;
}
.bouton-cadenas:hover { background: transparent; opacity: 0.8; }
.bouton-cadenas.ouvert { opacity: 1; color: var(--danger); }

.panneau-confidentiel-contenu {
  margin-top: 0.4rem;
  border: 1px solid var(--danger);
  border-radius: var(--rayon);
  padding: 0.7rem 0.8rem;
  background: var(--surface);
}
.panneau-confidentiel-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--danger);
  margin-bottom: 0.5rem;
}
.compte-a-rebours { font-variant-numeric: tabular-nums; opacity: 0.75; }
.ligne-confidentielle {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--bordure);
  font-size: 0.9rem;
}
.ligne-confidentielle:last-of-type { border-bottom: none; }
/* Une valeur inconnue est dite telle — jamais estimée, jamais reconstituée. */
.valeur-inconnue { color: var(--texte-discret); font-weight: 400; font-style: italic; }

/* Badges d'état de la page de santé (ADR-0066 §5.3). */
.badge-sante-ok { background: #1f7a4d; color: #fff; }
.badge-sante-attention { background: #c9741c; color: #fff; }
.badge-sante-bloquant { background: #b3261e; color: #fff; }

button, .bouton {
  padding: 0.55rem 1.1rem;
  border-radius: var(--rayon);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  font-size: 0.95rem;
  cursor: pointer;
}

button.secondaire, .bouton.secondaire {
  background: transparent;
  color: var(--accent);
}

button:hover { background: var(--accent-fonce); border-color: var(--accent-fonce); }
/* Un bouton désactivé doit rester LISIBLE — il dit ce qu'on ne peut pas faire,
   pas rien. La règle précédente était :

       button:disabled { opacity: 0.4; background: var(--accent); border-color: var(--accent); }

   Elle reposait le FOND sans reposer la COULEUR. Deux conséquences mesurées le
   2026-08-28 :
   - bouton plein désactivé : blanc sur accent à 40 % d'opacité = 1,71:1 ;
   - bouton `.secondaire` désactivé : le fond devenait accent alors que le
     texte RESTAIT accent — 1,00:1, c'est-à-dire invisible. C'est ce qui
     effaçait « ← Précédent » et « Suivant → », et les flèches d'ordre des
     vocabulaires.

   On ne signale plus l'indisponibilité en effaçant le texte, mais par un fond
   neutre et un trait discret. #5c564c sur #efece7 = 6,2:1. */
button:disabled, .bouton:disabled,
button.secondaire:disabled, .bouton.secondaire:disabled {
  opacity: 1;
  cursor: default;
  background: #efece7;
  border-color: #cfc7ba;
  color: #5c564c;
}

.bloc-actions-document {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.bloc-actions-document button {
  min-height: 44px; /* cible tactile confortable sur iPhone (recommandation Apple HIG) */
}

.grille-catalogue {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1.2rem;
}

.carte-bijou {
  background: var(--surface);
  border-radius: var(--rayon);
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0,0,0,0.07);
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  position: relative;
}
.carte-bijou:hover { transform: translateY(-3px); box-shadow: 0 6px 14px rgba(0,0,0,0.1); }

.carte-bijou .case-selection {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  z-index: 2;
  width: 26px;
  height: 26px;
  background: rgba(255,255,255,0.9);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
  cursor: pointer;
}
.carte-bijou .case-selection input { width: 16px; height: 16px; margin: 0; cursor: pointer; }

.carte-bijou .image-conteneur {
  aspect-ratio: 1 / 1;
  background: #efe9df;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.carte-bijou .image-conteneur img { width: 100%; height: 100%; object-fit: contain; display: block; }
.carte-bijou .sans-photo { color: var(--texte-discret); font-size: 0.8rem; text-align: center; padding: 0 1rem; }

.carte-bijou .infos { padding: 0.7rem 0.9rem; }
.carte-bijou .reference { font-weight: 600; font-size: 0.98rem; }
/* Nom lisible de l'article sur la carte catalogue (2026-08-08) — « Bague
   solitaire diamant 0,30 ct » parle bien plus qu'une référence seule. Tronqué
   sur une ligne pour ne jamais déformer la grille. */
.carte-bijou .designation-carte {
  font-size: 0.85rem; color: var(--texte); margin-bottom: 0.15rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.carte-bijou .categorie { font-size: 0.8rem; color: var(--texte-discret); margin-bottom: 0.4rem; }
.carte-bijou .details-commerciaux { font-size: 0.78rem; color: var(--texte-discret); margin-bottom: 0.4rem; }
/* La vitrine se lit d'un coup d'œil sur la carte : c'est elle qui dit où
   aller chercher le bijou. Assez marquée pour ne pas se noyer dans les
   détails commerciaux, assez discrète pour ne pas voler la référence. */
.carte-bijou .presence-carte {
  font-size: 0.78rem; font-weight: 600; color: var(--texte); margin-bottom: 0.4rem;
}
/* Le prix que la vendeuse annonce au client : c'est l'information qu'on
   cherche du regard, elle doit se détacher du reste de la carte. */
.carte-bijou .prix-carte {
  font-size: 0.92rem; font-weight: 700; color: var(--texte); margin-bottom: 0.4rem;
}

@media (max-width: 900px) {
  /* Grille catalogue plus dense sur mobile : 2 colonnes façon galerie
     photo plutôt qu'une seule colonne de grandes cartes. */
  .grille-catalogue { grid-template-columns: repeat(2, 1fr); gap: 0.7rem; }
  .carte-bijou .infos { padding: 0.55rem 0.6rem; }
  .carte-bijou .reference { font-size: 0.88rem; }

  /* Grille "simple" (photos non classées) : chaque carte contient un
     champ de recherche + résultats, trop à l'étroit sur 2 colonnes —
     reste sur une seule colonne, plus large. */
  .grille-catalogue.grille-simple { grid-template-columns: 1fr; }
}

.icone-photo { width: 34px; height: 34px; opacity: 0.35; }

table.catalogue {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border-radius: var(--rayon);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}

table.catalogue th {
  text-align: left;
  padding: 0.7rem 1rem;
  background: #f3efe8;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  /* CIBLÉ, et pas `--texte-discret` : cette variable sert 65 fois dans cette
     feuille et dans une trentaine de gabarits. La toucher pour un en-tête de
     tableau changerait l'aspect de toute l'application.
     #7a7165 sur ce fond #f3efe8 ne donnait que 4,19:1 ; #5f584d donne 6,13:1
     tout en restant nettement plus clair que le texte courant (13:1). */
  color: #5f584d;
}

table.catalogue td {
  padding: 0.7rem 1rem;
  border-top: 1px solid var(--bordure);
}

table.catalogue tr.ligne-bijou { cursor: pointer; }
table.catalogue tr.ligne-bijou:hover { background: #f7f3ec; }

/* --- Tableaux -> cartes sur mobile ---
   En dessous de 720px, chaque <tr> de table.catalogue devient une carte
   empilée et chaque <td> une ligne "libellé : valeur" (le libellé vient
   de l'attribut data-label posé sur le <td>, jamais du texte du <th> —
   ça reste correct même si les colonnes changent d'ordre). Le <thead>
   est masqué car les libellés sont désormais portés par chaque cellule.
   Bien plus lisible qu'un défilement horizontal sur un écran étroit. */
@media (max-width: 720px) {
  table.catalogue { box-shadow: none; background: transparent; }
  table.catalogue thead { display: none; }
  table.catalogue, table.catalogue tbody, table.catalogue tr, table.catalogue td {
    display: block;
    width: 100%;
  }
  table.catalogue tr {
    background: var(--surface);
    border-radius: var(--rayon);
    box-shadow: 0 1px 3px rgba(0,0,0,0.07);
    margin-bottom: 0.7rem;
    padding: 0.3rem 0;
    overflow: hidden;
  }
  table.catalogue td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.55rem 0.9rem;
    border-top: none;
    border-bottom: 1px solid var(--bordure);
    text-align: right;
  }
  table.catalogue tr td:last-child { border-bottom: none; }
  table.catalogue td[data-label]::before {
    content: attr(data-label);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    /* L'en-tête du téléphone : sous 720 px le <thead> disparaît et c'est CE
       libellé qui le remplace. Il doit donc suivre la même exigence — d'autant
       qu'il est plus petit (0,72rem). #5f584d sur la surface blanche : 7,0:1. */
    color: #5f584d;
    text-align: left;
    flex-shrink: 0;
  }
  /* Une cellule sans data-label (icône seule, case à cocher) prend toute
     la largeur sans le libellé fantôme d'une cellule vide. */
  table.catalogue td:not([data-label]) { justify-content: center; }
}

/* --- Liste de DOCUMENTS (Devis, BC, BL, Factures, Avoirs, Confié, Retour) ---
   Présentation partagée, scopée `.doc-table` pour ne toucher à aucun autre
   tableau `.catalogue`. Sur iPhone, chaque document devient une carte COMPACTE
   et scannable — N° + état sur la 1re ligne, client, puis date · lignes · total —
   au lieu de six lignes empilées qui ne laissaient voir qu'un document à la fois.
   Le fond/bordure de carte et les badges d'état sont ceux, inchangés, de la
   présentation générale. */
@media (max-width: 720px) {
  table.catalogue.doc-table tr {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.15rem 0.7rem;
    align-items: baseline;
    padding: 0.8rem 0.95rem;
  }
  table.catalogue.doc-table td {
    display: block;
    padding: 0;
    border: none;
    text-align: left;
  }
  table.catalogue.doc-table td::before { display: none !important; }
  table.catalogue.doc-table td[data-label="N°"]     { grid-column: 1; grid-row: 1; font-size: 1.02rem; font-weight: 700; color: var(--texte); }
  table.catalogue.doc-table td[data-label="Statut"] { grid-column: 2; grid-row: 1; justify-self: end; }
  table.catalogue.doc-table td[data-label="Client"] { grid-column: 1; grid-row: 2; color: var(--texte); }
  table.catalogue.doc-table td[data-label="Total"]  { grid-column: 2; grid-row: 2; justify-self: end; font-weight: 600; color: var(--texte); }
  table.catalogue.doc-table td[data-label="Date"]   { grid-column: 1; grid-row: 3; color: var(--texte-discret); font-size: 0.88rem; }
  table.catalogue.doc-table td[data-label="Lignes"] { grid-column: 2; grid-row: 3; justify-self: end; color: var(--texte-discret); font-size: 0.88rem; }
  table.catalogue.doc-table td[data-label="Lignes"]::after { content: " lignes"; }
}

/* --- Liste CLIENTS : même motif compact que les documents sur iPhone ---
   Scopé `.cli-table` : chaque client devient une carte lisible (nom + type,
   e-mail, téléphone) au lieu de cinq lignes empilées. L'avatar d'initiales,
   utile sur grand écran, est masqué en compact pour laisser voir plus de
   clients d'un coup d'œil. Aucun autre tableau `.catalogue` n'est touché. */
@media (max-width: 720px) {
  table.catalogue.cli-table tr {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.12rem 0.7rem;
    align-items: baseline;
    padding: 0.8rem 0.95rem;
  }
  table.catalogue.cli-table td { display: block; padding: 0; border: none; text-align: left; }
  table.catalogue.cli-table td::before { display: none !important; }
  table.catalogue.cli-table td:first-child { display: none; }  /* initiales : masquées en compact */
  table.catalogue.cli-table td[data-label="Nom"]       { grid-column: 1; grid-row: 1; font-size: 1.02rem; font-weight: 700; color: var(--texte); }
  table.catalogue.cli-table td[data-label="Type"]      { grid-column: 2; grid-row: 1; justify-self: end; color: var(--texte-discret); font-size: 0.85rem; }
  table.catalogue.cli-table td[data-label="E-mail"]    { grid-column: 1 / -1; grid-row: 2; color: var(--texte-discret); font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; }
  table.catalogue.cli-table td[data-label="Téléphone"] { grid-column: 1 / -1; grid-row: 3; color: var(--texte); font-size: 0.92rem; }
}

/* --- Liste FOURNISSEURS : même motif compact que les clients sur iPhone ---
   Scopé `.fou-table` : chaque fournisseur devient une carte lisible (nom en
   avant, catégorie à droite, contact et lien de site en dessous) au lieu de
   cinq lignes empilées. L'avatar d'initiales, utile sur grand écran, est masqué
   en compact. Aucun autre tableau `.catalogue` n'est touché. */
@media (max-width: 720px) {
  table.catalogue.fou-table tr {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.12rem 0.7rem;
    align-items: baseline;
    padding: 0.8rem 0.95rem;
  }
  table.catalogue.fou-table td { display: block; padding: 0; border: none; text-align: left; }
  table.catalogue.fou-table td::before { display: none !important; }
  table.catalogue.fou-table td:first-child { display: none; }  /* initiales : masquées en compact */
  table.catalogue.fou-table td[data-label="Nom"]       { grid-column: 1; grid-row: 1; font-size: 1.02rem; font-weight: 700; color: var(--texte); }
  table.catalogue.fou-table td[data-label="Catégorie"] { grid-column: 2; grid-row: 1; justify-self: end; color: var(--texte-discret); font-size: 0.85rem; }
  table.catalogue.fou-table td[data-label="Contact"]   { grid-column: 1 / -1; grid-row: 2; color: var(--texte); font-size: 0.92rem; }
  table.catalogue.fou-table td[data-label="Site"]      { grid-column: 1 / -1; grid-row: 3; color: var(--texte-discret); font-size: 0.9rem; }
}

/* --- Liste SIGNALEMENTS : même motif compact que les clients sur iPhone ---
   Scopé `.sig-table` : chaque signalement devient une carte lisible (titre en
   avant, type à droite, statut sur sa propre ligne pour rester manipulable —
   c'est un menu déroulant pour qui gère les signalements —, auteur et date en
   dessous) au lieu de cinq lignes empilées. Aucun autre tableau `.catalogue`
   n'est touché. */
@media (max-width: 720px) {
  table.catalogue.sig-table tr {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.2rem 0.7rem;
    align-items: baseline;
    padding: 0.8rem 0.95rem;
  }
  table.catalogue.sig-table td { display: block; padding: 0; border: none; text-align: left; }
  table.catalogue.sig-table td::before { display: none !important; }
  table.catalogue.sig-table td[data-label="Titre"]  { grid-column: 1; grid-row: 1; font-size: 1.02rem; font-weight: 700; color: var(--texte); }
  table.catalogue.sig-table td[data-label="Type"]   { grid-column: 2; grid-row: 1; justify-self: end; color: var(--texte-discret); font-size: 0.85rem; }
  table.catalogue.sig-table td[data-label="Statut"] { grid-column: 1 / -1; grid-row: 2; }
  table.catalogue.sig-table td[data-label="Auteur"] { grid-column: 1; grid-row: 3; color: var(--texte-discret); font-size: 0.88rem; }
  table.catalogue.sig-table td[data-label="Date"]   { grid-column: 2; grid-row: 3; justify-self: end; color: var(--texte-discret); font-size: 0.88rem; }
}

.badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.78rem;
  background: #ece5d8;
  color: var(--texte);
}
.badge.en_stock { background: #e2efe4; color: #2e6b3e; }
.badge.reserve { background: #f5e9cf; color: #8a6416; }
.badge.vendu { background: #eee; color: #777; }
.badge.occasion { background: #e6ecf5; color: #3b5a8a; }
.badge.archive { background: #eee; color: #999; }

/* Création rapide de fiche client depuis photo/PDF/SIREN (ADR-0057) —
   confiance par champ, jamais de couleur "vendu/reserve" détournée. */
.badge.certain { background: #e2efe4; color: #2e6b3e; }
.badge.incertain { background: #f5e9cf; color: #8a6416; }
.badge.absent { background: #eee; color: #999; }

.bouton-import-client {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.9rem 1rem;
  margin-bottom: 0.7rem;
  font-size: 1rem;
  font-weight: 600;
  background: var(--accent-fonce);
  color: #fff;
  border: none;
  border-radius: 12px;
}

.options-capture { display: flex; flex-direction: column; gap: 0.6rem; }
.options-capture button {
  width: 100%;
  padding: 0.85rem;
  text-align: left;
}
.separateur-ou {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--texte-discret);
  font-size: 0.85rem;
  margin: 0.4rem 0;
}
.separateur-ou::before, .separateur-ou::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--bordure);
}

.champ-import { margin-bottom: 0.9rem; }
.champ-import label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.25rem;
}

.carte-doublon {
  border: 1px solid #e0b34d;
  background: #fdf6e6;
  border-radius: 10px;
  padding: 0.9rem;
  margin-bottom: 1rem;
}
.carte-doublon.certain { border-color: #c0392b; background: #fbeae7; }
.carte-doublon h3 { margin: 0 0 0.4rem; font-size: 0.95rem; }
.carte-doublon .actions-feuille { margin-top: 0.6rem; }

.source-import {
  font-size: 0.85rem;
  color: var(--texte-discret);
  margin-bottom: 0.8rem;
}

.bouton.actif, button.actif { background: var(--accent-fonce); border-color: var(--accent-fonce); color: #fff; }

.barre-selection {
  position: sticky;
  bottom: 0;
  margin-top: 1.2rem;
  padding: 0.8rem 1rem;
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  box-shadow: 0 -2px 10px rgba(0,0,0,0.08);
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
}
.barre-selection #compte-selection { font-weight: 600; margin-right: auto; }
@media (max-width: 900px) {
  /* La barre de sélection colle au bas du VIEWPORT (position:sticky),
     mais sur mobile ce bas est déjà occupé par la barre d'onglets fixe
     — sans ce décalage, la barre de sélection se cachait derrière elle. */
  .barre-selection { bottom: calc(56px + env(safe-area-inset-bottom, 0)); }

  /* Tant qu'aucun bijou n'est sélectionné, réduire la barre à une simple
     ligne discrète (2026-07-29, retour iPhone réel) : la priorité de
     l'écran doit rester aux photos, pas à cette barre. Les boutons
     "Sélectionner..." restent cliquables, juste présentés en texte fin
     plutôt qu'en gros boutons — jamais besoin de cocher une fiche à la
     main pour les faire apparaître (exigence du 2026-07-22, toujours
     valable). Dès qu'une sélection existe, la barre reprend sa taille
     normale (compte, Vider, Créer le PDF ont besoin de place). */
  .barre-selection.vide {
    padding: 0.45rem 0.9rem;
    gap: 0.5rem;
    box-shadow: 0 -1px 4px rgba(0,0,0,0.05);
  }
  .barre-selection.vide #compte-selection { display: none; }
  .barre-selection.vide button,
  .barre-selection.vide a {
    min-height: auto;
    padding: 0.2rem 0;
    border: none;
    background: transparent;
    color: var(--texte-discret);
    font-size: 0.78rem;
    text-decoration: underline;
  }
}

/* Barre de sélection PDF « repliée » (iPhone) : tant que rien n'est sélectionné,
   on ne montre qu'une seule puce discrète « Créer un catalogue PDF ». Un tap la
   déplie (voir catalogue.html) et révèle « Sélectionner cette page / tous », donc
   sans jamais devoir cocher une fiche (exigence 2026-07-22). Sur PC, la puce
   reste masquée et la barre entière (la règle de masquage est sous média mobile). */
.cat-selection-chip { display: none; }
@media (max-width: 900px) {
  .barre-selection.repliee { justify-content: flex-start; }
  .barre-selection.repliee > :not(.cat-selection-chip) { display: none !important; }
  .barre-selection.repliee .cat-selection-chip {
    display: inline-block; min-height: auto; padding: 0.25rem 0;
    border: none; background: transparent; color: var(--texte-discret);
    font-size: 0.82rem; text-decoration: underline;
  }
}

.pagination { margin-top: 1.2rem; display: flex; gap: 0.35rem; align-items: center; flex-wrap: wrap; }
.pagination button.page {
  min-width: 36px;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--bordure);
  background: var(--surface);
  color: var(--texte);
}
.pagination button.page.actuelle { background: var(--accent); color: #fff; border-color: var(--accent); }
.pagination button.page:disabled { opacity: 0.4; cursor: default; }
.pagination .points { color: var(--texte-discret); padding: 0 0.2rem; }
.pagination .info-total { margin-left: 0.6rem; font-size: 0.85rem; color: var(--texte-discret); }

.fiche {
  background: var(--surface);
  border-radius: var(--rayon);
  padding: 1.5rem;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}

.fiche h1 { margin-top: 0; font-size: 1.4rem; }

.fiche-layout {
  display: grid;
  grid-template-columns: 380px 1fr;
  gap: 2rem;
}
@media (max-width: 760px) {
  .fiche-layout { grid-template-columns: 1fr; }
}

.galerie .image-principale {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #efe9df;
  border-radius: var(--rayon);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.galerie .image-principale img { width: 100%; height: 100%; object-fit: contain; cursor: zoom-in; }
.galerie .image-principale { position: relative; }

/* ── LA PHOTO EN GRAND (07/10/2026) ────────────────────────────────────────
   Avant, la photo partait dans un onglet du navigateur : aucune croix, et le
   retour ne ramenait pas au catalogue. Elle se superpose desormais a la page,
   qui reste dessous, intacte.

   Le z-index passe au-dessus de la barre de navigation (z-index 100 plus bas)
   et des feuilles laterales : une photo plein ecran ne doit rien laisser
   depasser, sans quoi on touche un onglet en croyant fermer l image. */
.visionneuse {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(10, 8, 6, 0.94);
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
}
.visionneuse[hidden] { display: none; }
.visionneuse img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 0.3rem;
}

/* ⚠️ LA CROIX, SOUS L ENCOCHE DE L IPHONE.
   `env(safe-area-inset-top)` vaut 0 tant que la page ne passe pas sous la
   barre d etat — c est le cas ici — et prend sa vraie valeur si cela change
   un jour. Les 0.75rem fixes suffisent donc aujourd hui, et la somme reste
   juste demain : on ne calcule pas sur une hypothese.

   44px de cote : la taille minimale qu Apple donne pour qu une cible se
   touche sans viser. Un bouton de 24px se rate une fois sur trois. */
.visionneuse-fermer {
  position: absolute;
  top: calc(0.75rem + env(safe-area-inset-top, 0px));
  right: calc(0.75rem + env(safe-area-inset-right, 0px));
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem; line-height: 1;
  color: #fff; background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 50%;
  cursor: pointer; padding: 0;
  /* Le fond sombre de la visionneuse peut rencontrer une photo claire ou
     foncee : l ombre garde la croix lisible sur les deux. */
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
}
.visionneuse-fermer:hover,
.visionneuse-fermer:focus-visible {
  background: rgba(0, 0, 0, 0.8);
  outline: 2px solid #fff; outline-offset: 2px;
}
/* « Photo de vitrine » (17/09/2026) : la photo témoin du recensement,
   affichée faute de photo de catalogue. Carte du catalogue ET fiche. */
.mention-photo-vitrine {
  position: absolute; bottom: 0.4rem; left: 0.4rem; z-index: 2;
  background: rgba(40, 34, 26, 0.72); color: #fff;
  font-size: 0.7rem; line-height: 1.2; padding: 0.15rem 0.45rem;
  border-radius: 0.3rem; pointer-events: none; letter-spacing: 0.01em;
}
.galerie .image-principale .sans-photo { color: var(--texte-discret); text-align: center; padding: 1rem; }

.galerie .vignettes { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.6rem; }
.galerie .vignettes .vignette-conteneur {
  display: inline-block; cursor: pointer; border-radius: 4px; border: 2px solid transparent;
}
.galerie .vignettes img {
  width: 58px; height: 58px; object-fit: contain; background: #efe9df; border-radius: 4px;
  display: block; opacity: 0.85;
}
.galerie .vignettes .vignette-conteneur:hover img { opacity: 1; }
.galerie .vignettes .vignette-conteneur.selectionnee { border-color: var(--accent); }
.galerie .vignettes .vignette-conteneur.selectionnee img { opacity: 1; }
.galerie .vignettes .vignette-conteneur.masquee img { opacity: 0.35; filter: grayscale(1); }

#controles-photo-principale { margin-top: 0.6rem; display: flex; gap: 0.4rem; flex-wrap: wrap; }
#controles-photo-principale button, #controles-photo-principale label.bouton {
  padding: 0.3rem 0.6rem; font-size: 0.82rem;
}

.champs-fiche { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1rem; margin: 1.2rem 0; }
.champ label { display: block; font-size: 0.78rem; color: var(--texte-discret); text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 0.25rem; }
.champ .valeur { font-size: 1rem; }

.message { padding: 0.7rem 1rem; border-radius: var(--rayon); margin-bottom: 1rem; }
.message.erreur { background: #fbe9e9; color: var(--danger); }
.message.succes { background: #e6f2e8; color: #2e6b3e; }
/* Avertissement : ni une erreur (rien n'est cassé), ni un succès — un état
   dans lequel l'application fonctionne mais volontairement bridée. Le rouge
   de `.erreur` ferait croire à une panne. */
.message.avertissement { background: #fdf3e3; color: #8a5a12; border-left: 4px solid #c9741c; }

.page-connexion {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1.2rem;
}
.carte-connexion {
  background: var(--surface);
  padding: 2.2rem;
  border-radius: var(--rayon);
  box-shadow: 0 2px 10px rgba(0,0,0,0.06);
  width: 320px;
  max-width: 100%;
}
@media (max-width: 480px) {
  .carte-connexion { padding: 1.6rem 1.3rem; box-shadow: none; }
}
.carte-connexion h1 { margin-top: 0; font-size: 1.2rem; }
.carte-connexion .champ { margin-bottom: 1rem; display: flex; flex-direction: column; gap: 0.3rem; }
.carte-connexion button { width: 100%; }

.retour { display: inline-block; margin-bottom: 1rem; }

.grille-tuiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1rem;
}
.tuile {
  background: var(--surface);
  border-radius: var(--rayon);
  padding: 1.1rem 1.2rem;
  box-shadow: 0 1px 3px rgba(0,0,0,0.07);
}
.tuile-libelle { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--texte-discret); }
.tuile-valeur { font-size: 1.9rem; font-weight: 600; margin-top: 0.3rem; }
.tuile-sous-texte { font-size: 0.85rem; color: var(--texte-discret); margin-top: 0.3rem; }
.tuile-lien { display: block; cursor: pointer; transition: transform 0.12s ease, box-shadow 0.12s ease; }
.tuile-lien:hover { transform: translateY(-2px); box-shadow: 0 6px 14px rgba(0,0,0,0.1); text-decoration: none; }
.tuile-lien .tuile-libelle { color: var(--accent-fonce); font-size: 1rem; text-transform: none; letter-spacing: normal; font-weight: 600; }
.tuile-a-venir { opacity: 0.6; border: 1px dashed var(--bordure); box-shadow: none; }

.filtre-statut {
  display: inline-block; padding: 0.4rem 0.9rem; border-radius: 999px; border: 1px solid var(--bordure);
  cursor: pointer; font-size: 0.85rem; color: var(--texte-discret); background: var(--surface);
}
.filtre-statut.actif { background: var(--accent); border-color: var(--accent); color: #fff; }

.badge.statut-ouvert { background: #e6ecf5; color: #3b5a8a; }
.badge.statut-en_cours { background: #f5e9cf; color: #8a6416; }
.badge.statut-incomplet { background: #fbe9e9; color: var(--danger); }
.badge.statut-a_corriger { background: #fbe0d6; color: #a4521a; }
.badge.statut-valide { background: #ece3d3; color: #6b5329; }
.badge.statut-cloture { background: #e2efe4; color: #2e6b3e; }
.badge.statut-annule { background: #ececec; color: #6b6b6b; }
.badge.statut-brouillon { background: #e6ecf5; color: #3b5a8a; }
.badge.statut-confirme { background: #ece3d3; color: #6b5329; }
.badge.statut-partiellement_livre { background: #f5e9cf; color: #8a6416; }
.badge.statut-entierement_livre { background: #e2efe4; color: #2e6b3e; }
.badge.statut-validee { background: #ece3d3; color: #6b5329; }
.badge.statut-payee_partiellement { background: #f5e9cf; color: #8a6416; }
.badge.statut-payee { background: #e2efe4; color: #2e6b3e; }
.badge.statut-envoye { background: #e6ecf5; color: #3b5a8a; }
.badge.statut-accepte { background: #e2efe4; color: #2e6b3e; }
.badge.statut-refuse { background: #fbe9e9; color: var(--danger); }
.badge.statut-expire { background: #ececec; color: #6b6b6b; }

.suggestions {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 10;
  background: var(--surface); border: 1px solid var(--bordure); border-radius: var(--rayon);
  box-shadow: 0 4px 14px rgba(0,0,0,0.1); max-height: 260px; overflow-y: auto; margin-top: 0.2rem;
}
.suggestion { padding: 0.6rem 0.8rem; cursor: pointer; font-size: 0.9rem; border-bottom: 1px solid var(--bordure); }
.suggestion:last-child { border-bottom: none; }
.suggestion:hover { background: #f7f3ec; }

/* --- Champ Autocomplete : LE composant officiel de recherche/autocomplétion
   (champ-autocomplete.js). Réutilisé partout où une liste peut dépasser
   quelques dizaines d'éléments. Cible tactile 44pt, dropdown positionné,
   ligne « Créer » distincte. */
.champ-ac { position: relative; width: 100%; }
/* Boîte « champ » : ressemble à un input, contient chips (multi) + saisie. */
.champ-ac-controle {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem;
  min-height: 44px; padding: 0.25rem 0.4rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon); background: var(--surface);
  cursor: text;
}
.champ-ac-controle:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Saisie sans bordure propre (la boîte porte le style) — 16px = pas de zoom iOS au focus. */
.champ-ac-controle .champ-ac-input {
  flex: 1; width: auto; min-width: 6ch; border: none; background: transparent;
  padding: 0.3rem 0.2rem; font-size: 16px; outline: none; color: var(--texte);
}
.champ-ac-controle .champ-ac-input:focus { outline: none; }
.champ-ac-effacer {
  padding: 0 0.3rem; border: none; background: transparent; color: var(--texte-discret);
  font-size: 1.2rem; line-height: 1; cursor: pointer; min-height: auto; align-self: center;
}
.champ-ac-effacer:hover { background: transparent; color: var(--texte); }

/* Chips (sélection multiple). */
.champ-ac-chips { display: contents; }
.champ-ac-chip {
  display: inline-flex; align-items: center; gap: 0.3rem;
  background: var(--surface-2, #f3efe8); border: 1px solid var(--bordure);
  border-radius: 999px; padding: 0.15rem 0.2rem 0.15rem 0.5rem; font-size: 0.85rem; max-width: 100%;
}
.champ-ac-chip .champ-ac-texte { max-width: 12rem; }
.champ-ac-chip-x {
  padding: 0; border: none; background: transparent; color: var(--texte-discret);
  font-size: 1rem; line-height: 1; width: 1.4rem; height: 1.4rem; min-height: auto;
  border-radius: 50%; cursor: pointer;
}
.champ-ac-chip-x:hover { background: var(--bordure); color: var(--texte); }

/* Liste déroulante. */
.champ-ac-liste {
  position: absolute; top: calc(100% + 0.2rem); left: 0; right: 0; z-index: 60;
  margin: 0; padding: 0.25rem; list-style: none;
  background: var(--surface); border: 1px solid var(--bordure); border-radius: var(--rayon);
  box-shadow: 0 6px 18px rgba(0,0,0,0.12); max-height: 46vh; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.champ-ac-section {
  padding: 0.4rem 0.7rem 0.2rem; font-size: 0.7rem; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--texte-discret); font-weight: 600;
}
.champ-ac-option {
  display: flex; align-items: center; gap: 0.5rem; min-height: 44px;
  padding: 0.45rem 0.7rem; border-radius: 4px; cursor: pointer; font-size: 0.95rem;
  -webkit-tap-highlight-color: transparent;
}
.champ-ac-option.actif, .champ-ac-option:hover { background: #f7f3ec; }
.champ-ac-option.choisie { background: var(--bronze-tint, #f1e9db); }
.champ-ac-creer { color: var(--accent-fonce); font-weight: 600; border-top: 1px solid var(--bordure); }
.champ-ac-creer.actif, .champ-ac-creer:hover { background: var(--bronze-tint, #f1e9db); }
.champ-ac-vide { padding: 0.6rem 0.7rem; color: var(--texte-discret); font-size: 0.9rem; }

/* Ornements par élément : pastille couleur, icône, texte, favori, badge, coche. */
.champ-ac-pastille { flex-shrink: 0; width: 0.7rem; height: 0.7rem; border-radius: 50%; border: 1px solid rgba(0,0,0,0.1); }
.champ-ac-icone { flex-shrink: 0; font-size: 1.05rem; line-height: 1; }
.champ-ac-texte { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.champ-ac-etoile { color: #c8a13a; flex-shrink: 0; }
.champ-ac-badge {
  flex-shrink: 0; font-size: 0.72rem; background: var(--surface-2, #f3efe8);
  color: var(--texte-discret); border-radius: 999px; padding: 0.05rem 0.45rem;
}
.champ-ac-check { color: var(--accent-fonce); flex-shrink: 0; }

.champ-ac-message { min-height: 0; }
.champ-ac-message:empty { display: none; }
.champ-ac-charge { font-size: 0.8rem; color: var(--texte-discret); }
.champ-ac-erreur { font-size: 0.82rem; color: var(--danger); }

/* --- Inventaire des modules (tableau de bord) ---------------------------
   Point d'entrée : comprendre d'un coup d'œil où aller et ce qui est prêt.
   Conçu iPhone d'abord — une colonne pleine largeur, cible tactile large —
   puis élargi en plusieurs colonnes sur écran confortable. */
.intro-modules {
  color: var(--texte-discret);
  font-size: 0.88rem;
  margin: -0.4rem 0 0.9rem;
  max-width: 60ch;
}
.grille-modules {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.7rem;
}
.module {
  display: block;
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  padding: 0.95rem 1rem;
  color: inherit;
  min-height: 44px; /* cible tactile confortable au pouce */
}
a.module:active { background: var(--fond); }
.module-entete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}
.module-nom { font-weight: 600; font-size: 1.02rem; }
.module-description {
  color: var(--texte-discret);
  font-size: 0.87rem;
  margin-top: 0.25rem;
  line-height: 1.35;
}
.module-detail {
  color: var(--texte-discret);
  font-size: 0.82rem;
  margin-top: 0.35rem;
  font-style: italic;
}
.etiquette {
  flex-shrink: 0;
  /* Mesure au tableau de bord le 2026-08-16 : 0.74rem donnait 11,84 px, sous
     le seuil de lisibilite qu'on s'est fixe. Une etiquette d'etat qu'on doit
     approcher pour lire ne remplit pas son role. */
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.etiquette-pret { background: #eef3ea; color: #4a6b3a; }
.etiquette-a-remplir { background: #f6f1e6; color: var(--accent-fonce); }
.etiquette-indisponible { background: #f2efec; color: var(--texte-discret); }
/* Un module indisponible reste lisible mais visiblement non cliquable :
   mieux vaut l'annoncer qu'offrir un lien qui échouerait. */
.module-indisponible { opacity: 0.68; }

@media (min-width: 620px) {
  .grille-modules { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
}

/* Utilisateur sans aucun module attribué : on explique, on ne laisse jamais
   un écran vide sans mot d'explication (ADR-0073). */
.message-aucun-module {
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  padding: 1.3rem 1.2rem;
  max-width: 60ch;
}
.message-aucun-module p { color: var(--texte-discret); margin-bottom: 0; }
.aucun-module-feuille { color: var(--texte-discret); padding: 0.8rem 0; }

/* --- Écran « Qui a accès à quoi ? » (ADR-0073) -------------------------------
   Conçu pour être lu sans connaissance technique : des personnes et des
   modules, jamais des codes de permission. iPhone d'abord. */
.barre-onglets-simple { display: flex; gap: 0.4rem; margin: 0 0 1rem; flex-wrap: wrap; }
.onglet-simple {
  background: transparent;
  border: 1px solid var(--bordure);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  min-height: 44px;
  color: var(--texte-discret);
  cursor: pointer;
}
.onglet-simple.actif { background: var(--accent); border-color: var(--accent); color: #fff; }
.carte-acces {
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  padding: 0.9rem 1rem;
  margin-bottom: 0.7rem;
}
.carte-acces-inactive { opacity: 0.6; }
.carte-acces-entete { display: flex; align-items: baseline; justify-content: space-between; gap: 0.6rem; }
.carte-acces-nom { font-weight: 600; }
.carte-acces-sous { color: var(--texte-discret); font-size: 0.85rem; margin-top: 0.15rem; }
.carte-acces-modules { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.6rem; }
.jeton-module {
  background: #eef3ea; color: #4a6b3a;
  font-size: 0.78rem; padding: 0.15rem 0.55rem; border-radius: 999px;
}
.jeton-aucun { color: var(--texte-discret); font-size: 0.82rem; font-style: italic; }
.grille-cases-modules { display: grid; grid-template-columns: 1fr; gap: 0.2rem; margin-top: 0.7rem; }
.case-module {
  display: flex; align-items: center; gap: 0.55rem;
  min-height: 44px; /* cible tactile confortable */
  padding: 0.2rem 0.1rem;
  cursor: pointer;
}
.case-module input { width: 20px; height: 20px; flex-shrink: 0; }
.case-module-nom { font-size: 0.94rem; }
.case-module-verbes { color: var(--texte-discret); font-size: 0.76rem; margin-left: auto; text-align: right; }
.case-module-figee { cursor: default; opacity: 0.65; }
@media (min-width: 620px) {
  .grille-cases-modules { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
}

/* La barre du haut est désormais dessinée à partir du registre : elle peut
   compter dix-huit entrées quand tous les modules sont installés. Sans ces
   règles, elle poussait la page vers la droite au lieu de s'adapter.
   Elle revient d'elle-même sur une seule ligne pour une installation
   restreinte à quelques modules. */
header.entete nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  row-gap: 0.35rem;
  min-width: 0;
  flex: 1 1 auto;
  justify-content: center;
}
header.entete nav a.actif {
  color: var(--accent-fonce);
  text-decoration: underline;
  text-underline-offset: 4px;
}
header.entete { gap: 1rem; flex-wrap: wrap; }
header.entete .marque, header.entete .utilisateur { flex: 0 0 auto; }

/* ---------------------------------------------------------------------------
   Passeport article — suivi individuel
   
   Règle d'ergonomie qui gouverne ces blocs : on ne montre les trois quantités
   que lorsqu'elles DIFFÈRENT. Afficher « 10 / 0 / 10 » sur une référence dont
   aucun exemplaire n'est suivi n'apprend rien et encombre la fiche.
   --------------------------------------------------------------------------- */

.trio-quantites {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--bordure);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  overflow: hidden;
  margin-bottom: 0.7rem;
}
.trio-quantites > div { background: var(--surface); padding: 0.7rem 0.5rem; text-align: center; }
.trio-quantites .nombre {
  font-size: 1.6rem; font-weight: 600; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.trio-quantites .quoi {
  display: block; font-size: 0.72rem; color: var(--texte-discret);
  margin-top: 0.25rem; line-height: 1.25;
}
/* Le chiffre qui compte au comptoir : ce qu'on peut vendre. */
.trio-quantites .vendable .nombre { color: var(--accent-fonce); }
.trio-quantites .vendable.zero .nombre { color: var(--danger); }

/* La phrase qui explique l'écart. Les chiffres seuls laissent deviner ; une
   phrase ne se devine pas. */
.explication-quantites {
  font-size: 0.88rem; color: var(--texte-discret);
  margin: 0 0 0.7rem; line-height: 1.4;
}

.liste-exemplaires { list-style: none; padding: 0; margin: 0.5rem 0 0; }
.liste-exemplaires li { border-top: 1px solid var(--bordure); }
.liste-exemplaires li:first-child { border-top: none; }
/* Disposition en grille, et non en ligne flex.
 *
 * Constaté en mesurant la page à 375 px : la pastille de situation, qui ne se
 * coupe pas, s'octroyait 222 px sur 375 et laissait 90 px au NOM de l'objet,
 * qui se repliait alors sur cinq lignes. L'information secondaire écrasait
 * l'information principale.
 *
 * Sur écran étroit, la situation passe donc SOUS le nom, où elle dispose de
 * toute la largeur. Le chevron reste à droite, à cheval sur les deux lignes.
 */
.liste-exemplaires a {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "identite chevron" "situation chevron";
  align-items: center;
  gap: 0.3rem 0.6rem;
  padding: 0.75rem 0.2rem;      /* cible tactile confortable au pouce */
  text-decoration: none; color: var(--texte);
}
.liste-exemplaires .identite  { grid-area: identite; }
.liste-exemplaires .situation { grid-area: situation; display: flex;
                                align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.liste-exemplaires .chevron   { grid-area: chevron; }
.liste-exemplaires .depuis    { font-size: 0.78rem; color: var(--texte-discret); }

/* Dès qu'il y a de la place, tout revient sur une seule ligne : sur un
   ordinateur, empiler gaspillerait la largeur disponible. */
@media (min-width: 620px) {
  .liste-exemplaires a {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "identite situation chevron";
  }
}
.liste-exemplaires a:hover { background: var(--fond); }
.liste-exemplaires .identite { min-width: 0; }
.liste-exemplaires .identite strong { display: block; font-weight: 600; }
.liste-exemplaires .identite span {
  display: block; font-size: 0.8rem; color: var(--texte-discret);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.liste-exemplaires .chevron { color: var(--texte-discret); flex-shrink: 0; }

/* Un lien seul dans un bloc reste une cible tactile : sans hauteur minimale,
   il ne faisait que 18 px, soit moins de la moitie de ce qu'un pouce vise. */
/* Le bouton d'entree du suivi individuel : mesure a 37 px sur grand ecran,
   alors qu'une tablette de 1 024 px se manipule au doigt. La largeur de
   l'ecran ne dit rien du doigt qui s'en sert. */
#zone-suivi-individuel button { min-height: 44px; }

.lien-bloc {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 0.2rem 0;
  font-size: 0.9rem;
}

.pastille-situation {
  display: inline-block; padding: 0.2rem 0.6rem; border-radius: 999px;
  font-size: 0.78rem; font-weight: 600; white-space: nowrap;
}
.pastille-situation.libre { background: #e3f1e8; color: #1f5c3a; }
.pastille-situation.immobilise { background: #fdeee3; color: #8a4a1e; }
.pastille-situation.inconnu { background: #eee9e2; color: var(--texte-discret); }

/* --- Chronologie -------------------------------------------------------- */

.chronologie { list-style: none; padding: 0; margin: 0; }
.chronologie li {
  position: relative; padding: 0 0 1.1rem 1.5rem;
  border-left: 2px solid var(--bordure);
}
.chronologie li:last-child { border-left-color: transparent; padding-bottom: 0; }
.chronologie li::before {
  content: ""; position: absolute; left: -6px; top: 0.35rem;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--accent);
}
.chronologie li.immobilisant::before { border-color: #c9741c; }
.chronologie li.terminal::before { background: var(--texte); border-color: var(--texte); }
.chronologie .quand {
  display: block; font-size: 0.78rem; color: var(--texte-discret);
  font-variant-numeric: tabular-nums;
}
.chronologie .quoi-fait { font-weight: 600; }
.chronologie .detail { font-size: 0.86rem; color: var(--texte-discret); margin-top: 0.15rem; }
/* Mesure a 375 px : 0.72rem donnait 11,5 px. Une mention discrete doit rester
   discrete, pas illisible. */
.chronologie .saisi-apres {
  font-size: 0.75rem; color: var(--texte-discret); font-style: italic;
}

/* Hierarchie de lecture : on voit d'abord QUAND et QUOI ; le detail vient
   apres, plus petit et plus pale, sans jamais etre cache. */
.chronologie .quoi-fait { font-size: 1rem; display: block; margin-top: 0.1rem; }

/* --- Arbre de provenance ------------------------------------------------- */

.arbre, .arbre ul { list-style: none; padding-left: 0; margin: 0; }
.arbre ul { padding-left: 1.1rem; border-left: 1px dashed var(--bordure); margin-left: 0.35rem; }
/* Les liens de l'arbre sont le moyen NORMAL de circuler dans la provenance :
   mesures a 22 px de haut, ils etaient pratiquement invisables au pouce. */
.arbre li { padding: 0.15rem 0; }
.arbre .noeud a {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 0.1rem 0;
}
.arbre .noeud { display: flex; align-items: baseline; gap: 0.45rem; flex-wrap: wrap; }
.arbre .lien-role {
  font-size: 0.75rem; color: var(--texte-discret);
  background: var(--fond); border: 1px solid var(--bordure);
  border-radius: 999px; padding: 0.05rem 0.5rem;
}
.arbre .part { font-size: 0.78rem; color: var(--texte-discret); font-variant-numeric: tabular-nums; }
.arbre .boucle { font-size: 0.78rem; color: var(--texte-discret); font-style: italic; }

/* --- Ce qu'on ne sait pas ------------------------------------------------ */

/* Jamais une valeur inventée : un trou reste un trou, et il se voit. */
.inconnu {
  color: var(--texte-discret); font-style: italic;
}
/* Un lien de retour reste un lien qu'on vise au pouce, souvent en haut de
   page, la ou la main tient l'appareil. */
.lien-retour {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 0.2rem 0;
}

.avertissement-incomplet {
  background: #fdf6ec; border: 1px solid #e8d5b5; color: #7a5320;
  border-radius: var(--rayon); padding: 0.6rem 0.8rem;
  font-size: 0.86rem; margin: 0.6rem 0;
}

@media (max-width: 720px) {
  /* Mesure a 375 px : 0.68rem donnait 10,88 px, sous le seuil de lisibilite.
     On ne descend plus sous 0.75rem (12 px), quitte a ce que le libelle passe
     sur trois lignes — mieux vaut lire en trois lignes qu'echouer a lire. */
  .trio-quantites .nombre { font-size: 1.4rem; }
  .trio-quantites .quoi { font-size: 0.75rem; }
  .trio-quantites > div { padding: 0.6rem 0.25rem; }
  /* L'arbre se replie : sur iPhone, l'indentation mange la largeur utile. */
  .arbre ul { padding-left: 0.7rem; }
}

/* Un chemin de navigation présenté comme tel : cible pleine largeur, lisible
   d'un coup d'œil, plutôt qu'un mot souligné au milieu d'une phrase. */
.puce-lien {
  display: flex; align-items: center; gap: 0.5rem;
  min-height: 48px; padding: 0.5rem 0.8rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon);
  background: var(--surface); text-decoration: none; color: var(--texte);
}
.puce-lien:hover { background: var(--fond); }
.puce-lien span:first-child { font-size: 0.8rem; color: var(--texte-discret); }
.puce-lien strong { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.puce-lien span:last-child { color: var(--texte-discret); }

/* Texte d'aide sous un champ : il explique, il ne décore pas. 12 px minimum —
   une explication illisible ne vaut pas mieux qu'une absence d'explication. */
.aide-champ {
  font-size: 0.8rem;
  color: var(--texte-discret);
  margin: 0.3rem 0 0;
  line-height: 1.35;
}
.aide-champ:empty { display: none; }

/* La conséquence du choix, annoncée AVANT de valider : « cet objet ne sera
   plus proposé à la vente » se comprend, « rend_indisponible » non. */
.consequence-immobilise { color: #8a4a1e; }
.consequence-libere     { color: #1f5c3a; }

/* Les champs d'une feuille doivent rester confortables au pouce : sous 44 px,
   on vise à côté, et la saisie devient pénible avant d'être impossible. */
.feuille-generique input,
.feuille-generique select,
.feuille-generique textarea {
  min-height: 44px;
  font-size: 1rem;   /* sous 16 px, iOS zoome automatiquement au focus */
}
.feuille-generique textarea { min-height: 66px; }

/* Les boutons d'une feuille aussi : mesurés à 37 px sur grand écran, alors
   qu'une tablette de 1 024 px est tactile. La largeur de l'écran ne dit rien
   du doigt qui s'en sert. */
/* TOUS les boutons d'une feuille ou d'une fiche de traçabilité, pas seulement
   ceux de la barre d'action : « + Un autre objet produit » tombait à 37 px sur
   grand écran. La largeur de l'écran ne dit rien du doigt qui s'en sert — une
   tablette de 1 024 px est tactile. */
.feuille-generique button,
#fiche button,
#zone-suivi-individuel button { min-height: 44px; }

/* La barre d'action reste collée au bas de la feuille.
 *
 * Mesuré sur un iPhone SE (320 x 568) : le contenu dépassait, et le bouton de
 * validation se retrouvait sous la ligne de flottaison. La feuille défilait
 * bien, mais rien ne le laissait deviner — l'action principale semblait
 * absente. Elle est désormais toujours visible, quelle que soit la hauteur
 * d'écran. */
.feuille-generique .actions-feuille {
  position: sticky;
  bottom: 0;
  background: var(--surface);
  padding: 0.7rem 0 0.2rem;
  margin-top: 0.4rem;
  border-top: 1px solid var(--bordure);
}

/* --- Corrections : l'avant et l'après, côte à côte ----------------------- */

/* Une correction n'est pas un événement comme les autres : elle rectifie.
   Son point de chronologie le dit visuellement, sans crier. */
.chronologie li.correction::before {
  background: var(--fond);
  border-color: var(--texte-discret);
  border-style: dashed;
}

.detail-correction {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0.45rem 0.6rem;
  background: var(--fond);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  font-size: 0.86rem;
}
.detail-correction li { padding: 0.15rem 0; }
/* L'ancienne valeur reste LISIBLE : barrée, jamais effacée ni cachée. */
.detail-correction .avant { text-decoration: line-through; color: var(--texte-discret); }
.detail-correction .apres { font-weight: 600; }

/* Une action secondaire dans une chronologie : présente sans encombrer, mais
   qui reste une vraie cible tactile. */
.lien-discret {
  background: none; border: none; padding: 0.5rem 0 0;
  min-height: 44px;
  color: var(--accent); font-size: 0.86rem;
  text-decoration: underline; cursor: pointer;
}
.lien-discret:hover { color: var(--accent-fonce); }

/* Deux champs courts côte à côte (quantité + unité) : sur téléphone ils
   tiennent sur une ligne et évitent un formulaire à rallonge ; ils se
   replient en dessous de 300 px, largeur où deux colonnes ne tiennent plus. */
.deux-colonnes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}
@media (max-width: 300px) {
  .deux-colonnes { grid-template-columns: 1fr; }
}

/* Un objet produit par une transformation : encadré discret pour qu'on voie
   d'un coup d'œil combien il y en a, et lequel on remplit. */
.bloc-resultat {
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  padding: 0.7rem 0.8rem;
  margin-bottom: 0.6rem;
  background: var(--fond);
}
.bloc-resultat .champ:last-of-type { margin-bottom: 0; }

/* Un lien présenté comme un bouton reste une cible qu'on vise au doigt.
   Mesuré à 40 px sur la page SAV. Portée volontairement limitée aux blocs
   `.feuille` : je n'ai pas revu tous les écrans du logiciel, et élargir la
   règle à `.bouton` en général se ferait sans vérification. */
.feuille a.bouton {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;
}

/* Marquage « vendu » en masse (BackOffice, 2026-08-16) — replié par défaut :
   c'est un raccourci de période de transition, il ne doit pas occuper la
   place de la liste des articles, ni donner l'impression d'un mode de
   saisie principal. */
.bloc-marquage {
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  background: var(--surface);
  padding: 0.6rem 0.9rem;
  margin-bottom: 1rem;
}
.bloc-marquage summary { cursor: pointer; font-weight: 600; min-height: 44px; display: flex; align-items: center; }
.bloc-marquage .aide-marquage { color: var(--texte-discret); font-size: 0.9rem; margin: 0.2rem 0 0.7rem; }
.bloc-marquage textarea { width: 100%; box-sizing: border-box; font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; }
.bloc-marquage label { display: block; font-size: 0.78rem; color: var(--texte-discret); text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 0.25rem; }
.bloc-marquage #societe-marquage { margin-bottom: 0.7rem; }
.actions-marquage { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.6rem; }
.actions-marquage button { min-height: 44px; }

/* Le récapitulatif d'analyse : une ligne par famille de références, la
   liste elle-même défilant à l'intérieur de son cadre — une saisie de
   200 références ne doit pas repousser le bouton de confirmation hors
   de l'écran d'un iPhone. */
.recap-marquage { margin-top: 0.9rem; }
.recap-marquage h3 { font-size: 0.95rem; margin: 0.9rem 0 0.3rem; }
.recap-marquage .liste-references {
  max-height: 9rem;
  overflow-y: auto;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.85rem;
  color: var(--texte-discret);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  padding: 0.4rem 0.6rem;
  overflow-wrap: anywhere;
}

/* ─── LE RETOUR D'UN CRAN (ADR-0099) ──────────────────────────────────────
   Demandé par Emmanuel le 2026-08-29 : « je ne veux jamais me retrouver dans
   un écran où la seule solution pour sortir consiste à fermer la page ».

   En haut à gauche, collant : on ne cherche pas le retour en remontant la
   page. 44 px de cible tactile — la mesure retenue depuis l'audit du SAV.
   La couleur est posée EXPLICITEMENT : ce contrôle est un lien, pas un
   bouton, mais la leçon du 28/08 vaut partout (voir
   test_contraste_lisibilite.py). #4a443e sur #faf8f5 = 8,9:1. */
.retour-hierarchique {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 44px;
  padding: 0 0.6rem 0 0.2rem;
  margin: 0 0 0.4rem -0.2rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: #4a443e;
  text-decoration: none;
  border-radius: var(--rayon);
}
.retour-hierarchique span[aria-hidden] { font-size: 1.4rem; line-height: 1; }
.retour-hierarchique:hover { background: #f1ede6; color: #2b2622; }
.retour-hierarchique:focus-visible { outline: 3px solid #8a6d3b; outline-offset: 2px; }

@media (max-width: 720px) {
  .retour-hierarchique {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--fond);
    width: 100%;
    margin-left: 0;
    padding-left: 0.2rem;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   REFONTE UI — ACCUEIL (branche refonte-ui/accueil, 2026-09-09)

   AJOUT PUR. Rien au-dessus n'est modifié. Toutes les classes sont préfixées
   `tdb-` et ne sont utilisées que par `tableau_de_bord.html` : aucun autre
   écran n'est affecté. Les nouveaux tokens sémantiques ne sont pour l'instant
   consommés que par ces classes. Un `:root` supplémentaire est fusionné par le
   navigateur avec celui du haut — les tokens existants restent intacts.

   Séparation voulue (validée avec le client) :
   — une INFORMATION est plate et calme (indicateurs) ;
   — une ACTION a une affordance claire (ligne « à traiter » cliquable, bouton).
   Le champagne (--accent) reste une signature ; les ÉTATS ont leurs couleurs
   sémantiques propres (vert/orange/bleu/rouge), jamais le champagne.
   ═════════════════════════════════════════════════════════════════════════ */
:root {
  --succes: #2e7a53; --succes-fond: #e6f1ea; --succes-txt: #245a3d;
  --attention: #b0711a; --attention-fond: #f7eedb; --attention-txt: #845310;
  --info: #3a5788; --info-fond: #e8edf6; --info-txt: #2c4570;
  --danger-fond: #f7e6e2; --danger-txt: #8a2e2c;
}

.tdb-titre { margin: 0; font-size: 1.7rem; font-weight: 600; letter-spacing: -0.01em; color: var(--texte); }
.tdb-salut { color: var(--texte-discret); font-size: 0.92rem; margin: 0.4rem 0 0; }
.tdb-eyebrow { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--texte-discret); margin: 1.8rem 0 0.75rem; }
.tdb-eyebrow .n { font-weight: 500; letter-spacing: 0; text-transform: none; }

/* Accès rapide dès l'accueil : une barre qui ouvre la recherche globale
   (données + fonctions). Ressemble à un champ, agit comme un bouton. */
.tdb-recherche { display: flex; align-items: center; gap: 0.6rem; width: 100%; margin: 1.2rem 0 0.4rem; padding: 0.8rem 1rem; min-height: 48px; background: var(--surface); border: 1px solid var(--bordure); border-radius: 12px; color: var(--texte-discret); font-size: 0.95rem; text-align: left; cursor: text; box-shadow: 0 1px 2px rgba(28,26,23,.05); transition: border-color .15s, box-shadow .15s; }
.tdb-recherche:hover { border-color: var(--accent, #8a6d3b); box-shadow: 0 2px 8px rgba(28,26,23,.08); }
.tdb-recherche svg { flex: 0 0 auto; width: 18px; height: 18px; color: var(--texte-discret); }
.tdb-recherche span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* À traiter — lignes d'ACTION */
.tdb-actions { display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--bordure); border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(28,26,23,.05); }
.tdb-row { display: flex; align-items: center; gap: 0.9rem; padding: 0.95rem 1rem; border-top: 1px solid var(--bordure); text-decoration: none; color: inherit; position: relative; min-height: 44px; }
.tdb-row:first-child { border-top: none; }
.tdb-row:hover { background: #faf7f2; }
.tdb-row::before { content: ""; position: absolute; left: 0; top: 9px; bottom: 9px; width: 3px; border-radius: 0 3px 3px 0; }
.tdb-row.danger::before { background: var(--danger); }
.tdb-row.attention::before { background: var(--attention); }
.tdb-row.info::before { background: var(--info); }
.tdb-ico { flex: 0 0 auto; width: 38px; height: 38px; border-radius: 11px; display: flex; align-items: center; justify-content: center; }
.tdb-row.danger .tdb-ico { background: var(--danger-fond); color: var(--danger); }
.tdb-row.attention .tdb-ico { background: var(--attention-fond); color: var(--attention); }
.tdb-row.info .tdb-ico { background: var(--info-fond); color: var(--info); }
.tdb-ico svg { width: 19px; height: 19px; }
.tdb-txt { flex: 1; min-width: 0; }
.tdb-t { display: block; font-weight: 600; font-size: 0.95rem; color: var(--texte); line-height: 1.3; }
.tdb-d { display: block; font-size: 0.8rem; color: var(--texte-discret); margin-top: 2px; }
.tdb-cnt { flex: 0 0 auto; font-weight: 700; font-size: 1.05rem; color: var(--texte); font-variant-numeric: tabular-nums; }
.tdb-chev { flex: 0 0 auto; color: var(--texte-discret); display: flex; }
.tdb-chev svg { width: 18px; height: 18px; }
.tdb-tout-clair { display: flex; align-items: center; gap: 0.85rem; padding: 1.1rem; background: var(--succes-fond); border: 1px solid #cfe4d8; border-radius: 10px; color: var(--succes-txt); }
.tdb-tout-clair svg { width: 22px; height: 22px; flex: 0 0 auto; color: var(--succes); }
.tdb-tout-clair b { color: #1e4e36; }

/* Indicateurs — INFORMATION (sans affordance d'action) */
/* Flex plutôt que grid : le dernier indicateur d'une ligne incomplète s'étire
   au lieu de laisser une cellule fantôme (cas d'un nombre impair de KPI). Les
   filets internes sont peints par box-shadow (sans effet sur la mise en page) ;
   la bordure + overflow du conteneur masquent ceux des bords extérieurs. */
.tdb-kpis { display: flex; flex-wrap: wrap; background: var(--surface); border: 1px solid var(--bordure); border-radius: 10px; overflow: hidden; }
.tdb-kpi { flex: 1 1 150px; padding: 0.95rem 1rem; box-shadow: -1px 0 0 var(--bordure), 0 -1px 0 var(--bordure); }
.tdb-k-lib { font-size: 0.76rem; color: var(--texte-discret); }
.tdb-k-val { font-size: 1.7rem; font-weight: 600; color: var(--texte); margin-top: 0.25rem; font-variant-numeric: tabular-nums; line-height: 1; }
.tdb-k-sous { font-size: 0.76rem; color: var(--texte-discret); margin-top: 0.3rem; }

/* Actions rapides — ACTIONS (boutons-cartes) */
.tdb-quick { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
.tdb-qbtn { display: flex; align-items: center; gap: 0.75rem; padding: 0.95rem; background: var(--surface); border: 1px solid var(--bordure); border-radius: 10px; text-decoration: none; color: var(--texte); min-height: 44px; box-shadow: 0 1px 2px rgba(28,26,23,.05); }
.tdb-qbtn:hover { border-color: #d8cfc0; }
.tdb-qi { flex: 0 0 auto; width: 38px; height: 38px; border-radius: 11px; background: #efeae0; color: var(--accent-fonce); display: flex; align-items: center; justify-content: center; }
.tdb-qi svg { width: 19px; height: 19px; }
.tdb-ql { font-size: 0.9rem; font-weight: 600; line-height: 1.25; }
.tdb-ql small { display: block; font-weight: 400; color: var(--texte-discret); font-size: 0.76rem; margin-top: 2px; }
@media (min-width: 620px) { .tdb-quick { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } }

/* ═══════════════════════════════════════════════════════════════════════════
   REFONTE UI — CATALOGUE (branche refonte-ui/accueil, 2026-09-09)

   AJOUT PUR. Classes préfixées `cat-`, employées UNIQUEMENT par catalogue.html.
   Aucune règle existante n'est modifiée. La grille et les cartes du catalogue
   passent à ce composant autonome ; `.grille-catalogue` / `.carte-bijou`
   (écran « Photos non classées ») restent intacts et cet écran n'est pas
   touché. Les tons d'état réutilisent les tokens sémantiques ajoutés pour
   l'Accueil ; on ajoute seulement un ton neutre.

   Direction validée : photo dominante, référence et désignation lisibles,
   ÉTAT COMMERCIAL (statut_stock) clairement identifiable en pastille sur la
   photo, PRÉSENCE / localisation physique montrée À PART sous la photo — la
   distinction état ≠ localisation est conservée. Recherche et filtres pilotés
   par les mêmes ids et les mêmes gardes de droits qu'avant ; rien de métier.
   ═════════════════════════════════════════════════════════════════════════ */
:root { --neutre-fond: #e9e5df; --neutre-txt: #5f574e; }

/* Barre d'outils : recherche dominante + filtres compacts */
.cat-outils { margin-bottom: 1.3rem; }
.cat-recherche { display: flex; align-items: center; gap: 0.6rem; background: var(--surface); border: 1px solid var(--bordure); border-radius: 999px; padding: 0.7rem 1.1rem; box-shadow: 0 1px 2px rgba(28,26,23,.05); margin-bottom: 0.8rem; }
.cat-recherche svg { width: 19px; height: 19px; color: var(--texte-discret); flex: 0 0 auto; }
.cat-recherche input { border: none; background: none; outline: none; flex: 1; min-width: 0; font: inherit; font-size: 16px; color: var(--texte); }
.cat-filtres { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.cat-filtres select { border-radius: 999px; max-width: 100%; }
.cat-pousse { margin-left: auto; }
/* Bannière « filtre à traiter » (arrivée depuis une tuile de l'accueil). */
.cat-filtre-actif { display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; margin: 0 0 1rem; padding: 0.55rem 0.9rem; background: var(--surface); border: 1px solid var(--accent, #8a6d3b); border-radius: 10px; font-size: 0.92rem; color: var(--texte); }
.cat-filtre-actif::before { content: "Filtre :"; font-weight: 600; color: var(--texte-discret); }
.cat-filtre-actif button { margin-left: auto; }
.cat-avances { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-top: 0.7rem; padding-top: 0.8rem; border-top: 1px solid var(--bordure); }
@media (max-width: 719px) {
  /* Sur iPhone, les filtres primaires défilent horizontalement plutôt que de
     remplir l'écran : la photo reste la vedette, pas la mécanique de filtre. */
  .cat-filtres { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 4px; }
  .cat-filtres::-webkit-scrollbar { display: none; }
  .cat-filtres select, .cat-filtres button { flex: 0 0 auto; }
  .cat-pousse { margin-left: 0; }
}

/* Grille — photo dominante */
.cat-grille { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.8rem; }
@media (min-width: 720px) { .cat-grille { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1.1rem; } }

.cat-carte { position: relative; background: var(--surface); border: 1px solid var(--bordure); border-radius: 12px; overflow: hidden; cursor: pointer; box-shadow: 0 1px 3px rgba(28,26,23,.06); transition: transform .14s ease, box-shadow .14s ease; }
.cat-carte:hover { transform: translateY(-3px); box-shadow: 0 8px 18px rgba(28,26,23,.10); }
.cat-photo { aspect-ratio: 1 / 1; position: relative; background: radial-gradient(120% 100% at 50% 8%, #ffffff 0%, #f1ece2 55%, #e6ddcd 100%); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.cat-photo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.cat-sansphoto { color: var(--texte-discret); font-size: 0.76rem; text-align: center; padding: 0 1rem; display: flex; flex-direction: column; align-items: center; gap: 0.3rem; }
.cat-sansphoto svg { width: 30px; height: 30px; opacity: 0.4; }

/* Case de sélection (catalogue PDF) — discrète, posée sur la photo */
.cat-case { position: absolute; top: 0.5rem; right: 0.5rem; z-index: 2; width: 28px; height: 28px; background: rgba(255,255,255,0.92); border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
.cat-case input { width: 16px; height: 16px; margin: 0; cursor: pointer; }

/* Pastille d'ÉTAT COMMERCIAL (statut_stock), superposée sur la photo */
.cat-etat { position: absolute; top: 0.5rem; left: 0.5rem; z-index: 2; }
.cat-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 0.72rem; font-weight: 600; padding: 4px 9px; border-radius: 999px; white-space: nowrap; line-height: 1.2; box-shadow: 0 1px 2px rgba(28,26,23,0.12); }
.cat-badge svg { width: 12px; height: 12px; }
.cat-t-succes { background: var(--succes-fond); color: var(--succes-txt); } .cat-t-succes svg { color: var(--succes); }
.cat-t-attention { background: var(--attention-fond); color: var(--attention-txt); } .cat-t-attention svg { color: var(--attention); }
.cat-t-info { background: var(--info-fond); color: var(--info-txt); } .cat-t-info svg { color: var(--info); }
.cat-t-neutre { background: var(--neutre-fond); color: var(--neutre-txt); } .cat-t-neutre svg { color: var(--neutre-txt); }

/* Informations sous la photo */
.cat-info { padding: 0.7rem 0.8rem 0.85rem; }
.cat-ref { font-size: 0.88rem; font-weight: 600; color: var(--texte); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
.cat-des { font-size: 0.82rem; color: var(--texte); margin-top: 2px; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cat-cat { font-size: 0.77rem; color: var(--texte-discret); margin-top: 3px; }
.cat-deta { font-size: 0.75rem; color: var(--texte-discret); margin-top: 4px; }
.cat-pres { font-size: 0.78rem; color: var(--texte); font-weight: 600; margin-top: 8px; display: flex; align-items: center; gap: 5px; }
.cat-pres svg { width: 13px; height: 13px; color: var(--texte-discret); flex: 0 0 auto; }
.cat-prix { font-size: 0.92rem; font-weight: 700; color: var(--texte); margin-top: 6px; }
/* Le prix public conseille d'un agent commercial (ADR-0110) : calcule a
   l'affichage, jamais enregistre. Volontairement discret — c'est le prix
   de vente au-dessus qui est SON prix de travail. */
.cat-prix-conseille { font-size: 0.82rem; color: var(--texte-discret); margin-top: 2px; }

/* ═══════════════════════════════════════════════════════════════════════════
   REFONTE UI — FICHE ARTICLE (branche refonte-ui/accueil, 2026-09-10)

   AJOUT PUR. Classes préfixées `fa-`, employées UNIQUEMENT par bijou_detail.html.
   Aucune règle existante modifiée. On NE redéfinit PAS les classes partagées
   (`.fiche`, `.champ`, `.champs-fiche`, `.valeur`, `.feuille-generique`) qui
   servent ~33 autres écrans : la fiche garde ces classes pour ses champs, et
   `fa-` n'apporte que la nouvelle mise en page (en-tête, sections repliables).

   Direction validée : grande photo, référence + désignation + ÉTAT + PRÉSENCE
   immédiatement visibles et NETTEMENT distingués, puis informations en sections
   logiques (repliables) plutôt qu'un long formulaire uniforme. Composition par
   DONNÉE RÉELLE (une section technique ne se déplie que si elle porte une
   valeur) : aucun champ inventé, aucune capacité retirée (tout reste editable
   pour qui en a le droit, juste replié). Etat = statut_stock ; présence =
   module presence, montrée à part. Confidentiel inchangé (droits serveur).
   ═════════════════════════════════════════════════════════════════════════ */
.fa-layout { display: grid; grid-template-columns: 380px 1fr; gap: 0.4rem 2rem; align-items: start;
  grid-template-areas: "media entete" "media corps"; }
.fa-media { grid-area: media; }
.fa-entete { grid-area: entete; }
.fa-corps { grid-area: corps; }
@media (min-width: 761px) { .fa-media { position: sticky; top: 1rem; } }
/* iPhone : la grande photo d'abord, puis l'identité (réf/état/prix/présence)
   immédiatement lisible, puis le corps (gestion photo + formulaire). */
@media (max-width: 760px) {
  .fa-layout { grid-template-columns: 1fr; gap: 0.9rem; grid-template-areas: "media" "entete" "corps"; }
}

/* En-tête d'identité */
.fa-entete { margin-bottom: 1rem; }
.fa-entete h1 { margin: 0; font-size: 1.5rem; font-variant-numeric: tabular-nums; letter-spacing: 0.01em; color: var(--texte); }
.fa-designation { font-family: "Fraunces", Georgia, "Times New Roman", serif; font-size: 1.3rem; line-height: 1.2; color: var(--texte); margin-top: 0.25rem; }
.fa-designation:empty { display: none; }
/* La ligne commerciale : « 93 diamants ronds · 1,00 ct · 17 cm ». Ce que la
   désignation ne dit pas, et qui se vend (Emmanuel, 13/09/2026). Discrète —
   elle accompagne le nom, elle ne le concurrence pas. */
.fa-sous-titre { font-size: 0.9rem; color: var(--texte-discret); margin-top: 0.15rem; }
.fa-sous-titre:empty { display: none; }
.cat-sous { font-size: 0.75rem; color: var(--texte-discret); margin-top: 1px; line-height: 1.3; }
.cat-sous:empty { display: none; }

/* Le rappel de situation sur une carte du catalogue. DISCRET : c'est une
   information, pas une action principale. Faute de cette règle, il héritait du
   bouton brun de la charte et criait sur chaque carte (constaté le 14/09).
   Vide, il DISPARAÎT — on ne laisse pas un cadre gris sans texte. */
.cat-detention {
  display: block; width: 100%; text-align: left; margin-top: 0.3rem;
  padding: 0.15rem 0; border: 0; background: none;
  color: var(--texte-discret); font: inherit; font-size: 0.78rem;
  cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.cat-detention:empty { display: none; }

/* --- LA FEUILLE D'ACTION de la détention (ADR-0108) ---------------------
   La MÊME depuis la fiche et depuis le catalogue : un seul jeu de règles,
   parce qu'il n'y a qu'un seul parcours. Pensée pour le pouce : chaque cible
   fait au moins 44 px, y compris sur l'iPhone le plus étroit. */
.det-fond {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(20, 16, 10, 0.45);
  display: flex; align-items: flex-end; justify-content: center;
}
@media (min-width: 640px) { .det-fond { align-items: center; } }
.det-feuille {
  background: var(--fond-carte, #fff); color: var(--texte);
  width: 100%; max-width: 30rem; max-height: 88vh; overflow-y: auto;
  border-radius: 16px 16px 0 0; padding: 1.1rem 1.1rem 1.4rem;
  /* L'encoche et la barre d'accueil de l'iPhone : la feuille s'arrête avant. */
  padding-bottom: max(1.4rem, env(safe-area-inset-bottom));
  box-shadow: 0 -4px 30px rgba(40, 30, 15, 0.25);
}
@media (min-width: 640px) { .det-feuille { border-radius: 16px; } }
.det-fermer {
  float: right; border: 0; background: transparent; color: var(--texte-discret);
  font-size: 1.6rem; line-height: 1; min-width: 44px; min-height: 44px;
  cursor: pointer;
}
.det-ref { font-family: ui-monospace, Menlo, monospace; font-weight: 700;
  font-size: 1.05rem; margin: 0.2rem 0 0; }
.det-des { color: var(--texte-discret); margin: 0.1rem 0 0.8rem; }
.det-resume { font-size: 1.02rem; margin: 0 0 0.3rem; }
.det-resume.det-inconnu { color: var(--texte-discret); font-style: italic; }
.det-aide { font-size: 0.86rem; color: var(--texte-discret); margin: 0.2rem 0 0.9rem; }
.det-alerte { font-size: 1rem; font-weight: 600; margin: 0.2rem 0 0.4rem; }
.det-verbes { display: grid; grid-template-columns: 1fr 1fr; gap: 0.55rem;
  margin-top: 0.9rem; }
.det-verbe, .det-valider {
  min-height: 46px; padding: 0.7rem 0.9rem; border-radius: 11px;
  border: 1px solid var(--accent, #8a6d3b); background: var(--accent, #8a6d3b);
  color: #fff; font: 600 1rem inherit; cursor: pointer;
}
.det-verbe:last-child:nth-child(odd) { grid-column: 1 / -1; }
.det-valider { width: 100%; margin-top: 1rem; }
.det-label { display: block; font-size: 0.86rem; color: var(--texte-discret);
  margin: 0.9rem 0 0.25rem; }
.det-sur { font-style: italic; }
.det-feuille input, .det-feuille select {
  width: 100%; padding: 0.7rem 0.75rem; border-radius: 10px;
  border: 1px solid var(--bordure, #d8ccb4); background: var(--fond, #faf6ee);
  color: var(--texte);
  /* 16 px : en dessous, Safari zoome à chaque champ touché. */
  font-size: 16px;
}
.det-erreur { color: var(--danger, #a23b34); font-size: 0.9rem;
  margin: 0.7rem 0 0; }
.fa-etats { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin-top: 0.7rem; }
.fa-prix { font-size: 1.2rem; font-weight: 700; color: var(--texte); margin-top: 0.55rem; }
.fa-prix:empty { display: none; }
/* « Prix de détail non renseigné » : une information, pas un montant — ton
   discret, jamais l'allure d'un vrai prix. Affiché seulement à qui voit les prix. */
.fa-prix.fa-prix-absent { font-size: 0.9rem; font-weight: 500; font-style: italic; color: var(--texte-discret); }

/* Badge d'ÉTAT commercial (mêmes tons sémantiques que le reste de l'UI) */
.fa-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 0.82rem; font-weight: 600; padding: 5px 12px; border-radius: 999px; white-space: nowrap; }
.fa-badge svg { width: 14px; height: 14px; }
.fa-t-succes { background: var(--succes-fond); color: var(--succes-txt); } .fa-t-succes svg { color: var(--succes); }
.fa-t-attention { background: var(--attention-fond); color: var(--attention-txt); } .fa-t-attention svg { color: var(--attention); }
.fa-t-neutre { background: var(--neutre-fond); color: var(--neutre-txt); } .fa-t-neutre svg { color: var(--neutre-txt); }

/* PRÉSENCE dans l'en-tête — panneau info, visuellement distinct de l'état.
   Le contenu (h2/p) est injecté par chargerPresence() ; on ne fait que
   l'habiller. Vide (pas de présence / pas le droit), le bloc disparaît. */
.fa-entete #zone-presence { margin-top: 0.7rem; background: var(--info-fond); border: 1px solid #d7e0ef; border-radius: 9px; padding: 0.55rem 0.8rem; }
.fa-entete #zone-presence:empty { display: none; }
.fa-entete #zone-presence h2 { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--info-txt); margin: 0; }
.fa-entete #zone-presence p { margin: 0.2rem 0 0; font-size: 0.9rem; color: var(--texte); }
.fa-entete #zone-presence .aide-champ { font-size: 0.74rem; color: var(--texte-discret); }

/* Sections repliables du formulaire */
.fa-section { border: 1px solid var(--bordure); border-radius: 10px; margin: 0.7rem 0; background: var(--surface); }
.fa-section > summary { cursor: pointer; padding: 0.8rem 1rem; font-weight: 600; font-size: 0.95rem; color: var(--texte); list-style: none; display: flex; align-items: center; justify-content: space-between; min-height: 44px; box-sizing: border-box; }
.fa-section > summary::-webkit-details-marker { display: none; }
.fa-section > summary::after { content: ""; flex: 0 0 auto; width: 8px; height: 8px; border-right: 2px solid var(--texte-discret); border-bottom: 2px solid var(--texte-discret); transform: rotate(45deg); transition: transform 0.15s ease; margin-left: 0.6rem; }
.fa-section[open] > summary::after { transform: rotate(-135deg); }
.fa-section-corps { padding: 0 1rem 1rem; }
/* Titres de section non repliables (Caractéristiques, Informations
   commerciales, Quantités, Historique…). Ciblés par `.fa-corps h2` pour
   laisser les balises `<h2>` nues — un test vérifie « <h2>Quantités</h2> »
   au caractère près. La présence, elle, a son propre style plus haut. */
.fa-corps h2 { font-size: 1.05rem; font-weight: 600; margin: 1.5rem 0 0.3rem; color: var(--texte); }
.fa-corps > form > h2:first-child { margin-top: 0.4rem; }

/* La grille de champs respire un peu plus dans la fiche refondue, sans toucher
   à la règle globale `.champs-fiche` : on ne fait que réduire la marge haute
   quand elle suit un titre de section fa-. */
.fa-section-corps .champs-fiche { margin: 0.6rem 0 0; }

/* Action principale bien accessible au pouce sur iPhone */
@media (max-width: 760px) {
  #formulaire-edition button[type="submit"] { width: 100%; min-height: 46px; font-size: 1rem; }
}

/* Champs de la fiche en LECTURE SEULE (utilisateur sans `bijou.modifier`).
   Le gabarit pose `readonly`/`disabled` ; on habille ces champs comme une
   valeur affichée plutôt qu'un contrôle grisé « désactivé », pour un vrai
   rendu de consultation. Présentation uniquement — l'autorité reste le
   serveur, qui refuse tout PATCH sans le droit. Ciblé sous #formulaire-edition
   pour n'affecter aucun autre écran. */
#formulaire-edition input[readonly],
#formulaire-edition select:disabled {
  background: var(--fond);
  color: var(--texte);
  border-color: #e7e0d4;
  opacity: 1;                 /* jamais délavé : une valeur consultée reste lisible */
  cursor: default;
  -webkit-text-fill-color: var(--texte);   /* iOS n'estompe pas le texte d'un champ read-only */
}
#formulaire-edition select:disabled { appearance: none; -webkit-appearance: none; background-image: none; padding-right: 0.7rem; }

/* ═══ REFONTE UI — HARMONISATION NAV PC (2026-09-10) ═══
   Épuration VISUELLE de la barre du haut, strictement sur le registre de
   modules et les droits (mêmes liens, aucun ajout/retrait). Override des règles
   existantes `header.entete nav a` (même sélecteur, plus bas dans la cascade).
   N'affecte que l'en-tête ; la barre d'onglets mobile n'est pas touchée. */
header.entete nav { gap: 0.15rem 0.2rem; }
header.entete nav a {
  margin-right: 0;
  padding: 0.34rem 0.7rem;
  border-radius: 8px;
  color: var(--texte-discret);
  font-weight: 500;
  font-size: 0.92rem;
  line-height: 1.2;
  transition: background 0.12s ease, color 0.12s ease;
}
header.entete nav a:hover { background: #f4f0e8; color: var(--texte); text-decoration: none; }
header.entete nav a.actif {
  color: var(--accent-fonce);
  background: #efe9dd;
  font-weight: 600;
  text-decoration: none;
}

/* ═══ NAVIGATION PAR FAMILLES — menus déroulants PC (2026-09-10) ═══
   Familles Documents / Plus : un bouton qui ouvre un menu. Purement d'affichage :
   les liens sont rendus côté serveur (dans le DOM), seuls masqués tant que le
   menu est fermé — un module accessible reste donc toujours atteignable. */
.nav-famille { position: relative; display: inline-flex; }
.nav-famille-bouton {
  display: inline-flex; align-items: center; gap: 0.3rem;
  margin: 0; padding: 0.34rem 0.7rem; border: none; background: transparent;
  border-radius: 8px; color: var(--texte-discret); font: inherit;
  font-size: 0.92rem; font-weight: 500; line-height: 1.2; cursor: pointer;
}
.nav-famille-bouton:hover { background: #f4f0e8; color: var(--texte); }
.nav-famille.actif > .nav-famille-bouton { color: var(--accent-fonce); background: #efe9dd; font-weight: 600; }
.nav-chevron { font-size: 0.7rem; opacity: 0.75; transition: transform 0.15s ease; }
.nav-famille.ouvert > .nav-famille-bouton { background: #efe9dd; color: var(--texte); }
.nav-famille.ouvert .nav-chevron { transform: rotate(180deg); }

.nav-menu {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 220px; background: var(--surface); border: 1px solid var(--bordure);
  border-radius: 10px; box-shadow: 0 10px 28px rgba(28,26,23,.14);
  padding: 0.35rem; flex-direction: column;
}
.nav-famille.ouvert .nav-menu { display: flex; }
.nav-menu a {
  display: block; margin: 0; padding: 0.5rem 0.7rem; border-radius: 7px;
  color: var(--texte); font-weight: 500; font-size: 0.92rem; white-space: nowrap;
}
.nav-menu a:hover { background: #f4f0e8; text-decoration: none; }
.nav-menu a.actif { color: var(--accent-fonce); background: #efe9dd; font-weight: 600; }
.nav-menu-groupe {
  padding: 0.5rem 0.7rem 0.2rem; font-size: 0.7rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--texte-discret);
}
.nav-menu-groupe:first-child { padding-top: 0.2rem; }
/* « Plus » aligné à droite pour ne pas déborder du bord de l'écran. */
.nav-famille-plus .nav-menu { left: auto; right: 0; }

/* ── MA VALISE (ADR-0110) ────────────────────────────────────────────────
   Le compteur d'abord, et en grand : « il doit voir en permanence combien de
   bijoux il a ». Tout le reste vient apres. */
.val-entete { margin: 4px 0 14px; }
.val-compteur { font-size: 2rem; font-weight: 700; color: var(--texte); line-height: 1.1; }
.val-sous { font-size: 0.9rem; color: var(--texte-discret); margin-top: 2px; }
.val-ligne { display: flex; gap: 12px; align-items: center; padding: 10px 0;
             border-bottom: 1px solid var(--bordure); }
.val-image img, .val-sansphoto { width: 56px; height: 56px; border-radius: 8px; object-fit: cover; }
.val-sansphoto { display: flex; align-items: center; justify-content: center;
                 background: var(--fond-doux); color: var(--texte-discret); }
.val-texte { flex: 1; min-width: 0; }
.val-ref { font-weight: 700; }
.val-nb { font-weight: 400; font-size: 0.85rem; color: var(--texte-discret); }
.val-cat { font-size: 0.85rem; color: var(--texte-discret); }
.val-prix { font-size: 0.92rem; font-weight: 700; margin-top: 4px; }
.val-conseille { font-size: 0.82rem; color: var(--texte-discret); }
.val-actions { display: flex; flex-direction: column; gap: 6px; }
.val-actions button { white-space: nowrap; }
.val-ajout { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--bordure); }
.val-ajout-ligne { display: flex; gap: 8px; margin-top: 6px; }
.val-ajout-ligne input { flex: 1; }
.val-note { font-size: 0.85rem; color: var(--texte-discret); margin-top: 6px; }
@media (max-width: 720px) {
  .val-actions { flex-direction: row; }
  .val-actions button { font-size: 0.82rem; padding: 6px 8px; }
}

/* LA FILE DU BUREAU (ADR-0110). Préfixe `bag-` volontairement long : une classe
   courte partagée a déjà cassé deux maquettes le 14/09. */
.bag-entete h1 { margin: 0 0 4px; font-size: 1.5rem; }
.bag-entete .bag-note { margin: 0 0 14px; }
.bag-note { font-size: 0.85rem; color: var(--texte-discret); }
.bag-ligne { display: flex; gap: 12px; align-items: flex-start; padding: 12px 0;
  border-bottom: 1px solid var(--bordure); flex-wrap: wrap; }
.bag-texte { flex: 1; min-width: 200px; }
.bag-numero { font-weight: 700; }
.bag-agent { font-weight: 400; font-size: 0.85rem; color: var(--texte-discret); margin-left: 6px; }
.bag-client { font-size: 0.92rem; }
.bag-sous { font-size: 0.85rem; color: var(--texte-discret); }
.bag-alerte { font-size: 0.82rem; color: var(--danger); margin-top: 4px; }
.bag-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.bag-actions a { align-self: center; white-space: nowrap; }
.bag-numfacture { width: 150px; }
@media (max-width: 720px) {
  .bag-actions { width: 100%; }
  .bag-numfacture { flex: 1; width: auto; }
}

/* LE PRIX D'UN AGENT COMMERCIAL, sur sa fiche (ADR-0110). Il doit se lire sans
   être cherché : c'est le prix avec lequel il vend. */
.fa-prix-agent { font-size: 1.5rem; font-weight: 700; }
.fa-prix-mention { font-size: 0.8rem; font-weight: 500; color: var(--texte-discret);
  text-transform: uppercase; letter-spacing: 0.04em; margin-left: 8px; }
.fa-prix-conseille { font-size: 0.9rem; font-weight: 500; color: var(--texte-discret);
  margin-top: 2px; }

/* UN PRIX QUI MANQUE SE VOIT, sans crier : c'est une consigne pour le bureau,
   pas une alarme pour l'agent (ADR-0110). */
.val-prix-manquant, .cat-prix-manquant {
  font-weight: 500; font-style: italic; color: var(--texte-discret);
}

/* LE MOT DU JOUR (17/09/2026) — en haut de l'accueil, une phrase et un
   chiffre. Trois teintes selon le moment de la journée ; aucune ne crie. */
.mot-accueil { position: relative; border-radius: 12px; padding: 1rem 2.4rem 0.9rem 1rem; margin-bottom: 1.2rem; border: 1px solid var(--bordure); background: var(--surface); }
.mot-accueil--matin { background: #f7eedb; border-color: #e8d9b4; }
.mot-accueil--apres-midi { background: #e6f1ea; border-color: #c7e0d2; }
.mot-accueil--soir { background: #e8edf6; border-color: #c8d4e8; }
.mot-accueil-salut { margin: 0; font-size: 1.25rem; font-weight: 600; color: var(--texte); }
.mot-accueil-phrase { margin: 0.25rem 0 0; font-size: 1rem; line-height: 1.45; color: var(--texte); }
.mot-accueil-info { margin: 0.7rem 0 0; padding-top: 0.6rem; border-top: 1px solid rgba(43, 38, 34, 0.12); font-size: 0.9rem; color: var(--texte-discret); }
.mot-accueil-fermer { position: absolute; top: 0.35rem; right: 0.45rem; width: 2rem; height: 2rem; border: none; background: none; color: var(--texte-discret); font-size: 1.3rem; line-height: 1; cursor: pointer; }

/* Écran des mots d'accueil : une personne par bloc dépliable, pensé pour le
   pouce sur un téléphone. */
.mot-personne { margin-bottom: 0.8rem; }
.mot-personne summary { cursor: pointer; padding: 0.2rem 0; }
.mot-encours { background: #f7eedb; border: 1px solid #e8d9b4; border-radius: 8px; padding: 0.7rem 0.8rem; margin: 0.6rem 0; }
.mot-encours-date { font-size: 0.85rem; color: var(--texte-discret); margin: 0.3rem 0 0.5rem; }
.mot-encours-vide { color: var(--texte-discret); font-size: 0.9rem; margin: 0.5rem 0; }

/* « Envoyer à… » (18/09/2026) : le choix des destinataires WhatsApp, pensé
   pour le pouce — une ligne par numéro, deux champs libres. */
.bloc-actions-envoyer-a { margin-top: 0.7rem; padding: 0.8rem; border: 1px solid var(--bordure); border-radius: 10px; background: var(--surface); }
.bloc-actions-titre { margin: 0 0 0.6rem; font-weight: 600; }
.bloc-actions-choix { display: flex; align-items: center; gap: 0.6rem; padding: 0.45rem 0; font-size: 0.95rem; }
.bloc-actions-choix input { width: 22px; height: 22px; }
.bloc-actions-libre { display: block; margin-top: 0.5rem; font-size: 0.9rem; color: var(--texte-discret); }
.bloc-actions-libre input { display: block; width: 100%; box-sizing: border-box; margin-top: 0.25rem; }

/* ─── MA COLLECTION (représentant, ADR-0110) ──────────────────────────────
   Préfixe `mc-` partout : deux noms de classe courts partagés ont cassé une
   maquette deux fois en deux jours (14/09). Aucun `.mc-` n'existait avant. */
.mc-societes { display: flex; gap: 8px; margin: 0 0 14px; flex-wrap: wrap; }
.mc-societe { padding: 8px 16px; border: 1px solid var(--bordure); border-radius: 999px;
  background: var(--fond-carte); color: var(--texte-doux); font-size: .95rem; cursor: pointer; }
.mc-societe.choisie { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }

.mc-entete { margin: 4px 0 10px; }
.mc-titre { font-size: .95rem; color: var(--texte-doux); }
.mc-total { font-size: 2rem; font-weight: 700; color: var(--texte); line-height: 1.15; }
.mc-detail { font-size: .9rem; color: var(--texte-doux); margin-top: 2px; }

.mc-reserve { font-size: .82rem; color: var(--texte-doux); font-style: italic;
  background: var(--fond-doux); border-left: 3px solid var(--bordure);
  padding: 8px 12px; border-radius: 0 8px 8px 0; margin: 0 0 14px; }

.mc-axe { margin-bottom: 10px; }
.mc-axe-nom { display: block; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--texte-doux); margin-bottom: 5px; }
/* La bande défile au pouce : c'est le geste naturel sur un téléphone. */
.mc-bande { display: flex; gap: 7px; overflow-x: auto; padding-bottom: 4px;
  -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.mc-bande::-webkit-scrollbar { display: none; }
.mc-pastille { flex: 0 0 auto; padding: 7px 13px; border: 1px solid var(--bordure);
  border-radius: 999px; background: var(--fond-carte); color: var(--texte);
  font-size: .9rem; cursor: pointer; white-space: nowrap; }
.mc-pastille span { color: var(--texte-doux); font-size: .82rem; margin-left: 4px; }
.mc-pastille.choisie { background: var(--accent); border-color: var(--accent); color: #fff; }
.mc-pastille.choisie span { color: rgba(255,255,255,.75); }

.mc-ligne { display: flex; align-items: center; gap: 12px; padding: 10px;
  border: 1px solid var(--bordure); border-radius: 12px; background: var(--fond-carte);
  margin-bottom: 8px; text-decoration: none; color: inherit; }
.mc-ligne img, .mc-sans-photo { width: 58px; height: 58px; flex: 0 0 58px;
  border-radius: 9px; object-fit: contain; background: var(--fond-doux); }
.mc-sans-photo { display: flex; align-items: center; justify-content: center;
  font-size: .62rem; color: var(--texte-doux); text-align: center; font-style: italic; }
.mc-ligne-corps { flex: 1 1 auto; min-width: 0; }
.mc-ligne-corps b { display: block; font-size: 1rem; }
.mc-ligne-detail { display: block; font-size: .82rem; color: var(--texte-doux);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mc-ligne-prix { flex: 0 0 auto; text-align: right; font-weight: 600; font-size: .95rem; }
.mc-ligne-prix small { display: block; font-weight: 400; color: var(--texte-doux); }
.mc-sans-prix { font-weight: 400; font-style: italic; color: var(--texte-doux); font-size: .85rem; }
.mc-vide { color: var(--texte-doux); text-align: center; padding: 22px 0; }

/* Le bouton du document : collant en bas, sous le pouce. */
.mc-pdf { position: sticky; bottom: 14px; display: block; margin: 16px 0 6px;
  padding: 13px 18px; border-radius: 999px; background: var(--accent);
  color: #fff; font-weight: 600; text-align: center; text-decoration: none;
  box-shadow: 0 4px 14px rgba(0,0,0,.18); }
/* Les deux documents, cote a cote et colles en bas : sous le pouce, quelle
   que soit la longueur de la liste. Le second est secondaire, pas cache — un
   geste range dans un menu est un geste perdu sur un telephone. */
.mc-documents { position: sticky; bottom: 14px; display: flex; gap: 8px;
  align-items: stretch; margin: 16px 0 6px; }
.mc-documents .mc-pdf { position: static; margin: 0; flex: 1 1 auto; }
.mc-pdf-discret { flex: 0 1 auto; background: var(--fond-carte);
  color: var(--texte-doux); font-weight: 500; border: 1px solid var(--bordure);
  box-shadow: none; white-space: nowrap; }
@media (max-width: 380px) {
  /* Tres petit ecran : on empile plutot que de serrer deux boutons illisibles. */
  .mc-documents { flex-direction: column; }
}

/* ─── STOCKS REPRÉSENTANTS (vue administrateur) ───────────────────────── */
.sr-carte { display: block; width: 100%; text-align: left; margin-bottom: 10px;
  padding: 13px 15px; border: 1px solid var(--bordure); border-radius: 14px;
  background: var(--fond-carte); color: inherit; cursor: pointer; }
.sr-nom { display: block; font-weight: 600; font-size: 1.02rem; }
.sr-chiffres { display: block; font-size: 1.18rem; font-weight: 700; margin-top: 2px; }
.sr-sous { display: block; font-size: .85rem; color: var(--texte-doux); margin-top: 3px; }
.sr-pied { display: flex; gap: 10px; align-items: center; margin-top: 7px; }
.sr-alerte { font-size: .78rem; font-weight: 600; color: #fff; background: var(--danger);
  padding: 2px 9px; border-radius: 999px; }
.sr-quand { font-size: .78rem; color: var(--texte-doux); }

.sr-anomalies { border: 1px solid var(--danger); border-radius: 12px;
  padding: 10px 13px; margin-bottom: 12px; background: var(--fond-carte); }
.sr-anomalies > b { display: block; color: var(--danger); font-size: .82rem;
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: 5px; }
.sr-anomalie { font-size: .9rem; padding: 3px 0; }
.sr-anomalie span { display: block; font-size: .82rem; color: var(--texte-doux);
  font-style: italic; }
.sr-couts { display: block; font-size: .78rem; color: var(--texte-doux); margin-top: 2px; }

/* ─── NOUVEAU BON (representant, iPhone) ──────────────────────────────────
   Trois etapes, jamais plus d'une a l'ecran : debout chez un client, sur un
   telephone, on ne fait pas defiler un formulaire, on avance. */
.mb-fil { display: flex; gap: 6px; margin: 0 0 14px; }
.mb-etape { flex: 1 1 0; padding: 7px 4px; border-radius: 999px; text-align: center;
  font-size: .8rem; color: var(--texte-doux); background: var(--fond-carte);
  border: 1px solid var(--bordure); }
.mb-etape.choisie { background: var(--accent); color: #fff; border-color: var(--accent);
  font-weight: 600; }

.mb-panneau { margin-bottom: 8px; }

.mb-client-choisi { font-weight: 600; margin-bottom: 12px; }

/* Une cible large : on la touche avec le pouce, pas avec un curseur. */
.mb-choix { display: block; width: 100%; text-align: left; margin-bottom: 8px;
  padding: 13px 15px; min-height: 48px; border: 1px solid var(--bordure);
  border-radius: 14px; background: var(--fond-carte); color: inherit; cursor: pointer; }
.mb-choix.choisie { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent) inset; }
.mb-choix-nom { display: block; font-weight: 600; }
.mb-choix-sous { display: block; font-size: .85rem; color: var(--texte-doux); }

.mb-saisie { margin: 14px 0; padding: 14px; border: 1px solid var(--accent);
  border-radius: 16px; background: var(--fond-carte); }
.mb-saisie-titre { font-weight: 600; margin-bottom: 10px; }
.mb-saisie-champs { display: flex; gap: 10px; flex-wrap: wrap; }
.mb-saisie-champs label { flex: 1 1 130px; font-size: .85rem; color: var(--texte-doux); }
/* 17px : en dessous de 16px, iOS zoome tout seul sur le champ. */
.mb-saisie-champs input { display: block; width: 100%; margin-top: 4px; padding: 11px 12px;
  font-size: 17px; border: 1px solid var(--bordure); border-radius: 10px;
  background: var(--fond); color: inherit; }
.mb-indice { margin: 10px 0 0; font-size: .85rem; color: var(--texte-doux); }
.mb-indice-refus { color: #b3261e; font-weight: 600; }
.mb-ajouter { width: 100%; margin-top: 12px; padding: 12px; min-height: 48px;
  border: 0; border-radius: 999px; background: var(--accent); color: #fff;
  font-weight: 600; font-size: 1rem; cursor: pointer; }

.mb-liste-titre { margin: 16px 0 8px; font-size: .85rem; color: var(--texte-doux); }
.mb-ligne { display: flex; align-items: center; gap: 10px; padding: 11px 13px;
  margin-bottom: 7px; border: 1px solid var(--bordure); border-radius: 12px;
  background: var(--fond-carte); }
.mb-ligne-ref { font-weight: 600; }
.mb-ligne-detail { font-size: .85rem; color: var(--texte-doux); }
.mb-ligne-total { margin-left: auto; font-weight: 600; white-space: nowrap; }
.mb-retirer { width: 34px; height: 34px; flex: 0 0 34px; border: 1px solid var(--bordure);
  border-radius: 50%; background: transparent; color: var(--texte-doux);
  font-size: 1.2rem; line-height: 1; cursor: pointer; }

.mb-totaux { margin: 16px 0; padding: 14px; border-radius: 16px;
  background: var(--fond-carte); border: 1px solid var(--bordure); }
.mb-totaux-ligne { display: flex; justify-content: space-between; gap: 12px;
  padding: 5px 0; font-size: .95rem; }
.mb-totaux-fort { margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--bordure);
  font-size: 1.15rem; font-weight: 700; }

/* ⛔ CE QUI N'EST PAS ENCORE POSSIBLE, ET POURQUOI. Visible, pas discret : un
   geste desactive sans explication se lit comme une panne. */
.mb-avertissement { margin: 14px 0; padding: 12px 14px; border-radius: 12px;
  background: #fff4e5; border: 1px solid #f0c48a; color: #6b4a12;
  font-size: .9rem; }
.mb-valider { width: 100%; padding: 14px; min-height: 48px; border: 0;
  border-radius: 999px; background: var(--accent); color: #fff; font-weight: 600;
  font-size: 1.05rem; cursor: pointer; }
.mb-valider:disabled { background: var(--bordure); color: var(--texte-doux);
  cursor: not-allowed; }

/* ── LE JUSTIFICATIF, REPLIE PAR DEFAUT ─────────────────────────────────
   Facultatif : il ne doit pas encombrer le chemin de celui qui vend sans
   facture Oxygene sous les yeux. Mais atteignable d'un doigt. */
.mb-justificatif { margin: 14px 0; padding: 10px 14px; border-radius: 12px;
  background: var(--fond-carte); border: 1px solid var(--bordure); }
.mb-justificatif > summary { min-height: 44px; display: flex; align-items: center;
  font-size: .95rem; font-weight: 600; cursor: pointer; }
.mb-champ { display: block; margin: 10px 0; font-size: .88rem; }
.mb-champ > span { display: block; margin-bottom: 4px; color: var(--texte-doux); }
.mb-champ input { width: 100%; min-height: 48px; padding: 10px 12px;
  border: 1px solid var(--bordure); border-radius: 10px; font-size: 1rem;
  /* 1rem au minimum : en dessous, iOS zoome tout seul a la saisie et le
     formulaire sort de l'ecran. */ }
.mb-note { margin: 8px 0 2px; font-size: .82rem; color: var(--texte-doux); }

/* ── LA CONFIRMATION AVANT L'IRREVERSIBLE ───────────────────────────────
   Emmanuel, 15/10 : « une confirmation avant toute operation irreversible ».
   Dans la page, pas en `confirm()` : sur un ecran d'accueil installe, la
   boite native ne s'affiche pas toujours. */
.mb-confirmation { margin: 14px 0; padding: 16px; border-radius: 14px;
  background: #fff; border: 2px solid var(--accent); }
.mb-confirmation-titre { margin: 0 0 6px; font-size: 1.05rem; font-weight: 700; }
.mb-confirmation-detail { margin: 0 0 10px; font-size: .95rem; }
.mb-confirmation-avis { margin: 0 0 14px; font-size: .85rem;
  color: var(--texte-doux); }
.mb-confirmation-boutons { display: flex; gap: 10px; }
.mb-confirmation-boutons button { flex: 1; min-height: 48px; border-radius: 999px;
  font-size: 1rem; font-weight: 600; cursor: pointer; }
.mb-annuler { border: 1px solid var(--bordure); background: #fff; }
.mb-confirmer { border: 0; background: var(--accent); color: #fff; }
.mb-confirmer:disabled { background: var(--bordure); color: var(--texte-doux); }

/* ── VALIDE : UN ETAT QUI SE VOIT SANS LIRE ─────────────────────────────── */
.mb-marque-validee { margin: 14px 0; padding: 12px 14px; border-radius: 12px;
  background: #e8f6ec; border: 1px solid #9ad2ab; color: #1d5b2e;
  font-size: .92rem; font-weight: 600; }

/* ═══ REMETTRE / REPRENDRE — l'ecran de Nathalie ════════════════════════ */
.rr-page { max-width: 720px; margin: 0 auto; padding: 0 16px 90px; }
.rr-titre { font-size: 1.25rem; margin: 18px 0 14px; }

/* LE SENS DU GESTE SE CHOISIT EN PREMIER : remettre et reprendre ne se
   ressemblent pas, et les confondre fausserait une collection deux fois. */
.rr-sens { display: flex; gap: 10px; margin-bottom: 16px; }
.rr-choix-sens { flex: 1; min-height: 52px; border-radius: 12px; font-size: .95rem;
  font-weight: 600; cursor: pointer; background: #fff;
  border: 1px solid var(--bordure); color: var(--texte-doux); }
.rr-choix-sens.choisi { background: var(--accent); color: #fff; border-color: var(--accent); }

.rr-champ { display: block; margin: 12px 0; font-size: .88rem; }
.rr-champ > span { display: block; margin-bottom: 4px; color: var(--texte-doux); }
.rr-champ input, .rr-champ select { width: 100%; min-height: 48px;
  padding: 10px 12px; border: 1px solid var(--bordure); border-radius: 10px;
  font-size: 1rem; /* 1rem minimum : en dessous, iOS zoome a la saisie */ }
.rr-deux { display: flex; gap: 12px; }
.rr-deux .rr-champ { flex: 1; }

.rr-saisie { display: flex; gap: 10px; align-items: flex-end; margin: 14px 0; }
.rr-champ-ref { flex: 1 1 auto; margin: 0; }
.rr-champ-qte { flex: 0 0 92px; margin: 0; }
.rr-ajouter { min-height: 48px; padding: 0 18px; border: 0; border-radius: 999px;
  background: var(--accent); color: #fff; font-weight: 600; font-size: 1rem;
  cursor: pointer; }

.rr-lignes { list-style: none; margin: 10px 0; padding: 0; }
.rr-ligne { display: flex; align-items: center; gap: 10px; padding: 11px 12px;
  border: 1px solid var(--bordure); border-radius: 10px; margin-bottom: 8px;
  background: var(--fond-carte); }
.rr-ligne-ref { flex: 1; font-weight: 600; font-variant-numeric: tabular-nums; }
.rr-ligne-qte { color: var(--texte-doux); }
/* ⛔ LA LIGNE QUE LE SERVEUR A REFUSÉE — 07/11/2026.
   Emmanuel : « Nathalie doit voir immédiatement quelle ligne pose problème
   et pourquoi. » La couleur seule ne suffirait pas : le motif est ÉCRIT sur
   la ligne, et la bordure épaisse la trouve du coin de l'œil. */
.rr-ligne-refusee { border-color: var(--danger); border-left-width: 4px;
  background: #fdecea; flex-wrap: wrap; }
.rr-ligne-motif { flex-basis: 100%; color: #9b2c2c; font-size: .92rem;
  line-height: 1.35; padding-top: 4px; }

/* 🔴 BLANC SUR BLANC — mesuré à l'écran le 06/11/2026, sur un écran DÉJÀ
   EN PRODUCTION. Le bouton dit « Retirer » ; il était invisible.

   La règle générale `button { color: #fff }` s'applique à tout bouton ;
   poser un fond clair sans remettre la couleur du texte laisse le blanc.
   C'est le MÊME défaut que `.rr-annuler`, corrigé le matin même. */
.rr-retirer { min-height: 40px; padding: 0 12px; border: 1px solid var(--bordure);
  border-radius: 999px; background: #fff; color: var(--texte);
  font-size: .85rem; cursor: pointer; }
.rr-total { margin: 8px 0 14px; font-weight: 600; }

.rr-case { display: flex; gap: 10px; align-items: flex-start; margin: 14px 0;
  padding: 12px 14px; border-radius: 12px; background: var(--fond-carte);
  border: 1px solid var(--bordure); font-size: .88rem; }
.rr-case input { width: 22px; height: 22px; margin-top: 1px; flex: 0 0 auto; }

.rr-indice { min-height: 20px; margin: 8px 0; font-size: .88rem;
  color: var(--texte-doux); }
.rr-indice-refus { color: #9b2c2c; font-weight: 600; }

.rr-valider { width: 100%; padding: 14px; min-height: 52px; border: 0;
  border-radius: 999px; background: var(--accent); color: #fff; font-weight: 600;
  font-size: 1.05rem; cursor: pointer; }
.rr-valider:disabled { background: var(--bordure); color: var(--texte-doux);
  cursor: not-allowed; }

.rr-confirmation { margin: 14px 0; padding: 16px; border-radius: 14px;
  background: #fff; border: 2px solid var(--accent); }
.rr-confirmation-titre { margin: 0 0 6px; font-size: 1.05rem; font-weight: 700; }
.rr-confirmation-detail { margin: 0 0 10px; font-size: .95rem; }
.rr-confirmation-avis { margin: 0 0 14px; font-size: .85rem; color: var(--texte-doux); }
.rr-confirmation-boutons { display: flex; gap: 10px; }
.rr-confirmation-boutons button { flex: 1; min-height: 48px; border-radius: 999px;
  font-size: 1rem; font-weight: 600; cursor: pointer; }
/* 🔴 LE TEXTE ÉTAIT BLANC SUR BLANC (trouvé le 06/11/2026, à 375 px).
   La règle globale `button` pose `color: #fff` ; celle-ci ne changeait que
   le fond. Le bouton « Revenir » de la confirmation d'expédition — la seule
   sortie avant un envoi réel — était donc VIDE à l'écran, en production
   depuis le 3 novembre. Aucun test de DOM ne pouvait le dire. */
.rr-annuler { border: 1px solid var(--bordure); background: #fff;
  color: var(--texte); }
.rr-confirmer { border: 0; background: var(--accent); color: #fff; }
.rr-confirmer:disabled { background: var(--bordure); color: var(--texte-doux); }

/* ⚠️ UN BON INCOMPLET NE S'ANNONCE PAS COMME UNE REUSSITE : il n'a pas la
   meme couleur, et il dit ce qui manque. */
.rr-resultat { margin: 16px 0; padding: 14px 16px; border-radius: 12px;
  font-size: .92rem; }
.rr-resultat-titre { margin: 0 0 6px; font-size: 1.02rem; font-weight: 700; }
.rr-complet { background: #e8f6ec; border: 1px solid #9ad2ab; color: #1d5b2e; }
.rr-partiel { background: #fff4e5; border: 1px solid #f0c48a; color: #6b4a12; }
.rr-resultat-attente { margin: 10px 0 6px; }
.rr-resultat-liste { margin: 0; padding-left: 20px; font-variant-numeric: tabular-nums; }

/* ⚠️ STICKY, PAS FIXED — et ce n'est pas un detail de style.
   La coque a DEJA une barre d'onglets `position: fixed; bottom: 0; z-index: 40`
   sur mobile. Une barre fixee a `bottom: 0` passe donc DESSOUS : le bouton
   reste visible mais le clic ne l'atteint jamais, il part dans l'onglet. Un
   test navigateur l'a attrape ; aucun test serveur ne pouvait le dire.
   `sticky` la garde dans le flux, donc au-dessus des onglets — c'est ce que
   fait deja le bouton PDF de « Ma collection ». */
.mb-barre { position: sticky; bottom: 14px; display: flex; gap: 10px;
  margin-top: 18px; padding: 12px 0;
  background: var(--fond); }
.mb-retour, .mb-suite { min-height: 48px; padding: 12px 18px; border-radius: 999px;
  font-weight: 600; font-size: 1rem; cursor: pointer; }
.mb-retour { flex: 0 1 auto; border: 1px solid var(--bordure);
  background: var(--fond-carte); color: inherit; }
.mb-suite { flex: 1 1 auto; border: 0; background: var(--accent); color: #fff; }
.mb-suite:disabled { background: var(--bordure); color: var(--texte-doux);
  cursor: not-allowed; }

/* « Nouveau client » — visible d'emblee, pas cache derriere une recherche
   infructueuse : chez un client qu'il vient de rencontrer, Frederic SAIT
   qu'il n'est pas au fichier. */
.mb-nouveau { display: block; width: 100%; margin: 10px 0 0; padding: 13px;
  min-height: 48px; border: 1px dashed var(--accent); border-radius: 14px;
  background: transparent; color: var(--accent); font-weight: 600;
  font-size: 1rem; cursor: pointer; }

/* Le formulaire COURT. Pas une fiche CRM : sept champs, aucun obligatoire
   au-dela de l'identite, et rien d'administratif. */
.mb-formulaire { margin-top: 12px; padding: 14px; border: 1px solid var(--accent);
  border-radius: 16px; background: var(--fond-carte); }
.mb-formulaire-titre { font-weight: 600; margin-bottom: 12px; }
.mb-formulaire label { display: block; margin-bottom: 10px; font-size: .85rem;
  color: var(--texte-doux); }
/* 17px : en dessous de 16px, iOS zoome tout seul sur le champ. */
.mb-formulaire input { display: block; width: 100%; margin-top: 4px;
  padding: 11px 12px; font-size: 17px; border: 1px solid var(--bordure);
  border-radius: 10px; background: var(--fond); color: inherit; }
.mb-formulaire-duo { display: flex; gap: 10px; }
.mb-formulaire-duo label { flex: 1 1 0; }
.mb-formulaire-gestes { display: flex; gap: 10px; margin-top: 4px; }
.mb-formulaire-gestes .mb-retour { flex: 0 1 auto; }
.mb-formulaire-gestes .mb-ajouter { flex: 1 1 auto; margin-top: 0; }

.mb-cree { padding: 12px 14px; border-radius: 12px; font-weight: 600;
  background: var(--fond-carte); border: 1px solid var(--accent); }

/* ─── FILTRES DE « MA COLLECTION » : DEUX LIGNES DE SÉLECTEURS ───────────
   Le 25/09/2026, au premier essai réel d'Emmanuel sur iPhone : « les filtres
   Type / Pierre / Prix / Diamants occupent presque tout l'écran et certaines
   options sont coupées horizontalement ».

   Mesuré sur 390 px, les DEUX versions du gabarit, mêmes données :

       bloc des filtres   avant  372 px      après   96 px
       bas du 1ᵉʳ bijou   avant ~834 px      après  558 px

   L'écran fait 844 px, dont la barre d'onglets mange le bas : avant, aucun
   bijou ne tenait entièrement à l'écran. Et ces 372 px sont mesurés sur trois
   pièces de démonstration ; la valise de Frédéric en porte 78.

   ⚠️ TROIS SÉLECTEURS PAR LIGNE A ÉTÉ ESSAYÉ ET REFUSÉ : les libellés
   tombaient à 114 px et se lisaient « Boucles… », « Pierre n… », « 500 à 1 … ».
   Deux par ligne donnent 175 px, et se lisent. Emmanuel : « je préfère deux
   lignes propres et lisibles à trois cases trop étroites ».

   ⚠️ NE PAS SUPPRIMER `.mc-axe` / `.mc-bande` / `.mc-pastille` PLUS HAUT :
   « Stocks représentants » s'en sert toujours, et « À compléter » ici aussi. */
.mc-duo { display: flex; gap: 8px; margin-bottom: 8px; }
.mc-champ { flex: 1 1 0; min-width: 0; position: relative; }
/* 16 px : en dessous, iOS zoome tout seul sur le champ et décale la page. */
.mc-champ select { width: 100%; appearance: none; -webkit-appearance: none;
  padding: 11px 26px 11px 11px; font-size: 16px; border: 1px solid var(--bordure);
  border-radius: 10px; background: var(--fond-carte); color: inherit;
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
.mc-champ::after { content: "\25BE"; position: absolute; right: 9px; top: 50%;
  transform: translateY(-50%); color: var(--texte-doux); pointer-events: none;
  font-size: .8rem; }
.mc-champ select.choisi { border-color: var(--accent); color: var(--accent);
  font-weight: 600; }

.mc-plus { flex: 0 0 auto; padding: 11px 13px; min-height: 44px;
  border: 1px solid var(--bordure); border-radius: 10px;
  background: var(--fond-carte); color: var(--texte-doux); font-size: .88rem;
  white-space: nowrap; cursor: pointer; }
.mc-plus.choisi { border-color: var(--accent); color: var(--accent);
  font-weight: 600; }
.mc-repli { margin-bottom: 8px; display: flex; flex-direction: column; gap: 8px; }

/* CE QUI EST FILTRÉ, DIT EN CLAIR : un sélecteur fermé se lit mal du coin de
   l'œil ; cette ligne-ci se lit, et « Tout afficher » rouvre tout d'un geste. */
.mc-actifs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 10px; font-size: .85rem; }
.mc-jeton { padding: 5px 10px; border-radius: 999px; background: var(--accent);
  color: #fff; font-weight: 600; }
.mc-tout { border: 0; background: transparent; color: var(--accent);
  text-decoration: underline; font-size: .85rem; cursor: pointer; padding: 5px 0; }

/* ── LE DOSSIER COMMERCIAL D'UN REPRESENTANT (16/10/2026) ──────────────────
   Emmanuel : « Prevois un affichage et un telechargement simples sur iPhone ».
   Tout ce qui se touche fait 44 px de haut au minimum : c'est la cible qu'un
   pouce atteint sans viser. Rien n'est cache derriere un menu — sur un
   telephone, un geste cache est un geste perdu. */
.do-entete { padding: 14px 0 6px; }
.do-titre { font-size: 1.35rem; font-weight: 700; }
.do-societe { color: var(--texte-doux); font-size: .9rem; }
.do-observe { margin-top: 6px; padding: 6px 10px; border-radius: 8px;
  background: var(--accent); color: #fff; font-size: .85rem; }

.do-onglets { display: flex; gap: 4px; overflow-x: auto; margin: 10px 0;
  -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.do-onglets::-webkit-scrollbar { display: none; }
.do-onglet { flex: 1 0 auto; min-height: 44px; padding: 0 14px; border: 0;
  border-radius: 10px; background: var(--fond-doux); color: var(--texte);
  font-size: .95rem; font-weight: 600; cursor: pointer; white-space: nowrap; }
.do-onglet-actif { background: var(--accent); color: #fff; }

.do-recherche { margin-bottom: 10px; border: 1px solid var(--bordure);
  border-radius: 10px; }
.do-recherche > summary { min-height: 44px; display: flex; align-items: center;
  padding: 0 12px; cursor: pointer; font-weight: 600; }
/* ⬅️ DEUX COLONNES SUR TÉLÉPHONE — 23/10/2026.
   Cinq champs de 44 px en une seule colonne font ≈ 430 px une fois le bloc
   ouvert : la liste passait sous la ligne de flottaison et il fallait
   défiler pour voir le premier résultat. Emmanuel : « Après une recherche,
   les résultats doivent être immédiatement visibles, sans défilement
   excessif. »
   ⚠️ L'adresse et les dates restent lisibles à deux par ligne ; au-dessous
   de 340 px on retombe à une colonne plutôt que de tronquer. */
/* ⛔ `minmax(0, 1fr)` ET PAS `1fr`. Un `1fr` vaut `minmax(auto, 1fr)` : la
   colonne ne descend jamais sous la largeur NATURELLE de son contenu, et un
   `<input>` en réclame environ 200 px. Mesuré : un champ débordait à 471 px
   sur un écran de 390. Le contrôle du pouce l'a vu au premier passage. */
.do-champs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px; padding: 0 12px 12px; }
.do-champs label { min-width: 0; }
.do-champs input { width: 100%; min-width: 0; box-sizing: border-box; }
.do-champs .do-bouton { grid-column: span 2; }
@media (max-width: 339px) {
  .do-champs { grid-template-columns: 1fr; }
  .do-champs .do-bouton { grid-column: auto; }
}
.do-champs label { display: grid; gap: 4px; font-size: .8rem;
  color: var(--texte-doux); }
.do-champs input { min-height: 44px; padding: 0 10px; font-size: 1rem;
  border: 1px solid var(--bordure); border-radius: 8px; background: var(--fond);
  color: var(--texte); }
.do-bouton { min-height: 44px; border: 0; border-radius: 10px;
  background: var(--accent); color: #fff; font-size: 1rem; font-weight: 600;
  cursor: pointer; }
.do-bouton-discret { background: var(--fond-doux); color: var(--texte); }
.do-bouton:disabled { opacity: .45; cursor: default; }

.do-compteurs { display: flex; gap: 8px; margin-bottom: 10px; }
.do-compteur { flex: 1; padding: 10px 8px; border-radius: 10px;
  background: var(--fond-doux); text-align: center; }
.do-nombre { display: block; font-size: 1.3rem; font-weight: 700; }
.do-libelle { font-size: .72rem; color: var(--texte-doux); }

/* LA RESERVE. Elle doit se LIRE, pas se deviner : c'est elle qui dit que
   97 % des operations n'ont aucun document. */
.do-reserve { margin: 0 0 10px; padding: 9px 11px; border-radius: 8px;
  background: var(--avertissement-fond, #fff4e5);
  color: var(--avertissement-texte, #6b4300); font-size: .85rem; }

.do-ligne { padding: 11px 12px; margin-bottom: 8px; border-radius: 10px;
  background: var(--fond-doux); border-left: 4px solid transparent; }
.do-entree { border-left-color: #2e7d32; }
.do-sortie { border-left-color: #b3531d; }
.do-ligne-annulee { opacity: .55; }
.do-ligne > header { display: flex; align-items: center; gap: 8px; }
.do-reference-lien { border: 0; background: transparent; padding: 0;
  font: inherit; font-weight: 700; color: var(--accent); cursor: pointer;
  text-decoration: underline; min-height: 28px; }
.do-quantite { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.do-annulee { font-size: .7rem; font-weight: 700; color: #b3261e; }
.do-corps { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px;
  font-size: .85rem; color: var(--texte-doux); }
.do-pied { margin-top: 5px; font-size: .8rem; }
.do-doc { font-weight: 600; }
.do-doc-externe { color: var(--texte-doux); }
/* ⛔ L'ABSENCE DE DOCUMENT SE VOIT. La masquer ferait croire a un dossier
   complet alors que 2 176 operations sur 2 242 n'en ont aucun. */
.do-doc-absent { color: #8a6d3b; font-style: italic; }
.do-trombone { font-size: .8rem; }

/* ── PAR FACTURE / PAR CLIENT / PAR BIJOU ─────────────────────────────────
   Emmanuel, 21/10/2026 : « les ventes apparaissent bijou par bijou, ce qui
   est particulièrement peu pratique lorsqu'une facture comporte plusieurs
   dizaines de références ». Une seule en compte 53.

   ⚠️ 44 px est le minimum qu'un pouce atteint sans viser. En dessous, on
   tape à côté et on croit que le logiciel ne répond pas. */
.do-modes {
  display: flex; gap: .4rem; margin: .1rem 0 .6rem;
}
.do-mode {
  flex: 1 1 0; min-height: 44px; padding: .4rem .3rem;
  border: 1px solid var(--bordure, #d8d8dd); border-radius: 10px;
  background: var(--fond-doux, #f6f6f8); color: inherit;
  font-size: .85rem; font-weight: 600; cursor: pointer;
}
.do-mode-actif {
  background: var(--accent, #7a5c22); color: #fff;
  border-color: var(--accent, #7a5c22);
}

/* La facture repliée : UNE ligne par facture, et le détail au toucher. */
.do-facture, .do-client-bloc {
  border: 1px solid var(--bordure, #d8d8dd); border-radius: 12px;
  margin: 0 0 .55rem; background: var(--fond, #fff); overflow: hidden;
}
.do-facture > summary, .do-client-bloc > summary {
  /* ⚠️ `list-style: none` seul ne suffit pas sur Safari iOS : il faut aussi
     `::-webkit-details-marker`, sinon le triangle reste et décale le texte. */
  list-style: none; cursor: pointer;
  min-height: 44px; padding: .6rem .8rem;
}
.do-facture > summary::-webkit-details-marker,
.do-client-bloc > summary::-webkit-details-marker { display: none; }
.do-facture > summary::after, .do-client-bloc > summary::after {
  content: "▸"; float: right; margin-top: -1.4rem; opacity: .5;
}
.do-facture[open] > summary::after,
.do-client-bloc[open] > summary::after { content: "▾"; }
.do-facture-titre { font-weight: 700; font-size: .95rem; }
.do-facture-client { font-size: .88rem; margin-top: .1rem; }
.do-facture-chiffres {
  font-size: .8rem; opacity: .75; margin-top: .15rem;
}
.do-facture-corps {
  padding: .2rem .8rem .7rem; border-top: 1px solid var(--bordure, #e6e6ea);
}
/* Un client contient ses factures : on décale pour que l'emboîtement se
   voie sans compter les bordures. */
.do-client-bloc .do-facture { margin-left: .5rem; }

@media (max-width: 420px) {
  /* Trois boutons côte à côte sous 420 px donneraient trois demi-cibles. */
  .do-modes { flex-wrap: wrap; }
  .do-mode { flex: 1 1 45%; }
  .do-facture-client { font-size: .84rem; }
}

/* ── OUVRIR LA PIÈCE JUSTIFICATIVE ───────────────────────────────────────
   Emmanuel ouvre le dossier sur un iPhone : la cible doit se toucher sans
   viser. 44 px est le minimum qu'Apple donne pour un doigt — en dessous, on
   tape à côté et on croit que ça ne marche pas. */
.do-piece {
  display: inline-flex; align-items: center; gap: .3rem;
  min-height: 44px; padding: .35rem .7rem; margin: .2rem .25rem .2rem 0;
  border: 1px solid var(--bordure, #d8d8dd); border-radius: 10px;
  background: var(--fond-doux, #f6f6f8); color: inherit;
  font-size: .82rem; text-decoration: none; line-height: 1.2;
}
.do-piece:active { background: var(--fond-actif, #e9e9ee); }
.do-piece-ecart { color: #b25c00; font-weight: 600; }

@media (max-width: 420px) {
  /* Sur un écran étroit la pièce prend toute la largeur : deux boutons
     côte à côte deviendraient deux demi-cibles. */
  .do-piece { display: flex; width: 100%; margin-right: 0; }
}
/* ══ L'HISTOIRE D'UN BROUILLON D'IMPORT — 23/10/2026 ══════════════════════
   Emmanuel : « une personne peut importer, une autre corriger et une
   troisième valider ». Le bloc dit qui a fait quoi, et quand.

   ⚠️ UNE INTERVENTION SE LIT DE HAUT EN BAS SUR TÉLÉPHONE, en colonnes sur
      ordinateur. Un tableau à trois colonnes sur 390 px tronquerait l'auteur
      — c'est la faute « drey EFFENBACHER » du 19/10. */
.bl-historique {
  margin-top: 12px; border: 1px solid var(--bordure, #e4ded7);
  border-radius: 10px;
}
.bl-historique > summary {
  min-height: 44px; display: flex; align-items: center; padding: 0 12px;
  cursor: pointer; font-weight: 600;
}
.bl-intervention {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 12px; border-top: 1px solid var(--bordure, #e4ded7);
  font-size: .82rem;
}
.bl-quand { color: var(--texte-doux, #6b6b6b); font-size: .76rem; }
.bl-geste { font-weight: 600; }
.bl-auteur { color: var(--texte-doux, #6b6b6b); }
@media (min-width: 901px) {
  /* Sur un écran large, les trois informations tiennent sur une ligne et se
     lisent en colonnes alignées. */
  .bl-intervention {
    flex-direction: row; align-items: baseline; gap: 14px;
  }
  .bl-quand { flex: 0 0 150px; }
  .bl-geste { flex: 1 1 auto; }
  .bl-auteur { flex: 0 0 200px; text-align: right; }
}

/* ══ L'ÉCRAN DU DOSSIER SUR ORDINATEUR — 23/10/2026 ═══════════════════════
   Emmanuel : « Adapter les en-têtes, les onglets et les compteurs à chaque
   format d'écran. »

   ⛔ CECI NE TOUCHE PAS LA NAVIGATION PRINCIPALE : uniquement l'intérieur de
   l'écran « Mon dossier ». La refonte des menus n'est pas décidée. */
@media (min-width: 901px) {
  /* ① L'EN-TÊTE SUR UNE LIGNE, et les compteurs À CÔTÉ plutôt que dessous :
        sur un écran large, les empiler gâche une bande entière. */
  .do-entete {
    display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
    padding: 10px 0 4px;
  }
  .do-societe { margin-left: auto; font-size: 1rem; }
  .do-observe { flex-basis: 100%; }

  /* ② LES ONGLETS NE DÉFILENT PLUS : ils tiennent tous, et ne s'étirent pas
        sur toute la largeur — cinq boutons de 240 px seraient ridicules. */
  .do-onglets { overflow: visible; }
  .do-onglet { flex: 0 0 auto; }

  /* ③ LES MODES SE DISTINGUENT DES ONGLETS. Mêmes formes, mêmes couleurs :
        on ne savait pas lesquels commandaient quoi. Ici ils deviennent un
        sélecteur compact, visuellement rattaché à la liste. */
  .do-modes {
    display: inline-flex; gap: 0; margin: 2px 0 10px;
    border: 1px solid var(--bordure); border-radius: 10px; overflow: hidden;
  }
  .do-mode {
    border: 0; border-right: 1px solid var(--bordure); border-radius: 0;
    background: var(--fond); padding: 0 14px; min-height: 36px;
  }
  .do-mode:last-child { border-right: 0; }

  /* ④ LA RECHERCHE EST PERMANENTE : « Sur ordinateur, filtres accessibles
        directement. » Le dépliant disparaît, les champs tiennent sur une
        ligne. */
  .do-recherche > summary { display: none; }
  .do-champs {
    display: flex; flex-wrap: wrap; align-items: end; gap: 10px;
    padding: 10px 12px;
  }
  .do-champs label { flex: 1 1 150px; }
  .do-champs input { min-height: 36px; }
  .do-champs .do-bouton { grid-column: auto; min-height: 36px; padding: 0 16px; }

  /* ⑤ LES COMPTEURS NE PRENNENT PLUS TOUTE LA LARGEUR. */
  .do-compteurs { display: inline-flex; }
  .do-compteur { flex: 0 0 auto; min-width: 120px; }
}

/* ══ LE TABLEAU DU DOSSIER — 23/10/2026 ═══════════════════════════════════
   Emmanuel : « Sur ordinateur : exploitation de l'espace disponible,
   tableaux lisibles […] et gestion rapide de nombreuses opérations. »

   ⚠️ CES RÈGLES NE S'APPLIQUENT QU'AU-DESSUS DE 900 px. Le téléphone garde
      ses cartes — c'est le même seuil que la navigation, pour qu'il n'existe
      pas de largeur où l'en-tête est celui du bureau et le contenu celui du
      téléphone. */
@media (min-width: 901px) {
  .do-tableau {
    width: 100%; border-collapse: collapse; font-size: .86rem;
    margin-top: 6px;
  }
  .do-tableau th, .do-tableau td {
    padding: 6px 10px; text-align: left; vertical-align: top;
    border-bottom: 1px solid var(--bordure, #e4ded7);
  }
  .do-tableau thead th {
    position: sticky; top: 0; z-index: 1;
    background: var(--surface, #fff);
    border-bottom: 2px solid var(--bordure, #e4ded7);
    padding: 0;
  }
  /* L'en-tête EST un bouton : il se clique à la souris comme au clavier.
     Un tri qu'on ne peut atteindre qu'à la souris exclut une partie des
     utilisateurs. */
  .do-tri {
    width: 100%; padding: 7px 10px; background: none; border: 0;
    font: inherit; font-weight: 700; text-align: left; cursor: pointer;
    color: inherit;
  }
  .do-tri:hover { background: #f6f2ed; }
  .do-tri-actif { color: #8a6d3b; }
  .do-td-nombre { text-align: right; font-variant-numeric: tabular-nums; }
  .do-tableau tbody tr:hover { background: #faf7f3; }
  .do-tr-annulee { opacity: .55; text-decoration: line-through; }
  /* Les limites d'une ligne passent SOUS elle, sur toute la largeur : les
     mettre dans une colonne les tronquerait, et c'est précisément ce qu'on
     ne veut pas masquer. */
  .do-tr-limites td {
    padding-top: 0; font-size: .76rem; opacity: .75;
    border-bottom: 1px solid var(--bordure, #e4ded7);
  }
  /* ⛔ La carte reste une carte : sur grand écran elle sert d'en-tête de
     groupe (une facture, un client), et c'est SON contenu qui devient un
     tableau. */
  .do-facture, .do-client-bloc { max-width: none; }
}

/* LA PASTILLE DU JUSTIFICATIF — 23/10/2026.
   Trois situations, trois teintes, et un libellé lisible sans la couleur :
   une information portée par la seule couleur n'existe pas pour qui ne la
   distingue pas. */
.do-justif {
  display: inline-block; margin-left: 6px; padding: 1px 7px;
  border-radius: 999px; font-size: .7rem; white-space: nowrap;
  border: 1px solid currentColor; opacity: .85;
}
.do-justif-lmc_suite { color: #2f6f4f; }
.do-justif-oxygene_ouvrable { color: #8a6d3b; }
.do-justif-oxygene_numero { color: #8a6d3b; opacity: .7; }
.do-justif-aucun { color: #8a8a8a; }
.do-limites { margin: 6px 0 0; padding-left: 16px; font-size: .78rem;
  color: var(--texte-doux); }
.do-limites-tete { margin: 8px 0 12px; padding: 9px 11px 9px 26px;
  border-radius: 8px; background: var(--avertissement-fond, #fff4e5);
  color: var(--avertissement-texte, #6b4300); }

.do-attente-bloc, .do-ecarts, .do-detenteurs { margin-bottom: 14px; }
.do-attente-bloc h2, .do-ecarts h2, .do-detenteurs h2 { font-size: .95rem;
  margin: 0 0 6px; }
.do-bon-attente, .do-ecart { padding: 11px 12px; margin-bottom: 8px;
  border-radius: 10px; background: var(--fond-doux);
  border-left: 4px solid var(--accent); }
.do-ecart { border-left-color: #b3261e; }
.do-bon-attente > header, .do-ecart > header { font-weight: 700; }
.do-note { margin: 5px 0 0; font-size: .8rem; color: var(--texte-doux); }

/* ── CONFIRMER UNE RÉCEPTION (03/11/2026) ─────────────────────────────────
   ⚠️ TOUT EN COLONNE, Y COMPRIS SUR GRAND ÉCRAN. Une référence et son champ
      posés côte à côte tiennent à 1440 px et se chevauchent à 375 — or c'est
      sur un iPhone que ce geste se fait, un colis ouvert sur les genoux. */
/* Le rappel du dernier bon OXYGENE, sous son champ (04/11/2026). */
.rr-aide { display: block; margin-top: 4px; font-size: .78rem;
  color: var(--texte-doux); }

.do-recu-lignes { list-style: none; margin: 10px 0 0; padding: 0; }
.do-recu-ligne { display: flex; flex-direction: column; gap: 2px;
  padding: 9px 10px; margin-bottom: 7px; border-radius: 8px;
  background: var(--fond); }
.do-recu-ref { font-weight: 700; font-variant-numeric: tabular-nums; }
.do-recu-designation { font-size: .78rem; color: var(--texte-doux); }
.do-recu-champ { display: flex; flex-direction: column; gap: 3px;
  margin-top: 6px; font-size: .8rem; color: var(--texte-doux); }
/* 44 px de haut : la cible tactile recommandée. En dessous, on tape à côté. */
.do-recu-champ input { min-height: 44px; padding: 8px 10px; font-size: 1rem;
  border: 1px solid var(--bordure); border-radius: 8px; background: var(--fond);
  color: inherit; width: 100%; box-sizing: border-box; }
.do-recu-reserves { margin-top: 10px; }
.do-recu-valider { margin-top: 12px; width: 100%; min-height: 46px;
  border: 0; border-radius: 10px; background: var(--accent); color: #fff;
  font-size: 1rem; font-weight: 700; cursor: pointer; }
.do-recu-valider:disabled { opacity: .6; cursor: default; }
.do-recu-message { margin: 9px 0 0; font-size: .85rem; }
.do-recu-ok { color: #1b5e20; font-weight: 600; }
.do-recu-refus { color: #b3261e; font-weight: 600; }
.do-detenteur { display: flex; gap: 8px; align-items: baseline;
  padding: 8px 10px; border-radius: 8px; background: var(--fond-doux);
  margin-bottom: 5px; font-size: .88rem; }
.do-detenteur > span:nth-child(2) { margin-left: auto; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.do-le-sien { outline: 2px solid var(--accent); }
.do-situation { font-size: .75rem; color: var(--texte-doux); }

.do-pages { display: flex; gap: 8px; align-items: center; margin: 12px 0 24px; }
.do-pages > span { flex: 1; text-align: center; font-size: .85rem;
  color: var(--texte-doux); }
.do-pages .do-bouton { flex: 0 0 auto; padding: 0 14px; }

.do-vide, .do-attente { padding: 20px 12px; text-align: center;
  color: var(--texte-doux); }
/* ⛔ UN REFUS N'EST PAS UNE LISTE VIDE. Il se lit comme une erreur. */
.do-erreur { padding: 14px 12px; border-radius: 10px;
  background: var(--erreur-fond, #fdecea); color: var(--erreur-texte, #8c1d18);
  font-size: .9rem; }

/* ── LE BANDEAU « VOIR COMME » (16/10/2026) ───────────────────────────────
   Emmanuel : « Prevoir un bandeau permanent et visible […] Le bandeau ne doit
   pas masquer les fonctions de l'application. »

   D'ou `position: static` et non `fixed` : il POUSSE le contenu vers le bas
   au lieu de flotter par-dessus. Un ruban flottant aurait recouvert le
   premier bouton de chaque ecran sur un iPhone. */
.vue-observee { display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; background: #8c1d18; color: #fff;
  font-size: .9rem; flex-wrap: wrap; }
.vue-observee-texte { display: flex; align-items: baseline; gap: 8px;
  flex-wrap: wrap; min-width: 0; flex: 1; }
.vue-observee-texte strong { font-weight: 700; }
/* « Lecture seule » doit se lire d'un coup d'oeil : c'est la seule chose qui
   empeche de croire qu'on travaille normalement. */
.vue-observee-mention { padding: 2px 8px; border-radius: 999px;
  background: rgba(255, 255, 255, .22); font-weight: 700;
  text-transform: uppercase; font-size: .72rem; letter-spacing: .04em; }
.vue-observee-societe { opacity: .85; font-size: .82rem; }
/* 44 px : la cible qu'un pouce atteint sans viser. Quitter la vue est le
   geste qu'on cherche quand on s'est trompe — il ne doit pas se rater. */

/* ── LA PORTE DU DOSSIER COMMERCIAL ───────────────────────────────────────
   Quatre cibles, chacune à 60 px : un représentant ouvre cela debout, dans
   une bijouterie, d'une seule main.                                        */
.tdb-dossier-liens {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px; margin: 10px 0 22px;
}
.tdb-dossier-lien {
  display: flex; flex-direction: column; justify-content: center;
  min-height: 60px; padding: 12px 14px;
  background: #fff; border: 1px solid var(--trait, #e4ded7);
  border-radius: 12px; text-decoration: none; color: inherit;
  -webkit-tap-highlight-color: transparent;
}
.tdb-dossier-lien:active { background: #f6f2ed; }
/* QUELLE MAISON ? Écrit au-dessus de la porte, jamais deviné.
   ⚠️ `display: block` sur la note, et PAS un flex sans retour à la ligne :
      le 19/10 « drey EFFENBACHER » s'est fait couper par un flex sans `wrap`.
      Sur un téléphone, une carte se lit de HAUT EN BAS. */
.tdb-dossier-maison { display: block; margin: 8px 0 0; }
.tdb-dossier-note {
  display: block; margin-top: 3px;
  font-weight: 400; font-size: .76rem; opacity: .7;
}
.tdb-dossier-titre { font-weight: 700; font-size: .95rem; }
.tdb-dossier-sous { font-size: .76rem; opacity: .7; margin-top: 3px; }
@media (max-width: 420px) {
  /* Sur un téléphone étroit, une colonne : deux libellés tronqués valent
     moins qu'un seul lisible. */
  .tdb-dossier-liens { grid-template-columns: 1fr; }
}

/* ── ENTRER DANS LA VUE D'UN AGENT ────────────────────────────────────────
   Emmanuel, 18/10 : « Le bouton doit être simple à trouver et à utiliser »,
   et « il faut que cela fonctionne correctement sur iPhone ».
   Pleine largeur, 56 px de haut — bien au-delà des 44 px recommandés par
   Apple — et posé juste sous le nom de l'homme qu'on va regarder, pour qu'on
   ne puisse pas se tromper de personne.                                    */
.sr-observer {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 56px; margin: 12px 0 16px;
  padding: 10px 16px; border: 0; border-radius: 12px;
  background: #1d3f73; color: #fff;
  font-family: inherit; font-size: 1rem; text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;  /* pas de flash gris sur iOS */
}
.sr-observer:active { background: #16325c; }
.sr-observer:disabled { opacity: .6; cursor: default; }
.sr-observer:focus-visible { outline: 3px solid #ffd27f; outline-offset: 2px; }
.sr-observer-oeil { font-size: 1.35rem; line-height: 1; flex-shrink: 0; }
.sr-observer-texte { display: block; }
.sr-observer-texte strong { font-weight: 700; }
/* La mention de lecture seule est DANS le bouton : on la lit avant
   d'appuyer, pas après. */
.sr-observer-sous {
  display: block; margin-left: auto; text-align: right;
  font-size: .78rem; opacity: .85; max-width: 42%;
}
@media (max-width: 480px) {
  /* Sur un téléphone étroit, la mention passe sous le libellé plutôt que de
     le comprimer : deux lignes lisibles valent mieux qu'une illisible. */
  .sr-observer { flex-wrap: wrap; }
  .sr-observer-sous { margin-left: 0; text-align: left; max-width: 100%;
                      width: 100%; padding-left: 34px; }
}

.vue-observee-sortie { min-height: 44px; padding: 0 14px; border: 0;
  border-radius: 10px; background: #fff; color: #8c1d18;
  font-size: .9rem; font-weight: 700; cursor: pointer; flex: 0 0 auto; }
.vue-observee-sortie:disabled { opacity: .6; cursor: default; }

/* Une vue qui n'est PAS fidele le dit, sous le bandeau et dans sa couleur :
   un avertissement de la meme teinte que le ruban se lit comme sa suite, pas
   comme une alerte etrangere. */
.vue-observee-reserve { padding: 9px 14px; background: #6d1612; color: #fff;
  font-size: .82rem; line-height: 1.35; }
.vue-observee-reserve strong { font-weight: 700; }

/* ══ ÉTAT DES STOCKS ET ÉCARTS (25/10/2026) ════════════════════════════════
   Une ligne se lit de HAUT EN BAS sur téléphone, en colonnes sur ordinateur.
   ⛔ Pas de tableau à cinq colonnes : sur 390 px il tronque ses étiquettes,
   et « drey EFFENBACHER » nous a déjà appris ce que cela coûte.           */
.sd-cartes { display: grid; gap: 0.75rem; }
.sd-carte {
  border: 1px solid var(--bordure); border-radius: 8px;
  padding: 0.75rem 0.9rem; background: var(--fond-carte, transparent);
}
.sd-carte h3 { margin: 0 0 0.5rem; font-size: 1rem; }
.sd-l {
  display: flex; justify-content: space-between; gap: 0.75rem;
  padding: 0.2rem 0; font-size: 0.92rem;
}
.sd-l span { color: var(--texte-discret); min-width: 0; }
.sd-l b { white-space: nowrap; }
.sd-note {
  margin-top: 0.5rem; font-size: 0.85rem; color: var(--texte-discret);
  border-top: 1px dashed var(--bordure); padding-top: 0.4rem;
}
/* ⚠️ UN TROU N'EST PAS UN ZÉRO. Il se voit, et il se lit en français. */
.sd-trou {
  margin: 0.4rem 0; padding: 0.5rem 0.7rem; border-radius: 6px;
  background: var(--fond-avertissement, #fff6e5);
  border: 1px solid var(--bordure); font-size: 0.9rem;
}
.sd-avert { font-size: 0.86rem; color: var(--texte-discret); margin: 0.2rem 0 0.7rem; }
.sd-ligne {
  display: flex; flex-direction: column; gap: 0.15rem;
  padding: 0.45rem 0; border-bottom: 1px solid var(--bordure);
}
.sd-ou { font-size: 0.93rem; }
.sd-q { font-size: 0.9rem; font-weight: 600; }
.sd-d { font-size: 0.82rem; color: var(--texte-discret); }
.sd-compte {
  font-size: 0.8rem; padding: 0.1rem 0.45rem; border-radius: 999px;
  background: var(--bordure); vertical-align: middle;
}
.sd-alerte { color: var(--texte-alerte, #a8324a); }
.sd-constat { color: var(--texte-discret); }

/* L'ordinateur a de la place : on met les trois valeurs en colonnes. La
   bascule à 901 px est la MÊME que partout ailleurs — une seconde valeur
   ferait deux règles pour une seule idée. */
@media (min-width: 901px) {
  .sd-cartes { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }
  .sd-ligne {
    flex-direction: row; align-items: baseline; gap: 1rem;
  }
  .sd-ou { flex: 1 1 auto; min-width: 0; }
  /* ⚠️ 9rem coupait « 2 393 pièces détenues » en deux lignes : une colonne
     qui se casse donne l'air d'un défaut là où il n'y en a pas. */
  .sd-q  { flex: 0 0 11rem; text-align: right; }
  .sd-d  { flex: 0 0 15rem; }
}
