/* 24-utilitaires.css — ajouté au Sprint 17A.
   Classes utilitaires minimales, exclusivement basées sur les design tokens,
   pour remplacer les styles en ligne de index.html. Ces derniers
   contournaient les tokens et échappaient au garde-fou automatique
   (qui n'inspecte que les fichiers CSS, pas les attributs HTML).

   Nouveau fichier plutôt que modification des 23 existants : aucun risque
   de régression sur la cascade, et le découpage validé reste intact. */

/* --- Espacements verticaux ------------------------------------------ */
.mt-0{ margin-top:0; }
.mt-3{ margin-top:var(--space-3); }
.mt-4{ margin-top:var(--space-4); }
.mt-5{ margin-top:var(--space-5); }
.mt-6{ margin-top:var(--space-6); }
.mt-10{ margin-top:var(--space-10); }

.mb-3{ margin-bottom:var(--space-3); }
.mb-5{ margin-bottom:var(--space-5); }

.ml-3{ margin-left:var(--space-3); }

/* --- Dispositions courtes ------------------------------------------- */
.ligne-actions{
    display:flex;
    gap:var(--space-3);
    margin-top:var(--space-6);
    flex-wrap:wrap;
}

.ligne-champ{
    display:flex;
    gap:var(--space-3);
    align-items:flex-start;
}

.ligne-inline{
    display:flex;
    gap:var(--space-3);
    margin-top:var(--space-4);
    flex-wrap:wrap;
}

.champ-extensible{ flex:1; }

.texte-fort{
    font-weight:600;
    margin-bottom:var(--space-3);
}

/* --- Encart secondaire (formulaire imbriqué, aide contextuelle) ------ */
.encart{
    grid-column:1 / -1;
    background:var(--surface-muted);
    padding:var(--space-4);
    border-radius:var(--radius-md);
}

body.dark .encart{
    background:#334155;
}

/* --- État « Bientôt disponible » ------------------------------------
   Présentation unique pour toutes les fonctionnalités annoncées mais non
   opérationnelles. Sans repère visuel explicite, un bouton inerte est
   interprété comme un bug — surtout en bêta ouverte. */
.bientot{
    display:flex;
    flex-direction:column;
    align-items:center;
    text-align:center;
    gap:var(--space-3);
    padding:var(--space-8) var(--space-5);
    background:var(--surface-muted);
    border:1px dashed var(--border);
    border-radius:var(--radius-lg);
    color:var(--text-light);
}

.bientot i{
    font-size:32px;
    color:var(--primary);
    opacity:.5;
}

.bientot strong{
    color:var(--text);
    font-size:16px;
}

.bientot p{
    max-width:460px;
    font-size:14px;
}

body.dark .bientot{
    background:#1e293b;
    border-color:#334155;
}

/* Badge « Bientôt » à accoler à un titre de section */
.badge-bientot{
    font-size:11px;
    font-weight:700;
    text-transform:uppercase;
    padding:var(--space-1) var(--space-3);
    border-radius:var(--radius-full);
    background:var(--badge-attente-fond);
    color:var(--badge-attente-texte);
    white-space:nowrap;
    vertical-align:middle;
    margin-left:var(--space-3);
}

/* =====================================================================
   V3, Cycle 9 — Résumé de simulation
   Hiérarchie : le verdict et le score priment sur tout le reste.
   ===================================================================== */

.resume-simulation{
    background:var(--surface-muted);
    border:1px solid var(--border);
    border-radius:var(--radius-xl);
    padding:var(--space-6);
    margin-bottom:var(--space-6);
}

.resume-entete{
    display:flex;
    align-items:center;
    gap:var(--space-5);
    flex-wrap:wrap;
    margin-bottom:var(--space-5);
}

.verdict-pastille{
    font-weight:700;
    font-size:18px;
    padding:var(--space-2) var(--space-4);
    border-radius:var(--radius-full);
    border:2px solid currentColor;
}
.verdict-excellent{ color:var(--texte-success); }
.verdict-bon{ color:var(--primary); }
.verdict-vigilance{ color:var(--texte-warning); }
.verdict-insuffisant{ color:var(--danger-texte); }

