/* Panneaux latéraux : le garage à gauche, les résultats à droite.

   Cette feuille tient cinq choses : l'ossature commune des deux panneaux,
   les cartes de voiture et la zone d'import du garage, le tableau comparatif
   et les remarques des résultats, et les deux fenêtres du garage — l'édition
   d'une fiche et le choix d'une voiture —, qui ne peuvent vivre qu'ici
   puisqu'elles lui appartiennent.

   Deux contraintes gouvernent toutes les dimensions d'ici. Le panneau descend
   à 260 px de large sur un écran de 1180 px (voir layout.css) : rien ne doit y
   déborder, et aucune largeur fixe ne doit l'empêcher de rétrécir. Sous 920 px
   le même panneau devient un tiroir plein écran : les règles qui suivent sont
   donc écrites en fractions et en minimums, jamais en pixels de colonne.

   Aucune couleur n'est écrite ici. Les cartes empruntent la couleur de série de
   leur emplacement par la variable --slot-color, que le garage renseigne depuis
   la palette de tokens.css : c'est ce qui garantit qu'une voiture bleue dans le
   tableau est bleue à l'écran. */

/* ================================================================== */
/* Ossature d'un panneau                                               */
/* ================================================================== */

.panel {
  min-width: 0;                /* sans quoi le contenu impose sa largeur */
  color: var(--ink-1);
}

.panel-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 34px;
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line-1);
  background: var(--bg-2);
}
.panel-head h2 { flex: 1; min-width: 0; }

.panel-body {
  display: grid;
  align-content: start;
  gap: var(--sp-2);
  padding: var(--sp-2);
  min-width: 0;
}

.panel-foot {
  padding: var(--sp-2);
  border-top: 1px solid var(--line-1);
  background: var(--bg-2);
}

/* Panneau flottant au-dessus de la scène : il se détache par son ombre, pas
   par une couleur plus claire, pour ne pas voiler l'image. */
.panel-floating {
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-2);
  background: var(--bg-2);
  box-shadow: var(--shadow-2);
}

.panel-empty {
  margin: 0;
  padding: var(--sp-4) var(--sp-3);
  color: var(--ink-2);
  text-align: center;
}

/* ================================================================== */
/* Carte d'une voiture                                                 */
/* ================================================================== */

.car-card {
  /* Repli si le garage n'a pas encore attribué sa couleur de série. */
  --slot-color: var(--line-2);

  display: grid;
  /* Une colonne bornée à la carte, et non la colonne implicite « auto » :
     celle-ci prend la largeur minimale de son contenu le plus large, si bien
     qu'une rangée qui ne se replie pas élargissait toute la carte et faisait
     déborder la liste des finitions et les chiffres. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-2);
  min-width: 0;
  padding: var(--sp-2);
  border: 1px solid var(--line-2);
  /* Le liseré de couleur est à gauche : c'est le bord que l'œil suit quand on
     compare deux cartes empilées. */
  border-left: 3px solid var(--slot-color);
  border-radius: var(--radius-2);
  background: var(--bg-2);
}

/* Dépôt d'un modèle directement sur une carte. */
.car-card[data-state='over'] {
  border-color: var(--accent);
  box-shadow: var(--glow-accent);
}

.car-card-head {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--sp-1);
}

.car-mark {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--slot-color);
}

.car-remove { padding: 0 var(--sp-1); color: var(--ink-3); }
.car-remove:hover:not(:disabled) { color: var(--bad); background: transparent; }

.car-sub {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-xs);
  /* Variante et année peuvent être longues : la ligne se replie plutôt que de
     pousser la carte hors du panneau. */
  overflow-wrap: anywhere;
}

/* ---- Nom, logo, changement de voiture ---- */

.car-logo { display: inline-flex; color: var(--ink-1); --make-logo-size: 20px; }

/* Le nom passe sur deux lignes plutôt que d'être coupé : à 260 px de panneau,
   le bouton « Changer » ne laisse qu'une centaine de pixels à « Porsche
   Taycan ». Au-delà de deux lignes, le nom entier reste au survol. */
.car-name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  min-width: 0;
  margin: 0;
  color: var(--ink-0);
  font: 600 var(--fs-md)/1.25 var(--font-ui);
  letter-spacing: 0;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.car-change { color: var(--ink-1); }

/* ---- Rappel des chiffres ---- */

.car-figures {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-1) var(--sp-2);
}

