/* ==========================================================================
   Stackly — Composants
   Le vocabulaire commun des 82 pages. Ecrit contre tokens.css uniquement :
   aucune valeur en dur.
   Charge apres shell.css.
   ========================================================================== */

/* ---------- Garde generale --------------------------------------------------
   L'attribut `hidden` doit toujours masquer. Sa regle native n'a aucune
   specificite : la moindre classe portant un `display` la bat, et l'element
   reste visible alors que le gabarit le declare masque. Chaque feuille de
   module reecrivait la garde dans son coin ; elle est posee une fois ici.
   ------------------------------------------------------------------------- */

[hidden] { display: none !important; }

/* ---------- Boutons -------------------------------------------------------- */

.ui-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--control-md);
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: var(--radius-button);
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: var(--weight-semibold);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease),
              border-color var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease);
}

.ui-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ui-btn i { font-size: 14px; }

.ui-btn--primary   { background: var(--ink); color: var(--ink-on-dark); }
.ui-btn--primary:hover { background: #2F2E26; color: var(--ink-on-dark); }

.ui-btn--secondary { background: var(--surface); color: var(--ink); border-color: var(--border-strong); }
.ui-btn--secondary:hover { background: var(--surface-sunken); border-color: var(--ink); color: var(--ink); }

/* Accent : la teinte du module courant. Reservee a l'action creatrice du module. */
.ui-btn--accent    { background: var(--accent); color: #FFFFFF; }
.ui-btn--accent:hover { filter: brightness(0.93); color: #FFFFFF; }

.ui-btn--tinted    { background: var(--accent-tint); color: var(--accent-ink); }
.ui-btn--tinted:hover { background: var(--accent-tint); filter: brightness(0.97); }

.ui-btn--ghost     { background: none; color: var(--accent-ink); padding: 0 var(--space-2); }
.ui-btn--ghost:hover { color: var(--ink); }

.ui-btn--danger    { background: var(--danger); color: #FFFFFF; }
.ui-btn--danger:hover { filter: brightness(0.93); color: #FFFFFF; }

.ui-btn--danger-outline { background: var(--surface); color: var(--danger); border-color: rgba(192, 57, 43, 0.35); }
.ui-btn--danger-outline:hover { background: var(--danger-tint); color: var(--danger); }

.ui-btn--sm { height: var(--control-sm); padding: 0 14px; font-size: var(--text-sm); }
.ui-btn--lg { height: var(--control-lg); padding: 0 24px; font-size: 15px; }

.ui-btn--icon { width: var(--control-md); padding: 0; }
.ui-btn--icon.ui-btn--sm { width: var(--control-sm); }

.ui-btn[disabled],
.ui-btn--disabled {
  background: #D9D4C9;
  border-color: transparent;
  color: var(--ink-faint);
  cursor: not-allowed;
  pointer-events: none;
}

.ui-btn--block { width: 100%; }

/* Cible tactile : 44 px plancher sur mobile. Sans exception. */
@media (max-width: 992px) {
  .ui-btn { height: var(--touch-target); }
  .ui-btn--sm { height: 38px; }
  .ui-btn--icon { width: var(--touch-target); }
}

/* ---------- Champs --------------------------------------------------------- */

.ui-field { display: block; }

.ui-field-label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: #3F3D35;
  margin-bottom: 7px;
}

.ui-field-required { color: var(--danger); margin-left: 2px; }

.ui-field-control,
.ui-input,
.ui-select,
.ui-textarea {
  display: block;
  width: 100%;
  min-height: var(--field-height);
  padding: 0 13px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-field);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 14.5px;
  line-height: calc(var(--field-height) - 2px);
  transition: border-color var(--duration-fast) var(--ease),
              box-shadow var(--duration-fast) var(--ease);
}

.ui-textarea { line-height: var(--lh-normal); padding: 11px 13px; min-height: 86px; resize: vertical; }

.ui-input::placeholder,
.ui-textarea::placeholder { color: var(--ink-faint); }

.ui-input:focus,
.ui-select:focus,
.ui-textarea:focus {
  outline: none;
  border-color: var(--accent);
  border-width: 1.5px;
  box-shadow: var(--focus-ring);
}

.ui-select {
  appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%238A8578' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

.ui-field-hint {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin-top: 6px;
}

.ui-field-error {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  color: var(--danger);
  margin-top: 6px;
}

.ui-field--invalid .ui-input,
.ui-field--invalid .ui-select,
.ui-field--invalid .ui-textarea {
  border-color: var(--danger);
  border-width: 1.5px;
}

/* Montants, quantites, references : alignes et tabulaires. */
.ui-input--numeric { text-align: right; font-variant-numeric: tabular-nums; }

/* Interrupteur */
.ui-switch { display: inline-flex; align-items: center; gap: var(--space-3); cursor: pointer; }
.ui-switch input { position: absolute; opacity: 0; width: 0; height: 0; }

.ui-switch-track {
  width: 40px; height: 23px;
  border-radius: var(--radius-pill);
  background: #E9E4DB;
  position: relative;
  flex-shrink: 0;
  transition: background var(--duration-fast) var(--ease);
}

.ui-switch-track::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: var(--surface);
  transition: transform var(--duration-fast) var(--ease);
}

.ui-switch input:checked + .ui-switch-track { background: var(--accent); }
.ui-switch input:checked + .ui-switch-track::after { transform: translateX(17px); }
.ui-switch input:focus-visible + .ui-switch-track { box-shadow: var(--focus-ring); }

/* ---------- Statuts --------------------------------------------------------
   La couleur ne porte jamais l'information seule : chaque pastille a un mot
   et une icone.
   -------------------------------------------------------------------------- */

.ui-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: var(--radius-chip);
  font-size: 12.5px;
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  white-space: nowrap;
}

.ui-status i { font-size: 12px; }

.ui-status--neutral { background: var(--border-subtle); color: var(--ink-secondary); }
.ui-status--muted   { background: var(--border-subtle); color: var(--ink-muted); }
.ui-status--success { background: var(--success-tint); color: var(--success); }
.ui-status--warning { background: var(--warning-tint); color: var(--warning-ink); }
.ui-status--danger  { background: var(--danger-tint);  color: var(--danger); }
.ui-status--info    { background: var(--info-tint);    color: var(--info-ink); }
.ui-status--accent  { background: var(--accent-tint);  color: var(--accent-ink); }

/* ---------- Cartes ---------------------------------------------------------- */

.ui-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.ui-card--flush { padding: 0; overflow: hidden; }
.ui-card--padded { padding: var(--space-5) var(--space-5); }

.ui-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}

.ui-card-title {
  font-family: var(--font-display);
  font-size: var(--text-title-3);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.026em;
  color: var(--ink);
  margin: 0;
}

.ui-card-subtitle {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin: 2px 0 0;
}

.ui-card-body { padding: var(--space-5); }

.ui-card-foot {
  padding: var(--space-4) var(--space-5);
  background: var(--surface-muted);
  border-top: 1px solid var(--border-subtle);
}

/* Carte statistique : une metrique, une seule. */
.ui-stat { padding: var(--space-4) 18px; }

.ui-stat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

/* Teintes d'icone de carte statistique. Vocabulaire ferme : le gabarit passe
   un mot-cle, jamais une couleur, pour qu'aucun style en ligne ne subsiste. */
.ui-stat-icon--accent    { color: var(--accent); }
.ui-stat-icon--muted     { color: var(--ink-muted); }
.ui-stat-icon--documents { color: var(--mod-documents); }
.ui-stat-icon--stock     { color: var(--mod-stock); }
.ui-stat-icon--finance   { color: var(--mod-finance); }
.ui-stat-icon--crm       { color: var(--mod-crm); }
.ui-stat-icon--planning  { color: var(--mod-planning); }
.ui-stat-icon--expenses  { color: var(--mod-expenses); }
.ui-stat-icon--assistant { color: var(--mod-assistant); }
.ui-stat-icon--success   { color: var(--success); }
.ui-stat-icon--warning   { color: var(--warning); }
.ui-stat-icon--danger    { color: var(--danger); }

.ui-stat-label {
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}

.ui-stat-value {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: var(--weight-bold);
  letter-spacing: -0.032em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  margin-top: 10px;
  color: var(--ink);
}

.ui-stat-value--sm { font-size: var(--text-title-1); }
.ui-stat-foot { font-size: 12.5px; color: var(--ink-muted); margin-top: 7px; }

.ui-stat-delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12.5px;
  font-weight: var(--weight-semibold);
}

