/* ==========================================================================
   Tes CV
   --------------------------------------------------------------------------
   Tout ce qui est ici est repris de la charte (design-tokens.css). Aucune
   couleur, aucune taille et aucun espacement n'est écrit en dur : si la
   charte bouge, cette page bouge avec elle.

   Les trois états d'un verdict (c'est bon, à revoir, bloquant) portent les
   couleurs d'état de la charte, déjà vérifiées au contraste. La couleur ne
   dit jamais rien toute seule : le mot est écrit à côté, pour qui ne
   distingue pas les couleurs comme pour un lecteur d'écran.
   ========================================================================== */

.cv {
  padding: var(--esp-8) 0 var(--esp-12);
  background: var(--paper);
  min-height: 60vh;
}

/* La MÊME règle que toutes les autres pages du site (Ton Espace, Nos offres,
   Mes candidatures) et que la barre du haut : 1120 px, 24 px de marge
   intérieure. Elle était écrite autrement ici, `min(1100px, ...)` sans
   marge, et le contenu démarrait 14 px à gauche du logo. Mesuré en 1440 px
   de large : barre à 184, contenu à 170. Une page dont la colonne ne tombe
   pas sur celle du menu se voit, même sans savoir la nommer. */
.largeur-cv {
  max-width: var(--largeur);
  margin: 0 auto;
  padding: 0 var(--esp-3);
}

/* --------------------------------------------------------------------------
   Les deux écrans d'attente : le chargement, et « personne n'est connecté »

   Le motif de pulsation est CELUI de Ton Espace, volontairement. Un site qui
   attend de deux façons différentes selon la page donne l'impression de deux
   sites. La règle de mouvement réduit est déjà posée pour tout le site dans
   styles-base.css : rien à répéter ici.
   -------------------------------------------------------------------------- */

.cv-squelette {
  background: var(--surface-creuse);
  border-radius: var(--r-carte);
  animation: cv-pulsation 1.4s ease-in-out infinite;
}

/* Chaque squelette a la hauteur du bloc qu'il remplace, pour que rien ne
   saute au moment où le vrai contenu arrive. */
.cv-squelette-titre { height: 64px; max-width: 6ch; margin-bottom: var(--esp-2); }
.cv-squelette-chapo { height: 84px; max-width: 52ch; margin-bottom: var(--esp-6); }

.cv-squelette-promesses {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--esp-3);
}

.cv-squelette-carte { height: 148px; }

@keyframes cv-pulsation {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* ---------- Personne n'est connecté ---------- */

.cv-debut {
  text-align: center;
  padding-top: var(--esp-6);
  animation: cv-arrivee var(--dur-long) var(--ease-sortie) both;
}

.cv-debut-paraf {
  display: block;
  width: 150px;
  height: auto;
  margin: 0 auto var(--esp-4);
}

.cv-debut-titre {
  margin: 0 0 var(--esp-2);
  font-size: var(--t-section);
  font-weight: var(--graisse-titre);
  letter-spacing: var(--suivi-section);
  line-height: var(--interligne-titre);
  color: var(--ink);
}

.cv-debut-texte {
  margin: 0 auto var(--esp-5);
  max-width: 46ch;
  font-size: var(--t-corps);
  line-height: var(--interligne-corps);
  color: var(--muted);
}

.btn-large {
  padding: 14px var(--esp-5);
  font-size: var(--t-corps);
}

@keyframes cv-arrivee {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

@media (max-width: 720px) {
  .btn-large { display: block; width: 100%; text-align: center; }
}

.cv-titre {
  font-size: var(--t-page);
  font-weight: var(--graisse-titre);
  letter-spacing: var(--suivi-page);
  line-height: var(--interligne-titre);
  color: var(--ink);
  margin: 0 0 var(--esp-2);
}

.cv-chapo {
  font-size: var(--t-sous-titre);
  line-height: var(--interligne-corps);
  color: var(--muted);
  max-width: 52ch;
  margin: 0 0 var(--esp-6);
}

/* ---------- Le dépôt ---------- */

.cv-depot { margin: 0 0 var(--esp-6); }

/* --------------------------------------------------------------------------
   Après une première analyse

   `cv-apres` est posée sur le <body> par script-tes-cv.js. Elle ne cache
   rien d'utile : les trois promesses répondaient à « qu'allez-vous faire de
   mon fichier », et cette question ne se pose plus une fois qu'il est passé.
   La zone de dépôt, elle, reste, parce qu'on redépose souvent. Elle passe
   simplement d'un panneau à une ligne.
   -------------------------------------------------------------------------- */

.cv-apres .cv-promesses { display: none; }

.cv-apres .cv-depot {
  margin: var(--esp-6) 0 0;
  padding-top: var(--esp-5);
  border-top: 1px solid var(--line);
}

.cv-apres .cv-depot-titre { font-size: var(--t-sous-titre); }

.cv-apres .cv-zone {
  flex-direction: row;
  justify-content: center;
  gap: var(--esp-2);
  padding: var(--esp-2) var(--esp-3);
}

.cv-apres .cv-zone-principal { font-size: var(--t-corps); }

.cv-depot-titre {
  font-size: var(--t-section);
  font-weight: var(--graisse-titre);
  letter-spacing: var(--suivi-section);
  line-height: var(--interligne-titre);
  color: var(--ink);
  margin: 0 0 var(--esp-2);
}

/* La zone de dépôt est un vrai bouton : elle s'atteint au clavier, elle
   s'annonce, et elle garde l'anneau de focus de la charte. */
.cv-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--esp-1);
  width: 100%;
  padding: var(--esp-6) var(--esp-3);
  background: var(--surface);
  border: 2px dashed var(--line);
  border-radius: var(--r-carte);
  cursor: pointer;
  font-family: var(--police-texte);
  text-align: center;
  transition: border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
}

.cv-zone:hover,
.cv-zone:focus-visible,
.cv-zone-survol {
  border-color: var(--accent);
  background: var(--surface-survol);
}

.cv-zone-principal {
  font-size: var(--t-sous-titre);
  font-weight: var(--graisse-moyen);
  color: var(--ink);
}

.cv-zone-details {
  font-size: var(--t-interface);
  color: var(--muted);
}

/* Le champ de fichier natif est masqué, jamais retiré : c'est lui qui ouvre
   la fenêtre de sélection, le bouton ne fait que le déclencher. */
.cv-input-fichier {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.cv-textarea {
  width: 100%;
  padding: var(--esp-2);
  font-family: var(--police-texte);
  font-size: var(--t-corps);
  line-height: var(--interligne-corps);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-champ);
  resize: vertical;
}

.cv-bouton {
  margin-top: var(--esp-2);
  padding: var(--esp-2) var(--esp-4);
  font-family: var(--police-texte);
  font-size: var(--t-corps);
  font-weight: var(--graisse-moyen);
  color: var(--sur-bleu);
  background: var(--accent);
  border: 0;
  border-radius: var(--r-bouton);
  cursor: pointer;
}

.cv-bouton:hover { background: var(--accent-fonce); }

/* ---------- La réponse ---------- */

