/* ══════════════════════════════════════════════════════════
   shared.css — Styles communs à tous les outils Partithèque
   Partithèque AGSE · Bleu marine + lavande
══════════════════════════════════════════════════════════ */
/* Les polices sont chargées via <link> dans le <head> de chaque page (voir
   charte graphique § Polices), PAS via @import ici : un @import en tête de
   feuille de style force le navigateur à attendre d'avoir téléchargé ET
   analysé shared.css avant de découvrir qu'il faut aussi aller chercher les
   polices sur un autre domaine — deux allers-retours réseau strictement en
   série avant le premier texte lisible. Avec un <link rel="preconnect"> puis
   <link rel="stylesheet"> dans le <head>, les deux requêtes partent en
   parallèle dès l'analyse du HTML, sans attendre shared.css.
   NE PAS remettre cet @import : il annulerait ce gain sur toutes les pages. */

/* Transition fondue automatique du navigateur entre deux pages du site
   (navigation inter-documents) — étendu à toutes les pages (Joseph).
   Chrome/Edge uniquement pour l'instant ; sans effet ni erreur ailleurs, la
   navigation s'y comporte simplement comme avant. */
@view-transition { navigation: auto; }

:root {
  --navy:        #1e2d5a;
  --navy-light:  #2c4278;
  --navy-pale:   #e8ecf5;
  --lavender:    #e8e7f4;
  --lavender2:   #d4d2eb;
  --lavender3:   #b8b5de;
  --white:       #ffffff;
  --surface:     #eeecf8;
  --border:      #dddaf0;
  --text:        #1a1a2e;
  --text-2:      #4a5070;
  --text-3:      #8085a0;
  --green:       #1a6b3a;
  --green-bg:    #e3f5eb;
  --green-border: rgba(26,107,58,0.30);
  --blue:        #1a5fa0;
  --blue-bg:     #e3eef8;
  --gold:        #7a5200;
  --gold-bg:     #fdf3dc;
  --gold-border: #e8c866;   /* bordure du badge "non numéroté" */
  --red:         #b02020;
  --red-bg:      #fce8e8;
  --neutral-bg:  #f5f5f5;   /* fond du badge sans fichier */
  --neutral:     #999999;   /* texte du badge sans fichier */
  --neutral-border: #e0e0e0;/* bordure du badge sans fichier */
  --accent:      #5b4fcf;
  --accent-pale: #eeecfb;
  --c-voix:    #5b4fcf;  --c-voix-bg:    rgba(91,79,207,0.07);  --c-voix-border:    rgba(91,79,207,0.30);
  --c-etiq:    #b86000;  --c-etiq-bg:    rgba(184,96,0,0.07);   --c-etiq-border:    rgba(184,96,0,0.30);
  --c-themes:  #7a5200;  --c-themes-bg:  rgba(122,82,0,0.07);   --c-themes-border:  rgba(122,82,0,0.28);
  --c-dispo:   #1a6b3a;  --c-dispo-bg:   rgba(26,107,58,0.07);  --c-dispo-border:   rgba(26,107,58,0.28);
  --c-recueil: #b02020;  --c-recueil-bg: rgba(176,32,32,0.07);  --c-recueil-border: rgba(176,32,32,0.28);
  --c-langue:  #008078;  --c-langue-bg:  rgba(0,128,120,0.07);  --c-langue-border:  rgba(0,128,120,0.30);
  --c-audio:   #a13670;  --c-audio-bg:   rgba(161,54,112,0.07); --c-audio-border:   rgba(161,54,112,0.30);
  --c-audio-dark: #822a5a;  /* hover audio sélectionné */
  --radius:    8px;
  /* Dropdown hover thématique — chaque groupe colore son propre hover.
     Les couleurs sont celles définies par --c-<groupe> ci-dessus.
     Règle générale : hover = var(--c-<groupe>-bg), texte = var(--c-<groupe>).
     Défini dans style.css (catalogue) et saisie.css (saisie) via .filter-group.grp-* */
  --shadow:    0 2px 12px rgba(30,45,90,0.10);
  --shadow-lg: 0 8px 32px rgba(30,45,90,0.16);
  --font-sans: 'DM Sans', system-ui, sans-serif;
  --font-serif:'Source Serif 4', Georgia, serif;
  --font-mono: 'JetBrains Mono', monospace;
  /* Typographic scale */
  --fs-xs:   0.68rem;   /* labels, numéros, section-titles uppercase */
  --fs-sm:   0.75rem;   /* badges, meta, footer */
  --fs-base: 0.82rem;   /* corps principal, boutons, détail */
  --fs-md:   0.88rem;   /* autocomplete, inputs */
  --fs-lg:   0.95rem;   /* titres de morceaux, search input */
  /* Radius tokens */
  --radius-sm:   6px;   /* inputs, dropdowns, accordions */
  --radius-pill: 20px;  /* boutons, chips, badges pill */
  /* Additional colors */
  --surface-soft:  #f0eef9;  /* séparateurs subtils, zebra */
  --color-mark:    #ffe082;  /* surbrillance recherche */
  --c-voix-dark:   #4a3fb8;  /* hover voix selected */
  --c-recueil-dark:#8b1a1a;  /* hover recueil selected */
  --c-dispo-dark:  #145530;  /* hover dispo selected */

  /* ── Couleurs complémentaires (étape « jetons », 10 nov. 2026) : plus aucune couleur écrite en dur dans style.css / shared.css, hors impression ── */
  --hero-end:      #3a3080;   /* Violet : fin du dégradé de l’en-tête (.hero) */
  --c-unnum:       #f5d060;   /* Jaune clair : texte du badge « non numéroté » sur l’en-tête sombre de la fiche */
  --c-unnum-bg: rgba(245,208,96,0.18);   /* Fond du badge « non numéroté » (en-tête sombre) */
  --c-unnum-border: rgba(245,208,96,0.45);   /* Bordure du badge « non numéroté » (en-tête sombre) */
  --white-0: rgba(255,255,255,0);   /* Blanc totalement transparent (fin de dégradé) */
  --white-08: rgba(255,255,255,0.08);   /* Blanc transparent à 8 % */
  --white-15: rgba(255,255,255,0.15);   /* Blanc transparent à 15 % */
  --white-22: rgba(255,255,255,0.22);   /* Blanc transparent à 22 % */
  --white-30: rgba(255,255,255,0.3);   /* Blanc transparent à 30 % */
  --white-40: rgba(255,255,255,0.4);   /* Blanc transparent à 40 % */
  --white-55: rgba(255,255,255,0.55);   /* Blanc transparent à 55 % */
  --white-65: rgba(255,255,255,0.65);   /* Blanc transparent à 65 % */
  --white-75: rgba(255,255,255,0.75);   /* Blanc transparent à 75 % */
  --white-90: rgba(255,255,255,0.9);   /* Blanc transparent à 90 % */
  --black-06: rgba(0,0,0,0.06);   /* Noir à 6 % (survol discret) */
  --black-30: rgba(0,0,0,0.3);   /* Noir à 30 % (ombres des volets) */
  --navy-0: rgba(30,45,90,0);   /* Marine totalement transparent (départ d’animation d’ombre) */
  --navy-10: rgba(30,45,90,0.1);   /* Marine à 10 % (ombres légères, survol de carte) */
  --navy-16: rgba(30,45,90,0.16);   /* Marine à 16 % (ombres de survol) */
  --navy-20: rgba(30,45,90,0.2);   /* Marine à 20 % (bordure du badge de langue) */
  --navy-30: rgba(30,45,90,0.3);   /* Marine à 30 % (ombre du bouton retour en haut) */
  --scrim: rgba(12,17,38,0.50);   /* Voile derrière les fenêtres et volets */
  --scrim-strong: rgba(10,16,40,0.72);   /* Voile fort (fenêtre modale plein écran) */
  --lavender3-35: rgba(184,181,222,0.35);   /* Anneau de focus des champs (lavande 3 à 35 %) */
  --c-dispo-a15:   rgba(26,107,58,0.15);   /* Groupe « dispo » à 15 % : bouton d’ajout, comparatif (ajouts) */
  --fab-off:       #9098b0;   /* Gris-bleu : bouton flottant ➕ inactif (saisie) */
  --gold-dark:     #5e3f00;   /* Or foncé : survol du bouton flottant orange (saisie) */
  --mark-35:       rgba(255,200,0,0.35);   /* Surlignage jaune d’un mot dans le comparatif de descriptions */
  --nbsp-bg:       rgba(70,130,220,0.28);   /* Espace insécable rendue visible (comparatif de descriptions) */
  --spell-wave:    #ee0055;   /* Soulignement ondulé du correcteur orthographique (saisie) */
  --text-muted:    #666677;   /* Texte atténué (outil Description YouTube) */
  --yt-red:        #c0392b;   /* Rouge du lien « YouTube » (couleur de marque du tiers) */
  --yt-red-dark:   #922b21;   /* Rouge YouTube foncé : survol du lien */
  --c-voix-a25: rgba(91,79,207,0.25);   /* Groupe « voix » à 25 % : fond des pastilles de filtre actif */
  --c-voix-a50: rgba(91,79,207,0.5);   /* Groupe « voix » à 50 % : bordure des pastilles de filtre actif */
  --c-etiq-a15: rgba(184,96,0,0.15);   /* Groupe « etiq » à 15 % : survol des pastilles */
  --c-etiq-a25: rgba(184,96,0,0.25);   /* Groupe « etiq » à 25 % : fond des pastilles de filtre actif */
  --c-etiq-a50: rgba(184,96,0,0.5);   /* Groupe « etiq » à 50 % : bordure des pastilles de filtre actif */
  --c-themes-a15: rgba(122,82,0,0.15);   /* Groupe « themes » à 15 % : survol des pastilles */
  --c-themes-a25: rgba(122,82,0,0.25);   /* Groupe « themes » à 25 % : fond des pastilles de filtre actif */
  --c-themes-a50: rgba(122,82,0,0.5);   /* Groupe « themes » à 50 % : bordure des pastilles de filtre actif */
  --c-dispo-a25: rgba(26,107,58,0.25);   /* Groupe « dispo » à 25 % : fond des pastilles de filtre actif */
  --c-dispo-a50: rgba(26,107,58,0.5);   /* Groupe « dispo » à 50 % : bordure des pastilles de filtre actif */
  --c-recueil-a15: rgba(176,32,32,0.15);   /* Groupe « recueil » à 15 % : survol des pastilles */
  --c-recueil-a25: rgba(176,32,32,0.25);   /* Groupe « recueil » à 25 % : fond des pastilles de filtre actif */
  --c-recueil-a50: rgba(176,32,32,0.5);   /* Groupe « recueil » à 50 % : bordure des pastilles de filtre actif */
  --c-langue-a15: rgba(0,128,120,0.15);   /* Groupe « langue » à 15 % : survol des pastilles */
  --c-langue-a25: rgba(0,128,120,0.25);   /* Groupe « langue » à 25 % : fond des pastilles de filtre actif */
  --c-langue-a50: rgba(0,128,120,0.5);   /* Groupe « langue » à 50 % : bordure des pastilles de filtre actif */
  --c-audio-a15: rgba(161,54,112,0.15);   /* Groupe « audio » à 15 % : survol des pastilles */
  --c-audio-a25: rgba(161,54,112,0.25);   /* Groupe « audio » à 25 % : fond des pastilles de filtre actif */
  --c-audio-a50: rgba(161,54,112,0.5);   /* Groupe « audio » à 50 % : bordure des pastilles de filtre actif */
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Ne pas ajouter overflow/scrollbar-gutter sur <html> — voir DECISIONS.md §1. */

/* Défilement animé vers une section au clic sur un lien d'ancrage (doc-nav,
   liens internes #section, bouton retour en haut…) plutôt qu'un saut instantané.
   Désactivé pour les personnes préférant réduire les animations. Indépendant du
   correctif scrollbar ci-dessus/ci-dessous : n'a aucun lien avec le bug sticky. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}



body {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--text);
  background: var(--surface);
  min-height: 100dvh;   /* dvh : évite un footer mal positionné quand la barre d'URL mobile se rétracte */
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
}

