/* ============================================================
   ADMINISTRATION SONAWAVE
   ============================================================ */

/* `color-scheme` est héritée, donc la déclarer ici suffit à teindre tout le
   panneau : la liste déroulante native d'un `<select>`, les flèches d'un
   champ numérique, le sélecteur de date et les barres de défilement, que la
   feuille de style ne peut pas atteindre autrement. Elle n'est pas posée sur
   `:root` : les cases à cocher et les boutons radio du formulaire public
   gardent leur apparence native, et la déclaration globale changerait leur
   rendu sur une page qui n'a rien demandé. */
.admin-section {
  color-scheme: dark;
  padding-top: 140px;
  padding-bottom: 80px;
  min-height: 100vh;
}

/* En-tête tableau de bord */
.admin-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 24px;
  margin-bottom: 32px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--color-border);
}

.admin-header h1 {
  font-size: 2.2rem;
  margin: 8px 0 0;
}

.admin-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.admin-actions .btn {
  padding: 10px 18px;
  font-size: 0.85rem;
}

/* Tableau

   Le conteneur est focalisable parce qu'il défile. Les tests d'accessibilité
   du composant Table de l'US Web Design System relèvent qu'un tableau
   défilant « does not scroll with left and right arrow keystrokes in JAWS and
   NVDA », donc sans point d'entrée au clavier les colonnes hors écran ne
   s'atteignent qu'à la souris, ce qui manque WCAG 2.1.1.
   https://designsystem.digital.gov/components/table/accessibility-tests/ */
/* La même surface porte le tableau et les cartes de formulaire du catalogue :
   une seule règle, pour qu'un panneau ne dérive pas de l'autre. */
.admin-table-wrap,
.admin-card {
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-bg-card);
}

.admin-table-wrap {
  overflow-x: auto;
}

/* Un formulaire est borné, une donnée s'étale : la carte s'arrête avant la
   largeur du conteneur pour qu'une ligne de saisie reste lisible, là où les
   tableaux qui la suivent prennent tout. */
.admin-card {
  max-width: 880px;
  padding: 28px 32px;
  margin: 0 0 24px;
}

.admin-card h3 {
  margin: 0 0 24px;
}

/* Trois champs sur la ligne du dépôt, deux sur celle du style : la grille en
   deux colonnes fixes de `style.css` rejetait le troisième sur une seconde
   ligne à mi-largeur, d'où des champs de deux tailles dans un même bloc. */
.admin-card .form-row {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

/* Le champ de description tient en deux lignes, `rows` le dit : la hauteur
   minimale de 160 px écrite pour les formulaires publics en faisait une boîte
   quatre fois trop haute. */
.admin-card .form-group textarea {
  min-height: 72px;
}

.admin-table-wrap:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

.admin-table thead {
  background: rgba(0, 0, 0, 0.25);
}

.admin-table th {
  padding: 14px 16px;
  text-align: left;
  font-weight: 500;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}

/* Le motif Sortable Table de WAI-ARIA APG : le libellé d'une colonne triable
   est enveloppé dans un bouton, et `aria-sort` ne vit que sur la colonne
   effectivement triée. L'indicateur est tiré de cet attribut plutôt que
   d'une classe posée en parallèle, pour que l'image et l'état ne puissent
   pas diverger.
   https://www.w3.org/WAI/ARIA/apg/patterns/table/examples/sortable-table/ */
.admin-table th .sort-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}

.admin-table th .sort-button:hover {
  color: var(--color-text);
}

.admin-table th .sort-button::after {
  content: "⇅";
  opacity: 0.35;
  font-size: 0.9em;
}

.admin-table th[aria-sort="ascending"] .sort-button::after {
  content: "▲";
  opacity: 1;
  color: var(--color-accent);
}

.admin-table th[aria-sort="descending"] .sort-button::after {
  content: "▼";
  opacity: 1;
  color: var(--color-accent);
}

.admin-table th[aria-sort] .sort-button {
  color: var(--color-text);
}

.admin-table td {
  padding: 14px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  vertical-align: middle;
}

.admin-table tbody tr {
  transition: background var(--t-fast);
}

.admin-table tbody tr:hover {
  background: rgba(78, 195, 217, 0.04);
}