.car-figure { display: grid; gap: 0; min-width: 0; }
.car-figure-label {
  color: var(--ink-3);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.car-figure-value {
  color: var(--ink-0);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}

/* Marque d'une valeur estimée. Discrète mais présente : elle dit que le chrono
   repose en partie sur une hypothèse. */
.car-est,
.spec-est {
  color: var(--warn);
  font-weight: 700;
  cursor: help;
}

/* ---- Peinture ---- */

.car-paint {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--sp-2);
  align-items: end;
}
.car-paint-row { display: flex; align-items: center; gap: var(--sp-1); }
.car-color-reset { color: var(--ink-3); }

/* ---- Modèle 3D ---- */

.car-model {
  display: grid;
  /* Les boutons prennent chacun une colonne à la suite ; celui du retour à
     la silhouette, masqué sans modèle, n'en occupe alors aucune. */
  grid-template-columns: auto minmax(0, 1fr);
  grid-auto-flow: column;
  grid-auto-columns: auto;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2);
  border: 1px dashed var(--line-2);
  border-radius: var(--radius-1);
  background: var(--bg-1);
}
.car-model-glyph { width: 28px; height: 18px; color: var(--slot-color); }
.car-model-name {
  min-width: 0;
  color: var(--ink-2);
  font-size: var(--fs-xs);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.car-model-clear { color: var(--ink-3); }

/* Le champ de fichier est masqué par .sr-only, qui le positionne : le bouton
   doit être son repère, et porter l'anneau de focus, le champ restant
   atteignable au clavier. */
.car-model-import { position: relative; cursor: pointer; white-space: nowrap; }
.car-model-import:focus-within { outline: 2px solid var(--line-focus); outline-offset: 2px; }

/* ---- Actions ---- */

/* La rangée se replie : une fiche de la base large y porte un bouton de
   provenance de plus, et le badge des champs estimés passe alors à la ligne
   plutôt que d'être coupé. */
.car-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); }

.car-badge {
  padding: 1px var(--sp-2);
  border: 1px solid var(--warn);
  border-radius: var(--radius-pill);
  color: var(--warn);
  font-size: var(--fs-xs);
  white-space: nowrap;
  cursor: help;
}

/* ================================================================== */
/* Import de modèles 3D                                                */
/* ================================================================== */

.glb-import { display: grid; gap: var(--sp-1); margin-top: var(--sp-2); }

.glb-progress {
  width: 100%;
  height: 4px;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--bg-3);
  accent-color: var(--accent);
}
/* Les deux moteurs ne partagent pas le même pseudo-élément de barre. */
.glb-progress::-webkit-progress-bar { background: var(--bg-3); border-radius: var(--radius-pill); }
.glb-progress::-webkit-progress-value { background: var(--accent); border-radius: var(--radius-pill); }
.glb-progress::-moz-progress-bar { background: var(--accent); border-radius: var(--radius-pill); }

.glb-note {
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-xs);
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.glb-note[data-kind='ok'] { color: var(--ok); }
.glb-note[data-kind='warn'] { color: var(--warn); }
.glb-note[data-kind='error'] { color: var(--bad); }

/* ================================================================== */
/* Résultats : tableau comparatif                                      */
/* ================================================================== */

/* Les sélecteurs portent sur la structure plutôt que sur des classes : le
   tableau est construit par ui/compare.js, et une feuille de style qui
   dépendrait de ses noms de classe casserait au premier renommage. Les crochets
   nommés (.is-best, [data-rank], .measured, .delta, .unit) sont des
   suppléments : ils embellissent s'ils existent, et leur absence ne laisse pas
   un tableau illisible. */

#results-table table,
.compare-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

/* Les colonnes d'une voiture n'ont qu'un demi-intervalle de chaque côté : leurs
   chiffres sont alignés à droite, et l'espace entre deux colonnes reste celui
   d'un intervalle entier. */
#results-table th,
#results-table td {
  padding: var(--sp-1);
  border-bottom: 1px solid var(--line-1);
  text-align: right;
  vertical-align: baseline;
}

/* Première colonne : le nom de la grandeur mesurée. Elle reste visible quand
   le tableau défile, sur un écran trop étroit pour lui. Le libellé passe à la
   ligne entre ses mots, et se coupe avec un trait d'union quand la langue de
   la page le permet ; un mot plus long que la colonne l'élargit plutôt que
   d'être coupé n'importe où. */
#results-table th:first-child,
#results-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  padding-left: var(--sp-2);
  background: var(--bg-1);
  color: var(--ink-2);
  text-align: left;
  font-weight: 400;
  overflow-wrap: break-word;
  hyphens: auto;
}

/* Partage de la largeur : la colonne des libellés d'abord, le reste à parts
   égales entre les voitures, pour que l'œil compare des colonnes de même
   largeur. Ce sont des largeurs souhaitées : un contenu insécable plus large
   l'emporte, et le cadre défile alors plutôt que de couper. */