/* ── TOPBAR ── */
.topbar {
  background: var(--navy);
  color: var(--white);
  padding: 0 2rem;
  height: 60px;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  position: sticky;
  top: 0;
  z-index: 300;
  box-shadow: 0 2px 8px var(--black-30);
  width: 100%;   /* indispensable ici — piège récurrent, voir DECISIONS.md §9 */
  min-width: 0;
}
/* Logo + titre, cliquable vers l'accueil (déjà le comportement du titre seul
   sur la plupart des pages — le logo rejoint simplement ce même lien).
   Gap volontairement plus serré (0.6rem) que le gap général de la topbar
   (1.5rem, entre ce bloc et les éléments suivants — label, recherche…) :
   logo et titre forment un seul repère de marque, les autres éléments de la
   topbar sont des zones fonctionnelles distinctes. */
.topbar-brand-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  cursor: pointer;
  flex-shrink: 0;
}
.topbar-logo {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  flex-shrink: 0;
  display: block;
}
.topbar-title {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--white);
  line-height: 1.2;
  flex-shrink: 0;
}
.topbar-title span {
  display: block;
  font-weight: 300;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  opacity: 0.7;
}
.topbar-label {
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  color: var(--white-55);
  text-transform: uppercase;
  flex-shrink: 0;
}
.topbar-sep { flex: 1; }
.topbar-meta {
  font-size: 0.72rem;
  color: var(--white-40);
  font-family: var(--font-mono);
  flex-shrink: 0;
}
/* Bouton de déconnexion — ajouté en JS par partitheque/js/auth.js, toujours en bout de topbar */
.topbar-logout {
  flex-shrink: 0;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--white-55);
  text-decoration: none;
  padding: 0.35rem 0.75rem;
  border-radius: 20px;
  border: 1px solid var(--white-22);
  transition: color 0.15s, border-color 0.15s, background 0.15s;
  white-space: nowrap;
}
.topbar-logout:hover {
  color: var(--white);
  border-color: var(--white-40);
  background: var(--white-08);
}
@media (max-width: 720px) {
  .topbar-logout { font-size: 0.65rem; padding: 0.3rem 0.6rem; }
}
/* Mobile : la topbar déborderait (label + méta). On resserre les marges et on
   masque la méta décorative (présente uniquement sur accueil / charte /
   stats ; le catalogue et la saisie utilisent d'autres éléments, non
   affectés). Le rétrécissement du sous-titre du titre n'a plus lieu d'être
   ici : le titre est déjà masqué à ce même palier (voir .topbar-title
   ci-dessous), 720px partout — cohérent avec le reste du site, plus de
   palier à part pour la topbar. */