.cv-refus {
  background: var(--erreur-fond);
  border-color: var(--erreur);
  border-width: 1px;
  border-style: solid;
  border-radius: var(--r-carte);
  padding: var(--esp-4);
}

.cv-refus-titre {
  font-size: var(--t-section);
  font-weight: var(--graisse-titre);
  line-height: var(--interligne-titre);
  color: var(--ink);
  margin: 0 0 var(--esp-1);
}

.cv-refus-texte {
  font-size: var(--t-corps);
  line-height: var(--interligne-corps);
  color: var(--ink);
  margin: 0;
}

.cv-avertissements {
  list-style: none;
  margin: 0 0 var(--esp-3);
  padding: 0;
  display: grid;
  gap: var(--esp-1);
}

.cv-avertissement {
  background: var(--attention-fond);
  border-left: 3px solid var(--attention);
  border-radius: var(--r-champ);
  padding: var(--esp-2);
  font-size: var(--t-interface);
  line-height: var(--interligne-corps);
  color: var(--attention-texte);
}

.cv-liste-titre {
  font-size: var(--t-sous-titre);
  font-weight: var(--graisse-titre);
  color: var(--ink);
  margin: 0 0 var(--esp-2);
}










/* La correction est ce qu'on fait ensuite : elle se distingue du constat,
   sans crier plus fort que lui. */

/* ---------- Le détail d'où vient la note ---------- */

.cv-bloc { margin: var(--esp-6) 0 0; }

.cv-couche-texte {
  font-size: var(--t-interface);
  line-height: var(--interligne-corps);
  color: var(--muted);
  margin: 0 0 var(--esp-1);
}

.cv-penalite {
  font-size: var(--t-interface);
  line-height: var(--interligne-corps);
  color: var(--erreur-texte);
  background: var(--erreur-fond);
  border-radius: var(--r-champ);
  padding: var(--esp-1) var(--esp-2);
  margin: var(--esp-1) 0 0;
}

.cv-vide {
  font-size: var(--t-interface);
  color: var(--muted);
  margin: var(--esp-1) 0 0;
}

/* ---------- Les trois ATS (lot 5, étape 3) ---------- */






/* ---------- Ce que la machine lit vraiment (10 septembre 2026) ----------

   Replié par défaut : c'est une preuve qu'on va chercher, pas un mur de
   charabia qui accueille l'étudiant. */

.cv-machine {
  margin: var(--esp-4) 0;
  padding: var(--esp-3);
  background: var(--fond-alerte);
  border: 1px solid var(--alerte);
  border-radius: var(--r-carte);
}

.cv-machine-titre {
  font-weight: var(--graisse-titre);
  color: var(--alerte-texte);
  cursor: pointer;
}

.cv-machine-mesure {
  margin: var(--esp-2) 0 0;
  font-weight: var(--graisse-titre);
  color: var(--alerte-texte);
}

.cv-machine-explication {
  margin: var(--esp-1) 0 var(--esp-2);
  color: var(--ink);
  line-height: var(--interligne-corps);
}

.cv-machine-texte {
  max-height: 320px;
  overflow: auto;
  padding: var(--esp-2);
  background: var(--surface);
  border-radius: var(--r-champ);
  font-family: var(--police-chiffres);
  font-size: 0.8rem;
  line-height: 1.5;
  white-space: pre-wrap;
  color: var(--ink);
}

/* ==========================================================================
   La page « Ton score ATS », refonte du 12 septembre 2026.

   Direction artistique : DESIGN.md. Trois règles tiennent cette grille.
   1. Un seul aplat sombre, la carte du score : c'est le point focal, et c'est
      le seul endroit où l'orange existe.
   2. Les quatre cartes sont soeurs dans une seule grille, donc les cartes
      d'une même rangée commencent et finissent à la même hauteur.
   3. Chaque carte dit, sous son titre, ce qu'elle fait et ce qu'elle ne fait
      pas. Cette ligne ne disparaît jamais.
   ========================================================================== */

.cv-titre em { font-style: normal; color: var(--orange-texte); }

.cv-grille {
  display: grid;
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  gap: var(--esp-3);
  align-items: stretch;
  margin: var(--esp-6) 0 var(--esp-4);
}

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

.cv-carte {
  display: flex;
  flex-direction: column;
  padding: var(--esp-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-carte);
  box-shadow: var(--ombre-douce);
}

.cv-carte-titre {
  margin: 0 0 var(--esp-0-5);
  font-size: var(--t-sous-titre);
  font-weight: var(--graisse-titre);
  line-height: var(--interligne-titre);
  color: var(--ink);
}

.cv-aide {
  margin: 0 0 var(--esp-3);
  font-size: var(--t-interface);
  line-height: 1.5;
  color: var(--muted);
  text-wrap: pretty;
}

/* ---------- Carte 01 : quel CV ---------- */

.cv-bascule {
  display: flex;
  gap: 6px;
  padding: 6px;
  margin: 0 0 var(--esp-3);
  background: var(--surface-creuse);
  border-radius: var(--r-bouton);
}

.cv-bascule button {
  flex: 1;
  min-height: 44px;
  padding: 0 var(--esp-2);
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--r-bouton);
  font-size: var(--t-interface);
  font-weight: var(--graisse-moyen);
  cursor: pointer;
  transition: color var(--dur-court) var(--ease-sortie), background var(--dur-court) var(--ease-sortie);
}

.cv-bascule button[aria-selected="true"] {
  color: var(--ink);
  background: var(--surface);
  box-shadow: var(--ombre-douce);
}

.cv-volet[hidden] { display: none; }

.cv-choix { display: grid; gap: 10px; margin: 0 0 var(--esp-3); padding: 0; list-style: none; }

.cv-choix-bouton {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr);
  align-items: center;
  gap: var(--esp-2);
  width: 100%;
  min-height: 52px;
  padding: 6px var(--esp-2) 6px 6px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-champ);
  cursor: pointer;
  transition: border-color var(--dur-court) var(--ease-sortie), background var(--dur-court) var(--ease-sortie);
}

.cv-choix-bouton:hover { background: var(--surface-survol); }
.cv-choix-bouton[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }

.cv-choix-note {
  display: grid;
  place-items: center;
  height: 38px;
  font-family: var(--police-chiffres);
  font-size: var(--t-interface);
  font-weight: var(--graisse-titre);
  font-variant-numeric: tabular-nums;
  background: var(--surface-creuse);
  border-radius: 8px;
}

.cv-choix-nom { display: block; font-size: var(--t-interface); font-weight: var(--graisse-moyen); }
.cv-choix-quand { display: block; font-size: 0.75rem; color: var(--muted); }
.cv-choix-vide { font-size: var(--t-interface); color: var(--muted); }

.cv-principal {
  width: 100%;
  min-height: 48px;
  margin-top: auto;
  padding: 0 var(--esp-4);
  color: var(--sur-bleu);
  background: var(--accent);
  border: 0;
  border-radius: var(--r-bouton);
  font-weight: var(--graisse-moyen);
  cursor: pointer;
  box-shadow: var(--ombre-douce);
  transition: background var(--dur-court) var(--ease-sortie), transform var(--dur-court) var(--ease-sortie);
}

