/*
 * UI components (DESIGN §4). One definition per component, one template each in
 * templates/components/. Values come from tokens.css only.
 */
[x-cloak] {
  display: none !important;
}

/* --- Icons (DESIGN §2.5) --- */
.icon {
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon.is-small {
  width: 16px;
  height: 16px;
}

/* --- Buttons (DESIGN §4.1) --- */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-8);
  box-sizing: border-box;
  min-height: var(--hauteur-controle);
  padding: 0 var(--espace-16);
  border: 1px solid transparent;
  border-radius: var(--rayon-champ);
  font: inherit;
  font-weight: 500;
  line-height: var(--interligne-corps);
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--duree-survol) var(--courbe-apparition),
    color var(--duree-survol) var(--courbe-apparition),
    transform var(--duree-survol) var(--courbe-apparition);
}

.button:active:not(:disabled, [aria-disabled="true"]) {
  transform: translateY(1px);
}

.button.is-dense {
  min-height: var(--hauteur-controle-dense);
}

.button-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--texte-inverse);
  font-weight: 600;
  box-shadow: var(--ombre-bouton);
}

.button-primary:hover {
  background: var(--accent-survol);
  border-color: var(--accent-survol);
  color: var(--texte-inverse);
}

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

.button-secondary:hover {
  background: var(--accent-fond);
  color: var(--accent-survol);
}

.button-tertiary {
  background: transparent;
  color: var(--accent);
}

.button-tertiary:hover {
  text-decoration: underline;
}

.button-success {
  background: var(--surface);
  border-color: var(--succes);
  color: var(--succes);
}

.button-success:hover {
  background: var(--succes-fond);
}

.button-warning {
  background: var(--surface);
  border-color: var(--attention);
  color: var(--attention);
}

.button-warning:hover {
  background: var(--attention-fond);
}

.button-danger {
  background: var(--surface);
  border-color: var(--erreur);
  color: var(--erreur);
}

.button-danger:hover {
  background: var(--erreur-fond);
}

.button-destructive {
  background: var(--erreur);
  border-color: var(--erreur);
  color: var(--texte-inverse);
}

.button-destructive:hover {
  background: var(--erreur-survol);
  border-color: var(--erreur-survol);
  color: var(--texte-inverse);
}

.button:active {
  transform: translateY(1px);
}

/* Disabled stays visible, focusable, and explains itself (DESIGN §4.1) */
.button[aria-disabled="true"] {
  background: var(--surface-creuse);
  border-color: var(--trait-champ);
  color: var(--texte-secondaire);
  cursor: not-allowed;
}

.button[aria-disabled="true"]:active {
  transform: none;
}

.button-reason {
  display: inline-block;
  margin-left: var(--espace-8);
  font-size: var(--taille-aide);
  line-height: var(--interligne-aide);
  color: var(--texte-secondaire);
}

/* Loading: the label changes, a spinner appears, a second click does nothing */
.button .button-label-loading,
.button .spinner {
  display: none;
}

.button.htmx-request,
.button.is-loading {
  pointer-events: none;
}

.button.has-loading-label.htmx-request .button-label,
.button.has-loading-label.is-loading .button-label {
  display: none;
}

.button.has-loading-label.htmx-request .button-label-loading,
.button.has-loading-label.is-loading .button-label-loading,
.button.has-loading-label.htmx-request .spinner,
.button.has-loading-label.is-loading .spinner {
  display: inline-block;
}

.spinner {
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}

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

/* Busy overlay (DESIGN §4.18): a veil, a card with a spinner and what is running */
.busy-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 90;
  align-items: center;
  justify-content: center;
  background: var(--voile);
}

.busy-overlay.is-busy,
.busy-overlay.htmx-request {
  display: flex;
}

.busy-card {
  display: flex;
  align-items: center;
  gap: var(--espace-16);
  padding: var(--espace-24) var(--espace-32);
  background: var(--surface);
  border-radius: var(--rayon-panneau);
  box-shadow: var(--ombre-flottante);
  color: var(--texte);
  font-weight: 600;
}

.busy-card p {
  margin: 0;
}

.spinner.is-large {
  width: 32px;
  height: 32px;
  border-width: 3px;
  color: var(--accent);
}

/* htmx indicators (its own inline styles are off because of the CSP) */
.htmx-indicator {
  opacity: 0;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
}

/* --- Form fields (DESIGN §4.2) --- */
.field {
  margin-bottom: var(--espace-16);
}

.field-label {
  display: block;
  font-weight: 600;
}

.field-optional {
  font-weight: 400;
  color: var(--texte-secondaire);
}

.field-help {
  margin: var(--espace-4) 0 0;
  font-size: var(--taille-aide);
  line-height: var(--interligne-aide);
  color: var(--texte-secondaire);
}

.field-help ul {
  margin: 0;
  padding-left: var(--espace-16);
}

.field-control {
  margin-top: var(--espace-4);
}

.field input:not([type="checkbox"], [type="radio"], [type="file"], [type="hidden"]),
.field select,
.field textarea {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--largeur-champ-large);
  min-height: var(--hauteur-controle);
  padding: var(--espace-8) var(--espace-12);
  border: 1px solid var(--trait-champ);
  border-radius: var(--rayon-champ);
  background: var(--surface);
  color: var(--texte);
  font: inherit;
  transition: box-shadow var(--duree-survol) var(--courbe-apparition);
}

.field input:focus:not([type="checkbox"], [type="radio"], [type="file"]),
.field select:focus,
.field textarea:focus {
  border-color: var(--accent);
  box-shadow: var(--halo-focus-champ);
}

/* The list has the chevron of the icon set, not the browser's (DESIGN §4.2) */
.field select {
  appearance: none;
  padding-right: var(--espace-32);
  background: var(--surface) url("../img/select-chevron.svg") no-repeat right var(--espace-12) center / 16px;
}

.field input[type="checkbox"],
.field input[type="radio"] {
  appearance: none;
  flex-shrink: 0; /* a long label in a narrow cell must not squeeze the box */
  box-sizing: border-box;
  width: 24px; /* the minimum target size (DESIGN §10.1, WCAG 2.5.8) */
  height: 24px;
  margin: 0;
  border: 2px solid var(--trait-champ);
  border-radius: var(--rayon-case);
  background: var(--surface);
  cursor: pointer;
  transition: background-color var(--duree-survol) var(--courbe-apparition);
}

.field input[type="radio"] {
  border-radius: 50%;
}

.field input[type="checkbox"]:checked {
  border-color: var(--accent);
  background: var(--accent) url("../img/check-white.svg") no-repeat center / 16px;
}

