/*
 * Appli-Boutique-Vêtement — habillage de l'OUTIL.
 *
 * **Ce fichier a changé de camp le 2026-09-10.** Il se lisait auparavant comme
 * une rallonge de elleplus.ca et portait le rose du thème. Mais l'application
 * sert plusieurs boutiques clientes : la peindre aux couleurs de l'une d'elles
 * la ferait mentir chez la deuxième. C'est maintenant une console de travail,
 * neutre, à l'accent violet — la maquette validée le 2026-09-10.
 *
 * Les noms des jetons ne bougent PAS. `--color-accent` reste `--color-accent`
 * même si sa valeur passe du rose au violet : renommer trois cents usages pour
 * un changement de teinte serait un chantier sans bénéfice, et chaque nom dit
 * toujours son rôle.
 *
 * Rien n'est chargé depuis un CDN. La CSP du Worker (`src/index.ts`) n'admet
 * que l'origine `'self'` : un `<link>` vers Google Fonts serait bloqué sans
 * message. D'où les deux `@font-face` ci-dessous, servis depuis /fonts/.
 */

@font-face {
  font-family: "Epilogue";
  src: url("/fonts/epilogue-800-latin.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

/* Fichier variable : une seule ressource couvre 400 à 600. */
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-400-600-latin.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- Marque : la console, pas la boutique ------------------------------ */
  --color-background: #ffffff;
  --color-text: #17171c;
  /*
   * L'accent appartient à la BOUTIQUE, pas à l'application.
   *
   * `--accent-boutique` est posé par app.js depuis `GET /api/sante`, qui le lit
   * dans `organizations.accent` (migration 0040). Une boutique qui n'en a pas
   * garde le violet neutre : la console reste l'habillage d'un outil, et la
   * deuxième cliente ne travaille pas dans les couleurs de la première.
   *
   * Une seule couleur bouge. Les neutres, les états et les contrastes ne
   * dépendent d'aucune boutique.
   */
  --accent: var(--accent-boutique, #6c47ff);
  /* Violet d'action : boutons principaux, onglet actif, anneau de focus. */
  --color-accent: var(--accent);
  /*
   * L'encre posee SUR l'accent. Blanche par defaut ; app.js la passe au noir
   * quand l'accent de la boutique est trop clair pour du blanc. Une encre fixe
   * donnait du noir sur magenta — lisible a peine, et mou a l'oeil.
   */
  --sur-accent: #ffffff;
  /*
   * La même famille, mais lisible en TEXTE. L'accent seul plafonne à 4,3:1 et
   * ne peut pas servir d'encre ; assombri de la sorte, il dépasse 7:1 sur
   * blanc quelle que soit la teinte de départ — c'est la luminance qui décide
   * du contraste, et elle est ici imposée, pas héritée.
   */
  --color-brand-deep: color-mix(in srgb, var(--accent) 72%, #0b0616);
  --color-border: #ebebeb;
  --color-surface: #f2f4f5;
  --color-secondary: #55555f;
  /*
   * Fige le 2026-09-11. Le `color-mix(in srgb, var(--color-text) 58%,
   * var(--color-border))` d'origine rendait #707073 : 4,94:1 sur la page, mais
   * 4,47:1 sur les cartes — AA rate de 0,03, en production. Le test des
   * ambiances l'a revele. Trois unites par canal plus fonce, et 4,63:1.
   */
  --color-muted: #6d6d78;

  /*
   * États. Le rose de marque ne sert JAMAIS de couleur d'état : sur fond
   * blanc, `--color-brand-deep` et un rouge d'erreur ne se distinguent qu'à
   * ΔE 8 — trop proche. Le trio ci-dessous est mesuré à ΔE 16,6 en vision
   * normale, et chaque état porte de toute façon son libellé écrit.
   */
  --etat-ok: #0f7b52; /* 5,3:1 sur blanc — sert aussi d'encre */
  --etat-attention: #a9750d; /* 4,0:1 — signal (rails, bordures, teintes) */
  --etat-attention-encre: #7d5600; /* 6,6:1 — la même famille, lisible en texte */
  --etat-erreur: #b3261e; /* 6,5:1 — encre et signal */

  /* Le rail tient « Fiches incomplètes » sur une ligne, icône comprise. */
  --largeur-rail: 15rem;

  /* --- Surfaces ---------------------------------------------------------- */
  /*
   * Un gris neutre, et rien de plus.
   *
   * Le voile rose qui tenait ici teintait toute l'application. Une console de
   * travail ne se teinte pas : les seules couleurs qui doivent attirer l'œil
   * sont l'accent d'action et les trois états. Le fond ne fait que séparer les
   * cartes blanches de la page.
   */
  /*
   * Un gris plat, sans dégradé. La page est la TOILE sur laquelle flottent des
   * cartes blanches : un dégradé ferait varier le contraste d'une carte selon
   * sa hauteur dans l'écran.
   */
  --fond-page: none;
  --panneau-lavis: none;
  --panneau-bordure: var(--color-border);
  /* La colonne de gauche est blanche : c'est la page qui est grise. */
  --fond-rail: #ffffff;

  /* --- Rayons et ombres : jetons du thème -------------------------------- */
  /*
   * Arrondi généreux partout, pilule pour tout ce qui se clique. Aucun angle
   * vif : c'est la signature de forme, et elle ne souffre pas d'exception —
   * une seule carte à angles droits se lit comme une erreur d'affichage.
   */
  --radius-sm: 0.625rem;
  --radius-md: 0.875rem;
  --radius-lg: 1.25rem;
  --radius-xl: 1.75rem;
  --radius-pill: 999px;
  --shadow-soft: 0 2px 8px rgba(0, 0, 0, 0.06);
  /* L'ombre du bouton principal est TEINTÉE de l'accent de la boutique. */
  /*
   * Une ombre courte et nette. L'ancien halo (24 px, accent a 34 %) debordait
   * du bouton en brume coloree : le contour se lisait flou, surtout sur un
   * accent sature comme le magenta d'une boutique.
   */
  --shadow-accent: 0 1px 2px rgb(15 15 30 / 0.12);
  /*
   * Deux couches, et aucune bordure.
   *
   * Une carte blanche sur une toile grise se détache par son ombre seule : la
   * couche courte pose le contact, la longue donne la hauteur. Ajouter un
   * trait par-dessus redessinerait le bord que l'ombre vient de suggérer.
   */
  --shadow-carte: 0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -2px rgba(0, 0, 0, 0.08);

  /*
   * Ajoutés le 2026-09-11 avec les ambiances : ces valeurs vivaient en dur au
   * milieu des règles. Une ambiance ne peut redéfinir que ce qui porte un nom.
   */
  /* Le voile de la barre de marque : la surface élevée, presque opaque. */
  --voile-barre: rgba(255, 255, 255, 0.92);
  /*
   * Vers quoi un aplat se FONCE au survol. Noir sur une ambiance claire, blanc
   * sur une ambiance sombre : « plus foncé » n'a aucun sens dans le noir.
   */
  --melange-profond: #000000;
  --shadow-fenetre: 0 1.5rem 3.5rem rgba(45, 42, 48, 0.28);
  --shadow-flottant: 0 24px 48px rgb(17 17 24 / 0.16);

  /* --- Ce qui ne suit AUCUNE ambiance ------------------------------------ */
  /* L'encre posée sur un état. Les états sont fixes, leur encre aussi. */
  --sur-etat: #ffffff;
  /* Le voile derrière une fenêtre modale : sombre dans toutes les ambiances. */
  --voile-fenetre: rgba(26, 28, 28, 0.5);
  /*
   * L'anneau de la pastille de détourage. Blanc et noir à dessein : il doit se
   * lire sur N'IMPORTE quelle couleur de vêtement, donc il ne peut suivre ni
   * l'ambiance ni l'accent de la boutique.
   */
  --anneau-pastille-clair: #ffffff;
  --anneau-pastille-sombre: rgba(0, 0, 0, 0.75);
  --anneau-pastille-interne: rgba(0, 0, 0, 0.45);

  /* --- Typographie ------------------------------------------------------- */
  --font-heading: "Epilogue", "Segoe UI", system-ui, sans-serif;
  --font-body: "Inter", "Segoe UI", system-ui, sans-serif;

  --pas-3xl: clamp(1.75rem, 1.35rem + 1.8vw, 2.5rem);
  --pas-2xl: clamp(1.35rem, 1.2rem + 0.7vw, 1.6rem);
  --pas-xl: 1.25rem;
  --pas-lg: 1.0625rem;
  --pas-md: 1rem;
  --pas-sm: 0.875rem;
  --pas-xs: 0.8125rem;
  --pas-2xs: 0.75rem;

  /* --- Espacement -------------------------------------------------------- */
  --esp-1: 0.25rem;
  --esp-2: 0.5rem;
  --esp-3: 0.75rem;
  --esp-4: 1rem;
  --esp-5: 1.5rem;
  --esp-6: 2rem;
  --esp-7: 3rem;

  --gouttiere: clamp(1rem, 4vw, 2.5rem);
  --page-max: 76rem;
  --hauteur-barre: 4.25rem;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/*
 * `hidden` doit gagner, toujours.
 *
 * L'attribut ne vaut qu'un `display: none` posé par la feuille du navigateur :
 * la moindre déclaration `display` de notre côté le bat. `.tuiles` en `grid`,
 * le panneau d'onglet en `grid`, le bouton en `inline-flex` — tous restaient
 * affichés alors que le JavaScript les avait masqués, et la zone de dépôt
 * s'invitait dans l'onglet Historique.
 */
[hidden] {
  display: none !important;
}

/*
 * La PAGE ne défile jamais.
 *
 * L'application tient dans la fenêtre, quelle que soit sa taille : la barre de
 * marque, le titre, les tuiles et les onglets restent en place, et ce qui
 * déborde — l'historique, les lignes d'une facture — défile DANS son propre
 * cadre. Un tableau de trente factures ne doit pas pousser les chiffres clés
 * hors de l'écran.
 *
 * Tout repose sur `min-height: 0` répété à chaque niveau : par défaut un
 * élément de grille refuse de devenir plus petit que son contenu, et un seul
 * oubli dans la chaîne fait ressortir la barre de défilement de la page.
 */
html,
body {
  height: 100%;
  overflow: hidden;
}

body {
  margin: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  background-color: var(--color-background);
  background-image: var(--fond-page);
  background-repeat: no-repeat;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--pas-md);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-family: var(--font-heading);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0;
}

p {
  margin: 0;
}

a {
  color: var(--color-brand-deep);
}

/*
 * Un seul anneau de focus pour toute l'application. L'ancienne feuille posait
 * `outline: none` sur la zone de dépôt : au clavier, plus rien n'indiquait où
 * on se trouvait.
 */
:focus-visible {
  outline: 2px solid var(--color-brand-deep);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Visible seulement au lecteur d'écran. */
.hors-ecran {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Barre de marque ------------------------------------------------------ */

.barre-marque {
  z-index: 20;
  background: var(--voile-barre);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--panneau-bordure);
}

.barre-marque__interieur {
  max-width: var(--page-max);
  min-height: var(--hauteur-barre);
  margin: 0 auto;
  padding: var(--esp-2) var(--gouttiere);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-4);
  flex-wrap: wrap;
}

.marque {
  display: inline-flex;
  align-items: center;
  gap: var(--esp-2);
  text-decoration: none;
  color: inherit;
}

/* Proches des règles de `.header__logo` du thème, mais un cran plus grand :
   l'application est un outil de travail, consulté de plus loin qu'une page de
   boutique, et le logo y sert de repère plutôt que d'enseigne.
   Anciennes règles : la marque doit avoir le même
   gabarit dans l'outil et sur la boutique. */
.marque__logo {
  max-height: 3.25rem;
  width: auto;
  object-fit: contain;
}

.marque__separateur {
  width: 1px;
  height: 1.1rem;
  background: var(--color-border);
}

.marque__outil {
  font-size: var(--pas-sm);
  font-weight: 500;
  color: var(--color-muted);
}

.connexion__carte {
  max-width: 40rem;
  margin-inline: auto;
}

#connexion-code-valeur {
  max-width: 14rem;
  font-size: 1.5rem;
  letter-spacing: 0.35em;
  font-variant-numeric: tabular-nums;
}

.marque__nom {
  font-family: var(--font-heading);
  font-size: clamp(1rem, 0.9rem + 0.45vw, 1.25rem);
  font-weight: 800;
  letter-spacing: -0.025em;
}

/* --- Premier démarrage --------------------------------------------------- */

.onboarding {
  min-height: 0;
  overflow-y: auto;
  padding: clamp(1.25rem, 5vw, 4rem) var(--gouttiere);
}

.onboarding__carte {
  width: min(100%, 58rem);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(18rem, 1.1fr);
  gap: var(--esp-6) var(--esp-7);
  padding: clamp(1.5rem, 4vw, 3.5rem);
  border: 1px solid var(--panneau-bordure);
  border-radius: var(--radius-xl);
  background: var(--color-background);
  box-shadow: var(--shadow-soft);
}

.onboarding__intro h1 {
  max-width: 17ch;
  margin-top: var(--esp-2);
  font-size: var(--pas-3xl);
}

.onboarding__intro > p:last-child {
  max-width: 46ch;
  margin-top: var(--esp-4);
  color: var(--color-muted);
}

.onboarding__surtitre {
  color: var(--color-brand-deep);
  font-size: var(--pas-2xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/*
 * L'invitation annoncee avant d'etre acceptee. Elle occupe la colonne entiere
 * de la carte d'accueil : c'est la seule chose a lire a ce moment-la.
 */
.invitation {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: var(--esp-2);
  padding: var(--esp-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-background);
}

.invitation h2 {
  margin: 0;
  font-size: var(--pas-lg, 1.25rem);
}

.invitation__resume {
  margin: 0;
  line-height: 1.55;
  text-wrap: pretty;
}

.invitation__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2);
  margin-top: var(--esp-1);
}

.invitation__actions .bouton {
  margin: 0;
}

.onboarding__etapes {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--esp-2);
  padding: 0;
  margin: 0;
  list-style: none;
}

.onboarding__etapes li {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  padding-top: var(--esp-3);
  border-top: 2px solid var(--color-border);
  color: var(--color-muted);
  font-size: var(--pas-sm);
  font-weight: 600;
}

.onboarding__etapes span {
  display: inline-grid;
  width: 1.65rem;
  height: 1.65rem;
  place-items: center;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: var(--pas-2xs);
}

.onboarding__etapes li[data-etat="actif"] {
  border-top-color: var(--color-accent);
  color: var(--color-brand-deep);
}

.onboarding__etapes li[data-etat="fait"] {
  border-top-color: var(--etat-ok);
  color: var(--etat-ok);
}

.onboarding__formulaire {
  align-self: end;
  display: grid;
  gap: var(--esp-3);
}

.onboarding__formulaire label {
  display: block;
  font-weight: 600;
}

.onboarding__formulaire input {
  width: 100%;
  min-height: 3rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  color: var(--color-text);
  font: inherit;
}

.onboarding__formulaire .bouton {
  justify-self: start;
}

.champ-aide,
.onboarding__message {
  margin-top: var(--esp-1);
  color: var(--color-muted);
  font-size: var(--pas-sm);
}

.onboarding__deconnexion {
  justify-self: start;
  margin-top: var(--esp-3);
}

.onboarding__message {
  min-height: 1.5em;
  align-self: end;
}

.onboarding__message[data-etat="erreur"] {
  color: var(--etat-erreur);
}

.equipe__entete,
.equipe__ligne,
.equipe__lien {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-3);
}

.equipe__entete p,
.equipe__ligne small {
  display: block;
  color: var(--color-muted);
  font-size: var(--pas-sm);
}

.equipe__invitation {
  display: grid;
  grid-template-columns: minmax(14rem, 1fr) minmax(10rem, 0.55fr) auto;
  align-items: end;
  gap: var(--esp-3);
  margin: var(--esp-5) 0;
}

.equipe__invitation label {
  font-size: var(--pas-sm);
  font-weight: 600;
}

.equipe__invitation input,
.equipe__invitation select,
.equipe__lien input {
  display: block;
  width: 100%;
  min-height: 2.75rem;
  margin-top: var(--esp-1);
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  color: var(--color-text);
  font: inherit;
}

.equipe__invitation .bouton {
  margin: 0;
}

.equipe__lien {
  padding: var(--esp-3);
  margin-bottom: var(--esp-5);
  border-left: 3px solid var(--etat-ok);
  background: color-mix(in srgb, var(--etat-ok) 7%, var(--color-background));
}

.equipe__lien input {
  flex: 1;
  margin: 0;
}

/*
 * Type, Catégorie, Collections, Balises.
 *
 * La Catégorie retenue d'office se LIT, elle ne se choisit pas : du texte, pas
 * un champ grisé qui ferait croire à une panne. Deux à quatre choix : des
 * boutons radio, tous visibles, parce qu'un menu cacherait les autres.
 */
.classement__retenue,
.classement__attente {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2);
  align-items: baseline;
  margin: var(--esp-1) 0 0;
}

.classement__attente,
.classement__note {
  color: var(--color-muted);
  font-size: var(--pas-sm);
}

.classement__choix {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2) var(--esp-4);
  padding: 0;
  margin: 0;
  border: 0;
}

.classement__choix legend {
  width: 100%;
  margin-bottom: var(--esp-1);
}

.classement__choix /*
 * Les SECTIONS d'une fiche : Collections, Balises, Description.
 *
 * Elles se fondaient dans la grille des champs — trois etiquettes grises de la
 * meme taille que « Prix d'achat », collees au bloc precedent, sans rien pour
 * dire ou l'une finit et ou l'autre commence. Ce ne sont pourtant pas des
 * champs : chacune porte une liste, un choix ou un texte long.
 *
 * Un filet et de l'air suffisent. L'etiquette passe en capitales, comme le
 * titre du bloc : c'est un niveau de titre, pas un libelle de champ.
 */
.champ--section {
  margin-top: var(--esp-4);
  padding-top: var(--esp-3);
  border-top: 1px solid var(--color-border);
}

.champ--section > .champ__etiquette,
.champ--section > legend.champ__etiquette {
  margin-bottom: 0.2rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text);
}

.champ__aide {
  width: 100%;
}

.classement__radio {
  display: inline-flex;
  gap: var(--esp-2);
  align-items: center;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  cursor: pointer;
}

.classement__radio:has(input:checked) {
  border-color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 7%, var(--color-background));
}

/* La fenetre d'invitation : deux champs empiles, rien de plus. */
.formulaire-invitation {
  display: flex;
  flex-direction: column;
  gap: var(--esp-3);
}

.formulaire-invitation label {
  font-size: var(--pas-sm);
  font-weight: 600;
}

.formulaire-invitation input,
.formulaire-invitation select {
  display: block;
  width: 100%;
  min-height: 2.75rem;
  margin-top: var(--esp-1);
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  color: var(--color-text);
  font: inherit;
  font-weight: 400;
}

.formulaire-invitation .champ-aide,
.formulaire-invitation .bandeau {
  margin: 0;
}

/*
 * Une fenetre de reglage : large, mais pas plein ecran. Les trois colonnes de
 * permissions doivent tenir cote a cote sur un portable, et se replier seules
 * sur un telephone.
 */