.cv-principal:hover { background: var(--accent-fonce); }
.cv-principal:active { transform: scale(.99); }

/* ==========================================================================
   La carte du score : le seul aplat sombre de la page.
   ========================================================================== */

.cv-score {
  color: var(--sur-nuit);
  background: var(--nuit);
  border-color: var(--nuit);
  box-shadow: var(--ombre-carte);
}


/* Le verdict est monté au-dessus (16 septembre 2026, demandé par Valentin) :
   il ne reste plus que l'anneau ici, centré seul. */
.cv-score-corps {
  display: flex;
  justify-content: center;
  /* De l'air au-dessus et en dessous : l'anneau touchait le filet de la
     liste d'étude, et un cercle posé sur un trait se lit comme une erreur
     de mise en page. */
  margin: var(--esp-3) 0 var(--esp-3);
}

/* @property déclare --cv-tour comme un nombre, ce qui permet au navigateur
   de l'animer. Sans cette déclaration, la note sauterait d'un coup au lieu
   de monter jusqu'à sa graduation. */
@property --cv-tour {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

/* ==========================================================================
   L'anneau du score : deux arcs et un écart (16 septembre 2026)

   Ce qu'il y avait avant : un disque en dégradé conique, creusé par un
   masque, avec une pastille posée au départ et une autre à l'arrivée pour
   arrondir les bouts. Quatre couches qui devaient rester d'accord entre
   elles, et un arc dont les extrémités coupaient à l'équerre.

   Ce qu'il y a maintenant : deux traits de cercle. Le premier porte la note,
   le second porte ce qui reste à gagner, et il est tracé à rebours depuis
   midi, ce qui ménage un écart de chaque côté sans calculer une coordonnée.
   Les bouts sont ronds parce que le trait l'est (stroke-linecap), et non
   parce qu'on pose des pastilles par-dessus.

   Tout est piloté par --cv-tour, de 0 à 1. La géométrie ne connaît qu'une
   seule autre valeur, le pourcentage de tour en unités du dessin.
   ========================================================================== */

.cv-anneau-bloc { position: relative; width: 176px; height: 176px; }

.cv-anneau {
  --cv-tour: 0;
  /* r = 40 dans un carré de 100 : le trait de 10 tient dans le cadre
     (40 + 5 = 45) et il reste 5 % de marge tout autour, pour que la lueur
     ait où déborder. Tour = 2 x PI x 40 = 251,327. */
  --cv-tour-complet: 251.327px;
  --cv-un-pourcent: 2.51327px;
  /* L'écart entre l'arc de la note et l'arc du reste, en pourcentage du tour.
     Quatre pour cent de chaque côté : assez pour que l'oeil voie deux traits
     distincts, assez peu pour qu'un 99 ne devienne pas un tour complet. */
  --cv-ecart: 4;
  --cv-arc-a: var(--orange, #FF6B35);
  --cv-arc-b: #FFC27E;
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  /* C'est la VARIABLE qui s'anime, pas les traits. Animer directement le
     stroke-dasharray revient à interpoler une liste de longueurs, et le
     navigateur reste alors bloqué sur la valeur de départ : mesuré à l'écran
     le 16 septembre 2026, l'anneau restait vide quelle que soit la note.
     En animant --cv-tour, les deux arcs et la lueur se recalculent ensemble
     à chaque image, et ils ne peuvent pas se désynchroniser. */
  transition: --cv-tour 1200ms var(--ease-sortie);
}

.cv-arc-depart { stop-color: var(--cv-arc-a); }
.cv-arc-arrivee { stop-color: var(--cv-arc-b); }

.cv-anneau circle {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  transform-box: fill-box;
  transform-origin: center;
  /* Les traits ne transitionnent que sur la couleur : leur longueur suit
     --cv-tour, qui s'anime plus haut. */
  transition: stroke 420ms ease, opacity 420ms ease;
}

/* L'arc de la note. Un cercle SVG commence son tracé à 3 heures : la rotation
   d'un quart de tour vers l'arrière le fait partir de midi. */
.cv-anneau-arc {
  stroke: url(#cv-degrade-arc);
  stroke-dasharray: calc(var(--cv-tour) * 100 * var(--cv-un-pourcent)) var(--cv-tour-complet);
  transform: rotate(-90deg);
}

/* Ce qui reste à gagner, tracé à rebours depuis midi : le miroir vertical
   inverse le sens du tracé, et la rotation le ramène au départ. C'est ce
   couple-là, et lui seul, qui creuse l'écart des deux côtés de la note. */
.cv-anneau-reste {
  stroke: var(--nuit-ligne);
  /* max(0, ...) : à 100 sur 100, le reste vaudrait moins que rien, et une
     longueur négative fait ignorer la déclaration au navigateur, donc
     l'anneau resterait figé sur sa valeur précédente. */
  stroke-dasharray:
    calc(max(0, 100 - var(--cv-tour) * 100 - var(--cv-ecart) * 2) * var(--cv-un-pourcent))
    var(--cv-tour-complet);
  transform: rotate(calc(1turn - 90deg - var(--cv-ecart) * 3.6deg)) scaleY(-1);
}

/* La lueur : le même arc que la note, flouté et posé dessous. Sur un fond
   nuit, c'est elle qui donne son épaisseur à l'anneau. */
.cv-anneau-lueur {
  stroke: var(--cv-arc-a);
  stroke-dasharray: calc(var(--cv-tour) * 100 * var(--cv-un-pourcent)) var(--cv-tour-complet);
  transform: rotate(-90deg);
  filter: blur(5px);
  opacity: .4;
}

/* En attente, le tour entier est en pointillé et aucun arc ne porte de note :
   un zéro se lirait comme un très mauvais CV, un pointillé se lit comme
   « rien encore ».

   Tirets plus longs que le trait n'est épais : à 2 pixels de long pour 7
   d'épaisseur, ils se dressaient en rayons autour du centre au lieu de
   suivre la courbe (vu à l'écran le 16 septembre 2026). */
.cv-score[data-etat="attente"] .cv-anneau-reste {
  stroke-width: 4;
  stroke-linecap: butt;
  stroke-dasharray: 5px 7.5px;
  transform: none;
}

/* Une note de zéro. Un trait de longueur nulle terminé par un bout rond
   dessine quand même un point, et ce point se lisait comme une note posée à
   midi. Le SVG fait ce que la spécification demande ; c'est nous qui ne
   voulons rien montrer quand il n'y a rien à montrer. */
.cv-anneau-zero .cv-anneau-arc,
.cv-anneau-zero .cv-anneau-lueur { opacity: 0; }

/* Pendant la lecture, un segment court fait le tour. Il ne prétend pas
   connaître l'avancement, il dit que ça travaille. */
.cv-score[data-etat="lecture"] .cv-anneau { --cv-tour: .14; }
.cv-score[data-etat="lecture"] .cv-anneau-arc,
.cv-score[data-etat="lecture"] .cv-anneau-lueur {
  transition: none;
  animation: cv-chenille 1.4s linear infinite;
}

@keyframes cv-chenille {
  from { transform: rotate(-90deg); }
  to { transform: rotate(270deg); }
}

.cv-score[data-etat="attente"] .cv-anneau-arc,
.cv-score[data-etat="attente"] .cv-anneau-lueur { opacity: 0; }

.cv-anneau-centre { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }

.cv-score-chiffre {
  display: block;
  font-family: var(--police-chiffres);
  font-size: 2.75rem;
  font-weight: var(--graisse-titre);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -.04em;
}

.cv-score[data-etat="attente"] .cv-score-chiffre,
.cv-score[data-etat="lecture"] .cv-score-chiffre { font-size: 1.75rem; color: var(--sur-nuit-doux); }

.cv-score-sur {
  display: block;
  margin-top: 6px;
  font-size: 0.75rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--sur-nuit-doux);
}

.cv-verdict {
  margin: var(--esp-2) auto 0;
  max-width: 34rem;
  font-size: var(--t-sous-titre);
  font-weight: var(--graisse-moyen);
  line-height: 1.45;
  text-align: center;
  text-wrap: pretty;
}

.cv-verdict em { font-style: normal; color: var(--orange); }

@keyframes cv-ligne { from { opacity: 0; transform: translateY(6px); } }


/* ---------- Carte : tes CV enregistrés ---------- */

.cv-rangee { flex: 1; min-height: 0; margin: 0; padding: 0 var(--esp-1) 0 0; list-style: none; }

.cv-rangee li {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
  border-top: 1px solid var(--divider);
}

.cv-rangee li:first-child { border-top: 0; }

.cv-rangee-note {
  font-family: var(--police-chiffres);
  font-size: var(--t-interface);
  font-weight: var(--graisse-titre);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.cv-rangee-nom { display: block; font-size: var(--t-interface); overflow-wrap: anywhere; }
.cv-rangee-quand { display: block; font-size: 0.75rem; color: var(--muted); }

.cv-effacer {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--r-bouton);
  cursor: pointer;
  transition: color var(--dur-court) var(--ease-sortie), background var(--dur-court) var(--ease-sortie);
}

.cv-effacer:hover { color: var(--erreur-texte); background: var(--erreur-fond); }

.cv-reste { margin: var(--esp-2) 0 0; font-size: 0.75rem; color: var(--muted); }

/* ---------- Carte « Notre analyse » ----------
   Les corrections, puis les contrôles de lecture. La carte garde sa hauteur :
   ce qui dépasse se fait défiler à l'intérieur, et la carte de gauche a la
   même hauteur plancher pour que la rangée reste symétrique. */

/* Hauteur FIXE, et pas seulement minimale : c'est ce qui empêche la carte de
   descendre vers l'infini quand l'analyse est longue. Ce qui dépasse défile
   à l'intérieur. Sur une colonne (téléphone), la contrainte saute : une carte
   haute de 460 px au milieu d'une pile ne sert plus à rien. */
.cv-carte-haute { height: 460px; overflow: hidden; }

@media (max-width: 900px) { .cv-carte-haute { height: auto; max-height: 70vh; } }

/* Le fondu du bas : sur macOS, l'ascenseur ne se montre qu'au moment où on
   fait défiler. Sans ce dégradé, rien ne dirait qu'il reste des lignes en
   dessous, et une carte à hauteur fixe passerait pour une carte finie. */
.cv-carte-analyse { position: relative; }

.cv-carte-analyse::after {
  content: '';
  position: absolute;
  left: 1px;
  right: 1px;
  bottom: 1px;
  height: 32px;
  background: linear-gradient(to top, var(--surface), transparent);
  border-radius: 0 0 var(--r-carte) var(--r-carte);
  pointer-events: none;
}

.cv-analyse {
  flex: 1;
  min-height: 0;
  /* La barre de défilement se pose dans cette marge : sans elle, elle
     passerait sur le texte des lignes. */
  padding-right: var(--esp-1);
}



/* ---------- Les corrections, dans la carte ---------- */

.cv-recos { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; }

.cv-reco {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  gap: var(--esp-2);
  align-items: center;
  padding: var(--esp-2);
  background: var(--surface-creuse);
  border-radius: var(--r-champ);
  animation: cv-ligne var(--dur-long) var(--ease-sortie) backwards;
  animation-delay: calc(var(--rang, 0) * 70ms + 300ms);
}

.cv-gain {
  display: grid;
  place-items: center;
  height: 40px;
  font-family: var(--police-chiffres);
  font-size: 1.0625rem;
  font-weight: var(--graisse-titre);
  font-variant-numeric: tabular-nums;
  color: var(--succes-texte);
  background: var(--succes-fond);
  border-radius: 8px;
}

.cv-reco h3 { margin: 0; font-size: var(--t-corps); font-weight: var(--graisse-moyen); }
.cv-reco p { margin: 2px 0 0; font-size: var(--t-interface); line-height: 1.5; color: var(--muted); }
.cv-reco-vide { font-size: var(--t-interface); color: var(--muted); }
/* Le secteur confirmé, une fois la card refermée (17 septembre 2026) : une
   ligne d'information fixe, jamais une action, donc jamais de bouton. */
.cv-reco-secteur { font-size: var(--t-interface); color: var(--muted); font-style: italic; }

/* La ligne du CV que le conseil vise (13 septembre 2026). C'est une citation,
   pas un titre : filet à gauche, texte en italique, et jamais de couleur qui
   la fasse passer pour une alerte. Elle peut être longue, donc elle coupe
   proprement au lieu d'élargir la carte. */
.cv-reco-extrait {
  margin-top: 6px;
  padding-left: 10px;
  border-left: 2px solid var(--line);
  overflow-wrap: anywhere;
}
.cv-reco-extrait q { font-style: italic; quotes: '\00AB\00A0' '\00A0\00BB'; }

/* Le message du rangement, sous la grille. Vide, il ne prend aucune place. */
.cv-histo-etat { margin: 0 0 var(--esp-4); font-size: var(--t-interface); color: var(--muted); }
.cv-histo-etat:empty { display: none; }
.cv-histo-etat-ok { color: var(--succes-texte); }
.cv-histo-etat-refus { color: var(--erreur-texte); }

@media (prefers-reduced-motion: reduce) {
  .cv-reco { animation: none; }
  .cv-anneau { transition: none; }
  .cv-score[data-etat="lecture"] .cv-anneau-arc,
  .cv-score[data-etat="lecture"] .cv-anneau-lueur { animation: none; }
}

/* ==========================================================================
   Le choix de l'offre, et la proposition de rangement.
   Ajoutés le 12 septembre 2026 avec le lancement manuel du test.
   ========================================================================== */

/* Les deux volets deviennent des colonnes : c'est ce qui colle les deux
   boutons bleus au même endroit, tout en bas de la carte, quel que soit le
   nombre de CV rangés au-dessus. */
.cv-volet:not([hidden]) { display: flex; flex-direction: column; flex: 1; }

.cv-choisi {
  margin: var(--esp-2) 0 var(--esp-2);
  font-size: var(--t-interface);
  color: var(--muted);
  overflow-wrap: anywhere;
}
.cv-choisi:empty { display: none; }

/* ---------- La barre de défilement, partout où une liste dépasse ----------
   Fine, translucide, et elle ne prend pas de place en largeur. C'est le seul
   endroit du site où l'on habille l'ascenseur : une liste qui déborde doit se
   voir déborder, sinon on croit la carte finie. */
.cv-defile {
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(31, 28, 80, 0.22) transparent;
}
.cv-defile::-webkit-scrollbar { width: 8px; }
.cv-defile::-webkit-scrollbar-track { background: transparent; }
.cv-defile::-webkit-scrollbar-thumb {
  background: rgba(31, 28, 80, 0.18);
  border: 2px solid transparent;
  border-radius: 999px;
  background-clip: content-box;
}
.cv-defile:hover::-webkit-scrollbar-thumb { background: rgba(31, 28, 80, 0.32); background-clip: content-box; }

/* ---------- La proposition de rangement ---------- */

.cv-ranger {
  margin: 0 0 var(--esp-2);
  padding: var(--esp-2);
  background: var(--surface-creuse);
  border-radius: var(--r-champ);
}

.cv-ranger-texte {
  margin: 0 0 var(--esp-2);
  font-size: var(--t-interface);
  line-height: 1.5;
  color: var(--ink);
  text-wrap: pretty;
}

.cv-ranger-boutons { display: flex; align-items: center; gap: var(--esp-2); flex-wrap: wrap; }

.cv-ranger-non {
  min-height: 36px;
  padding: 0 var(--esp-2);
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--r-bouton);
  font-size: var(--t-interface);
  cursor: pointer;
}
.cv-ranger-non:hover { color: var(--ink); background: var(--surface-survol); }

/* ---------- La fenêtre « face à quelle offre ? » ---------- */

.cv-voile {
  position: fixed;
  inset: 0;
  z-index: var(--z-voile);
  background: rgba(20, 22, 60, 0.42);
  backdrop-filter: blur(3px);
}

.cv-fenetre {
  position: fixed;
  z-index: var(--z-fenetre);
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  width: min(560px, calc(100vw - 2 * var(--esp-3)));
  max-height: min(640px, calc(100vh - 2 * var(--esp-4)));
  padding: var(--esp-3);
  background: var(--surface);
  border-radius: var(--r-panneau);
  box-shadow: var(--ombre-fenetre);
}

.cv-fenetre[hidden], .cv-voile[hidden] { display: none; }

.cv-fenetre-tete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--esp-2);
  margin-bottom: var(--esp-2);
}