#results-table .cmp[data-columns='1'] thead th:first-child { width: 50%; }
#results-table .cmp[data-columns='1'] thead th[data-car] { width: 50%; }
#results-table .cmp[data-columns='2'] thead th:first-child { width: 36%; }
#results-table .cmp[data-columns='2'] thead th[data-car] { width: 32%; }
#results-table .cmp[data-columns='3'] thead th:first-child { width: 31%; }
#results-table .cmp[data-columns='3'] thead th[data-car] { width: 23%; }
#results-table .cmp[data-columns='4'] thead th:first-child { width: 26%; }
#results-table .cmp[data-columns='4'] thead th[data-car] { width: 18.5%; }

/* L'en-tête n'est pas collant : le cadre du tableau peut défiler
   horizontalement, et un en-tête collant dans un conteneur qui défile sur
   l'autre axe ne tiendrait pas sa promesse. Une épreuve compte au plus une
   dizaine de lignes, qui tiennent dans la hauteur du panneau. Les noms des
   voitures n'ont pas tous le même nombre de lignes : ils s'alignent en bas,
   sur le filet de couleur. */
#results-table thead th {
  background: var(--bg-2);
  color: var(--ink-0);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
  vertical-align: bottom;
}

#results-table tbody td {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  color: var(--ink-0);
  white-space: nowrap;
}

/* Une colonne par voiture, repérée par la couleur de son emplacement : c'est
   le seul lien visuel entre un chiffre et une voiture à l'écran. */
#results-table [data-car='1'] { --slot-color: var(--car-1); }
#results-table [data-car='2'] { --slot-color: var(--car-2); }
#results-table [data-car='3'] { --slot-color: var(--car-3); }
#results-table [data-car='4'] { --slot-color: var(--car-4); }
#results-table thead [data-car] { border-bottom: 2px solid var(--slot-color); }

/* La meilleure valeur d'une ligne. Le sens de lecture — plus haut ou plus bas
   est meilleur — est décidé par la simulation, pas par la feuille de style. */
#results-table td.is-best,
#results-table td[data-rank='1'] {
  color: var(--ok);
  font-weight: 700;
}

/* Valeur relevée, à côté de la valeur simulée : plus petite, parce qu'elle
   juge le modèle sans faire partie de la comparaison. */
#results-table .measured,
#results-table .delta {
  display: block;
  color: var(--ink-3);
  font-size: var(--fs-xs);
  font-weight: 400;
}

#results-table .unit { color: var(--ink-3); font-size: var(--fs-xs); white-space: nowrap; }

/* Où se coupent les textes d'une colonne de voiture : nom, précisions,
   relevé, mention à la place d'un écart. Entre leurs mots, et avec un trait
   d'union quand la langue de la page le permet. Au-delà de 1180 px d'écran,
   le panneau est taillé pour loger le tableau entier (layout.css) : un mot
   plus long que sa colonne s'y coupe n'importe où, en dernier recours, plutôt
   que de pousser la dernière voiture hors du cadre. En deçà, le mot reste
   entier et le cadre défile. */
#results-table .cmp-car-name,
#results-table .cmp-car-sub,
#results-table .measured,
#results-table .cmp-delta-note {
  overflow-wrap: break-word;
  hyphens: auto;
}
@media (min-width: 1181px) {
  #results-table .cmp-car-name,
  #results-table .cmp-car-sub,
  #results-table .measured,
  #results-table .cmp-delta-note { overflow-wrap: anywhere; }
}

#results-table tbody tr:hover td { background: var(--bg-2); }
#results-table tbody tr:hover td:first-child { background: var(--bg-3); }

/* Au-delà de 1180 px d'écran, le tableau tient dans le panneau jusqu'à quatre
   voitures, dans toutes les langues : le panneau s'élargit au nombre de
   colonnes (layout.css), et seuls les chiffres sont insécables. En deçà, le
   panneau se resserre et un tableau trop large défile dans son propre cadre,
   dont la barre se tient juste sous lui, plutôt que d'élargir la page ou
   d'être coupé. Le conteneur garde son propre défilement en dernier recours,
   et sa largeur minimale nulle empêche la grille du panneau de s'élargir à la
   mesure du tableau. */
#results-table { min-width: 0; overflow-x: auto; }
#results-table .cmp-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border-radius: var(--radius-1);
}
/* Le contour de focus se dessine à l'intérieur du cadre : le conteneur, qui
   défile lui aussi, couperait un contour posé à l'extérieur. */
