/*
  Feuille du design system.

  Choix assumé : les composants du design system utilisent des classes globales
  préfixées « app- » plutôt que l'isolation CSS de Blazor. Un design system est par
  nature global et doit rester surchargeable par le Host ; l'isolation est réservée
  aux composants propres au Host et aux modules.
*/

/* --- Socle ------------------------------------------------------------- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    font-size: 16px;
}

body {
    margin: 0;
    font-family: var(--font-family-base);
    font-size: var(--font-size-md);
    line-height: var(--line-height-base);
    color: var(--color-text);
    background-color: var(--color-background);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    margin: 0;
    font-weight: var(--font-weight-semibold);
    line-height: 1.25;
}

a {
    color: var(--color-primary);
}

:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}

/*
  FocusOnNavigate place le curseur du lecteur d'écran sur le titre de la page à chaque
  navigation. C'est une cible de focus PROGRAMMATIQUE, pas un élément actionnable :
  l'anneau de focus n'y apporte rien et encadrait le titre à chaque changement de page.
  La règle est volontairement limitée à tabindex="-1" : tous les vrais contrôles
  gardent leur indicateur de focus.
*/
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none;
}

.app-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* --- Bouton ------------------------------------------------------------ */

.app-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-sm);
    padding: 0 var(--spacing-lg);
    height: 2.375rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.app-button:disabled,
.app-button[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
}

.app-button--primary {
    background-color: var(--color-primary);
    color: var(--color-on-primary);
    box-shadow: var(--shadow-sm);
}

.app-button--primary:hover:not(:disabled) {
    background-color: var(--color-primary-hover);
}

.app-button--secondary {
    background-color: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-text);
}

.app-button--secondary:hover:not(:disabled) {
    background-color: var(--color-surface-muted);
}

.app-button--ghost {
    background-color: transparent;
    color: var(--color-text-secondary);
}

.app-button--ghost:hover:not(:disabled) {
    background-color: var(--color-surface-sunken);
}

.app-button--danger {
    background-color: var(--color-danger);
    color: var(--color-on-primary);
}

.app-button--sm {
    height: 2rem;
    padding: 0 var(--spacing-md);
    font-size: var(--font-size-xs);
}

.app-button--lg {
    height: 2.75rem;
    padding: 0 var(--spacing-xl);
    font-size: var(--font-size-md);
}

.app-icon-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background-color: transparent;
    color: var(--color-muted);
    cursor: pointer;
    transition: background-color var(--transition-fast);
}

.app-icon-button:hover:not(:disabled) {
    background-color: var(--color-surface-sunken);
    color: var(--color-text);
}

/* --- Carte -------------------------------------------------------------- */

.app-card {
    display: flex;
    gap: var(--spacing-lg);
    padding: var(--spacing-xl);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.app-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    flex: 1 1 auto;
    min-width: 0;
}

.app-card--flat {
    box-shadow: none;
}

.app-card__header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--spacing-md);
}

.app-card__title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
}

.app-card__hint {
    font-size: var(--font-size-xs);
    color: var(--color-muted);
}

/* --- Carte d'indicateur --------------------------------------------------- */

.app-stat-card {
    flex-direction: column;
    gap: var(--spacing-sm);
    padding: var(--spacing-lg);
}

.app-stat-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
}

.app-stat-card__head .app-card__icon {
    width: 2.25rem;
    height: 2.25rem;
}

/* Valeur et légende sur une même ligne ; la légende passe dessous si elle est longue. */
.app-stat-card__figures {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--spacing-xs) var(--spacing-sm);
}

/* Pastille d'icône : la signature visuelle des cartes d'indicateur. */
.app-card__icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-md);
    background-color: var(--color-surface-sunken);
    color: var(--color-text-secondary);
}

.app-card__icon--info { background-color: var(--color-info-soft); color: var(--color-info); }
.app-card__icon--success { background-color: var(--color-success-soft); color: var(--color-success); }
.app-card__icon--warning { background-color: var(--color-warning-soft); color: var(--color-warning); }
.app-card__icon--danger { background-color: var(--color-danger-soft); color: var(--color-danger); }

/* --- Badge -------------------------------------------------------------- */

.app-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-2xs) var(--spacing-sm);
    border-radius: var(--radius-pill);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    background-color: var(--color-surface-sunken);
    color: var(--color-text-secondary);
    white-space: nowrap;
}

.app-badge--success { background-color: var(--color-success-soft); color: var(--color-success); }
.app-badge--warning { background-color: var(--color-warning-soft); color: var(--color-warning); }
.app-badge--danger { background-color: var(--color-danger-soft); color: var(--color-danger); }
.app-badge--info { background-color: var(--color-info-soft); color: var(--color-info); }

/* --- Liste déroulante avec recherche ------------------------------------- */

.app-search-select {
    position: relative;
}

.app-search-select > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
    min-height: 2.75rem;
    padding: 0 var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
    font-size: var(--font-size-sm);
    cursor: pointer;
    /* Retire le triangle natif : l'icône chevron le remplace. */
    list-style: none;
}

.app-search-select > summary::-webkit-details-marker {
    display: none;
}

.app-search-select > summary > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-search-select[open] > summary {
    border-color: var(--color-primary);
}

