/* ============================================================================
   preferences.css — TOUTES les préférences système, rassemblées et chargées EN
   DERNIER.

   Pourquoi ce fichier existe : une media query n'ajoute **aucune** spécificité.
   Une règle écrite sous `@media (forced-colors: active)` dans un fichier chargé
   tôt se fait écraser, à spécificité égale, par n'importe quelle règle
   inconditionnelle déclarée plus loin dans la cascade. Elle est alors parsée,
   visible dans le CSSOM, et sans le moindre effet.

   Mesuré ici le 2026-08-07 : la première version de cette page portait
   **95 déclarations de préférence mortes** pour cette raison exacte. Elles
   avaient l'air correctes dans le code et ne s'appliquaient jamais.

   Règle : rien de conditionnel à une préférence ne vit ailleurs que dans ce
   fichier, et ce fichier est le dernier chargé.
   ============================================================================ */

/* ---------------------------------------------------------- contraste accru --
   ATTENTION — piège corrigé le 2026-08-07, après mesure sur les pixels rendus.
   Ces deux blocs mettaient `--surface-glass-film: transparent`, en croyant
   « supprimer la transparence ». C'était l'INVERSE de l'effet voulu : ce token
   n'est pas un effet décoratif posé SUR une surface, c'est le fond de la barre
   collante lui-même. Le passer à `transparent` retirait le voile et laissait le
   dégradé d'ambiance remonter sous le texte — `--text-faint` y tombait à 4,27:1,
   sous le seuil AA. Autrement dit : l'utilisateur qui demandait PLUS de contraste
   en obtenait MOINS, et sur l'élément le plus permanent de la page.
   La règle juste : sous ces préférences, le film devient OPAQUE. */
@media (prefers-contrast: more) {
  :root {
    --surface-glass: var(--surface);
    --surface-glass-film: var(--bg-elev);   /* opaque, jamais `transparent` */
    --border: rgba(255, 255, 255, 0.32);
    --border-strong: rgba(255, 255, 255, 0.48);
    --text-muted: var(--text);
    --text-faint: var(--text);
  }
}

/* ---- transparence réduite. Contrairement à ce que notait la version précédente,
   ce n'est PAS une simple amélioration facultative : Chromium l'active par défaut
   en mode sans interface, donc c'est un chemin de rendu réellement emprunté, et
   il doit être aussi lisible que le chemin par défaut. ---- */
@media (prefers-reduced-transparency: reduce) {
  :root {
    --surface-glass: var(--surface);
    --surface-glass-film: var(--bg-elev);   /* opaque, jamais `transparent` */
  }
}

/* ============================================================== mouvement === */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;   /* 0.01ms et jamais 0 : préserve transitionend */
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* État FINAL immédiat, jamais un contenu amputé : la page reste entière,
     seul le déplacement disparaît. */
  .js [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .aura::before, .aura::after { animation: none !important; }
  .prose a { text-decoration-color: currentColor !important; }
}

/* ========================================================= couleurs forcées ==
   Windows contraste élevé. En mode actif, `box-shadow`, `text-shadow` et les
   `background-image` non-URL passent à `none` : tout ce qui signale un état par
   une lueur ou un dégradé devient invisible.
   Les sélecteurs ci-dessous sont DÉLIBÉRÉMENT dupliqués (`.lvl.lvl`) pour
   passer devant les modificateurs de même spécificité déclarés dans
   components.css — c'est le correctif exact des 95 règles mortes.
   ============================================================================ */
@media (forced-colors: active) {
  :root { --focus: Highlight; }

  :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }

  /* Le bouton principal ne repose plus sur son dégradé : il lui faut une bordure. */
  .btn--primary.btn--primary {
    border: 2px solid ButtonText;
    background: ButtonFace;
    background-image: none;
    color: ButtonText;
    box-shadow: none;
    forced-color-adjust: none;
  }
  .btn--ghost.btn--ghost { border: 1px solid ButtonText; color: ButtonText; }

  /* Les marqueurs de fiabilité ne peuvent plus se distinguer par la couleur.
     Ce n'est pas grave : chacun porte son mot écrit ET une forme distincte,
     et la forme survit au mode contraste élevé. */
  .lvl.lvl { border: 1px solid CanvasText; background: Canvas; background-image: none; color: CanvasText; }

  .card.card, .rule.rule, .tool.tool, .table-wrap, .callout.callout,
  .versus.versus, .versus__side, .param, .check__visuel, .disclaimer, .legende {
    border: 1px solid CanvasText;
    background: Canvas;
    background-image: none;
    box-shadow: none;
  }
  .rule.rule { border-inline-start-width: 4px; }

  /* Les nappes de lumière n'ont plus de sens et parasiteraient le contraste système. */
  .aura, .aura__grain { display: none !important; }
  .card::after, .rule::after { display: none; }

  .gauge__fill { background: Highlight; background-image: none; }
  .timeline::before { background: CanvasText; }
  .timeline li::before { border-color: CanvasText; background: Canvas; }

  .toc a[aria-current="true"] { background: Highlight; color: HighlightText; }
  .tab[aria-selected="true"] { background: Highlight; color: HighlightText; border-color: Highlight; }
  .motion-ctl.motion-ctl { border: 1px solid ButtonText; color: ButtonText; background: ButtonFace; }
  .motion-ctl__dot { background: ButtonText; }
}