.admin-table .muted {
  color: var(--color-text-muted);
  font-size: 0.85rem;
}

.admin-table .mono {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.82rem;
  color: var(--color-accent);
}

.admin-table a {
  color: var(--color-accent);
  text-decoration: none;
}

.admin-table a:hover {
  text-decoration: underline;
}

.empty-row {
  text-align: center;
  padding: 60px 20px !important;
  color: var(--color-text-muted);
  font-style: italic;
}

/* Badges */
.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 10px;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.badge-ok {
  background: rgba(94, 224, 168, 0.15);
  color: #5ee0a8;
  border: 1px solid rgba(94, 224, 168, 0.3);
}

.badge-ko {
  background: rgba(255, 130, 130, 0.12);
  color: #ff9090;
  border: 1px solid rgba(255, 130, 130, 0.3);
}

.badge-np {
  background: rgba(255, 255, 255, 0.05);
  color: var(--color-text-dim);
  border: 1px solid var(--color-border);
}

/* La liste d'attente est le seul statut qui appelle une décision : ni acquis
   comme « sélectionnée », ni clos comme « refusée » ou « retirée ». */
.badge-wait {
  background: rgba(240, 190, 110, 0.12);
  color: #f0be6e;
  border: 1px solid rgba(240, 190, 110, 0.3);
}

/* Bouton lien (dans le tableau) */
.link-btn {
  background: none;
  border: none;
  color: var(--color-accent);
  cursor: pointer;
  font-size: 0.85rem;
  padding: 0;
  font-family: inherit;
}

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

/* Un contrôle éteint doit se voir éteint. Sans cette règle il garde la
   couleur d'accent et le curseur de la main, donc il se donne pour cliquable
   et le clic ne produit rien : la protection du catalogue existerait sans
   qu'aucun opérateur ne puisse la constater. La phrase qui dit pourquoi reste
   écrite à côté du bouton, parce qu'un lecteur d'écran n'annonce pas un
   contrôle désactivé. WCAG 2.2 dispense un contrôle désactivé du contraste
   minimum, c'est justement ce qui rend l'atténuation lisible comme un état. */
.link-btn:disabled {
  color: var(--color-text-dim);
  cursor: not-allowed;
}

.link-btn:disabled:hover {
  text-decoration: none;
}

/* Fiche

   Un `<dialog>` ouvert par `showModal()`, et non un `<div>` masqué : le
   navigateur y met le focus, rend le reste de la page inerte, ferme sur
   Échap et rend le focus à ce qui l'avait. Ce sont exactement les quatre
   comportements qu'il faudrait écrire à la main, et la fiche porte désormais
   les seuls contrôles qui changent le statut d'une personne, donc les
   improviser n'est plus une option.
   https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog

   Le remplissage vit sur le contenu et non sur le dialogue, pour qu'un clic
   sur le dialogue lui-même ne puisse venir que de l'arrière-plan. */
.admin-modal {
  /* Ce que la feuille du navigateur pose déjà sur un `dialog`, et que le
     reset `*, *::before, *::after { margin: 0 }` de `style.css` lui reprend :
     sans cette ligne le dialogue se colle en haut à gauche de l'écran au lieu
     d'être centré dans son arrière-plan. */
  margin: auto;
  padding: 0;
  max-width: 700px;
  width: calc(100% - 40px);
  max-height: 86vh;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  color: var(--color-text);
  overflow-y: auto;
}

.admin-modal::backdrop {
  background: rgba(6, 12, 31, 0.85);
  backdrop-filter: blur(8px);
}

.admin-modal-content {
  position: relative;
  padding: 40px 44px;
}

.admin-modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  background: none;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  width: 32px;
  height: 32px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 1.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.admin-modal-close:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* An h2, not the h3 it looks like: it follows the dashboard's h1 and an h3
   there skipped a rank. The weight is restated because the base h2 rule sets
   300 where h3 sets 500, and the dialog title is meant to read as the heavier
   of the two. */
.admin-modal-content h2 {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 500;
  margin: 0 0 24px;
}

.detail-list {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 14px 20px;
  margin: 0;
}