.app-search-select__panel {
    position: absolute;
    z-index: 30;
    top: calc(100% + var(--spacing-2xs));
    left: 0;
    width: max(100%, 18rem);
    padding: var(--spacing-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
    box-shadow: var(--shadow-lg, 0 18px 45px rgba(15, 23, 42, .18));
}

.app-search-select__search {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: 0 var(--spacing-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    color: var(--color-muted);
}

/*
  Spécificité volontairement doublée sur tout ce qui est « input » ou « button » dans ce
  composant.

  Les pages posent des règles larges du genre « .une-grille input { width:100% } », de même
  spécificité que « .app-search-select__search input », et leur feuille est chargée APRÈS
  celle-ci : à égalité, l'ordre tranche et la page gagne. Résultat vécu : des cases à cocher
  larges comme la ligne, qui chassaient leur propre libellé hors du panneau.

  Répéter la classe racine porte ces règles à deux classes et met le composant hors d'atteinte,
  sans recourir à !important.
*/

.app-search-select .app-search-select__search input {
    flex: 1;
    min-width: 0;
    width: auto;
    height: 2.25rem;
    min-height: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    outline: 0;
    background: transparent;
    color: var(--color-text);
    font: inherit;
    font-size: var(--font-size-sm);
}

.app-search-select__options {
    /* Hauteur bornée : ces référentiels comptent des centaines d'entrées, et un panneau
       aussi long que la page rendrait le reste du formulaire inatteignable. */
    max-height: 16rem;
    overflow: auto;
    margin-top: var(--spacing-xs);
}

.app-search-select .app-search-select__options button {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-sm);
    width: 100%;
    min-height: 0;
    padding: var(--spacing-xs) var(--spacing-sm);
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text);
    font: inherit;
    font-size: var(--font-size-sm);
    text-align: left;
    cursor: pointer;
}

.app-search-select .app-search-select__options button:hover {
    background-color: var(--color-surface-muted);
}

.app-search-select .app-search-select__options button.is-selected {
    background-color: var(--color-primary);
    color: var(--color-on-primary);
}

.app-search-select__options strong {
    flex: 0 0 auto;
    font-size: var(--font-size-xs);
}

.app-search-select__toolbar {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-sm);
    padding: var(--spacing-xs) 0;
    border-bottom: 1px solid var(--color-border-subtle);
}

.app-search-select__toolbar button {
    border: 0;
    background: transparent;
    color: var(--color-primary);
    font: inherit;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
}

.app-search-select .app-search-select__check {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.app-search-select .app-search-select__check:hover {
    background-color: var(--color-surface-muted);
}

.app-search-select .app-search-select__check input[type="checkbox"] {
    flex: 0 0 auto;
    /* Dimensions figées : une page qui étire ses champs à 100 % transformerait la case en pavé
       et pousserait le libellé hors du panneau. */
    width: 1rem;
    height: 1rem;
    min-height: 0;
    margin: 0;
    padding: 0;
    border-radius: 0;
    accent-color: var(--color-primary);
}

.app-search-select .app-search-select__check > span {
    display: grid;
    min-width: 0;
    /* Remise à zéro des règles de libellé de formulaire : hors de leur contexte, elles
       rendaient ce texte gris, gras et en petites capitales. */
    margin: 0;
    color: var(--color-text);
    font-weight: var(--font-weight-medium);
    text-transform: none;
    letter-spacing: normal;
}

.app-search-select .app-search-select__check strong {
    font-size: var(--font-size-xs);
}

.app-search-select .app-search-select__check small {
    color: var(--color-muted);
    font-size: var(--font-size-xs);
}

.app-search-select__empty {
    margin: 0;
    padding: var(--spacing-sm);
    color: var(--color-muted);
    font-size: var(--font-size-xs);
}

/* --- Explication d'un indicateur ---------------------------------------- */

.app-hint {
    position: relative;
    display: inline-flex;
    align-items: center;
    color: var(--color-muted);
    cursor: help;
    vertical-align: middle;
}

.app-hint:hover,
.app-hint:focus-visible {
    color: var(--color-info);
}

.app-hint::after {
    content: attr(data-hint);
    position: absolute;
    top: calc(100% + var(--spacing-2xs));
    left: 50%;
    transform: translateX(-50%);
    z-index: 20;
    /* Une définition tient en deux ou trois lignes : assez large pour ne pas se découper
       mot à mot, assez étroite pour rester lisible. */
    width: max-content;
    max-width: 22rem;
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-sm);
    background-color: var(--color-text);
    color: var(--color-surface);
    font-size: var(--font-size-xs);
    font-weight: 400;
    line-height: 1.45;
    text-align: left;
    /* Les cartes KPI mettent leurs libellés en petites majuscules espacées : sans ces deux
       remises à zéro, l'explication en hériterait et deviendrait illisible. */
    text-transform: none;
    letter-spacing: normal;
    white-space: normal;
    /* Masquée sans display:none, pour que la transition existe — et surtout pour qu'elle
       n'intercepte jamais la souris tant qu'elle est invisible. */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 120ms ease-in-out;
}

.app-hint:hover::after,
.app-hint:focus-visible::after {
    opacity: 1;
    visibility: visible;
}

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

.app-field {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
}

.app-field__label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
}

.app-field__wrapper {
    position: relative;
    display: flex;
}

.app-field__icon {
    position: absolute;
    left: var(--spacing-md);
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    color: var(--color-muted);
    pointer-events: none;
}

.app-field__control {
    width: 100%;
    height: 2.375rem;
    padding: 0 var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: inherit;
    font-size: var(--font-size-sm);
}

.app-field__wrapper--with-icon .app-field__control {
    padding-left: var(--spacing-2xl);
}

.app-field__control:focus {
    border-color: var(--color-primary);
}

.app-field__hint {
    font-size: var(--font-size-xs);
    color: var(--color-muted);
}

.app-field__error {
    font-size: var(--font-size-xs);
    color: var(--color-danger);
}

/* --- Alerte ------------------------------------------------------------- */

.app-alert {
    display: flex;
    gap: var(--spacing-md);
    padding: var(--spacing-lg);
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    font-size: var(--font-size-sm);
}

.app-alert--info { background-color: var(--color-info-soft); color: var(--color-text); border-color: var(--color-primary-soft); }
.app-alert--success { background-color: var(--color-success-soft); color: var(--color-text); }
.app-alert--warning { background-color: var(--color-warning-soft); color: var(--color-text); }
.app-alert--danger { background-color: var(--color-danger-soft); color: var(--color-text); }

.app-alert__title {
    font-weight: var(--font-weight-semibold);
}

/* --- Attente et vide ---------------------------------------------------- */

