/* ===================================================================
   qc-views.css — habillage des vues liste et fiche de l'administration.

   Va de pair avec `qc-views.js`. Même contrat : aucun vocabulaire métier,
   aucune dépendance, **copiable tel quel** dans Qodo Clock standard. C'est
   pour ça que ce n'est ni dans `input.css` (source Tailwind, fichier partagé
   qui conflitera à chaque sync avec le standard) ni dans `custom.css` : un
   fichier à part se déplace d'un dépôt à l'autre en une fois.

   CSS simple, sans `@apply` : le fichier n'a pas à traverser la compilation
   Tailwind pour fonctionner.

   Les deux couleurs de la marque passent par des variables — un dépôt qui
   les redéfinit sur `:root` récupère tout l'habillage sans toucher au reste.
   =================================================================== */

:root {
  --qc-accent: #34988D;
  --qc-accent-doux: #e8f5f4;
  --qc-trait: #e5e7eb;
  --qc-trait-doux: #f1f3f5;
  --qc-texte: #374151;
  --qc-texte-doux: #9ca3af;
  --qc-fond: #ffffff;
  --qc-survol: #f8fafb;
}

/* ----- Barre de contrôle : la même à chaque onglet, aux mêmes places ----- */

/* Grille en trois colonnes plutôt qu'un `flex` : avec `1fr auto 1fr`, la
   colonne du milieu est centrée sur la **zone de contenu**, quelle que soit
   la largeur des groupes de gauche et de droite. En flex, la recherche se
   contentait de prendre la place restante — donc elle penchait du côté du
   groupe le plus étroit, ce qui se voyait. */
.qc-cp {
  display: grid; grid-template-columns: 1fr minmax(0, 30rem) 1fr;
  align-items: center; gap: .75rem; margin-bottom: 1rem;
}
/* La sélection porte plus de commandes que la recherche : la piste du milieu
   s'élargit plutôt que d'écraser ses boutons. */
.qc-cp.qc-cp-large { grid-template-columns: 1fr minmax(0, 42rem) 1fr; }
.qc-cp-gauche { display: flex; align-items: center; gap: .5rem; min-width: 0; }
/* `position: relative` : le panneau dépliant de la recherche s'y accroche. */
.qc-cp-centre { position: relative; display: flex; gap: .5rem; width: 100%; }
.qc-cp-droite { display: flex; align-items: center; gap: .5rem; justify-self: end; }

/* En dessous de 60rem, les trois groupes s'empilent : la recherche prend toute
   la largeur, les commandes restent atteignables au pouce. */
@media (max-width: 60rem) {
  .qc-cp, .qc-cp.qc-cp-large { grid-template-columns: minmax(0, 1fr); }
  .qc-cp-droite { justify-self: start; }
  .qc-cp-gauche { flex-wrap: wrap; }
}

/* Fil d'Ariane — le premier segment ramène toujours à la liste. */
.qc-fil { display: flex; align-items: center; gap: .4rem; font-size: .95rem; min-width: 0; }
/* `nowrap` sur les segments : un nom d'équipe un peu long se coupait en deux
   lignes et faisait grandir la barre de commande d'un cran. Ce qui dépasse
   s'abrège, le titre complet reste dans l'infobulle. */
.qc-fil-seg, .qc-fil-repli {
  display: inline-flex; align-items: center; gap: .4rem;
  min-width: 0; white-space: nowrap;
}
.qc-fil-seg .qc-fil-lien, .qc-fil-seg .qc-fil-actuel {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 14rem;
}

/* Un nom qui mène ailleurs. Souligné au survol seulement : dans un tableau,
   une colonne entière de texte souligné se lit comme un formulaire à moitié
   rempli. */