.field input[type="radio"]:checked {
  border-color: var(--accent);
  background: radial-gradient(circle, var(--accent) 0 40%, var(--surface) 45%);
}

.field input[type="checkbox"]:disabled,
.field input[type="radio"]:disabled {
  border-color: var(--trait);
  background-color: var(--surface-creuse);
  cursor: not-allowed;
}

.field [aria-invalid="true"] {
  border: 2px solid var(--erreur);
}

.field-error-item {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-8);
}

.field-error-item .icon {
  height: var(--interligne-dense);
}

.field-errors {
  margin: var(--espace-4) 0 0;
  padding: 0;
  list-style: none;
}

/* A checkbox is the box and its whole label (DESIGN §4.2) */
.field-check {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-12);
  min-height: var(--hauteur-controle);
  cursor: pointer;
}

.field-check .field-label {
  font-weight: 400;
}

.field-password {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-8);
  max-width: var(--largeur-champ-large);
}

.field-password input {
  flex: 1;
}

.error-summary {
  margin-bottom: var(--espace-16);
}

/* --- Status badges (DESIGN §4.6) --- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-4);
  box-sizing: border-box;
  min-height: 28px;
  padding: 0 var(--espace-12);
  border: 1px solid transparent;
  border-radius: var(--rayon-badge);
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  font-weight: 600;
  white-space: nowrap;
}

.badge-neutral {
  background: var(--neutre-fond);
  color: var(--neutre);
}

.badge-attention {
  background: var(--attention-fond);
  color: var(--attention);
}

.badge-success {
  background: var(--succes-fond);
  color: var(--succes);
}

.badge-error {
  background: var(--erreur-fond);
  color: var(--erreur);
}

.badge-information {
  background: var(--information-fond);
  color: var(--information);
}

.badge.is-outline {
  background: transparent;
  border-color: currentColor;
}

/* --- Data table (DESIGN §4.5) --- */
.table-wrap {
  /* The containing block of the visually hidden texts in the cells: without it they sit outside the
     scrolling box and widen the page (reflow at 200 % zoom, DESIGN §10.2). */
  position: relative;
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  font-variant-numeric: tabular-nums;
}

.data-table caption {
  padding: var(--espace-12) var(--espace-16);
  text-align: left;
  font-weight: 600;
}

.data-table th,
.data-table td {
  height: var(--hauteur-ligne);
  padding: 0 var(--espace-16);
  border-bottom: 1px solid var(--trait);
  text-align: left;
  vertical-align: middle;
}

.data-table.is-dense th,
.data-table.is-dense td {
  height: var(--hauteur-ligne-dense);
}

.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-creuse);
  font-weight: 600;
}

.data-table tbody tr:last-child td,
.data-table tbody tr:last-child th {
  border-bottom: 0;
}

.data-table tbody th {
  font-weight: 400;
}

.data-table .is-numeric {
  text-align: right;
}

.data-table .is-mono {
  font-family: var(--police-mono);
  white-space: nowrap;
}

.sort-link {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-4);
  color: inherit;
  font-weight: inherit;
  text-decoration: none;
}

.sort-link:hover {
  text-decoration: underline;
}

.result-count {
  margin: 0 0 var(--espace-8);
  color: var(--texte-secondaire);
  font-size: var(--taille-dense);
}

/* --- Filter chips (DESIGN §4.5) --- */
.chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8);
  margin: 0 0 var(--espace-16);
  padding: 0;
  list-style: none;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-4);
  min-height: var(--hauteur-controle-dense);
  padding: 0 var(--espace-8) 0 var(--espace-12);
  background: var(--accent-fond);
  border: 1px solid var(--accent);
  border-radius: var(--rayon-badge);
  color: var(--texte);
  font-size: var(--taille-dense);
}

.chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;
  border-radius: 50%;
  color: var(--accent);
}

.chip-remove:hover {
  background: var(--surface);
}

/* --- Banners (DESIGN §4.9) --- */
.banner {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-12);
  margin: var(--espace-16) 0;
  padding: var(--espace-12) var(--espace-16);
  border: 1px solid currentColor;
  border-radius: var(--rayon-panneau);
}

.banner-body {
  flex: 1;
  color: var(--texte);
}

.banner-body p {
  margin: 0;
}

.banner-title {
  font-weight: 600;
}

.banner-action {
  margin-top: var(--espace-4);
}

.banner-information {
  background: var(--information-fond);
  color: var(--information);
}

.banner-attention {
  background: var(--attention-fond);
  color: var(--attention);
}

.banner-error {
  background: var(--erreur-fond);
  color: var(--erreur);
}

.banner-success {
  background: var(--succes-fond);
  color: var(--succes);
}

/* --- Progress of a background task (DESIGN §4.16) --- */
.progress {
  margin: var(--espace-16) 0;
  padding: var(--espace-16);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
  background: var(--surface);
}

.progress-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-12);
}

.progress-title {
  margin: 0;
  font-weight: 600;
}

.progress-detail,
.progress-counter {
  margin: var(--espace-8) 0 0;
  color: var(--texte-secondaire);
}

.progress-counter {
  font-variant-numeric: tabular-nums;
}

/* A native <progress> keeps its role and values for assistive technology; no width animation. */
.progress-bar {
  display: block;
  width: 100%;
  height: var(--espace-12);
  margin-top: var(--espace-12);
  border: 0;
  border-radius: var(--rayon-badge);
  background: var(--surface-creuse);
  color: var(--accent);
  appearance: none;
  overflow: hidden;
}

.progress-bar::-webkit-progress-bar {
  background: var(--surface-creuse);
}

.progress-bar::-webkit-progress-value {
  background: var(--accent);
}

.progress-bar::-moz-progress-bar {
  background: var(--accent);
}

/* --- Ephemeral notifications (DESIGN §4.9) --- */
.notifications {
  position: fixed;
  left: var(--espace-16);
  bottom: var(--espace-16);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: var(--espace-8);
  max-width: 420px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-12);
  padding: var(--espace-12) var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-left-width: 4px;
  border-radius: var(--rayon-panneau);
  box-shadow: var(--ombre-flottante);
  animation: appear var(--duree-ouverture) var(--courbe-apparition);
}

.toast.is-information {
  border-left-color: var(--information);
}

.toast.is-success {
  border-left-color: var(--succes);
}

.toast.is-attention {
  border-left-color: var(--attention);
}

.toast-body {
  flex: 1;
}

.toast-body p {
  margin: 0;
}

.toast-title {
  font-weight: 600;
}