.score-bloc{ display:flex; align-items:baseline; gap:var(--space-2); }
.score-valeur{ font-size:34px; font-weight:800; line-height:1; }
.score-total{ color:var(--text-light); font-size:15px; }

/* Jauge d'objectif : la barre est bornée à 100 % même en cas de
   dépassement — au-delà, c'est l'écart chiffré qui porte l'information. */
.jauge-objectif{
    background:var(--border);
    border-radius:var(--radius-full);
    height:12px;
    overflow:hidden;
    margin:var(--space-3) 0 var(--space-2);
}
.jauge-remplissage{
    height:100%;
    border-radius:var(--radius-full);
    background:var(--primary);
    transition:width .3s ease;
}
.jauge-atteinte{ background:var(--success); }

.resume-phrase{ margin:var(--space-2) 0; line-height:1.6; }

/* Analyse : ce qui va bien, ce qui mérite attention. */
.analyse-colonnes{
    display:grid;
    grid-template-columns:repeat(auto-fit, minmax(280px, 1fr));
    gap:var(--space-5);
    margin-bottom:var(--space-6);
}
.analyse-bloc{
    background:var(--surface-muted);
    border-radius:var(--radius-lg);
    padding:var(--space-5);
    border-left:4px solid var(--border);
}
.analyse-forces{ border-left-color:var(--success); }
.analyse-vigilances{ border-left-color:var(--warning); }
.analyse-bloc h4{ margin:0 0 var(--space-3); font-size:15px; }
.analyse-bloc ul{ margin:0; padding-left:var(--space-5); }
.analyse-bloc li{ margin-bottom:var(--space-2); line-height:1.5; }

/* Décomposition : du chiffre d'affaires au net, étape par étape. */
.decomposition-etape{
    display:flex;
    justify-content:space-between;
    align-items:center;
    gap:var(--space-4);
    padding:var(--space-3) var(--space-4);
    border-bottom:1px solid var(--border);
}
.decomposition-etape:last-child{ border-bottom:none; }
.decomposition-total{
    font-weight:700;
    background:var(--surface-muted);
    border-radius:var(--radius-md);
}
.decomposition-montant{ font-variant-numeric:tabular-nums; font-weight:600; }
.decomposition-retrait{ color:var(--danger-texte); }

/* Leviers classés : le rang est l'information principale. */
.levier-rang{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:26px;
    height:26px;
    border-radius:var(--radius-circle);
    background:var(--primary);
    color:var(--encre-bouton-plein);
    font-weight:700;
    font-size:14px;
    margin-right:var(--space-2);
}

.combinaison-ligne{
    display:flex;
    justify-content:space-between;
    padding:var(--space-3) var(--space-4);
    border-bottom:1px solid var(--border);
}
.combinaison-ligne:last-child{ border-bottom:none; }

/* =====================================================================
   FOCUS CLAVIER
   Relevé en revue d'accessibilité : aucune règle :focus-visible n'existait
   dans le projet. Le contour par défaut du navigateur restait actif — la
   navigation clavier n'était donc pas rompue — mais il varie d'un
   navigateur à l'autre et disparaît sur les fonds colorés.
   :focus-visible plutôt que :focus : l'anneau n'apparaît qu'à la
   navigation clavier, pas au clic à la souris.
   ===================================================================== */
:focus-visible{
    outline:2px solid var(--primary);
    outline-offset:2px;
    border-radius:var(--radius-xs);
}

/* Sur un bouton déjà bleu, un anneau bleu ne se voit pas : on l'écarte
   d'un liseré clair pour qu'il reste lisible dans les deux thèmes. */
.primary-button:focus-visible,
.menu-item.active:focus-visible{
    outline-color:var(--text);
    box-shadow:0 0 0 2px var(--surface);
}

/* Le témoin et la bascule vivent dans le champ : leur anneau doit rester
   à l'intérieur, sinon il déborde sur la bordure du champ. */