#results-table .cmp-scroll:focus-visible { outline-offset: -2px; }

/* ================================================================== */
/* Résultats : remarques du solveur                                    */
/* ================================================================== */

#results-notes ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--sp-2);
}

#results-notes li {
  display: grid;
  gap: 2px;
  padding: var(--sp-2);
  border: 1px solid var(--line-1);
  border-left: 3px solid var(--slot-color, var(--line-2));
  border-radius: var(--radius-1);
  background: var(--bg-2);
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}

#results-notes li[data-car='1'] { --slot-color: var(--car-1); }
#results-notes li[data-car='2'] { --slot-color: var(--car-2); }
#results-notes li[data-car='3'] { --slot-color: var(--car-3); }
#results-notes li[data-car='4'] { --slot-color: var(--car-4); }

#results-notes .note-car,
#results-notes strong {
  color: var(--ink-0);
  font-size: var(--fs-xs);
  font-weight: 600;
}
#results-notes p { margin: 0; color: var(--ink-1); }
#results-notes .muted { color: var(--ink-2); }

/* ================================================================== */
/* Fenêtre d'édition d'une fiche                                       */
/* ================================================================== */

.spec-editor { display: grid; gap: var(--sp-4); }

.spec-editor-head {
  display: grid;
  gap: var(--sp-2);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--line-1);
}
.spec-editor-id { margin: 0; overflow-wrap: anywhere; }

.spec-editor-count {
  padding: 1px var(--sp-2);
  border: 1px solid var(--warn);
  border-radius: var(--radius-pill);
  color: var(--warn);
  font-size: var(--fs-xs);
  cursor: help;
}

/* Un groupe de champs est un vrai `fieldset` : c'est ce qui permet à un lecteur
   d'écran d'annoncer « masses et cotes » avant les neuf champs qui suivent. */
.spec-group {
  margin: 0;
  padding: 0;
  border: none;
}
.spec-group legend {
  padding: 0 0 var(--sp-2);
  color: var(--ink-2);
  font-size: var(--fs-md);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* Colonnes de texte plutôt que grille : les aides n'ont pas la même longueur,
   et une grille alignait chaque rangée sur sa plus longue, laissant des trous
   sous les champs courts. Ici chaque champ suit le précédent. */
.spec-grid {
  columns: 220px 4;
  column-gap: var(--sp-4);
}
.spec-grid > * { break-inside: avoid; margin-bottom: var(--sp-3); }

.spec-field { display: grid; gap: var(--sp-1); min-width: 0; align-content: start; }
.spec-field label { display: flex; align-items: baseline; gap: var(--sp-1); }
.spec-label-text { color: var(--ink-1); }
.spec-unit { color: var(--ink-3); font-size: var(--fs-xs); }

.spec-input-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-1);
  align-items: center;
}

.spec-reset { padding: 0 var(--sp-2); color: var(--ink-3); }
.spec-reset:disabled { opacity: 0.25; }

.spec-hint {
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-xs);
  line-height: 1.35;
}

/* Un champ dont la valeur ne vient plus du catalogue : repéré, sans être
   présenté comme une faute. */
.spec-field[data-modified='true'] input,
.spec-field[data-modified='true'] select { border-color: var(--accent-dim); }

.spec-field[data-state='invalid'] input { border-color: var(--bad); }
.spec-field[data-state='invalid'] .spec-hint { color: var(--bad); }

/* ================================================================== */
/* Base large                                                          */
/* ================================================================== */

/* Origine d'une fiche de la base large, sur la carte du garage. Même ton que la
   marque « estimé » : c'est une information de confiance, pas une décoration. */
.car-source {
  margin: 0;
  color: var(--warn);
  cursor: help;
}

.car-provenance { color: var(--ink-2); }

/* La fiche de provenance seule, ouverte depuis la carte : elle prend la
   largeur que la fenêtre modale lui laisse. */
.wide { display: grid; gap: var(--sp-3); min-width: min(600px, 84vw); }
.wide-credits { margin: 0; }
.wide-credits a { color: var(--ink-1); }

.wide-status { margin: 0; min-height: 1.4em; font-size: var(--fs-sm); }
.wide-status[data-kind='error'] { color: var(--bad); }

.wide-row-marks { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); }
.wide-row-regs,
.wide-row-period { font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }

/* Pastilles : jeu d'origine, catégorie et sa confiance, provenance d'un champ.
   La confiance est la seule à changer de couleur, parce qu'elle est la seule à
   porter un jugement ; la famille de source ne fait que nommer. */