@keyframes appear {
  from {
    opacity: 0;
    transform: translateY(var(--espace-8));
  }
}

/* --- Dialogs and drawers (DESIGN §4.10) --- */
.dialog {
  box-sizing: border-box;
  width: calc(100% - var(--espace-32));
  max-width: var(--largeur-modale);
  padding: 0;
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
  background: var(--surface);
  color: var(--texte);
  box-shadow: var(--ombre-flottante);
}

.dialog::backdrop {
  background: var(--voile);
}

.dialog[open] {
  animation: appear var(--duree-ouverture) var(--courbe-apparition);
}

.dialog-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--espace-16);
  padding: var(--espace-24) var(--espace-24) var(--espace-8);
}

.dialog-body {
  padding: var(--espace-8) var(--espace-24) var(--espace-24);
}

.dialog-footer {
  display: flex;
  justify-content: space-between;
  gap: var(--espace-16);
  padding: var(--espace-16) var(--espace-24);
  border-top: 1px solid var(--trait);
  background: var(--surface-creuse);
}

.dialog-footer .button-group {
  display: flex;
  gap: var(--espace-8);
}

.drawer {
  max-width: var(--largeur-tiroir);
  width: 100%;
  height: 100%;
  max-height: none;
  margin: 0 0 0 auto;
  border-width: 0 0 0 1px;
  border-radius: 0;
}

.drawer[open] {
  animation: slide-in var(--duree-ouverture) var(--courbe-apparition);
}

@keyframes slide-in {
  from {
    opacity: 0;
    transform: translateX(var(--espace-32));
  }
}

/* --- Empty states (DESIGN §7.2) --- */
.empty-state {
  padding: var(--espace-48) var(--espace-24);
  background: var(--surface);
  border: 1px dashed var(--trait-champ);
  border-radius: var(--rayon-panneau);
  text-align: center;
}

.empty-state h2,
.empty-state h3 {
  margin-bottom: var(--espace-8);
}

.empty-state p {
  margin-left: auto;
  margin-right: auto;
  color: var(--texte-secondaire);
}

/* --- Step indicator (DESIGN §4.4): numbered markers joined by a line --- */
.step-item {
  position: relative;
  display: flex;
  align-items: stretch;
}

/* The line between two steps is accent once the step before it is done. */
.step-item + .step-item::before {
  content: "";
  align-self: center;
  width: var(--espace-24);
  height: 2px;
  background: var(--trait);
}

.step-item.is-done + .step-item::before {
  background: var(--accent);
}

.step {
  display: flex;
  align-items: center;
  gap: var(--espace-8);
  box-sizing: border-box;
  min-height: var(--hauteur-controle);
  padding: var(--espace-8) var(--espace-12);
  border-bottom: 3px solid transparent;
  color: var(--texte);
  text-decoration: none;
  transition: background-color var(--duree-survol);
}

a.step:hover {
  background: var(--accent-fond);
}

.step[aria-current] {
  border-bottom-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.step-marker {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 28px;
  height: 28px;
  border: 2px solid var(--trait-champ);
  border-radius: 50%;
  font-size: var(--taille-aide);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.step-item.is-done .step-marker {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--texte-inverse);
}

.step[aria-current] .step-marker,
.step.is-next .step-marker {
  border-color: var(--accent);
  color: var(--accent);
}

.step.is-next .step-marker {
  border-style: dashed;
}

.step-item.is-done .step[aria-current] .step-marker {
  color: var(--texte-inverse);
}

.step-badge,
.step-next {
  padding: 0 var(--espace-8);
  border-radius: var(--rayon-badge);
  background: var(--accent-fond);
  color: var(--accent-survol);
  font-size: var(--taille-aide);
  line-height: var(--interligne-aide);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.step.is-blocked {
  color: var(--texte-secondaire);
  cursor: not-allowed;
}

.step.is-blocked .step-marker {
  border-color: var(--trait);
}

/* The tip says why a step is closed, or what its badge counts. It stays while the pointer or
 * the focus is on the step, and the pointer can go onto it (WCAG 1.4.13). */
.step-tip {
  position: absolute;
  z-index: 20;
  top: 100%;
  left: 0;
  display: none;
  box-sizing: border-box;
  width: max-content;
  max-width: 280px;
  padding: var(--espace-8) var(--espace-12);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-champ);
  box-shadow: var(--ombre-flottante);
  font-size: var(--taille-aide);
  line-height: var(--interligne-aide);
}

.step-item:hover > .step-tip,
.step-item:focus-within > .step-tip {
  display: block;
}

.step-item[data-dismissed] > .step-tip {
  display: none;
}

/* Below the widest layout the « Suivante » label gives way: the dashed marker and the text
 * read by screen readers still say it. */
@media (max-width: 1279px) {
  .step-next {
    display: none;
  }

  .step-item + .step-item::before {
    width: var(--espace-12);
  }
}

/* --- Connection lost and similar global notices --- */
.connection-lost[hidden] {
  display: none;
}

@media (max-width: 1023px) {
  .button,
  .menu-item,
  .step,
  .chip-remove {
    min-height: var(--cible-tactile);
  }

  .chip-remove {
    min-width: var(--cible-tactile);
  }

  /* The steps are a list under the « Étapes » button: no line joins them. */
  .step-item + .step-item::before {
    display: none;
  }

  .step-next {
    display: inline;
  }

  .field input:not([type="checkbox"], [type="radio"], [type="file"], [type="hidden"]),
  .field select {
    min-height: var(--cible-tactile);
  }
}

@media (max-width: 767px) {
  .drawer,
  .dialog {
    width: 100%;
    max-width: none;
  }

  .field input:not([type="checkbox"], [type="radio"], [type="file"], [type="hidden"]),
  .field select,
  .field-password {
    max-width: none;
  }
}

/* --- File drop zone (DESIGN §4.3) ---
 * The real file input covers the zone, invisible: it stays reachable by keyboard and screen
 * reader, and a file dropped on it is chosen by the browser itself. */
.dropzone {
  position: relative;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: var(--largeur-depot);
  margin-top: var(--espace-8);
  padding: var(--espace-32);
  border: 2px dashed var(--trait-champ);
  border-radius: var(--rayon-panneau);
  background: var(--surface);
  text-align: center;
}

.dropzone.is-over {
  border-color: var(--accent);
  background: var(--accent-fond);
}

.dropzone:focus-within {
  outline: var(--focus-largeur) solid var(--accent);
  outline-offset: var(--focus-decalage);
}

.dropzone-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.dropzone-text {
  margin: 0;
}

.dropzone-link {
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
}

.dropzone-chosen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-12);
  max-width: var(--largeur-depot);
  margin-top: var(--espace-8);
}