.app-spinner {
    display: inline-block;
    width: 1.25rem;
    height: 1.25rem;
    border: 2px solid var(--color-border);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: app-spin 700ms linear infinite;
}

.app-spinner--lg { width: 2rem; height: 2rem; border-width: 3px; }

@keyframes app-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .app-spinner { animation-duration: 2s; }
}

/* --- Squelette de chargement ---------------------------------------------- */

.app-skeleton {
    display: block;
    border-radius: var(--radius-sm);
    background: linear-gradient(
        90deg,
        var(--color-surface-sunken) 25%,
        var(--color-border-subtle) 37%,
        var(--color-surface-sunken) 63%);
    background-size: 400% 100%;
    animation: app-skeleton-shimmer 1.4s ease infinite;
}

.app-skeleton--rounded {
    border-radius: var(--radius-pill);
}

@keyframes app-skeleton-shimmer {
    from { background-position: 100% 50%; }
    to { background-position: 0 50%; }
}

/* Une animation continue est une gêne pour qui y est sensible : le squelette reste
   alors un aplat, sans perdre son rôle d'indication d'attente. */
@media (prefers-reduced-motion: reduce) {
    .app-skeleton {
        animation: none;
        background: var(--color-surface-sunken);
    }
}

.app-skeleton-stack {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

.app-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-3xl) var(--spacing-xl);
    text-align: center;
    color: var(--color-text-secondary);
}

.app-empty-state__title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text);
}

.app-empty-state__description {
    margin: 0;
    font-size: var(--font-size-sm);
    max-width: 32rem;
}

/* --- En-tête de page ----------------------------------------------------- */

/*
  L'en-tête est une CARTE, pas une simple zone de titre : elle rassemble le fil
  d'Ariane, l'identité de la page et ses actions, et sert de point d'ancrage visuel
  en haut de chaque écran. C'est ce qui remplace la barre supérieure globale.
*/
.app-page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-lg) var(--spacing-xl);
    padding: var(--spacing-lg) var(--spacing-xl);
    margin-bottom: var(--spacing-lg);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-sm);
}

.app-page-header__main {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-lg);
    min-width: 0;
}

.app-page-header__icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-md);
    background-color: var(--color-space-primary);
    color: var(--color-on-primary);
}

.app-page-header__icon--violet { background-color: var(--color-space-violet); }
.app-page-header__icon--green { background-color: var(--color-space-green); }
.app-page-header__icon--amber { background-color: var(--color-space-amber); }
.app-page-header__icon--rose { background-color: var(--color-space-rose); }

.app-page-header__eyebrow {
    margin: 0 0 var(--spacing-2xs);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--color-muted);
}

.app-page-header__title {
    font-size: var(--font-size-xl);
    font-weight: var(--font-weight-bold);
    letter-spacing: -0.01em;
}

.app-page-header__description {
    margin: var(--spacing-2xs) 0 0;
    max-width: 52rem;
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
}

.app-page-header__actions {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    flex-wrap: wrap;
}

.app-section-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-md);
}

.app-section-header__title {
    font-size: var(--font-size-md);
}

/* --- Boîte de dialogue -------------------------------------------------- */

.app-modal__backdrop {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-lg);
    background-color: var(--color-overlay);
    z-index: 100;
}

.app-modal {
    width: min(34rem, 100%);
    max-height: 85vh;
    overflow: auto;
    background-color: var(--color-surface);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
    padding: var(--spacing-xl);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

/* Variante large : consultation d'une pièce, tableau de lignes. Le dialogue par défaut
   à 34rem écrase les colonnes chiffrées. */
.app-modal--lg {
    width: min(76rem, 100%);
}

.app-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
}

.app-modal__footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-sm);
}

/* Listes cherchables DANS une boîte de dialogue.

   Le panneau d'une liste cherchable est en « position: absolute », ce qui convient dans une page :
   il se pose par-dessus le contenu sans rien déplacer. Dans un dialogue, qui est en
   « overflow: auto » pour tenir en 85vh, ce même panneau est COUPÉ par le bord — on voyait une
   demi-liste posée sur les boutons, et il fallait faire défiler le dialogue pour atteindre le
   reste. Ici, le panneau reprend donc sa place dans le flux : la liste pousse le contenu vers le
   bas, le dialogue grandit, et il ne défile que s'il atteint sa hauteur maximale. */
.app-modal .app-search-select__panel {
    position: static;
    width: 100%;
    margin-top: var(--spacing-2xs);
}

/* Les champs d'un paramétrage s'alignent PAR LE HAUT dans un dialogue.

   La grille des critères aligne ses cellules par le bas — ce qui est juste dans une page, où les
   champs ont tous la même hauteur et où leurs libellés doivent se poser sur une même ligne. Dès
   qu'une liste s'ouvre dans le flux, sa cellule devient très haute, la rangée entière suit, et
   les champs voisins se retrouvent plaqués tout en bas d'un grand vide. L'alignement par le haut
   les laisse en place. */
.app-modal .app-criteria-grid {
    align-items: start;
}

/* La barre d'actions d'un paramétrage ferme le dialogue : son trait va donc AU-DESSUS d'elle.
   Le trait du bas, hérité de la page où ces blocs s'empilent les uns sous les autres, la collait
   aux champs et la faisait lire comme une ligne de plus du formulaire. */
.app-modal .app-defaults-screen {
    border-bottom: 0;
    border-top: 1px solid var(--app-border, #e5e7eb);
    padding-top: var(--spacing-md);
    margin-top: var(--spacing-sm);
}

/* --- Tableau ------------------------------------------------------------ */

.app-table-wrapper {
    overflow-x: auto;
}

.app-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--font-size-sm);
}

.app-table th {
    text-align: left;
    padding: var(--spacing-sm) var(--spacing-md);
    color: var(--color-muted);
    font-weight: var(--font-weight-medium);
    font-size: var(--font-size-xs);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    border-bottom: 1px solid var(--color-border);
    white-space: nowrap;
}