.wide-tag {
  display: inline-block;
  padding: 0 var(--sp-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  font-size: var(--fs-xs);
  line-height: 1.6;
  white-space: nowrap;
  cursor: help;
}
.wide-tag[data-family='aee'] { color: var(--info); border-color: var(--info); }
.wide-tag[data-family='ademe'] { color: var(--ok); border-color: var(--ok); }
.wide-tag[data-family='regle'],
.wide-tag[data-family='jeu'] { color: var(--ink-3); border-style: dashed; }
.wide-tag[data-confidence='haute'] { color: var(--ok); border-color: var(--ok); }
.wide-tag[data-confidence='moyenne'] { color: var(--warn); border-color: var(--warn); }
.wide-tag[data-confidence='basse'] { color: var(--bad); border-color: var(--bad); }
/* Une fiche du catalogue livré, dans le formulaire de choix : l'accent de
   l'application, parce que c'est la source à préférer. */
.wide-tag[data-family='catalogue'] { color: var(--accent); border-color: var(--accent-dim); }

/* La fiche. */
.wide-detail { display: grid; gap: var(--sp-3); }
.wide-detail-head { display: grid; gap: var(--sp-1); }
.wide-detail-name { margin: 0; color: var(--ink-0); font-size: var(--fs-lg); }
.wide-detail-sub { margin: 0; font-size: var(--fs-sm); }
.wide-credit { margin: 0; }
.wide-credit a { color: var(--ink-1); }

.wide-caveats h5,
.wide-fields-section h5 {
  margin: 0 0 var(--sp-1);
  color: var(--ink-0);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.wide-caveats ul { margin: 0; padding-left: var(--sp-4); display: grid; gap: var(--sp-1); }
.wide-caveats li { font-size: var(--fs-sm); color: var(--ink-1); }
.wide-caveats li[data-kind='warn'] { color: var(--warn); }
.wide-fields-section p { margin: 0 0 var(--sp-2); }

.wide-fields {
  display: grid;
  grid-template-columns: minmax(120px, auto) 1fr;
  gap: var(--sp-1) var(--sp-3);
  margin: 0;
}
.wide-fields dt { color: var(--ink-2); font-size: var(--fs-sm); }
.wide-fields dd { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); margin: 0; }
.wide-field-value {
  color: var(--ink-0);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
}
.wide-estimates { margin: 0; color: var(--warn); }
.wide-detail-actions { margin-top: var(--sp-1); }

/* ================================================================== */
/* Choix d'une voiture                                                 */
/* ================================================================== */

/* Le formulaire occupe une grande fenêtre de hauteur fixe : la recherche et
   les filtres restent en haut, seuls les résultats défilent. La fenêtre
   modale de base.css est faite pour un contenu qui défile en entier ; elle est
   reprise ici, et seulement quand elle porte ce formulaire. */
#modal:has(.finder) {
  width: min(1040px, 96vw);
  height: min(900px, 92vh);
  max-height: 92vh;
}
#modal:has(.finder) .modal-inner { height: 100%; max-height: none; }
#modal:has(.finder) .modal-body {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: var(--sp-3) var(--sp-4);
  overflow: hidden;
}

.finder-host,
.finder,
.finder-main {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--sp-2);
  min-height: 0;
}

.finder-context,
.finder-notice { margin: 0; font-size: var(--fs-sm); line-height: 1.4; }
.finder-notice {
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--warn);
  border-radius: var(--radius-1);
  color: var(--warn);
}

.finder-search input { min-height: 36px; font-size: var(--fs-lg); }

.finder-filters {
  border: 1px solid var(--line-1);
  border-radius: var(--radius-1);
  background: var(--bg-1);
}
.finder-filters-summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 32px;
  padding: 0 var(--sp-3);
  color: var(--ink-1);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.finder-filters-count { color: var(--accent); font-size: var(--fs-xs); }
.finder-filter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  align-items: end;
  gap: var(--sp-2);
  padding: 0 var(--sp-3) var(--sp-3);
}
.finder-reset { justify-self: start; }

/* Le total de la liste : la première chose qu'on lit. Il pâlit pendant
   qu'une nouvelle recherche attend sa réponse, sans changer de texte. */
.finder-status {
  margin: 0;
  min-height: 1.4em;
  color: var(--ink-0);
  font-size: var(--fs-lg);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  transition: opacity 0.15s;
}
.finder-status[data-busy='true'] { opacity: 0.55; }
.finder-status[data-kind='warn'] { color: var(--warn); }
.finder-status[data-kind='error'] { color: var(--bad); }