@media (max-width: 720px) {
  .topbar { padding: 0 1rem; gap: 0.85rem; }
  .topbar-meta { display: none; }
}
/* Logo seul (plus "Partithèque" / "Guides et Scouts d'Europe") : la marque
   reste identifiable par l'icône, le label de page (ex. "Statistiques")
   reste affiché juste après. Seuil à 720px, PAS 640px (au-dessus) : aligné
   sur le palier déjà utilisé par style.css pour Catalogue/Hodari/
   Statistiques (réservation de place pour la recherche de la topbar), qui
   calculait sa marge en fonction de la largeur du TITRE — masquer le titre
   seulement à 640px aurait laissé une fenêtre 641-720px où titre ET label
   auraient tous les deux concurrencé la recherche pour la même place. */
@media (max-width: 720px) {
  .topbar-title { display: none; }
}
/* ── HERO ── */
.hero {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-light) 60%, var(--hero-end) 100%);
  padding: 3rem 2rem 2.5rem;
  text-align: center;
}
.hero-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--lavender3);
  margin-bottom: 0.8rem;
}
.hero h1 {
  font-family: var(--font-serif);
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  font-weight: 600;
  color: var(--white);
  line-height: 1.2;
  margin-bottom: 0.5rem;
}
.hero-sub {
  font-size: 0.92rem;
  color: var(--white-65);
  max-width: 500px;
  margin: 0 auto;
  line-height: 1.6;
}