.dropzone-name {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.dropzone-size {
  color: var(--texte-secondaire);
  font-variant-numeric: tabular-nums;
}

/* --- Facts of an object: label and value pairs --- */
.facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--espace-8) var(--espace-24);
  margin: 0;
}

.facts > div {
  display: contents;
}

.facts dt {
  color: var(--texte-secondaire);
}

.facts dd {
  margin: 0;
  overflow-wrap: anywhere;
}

/* --- Row of actions at the end of a block: the main one comes first (DESIGN §3.2) --- */
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-12);
  margin: var(--espace-16) 0 0;
}

.actions.has-space-below {
  margin-bottom: var(--espace-24);
}

/* The three numbers of an accepted import (DESIGN §9.2). */
.import-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--espace-16);
  margin: var(--espace-16) 0 0;
  padding: 0;
  list-style: none;
}

.import-figure {
  display: flex;
  flex-direction: column;
  gap: var(--espace-4);
  padding: var(--espace-16);
  background: var(--fond-page);
  border-radius: var(--rayon-champ);
}

.import-figure-value {
  font-size: 2rem;
  line-height: 2.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.import-figure-label {
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  color: var(--texte-secondaire);
}

.import-figure.is-attention .import-figure-value {
  color: var(--attention);
}

.import-result .banner {
  margin-top: var(--espace-16);
}

/* --- Pagination (DESIGN §4.5) --- */
.pagination {
  margin-top: var(--espace-24);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-12);
}

.pagination-position {
  font-variant-numeric: tabular-nums;
}

/* --- Links that filter a list (the report's severity) --- */
.filter-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-16);
  margin: 0;
  padding: 0;
  list-style: none;
}

.filter-links a[aria-current] {
  color: var(--texte);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 3px solid var(--accent);
}

/* --- Indicators, gauges and charts of the quality control (DESIGN §4.8) --- */
.kpi-label {
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  color: var(--texte-secondaire);
}

.kpi-value {
  font-size: 2rem;
  line-height: 2.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.kpi-context {
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  color: var(--texte-secondaire);
}

.kpi-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8);
  margin-top: auto;
  padding-top: var(--espace-8);
}

.kpi-variation {
  font-size: var(--taille-dense);
  font-variant-numeric: tabular-nums;
}

.kpi-variation.is-better {
  color: var(--succes);
}

.kpi-variation.is-worse {
  color: var(--erreur);
}

.gauge {
  display: block;
  width: 100%;
  height: var(--espace-8);
  margin: var(--espace-8) 0;
  border-radius: var(--rayon-badge);
}

.gauge-track {
  fill: var(--surface-creuse);
}

.gauge-fill {
  fill: var(--accent);
}

.chart {
  margin-inline: 0;
  margin-bottom: 0;
  padding: var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.chart-title {
  margin-bottom: var(--espace-12);
  font-weight: 600;
}

.chart-actions {
  margin: var(--espace-12) 0 0;
}

/* The text of an isolated tertiary button lines up with the text above it (DESIGN §2.4) */
.chart-actions .button-tertiary,
.actions > .button-tertiary:first-child {
  margin-left: calc(-1 * var(--espace-16));
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-16);
  margin: 0 0 var(--espace-12);
  padding: 0;
  list-style: none;
  font-size: var(--taille-dense);
}

.legend-key {
  display: inline-block;
  width: var(--espace-12);
  height: var(--espace-12);
  margin-right: var(--espace-4);
  border-radius: var(--rayon-champ);
}

.legend-key-1,
.bar-segment-1 {
  background: var(--accent);
  fill: var(--accent);
}

.legend-key-2,
.bar-segment-2 {
  background: var(--attention);
  fill: var(--attention);
}

.legend-key-3,
.bar-segment-3 {
  background: var(--neutre);
  fill: var(--neutre);
}

.bars {
  display: grid;
  gap: var(--espace-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.bar-row {
  display: grid;
  grid-template-columns: minmax(120px, 240px) minmax(80px, 1fr) auto;
  align-items: center;
  gap: var(--espace-12);
  font-size: var(--taille-dense);
}

.bar-label {
  overflow-wrap: anywhere;
}

.bar {
  display: block;
  width: 100%;
  height: var(--espace-16);
}

.bar-value {
  min-width: var(--espace-48);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ring-body {
  display: flex;
  align-items: center;
  gap: var(--espace-24);
}

.ring-svg,
.ring-canvas {
  position: relative;
  flex: none;
  width: 96px;
  height: 96px;
}

.chart-canvas {
  position: relative;
  width: 100%;
}

.ring-track {
  stroke: var(--surface-creuse);
}

.ring-fill {
  stroke: var(--accent);
}

/* The help above a table runs the full width of the page, not the 80ch of a paragraph (DESIGN §9.5). */
.table-help {
  margin: 0;
  max-width: none;
}

.quality-summary {
  margin: 0;
  font-size: var(--taille-titre-section);
  line-height: var(--interligne-titre-section);
  font-weight: 600;
}

/* --- Validation of the changes (DESIGN §4.5, §4.7, §6.3) --- */
.review-progress {
  margin: 0;
  font-size: var(--taille-titre-section);
  line-height: var(--interligne-titre-section);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Progress and status filter in one block (DESIGN §6.3): the bar, then the pills that filter. */
.review-callout {
  display: flex;
  align-items: center;
  gap: var(--espace-16);
  margin-bottom: var(--espace-16);
}

.review-callout .banner-body {
  flex: 1;
}

.review-callout .banner-body p {
  margin: 0;
  font-weight: 500;
}

.review-callout-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8);
}

.review-lost .banner-body p {
  font-weight: 400;
}

/* Filter checkbox beside the selects of the toolbar. */
.check-field {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-8);
  min-height: 44px;
  font-weight: 500;
}

.review-progress-panel {
  margin-bottom: var(--espace-16);
}

.review-meter {
  display: block;
  width: 100%;
  height: 12px;
  margin-bottom: var(--espace-12);
}

.review-meter .meter-validated {
  fill: var(--succes);
}

.review-meter .meter-to-check {
  fill: var(--attention);
}

.review-meter .meter-to-validate {
  fill: var(--accent);
}

.review-meter .meter-rejected {
  fill: var(--trait-champ);
}

.review-meter .meter-failed {
  fill: var(--erreur);
}

.review-meter .meter-sent {
  fill: var(--accent);
}

.status-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.status-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-8);
  min-height: var(--cible-tactile);
  box-sizing: border-box;
  padding: 0 var(--espace-16);
  border: 1px solid var(--trait-champ);
  border-radius: var(--rayon-badge);
  background: var(--surface);
  color: var(--texte);
  font-size: var(--taille-dense);
  font-weight: 500;
  text-decoration: none;
  transition: background-color var(--duree-survol);
}