.finder-results {
  display: grid;
  align-content: start;
  gap: var(--sp-2);
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* L'anneau de focus d'une ligne ne doit pas être coupé par le bord. */
  padding: 2px;
}

.finder-head { display: grid; gap: var(--sp-1); min-width: 0; }
.finder-help { margin: 0; max-width: 90ch; }
.finder-empty,
.finder-note { margin: 0; font-size: var(--fs-sm); }
.finder-note[data-kind='error'] { color: var(--bad); }
/* La sentinelle du défilement continu : présente pour l'observateur, sans place à l'écran. */
.finder-sentinel { height: 1px; margin-top: -1px; }
.finder-more { justify-self: center; }
.finder-more[aria-disabled='true'] { opacity: 0.6; cursor: progress; }

.finder-list { display: grid; gap: var(--sp-1); margin: 0; padding: 0; list-style: none; }

.finder-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: stretch;
  gap: var(--sp-1);
}

/* La ligne entière est le bouton qui choisit : une grande cible, au doigt
   comme à la souris. Ses colonnes se replient sur un écran étroit. */
.finder-pick {
  display: grid;
  grid-template-columns: 28px minmax(0, 1.5fr) minmax(0, 1.2fr) minmax(0, 1fr) auto;
  grid-template-areas: 'logo names figures tags action';
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  min-width: 0;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-1);
  border-radius: var(--radius-1);
  background: var(--bg-1);
  color: var(--ink-1);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.finder-pick:hover { border-color: var(--line-2); background: var(--bg-3); }
.finder-pick:focus-visible { outline-offset: 0; border-color: var(--line-focus); }
.finder-pick[aria-disabled='true'] { cursor: not-allowed; }
.finder-pick[aria-disabled='true'] .finder-action { color: var(--warn); }
.finder-pick[aria-busy='true'] { opacity: 0.6; cursor: progress; }

.finder-logo { grid-area: logo; --make-logo-size: 24px; color: var(--ink-0); justify-self: center; }
.finder-names { grid-area: names; display: grid; gap: 1px; min-width: 0; }
.finder-name { color: var(--ink-0); font-weight: 600; font-size: var(--fs-md); overflow-wrap: anywhere; }
.finder-sub { color: var(--ink-2); font-size: var(--fs-xs); overflow-wrap: anywhere; }
.finder-period { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Une fiche détaillée se repère d'un coup d'œil dans la liste : un filet à
   la couleur de sa pastille. */
.finder-row[data-source='catalogue'] .finder-pick { border-left: 3px solid var(--accent-dim); }
.finder-figures { grid-area: figures; display: grid; gap: 1px; min-width: 0; }
.finder-power {
  color: var(--ink-0);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
}
.finder-meta { color: var(--ink-2); font-size: var(--fs-xs); overflow-wrap: anywhere; }
.finder-tags { grid-area: tags; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1); min-width: 0; }
.finder-regs { font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.finder-badge {
  padding: 0 var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--bg-4);
  color: var(--ink-0);
  font-size: var(--fs-xs);
  line-height: 1.6;
  white-space: nowrap;
}
.finder-action {
  grid-area: action;
  color: var(--accent);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
}
.finder-detail-button { align-self: center; }

.finder-detail { flex: 1; min-height: 0; overflow-y: auto; }

/* Une ligne de résultat sur un écran moyen : le nom et l'action sur la
   première ligne, les chiffres et les pastilles dessous. */
@media (max-width: 860px) {
  .finder-pick {
    grid-template-columns: 28px minmax(0, 1fr) auto;
    grid-template-areas:
      'logo names action'
      'logo figures figures'
      'logo tags tags';
  }
}

/* Sur un téléphone, la fenêtre devient l'écran entier. */
@media (max-width: 600px) {
  #modal:has(.finder) {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border: 0;
    border-radius: 0;
  }
  #modal:has(.finder) .modal-body { padding: var(--sp-2) var(--sp-3); }
  .finder-filter-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .finder-row { grid-template-columns: minmax(0, 1fr); }
  .finder-detail-button { justify-self: end; }
}

/* Logo de la marque en tête de colonne du tableau des résultats. */
#results-table .cmp-car .make-logo {
  --make-logo-size: 18px;
  display: block;
  margin: 0 0 2px auto;
  color: var(--ink-1);
}
#results-table .cmp-car .make-logo-monogram { display: grid; }

/* ================================================================== */
/* Saisie communautaire                                                */
/* ================================================================== */

/* L'invitation sur une carte du garage : un bouton fantôme, au ton des autres
   actions secondaires de la carte. */
.car-propose { color: var(--ink-2); }