.fenetre.fenetre--reglage {
  width: min(64rem, 94vw);
  max-height: 88vh;
}

.fenetre--reglage .fenetre-corps {
  overflow-y: auto;
}

/*
 * Les roles et leurs permissions.
 *
 * Un bloc par role, les cases groupees par domaine. Rien de dense : c'est un
 * ecran qu'on lit une fois par trimestre, pas un tableau de bord.
 */
.role {
  padding: var(--esp-4);
  margin-bottom: var(--esp-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
}

.role__entete {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2);
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--esp-3);
}

.role__entete small {
  display: block;
  color: var(--color-text-doux, inherit);
  font-size: var(--pas-sm);
}

.role__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2);
}

.role__actions .bouton {
  margin: 0;
}

.role__permissions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--esp-3);
}

.role__groupe {
  padding: var(--esp-3);
  margin: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.role__groupe legend {
  padding: 0 var(--esp-1);
  font-size: var(--pas-sm);
  font-weight: 600;
}

.role__case {
  display: flex;
  gap: var(--esp-2);
  align-items: flex-start;
  padding: var(--esp-1) 0;
  font-size: var(--pas-sm);
  line-height: 1.4;
}

.role__case input {
  margin-top: 0.15rem;
}

/* Le selecteur de role sur la ligne d'un membre. */
.equipe__role select {
  min-height: 2.25rem;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  color: var(--color-text);
  font: inherit;
  font-size: var(--pas-sm);
}

/* L'envoi qui echoue se lit comme un echec, pas comme une confirmation. */
.equipe__lien[data-etat="erreur"] {
  border-left-color: var(--etat-erreur);
  background: color-mix(in srgb, var(--etat-erreur) 7%, var(--color-background));
}

.equipe__liste {
  padding: 0;
  margin: var(--esp-3) 0 var(--esp-5);
  list-style: none;
  border-top: 1px solid var(--panneau-bordure);
}

.equipe__ligne {
  min-height: 3.5rem;
  padding: var(--esp-2) 0;
  border-bottom: 1px solid var(--panneau-bordure);
}

/* Administration de la plateforme : les composants de l'Équipe et du tableau
   des lignes, plus trois retouches. */
.admin__section {
  margin-top: var(--esp-6, 2rem);
}

/*
  Les quotas des services facturables : deux cartes cote a cote, une colonne
  au telephone. Les jetons de la boutique fournissent les couleurs — aucun
  litteral, l'accent suit l'ambiance de chaque boutique.
*/
.quotas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--esp-3, 1rem);
  margin-top: var(--esp-3, 1rem);
}

.quota h3 {
  margin: 0 0 var(--esp-2, .5rem);
  font-size: var(--pas-sm);
}

.quota__chiffre {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.75rem;
  line-height: 1.1;
  letter-spacing: -.02em;
}

.quota__chiffre span {
  display: block;
  font-family: inherit;
  font-size: var(--pas-xs);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--color-muted);
}

.quota__rail {
  margin-top: var(--esp-2, .5rem);
  height: .375rem;
  border-radius: 999px;
  background: var(--color-border);
  overflow: hidden;
}

.quota__part {
  height: 100%;
  border-radius: 999px;
  background: var(--color-accent);
}

.admin__detail {
  display: block;
  color: var(--color-muted);
  font-size: var(--pas-sm);
}

.admin__actions {
  white-space: nowrap;
  text-align: right;
}

.admin__message:empty {
  display: none;
}

.admin__message {
  color: var(--etat-erreur);
}

/* Côté droit de la barre : l'état, puis le bouton d'installation. Les deux
   sont regroupés pour que `justify-content: space-between` n'écarte pas le
   bouton du reste, à l'autre bout de la barre. */
.barre-actions {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
  flex-wrap: wrap;
}

/* Bloc d'état à droite : qui est connectée, et Shopify répond-il. */
.barre-etat {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
  flex-wrap: wrap;
  font-size: var(--pas-xs);
}

.barre-etat__utilisatrice {
  display: inline-flex;
  align-items: center;
  gap: var(--esp-2);
  color: var(--color-muted);
}

.jeton-initiales {
  display: inline-grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--color-accent) 18%, var(--color-background));
  color: var(--color-brand-deep);
  font-size: var(--pas-2xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  flex: none;
}

/* --- Coquille de page ----------------------------------------------------- */

/* Le rail à gauche, la section ouverte à droite. Titre et tuiles gardent leur
   hauteur ; les panneaux prennent ce qui reste et défilent chez eux. */

/* Navigation permanente et espace de travail. */
body:has(#application:not([hidden])) { grid-template-rows: minmax(0, 1fr); }
body:has(#application:not([hidden])) .barre-marque { display: none; }
.coquille { width: 100%; height: 100%; display: grid; grid-template-columns: var(--largeur-rail) minmax(0, 1fr); min-height: 0; overflow: hidden; }
.rail { display: flex; flex-direction: column; gap: var(--esp-4); min-width: 0; min-height: 0; padding: var(--esp-5) var(--esp-3) var(--esp-4); background: var(--fond-rail); border-right: 1px solid var(--color-border); overflow-y: auto; }
.rail__tete { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr); align-items: center; gap: var(--esp-3); padding: var(--esp-2); }
.rail__jeton { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: var(--radius-sm); background: var(--color-accent); color: var(--sur-accent); font-family: var(--font-heading); font-size: var(--pas-lg); font-weight: 800; }
.rail__identite { display: grid; gap: 2px; min-width: 0; }
.rail__marque { font-size: var(--pas-sm); font-weight: 600; overflow-wrap: anywhere; }
.rail__logo { width: 2.5rem; height: 2.5rem; object-fit: contain; border-radius: var(--radius-sm); }
.rail__tete:has(.rail__logo:not([hidden])) .rail__jeton { display: none; }
.rail__signature-boutique { color: var(--color-muted); font-size: var(--pas-2xs); line-height: 1.4; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.rail__recherche { position: relative; display: grid; align-items: center; }
.rail__loupe { position: absolute; left: .75rem; width: 1rem; height: 1rem; fill: none; stroke: var(--color-muted); stroke-width: 1.8; stroke-linecap: round; pointer-events: none; }
.rail__recherche input { width: 100%; min-height: 2.75rem; padding: .6rem .65rem .6rem 2.2rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); color: inherit; font: inherit; font-size: var(--pas-xs); }
.rail__recherche input::placeholder { color: var(--color-muted); }
.rail__sections { display: grid; gap: var(--esp-2); }
.rail__intertitre { padding: var(--esp-4) var(--esp-3) var(--esp-1); color: var(--color-muted); font-size: var(--pas-2xs); font-weight: 500; }
.rail__groupe { display: grid; gap: var(--esp-1); }
.rail__lien { display: grid; grid-template-columns: 1.25rem minmax(0, 1fr); align-items: center; gap: var(--esp-3); width: 100%; min-height: 2.75rem; padding: .6rem var(--esp-3); border: 1px solid transparent; border-radius: var(--radius-sm); background: none; color: var(--color-secondary); font: inherit; font-size: var(--pas-sm); font-weight: 500; text-align: left; cursor: pointer; transition: background-color .15s ease, color .15s ease; }
.rail__icone { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.rail__lien:hover { background: var(--color-surface); color: var(--color-text); }
.rail__lien--actif, .rail__lien--actif:hover { background: color-mix(in srgb, var(--color-accent) 10%, var(--color-background)); color: var(--color-brand-deep); font-weight: 600; border-color: color-mix(in srgb, var(--color-accent) 16%, var(--color-border)); }
.rail__pied { margin-top: auto; padding-top: var(--esp-4); display: grid; gap: var(--esp-3); border-top: 1px solid var(--color-border); }
.rail__signature { padding-inline: var(--esp-3); color: var(--color-muted); font-family: var(--font-heading); font-size: var(--pas-2xs); letter-spacing: -.04em; }
.compte { width: 100%; max-width: 58rem; padding: 0; }
.compte__section { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--esp-6); padding: var(--esp-6); align-items: start; }
.compte__section + .compte__section { border-top: 1px solid var(--color-border); }
.compte__intitule h2 { font-size: var(--pas-lg); margin-bottom: var(--esp-2); }
.compte__intitule p { max-width: 38ch; font-size: var(--pas-sm); color: var(--color-secondary); }
.compte__etat { display: grid; gap: var(--esp-4); justify-items: start; min-width: 0; font-size: var(--pas-sm); }
.compte__etat .barre-etat__utilisatrice { max-width: 100%; min-width: 0; }
.compte__etat .barre-etat__utilisatrice span:not(.jeton-initiales) { display: inline; overflow-wrap: anywhere; min-width: 0; }
.compte__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--esp-3); }
.espace { display: flex; flex-direction: column; gap: var(--esp-5); min-width: 0; min-height: 0; padding: var(--esp-7) var(--gouttiere) var(--esp-5); background: var(--color-surface); }
.entete-page { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-4); flex-wrap: wrap; flex: none; }
.entete-page h1 { font-family: var(--font-body); font-size: 2rem; font-weight: 600; line-height: 1.15; letter-spacing: -.04em; }
.entete-page__sous { margin-top: var(--esp-2); color: var(--color-secondary); font-size: var(--pas-sm); max-width: 65ch; }
.entete-page__actions { display: flex; align-items: center; gap: var(--esp-2); flex-wrap: wrap; }
.entete-page__actions:empty { display: none; }
.tuiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; flex: none; border-block: 1px solid var(--color-border); padding-block: var(--esp-4); }
.tuile { padding: 0 var(--esp-4); border-right: 1px solid var(--color-border); }
.tuile:first-child { padding-left: 0; }
.tuile:last-child { border-right: 0; }
.tuile__libelle { color: var(--color-secondary); font-size: var(--pas-xs); font-weight: 500; }
.tuile__valeur { margin-top: var(--esp-2); font-size: 1.6rem; font-weight: 600; line-height: 1.15; letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.tuile--attention .tuile__valeur { color: var(--etat-attention-encre); }
.tuile__note { margin-top: var(--esp-1); font-size: var(--pas-2xs); color: var(--color-muted); }

/* --- Fournisseurs --------------------------------------------------------- */
/* L'en-tête de l'onglet ; le tableau lui-même est plus bas, avec ses cellules. */

/* --- Panneaux et cartes --------------------------------------------------- */

.panneaux {
  display: grid; flex: 1; min-width: 0; min-height: 0;
}

/*
 * Le panneau actif est LE cadre qui défile. Tout au-dessus — titre, tuiles,
 * onglets — reste visible en permanence.
 */
.panneaux > [role="tabpanel"] {
  display: grid;
  align-content: start;
  gap: var(--esp-4);
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* La marge de droite évite que la barre de défilement colle aux cartes. */
  padding-right: var(--esp-1);
}

/* L'en-tête du tableau reste lisible pendant qu'on parcourt l'historique. */
.tableau-lignes thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-background);
}

.carte {
  min-width: 0; padding: var(--esp-5); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-background);
}

.carte h2 {
  font-size: var(--pas-xl);
  margin-bottom: var(--esp-3);
  color: color-mix(in srgb, var(--color-text) 94%, var(--color-brand-deep));
}

.carte-succes {
  border-left: 3px solid var(--etat-ok);
}
.carte-attention {
  border-left: 3px solid var(--etat-attention);
}
.carte-erreur {
  border-left: 3px solid var(--etat-erreur);
}

.etat-chargement {
  color: var(--color-muted);
}

.etat-ligne {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2) var(--esp-4);
  align-items: baseline;
  margin-bottom: var(--esp-2);
}

.etat-ligne:last-child {
  margin-bottom: 0;
}

.etiquette {
  min-width: 10rem;
  font-size: var(--pas-sm);
  color: var(--color-muted);
}

.valeur {
  font-weight: 600;
}

/* --- Zone de dépôt -------------------------------------------------------- */

.depot {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--esp-3); padding: var(--esp-7) var(--esp-5); min-height: 21rem; border: 1px dashed var(--color-muted); border-radius: var(--radius-sm); background: var(--color-background); text-align: center; cursor: pointer; transition: border-color .15s ease, background-color .15s ease;
}

.depot:hover {
  border-color: var(--color-accent);
}

.depot-actif {
  border-color: var(--color-brand-deep);
  background-color: color-mix(in srgb, var(--color-accent) 8%, var(--color-background));
}

.depot__icone {
  width: 3rem; height: 3rem; margin-bottom: var(--esp-3); fill: none; stroke: var(--color-brand-deep); stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round;
}

.depot__titre {
  font-family: var(--font-body); font-weight: 600; font-size: 1.5rem; line-height: 1.2; letter-spacing: -.03em;
}

.depot__aide {
  font-size: var(--pas-sm);
  color: var(--color-muted);
  max-width: 42ch;
}

/* --- Boutons -------------------------------------------------------------- */
/*
 * Même géométrie que `.button` du thème (rayon, ombre, majuscules espacées),
 * mais encre foncée au lieu du blanc : blanc sur `--color-accent` ne donne que
 * 2,8:1, sous le seuil AA de 4,5:1. Le noir sur le même rose monte à 6,2:1 —
 * on garde donc le rose exact de la boutique, en le rendant lisible.
 */

/*
 * Le bouton, redessine le 2026-09-11 : il se lisait flou.
 *
 * Trois causes, trois remedes :
 *  - un halo colore de 24 px autour du bouton → une ombre de 1 px ;
 *  - de l'encre noire sur l'accent → `--sur-accent`, blanche ou noire selon
 *    la clarte de l'accent de la boutique ;
 *  - des capitales de 12 px espacees, et un saut de 1 px au survol qui fait
 *    re-echantillonner le texte → une casse normale a 14 px, et un survol qui
 *    fonce la couleur au lieu de deplacer le bouton.
 */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--esp-2);
  min-height: 2.5rem;
  margin-top: var(--esp-3);
  padding: 0.55rem 1.1rem;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  background: var(--color-accent);
  color: var(--sur-accent);
  box-shadow: var(--shadow-accent);
  font: inherit;
  font-size: var(--pas-sm);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.bouton:hover {
  background: color-mix(in srgb, var(--color-accent) 86%, var(--melange-profond));
  border-color: color-mix(in srgb, var(--color-accent) 86%, var(--melange-profond));
}

.bouton:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.bouton-discret {
  min-height: 2rem;
  margin-top: 0;
  padding: 0.35rem 0.8rem;
  background: var(--color-background);
  border-color: var(--color-border);
  color: var(--color-text);
  box-shadow: none;
  font-weight: 500;
}

.bouton-discret:hover {
  border-color: color-mix(in srgb, var(--color-accent) 55%, var(--color-border));
  background: color-mix(in srgb, var(--color-accent) 6%, var(--color-background));
  color: var(--color-text);
}

/* --- Progression ---------------------------------------------------------- */
/*
 * Vraies puces reliées par un rail, au lieu des glyphes texte « ○ ● ◐ » qui
 * changeaient de dessin selon la police installée.
 */

.etapes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--esp-3);
}

.etape {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr);
  gap: var(--esp-3);
  align-items: start;
  color: var(--color-muted);
  font-size: var(--pas-sm);
}

.etape__puce {
  position: relative;
  width: 1rem;
  height: 1rem;
  margin-top: 0.2rem;
  border: 2px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-background);
}

/* Rail qui relie une puce à la suivante. */
.etape:not(:last-child) .etape__puce::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  translate: -50% 0;
  width: 2px;
  height: calc(var(--esp-3) + 0.2rem);
  background: var(--color-border);
}

.etape--fait {
  color: var(--color-text);
}

.etape--fait .etape__puce {
  border-color: var(--etat-ok);
  background: var(--etat-ok);
}

.etape--fait .etape__puce::after {
  background: var(--etat-ok);
}

.etape--encours {
  color: var(--color-text);
  font-weight: 600;
}

.etape--encours .etape__puce {
  border-color: var(--color-brand-deep);
  animation: pulsation 1.4s ease-in-out infinite;
}

@keyframes pulsation {
  0%,
  100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-accent) 55%, transparent);
  }
  60% {
    box-shadow: 0 0 0 6px color-mix(in srgb, var(--color-accent) 0%, transparent);
  }
}

@keyframes apparaitre {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

/* --- Pastilles d'état ----------------------------------------------------- */
/*
 * La couleur ne porte jamais seule : chaque pastille garde son libellé écrit.
 * Le vert et l'ambre ne se séparent qu'à ΔE 7,2 en vision protanope — le mot
 * est ce qui tranche.
 */

.pastille {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.15rem 0.6rem;
  border-radius: var(--radius-pill);
  font-size: var(--pas-2xs);
  font-weight: 600;
  white-space: nowrap;
}

.pastille::before {
  content: "";
  width: 0.45rem;
  height: 0.45rem;
  border-radius: var(--radius-pill);
  background: currentColor;
  flex: none;
}

.pastille-ok {
  background: color-mix(in srgb, var(--etat-ok) 12%, var(--color-background));
  color: var(--etat-ok);
}

.pastille-attention {
  background: color-mix(in srgb, var(--etat-attention) 14%, var(--color-background));
  color: var(--etat-attention-encre);
}

.pastille-verif {
  background: color-mix(in srgb, var(--color-accent) 16%, var(--color-background));
  color: var(--color-brand-deep);
}

.pastille-erreur {
  background: color-mix(in srgb, var(--etat-erreur) 10%, var(--color-background));
  color: var(--etat-erreur);
}

.pastille-attente {
  background: var(--color-surface);
  color: var(--color-secondary);
}

.avertissement {
  margin: var(--esp-3) 0;
  padding: var(--esp-3) var(--esp-4);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--etat-attention);
  background: color-mix(in srgb, var(--etat-attention) 8%, var(--color-background));
  color: var(--etat-attention-encre);
  font-size: var(--pas-sm);
}

/* --- Filtres de l'historique ---------------------------------------------- */
/* Une seule rangée au-dessus du tableau : les filtres se lisent d'un coup, et
   ce qu'ils cachent se dit dans le compte du titre (« 3 sur 12 »). */

.filtres {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--esp-3);
  margin-bottom: var(--esp-3);
  padding-bottom: var(--esp-3);
  border-bottom: 1px solid var(--panneau-bordure);
}

.filtre {
  display: grid;
  gap: 0.2rem;
  min-width: 0;
}

.filtre--large {
  flex: 1;
  min-width: 12rem;
}

.filtre__etiquette {
  font-size: var(--pas-2xs);
  font-weight: 600;
  color: var(--color-muted);
}

.filtres .bouton-discret {
  margin-bottom: 0.1rem;
}

/* --- En-têtes triables ----------------------------------------------------- */

.tri {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}

.tri:hover {
  color: var(--color-brand-deep);
}

.tri--actif {
  color: var(--color-brand-deep);
}

/* Réservée en permanence : sans largeur fixe, la colonne sautait d'un cran au
   moment où la flèche apparaît. */
.tri__fleche {
  width: 0.7rem;
  font-size: 0.55rem;
}

.nombre .tri {
  /* Le libellé reste collé à droite, au-dessus de ses chiffres. */
  flex-direction: row-reverse;
}

/* --- Tableaux ------------------------------------------------------------- */