.cv-fenetre-titre {
  margin: 0;
  font-size: var(--t-sous-titre);
  font-weight: var(--graisse-titre);
  line-height: var(--interligne-titre);
  color: var(--ink);
}

.cv-fenetre-sous {
  margin: var(--esp-0-5) 0 0;
  font-size: var(--t-interface);
  line-height: 1.5;
  color: var(--muted);
  text-wrap: pretty;
}

.cv-fenetre-avis {
  margin: 0 0 var(--esp-2);
  font-size: var(--t-interface);
  line-height: 1.5;
  color: var(--muted);
  text-wrap: pretty;
}

.cv-fermer {
  flex: none;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--r-bouton);
  cursor: pointer;
}
.cv-fermer:hover { color: var(--ink); background: var(--surface-survol); }

#cv-fenetre-choix { display: flex; flex-direction: column; min-height: 0; flex: 1; }
#cv-fenetre-coller { display: flex; flex-direction: column; min-height: 0; flex: 1; }
#cv-fenetre-choix[hidden], #cv-fenetre-coller[hidden] { display: none; }

.cv-chercher {
  width: 100%;
  min-height: 44px;
  padding: 0 var(--esp-2);
  margin-bottom: var(--esp-2);
  font: inherit;
  font-size: var(--t-corps);
  color: var(--ink);
  background: var(--surface-creuse);
  border: 1px solid var(--line);
  border-radius: var(--r-champ);
}
.cv-chercher:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* La liste tient dans la fenêtre et défile dedans : la fenêtre elle-même ne
   grandit jamais avec le nombre de candidatures. */