/* Le formulaire vit dans la fenêtre modale et reprend la grammaire de
   l'éditeur de fiche : un champ, c'est une étiquette, une saisie et une aide
   sous elle ; l'aide devient le message du serveur quand un champ est refusé,
   au même endroit, pour que l'œil n'ait pas à chercher. */
.sub-form { display: grid; gap: var(--sp-3); min-width: min(560px, 82vw); }
.sub-intro { margin: 0; font-size: var(--fs-sm); line-height: 1.5; max-width: 70ch; }
.sub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--sp-3);
}
.sub-field { display: grid; gap: var(--sp-1); min-width: 0; align-content: start; }
.sub-field label,
.sub-label { color: var(--ink-1); font-size: var(--fs-sm); }
.sub-car { color: var(--ink-0); font-size: var(--fs-md); }
.sub-hint {
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-xs);
  line-height: 1.35;
}
.sub-field[data-state='invalid'] input,
.sub-field[data-state='invalid'] select { border-color: var(--bad); }
.sub-field[data-state='invalid'] .sub-hint,
.sub-group[data-state='invalid'] .sub-group-hint { color: var(--bad); }

/* La source est un vrai `fieldset` : un lecteur d'écran annonce « source »
   avant les quatre champs, et son aide dit pourquoi elle est exigée. */
.sub-group {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-2);
}
.sub-group legend {
  padding: 0 var(--sp-1);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.sub-group-hint { color: var(--ink-2); }

/* L'état de l'envoi, au-dessus des actions : un refus en rouge, une attente
   en jaune, et rien du tout quand tout va bien. */
.sub-status { margin: 0; font-size: var(--fs-sm); line-height: 1.4; }
.sub-status[data-kind='error'] { color: var(--bad); }
.sub-status[data-kind='warn'] { color: var(--warn); }

/* Le compte rendu après l'envoi : la phrase d'abord, les faits ensuite. */
.sub-outcome-message { margin: 0; color: var(--ink-0); font-size: var(--fs-md); }
.sub-outcome-message[data-state='accepted'] { color: var(--ok); }
.sub-outcome-message[data-state='refused'] { color: var(--bad); }
.sub-recap {
  display: grid;
  grid-template-columns: minmax(120px, auto) 1fr;
  gap: var(--sp-1) var(--sp-3);
  margin: 0;
}
.sub-recap dt { color: var(--ink-2); font-size: var(--fs-sm); }
.sub-recap dd {
  margin: 0;
  color: var(--ink-0);
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}
.sub-recap a { color: var(--ink-1); }

/* Le suivi et le détail d'une citation. */
.sub-tracking,
.sub-citation { display: grid; gap: var(--sp-3); min-width: min(480px, 80vw); }
.sub-list {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 56vh;
  overflow-y: auto;
}
.sub-item {
  display: grid;
  gap: var(--sp-1);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-1);
  border-left-width: 3px;
  border-radius: var(--radius-1);
  background: var(--bg-1);
}
.sub-item[data-state='pending'] { border-left-color: var(--warn); }
.sub-item[data-state='accepted'] { border-left-color: var(--ok); }
.sub-item[data-state='refused'] { border-left-color: var(--bad); }
.sub-item-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-1) var(--sp-2);
}
.sub-item-car { color: var(--ink-0); font-weight: 600; font-size: var(--fs-sm); }
.sub-state {
  padding: 0 var(--sp-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  font-size: var(--fs-xs);
  line-height: 1.6;
  white-space: nowrap;
}
.sub-item[data-state='pending'] .sub-state { color: var(--warn); border-color: var(--warn); }
.sub-item[data-state='accepted'] .sub-state { color: var(--ok); border-color: var(--ok); }
.sub-item[data-state='refused'] .sub-state { color: var(--bad); border-color: var(--bad); }
.sub-item-figures { margin: 0; color: var(--ink-1); font-size: var(--fs-sm); }
.sub-item-citation { margin: 0; }
.sub-item-citation a { color: var(--ink-1); }
.sub-item-reason { margin: 0; color: var(--bad); font-size: var(--fs-sm); }

/* La fenêtre « À propos » : les crédits des jeux de données. */
.about { display: grid; gap: var(--sp-2); max-width: 60ch; }
.about p { margin: 0; }
.about-credits h4 { margin: var(--sp-2) 0 0; color: var(--ink-0); font-size: var(--fs-sm); }
.about-credits ul { margin: 0; padding-left: var(--sp-4); display: grid; gap: var(--sp-1); }
.about-credits li { font-size: var(--fs-sm); }
.about-credits a { color: var(--ink-1); }

/* ================================================================== */
/* Historique des comparatifs                                          */
/* ================================================================== */

/* La fenêtre de ui/history.js : les comparatifs du plus récent au plus
   ancien, chacun avec ses voitures et ses actions. Elle garde la largeur d'une
   fenêtre ordinaire ; seule la liste grandit, et le corps défile. */
.history { display: grid; gap: var(--sp-2); min-width: min(560px, 84vw); }
.history p { margin: 0; }
.history-storage { color: var(--warn); font-size: var(--fs-sm); }

.history-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.history-search {
  display: flex;
  flex: 1 1 260px;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  min-width: 0;
}
.history-search input[type='search'] { flex: 1 1 180px; width: auto; min-width: 0; }
.history-pinned-only { display: inline-flex; align-items: center; gap: var(--sp-1); white-space: nowrap; cursor: pointer; }
.history-import { position: relative; cursor: pointer; }
.history-import:focus-within { outline: 2px solid var(--line-focus); outline-offset: 2px; }

.history-status { min-height: 1.4em; color: var(--ink-2); font-size: var(--fs-sm); }
.history-status[data-kind='ok'] { color: var(--ok); }
.history-status[data-kind='warn'] { color: var(--warn); }
.history-status[data-kind='error'] { color: var(--bad); }

/* Une suppression s'annule ici, quelques secondes durant. */
.history-undo {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-2);
  background: var(--bg-3);
}
.history-undo-text { flex: 1; min-width: 0; font-size: var(--fs-sm); overflow-wrap: anywhere; }