.ui-stat-delta--up   { color: var(--success); }
.ui-stat-delta--down { color: var(--danger); }

.ui-stat--warning { border-color: rgba(190, 135, 36, 0.4); background: rgba(190, 135, 36, 0.045); }
.ui-stat--warning .ui-stat-label,
.ui-stat--warning .ui-stat-value { color: var(--warning-ink); }
.ui-stat--warning .ui-stat-foot  { color: var(--warning-ink); }

.ui-stat--danger { border-color: rgba(192, 57, 43, 0.35); background: rgba(192, 57, 43, 0.035); }

/* ---------- Tableau ---------------------------------------------------------
   Une seule action visible par ligne : le menu. Pas trois pastilles rondes.
   -------------------------------------------------------------------------- */

.ui-table { width: 100%; border-collapse: collapse; }

.ui-table thead th,
.ui-table-head {
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: left;
  padding: 11px var(--space-4);
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.ui-table tbody td {
  padding: 0 var(--space-4);
  height: var(--row-height);
  font-size: 14px;
  color: var(--ink);
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
}

.ui-table tbody tr:last-child td { border-bottom: none; }
.ui-table tbody tr:hover td { background: var(--surface-muted); }

.ui-table .is-numeric { text-align: right; font-variant-numeric: tabular-nums; }
.ui-table .is-strong  { font-weight: var(--weight-semibold); }
.ui-table .is-muted   { color: var(--ink-secondary); }

.ui-table tr.is-selected td { background: var(--accent-tint-2); box-shadow: inset 2px 0 0 var(--accent); }
.ui-table tr.is-flagged td  { background: rgba(190, 135, 36, 0.05); box-shadow: inset 2px 0 0 var(--warning); }

.ui-table-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.ui-table-count { font-size: var(--text-sm); color: var(--ink-muted); font-variant-numeric: tabular-nums; }

.ui-row-menu {
  width: 30px; height: 30px;
  border: none;
  background: none;
  color: var(--ink-muted);
  border-radius: var(--radius-field);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.ui-row-menu:hover { background: var(--border-subtle); color: var(--ink); }

/* Sur mobile un tableau devient une liste de cartes. Jamais un defilement lateral. */
@media (max-width: 768px) {
  /*  LA CARTE QUI CONTIENT DES CARTES SE DISSOUT.
   *
   *  Chaque ligne devient ici une carte blanche, bordee, au rayon de 14 px.
   *  Elle restait pourtant enfermee dans une `.ui-card` blanche, bordee, au
   *  rayon de 14 px : un cadre dans un cadre identique. Les lignes cessaient
   *  alors de se lire comme des objets separes — elles flottaient dans un
   *  contenant de la meme couleur, sans qu'on sache ou l'un finit et l'autre
   *  commence.
   *
   *  Le cadre exterieur s'efface donc, et les lignes se posent directement sur
   *  le fond de la page. L'en-tete de la carte, lui, reste : il nomme la liste.
   *
   *  L'ancienne feuille faisait deja cela pour `.table-mobile-cards` ; la
   *  regle n'avait pas suivi le nouveau vocabulaire.  */
  .ui-card:has(.ui-table--stack) {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
  }

  .ui-card:has(.ui-table--stack) > .ui-card-head {
    padding-left: 0;
    padding-right: 0;
    border-bottom: none;
  }

  /*  EN MODE CARTE, CE N'EST PLUS UN TABLEAU.
   *
   *  Les lignes passaient bien en `block`, mais la table elle-meme restait en
   *  `display: table` : elle continuait donc a calculer une largeur
   *  intrinseque a partir de ses cellules, et depassait son conteneur — 489 px
   *  dans une colonne de 316 sur la page Stock. Le contenu etait rogne sans
   *  qu'aucune barre de defilement ne le signale.  */
  .ui-table--stack {
    display: block;
    width: 100%;
    min-width: 0;
  }

  .ui-table--stack tbody { display: block; width: 100%; background: #FBFAF8; }

  .ui-table--stack thead { display: none; }
  .ui-table--stack tbody tr {
    display: block;
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    background: var(--surface);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
    /*  Le fond de l'application est a quatre points du blanc : sans un leger
        relief, une pile de cartes blanches sur un fond presque blanc se lit
        comme une liste plate, et les lignes ne se detachent plus les unes des
        autres. La bordure seule n'y suffit pas.  */
    box-shadow: var(--shadow-1);
  }
  .ui-table--stack tbody td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    height: auto;
    padding: 6px 0;
    border-bottom: none;
    /*  Une valeur saisie par un client peut etre longue et sans espace — une
        reference, une unite fantaisiste. Sans ces deux lignes elle poussait la
        carte au-dela de l'ecran et rognait le reste en silence.  */
    min-width: 0;
    overflow-wrap: anywhere;
  }
  /*  Le libelle, lui, ne se coupe pas : c'est le repere de lecture. */
  .ui-table--stack tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    color: var(--ink-muted);
  }
}

/* ---------- Onglets de filtre ------------------------------------------------
   Des liens, pas des boutons : le filtre passe par l'adresse, une vue filtree
   se partage et survit au bouton Precedent. Le soulignement de la navigation
   interne du CRM, avec un compteur par onglet.

   <nav class="ui-tabs" aria-label="…">
     <a class="ui-tab is-current" aria-current="page" href="?statut=a-traiter">
       A traiter <span class="ui-tab-count">3</span></a>
   </nav>
   ---------------------------------------------------------------------------- */

.ui-tabs {
  display: flex;
  gap: var(--space-1);
  overflow-x: auto;
  scrollbar-width: none;
}
.ui-tabs::-webkit-scrollbar { display: none; }

.ui-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: var(--control-md);
  padding: 0 var(--space-3);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--ink-secondary);
  font-size: 14px;
  font-weight: var(--weight-medium);
  text-decoration: none;
  white-space: nowrap;
}
.ui-tab:hover { color: var(--ink); }
.ui-tab:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-field); }
.ui-tab.is-current { color: var(--ink); border-bottom-color: var(--ink); font-weight: var(--weight-semibold); }