.status-tab:hover {
  background: var(--surface-creuse);
}

.status-tab[aria-current] {
  border-color: var(--accent);
  background: var(--accent-fond);
  color: var(--accent-survol);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.status-count {
  font-family: var(--police-mono);
  font-weight: 400;
}

.status-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

.dot-validated {
  background: var(--succes);
}

.dot-to-check {
  background: var(--attention);
}

.dot-to-validate {
  background: var(--accent);
}

.dot-rejected {
  background: var(--trait-champ);
}

.dot-failed {
  background: var(--erreur);
}

.dot-sent {
  background: var(--accent);
}

/* A case to check carries a bar of attention on its left, besides its badge (DESIGN §9.3). */
.review-list tr.is-to-check > :first-child {
  box-shadow: inset 4px 0 0 var(--attention);
}

/* One panel for the filters and the search: the search sits under the selectors, not in a panel of its own. */
.review-toolbar .search-form {
  margin-top: var(--espace-16);
  padding-top: var(--espace-16);
  border-top: 1px solid var(--trait);
}

/* Fields side by side in a panel: a grid aligned on the bottom, never a lone 480 px column (DESIGN §4.2) */
.filter-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  align-items: end;
  gap: var(--espace-16) var(--espace-24);
}

.filter-form .field,
.search-form .field {
  min-width: 0;
  margin-bottom: 0;
}

.filter-form .field input,
.filter-form .field select,
.search-form .field input {
  max-width: none;
}

.filter-form .filter-row {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  align-items: end;
  gap: var(--espace-16) var(--espace-24);
}

.filter-form .actions,
.filter-form fieldset.field {
  grid-column: 1 / -1;
  margin: 0;
}

fieldset.field {
  min-width: 0;
  padding: 0;
  border: 0;
}

fieldset.field > legend {
  padding: 0;
}

.checkbox-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8);
}

/* Options of a group are chips: the whole chip is the target (DESIGN §4.2) */
.checkbox-row .field-check {
  align-items: center;
  padding: 0 var(--espace-16) 0 var(--espace-12);
  border: 1px solid var(--trait-champ);
  border-radius: var(--rayon-badge);
  background: var(--surface);
  transition: background-color var(--duree-survol) var(--courbe-apparition);
}

.checkbox-row .field-check:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-fond);
}

/* Dropdown with several choices (DESIGN §4.2): a button that opens a scrollable list of checkboxes */
.multi-select {
  position: relative;
}

.multi-select-button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-8);
  box-sizing: border-box;
  width: 100%;
  min-height: var(--hauteur-controle);
  padding: var(--espace-8) var(--espace-12);
  border: 1px solid var(--trait-champ);
  border-radius: var(--rayon-champ);
  background: var(--surface);
  color: var(--texte);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.multi-select-button:focus-visible {
  border-color: var(--accent);
  box-shadow: var(--halo-focus-champ);
}

.multi-select-panel {
  position: absolute;
  z-index: 10;
  left: 0;
  right: 0;
  top: 100%;
  min-width: 240px;
  max-height: 320px;
  overflow-y: auto;
  margin-top: var(--espace-4);
  padding: var(--espace-8);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
  box-shadow: var(--ombre-flottante);
}

.multi-select-panel[hidden] {
  display: none;
}

.multi-select-panel .field-check[hidden] {
  display: none;
}

.multi-select-search {
  margin-bottom: var(--espace-8);
}

.multi-select-panel .field-check {
  align-items: center;
  min-height: var(--hauteur-controle);
  padding: 0 var(--espace-8);
}

.search-form {
  display: grid;
  grid-template-columns: minmax(0, 480px) auto auto;
  align-items: end;
  justify-content: start;
  gap: var(--espace-16);
}

/* Fixed to the bottom of the screen; the send screen shows it only with a selection (DESIGN §9.4). */
.selection-bar {
  position: fixed;
  inset: auto 0 0;
  z-index: 2;
  background: var(--texte);
  color: var(--texte-inverse);
  box-shadow: var(--ombre-flottante);
  animation: appear var(--duree-ouverture) var(--courbe-apparition);
}

.selection-bar-inner {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--espace-16);
  box-sizing: border-box;
  max-width: var(--largeur-contenu);
  margin-inline: auto;
  padding: var(--espace-12) var(--marge-laterale);
}

.selection-bar-inner .selection-summary {
  margin-right: auto;
}

.selection-bar .button-tertiary {
  color: var(--texte-inverse);
}

.selection-count {
  margin: 0 auto 0 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.selection-summary {
  margin: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* The count of the list, the state of the selection and the PDF link on one line. */
.send-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-16);
  margin-block: var(--espace-16) var(--espace-12);
}

.send-toolbar .result-count {
  margin: 0;
  margin-right: auto;
}

.row-badges {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--espace-4);
}

.row-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--espace-4);
  padding-block: var(--espace-8);
}

/* Buttons inside a form stay as wide as the links beside them. */
.row-actions .button {
  width: 100%;
}

/* On the send screen one action is put forward, the others quiet, side by side at the end of the row. */
.send-list .row-actions,
.directory-list .row-actions,
.batch-list .row-actions {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  padding-block: 0;
}

.send-list .row-actions .button,
.directory-list .row-actions .button,
.batch-list .row-actions .button {
  width: auto;
}

/* The PDF list stacks its actions in the order of the work, with the small spacing above and below so
   that no button touches the border of its row (DESIGN §9.3 bis). */
.pdf-list .row-actions {
  align-items: flex-start;
  padding-block: var(--espace-8);
}

.pdf-list .row-actions .button {
  width: auto;
}

.undo-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-12);
  padding: var(--espace-8) var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.undo-bar p {
  margin: 0;
  font-weight: 600;
}

.name-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--espace-16);
  margin: var(--espace-16) 0;
}

.name-compare h3 {
  margin: 0 0 var(--espace-4);
  font-size: var(--taille-dense);
  color: var(--texte-secondaire);
}

.owner-name {
  margin: 0;
  font-size: var(--taille-corps);
  overflow-wrap: anywhere;
}

.diff {
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: 3px;
  text-underline-offset: 3px;
}