.app-table td {
    padding: var(--spacing-md);
    border-bottom: 1px solid var(--color-border-subtle);
}

.app-table tbody tr:hover {
    background-color: var(--color-surface-muted);
}

/* --- Mise en page utilitaire -------------------------------------------- */

.app-stack {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xl);
}

.app-stack--sm { gap: var(--spacing-sm); }
.app-stack--md { gap: var(--spacing-md); }

.app-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    flex-wrap: wrap;
}

.app-row--between { justify-content: space-between; }

.app-grid {
    display: grid;
    gap: var(--spacing-lg);
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.app-grid--wide {
    grid-template-columns: repeat(auto-fit, minmax(24rem, 1fr));
}

/* --- Liste de liens ------------------------------------------------------- */

.app-link-list {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

.app-link-list a {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-md);
    margin-inline: calc(var(--spacing-md) * -1);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    text-decoration: none;
    font-size: var(--font-size-sm);
}

.app-link-list a:hover {
    background-color: var(--color-surface-sunken);
    color: var(--color-primary);
}

.app-link-list svg {
    flex: 0 0 auto;
    color: var(--color-muted);
}

.app-link-list a:hover svg {
    color: var(--color-primary);
}

/* --- Indicateur ---------------------------------------------------------- */

.app-stat__value {
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-bold);
    line-height: 1.05;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.app-stat__caption {
    font-size: var(--font-size-xs);
    color: var(--color-muted);
}

.app-stat__trend {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2xs);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
}

.app-stat__trend--up { color: var(--color-success); }
.app-stat__trend--down { color: var(--color-danger); }

/* --- Section repliable ---------------------------------------------------- */

.app-collapsible {
    display: block;
}

/*
   La barre de titre porte sa propre surface : repliée, la section n'est plus qu'une
   ligne, et sans fond elle flotterait au milieu de cartes blanches.
   Le corps, lui, n'est pas encarté : les cartes qu'il contient ont déjà leur surface.
*/
.app-collapsible__summary {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-md) var(--spacing-lg);
    cursor: pointer;
    list-style: none;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}

/* Anneau de focus vers l'INTÉRIEUR : la barre occupe toute la largeur du contenu, un
   anneau extérieur déborderait de la colonne. Le repère reste visible au clavier. */
.app-collapsible__summary:focus-visible {
    outline-offset: -2px;
}

.app-collapsible__summary::-webkit-details-marker {
    display: none;
}

.app-collapsible__chevron {
    display: inline-flex;
    align-self: center;
    color: var(--color-muted);
    transition: transform var(--transition-fast);
}

/* Fermée, la flèche pointe vers la droite ; ouverte, vers le bas. */
.app-collapsible:not([open]) > .app-collapsible__summary .app-collapsible__chevron {
    transform: rotate(-90deg);
}

.app-collapsible__title {
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text);
}

.app-collapsible__hint {
    margin-left: auto;
    font-size: var(--font-size-xs);
    color: var(--color-muted);
}

.app-collapsible__summary:hover .app-collapsible__title {
    color: var(--color-primary);
}

.app-collapsible__body {
    padding-top: var(--spacing-lg);
}

/* --- Graphiques ----------------------------------------------------------- */

.app-chart {
    width: 100%;
    min-width: 0;
}

.app-chart-row {
    display: flex;
    align-items: center;
    gap: var(--spacing-xl);
    flex-wrap: wrap;
}

.app-chart-row .app-chart {
    flex: 1 1 14rem;
}

.app-chart-legend {
    flex: 1 1 14rem;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--font-size-sm);
}

.app-chart-legend li {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    align-items: center;
    gap: var(--spacing-sm);
}

.app-chart-legend__label {
    color: var(--color-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-chart-legend__value {
    font-variant-numeric: tabular-nums;
    font-weight: var(--font-weight-medium);
}

.app-chart-legend__share {
    min-width: 3rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--color-muted);
    font-size: var(--font-size-xs);
}

/* --- Barre d'outils d'une liste ------------------------------------------- */

.app-toolbar {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--spacing-md);
    flex-wrap: wrap;
}

.app-toolbar .app-field {
    flex: 1 1 18rem;
    max-width: 26rem;
}

/* --- Jauge segmentée ------------------------------------------------------ */

.app-meter {
    display: flex;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    overflow: hidden;
    background-color: var(--color-surface-sunken);
}

.app-meter__segment {
    height: 100%;
}

.app-meter__segment--completed { background-color: var(--color-success); }
.app-meter__segment--progress { background-color: var(--color-warning); }
.app-meter__segment--blocked { background-color: var(--color-danger); }

.app-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-lg);
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
}

.app-legend__item {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
}

.app-legend__swatch {
    width: 0.625rem;
    height: 0.625rem;
    border-radius: var(--radius-pill);
}

/* --- Liste d'événements --------------------------------------------------- */

.app-timeline {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    margin: 0;
    padding: 0;
    list-style: none;
}

.app-timeline__item {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-md);
    padding-bottom: var(--spacing-md);
    border-bottom: 1px solid var(--color-border-subtle);
}

.app-timeline__item:last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

.app-timeline__body {
    flex: 1 1 auto;
    min-width: 0;
}

.app-timeline__message {
    font-size: var(--font-size-sm);
}

.app-timeline__time {
    font-size: var(--font-size-xs);
    color: var(--color-muted);
}

/* --- Barre latérale ----------------------------------------------------- */

.app-sidebar {
    display: flex;
    flex-direction: column;
    width: var(--sidebar-width);
    height: 100%;
    background-color: var(--color-sidebar-surface);
    color: var(--color-sidebar-text);
    border-right: 1px solid var(--color-sidebar-border);
    transition: width var(--transition-base);
}

.app-sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-lg) var(--spacing-lg) var(--spacing-md);
}

.app-sidebar__logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-md);
    overflow: hidden;
}