.ui-tab-count { font-size: var(--text-xs); color: var(--ink-faint); font-variant-numeric: tabular-nums; }

/* La barre qui porte les onglets dans une carte : filet du bas, action a droite. */
.ui-tabs-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

@media (max-width: 768px) {
  .ui-tabs-bar { padding: 0; align-items: stretch; }
  .ui-tabs-bar > .ui-btn { margin: var(--space-3) 0; }
}

/* ---------- Pagination ------------------------------------------------------- */

.ui-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
  background: var(--surface-muted);
  border-top: 1px solid var(--border);
}

.ui-pagination-range { font-size: var(--text-sm); color: var(--ink-secondary); font-variant-numeric: tabular-nums; }
.ui-pagination-pages { display: flex; align-items: center; gap: 5px; }

.ui-page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 8px;
  border-radius: var(--radius-field);
  border: 1px solid transparent;
  background: none;
  color: var(--ink-secondary);
  font-size: 13.5px;
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
}

.ui-page:hover { background: var(--border-subtle); color: var(--ink); }
.ui-page.is-current { background: var(--ink); color: var(--ink-on-dark); font-weight: var(--weight-semibold); }
.ui-page--arrow { border-color: var(--border-strong); background: var(--surface); }
.ui-page--arrow.is-disabled { color: var(--ink-disabled); border-color: var(--border); pointer-events: none; }