.table-defilante {
  overflow-x: auto;
  margin-top: var(--esp-3);
}

.tableau-lignes {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--pas-sm);
}

.tableau-lignes th {
  text-align: left;
  padding: var(--esp-2) var(--esp-3);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--pas-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
  white-space: nowrap;
}

.tableau-lignes td {
  padding: var(--esp-3);
  border-bottom: 1px solid color-mix(in srgb, var(--color-border) 55%, var(--color-background));
  vertical-align: middle;
}

.tableau-lignes tbody tr {
  transition: background 0.12s ease;
}

.tableau-lignes tbody tr:hover {
  background: color-mix(in srgb, var(--color-accent) 5%, var(--color-background));
}

.tableau-lignes tbody tr:last-child td {
  border-bottom: none;
}

/* Colonnes de chiffres : là, l'alignement vertical prime sur la largeur. */
.tableau-lignes .nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cellule-tailles {
  font-variant-numeric: tabular-nums;
  color: var(--color-muted);
  font-size: var(--pas-xs);
}

.cellule-actions {
  display: flex;
  gap: var(--esp-2);
  align-items: center;
  white-space: nowrap;
}

/*
 * L'historique porte neuf colonnes, et sa cellule d'actions en compte trois.
 * Mesuré : le tableau réclamait 1111 px pour un cadre de 1082 — vingt-neuf de
 * trop, et la poubelle sortait par la droite. On resserre les gouttières
 * plutôt que d'imposer un défilement horizontal sur une action fréquente.
 *
 * Le plancher, lui, ne sert que sous 58 rem : là, le tableau défile pour de
 * bon au lieu de s'écraser.
 */
#historique-corps .tableau-lignes {
  min-width: 58rem;
}

#historique-corps .tableau-lignes th,
#historique-corps .tableau-lignes td {
  padding-inline: 0.55rem;
}

#historique-corps .cellule-actions {
  gap: 0.35rem;
}

/* Une date ne se coupe pas en deux : le troisième bouton d'action a serré le
   tableau, et « 2026-08-07 » passait sur deux lignes. */
.tableau-lignes td[data-libelle="Déposée"],
.tableau-lignes td[data-libelle="Date"] {
  white-space: nowrap;
}

.sans-pdf {
  color: var(--color-muted);
  padding: 0 var(--esp-2);
}

/* --- État vide ------------------------------------------------------------ */

.vide {
  display: grid;
  justify-items: center;
  gap: var(--esp-2);
  padding: var(--esp-6) var(--esp-4);
  text-align: center;
}

.vide__icone {
  width: 3rem;
  height: 3rem;
  fill: none;
  stroke: var(--color-border);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.vide__titre {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: var(--pas-lg);
}

.vide__aide {
  font-size: var(--pas-sm);
  color: var(--color-muted);
  max-width: 38ch;
}

/* --- Fenêtre de la facture ------------------------------------------------ */
/* `<dialog>` natif : fond assombri, piège de focus et fermeture par Échap
   viennent du navigateur, sans une ligne de script. */

.fenetre {
  /* Presque plein écran : on compare un PDF à sa lecture, la place est le
     premier confort. Hauteur figée, jamais dépassée — ce sont les volets qui
     défilent. */
  width: min(100rem, calc(100vw - 2rem));
  height: min(58rem, calc(100dvh - 2rem));
  max-height: calc(100dvh - 2rem);
  padding: 0;
  border: none;
  border-radius: var(--radius-xl);
  background: var(--color-background);
  color: var(--color-text);
  box-shadow: var(--shadow-fenetre);
  overflow: hidden;
}

/*
 * La mise en page ne s'applique QU'À L'ÉTAT OUVERT. Un `display: flex` sur
 * `.fenetre` tout court écrase le `display: none` que le navigateur pose sur
 * un `<dialog>` fermé : la fenêtre restait alors étalée sur la page, invisible
 * mais interceptant tous les clics.
 */
.fenetre[open] {
  display: flex;
  flex-direction: column;
  animation: apparaitre 0.2s ease both;
}

.fenetre::backdrop {
  background: var(--voile-fenetre);
  backdrop-filter: blur(2px);
}

.fenetre-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-4);
  padding: var(--esp-4) var(--esp-5);
  border-bottom: 1px solid var(--panneau-bordure);
  background: var(--panneau-lavis), var(--color-background);
  /* L'en-tête reste visible quand la liste des lignes défile. */
  position: sticky;
  top: 0;
}

.fenetre-entete h2 {
  font-size: var(--pas-xl);
  color: color-mix(in srgb, var(--color-text) 94%, var(--color-brand-deep));
}

.fenetre-fermer {
  border: none;
  background: none;
  color: var(--color-muted);
  font-size: 1.6rem;
  line-height: 1;
  padding: 0 var(--esp-1);
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.fenetre-fermer:hover {
  color: var(--color-brand-deep);
}

.fenetre-actions {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
}

.fenetre-actions .bouton {
  margin-top: 0;
}

.bouton:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

/*
 * Fenêtre d'avertissement : étroite, et haute seulement de son contenu.
 *
 * Le sélecteur double n'est pas un tic : `.fenetre` fixe une hauteur pleine
 * pour la comparaison PDF, et à spécificité égale c'est l'ordre du fichier qui
 * tranche. Sans ce renfort, l'avertissement s'étirait sur tout l'écran avec un
 * grand vide sous ses deux boutons.
 */
.fenetre.fenetre--etroite {
  width: min(30rem, calc(100vw - 2rem));
  /*
   * `fit-content`, surtout pas `auto`. Un `<dialog>` modal est en
   * `position: fixed` avec `inset: 0` ; en positionnement absolu, une hauteur
   * `auto` bornée en haut ET en bas remplit tout l'espace disponible. C'est
   * pour ça que la feuille du navigateur lui donne `fit-content` — l'écraser
   * avec `auto` rallume l'étirement, et l'avertissement occupait tout l'écran
   * avec un grand vide sous ses boutons.
   */
  height: fit-content;
  max-height: calc(100dvh - 4rem);
}

.fenetre--etroite .fenetre-corps {
  overflow-y: auto;
}

.fenetre-pied {
  display: flex;
  justify-content: flex-end;
  gap: var(--esp-3);
  margin-top: var(--esp-2);
}

/*
  Les deux boutons de la fenetre d'acces, exactement de meme taille (demande
  du 2026-09-15).

  `.bouton-discret` est plus petit que `.bouton` PARTOUT ailleurs, et le
  `.bouton` porte un `margin-top` qui le decale en plus : egaliser la regle
  generale redimensionnerait tous les boutons secondaires de l'application.
  La correction reste donc portee par cette fenetre.

  Le `min-width` fixe la largeur des deux : leurs libelles n'ont pas la meme
  longueur, et `white-space: nowrap` interdit le retour a la ligne, donc sans
  lui l'egalite de rembourrage ne suffirait pas.
*/
#fenetre-acces .fenetre-pied .bouton {
  min-height: 2.5rem;
  min-width: 11.5rem;
  margin-top: 0;
  padding: 0.55rem 1.1rem;
  font-weight: 600;
}

/*
  Au telephone, deux fois 11,5 rem plus l'ecart depassent la fenetre, qui vaut
  `min(30rem, 100vw - 2rem)`. Les boutons passent donc l'un sous l'autre, et
  prennent toute la largeur : ils restent de meme taille, ce qui etait la
  demande, sans pousser un debordement horizontal.
*/
@media (max-width: 30rem) {
  #fenetre-acces .fenetre-pied {
    flex-direction: column;
  }

  #fenetre-acces .fenetre-pied .bouton {
    min-width: 0;
    width: 100%;
  }
}

/* Précision utile, ni alerte ni danger : la teinte de la marque, comme le
   récapitulatif d'envoi, sans sa marge. */
.bandeau--note {
  background: color-mix(in srgb, var(--color-accent) 8%, var(--color-background));
  border-left: 3px solid var(--color-accent);
}

.bandeau--danger {
  background: color-mix(in srgb, var(--etat-erreur) 8%, var(--color-background));
  border-left: 3px solid var(--etat-erreur);
  color: var(--color-text);
}

/*
 * Le geste destructeur porte la couleur de l'erreur, pas le rose de la marque :
 * il ne doit jamais se confondre avec l'action ordinaire.
 */
.bouton-danger {
  margin-top: 0;
  background: var(--etat-erreur);
  border-color: var(--etat-erreur);
  color: var(--sur-etat);
  box-shadow: none;
}

.bouton-danger:focus-visible {
  outline-color: var(--etat-erreur);
}

.bouton-danger:hover {
  background: color-mix(in srgb, var(--etat-erreur) 85%, var(--melange-profond));
  border-color: color-mix(in srgb, var(--etat-erreur) 85%, var(--melange-profond));
  box-shadow: none;
}

/*
 * Bouton réduit à son icône. Carré et non pastille : à côté de « DÉTAIL » et
 * « PDF » qui sont du texte, une forme différente se repère plus vite qu'une
 * couleur — et la cible reste à 2 rem, doigt compris.
 */
.bouton-icone {
  padding: 0;
  width: 2rem;
  height: 2rem;
  flex: none;
  border-radius: var(--radius-sm);
}