.drawer-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-12);
  margin-top: var(--espace-24);
}

kbd {
  margin-left: var(--espace-4);
  padding: 0 var(--espace-4);
  border: 1px solid var(--trait-champ);
  border-radius: var(--rayon-champ);
  font-family: var(--police-mono);
  font-size: var(--taille-aide);
}

/* --- PDF per structure and the ordered list of PDF fields (DESIGN §4.13, §9.4) --- */
.field-order {
  display: grid;
  gap: var(--espace-8);
  margin: var(--espace-16) 0;
  padding: 0;
  list-style: none;
}

.field-order-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-12);
  padding: var(--espace-8) var(--espace-12);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-champ);
}

/* --- Tabs of one form (DESIGN §4.17) --- */
.tabs-group {
  display: grid;
  gap: var(--espace-16);
}

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8);
  padding: var(--espace-4);
  background: var(--surface-creuse);
  border-radius: var(--rayon-badge);
  width: fit-content;
  max-width: 100%;
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-8);
  min-height: var(--hauteur-controle-dense);
  padding: var(--espace-8) var(--espace-16);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--rayon-badge);
  color: var(--texte-secondaire);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.tab:hover {
  color: var(--texte);
}

.tab[aria-selected="true"] {
  background: var(--surface);
  border-color: var(--trait);
  color: var(--accent);
}

/* A panel the script hides stays hidden whatever its other display rules say. */
.tab-panel[hidden] {
  display: none;
}

/* Move up / move down sit side by side, unlike the stacked actions of a table row. */
.field-order-actions {
  display: inline-flex;
  gap: var(--espace-8);
}

/* --- Send screen: segmented counters, full-width list, detail drawer (DESIGN §9.4) --- */
.counters {
  display: flex;
  gap: var(--espace-4);
  width: max-content;
  max-width: 100%;
  margin: 0;
  padding: var(--espace-4);
  overflow-x: auto;
  list-style: none;
  background: var(--surface-creuse);
  border-radius: var(--rayon-panneau);
}

.counter {
  display: flex;
  align-items: baseline;
  gap: var(--espace-8);
  padding: var(--espace-8) var(--espace-16);
  border-radius: var(--rayon-champ);
  color: var(--texte-secondaire);
  text-decoration: none;
  white-space: nowrap;
}

.counter.is-current {
  background: var(--surface);
  box-shadow: var(--ombre-bouton);
  color: var(--texte);
}

.counter-value {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--texte);
}

.counter-label {
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
}

.send-list {
  min-width: 0;
  /* Room for the fixed selection bar, so that it never hides the last row. */
  padding-bottom: calc(var(--espace-64) + var(--espace-32));
}

/* Seven columns do not fit the narrowest supported width: the cells give back 8 px on each side. */
@media (max-width: 1279px) {
  .send-list .data-table th,
  .send-list .data-table td {
    padding-inline: var(--espace-8);
  }
}

.send-list .data-table .field-help {
  display: block;
}

/* The reason of a disabled box wraps in a readable measure instead of stretching the name column. */
.send-list .data-table tbody th .field-help {
  max-width: 32ch;
}

.panel-title {
  margin: 0;
  font-size: var(--taille-titre-section);
  line-height: var(--interligne-titre-section);
  overflow-wrap: anywhere;
}

.panel-section-title {
  margin: 0 0 var(--espace-8);
  font-size: var(--taille-corps);
  line-height: var(--interligne-corps);
}

/* --- Text of the emails: a preformatted block that keeps the lines of the message --- */
.email-text {
  margin: 0;
  font-family: var(--police-texte);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* The server version of a chart gives way once Chart.js has drawn it (DESIGN §4.8) */
[data-chart-fallback][hidden],
.chart-canvas[hidden],
.ring-canvas[hidden] {
  display: none;
}

/* --- Module tile of the home page (DESIGN §4.19) --- */
.module-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--espace-24);
  margin: 0;
  padding: 0;
  list-style: none;
}

.module-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--espace-8);
  height: 100%;
  box-sizing: border-box;
  padding: var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
  color: var(--texte);
  text-decoration: none;
}

.module-tile:hover {
  border-color: var(--accent);
}

.module-tile-logo {
  width: var(--taille-logo-tuile);
  height: var(--taille-logo-tuile);
  margin-bottom: var(--espace-8);
}

.module-tile-name {
  font-size: 18px;
  font-weight: 600;
}

.module-tile-summary {
  color: var(--texte-secondaire);
}

@media (max-width: 1023px) {
  .module-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 767px) {
  .module-grid {
    grid-template-columns: 1fr;
  }
}

/* The decision buttons stay in view whatever the width of the table: the last column sticks to the
   right edge of the scrolling box (DESIGN §6.3). */
.review-list th:last-child,
.review-list td:last-child {
  position: sticky;
  right: 0;
  background: var(--surface);
  border-left: 1px solid var(--trait);
}


/* --- Campaign page: the facts of the active import, then the path in four cards (DESIGN §9.1) --- */
.facts-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8) var(--espace-24);
  padding: var(--espace-12) var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
}

.facts-bar dl {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8) var(--espace-24);
  margin: 0;
}

.facts-bar dl > div {
  display: flex;
  align-items: center;
  gap: var(--espace-4);
}

.facts-bar dt {
  color: var(--texte-secondaire);
}

.facts-bar dd {
  margin: 0;
  font-weight: 500;
}

.facts-bar-actions {
  display: flex;
  gap: var(--espace-8);
  margin-left: auto;
}

.route {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--espace-16);
  margin: 0;
  padding: 0;
  list-style: none;
}

.route-step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--espace-12);
  padding: var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.route-step::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--espace-16);
  right: var(--espace-16);
  height: 4px;
  border-radius: 0 0 4px 4px;
  background: var(--trait);
}

.route-step.is-done::before {
  background: var(--succes);
}

.route-step.is-current {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

.route-step.is-current::before {
  background: var(--accent);
}

.route-head {
  display: flex;
  align-items: center;
  gap: var(--espace-8);
  margin-top: var(--espace-4);
}

.route-head h3 {
  margin: 0;
  font-size: var(--taille-corps);
  font-weight: 600;
}

.route-state {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-4);
  margin-left: auto;
  font-size: var(--taille-aide);
  font-weight: 500;
  color: var(--texte-secondaire);
}

.route-step.is-done .route-state {
  color: var(--succes);
}

.route-step.is-current .route-state {
  color: var(--accent);
}