/* ---------- Etat vide --------------------------------------------------------
   Un etat vide dit toujours quoi faire. « Aucune donnee » seul est interdit.
   ---------------------------------------------------------------------------- */

.ui-empty {
  text-align: center;
  padding: var(--space-8) var(--space-6);
}

.ui-empty-icon {
  width: 54px; height: 54px;
  border-radius: var(--radius-card);
  background: var(--accent-tint);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin: 0 auto;
}

.ui-empty-title {
  font-family: var(--font-display);
  font-size: var(--text-title-2);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.028em;
  color: var(--ink);
  margin: 18px 0 0;
}

.ui-empty-text {
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--ink-secondary);
  max-width: 44ch;
  margin: var(--space-2) auto 0;
}

.ui-empty .ui-btn { margin-top: var(--space-5); }

/* ---------- Encarts ----------------------------------------------------------- */

.ui-note {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--ink-secondary);
}

.ui-note i { font-size: 17px; flex-shrink: 0; margin-top: 1px; }
.ui-note-title { font-size: 14px; font-weight: var(--weight-semibold); color: var(--ink); margin-bottom: 3px; }

.ui-note--warning { border-color: rgba(190, 135, 36, 0.3); background: rgba(190, 135, 36, 0.055); color: var(--warning-ink); }
.ui-note--warning i, .ui-note--warning .ui-note-title { color: var(--warning-ink); }

.ui-note--danger { border-color: rgba(192, 57, 43, 0.28); background: rgba(192, 57, 43, 0.05); color: var(--danger-ink); }
.ui-note--danger i, .ui-note--danger .ui-note-title { color: var(--danger-ink); }

.ui-note--success { border-color: rgba(47, 133, 88, 0.3); background: rgba(47, 133, 88, 0.05); color: var(--success-ink); }
.ui-note--success i, .ui-note--success .ui-note-title { color: var(--success-ink); }

.ui-note--accent { border-color: var(--accent-tint); background: var(--accent-tint-2); color: var(--accent-ink); }
.ui-note--accent i, .ui-note--accent .ui-note-title { color: var(--accent-ink); }

/* ---------- Grilles utilitaires ------------------------------------------------ */

.ui-grid { display: grid; gap: var(--space-4); }
.ui-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ui-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ui-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ui-grid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }

@media (max-width: 1200px) {
  .ui-grid--4, .ui-grid--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 768px) {
  .ui-grid--2, .ui-grid--3, .ui-grid--4, .ui-grid--5 { grid-template-columns: minmax(0, 1fr); }
}

.ui-stack { display: flex; flex-direction: column; gap: var(--space-4); }
.ui-row   { display: flex; align-items: center; gap: var(--space-2); }
.ui-row--between { justify-content: space-between; }
.ui-spacer { flex-grow: 1; }

/* ---------- Modale ------------------------------------------------------------
   Utilisee par la fiche client rapide du chassis. Les styles etaient inline
   dans base.html.twig avant la refonte.
   ---------------------------------------------------------------------------- */

/* Centree verticalement. Elle s'ouvrait a 32px du haut, ce qui la posait haut
   sur un grand ecran, loin du regard et loin du bouton qui l'a ouverte. */
.ui-modal {
  position: fixed;
  inset: 0;
  z-index: 1050;
  overflow-y: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) 0;
}

/*  Le voile et le dialogue sont deux enfants de .ui-modal, qui porte
    `position: fixed` et `z-index: 1050` : elle ouvre donc son propre contexte
    d'empilement, et seul l'ordre RELATIF de ses deux enfants compte ici.

    Le voile portait `z-index: 1040` et le dialogue `z-index: auto`, c'est-a-dire
    zero. Le voile passait donc PAR-DESSUS le dialogue : il le grisait, et
    surtout il interceptait tous les clics. Comme le voile a pour role de
    fermer, cliquer sur « Resilier maintenant », sur un menu deroulant ou dans
    un champ refermait la modale au lieu d'agir. Les cinq modales du profil et
    de la facturation etaient inutilisables a la souris ; seul le clavier, qui
    ne depend pas du test de survol, continuait de fonctionner.

    0 et 1 suffisent, et disent l'intention sans nombre magique.  */
.ui-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: rgba(22, 21, 15, 0.38);
  cursor: pointer;
}

.ui-modal-dialog {
  position: relative;
  z-index: 1;
  max-width: 800px;
  /* `margin: auto` plutot que `align-items: center` seul : quand le dialogue
     depasse la hauteur de l'ecran, un centrage par align-items rogne son haut
     et le rend inatteignable au defilement. La marge automatique, elle, le
     laisse entier. */
  margin: auto;
  padding: 0 var(--gutter-page);
}

.ui-modal-content {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card-lg);
  box-shadow: var(--shadow-3);
  overflow: hidden;
}

.ui-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}

.ui-modal-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-size: var(--text-title-2);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.028em;
  color: var(--ink);
  margin: 0;
}

.ui-modal-title i { font-size: 20px; color: var(--accent); }

.ui-modal-close {
  width: var(--control-sm);
  height: var(--control-sm);
  border: none;
  background: none;
  color: var(--ink-muted);
  font-size: 22px;
  line-height: 1;
  border-radius: var(--radius-field);
  cursor: pointer;
}

.ui-modal-close:hover { background: var(--border-subtle); color: var(--ink); }