.app-sidebar__logo img {
    display: block;
    width: 100%;
    height: 100%;
}

/* Repli lorsque aucun logotype n'est configuré : le sigle sur un aplat de marque. */
.app-sidebar__logo--initials {
    background: linear-gradient(140deg, var(--palette-cyan-400), var(--palette-cyan-700));
    color: var(--color-on-primary);
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-sm);
}

.app-sidebar__brand-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

.app-sidebar__app-name {
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-semibold);
    color: var(--color-sidebar-text-strong);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-sidebar__workspace {
    font-size: var(--font-size-xs);
    color: var(--color-sidebar-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-sidebar__scroll {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: var(--spacing-sm) var(--spacing-md) var(--spacing-lg);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

.app-sidebar__section-label {
    padding: 0 var(--spacing-md);
    margin: 0 0 var(--spacing-sm);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-sidebar-muted);
}

.app-sidebar__footer {
    border-top: 1px solid var(--color-sidebar-border);
    padding: var(--spacing-md);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

/*
  Groupe d'espace : une carte blanche élevée sur le fond de la barre. C'est ce qui
  fait lire chaque module comme une unité autonome plutôt qu'une section d'une
  longue liste.
  <details>/<summary> natifs : pliage au clavier, état exposé aux technologies
  d'assistance, et fonctionnement sans JavaScript ni circuit interactif.
*/
.app-nav-group {
    background-color: var(--color-sidebar-card);
    border: 1px solid var(--color-sidebar-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}

.app-nav-group + .app-nav-group {
    margin-top: var(--spacing-sm);
}

.app-nav-group--active {
    border-color: var(--color-primary-soft);
}

.app-nav-group__summary {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-md);
    cursor: pointer;
    list-style: none;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-sidebar-text-strong);
}

.app-nav-group__summary::-webkit-details-marker {
    display: none;
}

.app-nav-group__avatar {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 1.875rem;
    height: 1.875rem;
    border-radius: var(--radius-sm);
    background-color: var(--color-space-primary);
    color: var(--color-on-primary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
}

.app-nav-group__avatar--violet { background-color: var(--color-space-violet); }
.app-nav-group__avatar--green { background-color: var(--color-space-green); }
.app-nav-group__avatar--amber { background-color: var(--color-space-amber); }
.app-nav-group__avatar--rose { background-color: var(--color-space-rose); }

.app-nav-group__label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-nav-group__chevron {
    flex: 0 0 auto;
    transition: transform var(--transition-fast);
    color: var(--color-sidebar-muted);
}

.app-nav-group[open] > .app-nav-group__summary .app-nav-group__chevron {
    transform: rotate(180deg);
}

.app-nav-group__items {
    padding: 0 var(--spacing-sm) var(--spacing-sm);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.app-nav-item {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-sm);
    color: var(--color-sidebar-text);
    text-decoration: none;
    font-size: var(--font-size-sm);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.app-nav-item:hover {
    background-color: var(--color-sidebar-hover);
    color: var(--color-sidebar-text-strong);
}

.app-nav-item--active {
    background-color: var(--color-sidebar-active-surface);
    color: var(--color-sidebar-active-text);
    font-weight: var(--font-weight-medium);
    box-shadow: inset 2px 0 0 var(--color-sidebar-active-marker);
}

.app-nav-item__icon {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--color-sidebar-muted);
}

.app-nav-item--active .app-nav-item__icon {
    color: var(--color-sidebar-active-text);
}

.app-nav-item__label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-nav-item--child {
    padding-left: var(--spacing-lg);
}

/* --- Pied utilisateur --------------------------------------------------- */

.app-user-menu {
    position: relative;
}

.app-user-menu__trigger {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    width: 100%;
    padding: var(--spacing-sm);
    border: 0;
    border-radius: var(--radius-md);
    background-color: transparent;
    color: inherit;
    font: inherit;
    cursor: pointer;
    text-align: left;
    list-style: none;
}

.app-user-menu__trigger::-webkit-details-marker {
    display: none;
}

.app-user-menu__trigger:hover {
    background-color: var(--color-sidebar-hover);
}

.app-user-menu__avatar {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-pill);
    background: linear-gradient(140deg, var(--palette-cyan-400), var(--palette-cyan-700));
    color: var(--color-on-primary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
}

.app-user-menu__identity {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

.app-user-menu__name {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-sidebar-text-strong);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-user-menu__role {
    font-size: var(--font-size-xs);
    color: var(--color-sidebar-muted);
}

.app-user-menu__panel {
    position: absolute;
    bottom: calc(100% + var(--spacing-sm));
    left: 0;
    right: 0;
    background-color: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--spacing-sm);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    z-index: 20;
}

.app-user-menu__panel a,
.app-user-menu__panel button {
    display: block;
    width: 100%;
    padding: var(--spacing-sm) var(--spacing-md);
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: inherit;
    font: inherit;
    font-size: var(--font-size-sm);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.app-user-menu__panel a:hover,
.app-user-menu__panel button:hover {
    background-color: var(--color-surface-sunken);
}

/* --- Fil d'Ariane -------------------------------------------------------- */

.app-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-sm);
    margin: 0 0 var(--spacing-2xs);
    padding: 0;
    list-style: none;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--color-muted);
}

.app-breadcrumb li + li::before {
    content: "/";
    margin-right: var(--spacing-sm);
    color: var(--color-border);
}

.app-breadcrumb a {
    color: inherit;
    text-decoration: none;
}

.app-breadcrumb a:hover {
    color: var(--color-primary);
}

.app-breadcrumb [aria-current="page"] {
    color: var(--color-text-secondary);
}

/* --- Sélecteur de culture ---------------------------------------------- */

.app-culture-selector {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2xs);
    padding: var(--spacing-2xs);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    background-color: var(--color-surface);
}

.app-culture-selector__option {
    padding: var(--spacing-xs) var(--spacing-md);
    border: 0;
    border-radius: var(--radius-pill);
    background: none;
    color: var(--color-text-secondary);
    font: inherit;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
}