.history-list { display: grid; gap: var(--sp-2); margin: 0; padding: 0; list-style: none; }
.history-item {
  display: grid;
  gap: var(--sp-1);
  padding: var(--sp-3);
  border: 1px solid var(--line-1);
  border-radius: var(--radius-2);
  background: var(--bg-1);
}
.history-item[data-pinned='true'] { border-color: var(--accent-dim); }
.history-item-head { display: flex; align-items: baseline; gap: var(--sp-2); min-width: 0; }
/* Un nom long est coupé sur une ligne ; il reste entier au survol. */
.history-name {
  flex: 1;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  color: var(--ink-0);
  font-size: var(--fs-md);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.history-pin-mark { color: var(--accent); }
.history-meta,
.history-scenario { font-size: var(--fs-sm); }
.history-scenario { color: var(--ink-1); }
.history-shared { color: var(--info); }

.history-cars {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3);
  margin: var(--sp-1) 0 0;
  padding: 0;
  list-style: none;
}
.history-car {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-width: 0;
  color: var(--ink-1);
  font-size: var(--fs-sm);
  --make-logo-size: 18px;
}
/* La couleur de la voiture, peinte ou de série, comme le liseré des cartes. */
.history-car-color {
  flex: none;
  width: 4px;
  height: 16px;
  border-radius: 2px;
  background: var(--history-car, var(--ink-3));
}
.history-car-name { overflow-wrap: anywhere; }

.history-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  margin-top: var(--sp-1);
}
.history-actions .btn[aria-disabled='true'] { opacity: 0.45; cursor: not-allowed; }
.history-remove { color: var(--ink-3); }
.history-remove:hover:not(:disabled) { color: var(--bad); }

.history-rename { display: flex; flex: 1; flex-wrap: wrap; align-items: center; gap: var(--sp-1); min-width: 0; }
.history-rename-input { flex: 1 1 200px; width: auto; min-width: 0; }
.history-link-field { font-family: var(--font-num); text-overflow: ellipsis; }
.history-empty { padding: var(--sp-4) 0; text-align: center; }

/* Au doigt : des cibles qu'on touche sans viser. */
@media (pointer: coarse) {
  .history .btn,
  .history input[type='search'],
  .history-rename-input { min-height: 40px; }
}

/* Sur un téléphone, la fenêtre prend la largeur qu'elle a, et le nom passe à
   la ligne plutôt que d'être coupé. */
@media (max-width: 600px) {
  .history { min-width: 0; }
  .history-name { white-space: normal; overflow-wrap: anywhere; }
}

/* ================================================================== */
/* Écrans étroits                                                      */
/* ================================================================== */

/* En tiroir plein écran, le panneau dispose de toute la largeur : les cartes
   se mettent côte à côte plutôt que de laisser la moitié de l'écran vide. */
@media (max-width: 920px) {
  #garage > .panel-body {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    padding: var(--sp-3);
  }
  .wide { min-width: 0; }
  .sub-form, .sub-tracking, .sub-citation { min-width: 0; }
  .panel-head { min-height: 44px; }
  #results-table th,
  #results-table td { padding: var(--sp-2); }
}