.qc-lien-interne {
  border: none; background: none; padding: 0; cursor: pointer;
  font-weight: 700; color: var(--qc-texte); text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.qc-lien-interne:hover { color: var(--qc-accent); text-decoration: underline; }
/* Le même lien, au fil d'une phrase : il en prend la taille et la couleur. */
.qc-lien-inline {
  font-size: inherit; font-weight: 700; color: var(--qc-accent);
  text-decoration: underline; white-space: normal;
}
.qc-fil-lien {
  color: var(--qc-texte-doux); font-weight: 600;
  background: none; border: none; padding: 0; cursor: pointer;
}
.qc-fil-lien:hover { color: var(--qc-accent); text-decoration: underline; }
.qc-fil-sep { color: var(--qc-texte-doux); }
.qc-fil-actuel {
  font-weight: 800; color: #1f2937;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ----- Boîte de recherche à facettes -----
   Centrée et bornée en largeur : au-delà d'environ 30rem elle cesse d'aider
   et déséquilibre la barre. Les facettes vivent DANS la boîte, comme dans
   Odoo — un filtre actif doit se voir là où on l'a posé, sinon la liste
   paraît vide sans raison. */

.qc-recherche {
  display: flex; align-items: center; gap: .35rem; flex-wrap: wrap;
  width: 100%; margin: 0;
  padding: .3rem .35rem .3rem .6rem;
  border: 1px solid var(--qc-trait); border-radius: .625rem;
  background: var(--qc-fond);
}
.qc-recherche:focus-within { border-color: var(--qc-accent); }
.qc-recherche-loupe {
  width: .9rem; height: .9rem; color: var(--qc-texte-doux); flex-shrink: 0;
}
.qc-recherche input {
  flex: 1 1 6rem; min-width: 4rem; border: none; outline: none; background: none;
  font-size: .875rem; color: var(--qc-texte); padding: .2rem 0;
}
.qc-recherche-fleche {
  flex-shrink: 0; width: 1.4rem; height: 1.4rem; border: none; background: none;
  color: var(--qc-texte-doux); cursor: pointer; border-radius: .35rem;
  display: flex; align-items: center; justify-content: center;
}
.qc-recherche-fleche:hover { background: var(--qc-trait-doux); color: var(--qc-texte); }

.qc-facette {
  display: inline-flex; align-items: stretch; overflow: hidden;
  border-radius: .35rem; font-size: .75rem; font-weight: 700;
  background: var(--qc-accent-doux); color: var(--qc-accent); max-width: 18rem;
}
.qc-facette-label {
  padding: .15rem .4rem; background: var(--qc-accent); color: #fff;
  display: flex; align-items: center; white-space: nowrap;
}
.qc-facette-valeur {
  padding: .15rem .4rem; display: flex; align-items: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ── Icônes ────────────────────────────────────────────────────────────────
   Toutes au trait, dans la couleur du texte qui les porte, dimensionnées en
   `em` pour suivre la taille de ce texte.

   Elles remplacent les rouages, coches, cases, triangles de tri et flèches
   de reprise qu'on rendait comme du texte. Aucune police ne les dessine tous
   de la même façon : selon le navigateur et le
   système on obtenait un rectangle vide, une flèche d'une graisse étrangère
   au reste de l'interface, ou un pictogramme en couleur venu d'une police
   emoji — qui ignore `color` et jure avec tout. Un SVG au trait est dessiné
   par le navigateur lui-même : partout pareil, et il suit la couleur. */
.qc-ico {
  width: 1em; height: 1em; flex: 0 0 auto; display: block;
  /* Le trait est décrit pour une boîte de 24 : à 1 em il s'épaissit
     visuellement. On le rend proportionnel. */
  stroke-width: 2.2;
}
/* Les chevrons de groupe et de menu sont plus petits que le texte : ils
   accompagnent, ils n'annoncent pas. */
.qc-ico-chevron { width: .85em; height: .85em; }

.qc-facette-x {
  display: inline-flex; align-items: center;
  padding: 0 .3rem; border: none; background: none; cursor: pointer;
  color: var(--qc-accent); line-height: 1; font-size: .8rem;
}
.qc-facette-x:hover { background: rgba(0, 0, 0, .07); }

/* Panneau dépliant : Filtres | Regrouper par, comme dans Odoo — sans les
   favoris, qui mémorisaient une vue qu'on finissait par subir.
   Centré par une marge négative et **pas** par `translateX(-50%)` : Alpine
   anime `transform` pendant la transition, ce qui écrasait le centrage — le
   panneau arrivait en glissant depuis la droite avant de se remettre en place.

   La marge vaut la moitié de la largeur, au signe près, et se calcule donc
   **sur la même expression** : la version d'avant écrivait
   `min(-17rem, -46vw)`, or `min()` retient le plus négatif — à 2000 px de
   large, −46vw valait −920 px et le panneau partait hors de l'écran à gauche
   au lieu de se centrer sous la recherche. */
.qc-panneau-recherche {
  position: absolute; z-index: 40; top: calc(100% + .3rem);
  left: 50%; margin-left: calc(min(34rem, 92vw) / -2);
  width: min(34rem, 92vw); display: flex; flex-wrap: wrap; gap: 0;
  background: var(--qc-fond); border: 1px solid var(--qc-trait);
  border-radius: .625rem; box-shadow: 0 10px 30px rgba(0, 0, 0, .14);
  overflow: hidden;
}
.qc-panneau-colonne { flex: 1 1 0; padding: .5rem; min-width: 0; }
.qc-panneau-colonne + .qc-panneau-colonne { border-left: 1px solid var(--qc-trait); }
/* Le pied passe sous les colonnes : « Tout réinitialiser » n'appartient à
   aucune d'elles, il les défait toutes. */
.qc-panneau-pied {
  flex: 1 1 100%; padding: .35rem;
  border-top: 1px solid var(--qc-trait); background: var(--qc-survol);
}
.qc-panneau-titre {
  font-size: .625rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; color: var(--qc-texte-doux); padding: .2rem .45rem .4rem;
}
.qc-panneau-item {
  display: flex; align-items: center; gap: .45rem; width: 100%;
  padding: .35rem .45rem; border: none; background: none; border-radius: .4rem;
  font-size: .8125rem; font-weight: 600; color: var(--qc-texte);
  cursor: pointer; text-align: left;
}
.qc-panneau-item:hover { background: var(--qc-trait-doux); }
.qc-panneau-item.actif { color: var(--qc-accent); background: var(--qc-accent-doux); }
/* La coche est une icône SVG depuis 2026-08-20 : `inline-flex` la centre
   dans la gouttière, là où un caractère se posait sur la ligne de base. */
.qc-panneau-coche {
  width: .95rem; flex-shrink: 0; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center;
}

/* Pagination — position identique en liste (« 1-3 / 3 ») et en fiche (« 1 / 3 ») */
.qc-pager { display: flex; align-items: center; gap: .25rem; white-space: nowrap; }
.qc-pager-txt {
  font-size: .8125rem; color: var(--qc-texte-doux); font-weight: 600;
  font-variant-numeric: tabular-nums; padding: 0 .25rem;
}
.qc-pager-btn {
  display: flex; align-items: center; justify-content: center;
  width: 1.75rem; height: 1.75rem; border-radius: .5rem;
  border: 1px solid var(--qc-trait); background: var(--qc-fond);
  color: var(--qc-texte); cursor: pointer;
}
.qc-pager-btn:hover:not(:disabled) { border-color: var(--qc-accent); color: var(--qc-accent); }
.qc-pager-btn:disabled { opacity: .35; cursor: default; }


/* ----- Le tableau ----- */

.qc-table-boite {
  background: var(--qc-fond); border-radius: 1rem; overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .07);
}
/* Le défilement horizontal reste dans le tableau : la page, elle, ne bouge pas.
   Et il n'apparaît qu'en dernier recours — le tableau se resserre d'abord
   (voir plus bas) : une barre de défilement sur un tableau qui tiendrait dans
   la fenêtre est un aveu de mise en page, pas un service rendu. */
.qc-table-defile { overflow-x: auto; }
.qc-table { width: 100%; border-collapse: collapse; font-size: .875rem; }

.qc-table thead th {
  text-align: left; padding: .625rem .75rem;
  font-size: .6875rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--qc-texte-doux);
  border-bottom: 1px solid var(--qc-trait); background: var(--qc-survol);
  white-space: nowrap;
}
.qc-th-triable { cursor: pointer; user-select: none; }
.qc-th-triable:hover { color: var(--qc-accent); }
.qc-th-fleche {
  display: inline-flex; align-items: center; font-size: .8rem;
  margin-left: .2rem; color: var(--qc-accent);
}

.qc-table tbody td {
  padding: .625rem .75rem; border-bottom: 1px solid var(--qc-trait-doux);
  color: var(--qc-texte); vertical-align: middle;
}
.qc-table tbody tr:last-child td { border-bottom: none; }
/* La ligne entière ouvre la fiche — comme dans Odoo. */
.qc-ligne { cursor: pointer; }
.qc-ligne:hover td { background: var(--qc-survol); }
/* Teinte volontairement discrète : une ligne cochée doit se repérer sans
   noyer les pastilles d'état qu'elle porte. */
.qc-ligne.qc-ligne-cochee td { background: #f0faf9; }

/* Une liste dont les lignes ne mènent nulle part. L'onglet Saisies est dans ce
   cas : une saisie ne s'ouvre pas en fiche, il n'y a rien à y modifier depuis
   l'administration. Sans ça, le curseur en main promet une fiche qui n'existe
   pas, et on clique trois fois avant de comprendre. */
/* Une case qu'on ne peut pas cocher : elle reste visible — la retirer ferait
   croire que le réglage n'existe pas — mais elle n'invite plus au clic. */
.qc-membre-saisie-inerte { opacity: .45; cursor: not-allowed; }
.qc-membre-saisie-inerte .qc-case { cursor: not-allowed; }

.qc-ligne-inerte { cursor: default; }
.qc-ligne-inerte:hover td { background: transparent; }

/* La colonne des cases ne s'ouvre pas : y cliquer coche. */
.qc-col-case { width: 1%; white-space: nowrap; cursor: default; }
.qc-col-case { padding-left: .875rem !important; }
.qc-case { accent-color: var(--qc-accent); width: .95rem; height: .95rem; cursor: pointer; }


/* Avatar : l'écart au nom était trop serré, les deux se touchaient presque. */
/* `nowrap` : sur écran étroit, mieux vaut faire défiler le tableau que couper
   « Admin VA » sur deux lignes — la colonne d'identification doit se lire
   d'un coup d'œil. */
.qc-cellule-nom { display: flex; align-items: center; gap: .7rem; white-space: nowrap; }
.qc-avatar {
  width: 1.75rem; height: 1.75rem; border-radius: 999px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: .6875rem; font-weight: 800;
}

/* Choix des colonnes — au bout de l'en-tête, comme dans Odoo.
   `position: relative` sur la cellule : sans elle, le panneau s'accroche au
   premier ancêtre positionné et part se placer n'importe où. */
.qc-col-reglages {
  width: 2.5rem; white-space: nowrap; position: relative;
  padding: 0 .5rem 0 0 !important; text-align: right;
}
.qc-reglages-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.9rem; height: 1.9rem;
  border: none; background: none; cursor: pointer; color: var(--qc-texte-doux);
  border-radius: .4rem;
}
.qc-reglages-btn svg { width: 1.05rem; height: 1.05rem; }
.qc-reglages-btn:hover { background: var(--qc-trait-doux); color: var(--qc-accent); }

/* Ligne de groupe — repliable, avec son décompte. */
.qc-groupe td {
  background: var(--qc-survol) !important;
  font-weight: 800; color: var(--qc-texte); cursor: pointer;
  border-top: 1px solid var(--qc-trait);
}
.qc-groupe:hover td { background: var(--qc-trait-doux) !important; }
.qc-groupe-fleche {
  display: inline-flex; align-items: center; justify-content: center;
  width: .9rem; color: var(--qc-texte-doux); font-size: .9rem;
}
.qc-groupe-compte { color: var(--qc-texte-doux); font-weight: 700; }

.qc-vide { padding: 3rem 1rem; text-align: center; color: var(--qc-texte-doux); font-size: .875rem; }

/* Pastille d'état — la couleur se pose par une variante, jamais en dur ici. */
.qc-badge {
  display: inline-block; padding: .1rem .5rem; border-radius: 999px;
  font-size: .6875rem; font-weight: 800; white-space: nowrap;
}
/* Assez contrasté pour se lire sur une ligne sélectionnée : c'est la pastille
   des états « en attente d'action », donc ceux qu'on cherche du regard. */
.qc-badge-neutre { background: #e2e8f0; color: #475569; }
.qc-badge-vert   { background: #dcfce7; color: #15803d; }
.qc-badge-ambre  { background: #fef3c7; color: #b45309; }
.qc-badge-bleu   { background: #dbeafe; color: #1d4ed8; }
.qc-badge-violet { background: #ede9fe; color: #6d28d9; }
.qc-badge-gris   { background: #f3f4f6; color: #9ca3af; }

/* Barre d'actions groupées — prend la **place** de la recherche, elle ne
   s'ajoute pas au-dessus : quand on a sélectionné des lignes, on ne cherche
   plus, on agit. Une barre de plus décalerait le tableau à chaque case
   cochée. */
.qc-lot {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  width: 100%; margin: 0;
  padding: .3rem .35rem .3rem .7rem;
  background: var(--qc-accent-doux); border: 1px solid var(--qc-accent);
  border-radius: .625rem;
  font-size: .8125rem; color: var(--qc-accent); font-weight: 700;
}
/* Variante sobre pour « Actions ▾ » : le menu ne doit pas rivaliser
   visuellement avec l'action principale de la sélection. */
.qc-lot-btn-sobre {
  background: var(--qc-fond); color: var(--qc-accent);
  border: 1px solid var(--qc-accent);
}
.qc-lot-btn-sobre:hover:not(:disabled) { background: var(--qc-accent-doux); filter: none; }
.qc-lot-btn {
  padding: .3rem .75rem; border-radius: .5rem; font-weight: 700;
  background: var(--qc-accent); color: #fff; border: none; cursor: pointer;
}
.qc-lot-btn:hover:not(:disabled) { filter: brightness(.93); }
.qc-lot-btn:disabled { opacity: .5; cursor: default; }
.qc-lot-annuler { background: none; border: none; color: var(--qc-accent); font-weight: 700; cursor: pointer; }
.qc-lot-annuler:hover { text-decoration: underline; }

/* Menu d'actions de ligne — les gestes irréversibles y sont rangés, pas
   alignés au milieu des gestes courants. */
.qc-menu { position: relative; display: inline-block; }
/* Assez grand pour être visé, assez sombre pour être vu : la version d'avant
   était un caractère minuscule en gris clair, qu'on cherchait avant de
   comprendre qu'on pouvait cliquer dessus. */
.qc-menu-declencheur {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.75rem; height: 1.75rem;
  padding: 0 .3rem; border-radius: .4rem; border: 1px solid transparent;
  background: none; color: var(--qc-texte); cursor: pointer;
  font-size: 1.05rem; line-height: 1;
}
.qc-menu-declencheur:hover {
  background: var(--qc-accent-doux); color: var(--qc-accent);
  border-color: var(--qc-accent);
}
/* Hors du flux : `qcMenu()` fournit `top`, `left` et `max-height` en style
   en ligne. C'est la seule façon d'échapper aux conteneurs qui rognent — le
   tableau défile horizontalement, donc CSS lui impose aussi `overflow-y`, et
   un panneau ancré dans son en-tête se faisait couper à 99 %. */
.qc-menu-panneau {
  position: fixed; z-index: 50;
  min-width: 12rem; padding: .25rem;
  overflow-y: auto;
  background: var(--qc-fond); border: 1px solid var(--qc-trait);
  border-radius: .625rem; box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
}
.qc-menu-item {
  display: block; width: 100%; text-align: left;
  padding: .45rem .6rem; border-radius: .45rem; border: none; background: none;
  font-size: .8125rem; font-weight: 600; color: var(--qc-texte); cursor: pointer;
}
.qc-menu-item:hover { background: var(--qc-trait-doux); }
.qc-menu-item.danger { color: #dc2626; }
.qc-menu-item.danger:hover { background: #fef2f2; }
.qc-menu-sep { height: 1px; margin: .25rem .3rem; background: var(--qc-trait); }

/* ----- Fenêtre modale ----- */

.qc-modale-fond {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: flex-start; justify-content: center;
  padding: 2rem 1rem; overflow-y: auto;
  background: rgba(17, 24, 39, .45);
}
.qc-modale {
  width: 100%; max-width: 42rem; background: var(--qc-fond);
  border-radius: 1rem; box-shadow: 0 20px 60px rgba(0, 0, 0, .25);
}
.qc-modale-corps { padding: 1.35rem; }
/* Pied de fenêtre : l'action principale à gauche, comme partout ailleurs dans
   l'écran — l'œil ne doit pas chercher le bouton à un endroit différent selon
   la fenêtre. */
.qc-modale-pied {
  display: flex; gap: .75rem; padding: 1rem 1.35rem;
  border-top: 1px solid var(--qc-trait); background: var(--qc-survol);
  border-radius: 0 0 1rem 1rem;
}

/* ----- Fiche ----- */

.qc-fiche { background: var(--qc-fond); border-radius: 1rem; box-shadow: 0 1px 3px rgba(0, 0, 0, .07); }

/* En-tête : le nom en grand, l'état à droite. Le nom s'édite là où on le lit,
   sans champ « Nom complet » répété plus bas — c'est le geste d'Odoo, et ça
   évite d'écrire deux fois la même chose à trois centimètres d'écart. */
.qc-fiche-tete {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; padding: 1.35rem 1.5rem 0;
}
.qc-fiche-identite { flex: 1 1 auto; min-width: 0; }
.qc-fiche-surtitre {
  font-size: .625rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; color: var(--qc-texte-doux); margin-bottom: .15rem;
}
/* Champ nu tant qu'on ne le vise pas : un cadre permanent sur un titre le
   ferait lire comme un formulaire, alors que c'est le nom de la fiche. */
.qc-fiche-titre {
  width: 100%; font-size: 1.6rem; font-weight: 800; color: #1f2937;
  border: none; border-bottom: 1px dashed transparent; background: none;
  padding: 0 0 .25rem; outline: none;
}
.qc-fiche-titre::placeholder { color: #d1d5db; }
.qc-fiche-titre:hover { border-bottom-color: var(--qc-trait); }
.qc-fiche-titre:focus { border-bottom-color: var(--qc-accent); }
.qc-fiche-etat { flex-shrink: 0; padding-top: .5rem; }

/* Faits venus d'Odoo, sous le nom. En lecture seule et présentés comme tels :
   pas de cadre, pas de champ — on ne peut pas les modifier ici, et laisser
   croire le contraire ferait chercher un bouton qui n'existe pas. */
/* Deux colonnes de faits, et les libellés alignés d'une ligne à l'autre :
   en bande qui s'enroule, chaque valeur repoussait la suivante et l'œil ne
   trouvait plus où commence un fait. `display: contents` sur le fait laisse
   son libellé et sa valeur tomber dans les pistes de la grille du dessus —
   c'est ce qui les aligne verticalement. */
.qc-fiche-odoo {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr);
  align-items: baseline; gap: .3rem .8rem;
  margin-top: .55rem; max-width: 48rem;
}
.qc-fait { display: contents; }
.qc-fait-label {
  font-size: .625rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--qc-texte-doux);
}
.qc-fait-valeur {
  font-size: .8125rem; font-weight: 600; color: var(--qc-texte);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 18rem;
}
.qc-fait-source {
  grid-column: 1 / -1;
  font-size: .6875rem; font-style: italic; color: var(--qc-texte-doux);
}
/* Dès que la place manque, une seule paire libellé/valeur par ligne. */
@media (max-width: 64rem) {
  .qc-fiche-odoo { grid-template-columns: max-content minmax(0, 1fr); }
}
.qc-fiche-odoo-vide {
  margin-top: .5rem; font-size: .75rem; color: var(--qc-texte-doux);
}

/* Boîte à boutons — les « smart buttons » d'Odoo : en haut à droite de la
   feuille, sur la même bande que le nom. Ils ne montrent pas une donnée de
   plus, ils mènent quelque part — d'où l'icône, le chiffre et le mot, et une
   taille qui se vise au pouce. */
.qc-smarts {
  display: flex; flex-wrap: wrap; width: 100%;
  justify-content: center; gap: .5rem;
}
/* `align-items: stretch` et `padding: 0` sur le bouton : c'est ce qui laisse
   la bande d'icône tenir toute la hauteur du rectangle. Le rembourrage vit
   dans les deux moitiés, pas sur le cadre. */
.qc-smart {
  display: flex; align-items: stretch; overflow: hidden;
  min-width: 7.5rem; min-height: 2.5rem; padding: 0;
  border: 1px solid var(--qc-trait); border-radius: .75rem;
  background: var(--qc-fond); cursor: pointer; text-align: left;
}
.qc-smart:hover:not(:disabled) { border-color: var(--qc-accent); background: var(--qc-accent-doux); }
/* Sans équipe, le bouton ne mène nulle part : il le dit avant qu'on clique. */
.qc-smart:disabled { cursor: default; opacity: .55; }
.qc-smart-boite {
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; padding: 0 .6rem;
  background: var(--qc-accent-doux); border-right: 1px solid var(--qc-trait-doux);
}
.qc-smart-icone { width: 1.15rem; height: 1.15rem; color: var(--qc-accent); }
/* `justify-content: center` fait tout le travail des deux états : à zéro il
   ne reste que le mot, et il se centre de lui-même ; dès qu'il y a un compte,
   les deux lignes se partagent la hauteur, le mot au-dessus. */
.qc-smart-texte {
  display: flex; flex-direction: column; justify-content: center;
  min-width: 0; padding: .3rem .8rem;
}
.qc-smart-valeur {
  font-size: 1.05rem; font-weight: 800; color: var(--qc-accent);
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.qc-smart-label {
  font-size: .625rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--qc-texte-doux); line-height: 1.3;
}

/* Carnet d'onglets, comme le « notebook » d'Odoo. */
/* `overflow-y: hidden` est obligatoire : demander `overflow-x: auto` seul
   met aussi l'axe vertical en `auto`, et la bande d'onglets — haute de 42 px
   pour un contenu de 43 — affichait une barre de défilement verticale d'un
   pixel de course, en haut à droite de la fiche. */
.qc-onglets {
  display: flex; gap: .25rem; padding: 0 1.5rem; margin-top: 1.15rem;
  border-bottom: 1px solid var(--qc-trait);
  overflow-x: auto; overflow-y: hidden;
}
.qc-onglet {
  padding: .6rem .9rem; border: none; background: none; cursor: pointer;
  font-size: .875rem; font-weight: 700; color: var(--qc-texte-doux);
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap;
}
.qc-onglet:hover { color: var(--qc-texte); }
.qc-onglet.actif { color: var(--qc-accent); border-bottom-color: var(--qc-accent); }

.qc-fiche-corps { padding: 1.5rem; }

/* Deux colonnes comme Odoo, une seule dès que l'écran se resserre. */
.qc-champs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.1rem 2rem; }
@media (max-width: 48rem) { .qc-champs { grid-template-columns: minmax(0, 1fr); } }
.qc-champ { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.qc-champ-large { grid-column: 1 / -1; }
.qc-champ-label {
  font-size: .6875rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--qc-texte-doux);
}
.qc-champ-requis { color: #dc2626; }
/* L'explication d'un champ se lit **sous** lui, en gris : au-dessus, elle
   sépare le libellé de son champ et on ne sait plus lequel elle décrit. */
.qc-champ-aide { font-size: .75rem; color: var(--qc-texte-doux); line-height: 1.35; }
.qc-champ-note { font-size: .75rem; font-weight: 700; color: #b45309; line-height: 1.35; }
/* Valeur posée, qu'on ne modifie pas ici : présentée comme un fait, sans cadre
   ni fond de champ. Un champ grisé se lit comme « momentanément indisponible »
   et fait chercher comment le débloquer ; un texte simple dit qu'il n'y a rien
   à débloquer à cet endroit. */
.qc-champ-fige {
  font-size: .9375rem; font-weight: 700; color: var(--qc-texte);
  padding: .1rem 0;
}
.qc-champ-rouage {
  display: inline-flex; vertical-align: -.15em; color: var(--qc-texte);
}

.qc-section-titre {
  grid-column: 1 / -1; font-size: .6875rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; color: var(--qc-texte-doux);
  margin-top: .35rem; padding-bottom: .35rem; border-bottom: 1px solid var(--qc-trait-doux);
}

/* Case à cocher qui commande le reste de la fiche : encadrée, parce qu'elle
   change ce que les autres champs veulent dire. */
.qc-bascule {
  grid-column: 1 / -1; display: flex; align-items: flex-start; gap: .75rem;
  padding: .85rem; border: 1px solid var(--qc-trait); border-radius: .75rem;
  background: var(--qc-survol); cursor: pointer;
}
.qc-bascule input { margin-top: .15rem; accent-color: var(--qc-accent);
  width: .95rem; height: .95rem; flex-shrink: 0; cursor: pointer; }
.qc-bascule-titre { font-weight: 700; color: var(--qc-texte); }

/* Membres d'une équipe : un tableau dans une fiche.
   Il ne porte ni case à cocher ni pagination — on ne fait pas d'action en lot
   sur trois personnes qu'on a sous les yeux, et une équipe qui déborderait
   d'une page serait d'abord un problème d'organisation. */
.qc-membres { margin-top: .5rem; box-shadow: none; border: 1px solid var(--qc-trait); }
.qc-membres .qc-ligne { cursor: default; }
/* Le message d'équipe vide tient sur une ligne : les 2 rem de la liste
   principale creusaient un trou de la hauteur d'un écran sous « Ajouter une
   ligne », comme si le tableau attendait quelque chose. */
.qc-membres .qc-vide { padding: .85rem 1rem; }
/* La case et son « Oui » : le mot n'apparaît que si elle est cochée — une
   colonne de « Non » alignés ne dit rien que la case vide ne dise déjà. */
.qc-membre-saisie {
  display: inline-flex; align-items: center; gap: .5rem; cursor: pointer;
  font-size: .8125rem; font-weight: 700; color: var(--qc-accent);
}
.qc-membre-saisie .qc-case { accent-color: #FC9F09; }
.qc-membre-x {
  display: flex; align-items: center; justify-content: center;
  width: 1.75rem; height: 1.75rem; border-radius: .45rem;
  border: none; background: none; color: var(--qc-texte-doux); cursor: pointer;
}
.qc-membre-x svg { width: 1rem; height: 1rem; }
.qc-membre-x:hover { background: #fee2e2; color: #dc2626; }

/* « Ajouter une ligne » — le geste des lignes de commande d'un devis Odoo :
   un lien discret au bas du tableau, pas un bouton plein. Dans un formulaire,
   un bouton coloré au milieu du contenu se dispute l'attention avec
   l'enregistrement, alors qu'il n'ouvre qu'une ligne vide. */
.qc-ligne-lien td { padding: .35rem .85rem .6rem; }
.qc-ajout-lien {
  border: none; background: none; padding: 0; cursor: pointer;
  font-size: .8125rem; font-weight: 700; color: var(--qc-accent);
}
.qc-ajout-lien:hover { text-decoration: underline; }
.qc-ligne-ajout td { background: var(--qc-survol); }
.qc-ajout-select { max-width: 22rem; }
.qc-ajout-note { font-size: .75rem; color: var(--qc-texte-doux); }
@media (max-width: 48rem) {
  .qc-ajout-select { max-width: none; }
}

/* Modification non enregistrée, dans le fil d'Ariane — les deux boutons
   d'Odoo. Ils ne s'affichent que s'il y a quelque chose à enregistrer :
   toujours visibles, ils cesseraient de vouloir dire quoi que ce soit. */
.qc-sale { display: inline-flex; align-items: center; gap: .3rem; margin-left: .5rem; }
.qc-sale-btn {
  display: flex; align-items: center; justify-content: center;
  width: 1.7rem; height: 1.7rem; border-radius: .45rem;
  border: 1px solid var(--qc-trait); background: var(--qc-fond); cursor: pointer;
}
.qc-sale-btn svg { width: .95rem; height: .95rem; }
.qc-sale-btn.ok { color: var(--qc-accent); border-color: var(--qc-accent); }
.qc-sale-btn.ko { color: var(--qc-texte-doux); }
.qc-sale-btn:hover:not(:disabled) { filter: brightness(.97); }
.qc-sale-btn:disabled { opacity: .5; cursor: default; }
.qc-sale-point {
  width: .45rem; height: .45rem; border-radius: 999px;
  background: #f59e0b; margin-right: .1rem;
}
/* Colonne qu'on ne peut pas masquer : cochée, et visiblement inerte. */
.qc-menu-item.verrouille { color: var(--qc-texte-doux); cursor: default; }
.qc-menu-item.verrouille:hover { background: none; }

/* ===================================================================
   Écrans étroits
   =================================================================== */

/* Le tableau se resserre avant de défiler. À 1000 px de fenêtre — sidebar et
   marges déduites — il ne restait que 696 px de contenu pour 743 px de
   tableau : 47 px de débordement, donc une barre de défilement pour presque
   rien. Le seul gabarit à céder est l'espacement, jamais la lisibilité :
   mesuré à 0 px de débordement une fois les cellules resserrées. */
@media (max-width: 80rem) {
  .qc-table tbody td, .qc-table thead th { padding-left: .5rem; padding-right: .5rem; }
  .qc-col-case { padding-left: .6rem !important; }
  /* Le nom accepte de passer à la ligne : c'est la colonne la plus rigide
     (202 px de minimum à elle seule, avatar compris), et un nom sur deux
     lignes se lit toujours — un tableau qu'on doit faire glisser pour voir
     l'état de quelqu'un, non. */
  .qc-cellule-nom { gap: .5rem; white-space: normal; }
}

/* Téléphone : la recherche se replie derrière une loupe, et les commandes se
   rangent dans des menus. Une boîte de recherche permanente et quatre boutons
   côte à côte ne tiennent pas sur 375 px — ils s'y empilent sur trois lignes
   et repoussent le tableau hors de l'écran. */
.qc-loupe { display: none; }
/* Pas de `!important` sur `qc-tel-seul` : ces entrées portent aussi un
   `x-show`, qui pose un `display: none` en ligne. Un `!important` de classe
   passerait devant et ferait réapparaître une commande qu'Alpine venait de
   masquer — par exemple « Tout sélectionner » alors que tout l'est déjà. */
.qc-tel-seul { display: none; }

/* Le retour de la fiche n'existe que sur téléphone : sur écran large, le fil
   d'Ariane dit d'où l'on vient **et** permet de remonter de plusieurs crans,
   ce qu'une flèche ne sait pas faire. Deux commandes pour le même geste, dont
   une moins capable, ne s'affichent pas ensemble. */
.qc-retour { display: none; }

@media (max-width: 48rem) {
  /* Une seule ligne de commandes, comme dans Odoo mobile : à gauche le fil et
     son menu, à droite la pagination puis la loupe. La recherche ne prend
     jamais de place tant qu'on ne la demande pas. */
  .qc-cp, .qc-cp.qc-cp-large {
    display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
    position: relative; grid-template-columns: none;
  }
  .qc-cp-gauche { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; }
  .qc-cp-droite { flex: 0 0 auto; margin-left: auto; justify-self: auto; order: 1; }

  .qc-loupe {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.25rem; height: 2.25rem; flex-shrink: 0;
    border: 1px solid var(--qc-trait); border-radius: .625rem;
    background: var(--qc-fond); color: var(--qc-texte); cursor: pointer;
  }
  .qc-loupe svg { width: 1.05rem; height: 1.05rem; }
  .qc-loupe.actif { border-color: var(--qc-accent); color: var(--qc-accent); }

  /* Dépliée, la recherche descend **sous** la barre, hors du flux : c'est un
     panneau, pas une ligne de plus — la barre garde sa hauteur et le tableau
     ne bouge pas. */
  .qc-cp-centre {
    order: 2; position: absolute; left: 0; right: 0; width: auto;
    top: calc(100% + .35rem); z-index: 45;
  }
  .qc-cp-centre.repliee { display: none; }

  /* En fiche, la piste du milieu ne porte pas la recherche mais la boîte à
     boutons — elle doit rester dans le flux. Sortie du flux comme un panneau
     de recherche, elle se posait par-dessus le haut de la fiche et cachait le
     surtitre. Ici elle descend sur une deuxième ligne, sous le fil d'Ariane. */
  .qc-cp-centre.qc-piste-smarts {
    order: 3; position: static; top: auto; width: 100%;
  }
  /* La sélection, elle, dure : elle prend une vraie deuxième ligne plutôt que
     de recouvrir la barre. Ce qu'on a coché doit rester lisible en même temps
     que la pagination qui dit combien il y en a. */
  .qc-cp-centre.selection {
    position: relative; top: auto; left: auto; right: auto;
    flex: 1 1 100%; width: 100%;
  }

  /* « Importer » garde son bouton propre — c'est l'action principale de
     l'écran, elle ne se range pas dans un menu. Ce qui cède, c'est le titre
     du fil : la barre latérale dit déjà où l'on est. */
  .qc-tel-cache { display: none !important; }

  /* ── L'en-tête d'une fiche, sur téléphone ───────────────────────────────
     Une seule ligne, et rien d'autre que des commandes.

     Avant : « Importer » + « Utilisateurs / RECETTE Sandra Kunz » + le rouage
     remplissaient la première ligne, la pagination tombait sur la deuxième et
     la boîte à boutons sur la troisième. Trois lignes d'en-tête sur un écran
     de téléphone, pour un chemin que le titre de la fiche répète juste en
     dessous.

     Après : [←] [rouage] [boîte à boutons] … [pagination]. Le fil cède la
     place à la flèche, et « Importer » — action de la **liste** — se retire
     le temps qu'on regarde un enregistrement. */
  .qc-cp-fiche .qc-retour {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.25rem; height: 2.25rem; flex-shrink: 0;
    border: 1px solid var(--qc-trait); border-radius: .625rem;
    background: var(--qc-fond); color: var(--qc-texte); cursor: pointer;
  }
  .qc-cp-fiche .qc-retour svg { width: 1.05rem; height: 1.05rem; }

  /* Le chemin écrit s'efface — mais pas `.qc-fil`, qui porte aussi le rouage
     et les deux boutons d'enregistrement. */
  .qc-cp-fiche .qc-fil-repli,
  .qc-cp-fiche .qc-fil-seg { display: none; }

  .qc-cp-fiche .qc-fiche-tel-cache { display: none; }

  /* La boîte à boutons rentre dans la ligne au lieu d'en prendre une pour
     elle seule. C'est la règle générale des fiches sur téléphone qui la
     poussait en bas ; ici il y a la place, une fois le fil parti. */
  .qc-cp-fiche .qc-cp-centre.qc-piste-smarts {
    order: 0; flex: 0 0 auto; width: auto; justify-content: flex-start;
  }
  .qc-cp-fiche .qc-cp-gauche { flex: 0 0 auto; }
  .qc-btn-compact { padding-left: .7rem !important; padding-right: .7rem !important; }
  .qc-tel-seul { display: block; }

  /* Le panneau de filtres suit la boîte de recherche et prend la largeur. */
  .qc-panneau-recherche {
    left: 0; margin-left: 0; width: 100%;
    flex-direction: column; max-height: 70vh; overflow-y: auto;
  }
  .qc-panneau-colonne + .qc-panneau-colonne {
    border-left: none; border-top: 1px solid var(--qc-trait);
  }

  /* Sélection : le compte et un seul menu. Tout le reste y est rangé. */
  .qc-lot { padding: .3rem .5rem; }
  .qc-lot .qc-lot-btn:not(.qc-lot-menu) { display: none; }
}