.bouton-icone svg {
  width: 1.05rem;
  height: 1.05rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Discret dans le tableau — c'est la fenêtre qui porte l'avertissement. */
.bouton-supprimer {
  color: var(--etat-erreur);
}

.bouton-supprimer:hover {
  border-color: var(--etat-erreur);
  background: color-mix(in srgb, var(--etat-erreur) 7%, var(--color-background));
}

/* --- Comparaison : le document à gauche, sa lecture à droite -------------- */

/*
 * Le document prend tout ce que l'analyse ne réclame pas.
 *
 * Un partage en pourcentages fixes servait mal les deux : l'analyse a un
 * besoin PRÉCIS — la largeur de son tableau de six colonnes, ni plus ni moins
 * — tandis que le PDF profite de chaque pixel supplémentaire. D'où une colonne
 * de droite bornée, et une colonne de gauche qui absorbe le reste : sur un
 * écran large, c'est le document qui s'agrandit.
 */
.comparaison {
  flex: 1;
  min-height: 0;
  display: grid;
  /*
   * Moitié-moitié dès qu'il y a la place, et jamais moins que ce que le
   * tableau exige : son plancher de 41 rem plus les gouttières font 46 rem.
   * Sans ce minimum, à 1440 il manquait 32 px et le tableau se mettait à
   * défiler horizontalement — donc tout n'était plus visible d'un coup.
   */
  grid-template-columns: minmax(0, 1fr) minmax(47rem, 1fr);
}

.volet {
  min-width: 0;
  min-height: 0;
}

.volet--document {
  border-right: 1px solid var(--panneau-bordure);
  background: var(--color-surface);
  display: grid;
  place-items: stretch;
}

.apercu-pdf {
  width: 100%;
  height: 100%;
  border: none;
  display: block;
}

.volet__vide {
  place-self: center;
  padding: var(--esp-5);
  max-width: 30ch;
  text-align: center;
  color: var(--color-muted);
  font-size: var(--pas-sm);
}

.volet--analyse {
  overflow-y: auto;
  overscroll-behavior: contain;
}

.fenetre-corps {
  padding: var(--esp-5);
  display: grid;
  gap: var(--esp-4);
}

/* --- Formulaire de correction --------------------------------------------- */

.bloc {
  margin: 0;
  padding: var(--esp-4);
  border: 1px solid var(--panneau-bordure);
  border-radius: var(--radius-md);
  min-width: 0;
}

.bloc__titre {
  padding: 0 var(--esp-2);
  font-size: var(--pas-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* Quatre colonnes : empilés, l'en-tête et les totaux faisaient huit rangées et
   repoussaient les lignes de la facture hors de l'écran. */
/*
 * Trois bandes partagees : etiquette, saisie, aide.
 *
 * Chaque `.champ` etait une grille isolee, et rien n'alignait ses lignes sur
 * celles de son voisin : un champ dont l'aide tient sur deux lignes etirait le
 * champ d'a cote, dont la saisie devenait plus haute que les autres. `subgrid`
 * fait porter les trois lignes par la grille PARENTE — les etiquettes se
 * suivent, les saisies aussi, et une aide longue ne pousse plus que la bande
 * d'aide.
 */
.grille-champs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: auto;
  gap: var(--esp-3) var(--esp-3);
  align-items: start;
}

.champ {
  display: grid;
  gap: 0.2rem;
  min-width: 0;
}

.grille-champs > .champ {
  grid-row: span 3;
  grid-template-rows: subgrid;
  row-gap: 0.2rem;
}

/* Une saisie et une liste deroulante n'ont pas la meme hauteur naturelle. Sans
   plancher commun, deux champs cote a cote ne se repondent pas. */
.champ__saisie {
  min-height: 2.15rem;
}

.champ--large {
  grid-column: span 2;
}

.champ__etiquette {
  font-size: var(--pas-2xs);
  font-weight: 600;
  color: var(--color-muted);
}

.champ__aide {
  font-size: var(--pas-2xs);
  color: var(--color-muted);
}

.champ__saisie {
  width: 100%;
  min-width: 0;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-background);
  color: inherit;
  font: inherit;
  font-size: var(--pas-sm);
}

.champ__saisie:hover {
  border-color: var(--color-accent);
}

/*
 * Saisie en cellule : le cadre n'apparaît qu'au survol ou au focus, sinon un
 * tableau de dix lignes ressemblerait à un formulaire administratif.
 *
 * C'est un `<textarea>` qui s'ajuste à son texte, pas un champ d'une ligne :
 * « XS:1 S:1 M:1 L:1 XL:1 XXL:1 » ne tient pas sur une ligne dans un demi-
 * écran, et une valeur coupée est exactement ce qu'on vient vérifier.
 * `field-sizing` fait le travail sur Chrome ; ailleurs, app.js règle la
 * hauteur.
 */
.cellule__saisie {
  width: 100%;
  min-width: 4rem;
  padding: 0.25rem 0.4rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: inherit;
  font: inherit;
  font-size: var(--pas-sm);
  line-height: 1.35;
  field-sizing: content;
  overflow-wrap: normal;
  word-break: normal;
  resize: none;
  overflow: hidden;
  display: block;
}

.cellule__saisie:hover {
  border-color: var(--color-border);
}

/*
 * Le code article, lui, a le droit de se couper.
 *
 * `word-break: normal` protège « KAbabena » d'une coupure en plein mot, mais
 * une référence n'est pas un mot : elle se lit par morceaux, et mieux vaut
 * « C2689RD/ » puis « 736A » qu'un code tronqué. Ce qu'on vient vérifier ne
 * doit jamais sortir du cadre.
 */
.cellule__saisie[data-chemin$=".code_style"] {
  overflow-wrap: break-word;
  word-break: break-all;
}

.cellule__saisie:focus {
  border-color: var(--color-accent);
  background: var(--color-background);
}

.tableau-lignes--saisie td {
  padding: 0.15rem 0.25rem;
}

/*
 * Largeurs réelles plutôt qu'un partage à parts égales. Serrées dans un demi-
 * écran, les colonnes rognaient ce qu'on vient précisément vérifier :
 * « C3260/811C » devenait « C3260/8 ». En dessous de cette largeur le tableau
 * défile horizontalement dans son cadre — la fenêtre, elle, ne bouge pas.
 */
/*
 * Six colonnes : Code, Couleur, Libellé, Tailles, Qté, Prix.
 * En `table-layout: fixed`, SEULE la première rangée fixe les largeurs — une
 * règle posée sur une cellule du corps n'a aucun effet. Le libellé prend ce
 * qui reste.
 */
.tableau-lignes--saisie {
  /*
   * Plancher mesuré : sous 41 rem, le libellé tombe à 80 px et « KAbabena
   * Denim Shorts » se rogne — un nom d'article ne se coupe pas en plein mot,
   * il ne peut donc que déborder. En dessous, le tableau défile dans son cadre
   * plutôt que d'écraser ses colonnes.
   */
  min-width: 41rem;
  table-layout: fixed;
}

/* Mesuré sur une facture Charlie B : « C2689RD/736A » réclame 111 px, quand
   les codes DK à huit chiffres se contentaient de 82. */
.tableau-lignes--saisie th:nth-child(1) {
  width: 7.25rem;
}
.tableau-lignes--saisie th:nth-child(2) {
  width: 7rem;
}
/* Le libellé et les tailles sont les deux colonnes qui débordent : elles se
   partagent tout ce que les quatre autres ne prennent pas, et leur contenu
   passe sur deux lignes plutôt que d'être coupé. */
.tableau-lignes--saisie th:nth-child(4) {
  width: 9.25rem;
}

/* --- Pastilles de tailles ------------------------------------------------- */
/*
 * Une pastille par taille RÉELLEMENT lue : nom fixe, quantité modifiable, et
 * une croix pour la retirer. Le « + » en ajoute une que le parseur aurait
 * manquée.
 *
 * Tout est calibré pour tenir en DEUX rangées : au-delà, la ligne du produit
 * devient plus haute que ce qu'elle décrit. La croix ne prend aucune place —
 * elle se superpose au coin de la pastille et n'apparaît qu'au survol.
 */

.tailles {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem;
  align-items: start;
  /*
   * DEUX RANGÉES, jamais plus : au-delà, la ligne du produit devient plus
   * haute que ce qu'elle décrit. Une facture qui porterait plus de sept
   * tailles défile dans cette case plutôt que d'étirer toute la rangée.
   */
  /* Mesuré, pas estimé : une pastille fait 38,1 px, donc deux rangées plus leur
     gouttière demandent 79 px. */
  max-height: 5rem;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.taille {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 0.05rem;
  padding-top: 0.15rem;
  /* Figée : sans ça « XL/XXL » élargit sa pastille et fait déborder la rangée.
     Assez étroite pour que QUATRE tiennent par rangée — à cinq de large, la
     barre de défilement du plafond volait la place de la quatrième, ce qui
     ramenait à trois rangées, ce qui rappelait la barre. */
  width: 1.8rem;
}

.taille__nom {
  width: 100%;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--color-muted);
  line-height: 1;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.taille__qte {
  width: 100%;
  padding: 0.1rem 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: inherit;
  font: inherit;
  font-size: var(--pas-xs);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.taille__qte:hover {
  border-color: var(--color-border);
}

.taille__qte:focus {
  border-color: var(--color-accent);
  background: var(--color-background);
}

/* Superposée au coin : elle ne consomme pas de largeur dans la rangée. */
.taille__retirer {
  position: absolute;
  top: -0.25rem;
  right: -0.2rem;
  width: 0.85rem;
  height: 0.85rem;
  display: grid;
  place-items: center;
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--etat-erreur);
  color: var(--sur-etat);
  font-size: 0.6rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.taille:hover .taille__retirer,
.taille:focus-within .taille__retirer,
.taille__retirer:focus-visible {
  opacity: 1;
}

/*
 * La liste d'ajout garde la taille et l'allure d'un bouton « + ».
 * `appearance: none` retire la flèche native, qui l'aurait élargie de moitié
 * et fait déborder la rangée ; la liste s'ouvre quand même au clic.
 */
.taille-ajouter {
  align-self: end;
  flex: none;
  width: 1.3rem;
  height: 1.3rem;
  padding: 0;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-brand-deep);
  font: inherit;
  font-size: var(--pas-sm);
  line-height: 1;
  text-align: center;
  text-align-last: center;
  cursor: pointer;
  appearance: none;
}

/* Les tailles de la liste, elles, se lisent normalement. */
.taille-ajouter option {
  font-size: var(--pas-sm);
  text-align: left;
}

.taille-ajouter:hover {
  border-color: var(--color-accent);
  border-style: solid;
  background: color-mix(in srgb, var(--color-accent) 8%, var(--color-background));
}

.tableau-lignes--saisie th:nth-child(5) {
  width: 3.25rem;
}
.tableau-lignes--saisie th:nth-child(6) {
  width: 4.25rem;
}

/* Sur deux lignes, une cellule doit s'aligner par le haut avec ses voisines. */
.tableau-lignes--saisie td {
  vertical-align: top;
}

.tableau-lignes--saisie .nombre .cellule__saisie {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/*
 * La quantité se centre dans sa colonne. Alignée à droite, elle venait toucher
 * le prix de la colonne suivante : « 6 » et « 49.50 » se lisaient comme un seul
 * nombre. Le prix, lui, reste à droite — c'est un montant, et les montants
 * s'alignent sur leur virgule.
 */
.tableau-lignes--saisie td:nth-child(5) .cellule__saisie {
  text-align: center;
}


/* La ligne que les contrôles arithmétiques désignent. */
.rangee--fautive {
  background: color-mix(in srgb, var(--etat-attention) 9%, var(--color-background));
}


/* --- Bandeau des contrôles ------------------------------------------------ */

.bandeau {
  padding: var(--esp-3) var(--esp-4);
  border-radius: var(--radius-md);
  font-size: var(--pas-sm);
}

.bandeau--alerte {
  background: color-mix(in srgb, var(--etat-attention) 10%, var(--color-background));
  border-left: 3px solid var(--etat-attention);
  color: var(--etat-attention-encre);
}

/*
 * Le récapitulatif d'envoi. Bleu et non ambre : ce n'est pas une alerte, c'est
 * un constat qu'on demande de valider. L'ambre est réservé à ce qui cloche.
 */
.bandeau--envoi {
  margin: 0 var(--esp-5) var(--esp-3);
  background: color-mix(in srgb, var(--color-accent) 8%, var(--color-background));
  border-left: 3px solid var(--color-accent);
}

/*
 * « Annuler » dans le tableau : il change l'inventaire de la boutique, là où
 * « Détail » et « PDF » ne font que montrer. L'encre ambre le distingue sans
 * en faire une alerte — ce n'est pas une erreur, c'est un geste qui compte.
 */
.bouton-annuler {
  color: var(--etat-attention-encre);
  border-color: color-mix(in srgb, var(--etat-attention) 45%, transparent);
}

/* Dans la carte de l'historique, la marge latérale de la fenêtre n'a pas lieu
   d'être : la carte porte déjà son propre rembourrage. */
.bandeau--historique {
  margin: 0 0 var(--esp-4);
}

.bandeau--envoi.bandeau--alerte {
  background: color-mix(in srgb, var(--etat-attention) 10%, var(--color-background));
  border-left-color: var(--etat-attention);
}

.bandeau__chiffres {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2) var(--esp-4);
  margin: var(--esp-2) 0 0;
  padding: 0;
  list-style: none;
}

.bandeau__chiffre strong {
  font-variant-numeric: tabular-nums;
}

.bandeau__titre {
  font-weight: 600;
}

.bandeau__liste {
  margin: var(--esp-2) 0 0;
  padding-left: 1.1rem;
  display: grid;
  gap: var(--esp-2);
}

.note-correction {
  font-size: var(--pas-xs);
  color: var(--color-muted);
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 64rem) {
  .onboarding__carte {
    grid-template-columns: minmax(0, 1fr);
  }

  .equipe__invitation {
    grid-template-columns: minmax(0, 1fr) minmax(10rem, 0.6fr);
  }

  .equipe__invitation .bouton {
    justify-self: start;
  }

  .tuiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /*
   * Sous 1024 px, une colonne de 14,5 rem prend le quart de l'écran pour six
   * mots. Le rail repasse au-dessus du contenu, en bande qui défile
   * horizontalement — aucune entrée ne disparaît, aucune ne change de rang.
   */
  .coquille {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    gap: var(--esp-4);
  }

  .rail__groupe {
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    gap: var(--esp-1);
    overflow-x: auto;
    overscroll-behavior-x: contain;
  }

  .grille-champs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /*
   * Deux volets côte à côte sous 1024 px donneraient deux colonnes trop
   * étroites pour l'un comme pour l'autre. Empilés, le document garde une
   * hauteur fixe et l'analyse prend le reste — chacun défilant chez lui, la
   * fenêtre elle-même ne défile toujours pas.
   */
  .comparaison {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 2fr) minmax(0, 3fr);
  }

  .volet--document {
    border-right: none;
    border-bottom: 1px solid var(--panneau-bordure);
  }
}

@media (max-width: 40rem) {
  :root {
    --hauteur-barre: 3.5rem;
  }

  .onboarding {
    padding: var(--esp-4);
  }

  .onboarding__carte {
    gap: var(--esp-5);
    padding: var(--esp-5);
  }

  .onboarding__etapes {
    grid-template-columns: minmax(0, 1fr);
  }

  .equipe__invitation {
    grid-template-columns: minmax(0, 1fr);
  }

  .equipe__lien {
    align-items: stretch;
    flex-direction: column;
  }

  /*
   * Les tuiles restent sur deux colonnes jusqu'en bas. Empilées, elles
   * repoussaient la zone de dépôt — l'action principale — sous la ligne de
   * flottaison d'un téléphone.
   */
  .tuiles {
    gap: var(--esp-2);
  }

  .tuile {
    padding: var(--esp-3);
  }

  /* Le cumul « depuis le début » saute ; l'écart à trancher, lui, reste. */
  .tuile:not(.tuile--attention) .tuile__note {
    display: none;
  }

  .carte {
    padding: var(--esp-4);
  }

  .etiquette {
    min-width: 100%;
  }

  .barre-etat__utilisatrice span:not(.jeton-initiales) {
    display: none;
  }

  .marque__logo {
    /* Sur mobile la barre doit rester basse : le logo grandit, mais moins. */
    max-height: 2.5rem;
  }

  .grille-champs {
    grid-template-columns: minmax(0, 1fr);
  }

  .fenetre {
    width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    border-radius: 0;
  }

  .fenetre-corps {
    padding: var(--esp-4);
  }

  /* Les inputs en cellule reprennent leur cadre : dans la liste de cartes du
     mode téléphone, un champ sans bordure ne se voit plus comme modifiable. */
  .cellule__saisie {
    border-color: var(--color-border);
    background: var(--color-background);
  }

  /* En cartes empilées, la largeur minimale du tableau n'a plus de sens. */
  .tableau-lignes--saisie {
    min-width: 0;
    table-layout: auto;
  }


  /*
   * Neuf colonnes ne tiennent pas sur un téléphone. Le tableau devient une
   * liste de cartes empilées — en CSS seul : un unique balisage, aucun DOM
   * dupliqué, aucune media query en JavaScript. Le nom de colonne est repris
   * de l'attribut `data-libelle` posé sur chaque cellule.
   */
  .table-defilante {
    overflow-x: visible;
  }

  .tableau-lignes,
  .tableau-lignes tbody,
  .tableau-lignes tr,
  .tableau-lignes td {
    display: block;
    width: 100%;
  }

  .tableau-lignes thead {
    /* `display: none` sortirait l'en-tête de l'arbre d'accessibilité. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .tableau-lignes tr {
    margin-bottom: var(--esp-3);
    padding: var(--esp-3);
    border: 1px solid var(--panneau-bordure);
    border-radius: var(--radius-md);
    background: var(--color-background);
  }

  .tableau-lignes tbody tr:last-child {
    margin-bottom: 0;
  }

  .tableau-lignes td {
    display: grid;
    grid-template-columns: 8rem minmax(0, 1fr);
    gap: var(--esp-3);
    align-items: baseline;
    padding: var(--esp-1) 0;
    border-bottom: none;
    text-align: left;
  }

  .tableau-lignes td[data-libelle]::before {
    content: attr(data-libelle);
    font-size: var(--pas-2xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-muted);
  }

  .tableau-lignes .nombre {
    text-align: left;
  }

  .cellule-actions {
    padding-top: var(--esp-2);
  }
}

/* --- Navigation entre les factures d'un même PDF --------------------------- */

/*
 * Cette barre doit se voir. Un PDF Tribal porte plusieurs factures, et rien à
 * l'écran ne le laisse deviner : sans repère visible, la seconde reste
 * ignorée. D'où le cadre plein, à côté du titre et non perdu dans les actions.
 */
.fenetre-fratrie {
  display: flex;
  align-items: center;
  gap: var(--esp-1);
  margin-right: auto;
  margin-left: var(--esp-4);
  padding: var(--esp-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  font-size: var(--pas-sm);
  font-weight: 600;
  white-space: nowrap;
}

.fenetre-fratrie__rang {
  padding: 0 var(--esp-2);
}

.fenetre-fratrie button {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border-radius: var(--radius-pill);
  font-size: var(--pas-xl);
  line-height: 1;
}

.fenetre-fratrie button:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/*
 * Une facture n'a pas encore été ouverte : la barre passe en signal, et la
 * flèche qui y mène bat doucement. L'envoi est bloqué tant que c'est le cas —
 * le mouvement dit où cliquer pour le débloquer.
 */
.fenetre-fratrie--attente {
  border-color: var(--etat-attention);
  background: color-mix(in srgb, var(--etat-attention) 12%, var(--color-background));
  color: var(--etat-attention-encre);
}

.fenetre-fratrie--attente #facture-suivante:not(:disabled) {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--sur-accent);
  animation: fratrie-appel 1.6s ease-in-out infinite;
}

@keyframes fratrie-appel {
  0%,
  100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-accent) 55%, transparent);
  }
  50% {
    box-shadow: 0 0 0 6px color-mix(in srgb, var(--color-accent) 0%, transparent);
  }
}

/* --- Dépôt à plusieurs factures ------------------------------------------- */

.depot-multiple {
  list-style: none;
  margin: var(--esp-4) 0 0;
  padding: 0;
  display: grid;
  gap: var(--esp-2);
}

.depot-multiple__ligne {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
  flex-wrap: wrap;
  padding: var(--esp-2) var(--esp-3);
  background: var(--color-surface);
  border-radius: var(--radius-sm);
}

.depot-multiple__numero {
  font-weight: 600;
}

/* Pousse le bouton à droite sans marge négative ni valeur en dur. */
.depot-multiple__total {
  color: var(--color-muted);
  margin-right: auto;
  font-variant-numeric: tabular-nums;
}

/* --- Produits ------------------------------------------------------------- */

.tableau-produits td {
  vertical-align: middle;
}

.produit__visuel {
  width: 3.5rem;
}

.produit__vignette {
  width: 3rem;
  height: 3.75rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  display: block;
  background: var(--color-surface);
}

.produit__vignette--vide {
  display: grid;
  place-items: center;
  color: var(--color-muted);
}

.produit__titre {
  display: block;
  font-weight: 600;
}

.produit__handle {
  display: block;
  color: var(--color-muted);
  font-size: var(--pas-xs);
}

/* Une liste de coloris peut être longue ; le titre complet reste en infobulle. */
.produit__couleurs {
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* La ligne entière ouvre la fiche produit. */
.produit__ligne {
  cursor: pointer;
}

.produit__ligne:hover,
.produit__ligne:focus-visible {
  background: var(--color-surface);
}

.produit__replier {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  background: none;
  border: 0;
  padding: 0.125rem 0;
  color: var(--color-text);
  font: inherit;
  cursor: pointer;
}

.produit__replier:hover {
  text-decoration: underline;
}

/* Chevron en pur CSS : une icône de plus à charger pour un triangle. */
.produit__chevron {
  width: 0.4rem;
  height: 0.4rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 120ms ease;
}

.produit__replier[aria-expanded="true"] .produit__chevron {
  transform: rotate(45deg);
}

.produit__detail td {
  padding-top: 0;
}

.produit__coloris {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.produit__coloris li {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.125rem 0.5rem;
  font-size: var(--pas-xs);
  color: var(--color-muted);
}

.produit__nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.produit__note {
  display: block;
  color: var(--etat-attention-encre);
  font-size: var(--pas-xs);
}

/* --- Fiches incomplètes --------------------------------------------------- */

.visuel-aide {
  color: var(--color-muted);
  margin: 0 0 var(--esp-3);
}

.visuel-liste {
  display: grid;
  gap: var(--esp-4);
  margin-top: var(--esp-5);
}

.fiche {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--esp-4);
}

.fiche__tete h3 {
  margin: 0;
  font-size: 1rem;
}

.fiche__meta {
  margin: var(--esp-1) 0 var(--esp-3);
  color: var(--color-muted);
  font-size: 0.875rem;
}

.manques {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--esp-2);
}

.manque {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
  flex-wrap: wrap;
  padding: var(--esp-2) var(--esp-3);
  background: var(--color-surface);
  border-radius: var(--radius-sm);
  /* Le rail de gauche porte la gravité ; le libellé la porte aussi en toutes
     lettres, la couleur seule ne disant rien à qui ne la distingue pas. */
  border-left: 3px solid var(--etat-attention);
}

.manque--bloquant {
  border-left-color: var(--etat-erreur);
}

.manque__type {
  font-weight: 600;
  min-width: 7rem;
}

.manque__detail {
  color: var(--color-muted);
  font-size: 0.875rem;
  margin-right: auto;
}

/*
 * Un `<label>` qui contient l'`<input type="file">` : c'est le label qui ouvre
 * le sélecteur, sans une ligne de JavaScript. Le champ reste dans le DOM —
 * `display: none` le retirerait de la navigation au clavier.
 */
.manque__action {
  cursor: pointer;
}

.manque__action:has(input:disabled) {
  opacity: 0.6;
  cursor: progress;
}

/* --- Réglage de la pastille ------------------------------------------------ */

.pastille-validation {
  flex-basis: 100%;
  margin-top: var(--esp-3);
  padding-top: var(--esp-3);
  border-top: 1px solid var(--color-border);
}

.pastille-reglage {
  display: flex;
  gap: var(--esp-4);
  flex-wrap: wrap;
  align-items: flex-start;
}

/*
 * La scène porte la photo et le rond. `position: relative` sur elle, `absolute`
 * sur le rond, et tout se place en POURCENTAGES : l'image est fluide, un
 * positionnement en pixels dériverait au moindre changement de largeur.
 */
.pastille-scene {
  position: relative;
  flex: 0 0 auto;
  width: min(260px, 100%);
  line-height: 0;
  touch-action: none; /* sans quoi le doigt fait défiler la page au lieu de glisser */
  cursor: crosshair;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--color-border);
}

.pastille-scene__photo {
  width: 100%;
  height: auto;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

/*
 * Le rond d'échantillonnage. `aspect-ratio: 1` plutôt qu'une hauteur : le carré
 * mesuré est carré en PIXELS de la photo, et la largeur est déjà exprimée en
 * fraction de celle-ci.
 *
 * Double anneau — un trait sombre bordé de blanc — pour rester visible aussi
 * bien sur un tissu noir que sur du blanc cassé.
 */
.pastille-cible {
  position: absolute;
  aspect-ratio: 1;
  border-radius: var(--radius-pill);
  border: 2px solid var(--anneau-pastille-clair);
  box-shadow:
    0 0 0 2px var(--anneau-pastille-sombre),
    inset 0 0 0 1px var(--anneau-pastille-interne);
  cursor: grab;
}

.pastille-cible:active {
  cursor: grabbing;
}

.pastille-lecture {
  display: flex;
  align-items: center;
  gap: var(--esp-4);
  flex: 1 1 16rem;
}

/*
 * Le prélèvement retenu, à une taille où l'œil juge vraiment la couleur.
 *
 * **Rond, comme le rond qu'on déplace, et comme Shopify l'affichera.**
 *
 * Il était carré. Trois formes cohabitaient donc pour une même chose : un rond
 * sur la photo, un carré en aperçu, un rond en boutique — et ce qui logeait
 * dans les coins du carré n'avait jamais été visé. « La pastille devrait être
 * pareille à ce qu'il y a dans le rond », et c'était exact.
 *
 * La forme suit maintenant la mesure : `mesurerCarre` ne lit que le disque, et
 * `decouperPastille` ne découpe que le disque.
 */
.pastille-lecture__image,
.pastille-lecture__aplat {
  width: 88px;
  height: 88px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  object-fit: cover;
  flex: none;
}

.pastille-lecture__aplat {
  display: block;
}

.pastille-lecture__texte p {
  margin: 0;
}

.pastille-lecture__note,
.pastille-lecture__aide {
  color: var(--color-muted);
  font-size: 0.875rem;
}

.pastille-lecture__aide {
  margin-top: var(--esp-2) !important;
}

.pastille-validation__actions {
  display: flex;
  gap: var(--esp-2);
  flex-wrap: wrap;
  margin-top: var(--esp-3);
}

/*
 * La glissière de taille du prélèvement.
 *
 * Elle porte un réglage que la molette fait aussi — mais la molette ne se
 * découvre pas. La barre est donc l'interface, les raccourcis en sont
 * l'accélérateur.
 */
.pastille-taille {
  display: grid;
  gap: var(--esp-1);
  margin-top: var(--esp-3);
  max-width: 22rem;
}

.pastille-taille__nom {
  font-size: 0.875rem;
  color: var(--color-muted);
}

.pastille-taille__barre {
  width: 100%;
  /* La piste native suit la couleur d'accent du système ; on la force sur la
     palette de l'application, sinon elle jure sur un poste au thème coloré. */
  accent-color: var(--color-accent);
  cursor: pointer;
}

.pastille-taille__barre:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* --- Mouvement réduit ----------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .bouton:hover {
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   Confirmation
   --------------------------------------------------------------------------- */

/*
 * Remplace `confirm()`. Le dialogue natif annonce le nom de l'hébergeur avant
 * la question et garde ses boutons dans la langue du navigateur : pour un geste
 * qui touche un inventaire, il ressemble à une alerte technique alors que c'est
 * une décision de gestion.
 *
 * La question NOMME ce qu'elle vise — fournisseur et numéro de facture dans un
 * bandeau. Une question générique se répond machinalement.
 */
#fenetre-confirmation .fenetre-corps {
  display: flex;
  flex-direction: column;
  gap: var(--esp-3);
}

#fenetre-confirmation #confirmation-detail {
  margin: 0;
  font-weight: 600;
}

#fenetre-confirmation #confirmation-corps {
  margin: 0;
  color: var(--color-text-doux, inherit);
  line-height: 1.55;
  text-wrap: pretty;
}

/*
 * Le verrou des gestes irréversibles : un nom à retaper. Le bouton reste
 * désactivé tant que la frappe ne correspond pas, et le dit — un bouton inerte
 * sans explication se lit comme une panne.
 */
#fenetre-confirmation .confirmation-saisie {
  display: block;
  font-size: var(--pas-sm);
  font-weight: 600;
}