.bascule-mdp:focus-visible{ outline-offset:0; }

/* Les bascules de Paramètres — Cycle 132.
   L'élément qui reçoit le focus est l'`<input type="checkbox">`, que
   `17-toggle-switch.css` met en `opacity:0` et en 0×0 pour laisser voir le
   `.slider` à sa place. L'anneau ci-dessus s'y peignait donc bel et bien,
   sur une boîte sans surface et entièrement transparente : personne ne le
   voyait. Sept arrêts de tabulation sans curseur visible dans Paramètres.
   On reporte l'anneau sur `.slider`, la seule partie que l'œil voit. */
.switch input:focus-visible + .slider{
    outline:2px solid var(--primary);
    outline-offset:2px;
}

/* Bascule allumée, le curseur est déjà `--primary` : un anneau de la même
   couleur s'y fondrait. Même geste qu'au-dessus pour `.primary-button`. */
.switch input:checked:focus-visible + .slider{
    outline-color:var(--text);
}

/* Lien d'évitement : la première tabulation d'une page permet d'aller
   droit au contenu sans traverser tout le menu latéral.

   V3, Cycle 130 — IL DÉPASSAIT, et c'était de l'arithmétique.

   Il était remonté hors de l'écran par `top: calc(-1 * var(--space-10))`,
   soit −40 px. Or il mesure environ 48 px de haut : 12 px de marge
   intérieure en haut, 12 en bas, la ligne de texte et la bordure. Une
   dizaine de pixels restaient donc visibles en haut à gauche, en
   permanence, sur toutes les pages.

   Le défaut n'est pas la valeur, c'est la MÉTHODE : un nombre fixe ne
   peut pas masquer un élément dont il ne connaît pas la hauteur. Changer
   40 en 100 marcherait aujourd'hui et casserait au prochain changement de
   police ou de marge intérieure.

   `translateY(-200%)` se mesure sur la hauteur de l'élément lui-même :
   quelle que soit sa taille, il est dehors. C'est la seule écriture qui
   ne redevient pas fausse toute seule.

   Il n'est PAS supprimé, malgré la gêne visuelle qu'il causait : c'est le
   seul moyen pour qui navigue au clavier d'atteindre le contenu sans
   traverser les sept entrées du menu à chaque page (WCAG 2.4.1). Le
   rendre invisible était le vrai correctif ; le retirer aurait échangé un
   défaut d'affichage contre un défaut d'accès. */
.lien-evitement{
    position:absolute;
    left:var(--space-4);
    top:var(--space-4);
    transform:translateY(-200%);
    z-index:10002;
    padding:var(--space-3) var(--space-4);
    background:var(--surface);
    color:var(--text);
    border:1px solid var(--border);
    border-radius:var(--radius-md);
    box-shadow:var(--ombre-panneau);
    font-weight:600;
    text-decoration:none;
    transition:transform .15s ease;
}

.lien-evitement:focus{
    transform:translateY(0);
}

/* ---------------------------------------------------------------------
   Un échec de chargement — V3, Cycle 18.

   Même famille que .empty-hint, parce que c'est le même emplacement et
   le même moment de lecture ; une couleur d'alerte, parce que ce n'est
   pas la même nouvelle. L'ambre plutôt que le rouge : la donnée n'est
   pas perdue, elle n'a pas pu être lue.
   --------------------------------------------------------------------- */
/* `display:flex` ci-dessous écraserait l'attribut `hidden`. Les messages
   d'indisponibilité des graphiques (Cycle 31) portent précisément cet
   attribut : sans cette règle, ils restaient affichés en permanence.
   La vérification en navigateur ne l'avait pas vu — le message était
   vide quand Chart.js répondait, donc invisible en pratique. */
.empty-hint--echec[hidden]{ display:none; }