.route-headline {
  margin: 0;
  font-size: 1.75rem;
  line-height: 2rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.route-headline small {
  display: block;
  margin-top: var(--espace-4);
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  font-weight: 400;
  color: var(--texte-secondaire);
}

.route-step .review-meter {
  margin-bottom: 0;
}

.route-alert {
  display: flex;
  align-items: center;
  gap: var(--espace-8);
  margin: 0;
  padding: var(--espace-8) var(--espace-12);
  font-size: var(--taille-dense);
  color: var(--attention);
  background: var(--attention-fond);
  border-radius: var(--rayon-champ);
}

.route-counters {
  display: grid;
  gap: var(--espace-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--taille-dense);
}

.route-counters li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-8);
}

.route-counters .status-dot {
  display: inline-block;
  margin-right: var(--espace-8);
}

.route-count {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.route-step > .button {
  margin-top: auto;
  justify-content: center;
}

/* French typography: a no-break space, then the colon, after each label of the bar. */
.facts-bar dt::after {
  content: "\00a0:";
}

.route-step.is-done {
  border-color: var(--succes);
}

/* The cancel bar stays in view whatever row was decided: it floats at the bottom right, above the selection bar. */
#undo-area .undo-bar {
  position: fixed;
  right: var(--espace-24);
  bottom: var(--espace-24);
  z-index: 3;
  box-shadow: var(--ombre-flottante);
}

/* --- Campaign list: the campaign under way put forward, the earlier ones in a compact list (DESIGN §9.2) --- */
.campaign-current {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-16) var(--espace-32);
  padding: var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
  border-radius: var(--rayon-panneau);
}

.campaign-current h2 {
  margin: var(--espace-4) 0 0;
  font-size: 2rem;
  line-height: 2.5rem;
  font-weight: 600;
}

.campaign-eyebrow {
  margin: 0;
  font-size: var(--taille-aide);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
}

.campaign-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8) var(--espace-32);
  margin: 0 auto 0 0;
  font-size: var(--taille-dense);
}

.campaign-facts dt {
  color: var(--texte-secondaire);
}

.campaign-facts dd {
  margin: 0;
  font-weight: 500;
}

.campaign-earlier {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
  overflow: hidden;
}

.campaign-earlier li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8) var(--espace-24);
  padding: var(--espace-12) var(--espace-16);
  border-top: 1px solid var(--trait);
}

.campaign-earlier li:first-child {
  border-top: 0;
}

.campaign-name {
  min-width: 9rem;
  font-weight: 600;
}

.campaign-meta {
  margin-right: auto;
  font-size: var(--taille-dense);
  color: var(--texte-secondaire);
}

.campaign-meta b {
  font-weight: 500;
  color: var(--texte);
}

.campaign-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8) var(--espace-16);
}

/* --- Quality control: the verdict, what to watch, then one row per indicator (DESIGN §4.8, §9.5) --- */
.quality-verdict {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-16) var(--espace-24);
  padding: var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--succes);
  border-radius: var(--rayon-panneau);
}

.quality-verdict.is-watch {
  border-color: var(--attention);
}

.quality-verdict.is-critical {
  border-color: var(--erreur);
}

.quality-verdict-mark {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--succes-fond);
  color: var(--succes);
}

.quality-verdict.is-watch .quality-verdict-mark {
  background: var(--attention-fond);
  color: var(--attention);
}

.quality-verdict.is-critical .quality-verdict-mark {
  background: var(--erreur-fond);
  color: var(--erreur);
}

.quality-verdict h2 {
  flex: 1;
  margin: 0;
  font-size: 1.5rem;
  line-height: 2rem;
}

.indicators {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
  overflow: hidden;
}

.indicator {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8) var(--espace-16);
  padding: var(--espace-12) var(--espace-16);
  border-top: 1px solid var(--trait);
}

.indicator:first-child {
  border-top: 0;
}

.indicator-label small {
  display: block;
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  color: var(--texte-secondaire);
}

.quality-section > h2 {
  margin-bottom: var(--espace-16);
}

.quality-anchors {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.quality-anchors a {
  display: inline-flex;
  align-items: center;
  min-height: var(--hauteur-controle);
  padding: 0 var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-badge);
  color: var(--texte);
  font-size: var(--taille-dense);
  text-decoration: none;
}

.quality-anchors a:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.indicator {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(5rem, auto) minmax(8rem, auto);
  gap: var(--espace-8) var(--espace-24);
}

.indicator p {
  margin: 0;
}

.indicator-value {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.indicator-meter {
  margin: 0;
}

.indicator-meta .kpi-meta {
  margin: 0;
  padding: 0;
}

@media (max-width: 720px) {
  .indicator {
    grid-template-columns: 1fr auto;
  }

  .indicator-meter {
    grid-column: 1 / -1;
  }
}

/* Cards of the quality control: a figure, what it counts, its state in words, its action (DESIGN §4.8). */
.quality-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--espace-16);
  margin: 0;
  padding: 0;
  list-style: none;
}

.quality-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--espace-8);
  padding: var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.quality-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--espace-16);
  right: var(--espace-16);
  height: 4px;
  border-radius: 0 0 4px 4px;
  background: var(--succes);
}

.quality-card.is-watch {
  border-color: var(--attention);
}

.quality-card.is-watch::before {
  background: var(--attention);
}

.quality-card.is-critical {
  border-color: var(--erreur);
}

.quality-card.is-critical::before {
  background: var(--erreur);
}

.quality-card.is-info::before {
  background: var(--trait);
}

.quality-card p {
  margin: 0;
}

.quality-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-8);
  margin-top: var(--espace-4);
}

.quality-card-label {
  font-size: var(--taille-dense);
  line-height: var(--interligne-dense);
  color: var(--texte-secondaire);
}

.quality-card-value {
  font-size: 2.25rem;
  line-height: 2.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.quality-card.is-watch .quality-card-value {
  color: var(--attention);
}

.quality-card.is-critical .quality-card-value {
  color: var(--erreur);
}

.quality-card .gauge {
  margin: 0;
}

.quality-card-link {
  margin-top: auto;
  padding-top: var(--espace-8);
}

/* Status block of the PDF and send screens: where things stand and the useful action, then rows that carry a bar when they are to do (DESIGN §9.3 bis, §9.4). */
.status-block {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-16) var(--espace-32);
  margin-bottom: var(--espace-24);
  padding: var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
  border-radius: var(--rayon-panneau);
}

.status-block-body {
  flex: 1;
  min-width: 16rem;
}