.ui-modal-body {
  padding: var(--space-5);
  max-height: calc(100vh - 250px);
  overflow-y: auto;
}

.ui-modal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-muted);
  border-top: 1px solid var(--border-subtle);
}

@media (max-width: 992px) {
  .ui-modal-close { width: var(--touch-target); height: var(--touch-target); }
}

/* ---------- Fenetres de message (flash) ---------------------------------------
   Une action qui aboutit doit le dire. Ces fenetres etaient decrites a deux
   endroits qui se contredisaient : 230 lignes dans shell-legacy.css, en
   couleurs brutes et degrades, puis 48 lignes dans shell.css qui en
   redefinissaient la moitie. Tout est ici, sur les jetons.
   ---------------------------------------------------------------------------- */

/*  EN BAS, AU CENTRE.

    Les messages sortaient en haut a droite, la ou chaque ecran de
    l'application pose ses boutons d'action : ils recouvraient « Nouveau
    document », « Exporter », « Ajouter un produit »... c'est-a-dire ce sur
    quoi on venait de cliquer et ce sur quoi on allait cliquer ensuite. Le bas
    du centre n'est occupe par rien et se lit sans quitter des yeux le contenu.

    `bottom` tient compte de `safe-area-inset-bottom` : sur un telephone, la
    barre de geste mangeait le message. */
#flashMessagesContainer {
  position: fixed;
  bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  /*  Au-dessus des modales, pour de bon. La valeur etait 1080 sous un
      commentaire qui annoncait le contraire : les modales de l'application
      montent a 1200, et deux fonds de modale jusqu'a 9999. Un message qui
      confirme une suppression ne doit pas passer derriere la fenetre qui l'a
      declenchee. */
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  width: min(420px, calc(100vw - var(--space-5) * 2));
  pointer-events: none;   /* la page reste cliquable autour des fenetres */
}

.flash-toast {
  pointer-events: auto;
  position: relative;
  width: 100%;
  display: flex;
  align-items: flex-start;
  gap: 11px;
  overflow: hidden;
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-3);
  color: var(--ink);
  animation: flashEntree 0.28s var(--ease);
}

.flash-toast.removing {
  animation: flashSortie 0.28s var(--ease) forwards;
}

@keyframes flashEntree {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes flashSortie {
  to { opacity: 0; transform: translateY(14px); }
}

.flash-toast-icon { flex-shrink: 0; margin-top: 1px; }
.flash-toast-icon svg { display: block; width: 18px; height: 18px; }

.flash-toast-content {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--ink-secondary);
  /* Un message peut citer un nom de fichier ou de client sans espace. */
  overflow-wrap: anywhere;
}

/* La couleur ne porte que l'icone et le filet : le texte reste a l'encre,
   lisible quel que soit le type. */
.flash-toast-success .flash-toast-icon { color: var(--success); }
.flash-toast-error   .flash-toast-icon,
.flash-toast-danger  .flash-toast-icon { color: var(--danger); }
.flash-toast-warning .flash-toast-icon { color: var(--warning-ink); }
.flash-toast-info    .flash-toast-icon { color: var(--info); }

.flash-toast-close {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-sm);
  height: var(--control-sm);
  margin: -4px -4px 0 0;
  padding: 0;
  border: none;
  border-radius: var(--radius-field);
  background: none;
  color: var(--ink-muted);
  cursor: pointer;
}

.flash-toast-close:hover { background: var(--border-subtle); color: var(--ink); }
.flash-toast-close:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.flash-toast-close svg { display: block; width: 16px; height: 16px; }

/* Le filet de progression dit combien de temps il reste avant disparition.
   Il prend la couleur de l'icone, donc du type de message. */
.flash-progress {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: currentColor;
  opacity: 0.28;
  transition: width 12s linear;
}

.flash-toast-success .flash-progress { color: var(--success); }
.flash-toast-error   .flash-progress,
.flash-toast-danger  .flash-progress { color: var(--danger); }
.flash-toast-warning .flash-progress { color: var(--warning-ink); }
.flash-toast-info    .flash-progress { color: var(--info); }

/* Sur telephone, la fenetre prend la largeur, gouttieres comprises. */
@media (max-width: 600px) {
  #flashMessagesContainer {
    left: var(--gutter-page);
    right: var(--gutter-page);
    top: calc(var(--space-4) + env(safe-area-inset-top, 0px));
    width: auto;
  }
}

/* Une disparition qui glisse n'apporte rien a qui demande moins de mouvement,
   et le filet de progression cesse d'etre une animation pour devenir un
   simple reste de temps. */
@media (prefers-reduced-motion: reduce) {
  .flash-toast,
  .flash-toast.removing { animation: none; }
  .flash-progress { transition: none; }
}

/* ---------- Modale d'alerte et de confirmation (.cm-*) -----------------------
   C'est la modale que shell.js construit pour customAlert() et customConfirm(),
   donc celle qui s'affiche a chaque action destructrice de l'application. Elle
   vivait dans shell-legacy.css, en couleurs brutes — #ef4444, #f59e0b,
   #10b981, #111827, #6b7280, #f3f4f6 — et sur var(--primary), qui vaut
   l'ancien violet #6022C4. Reecrite ici sur les jetons, dans le meme
   vocabulaire que .ui-modal ci-dessus.

   Les noms de classes sont conserves : shell.js les construit, et 94 appels
   dans l'application en dependent.
   ---------------------------------------------------------------------------- */