.app-culture-selector__option[aria-current="true"] {
    background-color: var(--color-primary);
    color: var(--color-on-primary);
}

/* --- Mode réduit -------------------------------------------------------- */

.app-shell--collapsed .app-sidebar {
    width: var(--sidebar-width-collapsed);
}

.app-shell--collapsed .app-sidebar__brand-text,
.app-shell--collapsed .app-sidebar__section-label,
.app-shell--collapsed .app-nav-group__label,
.app-shell--collapsed .app-nav-group__chevron,
.app-shell--collapsed .app-nav-item__label,
.app-shell--collapsed .app-user-menu__identity,
.app-shell--collapsed .app-culture-selector {
    display: none;
}

.app-shell--collapsed .app-sidebar__scroll {
    padding-inline: var(--spacing-sm);
}

/* En mode réduit, le logotype et le bouton de repli s'empilent : côte à côte, ils
   imposeraient au conteneur une largeur supérieure à celle du jeton. */
.app-shell--collapsed .app-sidebar__brand {
    flex-direction: column;
    gap: var(--spacing-sm);
    padding-inline: var(--spacing-sm);
}

.app-shell--collapsed .app-nav-item,
.app-shell--collapsed .app-nav-group__summary,
.app-shell--collapsed .app-user-menu__trigger {
    justify-content: center;
    padding-inline: var(--spacing-sm);
}

.app-shell--collapsed .app-nav-item--child {
    padding-left: var(--spacing-sm);
}

/* Infobulle en mode réduit : purement CSS, sans dépendance JavaScript. */
.app-shell--collapsed [data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    left: calc(var(--sidebar-width-collapsed) - var(--spacing-sm));
    z-index: 50;
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-sm);
    background-color: var(--palette-taupe-900);
    color: var(--palette-neutral-0);
    font-size: var(--font-size-xs);
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-fast);
}

.app-shell--collapsed [data-tooltip] {
    position: relative;
}

.app-shell--collapsed [data-tooltip]:hover::after,
.app-shell--collapsed [data-tooltip]:focus-visible::after {
    opacity: 1;
}

/* --- Notifications passagères --------------------------------------------
   En haut à droite, au-dessus de tout, y compris des dialogues. Le conteneur ne capte pas le
   clic : seules les notifications elles-mêmes sont cliquables. */
.app-toasts {
    position: fixed;
    top: var(--spacing-lg);
    right: var(--spacing-lg);
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    width: min(24rem, calc(100vw - 2 * var(--spacing-lg)));
    pointer-events: none;
}

.app-toast {
    position: relative;
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: start;
    gap: var(--spacing-md);
    padding: var(--spacing-md) var(--spacing-lg);
    border: 1px solid var(--color-border);
    border-left: 3px solid var(--color-border);
    border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
    background-color: var(--color-surface);
    box-shadow: 0 1rem 2.5rem rgba(15, 23, 42, .16);
    pointer-events: auto;
    overflow: hidden;
    animation: app-toast-in 220ms cubic-bezier(.21, 1.02, .73, 1);
}

@keyframes app-toast-in {
    from { opacity: 0; transform: translateX(1.5rem); }
    to { opacity: 1; transform: translateX(0); }
}

.app-toast__icon {
    display: grid;
    place-items: center;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 50%;
}

.app-toast__body { min-width: 0; }

.app-toast__body strong {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
}

.app-toast__body span {
    display: block;
    margin-top: .15rem;
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    line-height: 1.45;
}

.app-toast__close {
    display: grid;
    place-items: center;
    width: 1.6rem;
    height: 1.6rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--color-muted);
    cursor: pointer;
}

.app-toast__close:hover { background-color: var(--color-background); color: var(--color-text); }

/* Barre de temps restant, collée au bas de la notification. */
.app-toast__progress {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 100%;
    transform-origin: left;
    animation-name: app-toast-progress;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}

@keyframes app-toast-progress {
    from { transform: scaleX(1); }
    to { transform: scaleX(0); }
}