.status-block-figure {
  margin: 0 0 var(--espace-12);
  font-size: 2rem;
  line-height: 2.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.status-block-figure small {
  margin-left: var(--espace-8);
  font-size: var(--taille-corps);
  font-weight: 400;
  color: var(--texte-secondaire);
}

.status-block .review-meter {
  margin-bottom: var(--espace-8);
}

.status-block-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-4) var(--espace-24);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--taille-dense);
}

.status-block-legend .status-dot {
  display: inline-block;
  margin-right: var(--espace-8);
}

.pdf-list tr.is-todo > :first-child,
.send-list tr.is-todo > :first-child,
.commune-list tr.is-todo > :first-child,
.directory-list tr.is-todo > :first-child,
.batch-list tr.is-todo > :first-child {
  box-shadow: inset 4px 0 0 var(--attention);
}

.pdf-list tr.is-failed > :first-child,
.send-list tr.is-failed > :first-child,
.batch-list tr.is-failed > :first-child,
.event-list tr.is-failed > :first-child {
  box-shadow: inset 4px 0 0 var(--erreur);
}

.status-block .status-block-side {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--espace-8);
}

.status-block-note {
  margin: 0;
  font-size: var(--taille-dense);
  color: var(--texte-secondaire);
}

.send-list .status-block {
  margin-top: var(--espace-24);
}

.send-list .counters {
  margin-bottom: var(--espace-8);
}

/* Structure sheet: who the PDF go to comes first, then the sections one under the other (DESIGN §9.9). */
.sheet-identity {
  padding: var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.sheet-identity-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--espace-16);
}

.sheet-identity h2 {
  margin: 0;
  font-size: 1.5rem;
  line-height: 2rem;
  overflow-wrap: anywhere;
}

.sheet-identity-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8) var(--espace-16);
  margin: var(--espace-4) 0 0;
  color: var(--texte-secondaire);
}

.sheet-recipient {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8) var(--espace-16);
  margin-top: var(--espace-16);
  padding: var(--espace-12) var(--espace-16);
  background: var(--surface-creuse);
  border-radius: var(--rayon-champ);
}

.sheet-recipient.is-missing {
  background: var(--attention-fond);
}

.sheet-recipient strong {
  overflow-wrap: anywhere;
}

.sheet-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--espace-16) var(--espace-24);
  margin: var(--espace-24) 0 0;
  padding-top: var(--espace-16);
  border-top: 1px solid var(--trait);
}

.sheet-facts dt {
  font-size: var(--taille-dense);
  color: var(--texte-secondaire);
}

.sheet-facts dd {
  margin: var(--espace-4) 0 0;
}

.sheet-section {
  margin-top: var(--espace-16);
}

.sheet-section > h2 {
  margin: 0 0 var(--espace-12);
  font-size: var(--taille-titre-section);
  line-height: var(--interligne-titre-section);
}

.sheet-changes {
  display: flex;
  flex-direction: column;
  gap: var(--espace-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.sheet-changes li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-8) var(--espace-16);
  padding: var(--espace-12) var(--espace-16);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.sheet-changes p {
  margin: 0;
}

/* The border of the status block of a batch says its verdict, which the sentence says in words too. */
.status-block.is-success {
  border-color: var(--succes);
  box-shadow: 0 0 0 1px var(--succes);
}

.status-block.is-attention {
  border-color: var(--attention);
  box-shadow: 0 0 0 1px var(--attention);
}

.status-block.is-error {
  border-color: var(--erreur);
  box-shadow: 0 0 0 1px var(--erreur);
}

.status-block-verdict {
  margin: 0 0 var(--espace-12);
  color: var(--texte-secondaire);
}

.status-block-verdict b {
  color: var(--texte);
}

.commune-list .field-help {
  display: block;
}

/* The typing of a town hall's email sits on one line, the erase and its confirmation under it. */
.commune-list td .actions {
  margin-top: var(--espace-8);
}

/* Structure list: the name comes first and the filters sit beside it on one line (DESIGN §9.9). */
.structure-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--espace-16);
  padding: var(--espace-16) var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.structure-tools .field {
  min-width: 11rem;
  margin-bottom: 0;
}

.structure-tools .structure-tools-search {
  flex: 1;
  min-width: 16rem;
}

.structure-tools .field input,
.structure-tools .field select {
  max-width: none;
}

/* The action keeps its label on one line, and the cells give back 8 px per side below 1280 px so that the name column keeps its width. */
.directory-list .row-actions .button {
  white-space: nowrap;
}

@media (max-width: 1279px) {
  .directory-list .data-table th,
  .directory-list .data-table td {
    padding-inline: var(--espace-8);
  }
}

.directory-list .field-help {
  display: block;
}

/* The filters of the journals sit on one line above the table (DESIGN §4.14). */
.journal-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--espace-16);
  padding: var(--espace-16) var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.journal-tools .field {
  flex: 1;
  min-width: 10.5rem;
  margin-bottom: 0;
}

.journal-tools .field input,
.journal-tools .field select {
  max-width: none;
}

.journal-tools-actions {
  display: flex;
  gap: var(--espace-8);
}

.event-list .field-help {
  display: block;
}

/* --- PDF fields: version bar, columns and letter side by side, one save bar (DESIGN §4.13) --- */
.version-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-12);
  padding: var(--espace-16) var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-panneau);
}

.version-bar p {
  margin: 0;
}

.setting-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: var(--espace-24);
  align-items: start;
}

@media (max-width: 900px) {
  .setting-cols {
    grid-template-columns: 1fr;
  }
}

.save-bar {
  position: sticky;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-16);
  padding: var(--espace-16) var(--espace-24);
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--rayon-panneau);
  box-shadow: var(--ombre-flottante);
}

.save-bar p {
  margin: 0;
}

.save-bar-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-12);
}

/* The email as it will read: a subject line over the body (DESIGN §4.13 bis). */
.mail-card {
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-champ);
}

.mail-card-subject {
  margin: 0;
  padding: var(--espace-12) var(--espace-16);
  background: var(--surface-creuse);
}

.mail-card .email-text {
  margin: 0;
  padding: var(--espace-16);
}

/* Printing a page (DESIGN §9.10): the content only, on white, with no navigation or button.
   The closure page is printed to keep a dated record; « Enregistrer en PDF » of the browser
   replaces any file kept by the server. */
@media print {
  .site-header,
  .site-nav,
  .skip-link,
  .breadcrumb,
  .facts-bar-actions,
  .messages,
  .toast-region,
  dialog,
  .button {
    display: none;
  }

  body {
    background: none;
  }

  .table-wrap {
    overflow: visible;
  }

  .data-table {
    width: 100%;
  }

  .closure-page section {
    break-inside: avoid;
  }
}