/* shell.js bascule cette classe pour ouvrir et fermer. Elle doit l'emporter
   sur le `display: flex` de .cm-overlay, d'ou le !important — meme raison que
   la garde [hidden] plus haut dans cette feuille. */
.cm-hidden { display: none !important; }

.cm-overlay {
  position: fixed;
  inset: 0;
  /*  Devant toute modale applicative : c'est le dernier ecran avant un geste
      irreversible. A 1060, il passait derriere les modales de l'inventaire
      (1200) et le bouton de confirmation devenait incliquable. */
  z-index: var(--z-confirm);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgba(22, 21, 15, 0.38);
  backdrop-filter: blur(3px);
  animation: cmFadeIn 0.15s var(--ease);
}

.cm-box {
  width: 100%;
  max-width: 420px;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card-lg);
  box-shadow: var(--shadow-3);
  animation: cmSlideIn 0.2s var(--ease);
}

@keyframes cmFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes cmSlideIn {
  from { opacity: 0; transform: translateY(-12px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)     scale(1); }
}

/* La reduction de mouvement est respectee : l'apparition reste instantanee. */
@media (prefers-reduced-motion: reduce) {
  .cm-overlay,
  .cm-box { animation: none; }
}

/* Le filet de couleur en tete, qui dit la nature du message avant la lecture. */
.cm-stripe { height: 4px; width: 100%; }

.cm-stripe--danger  { background: var(--danger); }
.cm-stripe--warning { background: var(--warning); }
.cm-stripe--error   { background: var(--danger); }
.cm-stripe--success { background: var(--success); }
.cm-stripe--info    { background: var(--info); }

.cm-icon-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  margin: var(--space-5) auto 0;
  border-radius: var(--radius-pill);
  font-size: 20px;
}

.cm-icon-wrap--danger  { background: var(--danger-tint);  color: var(--danger-ink); }
.cm-icon-wrap--warning { background: var(--warning-tint); color: var(--warning-ink); }
.cm-icon-wrap--error   { background: var(--danger-tint);  color: var(--danger-ink); }
.cm-icon-wrap--success { background: var(--success-tint); color: var(--success-ink); }
.cm-icon-wrap--info    { background: var(--info-tint);    color: var(--info-ink); }

.cm-title {
  margin: var(--space-3) var(--space-5) 0;
  font-family: var(--font-display);
  font-size: var(--text-title-2);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.028em;
  line-height: var(--lh-snug);
  color: var(--ink);
  text-align: center;
}

.cm-message {
  margin: var(--space-2) var(--space-5) 0;
  font-size: var(--text-body);
  line-height: var(--lh-normal);
  color: var(--ink-secondary);
  text-align: center;
}

.cm-footer {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-5);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-muted);
  border-top: 1px solid var(--border-subtle);
}

/* Sur un telephone, les deux actions prennent la largeur et se superposent :
   viser un bouton de 90px au pouce, en bas d'ecran, est une source d'erreur
   sur une action destructrice. */
@media (max-width: 480px) {
  .cm-footer { flex-direction: column-reverse; }
  .cm-footer .ui-btn { width: 100%; }
}

/* ==========================================================================
   Assistant a etapes (import d'un fichier)
   Le chassis partage par les assistants d'import — stock, CRM, et les
   suivants. Rien ici ne connait le module : la teinte vient de --accent,
   remappe par <body data-module>. Le nombre d'etapes, leurs libelles et la
   liste des options ne sont pas decrits ici : le gabarit en decide.
   Aucun selecteur d'element nu : cette feuille est chargee par toutes les
   pages.
   ========================================================================== */

/* ---------- Fleche de retour dans la barre du haut --------------------------
   Un carre contour, pas la pastille teintee par defaut du chassis.
   ---------------------------------------------------------------------------- */

.topbar-icon:has(.ui-wizard-back) { background: none; }

.ui-wizard-back {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-button);
  background: var(--surface);
  color: var(--ink);
  font-size: 17px;
  text-decoration: none;
}

.ui-wizard-back:hover { background: var(--surface-sunken); border-color: var(--ink); color: var(--ink); }
.ui-wizard-back:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ---------- Indicateur d'etapes ----------------------------------------------
   Bandeau pleine largeur sous la barre du haut : il deborde les gouttieres
   de .content-wrapper. Deux etapes ou cinq, la regle ne compte pas.
   ---------------------------------------------------------------------------- */

.ui-wizard-steps {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-3) 0;
  margin: calc(-1 * var(--space-6)) calc(-1 * var(--space-8)) var(--space-6);
  padding: var(--space-5) var(--space-8);
  background: var(--canvas);
  border-bottom: 1px solid var(--border);
}

.ui-wizard-step {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
}

.ui-wizard-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border: 1.5px solid var(--border-dashed);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-faint);
  font-size: 13.5px;
  font-weight: var(--weight-bold);
  line-height: 1;
}

.ui-wizard-badge i { font-size: 15px; }

.ui-wizard-step.is-done .ui-wizard-badge,
.ui-wizard-step.is-current .ui-wizard-badge {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--surface);
}

.ui-wizard-text { display: flex; flex-direction: column; min-width: 0; }