.cv-offres {
  margin: 0;
  padding: 0 var(--esp-0-5) 0 0;
  list-style: none;
  display: grid;
  gap: 8px;
  align-content: start;
  max-height: 320px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(31, 28, 80, 0.22) transparent;
}
.cv-offres::-webkit-scrollbar { width: 8px; }
.cv-offres::-webkit-scrollbar-track { background: transparent; }
.cv-offres::-webkit-scrollbar-thumb {
  background: rgba(31, 28, 80, 0.18);
  border: 2px solid transparent;
  border-radius: 999px;
  background-clip: content-box;
}
.cv-offres:hover::-webkit-scrollbar-thumb { background: rgba(31, 28, 80, 0.32); background-clip: content-box; }

.cv-offre-ligne {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-2);
  width: 100%;
  min-height: 56px;
  padding: 8px var(--esp-2);
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-champ);
  cursor: pointer;
  transition: border-color var(--dur-court) var(--ease-sortie), background var(--dur-court) var(--ease-sortie);
}
.cv-offre-ligne:hover { background: var(--surface-survol); }
.cv-offre-ligne[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }

.cv-offre-texte-ligne { min-width: 0; }
.cv-offre-poste { display: block; font-size: var(--t-corps); font-weight: var(--graisse-moyen); color: var(--ink); }
.cv-offre-entreprise { display: block; font-size: var(--t-interface); color: var(--muted); }

.cv-offre-etat {
  flex: none;
  padding: 3px 10px;
  font-size: 0.75rem;
  color: var(--alerte-texte);
  background: var(--fond-alerte);
  border-radius: var(--r-bouton);
  white-space: nowrap;
}
.cv-offre-prete { color: var(--succes-texte); background: var(--fond-succes); }

.cv-offres-vide { font-size: var(--t-interface); color: var(--muted); line-height: 1.5; }

.cv-fenetre-pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-2);
  margin-top: var(--esp-3);
}

.cv-sans-offre {
  min-height: 44px;
  padding: 0 var(--esp-2);
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--r-bouton);
  font-size: var(--t-interface);
  cursor: pointer;
}
.cv-sans-offre:hover { color: var(--ink); background: var(--surface-survol); }
.cv-sans-offre[hidden] { display: none; }

/* Le bouton bleu de la fenêtre reprend celui des cartes, sans son
   « margin-top: auto » qui n'a pas de sens dans un pied de fenêtre. */
/* margin-left auto : au deuxième temps, « Tester sans offre » disparaît, et
   sans ça le bouton bleu glisserait à gauche de la fenêtre. */
.cv-valider { width: auto; margin-top: 0; margin-left: auto; }
.cv-valider:disabled { background: var(--metal); color: var(--muted); cursor: not-allowed; box-shadow: none; }

@media (max-width: 560px) {
  .cv-fenetre-pied { flex-direction: column-reverse; align-items: stretch; }
  .cv-valider { width: 100%; }
}

/* Un retrait forfaitaire n'est pas une correction qui rapporte : il se
   distingue au premier coup d'oeil, sans crier. */