.detail-list dt {
  font-size: 0.82rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.detail-list dd {
  margin: 0;
  color: var(--color-text);
  font-size: 0.95rem;
  word-break: break-word;
}

.detail-list dd.mono {
  font-family: ui-monospace, monospace;
  font-size: 0.88rem;
  color: var(--color-accent);
}

.detail-list dd.motivation {
  white-space: pre-wrap;
  background: rgba(0, 0, 0, 0.2);
  padding: 12px 16px;
  border-left: 2px solid var(--color-accent);
  border-radius: 0 4px 4px 0;
  font-style: italic;
  line-height: 1.6;
}

/* Les actes de la fiche, sous les champs qu'ils modifient */
.fiche-actes {
  margin-top: 32px;
  padding-top: 28px;
  border-top: 1px solid var(--color-border);
}

/* Un h3, et non le h4 qu'il paraît : il suit le h2 du dialogue, et sauter un
   rang casserait la structure que WCAG 1.3.1 demande de refléter. */
.fiche-actes h3 {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 500;
  margin: 0 0 20px;
}

.fiche-actes .form-group:last-of-type {
  margin-bottom: 20px;
}

/* Catalogue musical */

/* Le titre qui ouvre la liste suit deux cartes, donc il porte lui-même la
   respiration : le reset de `style.css` met toute marge haute à zéro, et sans
   cette ligne il se colle au bouton du formulaire précédent. */
.catalogue-title {
  margin: 40px 0 8px;
}

#catalogue-list {
  margin-top: 24px;
}

/* `padding: 0` est ce que la couche de cascade rend possible : chaque bloc est
   une `<section>`, et `style.css` en fait une section de page d'atterrissage à
   140 px de remplissage vertical. La déclaration hors couche l'emporte sans
   avoir à surenchérir en spécificité. */
.catalogue-style {
  padding: 0;
  margin: 0 0 32px;
}

.catalogue-style h4 {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 1.05rem;
  color: var(--color-text);
}

/* Le code est l'identifiant que lisent les machines, le libellé celui que lit
   l'opérateur : la fonte à chasse fixe est ce qui les distingue au premier
   coup d'œil, comme dans les colonnes de la table des candidatures. */
.catalogue-code {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.82rem;
  font-weight: 400;
  color: var(--color-accent);
}

.catalogue-empty {
  margin: 0;
  color: var(--color-text-muted);
  font-style: italic;
  font-size: 0.9rem;
}

/* Les trois actes s'empilent, et la phrase de refus passe dessous : c'est elle
   qui explique un bouton éteint, donc elle ne doit jamais être coupée ni
   repoussée hors de la cellule. */
.catalogue-actions {
  min-width: 220px;
}

/* Le remplissage vertical et l'écart ne sont pas décoratifs. Empilés sans eux,
   deux libellés de 17 px séparés de 6 px auraient leurs centres à 23 px l'un de
   l'autre, sous le seuil de l'exception « Spacing » de WCAG 2.2 SC 2.5.8, que
   la disposition en ligne satisfaisait déjà. Ici 25 px de hauteur et 8 px
   d'écart donnent 33 px de centre à centre.
   https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html */
.catalogue-acts {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.catalogue-acts .link-btn {
  padding: 4px 0;
}

/* Le seul acte irréversible de l'écran ne se présente pas comme les deux
   autres. La couleur ne le porte pas seule : le libellé le dit, et la
   confirmation le redit en nommant le morceau. */
.link-btn-danger {
  color: var(--color-error-text);
}

.catalogue-actions .form-hint {
  display: block;
  margin: 6px 0 0;
}

/* Une aide posée sur la surface d'une carte ou d'un tableau, plus claire que
   le fond de page, ne tient plus le contraste : mesuré à 4,25 pour 1 en
   `--color-text-dim`, sous les 4,5 que WCAG 1.4.3 demande à 12,5 px. Le
   jeton immédiatement au-dessus suffit, et la taille garde la hiérarchie que
   la couleur portait.
   https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html */
.admin-card .form-hint,
.catalogue-actions .form-hint {
  color: var(--color-text-muted);
}

/* Responsive */
@media (max-width: 600px) {
  .admin-modal-content {
    padding: 28px 24px;
  }
  .detail-list {
    grid-template-columns: 1fr;
    gap: 4px 0;
  }
  .detail-list dt {
    margin-top: 12px;
  }
}