.ui-wizard-name {
  font-size: 14px;
  font-weight: var(--weight-semibold);
  color: var(--ink-faint);
}

.ui-wizard-step.is-done .ui-wizard-name,
.ui-wizard-step.is-current .ui-wizard-name { color: var(--ink); }

.ui-wizard-note {
  font-size: var(--text-xs);
  color: var(--ink-muted);
}

.ui-wizard-step.is-current .ui-wizard-note {
  color: var(--accent-ink);
  font-weight: var(--weight-medium);
}

.ui-wizard-line {
  flex: 0 1 90px;
  min-width: var(--space-6);
  height: 2px;
  margin: 0 var(--space-5);
  background: var(--border);
}

.ui-wizard-line.is-done { background: var(--accent); }

/* ---------- Gabarits de page de l'assistant ----------------------------------- */

/* Premiere etape : deux cartes cote a cote, puis la barre d'actions. */
.ui-wizard-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.ui-wizard-split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: var(--space-5);
}

/* Etapes suivantes : le travail a gauche, la decision a droite. */
.ui-wizard-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  align-items: start;
  gap: var(--space-5);
}

.ui-wizard-side {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
}

.ui-wizard-side .ui-card--padded { padding: var(--space-5) 22px; }

/* En-tete de carte de l'assistant : un peu plus dense que .ui-card-head,
   et un filet franc plutot que le separateur de lignes. */
.ui-wizard-head {
  align-items: center;
  padding: 17px var(--space-5);
  border-bottom-color: var(--border);
}

.ui-wizard-head .ui-card-subtitle { font-size: 12.5px; }

/* ---------- Barres d'actions ---------------------------------------------------
   `--end` ferme un formulaire pleine largeur, `--split` ferme une colonne
   laterale : deux boutons de meme largeur.
   ---------------------------------------------------------------------------- */

.ui-wizard-actions { display: flex; gap: var(--space-3); }
.ui-wizard-actions--end { justify-content: flex-end; }
.ui-wizard-actions--split .ui-btn { flex: 1 1 0; min-width: 0; }

/* ---------- Mention de bas de panneau ------------------------------------------
   Icone + texte, sans cadre : ce n'est pas un encart .ui-note.
   ---------------------------------------------------------------------------- */

.ui-wizard-hint {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0;
  font-size: 12.5px;
  line-height: var(--lh-normal);
  color: var(--ink-secondary);
}

.ui-wizard-hint i {
  flex-shrink: 0;
  margin-top: 2px;
  font-size: 15px;
  color: var(--ink-muted);
}

/* ---------- Zone de depot de fichier -------------------------------------------- */

.ui-dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-height: 190px;
  padding: var(--space-8) var(--space-5);
  border: 1.5px dashed var(--border-dashed);
  border-radius: var(--radius-card);
  background: var(--surface-muted);
  cursor: pointer;
  text-align: center;
  transition: border-color var(--duration-fast) var(--ease),
              background var(--duration-fast) var(--ease);
}

.ui-dropzone:hover,
.ui-dropzone:focus-visible,
.ui-dropzone.is-over {
  outline: none;
  border-color: var(--accent);
  background: var(--accent-tint-2);
}

.ui-dropzone-icon {
  font-size: 30px;
  color: var(--accent);
}

.ui-dropzone-title {
  font-family: var(--font-display);
  font-size: var(--text-title-3);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-title);
  color: var(--ink);
  margin: var(--space-2) 0 0;
}

.ui-dropzone-sub {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  margin: 0;
}

/* Le champ natif reste dans le flux pour l'accessibilite, sans etre visible. */
.ui-file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.ui-file-selected {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--touch-target);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--success);
  border-radius: var(--radius-card);
  background: var(--success-tint);
  color: var(--success-ink);
}

.ui-file-selected i { font-size: 17px; }

.ui-file-name {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- Marche a suivre, numerotee ------------------------------------------
   « Comment ca marche » : autant d'items que le gabarit en pose.
   ---------------------------------------------------------------------------- */

.ui-steplist {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ui-steplist-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.ui-steplist-num {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-pill);
  background: var(--accent-tint);
  color: var(--accent-ink);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}

.ui-steplist-title {
  font-size: 14px;
  font-weight: var(--weight-semibold);
  color: var(--ink);
  margin: 3px 0 2px;
}

.ui-steplist-sub {
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--ink-secondary);
  margin: 0;
}

/* ---------- Grille de correspondance des colonnes --------------------------------
   Quatre colonnes : source, fleche, champ cible, etat. Les champs cibles sont
   ceux du module ; la grille ne les connait pas.
   ---------------------------------------------------------------------------- */

.ui-map-card { align-self: start; }
.ui-map-count { flex-shrink: 0; }

.ui-map-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--control-sm) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  min-height: var(--row-height);
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}

.ui-map-row:last-child { border-bottom: none; }

.ui-map-labels {
  min-height: 0;
  padding-top: 10px;
  padding-bottom: 10px;
  background: var(--surface-sunken);
  border-bottom-color: var(--border);
}