#fenetre-confirmation .confirmation-saisie input {
  display: block;
  width: 100%;
  min-height: 2.75rem;
  margin-top: var(--esp-1);
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
  color: var(--color-text);
  font: inherit;
  font-weight: 400;
}

#fenetre-confirmation .bouton[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Le bouton sûr passe en premier : la lecture s'arrête sur « Annuler » avant
   d'atteindre le geste irréversible. */
#fenetre-confirmation .fenetre-pied {
  margin-top: var(--esp-1);
}


/* --- Fenêtre de création de produit ---------------------------------------- */

/*
 * Même disposition que la fenêtre de vérification : la pièce à regarder à
 * gauche, la fiche à remplir à droite. Réutiliser `.comparaison` et `.volet`
 * évite d'avoir deux grilles qui se ressemblent sans se ressembler tout à fait.
 */
/*
 * La photo se plie d'abord a la hauteur disponible. Quand le zoom ou un ecran
 * peu haut ne laisse vraiment plus assez de place, le volet defile : aucun
 * coloris ni reglage ne doit etre coupe silencieusement.
 */
.volet--visuels {
  /* Le zoom ou un écran peu haut ne doit jamais couper le dernier coloris. */
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-right: 1px solid var(--panneau-bordure);
  background: var(--color-surface);
  padding: var(--esp-5);
  display: flex;
  flex-direction: column;
  gap: var(--esp-4);
  min-height: 0;
}

.creation-vide {
  display: flex;
  flex-direction: column;
  gap: var(--esp-3);
  flex: 1;
  min-height: 0;
}

/* L'en-tete garde sa mesure de lecture ; le reste prend toute la largeur. */
.creation-vide > p {
  max-width: 34ch;
}

.creation-vide__titre {
  font-weight: 600;
  color: var(--color-muted);
}

.creation-photo {
  display: grid;
  gap: var(--esp-3);
}

.creation-photo__actions {
  display: flex;
  gap: var(--esp-2);
}

.creation-coloris {
  margin: 0;
  padding-left: 1.1rem;
  display: grid;
  gap: 0.2rem;
  font-size: var(--pas-sm);
}

/* Le code d'imprimé du fournisseur : présent pour être recoupé avec la
   facture, discret pour ne pas concurrencer le nom du coloris. */
.creation-code {
  font-family: var(--police-mono, ui-monospace, monospace);
  font-size: var(--pas-2xs);
  color: var(--color-muted);
}

/*
 * Les candidats trouves chez le fournisseur.
 *
 * La preuve sous la vignette n'est pas une legende decorative : c'est elle qui
 * permet de verifier au lieu de croire. Elle reste donc lisible, jamais
 * reduite a une infobulle.
 */
.creation-candidats {
  display: grid;
  gap: var(--esp-3);
  width: 100%;
}

.creation-candidat {
  margin: 0;
  display: grid;
  gap: var(--esp-2);
}

/*
 * Une photo sous les 1120 px de la scène produit.
 *
 * Elle n'est pas retirée de la liste — quand c'est tout ce qui existe, la voir
 * vaut mieux qu'un écran qui dit « aucune photo ». Mais elle est reléguée en
 * fin de liste par le serveur, et l'étiquette dit pourquoi : un choix grisé
 * sans explication est un choix cassé.
 */
.creation-candidat__choix {
  position: relative;
}

.creation-candidat__alerte {
  position: absolute;
  left: var(--esp-2);
  bottom: var(--esp-2);
  padding: 2px var(--esp-2);
  border-radius: var(--radius-pill);
  background: var(--etat-attention-encre);
  color: var(--sur-etat);
  font-size: var(--pas-2xs);
  font-weight: 600;
  letter-spacing: 0.01em;
}

.creation-candidat--floue img {
  opacity: 0.72;
}

.creation-candidat__choix {
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--radius-md);
  background: none;
  cursor: pointer;
  overflow: hidden;
  line-height: 0;
}

.creation-candidat__choix:hover,
.creation-candidat__choix:focus-visible {
  border-color: var(--color-accent);
}

.creation-candidat__choix img {
  width: 100%;
  max-width: 20rem;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  display: block;
}

.creation-candidat__preuve {
  font-size: var(--pas-2xs);
  color: var(--color-muted);
  max-width: 34ch;
  line-height: 1.5;
}

.creation-candidat__preuve code {
  font-family: var(--police-mono, ui-monospace, monospace);
  color: var(--color-text);
}

/* ------------------------------------------------------------------ *
 * Une pastille par coloris
 *
 * Shopify ne lie l'option Couleur que lorsque TOUTES ses valeurs portent une
 * pastille. Les coloris se montrent donc tous, y compris ceux sans photo —
 * en cacher un le ferait oublier, et il suffit d'un seul manquant pour
 * qu'aucune pastille ne s'affiche en boutique.
 * ------------------------------------------------------------------ */

.creation-pastilles {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  margin-top: 1rem;
  /* Chaque coloris garde sa hauteur naturelle; le volet parent défile. */
  flex: none;
}

.creation-coloris-bloc {
  padding-block-end: 1.25rem;
  border-block-end: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  flex: none;
}

.creation-coloris-bloc:last-child {
  border-block-end: none;
  padding-block-end: 0;
}

.creation-coloris-bloc__nom {
  margin: 0 0 0.5rem;
  font-weight: 600;
  flex: none;
}

/*
 * Photo a gauche, echantillon et description a droite — cote a cote, jamais
 * l'un sous l'autre : c'est la comparaison des deux qui dit si le rond est
 * bien pose, et elle demande de les voir ensemble.
 *
 * La photo se dimensionne par sa HAUTEUR (`height: 100%`, largeur libre) :
 * c'est la hauteur qui manque dans un volet qui ne defile pas. Le rond reste
 * pose en pourcentages de la scene, et la scene epouse l'image — la geometrie
 * ne bouge pas.
 */
.creation-coloris-bloc .pastille-reglage {
  flex: none;
  flex-wrap: nowrap;
  align-items: flex-start;
}

.creation-coloris-bloc .pastille-scene {
  width: min(16rem, 45%);
  height: auto;
  max-width: none;
}

.creation-coloris-bloc .pastille-scene__photo {
  width: 100%;
  height: auto;
  max-width: 100%;
  object-fit: cover;
}

.creation-coloris-bloc .pastille-lecture {
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: var(--esp-3);
  overflow: visible;
}

/* Un champ rempli par la facture, que personne ne modifie. Le fond gris le
   distingue d'un champ saisissable AVANT qu'on essaie d'y écrire. */
.champ__saisie--lecture {
  background: var(--color-surface);
  color: var(--color-secondary);
  cursor: default;
}

/*
 * Ce qui bloque encore l'enregistrement des fiches.
 *
 * C'est un BOUTON, pas un paragraphe : il mène à la première fiche qui manque
 * quelque chose. Il en garde donc les affordances — curseur, survol, focus
 * visible — tout en gardant l'apparence d'un bandeau, pour ne pas ressembler
 * à une seconde action à côté d'« Enregistrer ».
 */
.creation-blocage {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
  border: 0;
  border-left: 3px solid var(--color-accent);
}

.creation-blocage:hover {
  background: color-mix(in srgb, var(--color-accent) 14%, var(--color-background));
}

/* --- Les collections de la fiche produit ---------------------------------
   Des cases a cocher plutot qu'une liste deroulante multiple : la seconde
   demande un Ctrl-clic, et un Ctrl-clic maladroit efface le premier choix sans
   rien dire. La grille se remplit en colonnes de largeur minimale plutot qu'en
   nombre fixe : la liste vient de Shopify, personne ne sait combien
   d'entrees elle portera. */
.champ.champ--large > /*
 * Ce qui est CHOISI — collections posees, balises posees.
 *
 * Un jeton par valeur, avec son bouton de retrait. La liste deroulante dit ce
 * qu'on peut ajouter, les jetons disent ce qui est pose : deux questions
 * differentes, deux endroits differents. Une vingtaine de cases a cocher
 * melangeait les deux et noyait les deux collections qui comptent.
 */
/*
 * Les importations a finir, sous la zone de depot.
 *
 * Discrete : c'est un rappel, pas l'action principale de l'ecran. La zone de
 * depot garde le premier regard.
 */
.a-finir__titre {
  margin: 0;
  font-size: var(--pas-md);
}

.a-finir__aide {
  margin: 0.2rem 0 var(--esp-3);
  font-size: var(--pas-2xs);
  color: var(--color-muted);
}

.a-finir__liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--esp-2);
}

.a-finir__ligne {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-2);
  padding: var(--esp-2) var(--esp-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}

.a-finir__quoi {
  display: grid;
  gap: 0.15rem;
  min-width: 0;
}

.a-finir__detail {
  font-size: var(--pas-2xs);
  color: var(--color-muted);
}

.jetons {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.jetons__vide {
  font-size: var(--pas-2xs);
  color: var(--color-muted);
}

.jeton {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.3rem 0.2rem 0.55rem;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  font-size: var(--pas-sm);
}

.jeton__retirer {
  width: 1.25rem;
  height: 1.25rem;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--color-muted);
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

.jeton__retirer:hover,
.jeton__retirer:focus-visible {
  color: var(--etat-erreur);
}

/* La liste des balises existantes et le champ qui en cree une, sur une ligne
   qui se plie sur un ecran etroit. */
.balises__ajout {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--esp-2);
  margin-top: 0.4rem;
}

.balises__ajout select,
.balises__ajout input {
  flex: 1 1 12rem;
  min-width: 0;
}

.collections {
  grid-column: 1 / -1;
}

fieldset.champ {
  border: 0;
  margin: 0;
  padding: 0;
  min-inline-size: 0; /* Un fieldset refuse de retrecir sans cela. */
}

.collections {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 0.35rem var(--esp-3);
  margin-top: 0.35rem;
}

.collection {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: var(--pas-sm);
  cursor: pointer;
}

.collection:hover {
  background: var(--color-surface);
}

/* La cible du focus est la case, mais c'est l'etiquette entiere qui doit se
   voir : au clavier, un anneau de 13 pixels ne se repere pas. */
.collection:has(input:focus-visible) {
  border-color: var(--color-secondary);
  background: var(--color-surface);
}

.collection input {
  accent-color: var(--color-secondary);
  margin: 0;
  flex: none;
}

.collection:has(input:checked) {
  border-color: var(--color-border);
  background: var(--color-surface);
  font-weight: 600;
}

/* Quand les deux volets deviennent trop étroits, chacun reprend toute la
   largeur. Ce seuil couvre aussi les petits portables utilisés avec zoom. */
@media (max-width: 80rem) {
  #fenetre-creation .comparaison {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(16rem, 1fr) minmax(0, 1.25fr);
  }

  #fenetre-creation .volet--visuels {
    border-right: none;
    border-bottom: 1px solid var(--panneau-bordure);
  }
}

@media (max-width: 40rem) {
  #fenetre-creation .fenetre-entete {
    flex-wrap: wrap;
    padding: var(--esp-3) var(--esp-4);
  }

  #fenetre-creation .fenetre-fratrie {
    order: 3;
    width: 100%;
    margin: 0;
    justify-content: center;
  }

  #fenetre-creation .fenetre-actions {
    margin-left: auto;
  }

  #fenetre-creation .fenetre-actions .bouton {
    padding-inline: var(--esp-3);
    white-space: normal;
  }
}
.selecteur-organisation select {
  max-width: 16rem;
  min-height: 2.5rem;
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
  background: var(--color-background);
  padding: 0.45rem 2rem 0.45rem 0.7rem;
  color: inherit;
  font: inherit;
}


/* --- Fiche produit complète ------------------------------------------------
 *
 * Une fenêtre d'édition, pas un formulaire administratif : les champs se
 * groupent par question posée — qu'est-ce que c'est, se vend-il, que dit-on
 * de lui, à quoi ressemble-t-il, combien coûte-t-il — et chaque groupe est
 * une carte. Sans ces cartes, quatorze champs alignés se lisent comme une
 * liste de cases à remplir, et on ne sait plus laquelle décide de quoi.
 */

/* Le bouton d'ouverture vit dans l'en-tête de la carte, aligné à droite : la
   ligne de méta reste la première chose lue, le geste vient après. */
.fiche__tete {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  column-gap: var(--esp-3);
}

.fiche__tete h3,
.fiche__meta {
  grid-column: 1;
}

.fiche__ouvrir {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  white-space: nowrap;
}

/* Large, mais pas illimitée : au-delà, le titre et le bouton d'envoi se
   retrouvent à deux pieds l'un de l'autre sur un écran de bureau. */
.fenetre--fiche {
  width: min(78rem, calc(100vw - 2rem));
}

/*
 * C'EST LE CORPS QUI DÉFILE, pas la fenêtre.
 *
 * `.fenetre` a une hauteur figée et `overflow: hidden` : les autres fenêtres
 * s'en accommodent parce que leurs volets défilent chacun de leur côté. Sans
 * cette règle, la fiche était simplement coupée sous la description — les
 * photos et les variantes existaient, hors d'atteinte.
 */
.fenetre--fiche .fenetre-corps {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* Le bandeau d'état est collé au-dessus : sans marge, la première carte
     lui touche le bord. */
  padding-block-start: var(--esp-4);
}

.fenetre--fiche > .bandeau {
  margin: var(--esp-4) var(--esp-5) 0;
}

.fiche-entete__nom {
  display: grid;
  gap: 0.15rem;
  min-width: 0;
}

.fiche-entete__meta {
  margin: 0;
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*
 * Deux colonnes quand l'écran les porte : l'identité à gauche, la mise en
 * vente à droite. Description, photos et variantes prennent toute la largeur —
 * un texte de deux paragraphes et un tableau de prix ne se lisent pas en
 * demi-colonne.
 */
.fiche-edit {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--esp-4);
  align-items: start;
}

.fiche-bloc {
  display: grid;
  min-width: 0;
  gap: var(--esp-3);
  align-content: start;
  padding: var(--esp-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
}

.fiche-bloc--large {
  grid-column: 1 / -1;
}

.fiche-bloc__titre {
  margin: 0;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}

.fiche-bloc__tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-3);
  flex-wrap: wrap;
}

.fiche-champs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: var(--esp-3);
  align-items: start;
}

.fiche-champs .champ--large,
.fiche-champs > .champ__aide {
  grid-column: 1 / -1;
}

.fiche-champs > .champ__aide {
  margin: -0.3rem 0 0;
}

/*
 * Assez haut pour deux paragraphes : une description qu'on relit dans une
 * fente de trois lignes ne se relit pas. Le cadre est celui des autres
 * saisies — c'en est une, même si le navigateur l'appelle autrement.
 */
.fiche-description {
  overflow-wrap: anywhere;
  min-height: 9.5rem;
  max-height: 24rem;
  overflow-y: auto;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-background);
  font-size: var(--pas-sm);
  line-height: 1.55;
}

.fiche-description:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

/* Un champ riche vide n'a pas de `placeholder` : il faut l'écrire soi-même,
   sinon la zone ressemble à une panne. */
.fiche-description:empty::before {
  content: attr(data-vide);
  color: var(--color-muted);
}

.fiche-description > :first-child {
  margin-top: 0;
}

.fiche-description p {
  margin: 0 0 0.7em;
}

.fiche-vide {
  margin: 0;
  color: var(--color-muted);
  font-size: var(--pas-2xs);
}

/* Les collections : des cases, en colonnes qui se remplissent. */
.fiche-collections {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr));
  gap: 0.375rem 1rem;
  margin-top: 0.75rem;
}

.fiche-collection {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
}

.fiche-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
  gap: var(--esp-3);
}

.fiche-photo {
  margin: 0;
  display: grid;
  gap: var(--esp-1);
}

.fiche-photo img,
.fiche-photo__absente {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}

.fiche-photo__absente {
  display: grid;
  place-items: center;
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  text-align: center;
}

/* Une photo cochée est DÉJÀ partie, visuellement : le geste est destructif,
   et il doit se voir avant l'envoi, pas après. */
.fiche-photo:has(.fiche-retirer:checked) img {
  opacity: 0.35;
  filter: grayscale(1);
}

.fiche-photo:has(.fiche-retirer:checked) .fiche-photo__retrait {
  color: var(--etat-erreur);
  font-weight: 600;
}

.fiche-photo__retrait,
.fiche-ajout {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  font-size: var(--pas-2xs);
}

.fiche-ajout {
  padding: 0.3rem 0;
  border-top: 1px solid var(--color-border);
}

.fiche-ajout__nom {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fiche-ajout__couleur {
  max-width: 12rem;
}

/* --- Catalogue en grille (maquette du 2026-09-10) ------------------------- */

/*
 * `auto-fill` et non `auto-fit` : à trois produits, `auto-fit` étire trois
 * cartes sur toute la largeur et donne des vignettes de la taille d'une
 * affiche. Ici les cartes gardent leur gabarit et la ligne reste courte —
 * c'est ce que fait la maquette.
 */
.grille-produits {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: var(--esp-5) var(--esp-4); padding-bottom: var(--esp-4);
}

.carte-produit {
  display: grid; grid-template-rows: auto auto; align-content: start; min-width: 0; gap: 0; padding: 0; border: 1px solid var(--color-border); border-radius: var(--radius-sm); overflow: hidden; background: var(--color-background); box-shadow: var(--shadow-soft); cursor: pointer; text-align: left;
}

.carte-produit:hover .carte-produit__titre { text-decoration: underline; text-underline-offset: .2em; }
.carte-produit.produit__ligne:hover, .carte-produit.produit__ligne:focus-visible { background: var(--color-background); border-color: var(--color-brand-deep); }
.carte-produit.produit__ligne:focus-visible { outline: 2px solid var(--color-brand-deep); outline-offset: 3px; }

.carte-produit__image {
  position: relative; aspect-ratio: 3 / 4; min-width: 0; border-radius: calc(var(--radius-sm) - 1px) calc(var(--radius-sm) - 1px) 0 0; overflow: hidden; background: var(--color-surface);
}

.carte-produit__image img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/*
 * L'absence de photo se DIT, elle ne se devine pas.
 *
 * Une case grise vide se lit comme un chargement en cours ; la cliente attend
 * devant un produit qui n'aura jamais d'image. Le mot est écrit, et c'est
 * aussi le premier manque à corriger sur une fiche.
 */
.carte-produit__sans-photo {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--color-surface);
  border-radius: inherit;
  box-shadow: inset 0 -1px var(--color-border);
  color: var(--color-muted);
  font-size: var(--pas-2xs);
}

.carte-produit__etat {
  position: absolute;
  top: var(--esp-2);
  left: var(--esp-2);
}

.carte-produit__texte {
  display: grid; align-content: start; min-width: 0; gap: var(--esp-1); padding: var(--esp-3);
}

/*
 * Deux lignes de titre, jamais trois.
 *
 * Un titre long ferait grandir sa carte et casserait l'alignement de toute la
 * rangée. Coupé net, il se lit en entier dans la fiche — qui est à un clic.
 */