/* ── DOC NAV (barre de navigation secondaire) ── */
.doc-nav {
  background: var(--white);
  border-bottom: 2px solid var(--border);
  position: sticky;
  top: 60px;
  z-index: 200;
  min-height: 44px;
}
.doc-nav-inner {
  display: flex;
  overflow-x: auto;
  scrollbar-width: none;
  min-height: 44px;
  align-items: stretch;
  padding: 0;
  cursor: grab;
  user-select: none;
}
.doc-nav-inner:active { cursor: grabbing; }
.doc-nav-inner::-webkit-scrollbar { display: none; }
.doc-nav-inner::before,
.doc-nav-inner::after {
  content: '';
  flex: 1;
  min-width: 1rem;
}
.doc-nav a {
  display: flex;
  align-items: center;
  padding: 0 0.85rem;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-3);
  text-decoration: none;
  letter-spacing: 0.03em;
  box-shadow: inset 0 -2px 0 transparent;
  white-space: nowrap;
  transition: color 0.15s, box-shadow 0.15s;
  flex-shrink: 0;
}
/* @media (hover:hover) : le survol lavande ne s'applique qu'aux appareils à
   pointeur précis (souris/trackpad). Sans ça, sur tactile, :hover reste
   "collé" sur le dernier lien touché jusqu'au tap suivant ailleurs sur la
   page — un simple scroll ne le retire pas, laissant un lien en bleu clair
   même après que le scroll-spy a déplacé .active ailleurs. */