.ui-map-label {
  font-size: var(--text-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}

.ui-map-source { min-width: 0; }

.ui-map-name {
  margin: 0;
  font-size: 14px;
  font-weight: var(--weight-medium);
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Valeurs d'exemple sous l'en-tete : on reconnait sa colonne a son contenu,
   pas a son titre. */
.ui-map-sample {
  margin: 0;
  font-size: 12.5px;
  color: var(--ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-map-arrow {
  justify-self: center;
  font-size: 17px;
  color: var(--ink-disabled);
}

.ui-map-target { min-width: 0; }

.ui-map-select {
  height: var(--control-md);
  min-height: var(--control-md);
  line-height: calc(var(--control-md) - 2px);
  font-size: 14px;
}

.ui-map-state { justify-self: start; }

/* Colonne a confirmer : fond ambre discret et filet vertical.
   Le lisere passe par une ombre interne : pas de decalage de 0,5 px. */
.ui-map-row.is-todo {
  background: var(--mod-expenses-tint-2);
  box-shadow: inset 2px 0 0 var(--warning);
}

.ui-map-row.is-todo .ui-map-arrow { color: var(--warning-ink); }

.ui-map-row.is-todo .ui-map-select {
  border-color: var(--warning);
  box-shadow: inset 0 0 0 1px var(--warning);
}

/* Colonne ignoree. */
.ui-map-row.is-off .ui-map-name,
.ui-map-row.is-off .ui-map-sample { color: var(--ink-faint); }

.ui-map-row.is-off .ui-map-arrow { color: var(--border-strong); }

.ui-map-row.is-off .ui-map-select {
  border-style: dashed;
  border-color: var(--border-dashed);
  background-color: transparent;
  color: var(--ink-faint);
}

/* ---------- Liste de choix exclusifs ---------------------------------------------
   Politique de doublon, cle de rapprochement, type de contact : une carte,
   plusieurs options radio dessinees. Le chassis ne connait aucune option en
   particulier ; les variantes propres a un module restent dans sa feuille.
   ---------------------------------------------------------------------------- */

.ui-choice-list {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin: var(--space-4) 0 0;
  padding: 0;
  border: 0;
}

.ui-choice-option {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: var(--space-3) 13px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-button);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease),
              background var(--duration-fast) var(--ease);
}

.ui-choice-option input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.ui-choice-mark {
  flex-shrink: 0;
  width: 19px;
  height: 19px;
  margin-top: 1px;
  border: 1.5px solid var(--border-dashed);
  border-radius: 50%;
  background: var(--surface);
}

.ui-choice-text { display: flex; flex-direction: column; min-width: 0; }

.ui-choice-title {
  font-size: 14px;
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

.ui-choice-desc {
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-secondary);
}

.ui-choice-option:hover { border-color: var(--ink-muted); }

.ui-choice-option:has(input:checked) {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  background: var(--accent-tint-2);
}

.ui-choice-option:has(input:checked) .ui-choice-mark {
  border-color: var(--accent);
  border-width: 5px;
}

.ui-choice-option:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Carte a choix : le sous-titre porte la question, il respire un peu plus
   que le sous-titre de carte par defaut. */
.ui-choice-card .ui-card-subtitle {
  font-size: 12.5px;
  line-height: 1.45;
  margin-top: var(--space-1);
}

/* ---------- Panneau « Ce qui va se passer » ---------------------------------------
   L'effet annonce sur les donnees, avant toute ecriture.
   ---------------------------------------------------------------------------- */

.ui-plan-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: var(--space-4) 0 0;
}

.ui-plan-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.ui-plan-term {
  font-size: 13.5px;
  font-weight: var(--weight-regular);
  color: var(--ink-secondary);
}

.ui-plan-value {
  margin: 0;
  font-size: var(--text-title-3);
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

.ui-plan-value--success { color: var(--success); }
.ui-plan-value--warning { color: var(--warning-ink); }

.ui-plan-row--total {
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-subtle);
}

.ui-plan-row--total .ui-plan-term {
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

.ui-plan-note {
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  line-height: 1.45;
  color: var(--ink-muted);
}

/* ---------- Tableau large : seul le tableau defile, jamais la page --------------- */

.ui-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---------- Adaptations ------------------------------------------------------------ */

@media (max-width: 1200px) {
  .ui-wizard-layout { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 992px) {
  .ui-wizard-split { grid-template-columns: minmax(0, 1fr); }
  .ui-wizard-back { width: var(--touch-target); height: var(--touch-target); }
  .ui-wizard-steps {
    margin: calc(-1 * var(--space-5)) calc(-1 * var(--gutter-page)) var(--space-5);
    padding: var(--space-4) var(--gutter-page);
  }
  .ui-wizard-line { flex: 0 1 var(--space-8); margin: 0 var(--space-3); }
}

@media (max-width: 768px) {
  .ui-wizard-steps {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
  }
  .ui-wizard-step { width: 100%; }
  .ui-wizard-line {
    flex: none;
    width: 2px;
    height: var(--space-4);
    min-width: 0;
    margin: 0 0 0 14px;
  }
  .ui-wizard-actions { flex-direction: column-reverse; }
  .ui-wizard-actions--end .ui-btn { width: 100%; }
  .ui-map-row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2);
    padding: var(--space-4) var(--space-4);
  }
  .ui-map-labels { display: none; }
  .ui-map-arrow { display: none; }
  .ui-map-select { min-height: var(--touch-target); line-height: calc(var(--touch-target) - 2px); }
  .ui-map-name,
  .ui-map-sample { white-space: normal; }
  /* Cible tactile : chaque choix reste cliquable au doigt. */
  .ui-choice-option { min-height: var(--touch-target); }
}