.carte-produit__titre {
  font-weight: 600;
  font-size: var(--pas-sm);
  line-height: 1.3;
  height: 2.6em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.carte-produit__dessous {
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.carte-produit__prix {
  display: grid; grid-template-rows: 2.6em 1.3em; align-items: start; margin-top: var(--esp-1); font-size: var(--pas-sm); line-height: 1.3; font-weight: 600; font-variant-numeric: tabular-nums;
}

.carte-produit__drapeau {
  grid-row: 2;
  color: var(--etat-attention-encre);
  font-size: var(--pas-2xs);
  font-weight: 500;
}

/* --- Bascule grille / tableau --------------------------------------------- */

.bascule-vue {
  display: flex;
  gap: 2px;
  padding: 2px;
  margin-left: auto;
  align-self: end;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-background);
}

.bascule-vue__bouton {
  display: grid;
  place-items: center;
  padding: 0.35rem 0.5rem;
  border: 0;
  border-radius: calc(var(--radius-md) - 2px);
  background: none;
  color: var(--color-muted);
  cursor: pointer;
}

.bascule-vue__bouton svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* La vue active se voit à sa surface, pas seulement à sa couleur : sur un
   écran pâle, deux gris ne se distinguaient pas. */
.bascule-vue__bouton[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--color-background));
  color: var(--color-brand-deep);
}

/* --- Détourage du fond (Photoroom) ---------------------------------------- */

/*
 * L'aperçu d'un fond transparent DOIT montrer sa transparence.
 *
 * Sur la surface blanche de l'application, un PNG détouré et un JPEG à fond
 * blanc sont indiscernables : la cliente cliquerait « Remplacer » sans avoir
 * rien vérifié. Le damier est donc la preuve visuelle du détourage, et il ne
 * coûte pas une image — c'est un dégradé.
 */
.fiche-photo--detouree img,
.creation-detourage__apercu {
  --damier: color-mix(in srgb, var(--color-border) 45%, var(--color-background));
  background-color: var(--color-background);
  background-image:
    linear-gradient(45deg, var(--damier) 25%, transparent 25%),
    linear-gradient(-45deg, var(--damier) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--damier) 75%),
    linear-gradient(-45deg, transparent 75%, var(--damier) 75%);
  background-size: 14px 14px;
  background-position: 0 0, 0 7px, 7px -7px, -7px 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.fiche-photo__detourage {
  display: grid;
  gap: var(--esp-1);
  justify-items: stretch;
}

.fiche-photo__detourer {
  width: 100%;
  font-size: var(--pas-2xs);
  padding-block: 0.35rem;
}

.fiche-photo__note {
  margin: 0;
  font-size: var(--pas-2xs);
  color: var(--color-muted);
}

.fiche-photo__note--danger {
  color: var(--etat-erreur);
}

/* L'essai n'est pas une erreur : c'est un avertissement. La couleur d'alerte
   plutot que celle d'echec — rien n'a echoue, rien ne peut simplement partir. */
.fiche-photo__note--essai {
  color: var(--etat-attention-encre);
}

/* Trois gestes tiennent sur une colonne de vignette : empiles, pas cote a
   cote. « Confirmer » et « Ajouter » ne se distingueraient plus a 5 rem. */
.fiche-photo__gestes {
  display: grid;
  gap: var(--esp-1);
}

.fiche-photo__outils {
  display: grid;
  gap: var(--esp-1);
}

.fiche-photo__outils .bouton {
  font-size: var(--pas-2xs);
  padding-block: 0.35rem;
  justify-content: center;
}

/* --- Fonds transparents : sélection et validation groupées ---------------- */
.photo-lot__barre { display: grid; gap: var(--esp-3); padding-block: var(--esp-3); border-bottom: 1px solid var(--color-border); }
.photo-lot__introduction strong { font-size: var(--pas-sm); }
.photo-lot__aide { color: var(--color-secondary); font-size: var(--pas-xs); line-height: 1.5; overflow-wrap: anywhere; }
.photo-lot__actions, .photo-lot__entete, .photo-lot__confirmation { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--esp-3); }
.photo-lot__actions { justify-content: flex-start; }
.photo-lot__actions .bouton, .photo-lot__entete .bouton, .photo-lot__confirmation .bouton { min-height: 2.75rem; white-space: normal; text-align: center; justify-content: center; }
.photo-lot__compteur { color: var(--color-secondary); font-size: var(--pas-xs); font-variant-numeric: tabular-nums; margin-right: auto; }
.photo-lot__selection { display: flex; align-items: center; gap: var(--esp-2); min-height: 2.75rem; padding: var(--esp-1); border: 1px solid var(--color-border); border-radius: var(--radius-sm); font-size: var(--pas-2xs); line-height: 1.3; cursor: pointer; }
.photo-lot__selection input { flex: none; width: 1rem; height: 1rem; margin: 0; }
.photo-lot__selection:has(input:checked) { border-color: var(--color-brand-deep); background: var(--color-surface); font-weight: 600; }
.photo-lot__selection:has(input:disabled) { cursor: default; color: var(--color-muted); }
.photo-lot__selection:has(input:focus-visible) { outline: 2px solid var(--color-brand-deep); outline-offset: 2px; }
.photo-lot__photo--selectionnee > img { outline: 2px solid var(--color-brand-deep); outline-offset: -2px; }
.photo-lot__resultats { display: grid; gap: var(--esp-4); margin-top: var(--esp-4); padding-top: var(--esp-4); border-top: 1px solid var(--color-border); }
.photo-lot__entete h4 { font-size: var(--pas-sm); }
.photo-lot__progression { display: block; width: 100%; height: .5rem; accent-color: var(--color-brand-deep); }
.photo-lot__message { font-size: var(--pas-sm); color: var(--color-text); padding: var(--esp-3); border-left: 3px solid var(--color-brand-deep); background: var(--color-surface); overflow-wrap: anywhere; }
.photo-lot__grille { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 8rem), 1fr)); align-items: start; gap: var(--esp-3); }
.photo-lot__resultat { min-width: 0; margin: 0; }
.photo-lot__apercu { position: relative; display: grid; place-items: center; aspect-ratio: 3 / 4; overflow: hidden; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); }
.photo-lot__chargement { position: absolute; inset: 0; display: grid; place-items: center; background: color-mix(in srgb, var(--color-background) 55%, transparent); }
.photo-lot__rotation { width: 2.5rem; height: 2.5rem; border: 3px solid var(--color-border); border-top-color: var(--color-brand-deep); border-right-color: var(--color-brand-deep); border-radius: 50%; background: var(--color-background); animation: photo-lot-rotation .9s linear infinite; }
@keyframes photo-lot-rotation { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .photo-lot__rotation { animation: none; } }
.photo-lot__apercu img { width: 100%; height: 100%; min-height: 0; object-fit: contain; }
.photo-lot__apercu--transparent { --damier: color-mix(in srgb, var(--color-border) 45%, var(--color-background)); background-color: var(--color-background); background-image: linear-gradient(45deg, var(--damier) 25%, transparent 25%), linear-gradient(-45deg, var(--damier) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--damier) 75%), linear-gradient(-45deg, transparent 75%, var(--damier) 75%); background-size: 14px 14px; background-position: 0 0, 0 7px, 7px -7px, -7px 0; }
.photo-lot__resultat figcaption { display: grid; gap: var(--esp-1); padding-top: var(--esp-2); font-size: var(--pas-2xs); overflow-wrap: anywhere; }
.photo-lot__nom { color: var(--color-secondary); }
.photo-lot__etat { font-weight: 600; }
.photo-lot__etat--erreur, .photo-lot__erreur { color: var(--etat-erreur); }
.photo-lot__confirmation { padding-top: var(--esp-3); border-top: 1px solid var(--color-border); }
.photo-lot__confirmation > p { flex: 1 1 15rem; }
@media (max-width: 36rem) {
  .photo-lot__actions > [data-photo-lot="traiter"], .photo-lot__confirmation > .bouton { width: 100%; }
  .photo-lot__entete > .bouton { width: 100%; }
  .photo-lot__grille { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- Atelier d'une photo -------------------------------------------------- */

/*
 * Deux colonnes : l'image, puis les outils.
 *
 * La photo reste entière pour juger les contours du vêtement. Une colonne
 * courte regroupe le retrait du fond et la confirmation du résultat.
 */
.fenetre.fenetre--photo {
  width: min(52rem, 94vw);
  height: fit-content;
  max-height: calc(100dvh - 2rem);
}

/*
 * Le corps défile lorsque la hauteur disponible est réduite.
 *
 * Un message d'erreur peut agrandir les outils : le corps doit défiler pour
 * que la confirmation et l'annulation restent accessibles.
 */
.fenetre--photo .fenetre-corps {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.fenetre--photo > .bandeau {
  margin: var(--esp-4) var(--esp-5) 0;
}

.atelier {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 16rem;
  gap: var(--esp-5);
  align-items: start;
  align-content: start;
}

.atelier__scene {
  display: grid;
  min-width: 0;
  gap: var(--esp-2);
}

.atelier__scene img {
  width: 100%;
  max-height: min(52vh, 30rem);
  object-fit: contain;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

/* Le damier n'apparait QUE sous un resultat de DETOURAGE : sous une photo
   opaque — photo de boutique, ou resultat d'amelioration de nettete — il
   ferait croire a une transparence qui n'existe pas. C'est `rendreAtelier`
   qui pose la classe, en excluant l'origine « nettete ». */
.atelier__scene--detouree img {
  --damier: color-mix(in srgb, var(--color-border) 45%, var(--color-background));
  background-color: var(--color-background);
  background-image:
    linear-gradient(45deg, var(--damier) 25%, transparent 25%),
    linear-gradient(-45deg, var(--damier) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--damier) 75%),
    linear-gradient(-45deg, transparent 75%, var(--damier) 75%);
  background-size: 18px 18px;
  background-position: 0 0, 0 9px, 9px -9px, -9px 0;
  border-color: var(--color-accent);
}

.atelier__legende {
  color: var(--color-muted);
  font-size: var(--pas-2xs);
}

.atelier__outils {
  display: grid;
  min-width: 0;
  gap: var(--esp-3);
  align-content: start;
  align-self: center;
}

.atelier__outils h3 { font-size: var(--pas-lg); }
.atelier__outils .fiche-photo__note { font-size: var(--pas-xs); line-height: 1.5; }

.atelier .fiche-photo__gestes {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--esp-2);
  padding-top: var(--esp-2);
}

@media (max-width: 44rem) {
  .atelier {
    grid-template-columns: minmax(0, 1fr);
  }
  .atelier__scene img { max-height: 35vh; }
}

.fiche-photo__confirmer {
  font-size: var(--pas-2xs);
  padding-block: 0.35rem;
  justify-content: center;
}

.fiche-photo__gestes .bouton-discret {
  font-size: var(--pas-2xs);
  padding-block: 0.35rem;
  justify-content: center;
}

.atelier__outils .bouton { min-height: 2.75rem; font-size: var(--pas-xs); }

/*
 * La photo détourée occupe EXACTEMENT la place de l'originale.
 *
 * `contain` et non `cover` une fois détourée : le vêtement est maintenant
 * découpé sur du vide, et recadrer au remplissage lui couperait une manche.
 * Le damier occupe alors la marge, ce qui montre bien où finit le sujet.
 */
.fiche-photo--detouree img {
  object-fit: contain;
  border-color: var(--color-accent);
}

.creation-detourage {
  display: grid;
  gap: var(--esp-2);
  justify-items: start;
  margin-top: var(--esp-3);
  padding-top: var(--esp-3);
  border-top: 1px solid var(--panneau-bordure);
}

.creation-detourage__apercu {
  max-width: 12rem;
}

.creation-detourage__apercu img {
  display: block;
  width: 100%;
  height: auto;
}

.champ__aide--danger {
  color: var(--etat-erreur);
}

/* Le tableau défile DANS sa carte : sur un téléphone, c'est lui qui bouge,
   pas la page entière. */
.fiche-table__cadre {
  min-width: 0;
  overflow-x: auto;
}

.fiche-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--pas-sm);
}

.fiche-table th,
.fiche-table td {
  text-align: left;
  padding: 0.35rem 0.5rem;
  border-bottom: 1px solid var(--color-border);
}

.fiche-table thead th {
  position: sticky;
  top: 0;
  background: var(--color-background);
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Le coloris annoncé une fois, en tête de son groupe : le répéter sur chaque
   taille noierait la seule information qui change d'une ligne à l'autre. */
.fiche-table__groupe th {
  padding-top: var(--esp-3);
  background: var(--color-surface);
  font-size: var(--pas-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-secondary);
}

.fiche-table__code {
  font-variant-numeric: tabular-nums;
  color: var(--color-muted);
  white-space: nowrap;
}

.fiche-prix__cadre {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--color-muted);
}

.fiche-prix {
  max-width: 7rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.fiche-codebarre {
  max-width: 11rem;
}

/* --- La galerie d'un coloris, dans la fenêtre de création ------------------
 *
 * La première photo ouvre la fiche en boutique ET porte la pastille : elle est
 * donc marquée, pas seulement première. Sans ce repère, l'ordre ressemble à une
 * préférence d'affichage alors qu'il décide de deux choses visibles.
 */
.galerie {
  display: grid;
  gap: var(--esp-2);
  margin-top: var(--esp-3);
}

.galerie__titre {
  margin: 0;
  font-size: var(--pas-2xs);
  color: var(--color-muted);
}

.galerie__liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
  gap: var(--esp-2);
}

.galerie__item {
  position: relative;
  display: grid;
  gap: 0.2rem;
}

.galerie__item img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}

.galerie__item--principale img {
  border: 2px solid var(--color-accent);
}

/*
 * Le glisser-deposer de la galerie.
 *
 * `cursor: grab` est la seule chose qui ANNONCE que la vignette se deplace :
 * sans elle, personne n'essaie. `touch-action: manipulation` laisse le
 * defilement au doigt — sur une tablette, ce sont les fleches qui servent, et
 * un glisser capture par la vignette empecherait de faire defiler la page.
 */
.galerie__item[draggable="true"] img {
  cursor: grab;
  touch-action: manipulation;
}

.galerie__item--glisse {
  opacity: 0.4;
}

/* La ou la photo va tomber. */
.galerie__item--cible img {
  border: 2px dashed var(--color-accent);
  transform: scale(0.97);
}

.galerie__marque {
  position: absolute;
  top: 0.25rem;
  left: 0.25rem;
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
  background: var(--color-accent);
  color: var(--sur-accent);
  font-size: var(--pas-3xs, 0.65rem);
  font-weight: 600;
  letter-spacing: 0.02em;
}

/*
 * Le coloris, sous chaque vignette.
 *
 * Six photos, deux coloris : sans le nom, on retire la photo du mauvais — et
 * en boutique, la pastille « Brun » montre alors un vetement ecru.
 */
.galerie__couleur,
.fiche-photo__couleur {
  font-size: var(--pas-2xs);
  color: var(--color-muted);
  text-align: center;
  overflow-wrap: anywhere;
}

.galerie__gestes {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
}

.galerie__geste {
  padding: 0.1rem 0.35rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-background);
  color: inherit;
  font: inherit;
  font-size: var(--pas-2xs);
  cursor: pointer;
}

.galerie__geste:hover:not(:disabled) {
  border-color: var(--color-accent);
}

.galerie__geste:disabled {
  opacity: 0.35;
  cursor: default;
}

/*
 * Le retrait d'une photo : un « × » dans le coin de la vignette.
 *
 * Sur la vignette et non dans la rangee de gestes : c'est la photo qu'on
 * retire, pas un rang qu'on change, et la rangee est deja pleine. Il reste
 * atteignable au clavier comme les autres boutons.
 */
/*
 * Les deux boutons de COIN : retirer en haut a droite, agrandir en bas a droite.
 *
 * Sur la vignette et non dessous : c'est la photo qu'ils visent. Aux coins
 * opposes, parce que la rangee de gestes d'avant — deux fleches et un bouton
 * « En principale » — se chevauchait sous cinq centimetres de large. Ce qui
 * reste tient sans se marcher dessus, et le reste est passe dans la loupe.
 */
.galerie__coin {
  position: absolute;
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-background);
  color: inherit;
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

.galerie__coin--retirer {
  top: 0.25rem;
  right: 0.25rem;
}

.galerie__coin--loupe {
  bottom: 0.25rem;
  right: 0.25rem;
}