@media (hover: hover) {
  .doc-nav a:hover { color: var(--navy); box-shadow: inset 0 -2px 0 var(--lavender3); }
}
.doc-nav a.active { color: var(--navy); font-weight: 600; box-shadow: inset 0 -2px 0 var(--navy); }

/* Ombres latérales : indiquent que la barre peut défiler, masquées aux extrémités.
   Activées par les classes .can-left / .can-right posées en JS selon la position de scroll.
   .doc-nav est déjà en position:sticky → sert de bloc conteneur aux pseudo-éléments. */
.doc-nav::before,
.doc-nav::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 2px;                 /* laisse apparaître la bordure inférieure */
  width: 54px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
  z-index: 2;
}
.doc-nav::before { left: 0;  background: linear-gradient(to right, var(--white) 35%, var(--white-0)); }
.doc-nav::after  { right: 0; background: linear-gradient(to left,  var(--white) 35%, var(--white-0)); }
.doc-nav.can-left::before  { opacity: 1; }
.doc-nav.can-right::after   { opacity: 1; }

/* ── FOOTER ── */
.footer {
  background: var(--navy);
  color: var(--white-40);
  padding: 1.5rem 2rem;
  font-size: 0.75rem;
  position: relative;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: auto;
  /* Ombre partant du footer vers le haut (sur la barre d'impression),
     même principe que .topbar dont l'ombre part vers le bas sur .search-zone */
  box-shadow: 0 -2px 8px var(--black-30);
}
/* Sous un certain seuil, la marque et les liens du footer ne tiennent plus
   côte à côte élégamment (espace excessif ou lien collé au bord) : centrés
   verticalement à la place. Le seuil dépend du rôle — role-admin a bien plus
   de liens dans .footer-nav (Hodari, Statistiques, Saisie, Export JSON,
   Charte graphique…) et a donc besoin de plus de place avant de basculer.
   Rôle posé sur <html> par un script inline en tête de <body> sur chaque page
   (role-user/role-admin/role-visiteur, voir charte graphique § Règles d'usage). */
@media (max-width: 650px) {
  html:not(.role-admin) .footer { flex-direction: column-reverse; align-items: center; text-align: center; }
  html:not(.role-admin) .footer-nav { justify-content: center; }
}
@media (max-width: 1150px) {
  html.role-admin .footer { flex-direction: column-reverse; align-items: center; text-align: center; }
  html.role-admin .footer-nav { justify-content: center; }
}
.footer-brand {
  display: block;
  height: 54px;
  width: auto;
  opacity: 0.6;
}
.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  align-items: center;
}
.footer-nav-label {
  font-size: 0.65rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.5;
  margin-right: 0.5rem;
}
/* .footer-nav a ET .footer-nav .current partagent le même gabarit (padding,
   taille, radius) pour un espacement horizontal homogène entre tous les
   outils — l'outil actif n'est PAS un lien (<span class="current">, voir
   catalogue.html etc., volontairement non cliquable) mais doit occuper
   exactement la même "case" visuelle que ses voisins.
   AVANT CE CORRECTIF : cette règle commune ciblait uniquement `.footer-nav a`,
   et la distinction de l'outil actif était portée par `.footer-nav a.current`
   — un sélecteur qui ne correspondait JAMAIS à rien, puisque .current est
   toujours un <span>, jamais un <a>, dans le HTML réel de chaque page. L'outil
   actif n'héritait donc que du style par défaut du footer (texte translucide
   à peine visible) et d'AUCUN padding — d'où un contraste presque
   imperceptible et un espacement resserré par rapport aux autres outils,
   tous deux signalés par Joseph. Voir DECISIONS.md §23. */