/* V3, Cycle 124 — `display:flex` sur un PARAGRAPHE.
   
   Cette règle a été écrite pour de courts messages d'échec d'une seule
   ligne, où le flex sert à aligner un pictogramme. Appliquée à un
   paragraphe contenant du balisage inline, elle fait de CHAQUE `<strong>`
   et de chaque morceau de texte un élément de flex : le paragraphe se
   brise en colonnes, et les espaces entre les éléments disparaissent.
   
   Constaté à l'écran sur la page Confidentialité, par capture. Je l'avais
   d'abord déclaré inexistant après avoir lu le balisage — le balisage
   était correct, et le rendu ne l'était pas. Une lecture est une
   hypothèse ; l'exécution en fait un fait, et un écran est une exécution.
   
   `display:flex` est conservé pour l'usage prévu, et
   `.avertissement-responsabilite` existe pour le texte long. */
/* V3, Cycle 135 — l'encre, pas l'aplat. Cette règle portait
   `var(--warning)` : #f59e0b sur une surface blanche donne 2,15:1,
   contre 4,5 exigés. La phrase qui rassure quelqu'un devant un écran
   vide — « Rien n'est perdu : c'est la lecture qui a échoué » — était
   la moins lisible du produit. Mesuré dans un navigateur : le thème
   sombre allait bien (9,86:1), parce qu'il éclaircit ses accents.
   Le défaut ne vivait que le jour. */
.empty-hint--echec{
    color:var(--texte-warning);
    font-weight:500;
    display:flex;
    align-items:center;
    gap:var(--space-2);
    margin-bottom:var(--space-3);
}

/* Un avertissement qui est un PARAGRAPHE, pas une ligne d'état : il garde
   le flux du texte, donc ses espaces et ses retours à la ligne.
   
   V3, Cycle 125 — il était en `--warning`, l'orange d'alerte, sur cinq
   lignes de texte suivi. Une couleur saturée tenue sur un paragraphe
   entier fatigue à la lecture et annonce une urgence qui n'existe pas :
   ce texte dit une responsabilité, pas un incident.
   
   Il reste distingué — filet latéral dans la couleur d'identité du
   produit, fond légèrement détaché — et il se lit. */
.avertissement-responsabilite{
    margin-bottom:var(--space-4);
    padding:var(--space-3) var(--space-4);
    border-left:3px solid var(--primary);
    border-radius:var(--radius-xs);
    background:var(--surface-muted);
    font-size:14px;
    line-height:1.65;
    color:var(--text);
}

/* ---------------------------------------------------------------------
   Un graphique borné — V3, Cycle 25.

   Chart.js est responsive : sans borne, l'anneau du Simulateur occupe
   toute la largeur du panneau. La valeur était en style en ligne dans
   le balisage depuis le Cycle 4c, dont la clôture le signalait déjà :
   « efficace, et ce n'est pas le design system du projet ».
   --------------------------------------------------------------------- */
.graphique-borne{
    max-width:300px;
    margin:0 auto var(--space-6);
}

/* Visible des seuls lecteurs d'écran. Ajouté avec le module « Simulation
   avancée », qui a des tableaux dont la légende doit être annoncée sans
   être affichée — mais la classe n'est pas propre à ce module. */
.sr-only{
    position:absolute;
    width:1px; height:1px;
    padding:0; margin:-1px;
    overflow:hidden;
    clip:rect(0 0 0 0);
    white-space:nowrap;
    border:0;
}

/* Le bloc « repartir » du tableau de bord. Trois actions graduées, dont
   une seule est destructive — et elle est la seule à porter le style de
   danger. Une remise à zéro qui ressemble à une suppression pousse à
   supprimer par erreur. */
/* L'attribut `hidden` pose `display:none` avec une spécificité nulle :
   toute règle de classe qui déclare un `display` l'écrase. Le bloc restait
   donc visible malgré `hidden`, et les trois boutons — dont l'effacement
   définitif — s'affichaient à quelqu'un qui venait de créer son compte.
   Le piège vaut pour toute classe qui déclare un display. */
.reprise[hidden]{ display:none; }