.cv-gain-malus { color: var(--erreur-texte); background: var(--erreur-fond); }
/* Le conseil bonus du secteur : ni un gain de points ni un retrait, une
   étoile plutôt qu'un chiffre pour ne pas laisser croire à l'un ou l'autre. */
.cv-gain-bonus { color: var(--accent-fonce); background: var(--accent-doux); font-size: 1.25rem; }

/* Le verdict en quatre états, et les portes éliminatoires (15 septembre 2026,
   quatrième état le 16). Le verdict est la première chose lue : il a sa
   couleur, et elle dit la gravité sans qu'on ait à lire la phrase.

   « à renforcer » est le cas d'un CV que la machine lit sans peine mais dont
   le contenu reste maigre : le vert mentirait, le rouge serait injuste. */
.cv-verdict-titre { display: block; font-size: 1.125rem; font-weight: 700; margin-bottom: 0.25rem; color: var(--sur-nuit); }
.cv-verdict-detail { display: block; opacity: 0.85; }

#cv-score[data-verdict="risque"] .cv-verdict-titre { color: #FFB35C; }
#cv-score[data-verdict="illisible"] .cv-verdict-titre { color: #FF8F85; }


/* Fondue dans #cv-recos depuis le 17 septembre 2026 : ces li vivent
   maintenant dans la grille de « Notre analyse », qui pose déjà le
   list-style et le gap. */
.cv-porte { display: flex; gap: 0.6rem; align-items: flex-start; padding: 0.6rem 0.75rem;
  border-radius: 10px; border: 1px solid rgba(0, 0, 0, 0.08); background: rgba(0, 0, 0, 0.02); }
.cv-porte h3 { margin: 0 0 0.2rem; font-size: 0.95rem; }
.cv-porte p { margin: 0; font-size: 0.85rem; opacity: 0.85; }
.cv-porte-etiquette { flex: 0 0 auto; font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; padding: 0.15rem 0.45rem; border-radius: 999px; }
.cv-porte-risque .cv-porte-etiquette { background: #fdeccd; color: #8a4b00; }
.cv-porte-inconnu .cv-porte-etiquette { background: #e7eaf0; color: #4a5568; }


/* Le conseil en quatre morceaux (15 septembre 2026) : ce que ça casse, le
   problème, ce que ça coûte, la ligne citée, puis quoi faire. Le remède est le
   seul morceau qu'on recopie : il se voit. */
.cv-reco-cout { margin: 0.1rem 0 0.3rem; font-size: 0.82rem; opacity: 0.75; }
.cv-reco-remede { margin: 0.4rem 0 0; padding: 0.45rem 0.6rem; border-radius: 8px;
  background: rgba(26, 127, 75, 0.08); border-left: 3px solid #1a7f4b; font-size: 0.88rem; }
.cv-reco-remede-titre { font-weight: 700; }

/* Ce qui manque pour lancer le test, dit là où l'oeil est déjà (15 sept 2026).
   Avant, le bouton restait muet, ou ouvrait la fenêtre des offres pour rien. */
.cv-choisi-manque { color: #a35a00; font-weight: 600; }

/* La couleur de l'anneau suit le VERDICT, pas la note : un 68 qui passe la
   machine et un 68 bloqué ne racontent pas la même chose. */
.cv-score[data-verdict="passe"] .cv-anneau {
  --cv-arc-a: #2FA173; --cv-arc-b: #8BF0C0;
}
.cv-score[data-verdict="illisible"] .cv-anneau {
  --cv-arc-a: #C84B4B; --cv-arc-b: #F5B4B4;
}
.cv-score[data-verdict="a-renforcer"] .cv-anneau {
  --cv-arc-a: #C98A2E; --cv-arc-b: #F2D49B;
}

}

/* Le second paragraphe du chapô dit ce qu'on regarde, et dans quel ordre.
   Il est plus discret que le premier : on annonce, on n'assomme pas. */
.cv-chapo-suite { opacity: 0.82; }

/* Le voyant de la lecture machine, au-dessus du verdict du contenu. */
.cv-voyant {
  display: block;
  border-left: 4px solid var(--line);
  border-radius: var(--r-champ);
  padding: var(--esp-1) var(--esp-2);
  margin: 0 0 var(--esp-2);
}
.cv-voyant-lu { border-left-color: var(--succes); background: var(--succes-fond); }
.cv-voyant-risque { border-left-color: var(--attention); background: var(--attention-fond); }
.cv-voyant-bloque { border-left-color: var(--erreur); background: var(--erreur-fond); }
.cv-voyant-titre { display: block; font-weight: var(--graisse-moyen); }
.cv-voyant-lu .cv-voyant-titre { color: var(--succes-texte); }
.cv-voyant-risque .cv-voyant-titre { color: var(--attention-texte); }
.cv-voyant-bloque .cv-voyant-titre { color: var(--erreur-texte); }
.cv-voyant-detail { display: block; font-size: 0.875rem; color: var(--ink); }

/* La nuance de ton ajoutée par le secteur, une phrase de plus dans le même
   voyant : jamais une deuxième couleur, jamais un nouvel état (16 sept 2026,
   règle 4 du chantier). */
.cv-voyant-secteur { display: block; font-size: 0.875rem; margin-top: 0.3rem; color: var(--ink); opacity: 0.85; }

/* Le secteur détecté : jamais un retrait, un ton et un conseil bonus. Sous le
   titre de la carte, avant la note (docs/CV-ATS.md, section Secteurs). */
.cv-secteur {
  margin: 0 0 var(--esp-2);
  padding: var(--esp-2);
  background: var(--surface-creuse);
  border-radius: var(--r-champ);
}
.cv-secteur-texte { margin: 0 0 var(--esp-1); font-size: var(--t-interface); line-height: 1.5; color: var(--ink); }
.cv-secteur-bonus { margin: var(--esp-1) 0 0; font-size: 0.875rem; color: var(--ink); opacity: 0.85; }
.cv-secteur-boutons { display: flex; align-items: center; gap: var(--esp-2); flex-wrap: wrap; }
.cv-secteur-boutons .cv-bouton { margin-top: 0; }

.cv-secteur-changer {
  min-height: 36px;
  padding: 0 var(--esp-2);
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--r-bouton);
  font-size: var(--t-interface);
  cursor: pointer;
}
.cv-secteur-changer:hover { color: var(--ink); background: var(--surface-survol); }

.cv-secteur-choix { display: flex; flex-wrap: wrap; gap: var(--esp-1); }
.cv-secteur-choix-bouton {
  padding: 0.4rem 0.75rem;
  font-size: var(--t-interface);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-bouton);
  cursor: pointer;
}
.cv-secteur-choix-bouton:hover { background: var(--surface-survol); }

/* ---------- L'analyse IA (lot 5) : un bloc sous « Notre analyse » ---------- */
.cv-ia-etiquette { display: block; margin-bottom: var(--esp-1); font-size: var(--t-interface); color: var(--muted); }
.cv-ia-champ {
  width: 100%; max-width: 360px; padding: var(--esp-2); font: inherit; color: inherit;
  background: var(--surface-creuse); border: 1px solid var(--line); border-radius: var(--r-champ);
}
.cv-bouton:disabled { opacity: 0.5; cursor: not-allowed; }

select.cv-ia-champ { margin-bottom: var(--esp-2); }

/* ---------- Les conseils : « + » veut dire « à gagner » ---------- */
.cv-gain-points { height: auto; padding: 6px 0; line-height: 1.1; }
.cv-gain-points::after {
  content: 'à gagner'; display: block; margin-top: 2px;
  font-family: var(--police-texte); font-size: 0.625rem; font-weight: var(--graisse-moyen);
  letter-spacing: 0; color: var(--muted);
}
.cv-gain-ia { font-size: 0.875rem; color: var(--accent-fonce); }
.cv-ia-acquis { color: var(--succes-texte); }
.cv-ia-lancer { margin-top: var(--esp-2); }

/* ---------- La porte vers l'atelier : une carte fine ---------- */
.cv-atelier-porte {
  display: flex; align-items: center; justify-content: space-between; gap: var(--esp-3);
  margin-top: var(--esp-3); padding: var(--esp-3) var(--esp-4);
  color: inherit; text-decoration: none; background: var(--surface-creuse);
  border: 1px solid var(--line); border-radius: var(--r-champ);
}
.cv-atelier-porte:hover { border-color: var(--accent); }
.cv-atelier-texte { display: grid; gap: 2px; font-size: var(--t-interface); color: var(--muted); }
.cv-atelier-texte strong { color: inherit; font-size: var(--t-corps); }
.cv-atelier-aller { flex: none; font-weight: var(--graisse-moyen); color: var(--accent-fonce); white-space: nowrap; }
@media (max-width: 600px) { .cv-atelier-porte { flex-direction: column; align-items: flex-start; } }


/* ---------- La carte du score, compacte (14 octobre 2026) ----------
   Elle ne porte plus que la note et son verdict : le titre, le duel et la liste
   d'étude sont partis dans la fenêtre d'analyse. Elle garde la hauteur de la carte
   de gauche (même rangée de la grille), son contenu est centré dedans. */
.cv-score { justify-content: center; }
.cv-score .cv-score-corps { margin: var(--esp-3) 0 0; }
.cv-anneau-bloc { width: 164px; height: 164px; }
.cv-ia-info { margin-bottom: var(--esp-2); }
.cv-quota:empty { display: none; }
.cv-quota { font-weight: var(--graisse-moyen); color: var(--accent-fonce); }

/* ---------- La fenêtre d'analyse ---------- */
.cv-scan {
  width: min(760px, 92vw);
  padding: 0; border: 0; background: transparent; color: var(--ink);
  max-width: none; max-height: none; overflow: visible;
}
.cv-scan::backdrop {
  background: rgba(20, 22, 60, 0.58);
  backdrop-filter: blur(3px);
  transition: opacity 240ms linear;
}
.cv-scan.cv-scan-sortie::backdrop { opacity: 0; }
body.cv-scan-ouvert { overflow: hidden; }

.cv-scan-carte {
  padding: var(--esp-5) var(--esp-5) var(--esp-4);
  background: #fff; border-radius: 22px; outline: none;
  box-shadow: 0 28px 80px rgba(20, 22, 60, 0.38), 0 2px 0 rgba(255, 255, 255, 0.6) inset;
  animation: cv-scan-pop 260ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
  transition: opacity 240ms ease, transform 240ms ease;
}
.cv-scan.cv-scan-sortie .cv-scan-carte { opacity: 0; transform: translateY(6px) scale(0.985); }
@keyframes cv-scan-pop { from { opacity: 0; transform: translateY(10px) scale(0.96); } }

.cv-scan-titre { margin: 0; font-size: 1.375rem; line-height: 1.2; text-align: center; }
.cv-scan-etat { margin: 6px 0 0; font-size: var(--t-interface); color: var(--muted); text-align: center; min-height: 1.4em; }
.cv-scan-note { margin: var(--esp-3) 0 0; font-size: 0.8125rem; color: var(--muted); text-align: center; }

.cv-scan-corps {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--esp-5); align-items: center; margin-top: var(--esp-4);
}