.footer-nav a,
.footer-nav .current {
  font-size: 0.75rem;
  padding: 0.25rem 0.65rem;
  border-radius: 20px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.footer-nav a {
  color: var(--white-55);
  text-decoration: none;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.footer-nav a:hover {
  color: var(--white);
  border-color: var(--white-22);
  background: var(--white-08);
}
.footer-nav .current {
  color: var(--navy);
  background: var(--white);
  border-color: var(--white);
  font-weight: 700;
  cursor: default;
}

/* ── BACK TO TOP ── */
#back-to-top {
  position: fixed;
  bottom: 1.8rem;
  right: 1.8rem;
  width: 42px;
  height: 42px;
  background: var(--navy);
  color: var(--white);
  border: none;
  border-radius: 50%;
  font-size: 1.1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 16px var(--navy-30);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s, transform 0.2s, background 0.15s, bottom 0.25s ease;
  z-index: 500;               /* au-dessus de tout : topbar(300), footer(400), print-toolbar(450) */
  pointer-events: none;
}
#back-to-top.visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
#back-to-top:hover   { background: var(--navy-light); }

/* ── INSTALL CARD (raccourci écran d'accueil, mobile uniquement) ──
   Masquage : hidden par défaut dans le HTML, retiré par js/install-card.js
   si mobile ET pas déjà installée (mode standalone). Le @media ci-dessous
   est un filet de sécurité redondant (même principe que le rôle visiteur
   vérifié deux fois dans refresh-cache.js) : si le script échoue ou tourne
   après le premier rendu, la carte ne doit jamais s'afficher sur grand
   écran. [hidden] doit être répété ici avec la classe : un sélecteur
   d'attribut seul a la même spécificité que la règle [hidden]{display:none}
   du navigateur, et l'origine "auteur" de .install-card{display:flex}
   l'emporterait sinon silencieusement sur l'origine "user-agent", quelle
   que soit la spécificité — l'attribut hidden resterait sans effet. */
.install-card {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  background: var(--navy-pale);
  border-bottom: 1.5px solid var(--border);
  padding: 0.85rem 1.25rem;
  /* Sans position ni z-index, un élément se peint toujours sous le moindre
     élément positionné qu'il chevauche — ici la topbar (sticky, z-index 300)
     et, dans le catalogue mobile, le voile d'overlay de la fiche détaillée/
     recherche avancée (.overlay-scrim, fixed, z-index 301, voir style.css) :
     la carte passait sous l'un ou l'autre dès qu'ils se chevauchaient
     visuellement, quel que soit son ordre dans le HTML (signalé par Joseph).
     301 : au même niveau que le voile, donc toujours au-dessus de la
     topbar — cohérent avec sa position avant elle dans le document. */
  position: relative;
  z-index: 301;
}
.install-card[hidden] { display: none; }
.install-card__icon {
  border-radius: 10px;
  flex-shrink: 0;
}
.install-card__text { flex: 1; min-width: 0; }
.install-card__text p {
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: 1.5;
}
.install-card__text strong { color: var(--navy); }
.install-card__steps {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
}
.install-card__steps p {
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: 1.5;
}
.install-card__steps p + p { margin-top: 0.3rem; }
.install-card__button {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--white);
  color: var(--navy);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.2s ease, background 0.15s, border-color 0.15s;
}
.install-card__button:hover { background: var(--lavender); border-color: var(--lavender3); }
.install-card__button[hidden] { display: none; }
.install-card[data-open="1"] .install-card__button { transform: rotate(90deg); }
/* Filet de sécurité desktop — voir commentaire en tête de section. */
@media (min-width: 721px) {
  .install-card { display: none !important; }
}

/* ── SCROLLBAR ── Défilement général de la page : apparence par défaut du
   navigateur, volontairement — voir DECISIONS.md §2. */
*:not(html):not(body)::-webkit-scrollbar       { width: 6px; height: 6px; }
*:not(html):not(body)::-webkit-scrollbar-track { background: var(--surface); }
*:not(html):not(body)::-webkit-scrollbar-thumb { background: var(--lavender2); border-radius: 3px; }
*:not(html):not(body)::-webkit-scrollbar-thumb:hover { background: var(--lavender3); }