.reprise{
    display:flex;
    flex-wrap:wrap;
    gap:var(--space-2);
    align-items:center;
    margin-bottom:var(--space-4);
    padding-bottom:var(--space-4);
    border-bottom:1px solid var(--border);
}

.reprise button{ flex:0 0 auto; }

.reprise .empty-hint{
    flex:1 1 100%;
    margin:var(--space-2) 0 0;
}

@media (max-width: 600px){
    .reprise button{ flex:1 1 100%; }
}

/* L'icône de marque. Elle remplace un glyphe de police aux deux endroits
   où l'application affiche son identité — et depuis que FontAwesome est
   hors du chemin critique, elle a l'avantage d'être là tout de suite,
   là où le glyphe attendait sa feuille externe. */
.marque-icone{
    display:block;
    border-radius:var(--radius-md);
    object-fit:contain;
    flex:0 0 auto;
}

/* V3, Cycle 91 — les blocs de l'inventaire des données personnelles, sur la
   page Confidentialité. Un séparateur et un peu d'air : la liste est longue
   par nature — c'est le sujet — et sans respiration elle ne serait pas lue. */
.bloc-inventaire{
    border-top:1px solid var(--border);
    padding-top:var(--space-4);
    margin-top:var(--space-4);
}
.bloc-inventaire:first-child{ border-top:none; padding-top:0; margin-top:0; }
.bloc-inventaire h4{ margin:0 0 var(--space-1); font-size:15px; }
.bloc-inventaire ul{ margin:var(--space-2) 0 0; padding-left:var(--space-5); }
.bloc-inventaire li{ margin-bottom:var(--space-1); }

/* V3, Cycle 92 — la liste des personnes qu'il reste à informer, sur la page
   Confidentialité. Le liseré de gauche porte l'urgence : rouge au-delà du mois
   prévu par l'article 14, ambre quand il approche. Une liste sans hiérarchie
   visuelle se lit du haut vers le bas jusqu'à ce qu'on se lasse. */
.liste-a-informer{ list-style:none; margin:var(--space-3) 0 0; padding:0; }
.ligne-a-informer{
    display:flex;
    justify-content:space-between;
    align-items:center;
    gap:var(--space-4);
    padding:var(--space-3);
    border-left:3px solid var(--border);
    border-bottom:1px solid var(--border);
}
.ligne-a-informer[data-urgence="depasse"]{ border-left-color:#dc2626; }
.ligne-a-informer[data-urgence="bientot"]{ border-left-color:#f59e0b; }
.ligne-a-informer[data-urgence="inconnue"]{ border-left-color:#6b7280; }

/* V3, Cycle 93 — les deux gestes d'une ligne « à informer » : préparer le
   message, puis marquer comme fait. Ils vont ensemble et se lisent de gauche
   à droite dans l'ordre où on les fait. */
.gestes-a-informer{ display:flex; gap:var(--space-2); flex-shrink:0; }

/* ---------------------------------------------------------------------
   L'AVERTISSEMENT D'UN RÉFÉRENTIEL — V3, Cycle 129.

   Deux natures dans un même bloc : ce qu'il faut LIRE, et ce qui rend le
   chiffre VÉRIFIABLE. Elles étaient collées en une seule coulée sur trois
   écrans. Deux lignes, deux tailles, deux couleurs : l'œil sait où
   s'arrêter s'il ne veut que l'essentiel.
   --------------------------------------------------------------------- */
.avertissement-referentiel{
    display:block;
    max-width:68ch;
    margin:var(--space-2) 0 0;
}

.avertissement-referentiel__dit{
    display:block;
    font-size:13px;
    line-height:1.6;
    color:var(--text-light);
}

/* Deux réserves l'une sous l'autre — la Simulation avancée en affiche deux,
   d'origines différentes. Sans cet espace elles se lisent comme une seule. */
.avertissement-referentiel__dit + .avertissement-referentiel__dit{
    margin-top:var(--space-2);
}

.avertissement-referentiel__source{
    display:block;
    margin-top:var(--space-1);
    font-size:12px;
    line-height:1.5;
    color:var(--text-placeholder);
}