.galerie__coin svg {
  width: 0.85rem;
  height: 0.85rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.galerie__coin:hover:not(:disabled) {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.galerie__coin--retirer:hover:not(:disabled) {
  border-color: var(--etat-erreur);
  color: var(--etat-erreur);
}

.galerie__coin:disabled {
  opacity: 0.35;
  cursor: default;
}

/* La vignette prend le focus : ce sont les fleches du clavier qui la deplacent. */
.galerie__item:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* La photo en grand, ouverte par la loupe. */
.agrandie-corps {
  display: grid;
  gap: var(--esp-2);
  justify-items: center;
}

.agrandie-corps img {
  max-width: 100%;
  max-height: 70vh;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}

/* Retiree, pas jetee : montree en retrait, et remettable. */
.galerie__item--retiree img {
  opacity: 0.5;
  border-style: dashed;
}

.galerie__geste--promouvoir {
  white-space: nowrap;
}

/* --- Fenêtre d'attente (détection des nouveautés) -------------------------- */
/*
 * Une fenêtre qui ne dit rien pendant trente secondes est une fenêtre en
 * panne : celle-ci montre un pourcentage, l'étape en cours et le temps qui
 * reste. Le pourcentage est une ESTIMATION assumée — il ralentit près de la
 * fin plutôt que de mentir en atteignant 100 % avant la réponse.
 */

.fenetre--attente {
  /* Rien à comparer ici, contrairement aux autres fenêtres : la carte se
     réduit à ce qu'elle affiche. */
  width: min(26rem, calc(100vw - 2rem));
  /*
   * `fit-content`, jamais `auto` — la même erreur que `.fenetre--etroite`
   * (voir plus haut). Un `<dialog>` modal est en `position: fixed` avec
   * `inset: 0` ; une hauteur `auto` bornée en haut ET en bas remplit toute la
   * fenêtre du navigateur. La carte s'étirait donc sur toute la hauteur, son
   * anneau collé au bord supérieur et un long vide dessous.
   */
  height: fit-content;
  max-height: calc(100dvh - 2rem);
  /* Et une fois la hauteur juste, `margin: auto` la centre — verticalement
     comme horizontalement. C'est ce que la feuille du navigateur pose déjà,
     mais l'écrire ici le protège d'une règle `.fenetre` plus large. */
  margin: auto;
}

.attente {
  display: grid;
  justify-items: center;
  gap: var(--esp-3);
  padding: var(--esp-6) var(--esp-5) var(--esp-5);
  text-align: center;
  background: var(--panneau-lavis), var(--color-background);
}

.attente h2 {
  margin: 0;
  font-size: var(--pas-lg);
  color: color-mix(in srgb, var(--color-text) 94%, var(--color-brand-deep));
}

.attente__anneau {
  position: relative;
  width: 8.5rem;
  height: 8.5rem;
}

.attente__anneau svg {
  width: 100%;
  height: 100%;
  /* Le zéro d'un arc SVG est à 3 h : on le ramène en haut. */
  transform: rotate(-90deg);
}

.attente__anneau circle {
  fill: none;
  stroke-width: 7;
  stroke-linecap: round;
}

.attente__rail {
  stroke: color-mix(in srgb, var(--color-border) 55%, var(--color-background));
}

.attente__arc {
  stroke: var(--color-accent);
  /* 2πr, r = 52. Posé ici pour que l'arc parte plein et se dévoile. */
  stroke-dasharray: 326.73;
  stroke-dashoffset: 326.73;
  filter: drop-shadow(0 2px 6px color-mix(in srgb, var(--accent) 35%, transparent));
  /* La progression est estimée : sans lissage, chaque image de l'animation
     se verrait sauter. */
  transition: stroke-dashoffset 0.4s linear;
}

.attente__pourcent {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: var(--pas-xl);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--color-brand-deep);
}

.attente__etape {
  margin: 0;
  min-height: 1.4em;
  font-size: var(--pas-sm);
  color: var(--color-text);
  /* Le libellé change en cours de route : sans transition, il clignote. */
  animation: apparaitre 0.35s ease both;
}

.attente__reste {
  margin: 0;
  font-size: var(--pas-xs);
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

/* Le halo respire pour dire « ça travaille » même quand le pourcentage,
   lui, est sur un palier. */
.attente__anneau::after {
  content: "";
  position: absolute;
  inset: -0.35rem;
  border-radius: var(--radius-pill);
  animation: pulsation 1.8s ease-in-out infinite;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .attente__anneau::after,
  .attente__etape {
    animation: none;
  }
  .attente__arc {
    transition: none;
  }
}

/* --- Tableau des fournisseurs --------------------------------------------- */

.fournisseurs__entete {
  margin-bottom: var(--esp-5);
}

.fournisseurs__entete p {
  max-width: 65ch;
  color: var(--color-secondary);
}

.tableau-fournisseurs td {
  vertical-align: top;
}

.fournisseur__identite {
  display: block;
}

.cellule__titre {
  display: block;
  font-weight: 600;
}

.cellule__note,
.cellule__absent {
  display: block;
  margin-top: 2px;
  font-size: var(--pas-xs);
  color: var(--color-muted);
  overflow-wrap: anywhere;
}

.cellule__absent {
  font-style: italic;
}

.tableau-fournisseurs .pastille {
  display: inline-flex;
}

.fournisseur__b2b {
  display: inline-flex;
  width: max-content;
  margin: 0;
  text-decoration: none;
}

.fournisseurs__vide {
  padding-block: var(--esp-7) !important;
  text-align: center !important;
}

.fournisseurs__vide strong,
.fournisseurs__vide span {
  display: block;
}

.fournisseurs__vide span {
  margin-top: var(--esp-1);
  color: var(--color-secondary);
}

@media (max-width: 40rem) {
  .tableau-fournisseurs tr {
    margin: 0;
    padding: var(--esp-4) 0;
    border: 0;
    border-bottom: 1px solid var(--color-border);
    border-radius: 0;
    background: transparent;
  }

  .tableau-fournisseurs td {
    grid-template-columns: 7.25rem minmax(0, 1fr);
  }

  .tableau-fournisseurs .fournisseurs__vide {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --- L'assistante de la boutique ------------------------------------------ */

/*
 * Une bulle au coin de l'écran, par-dessus n'importe quelle section.
 *
 * Le bouton rond porte l'accent de la boutique; le panneau s'ouvre au-dessus
 * de lui. Une conversation se lit du bas : la saisie reste sous les yeux et
 * c'est le FIL qui défile, jamais le panneau.
 */
.bulle-chat {
  position: fixed;
  right: var(--esp-5);
  bottom: var(--esp-5);
  z-index: 40;
  display: grid;
  justify-items: end;
  gap: var(--esp-3);
}

.bulle-chat__bouton {
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  border: 0;
  border-radius: 50%;
  background: var(--color-accent);
  box-shadow: var(--shadow-accent);
  cursor: pointer;
  transition: transform 0.15s ease;
}

.bulle-chat__bouton:hover {
  transform: translateY(-2px);
}

.bulle-chat__bouton:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--accent) 45%, transparent);
  outline-offset: 3px;
}

.bulle-chat__bouton svg {
  width: 1.6rem;
  height: 1.6rem;
  fill: none;
  stroke: var(--sur-accent);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Une colonne souple, pas une grille : l'historique replié ne doit laisser
   aucune rangée vide derrière lui. */
.chat {
  display: flex;
  flex-direction: column;
  gap: var(--esp-3);
  width: min(26rem, calc(100vw - 2 * var(--esp-5)));
  height: min(40rem, calc(100vh - 7rem - var(--esp-5)));
  padding: var(--esp-4);
  border-radius: var(--radius-xl);
  background: var(--color-background);
  box-shadow: var(--shadow-carte), var(--shadow-flottant);
}

.chat[hidden] {
  display: none;
}

.chat__entete {
  display: flex;
  align-items: center;
  gap: var(--esp-1);
}

.chat__titre {
  flex: 1;
  font-size: var(--pas-lg);
  font-weight: 600;
  letter-spacing: -0.03em;
}

.chat__action {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--color-secondary);
  cursor: pointer;
}

.chat__action:hover,
.chat__action[aria-expanded="true"] {
  background: var(--color-surface);
  color: var(--color-text);
}

.chat__action svg {
  width: 1.15rem;
  height: 1.15rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* L'historique se déplie sous l'en-tête, borné : le fil garde la place. */
.chat__liste {
  display: grid;
  align-content: start;
  gap: var(--esp-1);
  max-height: 12rem;
  padding: var(--esp-2);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.chat__liste[hidden] {
  display: none;
}

/* Une conversation : son titre, coupé net plutôt que replié sur trois lignes. */
.chat__entree {
  padding: var(--esp-2) var(--esp-3);
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  color: var(--color-secondary);
  font: inherit;
  font-size: var(--pas-sm);
  letter-spacing: -0.01em;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}

.chat__entree:hover {
  background: var(--color-background);
  color: var(--color-text);
}

.chat__entree--active,
.chat__entree--active:hover {
  background: color-mix(in srgb, var(--accent) 12%, var(--color-background));
  color: var(--color-brand-deep);
}

.chat__budget {
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  letter-spacing: -0.01em;
}

.chat__messages {
  flex: 1;
  display: grid;
  align-content: start;
  gap: var(--esp-3);
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: var(--esp-1);
}

/* --- Les bulles ----------------------------------------------------------- */

.chat__bulle {
  max-width: 88%;
  padding: var(--esp-3) var(--esp-4);
  border-radius: var(--radius-lg);
  font-size: var(--pas-md);
  letter-spacing: -0.014em;
}

.chat__bulle--utilisateur {
  justify-self: end;
  background: color-mix(in srgb, var(--accent) 10%, var(--color-background));
  color: var(--color-text);
  border-bottom-right-radius: var(--radius-sm);
}

.chat__bulle--assistant {
  justify-self: start;
  background: var(--color-surface);
  border-bottom-left-radius: var(--radius-sm);
}

/* Les retours à la ligne du modèle comptent : une liste écrite en trois lignes
   ne doit pas se recoller en un paragraphe. */
.chat__texte {
  white-space: pre-wrap;
}

/* Les produits restent dans le fil, avec un accès direct à leur fiche. */
.chat__bulle--assistant:has(.chat__produits) {
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

.chat__produits {
  display: grid;
  gap: var(--esp-2);
  margin-top: var(--esp-3);
  min-width: 0;
}

.chat__produit {
  display: grid;
  grid-template-columns: 4rem minmax(0, 1fr);
  align-items: center;
  gap: var(--esp-3);
  width: 100%;
  min-width: 0;
  padding: var(--esp-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-background);
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.chat__produit:not(:disabled):hover { border-color: var(--color-brand-deep); }
.chat__produit:focus-visible { outline: 2px solid var(--color-brand-deep); outline-offset: 2px; }
.chat__produit:disabled { cursor: default; }

.chat__produit-image {
  display: grid;
  place-items: center;
  width: 4rem;
  height: 5rem;
  overflow: hidden;
  border-radius: calc(var(--radius-sm) - 3px);
  background: var(--color-surface);
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  line-height: 1.3;
  text-align: center;
}

.chat__produit-image img { width: 100%; height: 100%; object-fit: cover; }
.chat__produit-image > span { padding-inline: var(--esp-1); }
.chat__produit-infos { display: grid; min-width: 0; gap: 2px; }
.chat__produit-titre {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
  font-size: var(--pas-xs);
  font-weight: 600;
  line-height: 1.3;
}
.chat__produit-marque {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  line-height: 1.3;
}
.chat__produit-prix { font-size: var(--pas-xs); font-weight: 500; font-variant-numeric: tabular-nums; line-height: 1.3; }
.chat__produit-action { margin-top: 2px; color: var(--color-brand-deep); font-size: var(--pas-2xs); line-height: 1.3; }
.chat__produit:not(:disabled):hover .chat__produit-action { text-decoration: underline; text-underline-offset: .2em; }
.chat__produit:disabled .chat__produit-action { color: var(--color-secondary); }
:root[data-ambiance="encre"] .chat__produit:not(:disabled) .chat__produit-action { color: var(--color-text); }

/* Ce qui a été lu pour répondre. Discret, mais toujours là. */
.chat__sources {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-1);
  margin-top: var(--esp-3);
}

.chat__source {
  padding: 0.15rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-background);
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  letter-spacing: -0.01em;
}

/* Une lecture qui a échoué se dit, sinon la réponse paraît mieux fondée
   qu'elle ne l'est. */
.chat__source--echec {
  border-color: color-mix(in srgb, var(--etat-attention) 45%, transparent);
  color: var(--etat-attention-encre);
}

.chat__erreur {
  justify-self: start;
  max-width: 88%;
  padding: var(--esp-3) var(--esp-4);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--etat-erreur) 8%, var(--color-background));
  color: var(--etat-erreur);
  font-size: var(--pas-sm);
}

/* --- L'attente ------------------------------------------------------------ */

.chat__bulle--attente {
  display: flex;
  gap: 0.3rem;
  align-items: center;
}

.chat__point {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--color-muted);
  animation: chat-pulse 1.2s ease-in-out infinite;
}

.chat__point:nth-child(2) {
  animation-delay: 0.15s;
}

.chat__point:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes chat-pulse {
  0%,
  100% {
    opacity: 0.25;
    transform: translateY(0);
  }
  50% {
    opacity: 1;
    transform: translateY(-2px);
  }
}

/* Le mouvement n'apporte rien à qui le refuse — et il gêne. */
@media (prefers-reduced-motion: reduce) {
  .chat__point {
    animation: none;
    opacity: 0.5;
  }
}

/* --- L'écran vide --------------------------------------------------------- */

.chat__vide {
  justify-self: center;
  align-self: center;
  max-width: 34rem;
  text-align: center;
}

.chat__vide-titre {
  font-size: var(--pas-xl);
  font-weight: 600;
  letter-spacing: -0.04em;
}

/* Des exemples cliquables donneraient l'idée qu'il n'y a que ces trois
   questions. Ce sont des amorces, pas un menu. */
.chat__exemples {
  display: grid;
  gap: var(--esp-2);
  margin: var(--esp-4) 0 0;
  padding: 0;
  list-style: none;
  color: var(--color-muted);
  font-size: var(--pas-sm);
}

/* --- La saisie ------------------------------------------------------------ */

/*
 * Une pilule blanche et un bouton rond à l'accent de la boutique : c'est la
 * forme de la barre de recherche du système dont cet écran s'inspire, et la
 * seule de la page qui porte une ombre teintée.
 */
.chat__saisie {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--esp-2);
  padding: var(--esp-2) var(--esp-2) var(--esp-2) var(--esp-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  background: var(--color-background);
  box-shadow: var(--shadow-soft);
}

.chat__saisie:focus-within {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

.chat__saisie textarea {
  min-height: 2.5rem;
  max-height: 10rem;
  padding: 0.6rem 0;
  border: 0;
  background: none;
  color: var(--color-text);
  font: inherit;
  font-size: var(--pas-md);
  letter-spacing: -0.014em;
  line-height: 1.45;
  resize: none;
}

.chat__saisie textarea:focus {
  outline: none;
}

.chat__envoyer {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 0;
  border-radius: 50%;
  background: var(--color-accent);
  box-shadow: var(--shadow-accent);
  cursor: pointer;
  transition: transform 0.15s ease, opacity 0.15s ease;
}

.chat__envoyer svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: var(--sur-accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chat__envoyer:hover {
  transform: translateY(-1px);
}

.chat__envoyer:disabled {
  opacity: 0.5;
  cursor: progress;
  transform: none;
}

.chat__note {
  color: var(--color-muted);
  font-size: var(--pas-2xs);
  letter-spacing: -0.01em;
}

/*
 * Sur un téléphone, le panneau prend l'écran entier : une bulle de 26 rem n'y
 * laisserait qu'une bande illisible. Le bouton rond disparaît derrière lui;
 * la croix de l'en-tête referme. `dvh` suit la barre d'adresse mobile.
 */
@media (max-width: 40rem) {
  .bulle-chat {
    right: var(--esp-4);
    bottom: var(--esp-4);
  }

  .chat {
    position: fixed;
    inset: 0;
    width: auto;
    height: 100dvh;
    border-radius: 0;
  }

  .bulle-chat:has(.chat:not([hidden])) .bulle-chat__bouton {
    display: none;
  }

  /* 16 px au moins : en dessous, iOS zoome au focus (docs/06_lessons.md). */
  .chat__saisie textarea {
    font-size: 1rem;
  }
}

/* Réception et connexion : même vocabulaire que le catalogue. */
h1, h2, h3 { font-family: var(--font-body); font-weight: 600; }
button, input, select, textarea { accent-color: var(--color-brand-deep); }
input::placeholder, textarea::placeholder { color: var(--color-muted); opacity: 1; }
input, textarea { caret-color: var(--color-brand-deep); }
::selection { background: var(--color-brand-deep); color: var(--color-background); }
.bouton, .bouton-discret { min-height: 2.75rem; border-radius: var(--radius-sm); }
.bouton { white-space: normal; }
.reception { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(16rem, 1fr); gap: var(--esp-6); align-items: stretch; }
.depot__description { color: var(--color-secondary); font-size: var(--pas-sm); }
.reception__guide { padding: var(--esp-5) 0; }
.reception__guide > h2 { font-size: var(--pas-lg); letter-spacing: -.025em; margin-bottom: var(--esp-5); }
.reception__etapes { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--esp-5); }
.reception__etapes li { display: grid; grid-template-columns: 1.75rem minmax(0, 1fr); gap: var(--esp-3); }
.reception__etapes li > span { width: 1.75rem; height: 1.75rem; display: grid; place-items: center; border: 1px solid var(--color-muted); border-radius: 50%; font-size: var(--pas-xs); color: var(--color-secondary); }
.reception__etapes h3 { font-size: var(--pas-sm); margin-bottom: var(--esp-1); }
.reception__etapes p { color: var(--color-secondary); font-size: var(--pas-xs); max-width: 40ch; }
#produits { background: none; padding: 0; border: 0; box-shadow: none; }
#produits > h2 { font-size: var(--pas-sm); font-weight: 500; color: var(--color-secondary); }
#produits .filtres { padding: var(--esp-4); margin-bottom: var(--esp-5); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-background); }
.bascule-vue__bouton { min-width: 2.75rem; min-height: 2.75rem; }
.carte-produit__etat { box-shadow: var(--shadow-soft); }
.etat-reprise { display: grid; justify-items: start; gap: var(--esp-3); padding: var(--esp-5); border: 1px solid var(--etat-erreur); border-radius: var(--radius-sm); background: var(--color-background); color: var(--color-text); }
.vide { padding-block: var(--esp-7); }
.vide__aide { max-width: 60ch; margin-inline: auto; }
.equipe__ligne { padding-block: var(--esp-4); }
.equipe__ligne > span { min-width: 0; overflow-wrap: anywhere; }
.equipe__ligne .bouton { margin-top: 0; }
.equipe-page { display: grid; gap: var(--esp-5); min-width: 0; }
.equipe-page__entete { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--esp-4); }
.equipe-page__entete h2 { font-size: var(--pas-xl); display: flex; align-items: center; gap: var(--esp-2); }
.equipe-page__entete p { margin-top: var(--esp-1); color: var(--color-secondary); font-size: var(--pas-sm); }
.equipe-page__compte { display: inline-grid; place-items: center; min-width: 1.5rem; padding: .1rem .4rem; background: var(--color-background); border: 1px solid var(--color-border); border-radius: var(--radius-sm); color: var(--color-secondary); font-size: var(--pas-xs); font-weight: 500; font-variant-numeric: tabular-nums; }
.equipe-page__actions { display: flex; flex-wrap: wrap; gap: var(--esp-2); }
/* La marge haute du `.bouton` etait annulee par l'ancetre `.equipe-page`
   seulement. L'entete d'Administration reutilise `equipe-page__entete`
   sans etre dans `.equipe-page` : ses boutons gardaient leur marge, ce qui
   les decalait et les faisait passer a la ligne. La regle suit desormais le
   groupe d'actions, ou qu'il soit. */
.equipe-page .bouton,
.equipe-page__actions .bouton { margin-top: 0; }
.equipe-page__liste-cadre, .equipe-page__invitations { border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-background); overflow: hidden; }
.equipe-page__colonnes, .equipe-page__personne { display: grid; grid-template-columns: minmax(0, 1fr) minmax(9rem, .5fr) 8rem; align-items: center; gap: var(--esp-5); padding: var(--esp-4) var(--esp-5); }
.equipe-page__colonnes { color: var(--color-secondary); font-size: var(--pas-xs); border-bottom: 1px solid var(--color-border); }
.equipe-page__liste { margin: 0; padding: 0; list-style: none; }
.equipe-page__personne + .equipe-page__personne { border-top: 1px solid var(--color-border); }
.equipe-page__identite { display: flex; align-items: center; gap: var(--esp-3); min-width: 0; }
.equipe-page__identite .jeton-initiales { flex: none; width: 2rem; height: 2rem; }
.equipe-page__courriel { font-size: var(--pas-sm); font-weight: 500; overflow-wrap: anywhere; }
.equipe-page__role { display: grid; min-width: 0; }
.equipe-page__role select, .equipe-page__formulaire-transfert select { min-width: 0; width: 100%; min-height: 2.75rem; padding: .55rem .65rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); color: var(--color-text); background: var(--color-background); font: inherit; font-size: var(--pas-sm); }
.equipe-page__role-fixe { font-size: var(--pas-sm); color: var(--color-secondary); overflow-wrap: anywhere; }
.equipe-page__personne > .bouton { justify-self: end; }
.equipe-page__retirer { color: var(--etat-erreur); border-color: transparent; background: none; }
.equipe-page__invitations h3 { display: flex; align-items: center; flex-wrap: wrap; gap: var(--esp-2); font-size: var(--pas-lg); padding: var(--esp-5) var(--esp-5) var(--esp-3); }
.equipe-page__identite--invitation { display: grid; gap: var(--esp-1); }
.equipe-page__attente { color: var(--color-muted); font-size: var(--pas-xs); }
.equipe-page__vide { padding: var(--esp-4) var(--esp-5) var(--esp-5); color: var(--color-secondary); font-size: var(--pas-sm); }
.equipe-page__avance { border-top: 1px solid var(--color-border); }
.equipe-page__avance summary { display: flex; align-items: center; justify-content: space-between; min-height: 3rem; padding-block: var(--esp-3); font-size: var(--pas-sm); color: var(--color-secondary); cursor: pointer; list-style: none; }
.equipe-page__avance summary::-webkit-details-marker { display: none; }
.equipe-page__avance summary svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 1.6; }
.equipe-page__avance[open] summary svg { transform: rotate(180deg); }
.equipe-page__transfert { padding-block: var(--esp-4); }
.equipe-page__transfert h3 { font-size: var(--pas-lg); }
.equipe-page__transfert > p { margin-top: var(--esp-2); max-width: 65ch; color: var(--color-secondary); font-size: var(--pas-sm); }
.equipe-page__formulaire-transfert { display: flex; flex-wrap: wrap; align-items: end; gap: var(--esp-4); margin-top: var(--esp-5); }
.equipe-page__formulaire-transfert label { display: grid; gap: var(--esp-2); width: min(100%, 26rem); font-size: var(--pas-sm); }