.app-toast--success { border-left-color: #17b890; }
.app-toast--success .app-toast__icon { background-color: #ddf8ee; color: #07866f; }
.app-toast--success .app-toast__progress { background-color: #17b890; }

.app-toast--error { border-left-color: #dc2626; }
.app-toast--error .app-toast__icon { background-color: #fdeaea; color: #dc2626; }
.app-toast--error .app-toast__progress { background-color: #dc2626; }

.app-toast--warning { border-left-color: #f59e0b; }
.app-toast--warning .app-toast__icon { background-color: #fff4e0; color: #b45309; }
.app-toast--warning .app-toast__progress { background-color: #f59e0b; }

.app-toast--info { border-left-color: var(--color-primary); }
.app-toast--info .app-toast__icon { background-color: #e3f2f6; color: var(--color-primary); }
.app-toast--info .app-toast__progress { background-color: var(--color-primary); }

@media (max-width: 30rem) {
    .app-toasts { top: var(--spacing-sm); right: var(--spacing-sm); left: var(--spacing-sm); width: auto; }
}

/* ── Sélecteur de colonnes ────────────────────────────────────────────────────────────────── */
.app-column-picker {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .25rem;
  max-height: 22rem;
  overflow-y: auto;
}

.app-column-picker__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .5rem .625rem;
  border: 1px solid var(--app-border, #e5e7eb);
  border-radius: var(--app-radius-sm, .5rem);
  background: var(--app-surface, #fff);
}

.app-column-picker__item--locked { opacity: .7; }

.app-column-picker__label {
  display: flex;
  align-items: center;
  gap: .625rem;
  cursor: pointer;
  flex: 1 1 auto;
  min-width: 0;
}

.app-column-picker__item--locked .app-column-picker__label { cursor: default; }

.app-column-picker__label span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-column-picker__actions {
  display: flex;
  gap: .125rem;
  flex: 0 0 auto;
}

/* ── Paramétrage des écrans ───────────────────────────────────────────────────────────────── */
.app-defaults-target {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: .75rem;
  margin-bottom: .75rem;
}

.app-defaults-target__select {
  display: flex;
  flex-direction: column;
  gap: .25rem;
  min-width: 14rem;
}

.app-defaults-target__select > span {
  font-size: .8125rem;
  color: var(--app-text-muted, #6b7280);
}

.app-defaults-screen {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .75rem 0;
  border-bottom: 1px solid var(--app-border, #e5e7eb);
}

.app-defaults-screen:last-child { border-bottom: 0; }

/* ── Interrupteur ─────────────────────────────────────────────────────────────────────────── */
.app-switch-field {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  min-width: 12rem;
}

.app-switch-field__title {
  font-size: .8125rem;
  color: var(--app-text-muted, #6b7280);
}

.app-switch {
  display: inline-flex;
  align-items: center;
  gap: .625rem;
  cursor: pointer;
  user-select: none;
}

.app-switch--disabled { opacity: .55; cursor: not-allowed; }

/* La case native reste présente pour le clavier et les lecteurs d'écran ; seule sa peinture
   est remplacée. La masquer avec display:none la retirerait de la navigation au clavier. */
.app-switch input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.app-switch__track {
  position: relative;
  flex: 0 0 auto;
  width: 2.25rem;
  height: 1.25rem;
  border-radius: 999px;
  background: var(--app-border, #d1d5db);
  transition: background-color .15s ease;
}

.app-switch__track::after {
  content: "";
  position: absolute;
  top: 50%;
  left: .1875rem;
  width: .875rem;
  height: .875rem;
  border-radius: 50%;
  background: #fff;
  transform: translateY(-50%);
  transition: transform .15s ease;
  box-shadow: 0 1px 2px rgb(0 0 0 / .2);
}

.app-switch input:checked + .app-switch__track {
  background: var(--app-accent, #0f766e);
}

.app-switch input:checked + .app-switch__track::after {
  transform: translate(1rem, -50%);
}

.app-switch input:focus-visible + .app-switch__track {
  outline: 2px solid var(--app-accent, #0f766e);
  outline-offset: 2px;
}

.app-switch__label { font-size: .875rem; }


/* ── Écrans d'extrait : le tableau défile dans sa carte, jamais la page ───────────────────────
   Une grille à dix colonnes est plus large que l'écran. Sans largeur maximale sur ses conteneurs,
   elle pousse la carte, qui pousse la page : le navigateur affiche alors une barre horizontale
   générale, et l'en-tête comme le menu défilent avec le tableau. Les conteneurs sont donc bornés,
   et le défilement reste à l'intérieur de la grille — comme sur l'extrait détaillé. */
.statement-shell {
  max-width: 100%;
  min-width: 0;
}

.statement-shell > * {
  max-width: 100%;
  min-width: 0;
}

.statement-movements {
  overflow: hidden;
}

/* ── Défilement horizontal des grilles ────────────────────────────────────────────────────────
   La table rendue par la grille est en « table-layout: fixed » : à dix colonnes, elle est plus
   large que sa carte. Sans conteneur qui défile, elle pousse la carte, puis la page — le
   navigateur affiche alors une barre horizontale générale, et l'en-tête comme le menu latéral
   défilent avec le tableau.

   La règle est posée sur le conteneur de données, pas sur la carte : c'est lui qui doit défiler,
   pour que l'en-tête de page et la pagination restent en place. */
.rz-data-grid,
.rz-datatable {
  max-width: 100%;
}

.rz-data-grid-data,
.rz-datatable-data,
.rz-datatable-scrollable-body {
  overflow-x: auto;
}

/* ── Grille de critères de l'écran de paramétrage ─────────────────────────────────────────────
   Classe PROPRE à ce composant, et non « statement-filter-grid » : celle-ci appartient au module
   Clients, qui la définit déjà pour ses écrans. La redéfinir ici l'écrasait sur des pages qui ne
   le demandaient pas — un composant partagé ne doit pas reprendre le nom de classe d'un module. */
.app-criteria-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem;
  align-items: end;
}

.app-criteria-grid .statement-field,
.app-criteria-field {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  min-width: 0;
}

.app-criteria-grid .statement-field > span,
.app-criteria-field > span {
  font-size: .8125rem;
  color: var(--app-text-muted, #6b7280);
}

/* Champs directs de la grille de critères : « label > span » puis le contrôle. Ces styles sont
   ici et non dans le module, parce que la grille l'est aussi — reprendre la classe du module
   ramènerait son nombre de colonnes fixe, donc le débordement de la page. */
.app-criteria-grid > label {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  min-width: 0;
}

.app-criteria-grid > label > span,
.app-criteria-grid .statement-balance-toggle > span {
  font-size: .8125rem;
  color: var(--app-text-muted, #6b7280);
}

.app-criteria-grid input[type="date"],
.app-criteria-grid select {
  width: 100%;
  min-width: 0;
  padding: .5rem .625rem;
  border: 1px solid var(--app-border, #d1d5db);
  border-radius: var(--app-radius-sm, .5rem);
  background: var(--app-surface, #fff);
  color: inherit;
  font: inherit;
}

.app-criteria-grid .statement-balance-toggle {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  min-width: 0;
}

.app-criteria-grid .statement-switch {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  cursor: pointer;
}

.app-column-picker__sort {
  flex: 0 0 auto;
  max-width: 10rem;
  padding: .25rem .375rem;
  border: 1px solid var(--app-border, #d1d5db);
  border-radius: var(--app-radius-sm, .5rem);
  background: var(--app-surface, #fff);
  color: inherit;
  font: inherit;
  font-size: .8125rem;
}

/* --- Composeur de courriel -------------------------------------------------
   Volontairement proche d'une fenêtre de messagerie : des lignes « À / Objet »
   sans encadrement, séparées par un simple filet. Des champs encadrés auraient
   donné un formulaire administratif là où l'utilisateur attend d'écrire.        */

.app-mail {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.app-mail__ligne {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .5rem .125rem;
  border-bottom: 1px solid var(--app-border, #e5e7eb);
}

.app-mail__etiquette {
  flex: 0 0 auto;
  min-width: 4.5rem;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--app-text-muted, #6b7280);
}

.app-mail__champ {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  padding: .125rem 0;
}

.app-mail__champ:focus {
  outline: none;
}

/* L'objet porte le message : il se lit avant le reste. */
.app-mail__champ--objet {
  font-weight: 600;
}

.app-mail__lien {
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  padding: .125rem .25rem;
  color: var(--app-accent, #4f46e5);
  font: inherit;
  font-size: .8125rem;
  cursor: pointer;
}

.app-mail__lien:hover {
  text-decoration: underline;
}

.app-mail__corps {
  width: 100%;
  min-height: 12rem;
  margin: .75rem 0;
  padding: .5rem .125rem;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  line-height: 1.55;
  resize: vertical;
}

.app-mail__corps:focus {
  outline: none;
}

.app-mail__pieces {
  border-top: 1px solid var(--app-border, #e5e7eb);
  padding-top: .75rem;
}

.app-mail__pieces-tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--app-text-muted, #6b7280);
}

.app-mail__pieces-tete em {
  font-style: normal;
  font-weight: 400;
}

/* Le champ de fichier natif est illisible et impossible à styler : il est masqué
   sous un libellé cliquable, qui reste un vrai <label> pour le clavier. */
.app-mail__joindre {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  padding: .375rem .625rem;
  border: 1px solid var(--app-border, #d1d5db);
  border-radius: var(--app-radius-sm, .5rem);
  background: var(--app-surface, #fff);
  color: inherit;
  font-weight: 500;
  cursor: pointer;
}

.app-mail__joindre:hover {
  border-color: var(--app-accent, #4f46e5);
  color: var(--app-accent, #4f46e5);
}

.app-mail__joindre input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.app-mail__vide {
  margin: .5rem 0 0;
  font-size: .8125rem;
  color: var(--app-text-muted, #6b7280);
}

.app-mail__liste {
  list-style: none;
  margin: .625rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}

.app-mail__piece {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  max-width: 100%;
  padding: .375rem .5rem .375rem .625rem;
  border: 1px solid var(--app-border, #e5e7eb);
  border-radius: var(--app-radius-sm, .5rem);
  background: var(--app-surface-muted, #f9fafb);
  font-size: .8125rem;
}

.app-mail__piece-nom {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 16rem;
}

.app-mail__piece-taille {
  color: var(--app-text-muted, #6b7280);
}

/* --- Comptes d'envoi ------------------------------------------------------- */

.app-mail-comptes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  gap: .75rem;
}

.app-mail-compte {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  padding: .875rem 1rem;
  border: 1px solid var(--app-border, #e5e7eb);
  border-radius: var(--app-radius, .75rem);
  background: var(--app-surface, #fff);
}

.app-mail-compte--defaut {
  border-color: var(--app-accent, #4f46e5);
}

.app-mail-compte__tete {
  display: flex;
  align-items: center;
  gap: .5rem;
}

.app-mail-compte__tete strong {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-mail-compte__ligne {
  font-size: .8125rem;
  color: var(--app-text-muted, #6b7280);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-mail-compte__actions {
  display: flex;
  gap: .375rem;
  margin-top: .375rem;
}

/* Les champs n'ont pas tous une aide sous eux : alignés par le bas, ils partaient en escalier et
   les libellés ne se lisaient plus sur une même ligne. Alignés par le haut, chaque ligne démarre
   au même trait quelle que soit la hauteur de l'aide.

   Colonnes fixes plutôt qu'auto-fit : quatre champs par ligne sur un écran large, deux sur un
   écran étroit. Le remplissage automatique produisait des lignes de largeurs inégales. */
.app-mail-form {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem .875rem;
  align-items: start;
}

@media (max-width: 62rem) {
  .app-mail-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 34rem) {
  .app-mail-form { grid-template-columns: minmax(0, 1fr); }
}

/* Un champ sur toute la largeur : les adresses sont longues. */
.app-mail-form__large { grid-column: 1 / -1; }

/* Le sélecteur de sécurité doit ressembler aux autres champs, pas à un <select> nu posé à côté. */
.app-mail-form .statement-field {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  min-width: 0;
}

.app-mail-form .statement-field > span {
  font-size: .8125rem;
  font-weight: 600;
  color: var(--app-text-muted, #6b7280);
}

.app-mail-form .statement-field select {
  width: 100%;
  padding: .5rem .625rem;
  border: 1px solid var(--app-border, #d1d5db);
  border-radius: var(--app-radius-sm, .5rem);
  background: var(--app-surface, #fff);
  color: inherit;
  font: inherit;
}

/* Les deux interrupteurs terminent le formulaire, sur leur propre ligne. */
.app-mail-form__bascules {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  padding-top: .75rem;
  border-top: 1px solid var(--app-border, #e5e7eb);
}

/* Réglages connus, au-dessus du formulaire d'un compte d'envoi. */
.app-mail-presets {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  margin-bottom: 1rem;
  padding-bottom: .875rem;
  border-bottom: 1px solid var(--app-border, #e5e7eb);
}

.app-mail-presets > span {
  font-size: .8125rem;
  font-weight: 600;
  color: var(--app-text-muted, #6b7280);
  margin-right: .25rem;
}

/* Case « figer », dans le sélecteur de colonnes. Discrète : elle ne concerne que les premières
   colonnes, et ne doit pas concurrencer la case de visibilité. */
.app-column-picker__figee {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  flex: 0 0 auto;
  font-size: .75rem;
  color: var(--app-text-muted, #6b7280);
  cursor: pointer;
  white-space: nowrap;
}

.app-column-picker__figee input {
  margin: 0;
}