/* Les six étapes : à gauche, centrées sur la hauteur du CV. */
.cv-scan-etapes { margin: 0; padding: 0 0 0 var(--esp-2); list-style: none; display: grid; gap: 14px; }
.cv-scan-etape {
  display: flex; align-items: center; gap: 12px;
  font-size: var(--t-corps); color: var(--muted);
  opacity: 0; transform: translateX(-12px);
}
.cv-scan-vue {
  opacity: 1; transform: none;
  transition: opacity 320ms cubic-bezier(0.2, 0.8, 0.2, 1), transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.cv-scan-puce {
  position: relative; flex: none; width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid #CBD0EA; background: #fff;
  transition: background 220ms ease, border-color 220ms ease;
}
.cv-scan-active { color: var(--ink); font-weight: var(--graisse-titre); }
.cv-scan-active .cv-scan-puce { border-color: var(--accent); }
.cv-scan-active .cv-scan-puce::after {
  content: ''; position: absolute; inset: 3px; border-radius: 50%; background: var(--accent);
  animation: cv-scan-pouls 1.1s ease-in-out infinite;
}
.cv-scan-faite { color: var(--ink); }
.cv-scan-faite .cv-scan-puce { background: var(--accent); border-color: var(--accent); }
.cv-scan-faite .cv-scan-puce::after {
  content: ''; position: absolute; left: 5px; top: 1.5px; width: 5px; height: 9px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
@keyframes cv-scan-pouls { 0%, 100% { transform: scale(0.55); opacity: 0.5; } 50% { transform: scale(1); opacity: 1; } }

/* Le faux CV et son faisceau. La couche teintée est dévoilée par le haut jusqu'au
   faisceau : les deux animations ont la même durée et la même courbe, donc elles ne
   se décalent pas. */
.cv-scan-doc { position: relative; width: 100%; max-width: 280px; margin: 0 auto; aspect-ratio: 260 / 340; overflow: hidden; border-radius: 10px; }
.cv-scan-svg { display: block; width: 100%; height: 100%; }
.cv-scan-ombre { fill: #E7E9F5; }
.cv-scan-page { fill: #FAFAFD; stroke: #DDE0EE; }
.cv-scan-bandeau { fill: var(--accent); }
.cv-scan-sigle { fill: #fff; font: 700 21px var(--police-texte, system-ui); letter-spacing: 0.08em; }
.cv-scan-avatar { fill: #DDE1FA; }
.cv-scan-silhouette { fill: var(--accent); opacity: 0.85; }
.cv-scan-frise { stroke: #D3D6E6; stroke-width: 1.5; }
.cv-scan-point { fill: #C5C9DE; }
.cv-scan-ligne { fill: #CDD0DF; }
.cv-scan-titreligne { fill: var(--orange); }
.cv-scan-couche { position: absolute; inset: 0; clip-path: inset(0 0 100% 0); animation: cv-scan-revele 3.4s ease-in-out infinite; }
.cv-scan-couche .cv-scan-ligne { fill: #8D9AF3; }
.cv-scan-couche .cv-scan-point { fill: var(--accent); }
.cv-scan-couche .cv-scan-page, .cv-scan-couche .cv-scan-ombre, .cv-scan-couche .cv-scan-bandeau,
.cv-scan-couche .cv-scan-sigle, .cv-scan-couche .cv-scan-avatar, .cv-scan-couche .cv-scan-silhouette,
.cv-scan-couche .cv-scan-titreligne, .cv-scan-couche .cv-scan-frise { opacity: 0; }

.cv-scan-faisceau {
  position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--orange); border-radius: 2px;
  box-shadow: 0 0 14px 3px rgba(255, 107, 53, 0.5);
  animation: cv-scan-balayage 3.4s ease-in-out infinite;
}
.cv-scan-faisceau::before, .cv-scan-faisceau::after {
  content: ''; position: absolute; left: 0; right: 0; height: 46px; pointer-events: none;
}
.cv-scan-faisceau::before { bottom: 100%; background: linear-gradient(to top, rgba(255, 107, 53, 0.2), transparent); animation: cv-scan-traine-haut 3.4s step-end infinite; }
.cv-scan-faisceau::after { top: 100%; background: linear-gradient(to bottom, rgba(255, 107, 53, 0.2), transparent); animation: cv-scan-traine-bas 3.4s step-end infinite; }
@keyframes cv-scan-balayage { 0%, 100% { top: 0; } 50% { top: calc(100% - 3px); } }
@keyframes cv-scan-revele { 0%, 100% { clip-path: inset(0 0 100% 0); } 50% { clip-path: inset(0 0 0 0); } }
@keyframes cv-scan-traine-haut { 0% { opacity: 1; } 50% { opacity: 0; } }
@keyframes cv-scan-traine-bas { 0% { opacity: 0; } 50% { opacity: 1; } }

@media (max-width: 640px) {
  .cv-scan-carte { padding: var(--esp-4) var(--esp-3) var(--esp-3); }
  .cv-scan-corps { grid-template-columns: 1fr; gap: var(--esp-3); }
  .cv-scan-doc { order: -1; max-width: 170px; }
  .cv-scan-etapes { gap: 10px; padding-left: 0; justify-self: center; }
}

/* Réduire les animations : pas de faisceau, pas de glissement. Les étapes sont posées
   d'un coup (animation-analyse.js) et l'état reste annoncé en texte. */
@media (prefers-reduced-motion: reduce) {
  .cv-scan-carte { animation: none; transition: none; }
  .cv-scan-faisceau { display: none; }
  .cv-scan-couche { animation: none; clip-path: inset(0 0 45% 0); }
  .cv-scan-etape, .cv-scan-vue { transition: none; transform: none; }
  .cv-scan-active .cv-scan-puce::after { animation: none; }
}

/* ---------- Les conseils rangés par importance (14 octobre 2026) ---------- */
.cv-niveau {
  margin: var(--esp-2) 0 0; padding: 0;
  font-size: 0.75rem; font-weight: var(--graisse-moyen); letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted); list-style: none;
}
.cv-niveau:first-child { margin-top: 0; }
.cv-reco-theme {
  display: block; margin: 0 0 2px;
  font-size: 0.6875rem; font-weight: var(--graisse-moyen); letter-spacing: .06em;
  text-transform: uppercase; color: var(--accent-fonce);
}
.cv-facultatif { list-style: none; margin: var(--esp-2) 0 0; padding: 0; }
.cv-facultatif summary { cursor: pointer; font-size: var(--t-interface); font-weight: var(--graisse-moyen); color: var(--muted); }
.cv-facultatif details > .cv-reco { margin-top: var(--esp-2); }

/* ---------- L'échelle de la note : ce que le chiffre veut dire ---------- */
.cv-echelle { width: 100%; max-width: 20rem; margin: var(--esp-3) auto 0; }
.cv-echelle-barre { position: relative; display: flex; gap: 3px; height: 8px; }
.cv-echelle-zone { height: 100%; border-radius: 4px; opacity: 0.45; transition: opacity 240ms ease; }
.cv-echelle-reprendre { flex: 56 1 0; background: #F0866B; }
.cv-echelle-norme { flex: 21 1 0; background: #F2C265; }
.cv-echelle-solide { flex: 23 1 0; background: #55D3A0; }
.cv-echelle[data-zone="reprendre"] .cv-echelle-reprendre,
.cv-echelle[data-zone="norme"] .cv-echelle-norme,
.cv-echelle[data-zone="solide"] .cv-echelle-solide,
.cv-echelle[data-zone=""] .cv-echelle-zone { opacity: 1; }
.cv-echelle-repere {
  position: absolute; top: -4px; width: 4px; height: 16px; margin-left: -2px;
  background: #fff; border-radius: 2px; box-shadow: 0 0 0 2px var(--nuit);
  transition: left 600ms var(--ease-sortie);
}
.cv-echelle-legende { display: flex; justify-content: space-between; gap: var(--esp-1); margin: 8px 0 0; padding: 0; list-style: none; }
.cv-echelle-legende li { display: grid; gap: 1px; font-size: 0.6875rem; color: var(--sur-nuit-doux); text-align: center; flex: 1; }
.cv-echelle-legende b { font-family: var(--police-chiffres); font-weight: var(--graisse-moyen); color: var(--sur-nuit); }
.cv-echelle[data-zone="reprendre"] li:not([data-zone="reprendre"]),
.cv-echelle[data-zone="norme"] li:not([data-zone="norme"]),
.cv-echelle[data-zone="solide"] li:not([data-zone="solide"]) { opacity: 0.5; }

/* ---------- L'introduction de la page : trois lignes, pas deux gros paragraphes ---------- */
.cv-intro { margin: 0 0 var(--esp-5); }
.cv-intro .cv-titre { font-size: clamp(2rem, 4.2vw, 2.75rem); margin-bottom: var(--esp-2); }
.cv-trois { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--esp-2); margin: 0; padding: 0; list-style: none; }
.cv-trois-etape {
  display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px;
  background: var(--surface-creuse); border-radius: var(--r-champ);
}
.cv-trois-num {
  flex: none; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  font-size: 0.8125rem; font-weight: var(--graisse-titre); color: var(--sur-bleu); background: var(--accent);
}
.cv-trois-texte { display: grid; gap: 2px; font-size: 0.8125rem; line-height: 1.45; color: var(--muted); }
.cv-trois-texte strong { font-size: var(--t-interface); color: var(--ink); }
@media (max-width: 720px) {
  .cv-trois { grid-template-columns: 1fr; }
  .cv-trois-etape { padding: 10px 12px; }
}

/* Emporter ses données : un lien-bouton discret sous l'historique, jamais un appel à l'action. */
.cv-exporter { min-height: 44px; margin-top: var(--esp-2); padding: 0; font: inherit; font-size: var(--t-interface); color: var(--blue-dark); background: none; border: 0; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.cv-exporter:disabled { opacity: .5; cursor: progress; }
.cv-exporter:focus-visible { outline: none; box-shadow: var(--focus-anneau); }