/* Le studio d'identité : les miniatures reçoivent les jetons de leur ambiance. */
.apparence { display: grid; gap: var(--esp-4); max-width: 70rem; min-width: 0; }
.apparence__champs { display: grid; gap: var(--esp-5); min-inline-size: 0; padding: 0; margin: 0; border: 0; }
.apparence__section { min-width: 0; margin: 0; padding: var(--esp-5); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-background); }
.apparence__entete { margin-bottom: var(--esp-5); }
.apparence__entete h2, .apparence__ambiances > legend { font-size: var(--pas-lg); font-weight: 600; letter-spacing: -.02em; }
.apparence__entete p, .apparence__aide { color: var(--color-secondary); font-size: var(--pas-sm); margin-top: var(--esp-1); max-width: 65ch; }
.apparence__identite { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); align-items: start; gap: var(--esp-6); }
.apparence__logo { display: grid; grid-template-columns: 6rem minmax(0, 1fr); gap: var(--esp-4); align-items: start; }
.apparence__logo-visuel { display: grid; place-items: center; width: 6rem; height: 6rem; border: 1px dashed var(--color-muted); border-radius: var(--radius-sm); background: var(--color-surface); overflow: hidden; }
.apparence__logo-visuel img { width: 100%; height: 100%; padding: var(--esp-2); object-fit: contain; }
.apparence__logo-vide { width: 2.5rem; height: 2.5rem; fill: none; stroke: var(--color-muted); stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
.apparence__logo-visuel:has(img:not([hidden])) .apparence__logo-vide { display: none; }
.apparence__logo-commandes { display: grid; justify-items: start; gap: var(--esp-2); min-width: 0; }
.apparence__logo-libelle { font-size: var(--pas-sm); font-weight: 500; }
.apparence__choisir-logo { position: relative; overflow: hidden; }
#apparence-logo { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.apparence__choisir-logo:focus-within { outline: 2px solid var(--color-brand-deep); outline-offset: 2px; }
.apparence__choisir-logo:has(input:disabled) { opacity: .55; cursor: not-allowed; }
.apparence__nom-signature { display: grid; gap: var(--esp-4); min-width: 0; }
.apparence__champ { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: var(--esp-2); min-width: 0; font-size: var(--pas-sm); font-weight: 500; }
.apparence__champ .champ__saisie, .apparence__champ .champ-aide { grid-column: 1 / -1; }
.apparence__champ .champ__saisie { min-width: 0; width: 100%; min-height: 2.75rem; }
.apparence .champ-aide { margin: 0; font-size: var(--pas-xs); font-weight: 400; }
.apparence__facultatif { color: var(--color-muted); font-size: var(--pas-xs); font-weight: 400; }
.apparence__ambiances > legend { float: left; width: 100%; padding: 0; margin-bottom: var(--esp-1); }
.apparence__ambiances > .apparence__aide { clear: both; }
.apparence__galerie { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--esp-3); margin-top: var(--esp-5); }
.apparence__choix { display: grid; align-content: start; gap: var(--esp-3); position: relative; min-width: 0; padding: var(--esp-2); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; }
.apparence__choix:hover { border-color: var(--color-muted); }
.apparence__choix:has(input:checked) { border-color: var(--color-brand-deep); box-shadow: inset 0 0 0 1px var(--color-brand-deep); }
.apparence__choix:has(input:focus-visible) { outline: 2px solid var(--color-brand-deep); outline-offset: 3px; }
.apparence__choix > input { position: absolute; right: var(--esp-3); bottom: 2.2rem; width: 1rem; height: 1rem; margin: 0; }
.apparence__choix-texte { display: grid; gap: var(--esp-1); padding: 0 var(--esp-1) var(--esp-2); }
.apparence__choix-texte strong { padding-right: var(--esp-5); font-size: var(--pas-sm); font-weight: 600; }
.apparence__choix-texte > span { color: var(--color-secondary); font-size: var(--pas-2xs); line-height: 1.35; }
.apparence__miniature { display: grid; grid-template-columns: 23% minmax(0, 1fr); height: 8.5rem; border: 1px solid var(--color-border); border-radius: .25rem; overflow: hidden; background: var(--color-surface); }
.apparence__mini-rail { display: flex; flex-direction: column; gap: .45rem; padding: .75rem .4rem; background: var(--fond-rail); border-right: 1px solid var(--color-border); }
.apparence__mini-rail > i { height: .25rem; border-radius: 1px; background: var(--color-border); }
.apparence__mini-rail > i:first-child { width: .6rem; height: .6rem; margin-bottom: .4rem; border-radius: .15rem; background: var(--accent); }
.apparence__mini-contenu { display: grid; grid-template-rows: .35rem minmax(0, 1fr) .75rem; gap: .75rem; padding: .8rem .6rem; }
.apparence__mini-titre { width: 65%; background: var(--color-text); border-radius: 1px; }
.apparence__mini-cartes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .3rem; }
.apparence__mini-cartes > i { background: var(--color-background); border: 1px solid var(--color-border); border-radius: .15rem; }
.apparence__mini-action { width: 42%; justify-self: end; background: var(--accent); border-radius: .15rem; }
.apparence__couleur { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--esp-5); margin-bottom: var(--esp-3); }
.apparence__palette { display: flex; flex-wrap: wrap; gap: var(--esp-2); }
.apparence__pastille { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; padding: .35rem; border: 1px solid var(--color-border); border-radius: 50%; background: var(--color-background); cursor: pointer; }
.apparence__pastille::before { content: ''; width: 100%; height: 100%; background: var(--pastille-couleur); border-radius: 50%; }
.apparence__pastille[aria-pressed="true"] { border-color: var(--color-text); box-shadow: inset 0 0 0 1px var(--color-text); }
.apparence__pastille--violet {
  --pastille-couleur: #6c47ff;
}
.apparence__pastille--framboise {
  --pastille-couleur: #c50090;
}
.apparence__pastille--foret {
  --pastille-couleur: #28745d;
}
.apparence__pastille--terre {
  --pastille-couleur: #ae543c;
}
.apparence__pastille--bleu {
  --pastille-couleur: #315a8c;
}
.apparence__pastille--charbon {
  --pastille-couleur: #303038;
}
.apparence__couleur-libre { display: flex; align-items: end; gap: var(--esp-3); }
.apparence__couleur-libre .apparence__champ { max-width: 13rem; }
#apparence-accent { width: 2.75rem; height: 2.75rem; flex: none; padding: .3rem; background: var(--color-background); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; }
.apparence__retour:has(#apparence-message:empty):has(#apparence-reessayer[hidden]) { display: none; }
.apparence__retour { display: grid; justify-items: start; gap: var(--esp-3); font-size: var(--pas-sm); }
.apparence__pied { position: sticky; bottom: 4.5rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--esp-3); padding: var(--esp-4); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-background); z-index: 2; }
.apparence__pied > p { max-width: 35ch; color: var(--color-secondary); font-size: var(--pas-xs); }
.apparence__actions { display: flex; gap: var(--esp-2); margin-left: auto; }
.apparence .bouton { margin-top: 0; }
.apparence__section > #apparence-accent-logo { margin-top: var(--esp-3); }
/* Les encres d'état restent fixes; leur support reste clair en ambiance sombre. */
:root[data-ambiance="encre"] :is(.rail__lien--actif, .pastille-verif, .jeton-initiales) { color: var(--color-text); }
:root[data-ambiance="encre"] .pastille-ok { background: color-mix(in srgb, var(--etat-ok) 6%, var(--sur-etat)); }
:root[data-ambiance="encre"] :is(.pastille-attention, .avertissement, .bandeau--alerte, .chat__source--echec) { background: color-mix(in srgb, var(--etat-attention) 10%, var(--sur-etat)); color: var(--etat-attention-encre); }
:root[data-ambiance="encre"] .pastille-erreur { background: color-mix(in srgb, var(--etat-erreur) 6%, var(--sur-etat)); }
:root[data-ambiance="encre"] :is(.bouton-supprimer, .equipe-page__retirer, .chat__erreur) { background: color-mix(in srgb, var(--etat-erreur) 6%, var(--sur-etat)); color: var(--etat-erreur); }
:root[data-ambiance="encre"] .tuile--attention .tuile__valeur { display: table; padding: .15rem .4rem; border-radius: var(--radius-sm); background: color-mix(in srgb, var(--etat-attention) 10%, var(--sur-etat)); }
:root[data-ambiance="encre"] :is(.produit__note, .carte-produit__drapeau, .fiche-photo__note--essai) { color: var(--color-text); text-decoration: underline dotted var(--etat-attention); text-underline-offset: .2em; }
:root[data-ambiance="encre"] :is(.champ__aide--danger, .fiche-photo__note--danger, .fiche-photo__retrait:has(.fiche-retirer:checked)) { color: var(--etat-erreur); background: var(--sur-etat); border-radius: .2rem; padding: .2rem .4rem; }
#apparence-message[data-etat="erreur"] { padding: var(--esp-3) var(--esp-4); border: 1px solid var(--etat-erreur); border-radius: var(--radius-sm); color: var(--etat-erreur); background: var(--sur-etat); }
.fenetre { border-radius: var(--radius-md); }
.fenetre-entete h2 { font-size: var(--pas-xl); }
.fenetre-fermer { min-width: 2.75rem; min-height: 2.75rem; }
.fenetre-entete { gap: var(--esp-3); }
.onboarding { overflow-y: auto; }
#connexion { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: var(--esp-7); max-width: 76rem; width: 100%; margin: 0 auto; padding: var(--esp-7) var(--gouttiere); }
.connexion__accueil { padding: var(--esp-6); }
.connexion__accueil h2 { font-size: 3.25rem; line-height: 1.05; letter-spacing: -.04em; }
.connexion__accueil > p { max-width: 35ch; margin-top: var(--esp-5); color: var(--color-secondary); }
.connexion__parcours { list-style: none; display: grid; margin: var(--esp-7) 0 0; padding: 0; }
.connexion__parcours li { display: flex; gap: var(--esp-4); padding-block: var(--esp-4); border-top: 1px solid var(--color-border); font-size: var(--pas-sm); }
.connexion__parcours span { color: var(--color-muted); font-variant-numeric: tabular-nums; }
.connexion__carte { width: 100%; max-width: 29rem; grid-template-columns: minmax(0, 1fr); padding: var(--esp-7); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: none; background: var(--color-surface); }
.connexion__carte .onboarding__intro h1 { font-size: 1.5rem; line-height: 1.2; }
.connexion__carte input { background: var(--color-background); min-height: 3rem; }
.connexion__carte .onboarding__formulaire .bouton { width: 100%; }
.connexion__carte .onboarding__message:empty { display: none; }
.barre-marque { backdrop-filter: none; }
.barre-marque__interieur { max-width: 76rem; }

@media (max-width: 64rem) {
  .coquille { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); gap: 0; }
  .rail { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--esp-2) var(--esp-3); padding: var(--esp-3) var(--esp-4) 0; overflow: visible; border-right: 0; border-bottom: 1px solid var(--color-border); position: relative; z-index: 5; }
  .rail__tete { padding: 0; grid-column: 1; grid-row: 1; }
  .rail__jeton { width: 2rem; height: 2rem; font-size: var(--pas-sm); }
  .rail__logo { width: 2rem; height: 2rem; }
  .rail__tete { grid-template-columns: 2rem minmax(0, 1fr); }
  .rail__recherche { display: none; }
  .rail__sections { grid-column: 1 / -1; grid-row: 2; display: flex; gap: var(--esp-1); overflow-x: auto; padding-bottom: var(--esp-2); }
  .rail__intertitre { display: none; }
  .rail__groupe { display: contents; }
  .rail__lien { width: auto; flex: none; white-space: nowrap; padding-inline: var(--esp-3); gap: var(--esp-2); }
  .rail__pied { grid-column: 2; grid-row: 1; margin: 0; padding: 0; border: 0; }
  .rail__signature { display: none; }
  .espace { padding: var(--esp-5); gap: var(--esp-4); }
  .entete-page h1 { font-size: 1.75rem; }
  .tuiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .reception { gap: var(--esp-5); }
  #connexion { gap: var(--esp-5); }
  .connexion__accueil { padding: 0; }
  .connexion__accueil h2 { font-size: 2.5rem; }
  .connexion__carte { padding: var(--esp-5); }
  .apparence__identite { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 40rem) {
  .rail { padding-inline: var(--esp-3); }
  .rail__marque { font-size: var(--pas-xs); }
  .rail__pied .rail__lien { padding-inline: var(--esp-2); }
  .compte__section { grid-template-columns: minmax(0, 1fr); gap: var(--esp-5); padding: var(--esp-5); }
  .rail__lien { font-size: var(--pas-xs); }
  .espace { padding: var(--esp-5) var(--esp-4) var(--esp-4); overflow-y: auto; }
  .panneaux { flex: none; min-height: auto; }
  .panneaux > [role="tabpanel"] { overflow: visible; padding: 0 0 4.5rem; }
  .entete-page h1 { font-size: 1.6rem; }
  .entete-page__sous { font-size: var(--pas-xs); }
  .tuiles { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--esp-4); }
  .tuile { padding: 0 var(--esp-3); }
  .tuile:nth-child(odd) { padding-left: 0; }
  .tuile:nth-child(even) { border-right: 0; }
  .tuile__valeur { font-size: 1.4rem; }
  .reception { grid-template-columns: minmax(0, 1fr); gap: var(--esp-3); }
  .depot { min-height: 18rem; padding: var(--esp-5) var(--esp-4); }
  .depot__titre { font-size: 1.25rem; }
  .depot__icone { width: 2.25rem; height: 2.25rem; margin-bottom: var(--esp-1); }
  .reception__guide { padding-block: var(--esp-4); }
  .grille-produits { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--esp-5) var(--esp-3); }
  .carte-produit__texte { padding: var(--esp-3) var(--esp-2); }
  .carte-produit__titre { font-size: var(--pas-xs); }
  .carte-produit__etat { top: var(--esp-1); left: var(--esp-1); font-size: .6875rem; }
  #produits .filtres { padding: var(--esp-3); gap: var(--esp-3); }
  .filtres .filtre { min-width: 0; }
  .filtre--large { flex-basis: 100%; }
  #historique-corps .tableau-lignes { min-width: 0; }
  #historique-corps .tableau-lignes td { grid-template-columns: 6.75rem minmax(0, 1fr); gap: var(--esp-2); padding-inline: 0; overflow-wrap: anywhere; }
  #historique-corps .cellule-actions { display: flex; flex-wrap: wrap; }
  .filtre:has(#produits-recherche) { flex-basis: 100%; }
  input, select, textarea, .champ__saisie { font-size: 1rem; }
  .bulle-chat { right: var(--esp-4); bottom: var(--esp-4); }
  .bulle-chat__bouton { width: 3rem; height: 3rem; }
  .fenetre-entete { flex-wrap: wrap; padding: var(--esp-3); }
  .fenetre-entete h2 { font-size: var(--pas-lg); }
  .fenetre-actions { margin-left: auto; flex-wrap: wrap; }
  .equipe__ligne { gap: var(--esp-3); flex-wrap: wrap; }
  .equipe__ligne > span { flex-basis: 100%; }
  .equipe__entete { align-items: flex-start; flex-wrap: wrap; }
  .equipe__entete .bouton { margin-top: 0; }
  .equipe-page__entete { align-items: start; }
  .equipe-page__actions { width: 100%; }
  .equipe-page__actions .bouton:not(.bouton-discret) { order: -1; }
  .equipe-page__colonnes { display: none; }
  .equipe-page__personne { grid-template-columns: minmax(0, 1fr) auto; gap: var(--esp-3); padding: var(--esp-4); }
  .equipe-page__identite { grid-column: 1 / -1; }
  .equipe-page__role, .equipe-page__role-fixe { grid-column: 1 / -1; }
  .equipe-page__personne > .bouton { grid-column: 2; }
  .equipe-page__role select, .equipe-page__formulaire-transfert select { font-size: 1rem; }
  .equipe-page__invitations h3 { padding: var(--esp-4) var(--esp-4) var(--esp-2); font-size: var(--pas-md); }
  .equipe-page__vide { padding: var(--esp-3) var(--esp-4) var(--esp-4); }
  .apparence__section { padding: var(--esp-4); }
  .apparence__logo { grid-template-columns: 4rem minmax(0, 1fr); gap: var(--esp-3); }
  .apparence__logo-visuel { width: 4rem; height: 4rem; }
  .apparence__galerie { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--esp-2); }
  .apparence__miniature { height: 6.5rem; }
  .apparence__mini-contenu { padding: .6rem .4rem; gap: .5rem; }
  .apparence__choix-texte > span { min-height: 2.7em; }
  .apparence__choix > input { bottom: 3.3rem; right: var(--esp-2); }
  .apparence__palette { gap: var(--esp-1); }
  .apparence__pastille { width: 2.5rem; height: 2.5rem; }
  .apparence__couleur-libre { width: 100%; }
  .apparence__couleur-libre .apparence__champ { flex: 1; max-width: none; }
  .apparence__pied > p { width: 100%; max-width: none; }
  .apparence__actions { width: 100%; }
  .apparence__actions .bouton { flex: 1; }
  .fiche-bloc__tete .bouton { max-width: 100%; }
  .fiche-table { min-width: 30rem; }
  .fiche-edit { grid-template-columns: minmax(0, 1fr); }
  #connexion { grid-template-columns: minmax(0, 1fr); align-content: start; padding: var(--esp-5) var(--esp-4); }
  .connexion__accueil h2 { font-size: 2rem; }
  .connexion__accueil h2 br { display: none; }
  .connexion__accueil h2 br::after { content: ' '; }
  .connexion__accueil > p { margin-top: var(--esp-3); font-size: var(--pas-sm); }
  .connexion__parcours { display: none; }
  .connexion__carte { max-width: none; }
  .connexion__carte .onboarding__intro h1 { font-size: 1.25rem; }
  .marque__nom { font-size: var(--pas-sm); }
}
