/* ==========================================================================
   Archiverse Search

   Charte graphique Archiverse v1, section SEARCH.

   Couleurs      rampe Search : #d1dffa #a8c0f0 #85a3e0 #6688cc #4d6fb3 (clair)
                                #4d6fb3 #335599 #1f3d7a #0f2757 #05132e (sombre)
                 neutres clair : fond #f2f2f3, conteneur #fafafa,
                                 élément #eaecf0, bordure #d7d8db, texte #231f20
                 neutres sombre : fond #121314, conteneur #1e1f21,
                                  élément #22252b, bordure #2d3139, texte #fafafa
   Typographie   Bricolage Grotesque pour les titres et les éléments forts,
                 Radio Canada Big pour tout le reste.

   Règle de rayon appliquée partout :
     cartes et panneaux ...... var(--r-card)     14px
     champs et boutons ....... var(--r-control)  10px
     pastilles et étiquettes . var(--r-pill)     999px
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */

:root {
  color-scheme: light;

  --bg: #f2f2f3;
  --surface: #fafafa;
  --surface-2: #eaecf0;
  --surface-3: #dfe1e6;
  --line: #d7d8db;
  --line-strong: #bcbfc6;

  --text: #231f20;
  --text-2: #55585f;
  --text-3: #83878f;

  --accent: #4d6fb3;
  --accent-hi: #3d5b99;
  --accent-soft: #d1dffa;
  --accent-line: #a8c0f0;
  --on-accent: #ffffff;

  --ok: #2f6b46;
  --ok-soft: #e2efe8;
  --ok-hi: #275a3a;
  --on-ok: #ffffff;
  --danger: #a8332b;
  /* Le rouge n'avait que son ton plein. Un bandeau d'avertissement a besoin
     d'un fond pâle et d'un liseré, comme l'accent en a : sinon il emprunte
     ceux de l'accent et se retrouve bleu, ce qui dit exactement le contraire
     de ce qu'il annonce. */
  --danger-soft: #fae3e1;
  --danger-line: #eab4ae;
  --danger-hi: #8c2922;
  --on-danger: #ffffff;

  /* L'ambre manquait. La charte n'avait que trois voix — le bleu qui désigne,
     le vert qui approuve, le rouge qui refuse — et rien pour ce qui est en
     cours. Un outil en chantier n'est ni approuvé ni refusé : il attend.
     Le prendre en rouge le ferait passer pour cassé, en bleu pour ordinaire. */
  --warn: #8a5a12;
  --warn-soft: #fbeeda;
  --warn-line: #e8cf9f;
  --warn-hi: #744b0d;
  --on-warn: #ffffff;

  --shadow-sm: 0 1px 2px rgb(35 31 32 / .05), 0 2px 6px rgb(35 31 32 / .05);
  --shadow-md: 0 2px 4px rgb(35 31 32 / .05), 0 12px 28px rgb(35 31 32 / .10);
  --shadow-lg: 0 4px 10px rgb(35 31 32 / .08), 0 30px 60px rgb(35 31 32 / .16);

  --r-card: 14px;
  --r-control: 10px;
  --r-pill: 999px;

  --maxw: 1320px;
  --gut: clamp(1rem, 3.2vw, 2.5rem);
  --topbar-h: 64px;

  --ease: cubic-bezier(.16, 1, .3, 1);
  --dur: .22s;

  --font-display: "Bricolage Grotesque", "Radio Canada Big",
    "Segoe UI Variable Display", "Segoe UI", system-ui, sans-serif;
  --font-sans: "Radio Canada Big", "Segoe UI Variable Text", "Segoe UI",
    ui-sans-serif, system-ui, -apple-system, Arial, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", "Cascadia Code", Consolas,
    "SF Mono", "Roboto Mono", monospace;
}

html[data-theme="dark"] {
  color-scheme: dark;
  --bg: #121314;
  --surface: #1e1f21;
  --surface-2: #22252b;
  --surface-3: #282c33;
  --line: #2d3139;
  --line-strong: #3d434d;
  --text: #fafafa;
  --text-2: #a8adb6;
  --text-3: #7c828c;
  /* Sur fond sombre l'ancre #4d6fb3 manque de contraste pour du texte :
     la charte fournit une teinte plus claire de la même rampe. */
  --accent: #85a3e0;
  --accent-hi: #a8c0f0;
  --accent-soft: #0f2757;
  --accent-line: #1f3d7a;
  --on-accent: #05132e;
  --ok: #6fcf97;
  --ok-soft: #14241b;
  --ok-hi: #8bdcac;
  --on-ok: #072a15;
  --danger: #f2909b;
  --danger-soft: #331519;
  --danger-line: #6b2a31;
  --danger-hi: #f7aeb6;
  --on-danger: #2a0d10;
  --warn: #e0b46a;
  --warn-soft: #2b2114;
  --warn-line: #5c4623;
  --warn-hi: #efc986;
  --on-warn: #2a1d07;
  --shadow-sm: 0 1px 2px rgb(0 0 0 / .4);
  --shadow-md: 0 2px 6px rgb(0 0 0 / .35), 0 14px 34px rgb(0 0 0 / .45);
  --shadow-lg: 0 6px 14px rgb(0 0 0 / .4), 0 34px 70px rgb(0 0 0 / .55);
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #121314;
    --surface: #1e1f21;
    --surface-2: #22252b;
    --surface-3: #282c33;
    --line: #2d3139;
    --line-strong: #3d434d;
    --text: #fafafa;
    --text-2: #a8adb6;
    --text-3: #7c828c;
    --accent: #85a3e0;
    --accent-hi: #a8c0f0;
    --accent-soft: #0f2757;
    --accent-line: #1f3d7a;
    --on-accent: #05132e;
    --ok: #6fcf97;
    --ok-soft: #14241b;
    --ok-hi: #8bdcac;
    --on-ok: #072a15;
    --danger: #f2909b;
    --danger-soft: #331519;
    --danger-line: #6b2a31;
    --danger-hi: #f7aeb6;
    --on-danger: #2a0d10;
    --warn: #e0b46a;
    --warn-soft: #2b2114;
    --warn-line: #5c4623;
    --warn-hi: #efc986;
    --on-warn: #2a1d07;
    --shadow-sm: 0 1px 2px rgb(0 0 0 / .4);
    --shadow-md: 0 2px 6px rgb(0 0 0 / .35), 0 14px 34px rgb(0 0 0 / .45);
    --shadow-lg: 0 6px 14px rgb(0 0 0 / .4), 0 34px 70px rgb(0 0 0 / .55);
  }
}

/* ---------- 2. Base ------------------------------------------------------ */

/*  Ces règles habillaient un document entier, du temps où la maquette occupait
    seule la page. Intégrées au site, elles doivent s'arrêter au contenu : la
    barre de navigation d'Archiverse a sa propre feuille, et « ul { list-style:
    none } » ou « a { color: inherit } » la démonteraient au passage.

    Tout est donc cantonné à .archiverse-search, le conteneur qui enveloppe ce
    que cette charte dessine. Les variables, elles, restent sur :root — elles ne
    peignent rien par elles-mêmes, et aucun de leurs noms n'entre en conflit
    avec ceux du site : vérifié, zéro collision. */

.archiverse-search *,
.archiverse-search *::before,
.archiverse-search *::after {
  box-sizing: border-box;
}

/* La règle [hidden] du navigateur est portée par un sélecteur d'attribut, donc
   battue par n'importe quelle classe posant un display. Le site en compte plus
   de cent : sans cette ligne, masquer un élément en JavaScript reste sans effet
   et le défaut passe inaperçu, puisque rien n'échoue. Le cas s'est présenté
   trois fois, sur .counter, .field puis .options. Réglé une fois pour toutes. */
.archiverse-search [hidden] {
  display: none !important;
}

.archiverse-search {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 15.5px;
  line-height: 1.55;
  letter-spacing: -.006em;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 60vh;
}

/* Le pied de page vient se poser directement sur la section.

   css/footer-site.css lui donne quarante pixels de marge haute. Sur une page
   ordinaire, dont le fond est celui du corps, cette marge ne se voit pas.
   Ici la section peint son propre fond — un gris à #f2f2f3 —, le pied est
   blanc, et le corps entre les deux est à #fafafa : la marge laissait donc
   passer une bande de quarante pixels d'une troisième couleur, qui
   n'appartenait ni à la section ni au pied et ressemblait à un vide oublié.

   Rien n'est perdu à la retirer : le pied porte déjà un filet et soixante
   pixels de marge intérieure, et la mention qui termine la section en porte
   trente-huit. La respiration est là, du bon côté du trait. */
.archiverse-search+.landing-footer {
  margin-top: 0;
}

body.is-locked {
  overflow: hidden;
}

/* Ces règles remettent les éléments à zéro ; elles doivent donc perdre contre
   toute règle de composant. Écrites « .archiverse-search input », elles pèsent
   (0,1,1) et battaient « .calcul__champ » à (0,1,0) : la calculatrice se
   retrouvait avec deux textes superposés dans des polices différentes, son
   champ ayant récupéré la police du site au lieu de la sienne.

   :where() ne compte pour rien dans le calcul de spécificité. Le cantonnement
   demeure — ces règles ne sortent toujours pas du conteneur — mais leur poids
   redevient celui qu'elles avaient avant l'intégration, quand elles étaient
   écrites « input { … } » tout court. C'est ce poids-là que le reste de la
   charte suppose. */
:where(.archiverse-search) img {
  max-width: 100%;
  display: block;
}

/* Bricolage Grotesque porte les titres et les éléments forts, Radio Canada Big
   le reste. La graisse 700 correspond au « Bold » de la charte. */
:where(.archiverse-search) h1,
:where(.archiverse-search) h2,
:where(.archiverse-search) h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.14;
}

:where(.archiverse-search) p {
  margin: 0;
}

:where(.archiverse-search) ul,
:where(.archiverse-search) ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

:where(.archiverse-search) a {
  color: inherit;
  text-decoration: none;
}

:where(.archiverse-search) button,
:where(.archiverse-search) input,
:where(.archiverse-search) select,
:where(.archiverse-search) textarea {
  font: inherit;
  color: inherit;
}

.archiverse-search :focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.mono {
  font-family: var(--font-mono);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: .5rem;
  z-index: 200;
  background: var(--accent);
  color: var(--on-accent);
  padding: .6rem 1rem;
  border-radius: var(--r-control);
}

.skip-link:focus {
  left: .75rem;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.stack {
  display: grid;
  gap: .5rem;
}

.lead {
  color: var(--text-2);
  font-size: 1rem;
  max-width: 60ch;
}

/* Éléments forts de la charte : intertitres, libellés de rubrique, onglets.
   Tout ce qui structure la page, sans déborder sur les boutons courants. */
.empty__title,
.panel__title,
legend,
.filterline__lab,
.exthead__kicker,
.tab,
.journalblock__title,
.adminbar__tag,
.sugg__kind,
.pill {
  font-family: var(--font-display);
}

/* ---------- 3. Barre haute ---------------------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid var(--line);
}

@media (prefers-reduced-transparency: reduce) {
  .topbar {
    background: var(--bg);
    backdrop-filter: none;
  }
}

.topbar__inner {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 0 var(--gut);
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  color: var(--accent);
  min-width: 0;
}

.brand__mark {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
}

.brand__text {
  font-family: var(--font-display);
  font-size: 1.14rem;
  font-weight: 800;
  letter-spacing: -.03em;
  color: var(--text);
}

/* Le nom de section reste lisible sans concurrencer la marque. */
.brand__section {
  font-family: var(--font-display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  padding: .16rem .5rem;
  border-radius: var(--r-pill);
  white-space: nowrap;
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: .6rem;
}

.roleswitch {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.roleswitch__opt {
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: .38rem .85rem;
  border-radius: var(--r-pill);
  font-size: .82rem;
  font-weight: 560;
  color: var(--text-2);
  white-space: nowrap;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease),
    border-color var(--theme-dur) var(--theme-ease);
}

.roleswitch__opt:hover {
  color: var(--text);
}

.roleswitch__opt[aria-pressed="true"] {
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-sm);
}

.iconbtn {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.iconbtn:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

.iconbtn:active {
  transform: scale(.96);
}

.ico--moon {
  display: none;
}

html[data-theme="dark"] .ico--sun {
  display: none;
}

html[data-theme="dark"] .ico--moon {
  display: block;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .ico--sun {
    display: none;
  }

  html:not([data-theme="light"]) .ico--moon {
    display: block;
  }
}

.adminbar {
  background: var(--accent-soft);
  border-bottom: 1px solid var(--accent-line);
}

.adminbar__inner {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: .55rem var(--gut);
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.adminbar__tag {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}

.adminbar__links {
  display: flex;
  gap: .45rem;
  flex-wrap: wrap;
  margin-left: auto;
}

.counter {
  display: inline-grid;
  place-items: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 .35rem;
  margin-left: .3rem;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-size: .7rem;
  font-weight: 700;
  font-family: var(--font-mono);
}

/* Libellés longs sur grand écran, courts sur téléphone. */
.lbl-short {
  display: none;
}

/* ---------- 4. Boutons --------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  padding: .58rem 1.05rem;
  border-radius: var(--r-control);
  border: 1px solid transparent;
  cursor: pointer;
  font-size: .88rem;
  font-weight: 580;
  white-space: nowrap;
  text-align: center;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
    border-color var(--dur) var(--ease), transform .12s var(--ease);
}

.btn:active {
  transform: translateY(1px);
}

.btn--sm {
  padding: .4rem .75rem;
  font-size: .82rem;
}

.btn--block {
  width: 100%;
}

.btn--accent {
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-sm);
}

.btn--accent:hover {
  background: var(--accent-hi);
}

.btn--ghost {
  background: var(--surface);
  color: var(--text);
  border-color: var(--line);
}

.btn--ghost:hover {
  border-color: var(--line-strong);
  background: var(--surface-2);
}

.btn--quiet {
  background: transparent;
  color: var(--text-2);
}

.btn--quiet:hover {
  color: var(--text);
  background: var(--surface-2);
}

.btn--danger {
  color: var(--danger);
}

.btn--danger:hover {
  border-color: currentColor;
}

/* Pendant vert de btn--danger : valider et supprimer se répondent dans le
   panneau d'administration. */
.btn--ok {
  color: var(--ok);
}

.btn--ok:hover {
  border-color: currentColor;
}

/* Version pleine, pour la validation présentée comme action principale.
   Le texte suit le thème : blanc sur le vert foncé du mode clair, vert très
   sombre sur le vert clair du mode sombre. */
.btn--ok-plein {
  background: var(--ok);
  color: var(--on-ok);
  border-color: var(--ok);
  box-shadow: var(--shadow-sm);
}

.btn--ok-plein:hover {
  background: var(--ok-hi);
  border-color: var(--ok-hi);
}

.btn[disabled] {
  opacity: .5;
  cursor: not-allowed;
}

/* ---------- 5. Accueil : intro et contrôles ------------------------------ */

.view {
  flex: 1 0 auto;
}

/* Exactement le rembourrage de .hub, en tête de la bibliothèque Outils : les
   deux répertoires se répondent, et la lecture passe de l un à l autre sans
   que le titre change de niveau. Les valeurs différaient d un peu plus d un
   pixel — invisible seul, mais on le voit en basculant entre les deux. */
/* En-tete de section : le fil, le titre, l'accroche.

   Trois pages le portent — Outils, Logiciels et Ressources — et il vivait
   dans la feuille des seules pages Outils. Ressources ne la chargeant pas,
   son titre retombait sur le « h1 { font-size: 8vh } » de css/style2.css :
   cent un pixels au lieu de quarante et un. Un en-tete partage appartient
   a la charte.

   .intro juste en dessous en est la variante de la bibliotheque Logiciels,
   aux memes valeurs. Les deux nomenclatures cohabitent faute d'avoir ete
   unifiees a temps ; elles ne divergent pas. */
.hub {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: clamp(1.8rem, 4vw, 3rem) var(--gut) 1.4rem;
}

.hub__fil {
  display: flex;
  align-items: center;
  gap: .45rem;
  font-size: .78rem;
  color: var(--text-3);
  margin-bottom: .8rem;
}

.hub__fil b {
  color: var(--accent);
  font-weight: 600;
}

.hub__titre {
  font-size: clamp(1.65rem, 4vw, 2.6rem);
  max-width: 20ch;
  text-wrap: balance;
}

.hub__lead {
  margin-top: .6rem;
  color: var(--text-2);
  max-width: 62ch;
}

.hub__barre {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  margin-top: 1.4rem;
}

.hub__compte {
  font-size: .84rem;
  color: var(--text-2);
  margin-right: auto;
}

.hub__compte b {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text);
}

.intro {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: clamp(1.8rem, 4vw, 3rem) var(--gut) 1.4rem;
}

.intro__title {
  font-size: clamp(1.65rem, 4vw, 2.6rem);
  max-width: 20ch;
  text-wrap: balance;
}

.intro__lead {
  margin-top: .6rem;
  color: var(--text-2);
  max-width: 62ch;
}

/* Seule cette barre reste collante, et elle est volontairement courte :
   les filtres détaillés vivent dans un panneau qui défile normalement. */
.controls {
  position: sticky;
  top: var(--topbar-h);
  z-index: 40;
  /* La hauteur se pose ici et non sur le contenu : les liserés du haut et
     du bas appartiennent à ce bloc, et box-sizing les compte dedans. Posée
     sur l intérieur, elle donnait soixante et un pixels au lieu de soixante. */
  min-height: var(--hauteur-barre, 60px);
  background: color-mix(in srgb, var(--bg) 93%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-block: 1px solid var(--line);
}

/* La recherche garde une largeur plancher : plutôt que de se comprimer en
   « Recherc... », la ligne passe à la ligne suivante. */
.controls__inner {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  /* La même hauteur que la barre de navigation et la barre de mode : les trois
     bandeaux se répondent. En hauteur minimale et non fixe — sur écran étroit
     la ligne passe à la ligne, et il faut alors qu'elle puisse grandir. */
  min-height: 100%;
  padding: .4rem var(--gut);
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}

.tabs {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  flex: 0 0 auto;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.tab {
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: .4rem .9rem;
  border-radius: var(--r-pill);
  font-size: .85rem;
  font-weight: 560;
  color: var(--text-2);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease),
    border-color var(--theme-dur) var(--theme-ease);
}

.tab:hover {
  color: var(--text);
}

.tab[aria-selected="true"] {
  background: var(--accent);
  color: var(--on-accent);
}

.tab__n {
  font-family: var(--font-mono);
  font-size: .72rem;
  opacity: .7;
}

/* Suggérer se trouve au niveau des onglets, pas dans la barre de marque :
   c'est une action de catalogue, pas une action de compte. */
.suggestbtn {
  flex: 0 0 auto;
}

.searchrow {
  display: flex;
  gap: .5rem;
  flex: 1 1 300px;
  min-width: 0;
}

.search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
}

.search__ico {
  position: absolute;
  left: .8rem;
  color: var(--text-3);
  pointer-events: none;
}

.search__input {
  width: 100%;
  padding: .62rem 2.3rem .62rem 2.45rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  transition: border-color var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
  text-overflow: ellipsis;
}

.search__input::placeholder {
  color: var(--text-3);
}

.search__input:hover {
  border-color: var(--line-strong);
}

.search__clear {
  position: absolute;
  right: .45rem;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--text-3);
  padding: .35rem;
  border-radius: var(--r-pill);
  line-height: 0;
}

.search__clear:hover {
  color: var(--text);
  background: var(--surface-2);
}

.filterbtn {
  flex: 0 0 auto;
  padding-inline: .8rem;
}

/* Panneau de filtres : hors du flux collant, il disparaît quand on défile. */
.panelfilters {
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.panelfilters__inner {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: .9rem var(--gut) 1rem;
  display: grid;
  gap: .7rem;
}

.panelfilters__foot {
  display: flex;
  justify-content: flex-end;
}

.filterline {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
}

.filterline__lab {
  font-size: .72rem;
  font-weight: 640;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-3);
  min-width: 5.4rem;
  flex: 0 0 auto;
}

.chips {
  display: flex;
  gap: .35rem;
  flex-wrap: wrap;
}

.chip {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  padding: .32rem .72rem;
  border-radius: var(--r-pill);
  cursor: pointer;
  font-size: .81rem;
  font-weight: 520;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.chip:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

.chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.chip[data-empty]:not([aria-pressed="true"]) {
  opacity: .42;
}

.chip__n {
  font-family: var(--font-mono);
  font-size: .72rem;
  opacity: .62;
  margin-left: .3rem;
}

.select {
  appearance: none;
  padding: .6rem 2.1rem .6rem .8rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 1rem center, right .75rem center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

.select:hover {
  border-color: var(--line-strong);
}

.select--sm {
  padding-block: .38rem;
  font-size: .84rem;
}

.results {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 1.2rem var(--gut) 4rem;
}

.resultcount {
  font-size: .84rem;
  color: var(--text-2);
  margin-bottom: .9rem;
}

.resultcount b {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text);
}

/* ---------- 6. Cartes ---------------------------------------------------- */

.grid {
  display: grid;
  gap: .9rem;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

.card {
  display: flex;
  flex-direction: column;
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 1rem;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.card:hover {
  border-color: var(--line-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.card:focus-within {
  border-color: var(--accent);
}

.card__head {
  display: flex;
  gap: .75rem;
  align-items: center;
}

.card__id {
  min-width: 0;
}

.card__name {
  font-size: 1.05rem;
}

.card__name a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.card__vendor {
  font-size: .8rem;
  color: var(--text-3);
  margin-top: .1rem;
}

.card__desc {
  margin-top: .7rem;
  font-size: .875rem;
  color: var(--text-2);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;

  /* Trois lignes réservées, occupées ou non.

     La coupure à trois lignes fixait un plafond, pas un plancher : une
     accroche courte donnait une carte courte. Comme la grille aligne les
     cartes sur la plus haute de leur rangée, le trait de séparation tombait
     à une hauteur différente d une rangée à l autre, et sous les cartes
     brèves il restait un vide. Les cartes logiciel y échappaient par hasard
     — chacune de leurs rangées contient une accroche de trois lignes — ce
     qui n est pas une règle et cesserait à la première fiche modifiée.

     Réserver la place rend toutes les cartes de la section identiques :
     trois lignes à 1,5 de hauteur d une police de .875rem, soit 63 px. */
  min-height: calc(3 * 1.5 * .875rem);
}

/* Les systèmes à gauche, les compteurs à droite — mais collés l'un à l'autre.
   « justify-content: space-between » répartissait les trois blocs sur toute la
   largeur, ce qui écartait les écoles des extensions d'une carte entière. La
   marge automatique sur la rangée des systèmes fait le même travail sans
   séparer ce qui se lit ensemble. */
/* Deux blocs qui se font face : ce qui se rattache à la fiche d'un côté —
   écoles, extensions — et le régime de tarif de l'autre. Les systèmes ont
   quitté cette rangée pour la ligne qui alterne sous le nom, où ils tiennent
   en trois mots au lieu d'occuper une rangée de pastilles. */
.card__foot {
  margin-top: auto;
  padding-top: .85rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  flex-wrap: wrap;
}

.card__compteurs {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
}

.card__tarif {
  margin-left: auto;
}


/* Pied des cartes extension : logos des logiciels compatibles, et le statut.

   La rangée descend au bas de la carte. Elle ne le faisait pas : le
   « margin-top: auto » posé en début de règle était écrasé par le
   « margin-top: .9rem » de la ligne suivante, et le trait se calait sous la
   description. Comme la description tient une à trois lignes selon la fiche,
   deux cartes voisines montraient leur séparation à deux hauteurs
   différentes, la plus courte laissant un vide sous son trait.

   L écart minimal avec la description passe donc par la description
   elle-même : une marge basse fixe, que la marge automatique complète de
   tout l espace restant. Les marges ne fusionnent pas en flex, la somme est
   donc exacte. */
.card--ext .card__desc {
  margin-bottom: .9rem;
}

.card__for {
  margin-top: auto;
  padding-top: .85rem;
  display: flex;
  align-items: center;
  gap: .55rem;
  border-top: 1px solid var(--line);
}

.card__forlogos {
  display: flex;
}

.card__forlogos .logo {
  margin-right: -8px;
  box-shadow: 0 0 0 2px var(--surface);
}

.card__fortext {
  font-size: .78rem;
  color: var(--text-3);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tags {
  display: flex;
  gap: .3rem;
  flex-wrap: wrap;
  margin-top: .7rem;
}

.tag {
  font-size: .72rem;
  padding: .18rem .5rem;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-2);
  border: 1px solid var(--line);
}

.tag--accent {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent);
  font-weight: 600;
}

.tag--free {
  background: var(--ok-soft);
  border-color: color-mix(in srgb, var(--ok) 32%, transparent);
  color: var(--ok);
  font-weight: 600;
}

.osrow {
  display: flex;
  gap: .25rem;
  flex-wrap: wrap;
}

.os {
  font-family: var(--font-mono);
  font-size: .68rem;
  padding: .16rem .42rem;
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--text-2);
  border: 1px solid var(--line);
}

.logo {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface);
}

/* L'image remplit la tuile.

   « contain » avec 16% de marge la faisait flotter au milieu : mesurée sur
   une icône de 180×120 dans une tuile de 44, elle n'en couvrait que 29%.
   C'était pensé pour un logo de marque carré sur fond transparent, qu'il ne
   faut ni rogner ni coller aux bords ; mais les fiches portent surtout des
   icônes pleines et des captures, pour lesquelles la marge ne fait que
   rétrécir.

   « cover » remplit. Une icône carrée s'y rend à l'identique — c'est le cas
   de la plupart — et seule une image très allongée y perd ses bords, ce qui
   vaut mieux qu'un timbre-poste au centre d'un carré vide. */
.logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  padding: 0;
}

.logo--28 {
  width: 28px;
  height: 28px;
  border-radius: 7px;
}

.logo--44 {
  width: 44px;
  height: 44px;
}

.logo--64 {
  width: 64px;
  height: 64px;
}

.logo--84 {
  width: 84px;
  height: 84px;
}

/* Lettrage blanc quel que soit le thème : la teinte générée est calibrée
   pour rester assez sombre dans les deux cas. */
.logo__mono {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.04em;
  color: #fff;
}

.logo__mono svg {
  width: 52%;
  height: 52%;
  display: block;
}

.logo--28 .logo__mono {
  font-size: .65rem;
}

.logo--44 .logo__mono {
  font-size: .95rem;
}

.logo--64 .logo__mono {
  font-size: 1.35rem;
}

.logo--84 .logo__mono {
  font-size: 1.8rem;
}

.logo--soft {
  box-shadow: var(--shadow-md);
}

.grid>* {
  animation: cardin .4s var(--ease) both;
}

@keyframes cardin {
  from {
    opacity: 0;
    transform: translateY(8px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* ---------- 7. États vides ----------------------------------------------- */

.empty {
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-card);
  padding: clamp(1.6rem, 5vw, 3rem);
  text-align: center;
  background: var(--surface);
}

.empty__title {
  font-size: 1.08rem;
  font-weight: 620;
}

.empty__text {
  margin: .5rem auto 1.1rem;
  color: var(--text-2);
  max-width: 48ch;
  font-size: .9rem;
}

.empty__text:last-child {
  margin-bottom: 0;
}

/* ---------- 8. Fiche logiciel -------------------------------------------- */

.hero {
  position: relative;
  min-height: 260px;
  display: flex;
  align-items: flex-end;
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

.hero__bg {
  position: absolute;
  inset: 0;
}

.hero__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
      color-mix(in srgb, var(--bg) 97%, transparent) 4%,
      color-mix(in srgb, var(--bg) 78%, transparent) 42%,
      color-mix(in srgb, var(--bg) 40%, transparent) 100%);
}

.hero__inner {
  position: relative;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 4.2rem var(--gut) 1.5rem;
  display: flex;
  gap: 1.1rem;
  align-items: flex-end;
  flex-wrap: wrap;
}

.hero__id {
  display: flex;
  gap: 1.1rem;
  align-items: flex-end;
  min-width: 0;
}

.hero__txt {
  min-width: 0;
}

.hero__name {
  font-size: clamp(1.55rem, 4vw, 2.5rem);
}

.hero__vendor {
  color: var(--text-2);
  font-size: .95rem;
  margin-top: .2rem;
}

.hero__cta {
  margin-left: auto;
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
}

.backlink {
  position: absolute;
  top: 1.1rem;
  left: var(--gut);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-size: .85rem;
  color: var(--text-2);
}

.backlink:hover {
  color: var(--accent);
}

.backlink--static {
  position: static;
  display: inline-flex;
  margin-bottom: .8rem;
}

.detail {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 1.8rem var(--gut) 4rem;
  display: grid;
  grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
}

.section+.section {
  margin-top: 2.4rem;
}

.section__head {
  display: flex;
  align-items: baseline;
  gap: .8rem;
  margin-bottom: .9rem;
  flex-wrap: wrap;
}

.section__title {
  font-size: 1.2rem;
}

.section__hint {
  font-size: .82rem;
  color: var(--text-3);
}

.section__act {
  margin-left: auto;
}

.prose {
  color: var(--text-2);
  max-width: 68ch;
  margin-top: .8rem;
}

.prose p+p {
  margin-top: .85rem;
}

.pointlist {
  display: grid;
  gap: .45rem;
  margin-top: 1.1rem;
}

.pointlist .point,
.point {
  display: flex;
  gap: .6rem;
  font-size: .9rem;
  color: var(--text-2);
  width: auto;
  height: auto;
  border: none;
  border-radius: 0;
  box-shadow: none;
  cursor: default;
  transform: none;
}

.pointlist .point:hover,
.point:hover {
  transform: none;
}

.point__k {
  flex: 0 0 auto;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: .15rem;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  font-size: .7rem;
  font-weight: 700;
  background: var(--accent-soft);
  color: var(--accent);
}

.point--minus .point__k {
  background: var(--surface-2);
  color: var(--text-3);
}

.video {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  border-radius: var(--r-card);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--surface-2);
}

.video iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.video--empty {
  display: grid;
  place-items: center;
  text-align: center;
  padding: 1.5rem;
  border-style: dashed;
  border-color: var(--line-strong);
  aspect-ratio: 16 / 7;
}

.carousel {
  position: relative;
}

.carousel__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: min(80%, 520px);
  gap: .75rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
  padding-bottom: .6rem;
}

.carousel__track>figure {
  scroll-snap-align: start;
  margin: 0;
}

.carousel__track img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--r-card);
  border: 1px solid var(--line);
  background: var(--surface-2);
}

.carousel__nav {
  display: flex;
  gap: .4rem;
  justify-content: flex-end;
  margin-top: .3rem;
}

/* systèmes, poids, téléchargement */
.osgrid {
  display: grid;
  gap: .6rem;
}

.osrowbig {
  display: flex;
  align-items: center;
  gap: .85rem;
  flex-wrap: wrap;
  padding: .75rem .95rem;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
}

.osrowbig__name {
  font-weight: 600;
  font-size: .95rem;
  min-width: 5.2rem;
}

.osrowbig__size {
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: .16rem .5rem;
  border-radius: 6px;
  white-space: nowrap;
}

.osrowbig__note {
  font-size: .8rem;
  color: var(--text-3);
  flex: 1 1 12rem;
  min-width: 0;
}

.osrowbig__dl {
  margin-left: auto;
}

.pricegrid {
  display: grid;
  gap: .7rem;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}

.price {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}

.price--student {
  border-color: var(--accent-line);
  background: var(--accent-soft);
}

.price__lab {
  font-size: .82rem;
  color: var(--text-2);
}

.price--student .price__lab {
  color: var(--accent);
  font-weight: 600;
}

.price__amount {
  font-family: var(--font-mono);
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: -.03em;
}

.price__per {
  font-size: .78rem;
  color: var(--text-3);
}

.price__note {
  font-size: .8rem;
  color: var(--text-2);
  margin-top: .2rem;
}

.price__link {
  margin-top: auto;
  padding-top: .6rem;
  font-size: .82rem;
  color: var(--accent);
  font-weight: 560;
}

.price__link:hover {
  text-decoration: underline;
}

/* liste des extensions dans une fiche logiciel */
.extlist {
  display: grid;
  gap: .6rem;
}

.ext {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: .85rem;
  align-items: center;
  padding: .8rem .95rem;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.ext:hover {
  border-color: var(--line-strong);
}

.ext__body {
  min-width: 0;
}

.ext__name {
  font-weight: 600;
  font-size: .93rem;
}

.ext__name a:hover {
  color: var(--accent);
  text-decoration: underline;
}

.ext__vendor {
  font-size: .78rem;
  color: var(--text-3);
}

.ext__desc {
  font-size: .84rem;
  color: var(--text-2);
  margin-top: .25rem;
}

.ext__side {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.ext__price {
  font-family: var(--font-mono);
  font-size: .8rem;
  white-space: nowrap;
}

.aside {
  display: grid;
  gap: 1rem;
  position: sticky;
  top: calc(var(--topbar-h) + 1.5rem);
}

.panel {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: 1.1rem;
}

.panel--admin {
  border-color: var(--accent-line);
  background: var(--accent-soft);
}

.panel--admin .panel__title {
  color: var(--accent);
}

.panel--strong {
  border-color: var(--line-strong);
}

.panel__title {
  font-size: .74rem;
  font-weight: 680;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: .8rem;
}

.deflist {
  display: grid;
  gap: .7rem;
}

.deflist__row {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr);
  gap: .7rem;
  font-size: .875rem;
}

.deflist__k {
  color: var(--text-3);
}

.deflist__v {
  color: var(--text);
  min-width: 0;
}

.deflist__note {
  display: block;
  font-size: .76rem;
  color: var(--text-3);
  margin-top: .1rem;
}

.langs {
  display: flex;
  flex-wrap: wrap;
  gap: .28rem;
}

.linkrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6rem;
  padding: .55rem 0;
  font-size: .88rem;
  border-top: 1px solid var(--line);
}

.linkrow:first-of-type {
  border-top: 0;
}

.linkrow a {
  color: var(--accent);
  font-weight: 540;
}

.linkrow a:hover {
  text-decoration: underline;
}

/* ---------- 9. Fiche extension -------------------------------------------
   Pas de bannière : un en-tête plein, sobre, où le logo de l'extension et les
   logiciels compatibles portent l'identification.
   -------------------------------------------------------------------------- */

.exthead {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.exthead__inner {
  position: relative;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 3rem var(--gut) 1.6rem;
  display: flex;
  gap: 1.2rem;
  align-items: flex-end;
  flex-wrap: wrap;
}

.exthead__id {
  display: flex;
  gap: 1.1rem;
  align-items: center;
  min-width: 0;
}

.exthead__txt {
  min-width: 0;
}

.exthead__kicker {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: .25rem;
}

.exthead__name {
  font-size: clamp(1.5rem, 3.6vw, 2.2rem);
}

.exthead__vendor {
  color: var(--text-2);
  font-size: .92rem;
  margin-top: .15rem;
}

.exthead__cta {
  margin-left: auto;
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
}

.detail--ext {
  padding-top: 1.6rem;
}

.hostgrid {
  display: grid;
  gap: .6rem;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}

.hostcard {
  position: relative;
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: .8rem .9rem;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.hostcard:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
}

.hostcard__txt {
  display: grid;
  min-width: 0;
}

.hostcard__name {
  font-weight: 620;
  font-size: .95rem;
}

.hostcard__vendor {
  font-size: .78rem;
  color: var(--text-3);
}

.hostcard__x {
  margin-left: auto;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-3);
  width: 24px;
  height: 24px;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  cursor: pointer;
  flex: 0 0 auto;
}

.hostcard__x:hover {
  color: var(--danger);
  border-color: currentColor;
}

/* ---------- 10. Formulaires ---------------------------------------------- */

.formpage {
  width: 100%;
  max-width: 1000px;
  margin-inline: auto;
  padding: 2rem var(--gut) 4rem;
}

.formpage__head {
  margin-bottom: 1.6rem;
}

.formpage__title {
  font-size: clamp(1.45rem, 3.4vw, 2rem);
}

.formpage__lead {
  margin-top: .5rem;
  color: var(--text-2);
  max-width: 64ch;
  font-size: .92rem;
}

fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 1.6rem;
}

legend {
  font-size: .74rem;
  font-weight: 680;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 0 0 .7rem;
}

.fgrid {
  display: grid;
  gap: .9rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.f-span {
  grid-column: 1 / -1;
}

.field {
  display: grid;
  gap: .35rem;
  align-content: start;
}

.field>label {
  font-size: .84rem;
  font-weight: 560;
  color: var(--text);
}

.field__hint {
  font-size: .78rem;
  color: var(--text-3);
}

.field__err {
  font-size: .8rem;
  color: var(--danger);
}

.input,
.textarea {
  width: 100%;
  padding: .62rem .8rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-control);
  transition: border-color var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease),
    color var(--theme-dur) var(--theme-ease);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--text-3);
}

.input:hover,
.textarea:hover {
  border-color: var(--text-3);
}

.textarea {
  resize: vertical;
  min-height: 5.5rem;
  line-height: 1.55;
}

.field--invalid .input,
.field--invalid .textarea,
.field--invalid .checks {
  border-color: var(--danger);
}

.checks {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  padding: 2px;
  border: 1px solid transparent;
  border-radius: var(--r-control);
}

.check {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .38rem .75rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  cursor: pointer;
  font-size: .84rem;
  color: var(--text-2);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.check input {
  accent-color: var(--accent);
  margin: 0;
}

.check:hover {
  color: var(--text);
}

.check:has(input:checked) {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 560;
}

.repeater {
  display: grid;
  gap: .6rem;
}

.rowcard {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface-2);
  padding: .85rem;
}

.rowcard__grid {
  display: grid;
  gap: .6rem;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.rowcard__foot {
  display: flex;
  justify-content: flex-end;
  margin-top: .55rem;
}

.unitfield {
  position: relative;
  display: flex;
  align-items: center;
}

.unitfield .input {
  padding-right: 2.6rem;
}

.unitfield__u {
  position: absolute;
  right: .8rem;
  font-family: var(--font-mono);
  font-size: .8rem;
  color: var(--text-3);
  pointer-events: none;
}

/* Devise choisie dans le champ lui-même, à la place de l'unité fixe. */
.unitfield__sel {
  position: absolute;
  right: .35rem;
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: .85rem;
  color: var(--text-2);
  padding: .2rem .3rem;
  border-radius: 6px;
}

.unitfield__sel:hover {
  background: var(--surface-3);
  color: var(--text);
}

.formactions {
  position: sticky;
  bottom: 0;
  display: flex;
  gap: .6rem;
  justify-content: flex-end;
  padding: 1rem 0;
  background: linear-gradient(to top, var(--bg) 70%, transparent);
  flex-wrap: wrap;
  z-index: 5;
}

.formactions .btn--danger {
  margin-right: auto;
}

/* champ image */
.imgfield__row {
  display: flex;
  gap: .7rem;
  align-items: flex-start;
}

.imgfield__preview {
  flex: 0 0 auto;
  width: 62px;
  height: 62px;
  border-radius: var(--r-control);
  border: 1px dashed var(--line-strong);
  background: var(--surface-2);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.imgfield__preview img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 8%;
}

.imgfield__none {
  font-size: .66rem;
  color: var(--text-3);
}

.imgfield__ctrl {
  flex: 1 1 auto;
  display: grid;
  gap: .4rem;
  min-width: 0;
}

.imgfield__btns {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  align-items: center;
}

.gallery-edit {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
}

.gthumb {
  position: relative;
  margin: 0;
  width: 104px;
}

.gthumb img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
}

.gthumb__x {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 22px;
  height: 22px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.gthumb__x:hover {
  color: var(--danger);
  border-color: currentColor;
}

/* étiquettes de langues et logiciels associés */
.taglist {
  display: flex;
  gap: .35rem;
  flex-wrap: wrap;
  min-height: 1.9rem;
}

.taglist__item,
.assoc {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .26rem .3rem .26rem .7rem;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
  font-size: .82rem;
  font-weight: 560;
}

.taglist__x {
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  width: 18px;
  height: 18px;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  opacity: .7;
}

.taglist__x:hover {
  opacity: 1;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
}

.assoclist {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  min-height: 1.9rem;
}

.assoc {
  padding-left: .3rem;
}

.assoc .logo {
  border: 0;
}

.assoc__name {
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- 11. Suggestions ---------------------------------------------- */

.sugglist {
  display: grid;
  gap: .6rem;
}

.sugg {
  display: flex;
  gap: .9rem;
  align-items: flex-start;
  flex-wrap: wrap;
  padding: .9rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--surface);
}

.sugg--done {
  opacity: .58;
}

.sugg__kind {
  flex: 0 0 auto;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: .2rem .5rem;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-3);
}

.sugg__kind--extension {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent);
}

.sugg__main {
  flex: 1 1 16rem;
  min-width: 0;
}

.sugg__name {
  font-weight: 620;
}

.sugg__meta {
  font-size: .8rem;
  color: var(--text-3);
}

.sugg__note {
  font-size: .85rem;
  color: var(--text-2);
  margin-top: .35rem;
}

.sugg__act {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  margin-left: auto;
}

/* ---------- 12. Répertoire des ajouts -------------------------------------
   Apparence de journal, délibérément éloignée des cartes du catalogue :
   rail vertical, horodatage en chasse fixe, densité forte.
   -------------------------------------------------------------------------- */

.formpage--journal {
  max-width: 940px;
}

.journalblock {
  margin-top: 2rem;
}

.journalblock__head {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding-bottom: .6rem;
  border-bottom: 2px solid var(--text);
  margin-bottom: .9rem;
}

.journalblock__title {
  font-size: 1.05rem;
  letter-spacing: -.01em;
}

.journalblock__n {
  font-size: .78rem;
  color: var(--text-3);
  margin-left: auto;
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: .1rem .5rem;
  border-radius: var(--r-pill);
}

.journal__none {
  font-size: .88rem;
  color: var(--text-3);
  padding: .6rem 0;
}

.pill {
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: .12rem .45rem;
  border-radius: 5px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-3);
}

.pill--extension {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent);
}

.trashlist {
  display: grid;
  gap: 0;
}

.trashrow {
  display: flex;
  align-items: center;
  gap: .8rem;
  flex-wrap: wrap;
  padding: .7rem .2rem;
  border-bottom: 1px solid var(--line);
}

.trashrow__main {
  flex: 1 1 14rem;
  min-width: 0;
}

.trashrow__name {
  font-weight: 600;
  font-size: .93rem;
}

.trashrow__meta {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  font-size: .76rem;
  color: var(--text-3);
  margin-top: .15rem;
}

.trashrow__act {
  display: flex;
  gap: .4rem;
  margin-left: auto;
}

.journal {
  display: grid;
  position: relative;
  padding-left: 1.1rem;
}

.journal::before {
  content: "";
  position: absolute;
  left: 3px;
  top: .6rem;
  bottom: .6rem;
  width: 2px;
  background: var(--line);
}

.journal__row {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: .8rem;
  flex-wrap: wrap;
  padding: .48rem 0;
}

.journal__dot {
  position: absolute;
  left: -1.1rem;
  top: .82rem;
  width: 8px;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
  box-shadow: 0 0 0 3px var(--bg);
}

.journal__row--creation .journal__dot {
  background: var(--ok);
}

.journal__row--suppression .journal__dot {
  background: var(--danger);
}

.journal__row--restauration .journal__dot {
  background: var(--accent);
}

.journal__when {
  font-size: .74rem;
  color: var(--text-3);
  flex: 0 0 12rem;
}

.journal__what {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  min-width: 0;
}

.journal__action {
  font-size: .82rem;
  font-weight: 600;
}

.journal__name {
  font-size: .88rem;
  color: var(--accent);
}

.journal__name:hover {
  text-decoration: underline;
}

.journal__name--gone {
  color: var(--text-3);
  text-decoration: line-through;
}

/* ---------- 13. Sélecteur d'association ----------------------------------- */

.picker {
  display: grid;
  gap: .3rem;
  max-height: 46vh;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: .4rem;
  background: var(--surface-2);
}

.picker__empty {
  font-size: .86rem;
  color: var(--text-3);
  padding: 1rem;
  text-align: center;
}

.pickrow {
  display: flex;
  align-items: center;
  gap: .7rem;
  width: 100%;
  text-align: left;
  padding: .5rem .6rem;
  border-radius: var(--r-control);
  border: 1px solid transparent;
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease),
    background-color var(--theme-dur) var(--theme-ease);
}

.pickrow:hover {
  border-color: var(--line-strong);
}

.pickrow[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.pickrow__txt {
  display: grid;
  min-width: 0;
  flex: 1 1 auto;
}

.pickrow__name {
  font-weight: 600;
  font-size: .9rem;
}

.pickrow__vendor {
  font-size: .76rem;
  color: var(--text-3);
}

.pickrow__state {
  font-size: .78rem;
  color: var(--text-3);
  font-weight: 560;
  flex: 0 0 auto;
}

.pickrow[aria-pressed="true"] .pickrow__state {
  color: var(--accent);
}

/* ---------- 14. Modale et toasts ------------------------------------------ */

.modal {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgb(20 16 12 / .55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  animation: fade .18s var(--ease);
}

@keyframes fade {
  from {
    opacity: 0;
  }
}

.modal__box {
  width: min(520px, 100%);
  max-height: 88dvh;
  overflow: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lg);
  padding: 1.4rem;
  animation: pop .24s var(--ease);
}

.modal__box--wide {
  width: min(640px, 100%);
}

@keyframes pop {
  from {
    opacity: 0;
    transform: translateY(12px) scale(.98);
  }
}

.modal__title {
  font-size: 1.15rem;
}

.modal__lead {
  margin-top: .4rem;
  color: var(--text-2);
  font-size: .9rem;
}

.modal__body {
  margin-top: 1.1rem;
  display: grid;
  gap: .9rem;
}

.modal__foot {
  margin-top: 1.2rem;
  display: flex;
  gap: .5rem;
  justify-content: flex-end;
}

.toasts {
  position: fixed;
  bottom: 1rem;
  right: 1rem;
  z-index: 220;
  display: grid;
  gap: .5rem;
  justify-items: end;
  pointer-events: none;
  max-width: calc(100vw - 2rem);
}

.toast {
  background: var(--text);
  color: var(--bg);
  padding: .7rem 1rem;
  border-radius: var(--r-control);
  font-size: .87rem;
  box-shadow: var(--shadow-md);
  animation: toastin .28s var(--ease);
  max-width: min(380px, 88vw);
}

@keyframes toastin {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

/* ---------- 15. Pied de page --------------------------------------------- */

/* Note de fin de contenu.

   C'etait un <footer> a fond plein, du temps ou la maquette occupait seule la
   page. Le site ayant le sien, les deux s'empilaient en deux bandes. La mention
   reste — c'est un avertissement d'usage, pas une decoration — mais sans fond
   ni bordure, posee au fil du contenu juste avant le vrai pied de page. */
.mention {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 1.6rem var(--gut) 2.4rem;
  font-size: .82rem;
  color: var(--text-3);
  line-height: 1.6;
}

.mention__compte {
  font-family: var(--font-mono);
  white-space: nowrap;
}

/* ==========================================================================
   16. Tablette et téléphone
   La barre haute cesse d'être collante sur petit écran : elle libère sa place
   au profit de la seule barre de recherche, qui reste accessible en défilant.
   ========================================================================== */

@media (max-width: 980px) {
  .detail {
    grid-template-columns: 1fr;
  }

  .aside {
    position: static;
  }
}

@media (max-width: 860px) {
  .rowcard__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .rowcard__grid .field[style*="span 2"] {
    grid-column: 1 / -1 !important;
  }
}

@media (max-width: 760px) {
  .fgrid {
    grid-template-columns: 1fr;
  }

  .journal__when {
    flex: 1 1 100%;
  }

  .journal__row {
    padding-block: .55rem;
  }
}

@media (max-width: 720px) {
  html {
    --topbar-h: 0px;
  }

  .topbar {
    position: static;
  }

  /* La barre reste sur une ligne tant que son contenu tient. Le passage à la
     ligne n'est plus imposé par la largeur d'écran mais laissé au flex, qui ne
     le déclenche que lorsque la place manque réellement. */
  .topbar__inner {
    height: auto;
    min-height: 56px;
    padding-block: .5rem;
    flex-wrap: wrap;
    row-gap: .5rem;
  }

  .topbar__actions {
    margin-left: auto;
    gap: .4rem;
  }

  .lbl-full {
    display: none;
  }

  .lbl-short {
    display: inline;
  }

  .roleswitch__opt {
    padding: .55rem .8rem;
    font-size: .8rem;
  }

  .brand__text {
    font-size: 1rem;
  }

  .adminbar__inner {
    padding-block: .5rem;
  }

  .adminbar__links {
    margin-left: 0;
    width: 100%;
  }

  .adminbar__links .btn {
    flex: 1 1 auto;
  }

  /* Deux lignes compactes, et rien d'autre ne colle. */
  .controls {
    top: 0;
  }

  .controls__inner {
    flex-wrap: wrap;
    gap: .5rem;
    padding-block: .55rem;
  }

  /* Ligne 1 : les deux onglets et le bouton Suggérer réduit à son icône.
     Ligne 2 : recherche et filtres. Deux lignes, pas trois. */
  .tabs {
    flex: 1 1 auto;
  }

  .tab {
    flex: 1 1 0;
    justify-content: center;
    padding-block: .5rem;
  }

  .suggestbtn {
    padding-inline: .75rem;
  }

  .suggestbtn span {
    display: none;
  }

  .searchrow {
    width: 100%;
  }

  .filterbtn__lab {
    display: none;
  }

  .filterbtn {
    padding-inline: .7rem;
  }

  .panelfilters__inner {
    padding-block: .8rem;
  }

  .filterline {
    align-items: flex-start;
  }

  .filterline__lab {
    flex: 1 1 100%;
    min-width: 0;
    margin-bottom: .1rem;
  }

  .intro {
    padding-block: 1.4rem .9rem;
  }

  .intro__title {
    font-size: 1.5rem;
    max-width: none;
  }

  .intro__lead {
    font-size: .92rem;
  }

  .grid {
    grid-template-columns: 1fr;
    gap: .75rem;
  }

  .results {
    padding-top: 1rem;
  }

  /* Cibles tactiles confortables */
  .btn {
    padding: .62rem 1rem;
  }

  .btn--sm {
    padding: .5rem .8rem;
  }

  .chip {
    padding: .55rem .85rem;
    font-size: .84rem;
  }

  .iconbtn {
    width: 40px;
    height: 40px;
  }

  .hero {
    min-height: 0;
  }

  .hero__inner {
    padding: 2.6rem var(--gut) 1.2rem;
    gap: .9rem;
  }

  .hero__id {
    align-items: center;
    gap: .85rem;
  }

  .hero__cta {
    margin-left: 0;
    width: 100%;
  }

  .hero__cta .btn {
    flex: 1 1 auto;
  }

  .logo--84 {
    width: 60px;
    height: 60px;
  }

  .logo--84 .logo__mono {
    font-size: 1.3rem;
  }

  /* Le lien de retour est en position absolue en haut : la marge doit lui
     laisser la place, sinon il chevauche le libellé « Extension ». */
  .exthead__inner {
    padding: 3rem var(--gut) 1.3rem;
  }

  .exthead__cta {
    margin-left: 0;
    width: 100%;
  }

  .exthead__cta .btn {
    flex: 1 1 auto;
  }

  .detail {
    padding-top: 1.4rem;
    gap: 1.6rem;
  }

  .section+.section {
    margin-top: 2rem;
  }

  .section__act {
    margin-left: 0;
    flex: 1 1 100%;
  }

  .section__act .btn {
    width: 100%;
  }

  .osrowbig {
    gap: .5rem .7rem;
  }

  .osrowbig__dl {
    margin-left: 0;
    flex: 1 1 100%;
  }

  .osrowbig__dl .btn {
    width: 100%;
  }

  .osrowbig__note {
    flex: 1 1 100%;
  }

  .pricegrid {
    grid-template-columns: 1fr;
  }

  .hostgrid {
    grid-template-columns: 1fr;
  }

  .ext {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .ext__side {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }

  .deflist__row {
    grid-template-columns: 6rem minmax(0, 1fr);
    gap: .5rem;
  }

  .carousel__track {
    grid-auto-columns: 88%;
  }

  .sugg__act {
    margin-left: 0;
    width: 100%;
  }

  .sugg__act .btn {
    flex: 1 1 auto;
  }

  .trashrow__act {
    margin-left: 0;
    width: 100%;
  }

  .trashrow__act .btn {
    flex: 1 1 auto;
  }

  .formpage {
    padding-top: 1.4rem;
  }

  .rowcard__grid {
    grid-template-columns: 1fr;
  }

  .formactions {
    padding-block: .8rem;
  }

  .formactions .btn {
    flex: 1 1 auto;
  }

  .formactions .btn--danger {
    margin-right: 0;
    order: 3;
    flex: 1 1 100%;
  }

  .imgfield__btns .input {
    max-width: none !important;
    width: 100%;
  }

  .imgfield__btns {
    gap: .4rem;
  }

  .imgfield__btns .btn {
    flex: 1 1 auto;
  }

  /* La modale devient une feuille ancrée en bas, plus atteignable au pouce. */
  .modal {
    place-items: end center;
    padding: 0;
  }

  .modal__box {
    width: 100%;
    max-width: none;
    max-height: 92dvh;
    border-radius: var(--r-card) var(--r-card) 0 0;
    padding: 1.2rem 1.1rem calc(1.2rem + env(safe-area-inset-bottom));
    animation: sheetin .26s var(--ease);
  }

  @keyframes sheetin {
    from {
      transform: translateY(24px);
      opacity: 0;
    }
  }

  .modal__foot {
    position: sticky;
    bottom: 0;
    background: var(--surface);
    padding-top: .8rem;
  }

  .modal__foot .btn {
    flex: 1 1 auto;
  }

  .picker {
    max-height: 40vh;
  }

  .toasts {
    left: 1rem;
    right: 1rem;
    justify-items: stretch;
  }

  .toast {
    max-width: none;
  }
}

/* Sous 500px, la marque et le sélecteur de rôle se resserrent pour tenir sur
   une seule ligne jusqu'aux écrans de 375px. En dessous, le retour à la ligne
   reprend naturellement la main. */
@media (max-width: 500px) {
  .topbar__inner {
    column-gap: .5rem;
  }

  .brand {
    gap: .4rem;
  }

  .brand__section {
    font-size: .62rem;
    letter-spacing: .06em;
    padding: .14rem .42rem;
  }

  .roleswitch {
    padding: 2px;
  }

  /* Le rognage ne porte que sur l'horizontale : la hauteur reste confortable
     au pouce. */
  .roleswitch__opt {
    padding: .6rem .6rem;
  }

  .iconbtn {
    width: 36px;
    height: 36px;
  }
}

@media (max-width: 420px) {
  body {
    font-size: 15px;
  }

  .topbar__inner {
    column-gap: .35rem;
  }

  .brandzone {
    gap: .35rem;
  }

  /* Le chevron disparaît sur les écrans les plus étroits : ces quelques
     pixels décident du maintien de la barre sur une seule ligne, et la
     pastille reste cliquable avec son infobulle. */
  button.brand__section {
    gap: 0;
  }

  button.brand__section svg {
    display: none;
  }

  .brand {
    gap: .35rem;
  }

  .brand__text {
    font-size: .95rem;
  }

  .brand__section {
    font-size: .58rem;
    padding: .12rem .36rem;
  }

  .roleswitch__opt {
    padding: .65rem .5rem;
    font-size: .76rem;
  }

  .card {
    padding: .85rem;
  }

  .journalblock__title {
    font-size: .98rem;
  }
}

/* ---------- 17. Mouvement réduit ----------------------------------------- */

@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  .grid>* {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   18. Modifications en attente de validation
   Une fiche modifiée reste publiée telle quelle : la version proposée n'est
   visible que par l'administrateur, sous forme de comparatif, jusqu'à ce
   qu'il la valide.
   ========================================================================== */

/* bandeau de la page principale */
.bandeau {
  margin-top: 1.2rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: .8rem 1rem;
  border-radius: var(--r-card);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
}

.bandeau__txt {
  flex: 1 1 16rem;
  min-width: 0;
}

.bandeau__titre {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .95rem;
  color: var(--accent);
}

.bandeau__liste {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem .5rem;
  margin-top: .25rem;
}

.bandeau__lien {
  font-size: .82rem;
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--accent-line);
  text-underline-offset: 2px;
}

.bandeau__lien:hover {
  text-decoration-color: var(--accent);
}

.bandeau__reste {
  font-size: .82rem;
  color: var(--text-3);
}

/* marqueur sur les cartes */
.card--attente {
  border-color: var(--accent);
}

.card__attente {
  position: absolute;
  top: -1px;
  right: -1px;
  z-index: 2;
  font-family: var(--font-display);
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  background: var(--accent);
  color: var(--on-accent);
  padding: .2rem .55rem;
  border-radius: 0 var(--r-card) 0 var(--r-card);
}

/* bandeau de comparaison sur la fiche */
.attente {
  border: 1px solid var(--accent);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: 1.1rem;
  margin-bottom: 2rem;
}

.attente__head {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
}

.attente__pastille {
  font-family: var(--font-display);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  background: var(--accent);
  color: var(--on-accent);
  padding: .2rem .6rem;
  border-radius: var(--r-pill);
}

.attente__date {
  font-size: .76rem;
  color: var(--text-3);
}

.attente__lead {
  margin-top: .6rem;
  font-size: .88rem;
  color: var(--text-2);
}

.diff {
  margin-top: .9rem;
  display: grid;
  gap: .1rem;
}

.diff__row {
  display: grid;
  grid-template-columns: 9rem minmax(0, 1fr) minmax(0, 1fr);
  gap: .8rem;
  align-items: start;
  padding: .55rem 0;
  border-top: 1px solid var(--line);
  font-size: .86rem;
}

.diff__champ {
  font-weight: 620;
  color: var(--text);
}

.diff__avant,
.diff__apres {
  min-width: 0;
  overflow-wrap: anywhere;
}

.diff__avant {
  color: var(--text-3);
}

/* Le barré ne porte que sur la valeur : appliqué au parent, il rayerait
   aussi le libellé « Avant », car text-decoration se propage. */
.diff__avant .diff__val {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.diff__val {
  display: block;
}

.diff__apres {
  color: var(--text);
}

.diff__tag {
  display: block;
  font-size: .64rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: .15rem;
  text-decoration: none;
}

.diff__apres .diff__tag {
  color: var(--accent);
}

.diff__aucun {
  margin-top: .8rem;
  font-size: .86rem;
  color: var(--text-3);
}

.attente__act {
  display: flex;
  gap: .5rem;
  margin-top: 1.1rem;
  flex-wrap: wrap;
}

/* ligne du répertoire */
.trashrow--attente {
  border-left: 3px solid var(--accent);
  padding-left: .7rem;
}

@media (max-width: 720px) {
  .diff__row {
    grid-template-columns: 1fr;
    gap: .35rem;
    padding-block: .7rem;
  }

  .diff__champ {
    font-size: .82rem;
  }

  .attente__act .btn {
    flex: 1 1 auto;
  }

  .bandeau {
    margin-top: 1rem;
  }

  .bandeau .btn {
    width: 100%;
  }
}

/* ==========================================================================
   19. Menu de section
   La pastille « Search » de la barre haute ouvre la liste des bibliothèques
   de la section. Elle reste un simple bouton : aucune largeur en plus, ce qui
   compte sur les écrans étroits où la barre est déjà juste.
   ========================================================================== */

.brandzone {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  min-width: 0;
}

button.brand__section {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  cursor: pointer;
  line-height: 1.2;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

button.brand__section:hover {
  background: var(--accent-line);
}

button.brand__section svg {
  flex: 0 0 auto;
  transition: transform var(--dur) var(--ease);
}

button.brand__section[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

.sectionmenu {
  position: absolute;
  top: calc(100% + .5rem);
  left: 0;
  z-index: 80;
  width: min(19rem, calc(100vw - 2rem));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lg);
  padding: .45rem;
  animation: menuin .16s var(--ease);
}

@keyframes menuin {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
}

.sectionmenu__titre {
  font-family: var(--font-display);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-3);
  padding: .35rem .6rem .45rem;
}

.sectionmenu__item {
  display: grid;
  gap: .1rem;
  padding: .55rem .6rem;
  border-radius: var(--r-control);
  border: 1px solid transparent;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.sectionmenu__item:hover {
  background: var(--surface-2);
}

.sectionmenu__item.is-actif {
  background: var(--accent-soft);
  border-color: var(--accent-line);
}

.sectionmenu__lab {
  font-weight: 620;
  font-size: .9rem;
}

.sectionmenu__item.is-actif .sectionmenu__lab {
  color: var(--accent);
}

.sectionmenu__det {
  font-size: .78rem;
  color: var(--text-3);
}

.sectionmenu__pied {
  font-size: .74rem;
  color: var(--text-3);
  padding: .55rem .6rem .3rem;
  border-top: 1px solid var(--line);
  margin-top: .35rem;
}

/* Avertissement en tête d'un formulaire — ce qu'on doit savoir avant de
   remplir, pas après. Le jaune signale un fonctionnement incomplet, non une
   erreur : rien n'échoue, c'est précisément le problème. */
.notice {
  margin-top: 1rem;
  padding: .8rem 1rem;
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
  font-size: .88rem;
  line-height: 1.55;
  color: var(--text-2);
}

.notice b {
  color: var(--text);
}

.notice--warn {
  border-color: color-mix(in srgb, #d9a441 55%, var(--line));
  background: color-mix(in srgb, #d9a441 10%, var(--surface));
}

/* ==========================================================================
   Basculement clair/sombre — une seule cadence

   Le thème change des variables ; tout ce qui les utilise change avec elles.
   Mais seuls les éléments ayant une déclaration `transition` le faisaient en
   fondu : les autres sautaient d'une couleur à l'autre. La page basculait donc
   en deux temps, une partie glissant pendant que l'autre était déjà arrivée.

   Cette règle donne la cadence commune à tout le reste. Elle est écrite avec
   :where(), qui ne pèse rien : n'importe quelle règle de composant portant sa
   propre `transition` l'emporte entièrement — les boutons gardent leur
   animation de survol, les cartes leur mouvement au pointeur. Elle ne comble
   que les silences.

   Trois propriétés seulement, celles que le thème touche réellement. Une
   transition sur `all` aurait animé les positions et les tailles au moindre
   changement de classe. */
:where(.archiverse-search) *,
:where(.barre-mode) *,
:where(.archiverse-search),
:where(.barre-mode) {
  transition: background-color var(--theme-dur, .22s) var(--theme-ease, ease),
    border-color var(--theme-dur, .22s) var(--theme-ease, ease),
    color var(--theme-dur, .22s) var(--theme-ease, ease);
}

/* Le mouvement n'est pas un ornement pour tout le monde : qui l'a désactivé
   dans son système ne doit pas le retrouver ici. */
@media (prefers-reduced-motion: reduce) {

  :where(.archiverse-search) *,
  :where(.barre-mode) * {
    transition-duration: .01ms;
  }
}


/* ==========================================================================
   Compteurs de pied de carte : écoles, extensions

   Un nombre puis un pictogramme, dans cet ordre : le chiffre est
   l'information, l'icône la qualifie. Placée devant, elle se lirait comme une
   étiquette et ferait chercher le nombre.
   ========================================================================== */
.compte {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .74rem;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  padding: .14rem .5rem;
  border-radius: var(--r-pill);
}

.compte__n {
  font-family: var(--font-mono);
  line-height: 1;
}

.compte svg {
  flex: 0 0 auto;
}

/* ==========================================================================
   Sous-titre alternant : fournisseur, puis catégories

   Les deux occupent la même ligne et se relaient. L'animation est lente et
   passe l'essentiel du cycle sur l'un ou l'autre, la transition ne prenant
   qu'un dixième du temps : une ligne qui change sans arrêt se lit mal.

   Les deux textes se superposent en grille plutôt qu'en position absolue :
   la hauteur de la ligne reste celle du plus haut des deux, et la carte ne
   change pas de taille au passage.
   ========================================================================== */
.card__vendor[data-bascule] {
  display: grid;
}

.card__vendor[data-bascule]>* {
  grid-area: 1 / 1;
  animation: bascule-soustitre 14s infinite;

  /* Une seule ligne, toujours. Les catégories sont plus longues que le nom du
     fournisseur — « Mise en page et PAO, Image et retouche » —, et une ligne
     qui passe à deux fait grandir la carte au moment de la bascule : toute la
     grille se réorganise, ce qui attire l'œil bien plus que l'information ne
     le mérite. La liste est donc coupée par des points de suspension.

     min-width: 0 est indispensable en grille : sans lui l'élément refuse de
     descendre sous la largeur de son contenu, et text-overflow n'a jamais
     l'occasion de s'appliquer. */
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card__vendor-b {
  animation-delay: inherit;
}

.card__vendor[data-bascule] .card__vendor-a {
  animation-name: bascule-a;
}

.card__vendor[data-bascule] .card__vendor-b {
  animation-name: bascule-b;
}

@keyframes bascule-a {

  0%,
  45% {
    opacity: 1;
  }

  50%,
  95% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

@keyframes bascule-b {

  0%,
  45% {
    opacity: 0;
  }

  50%,
  95% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

/* Trois temps au lieu de deux : fournisseur, catégories, systèmes.

   Le cycle passe à vingt et une secondes — sept par état, la même durée
   qu'avant. Chaque part occupe un tiers du tour, et la transition prend les
   deux derniers pour cent : une ligne qui change trop souvent se lit mal, et
   la moitié du temps on la relit pour rien.

   La règle à deux temps reste au-dessus : une fiche sans catégorie ni système
   n'a qu'un seul texte, et elle ne doit pas clignoter. */
.card__vendor--trois[data-bascule]>* {
  animation-duration: 21s;
}

.card__vendor--trois[data-bascule] .card__vendor-a {
  animation-name: trois-a;
}

.card__vendor--trois[data-bascule] .card__vendor-b {
  animation-name: trois-b;
}

.card__vendor--trois[data-bascule] .card__vendor-c {
  animation-name: trois-c;
}

@keyframes trois-a {

  0%,
  31% {
    opacity: 1;
  }

  33%,
  98% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

@keyframes trois-b {

  0%,
  31% {
    opacity: 0;
  }

  33%,
  64% {
    opacity: 1;
  }

  66%,
  100% {
    opacity: 0;
  }
}

@keyframes trois-c {

  0%,
  64% {
    opacity: 0;
  }

  66%,
  98% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

/* Une seule des deux lignes suffit à qui a désactivé les animations : on
   garde le fournisseur, qui identifie la fiche. */
@media (prefers-reduced-motion: reduce) {
  .card__vendor[data-bascule]>* {
    animation: none;
  }

  .card__vendor[data-bascule] .card__vendor-b,
  .card__vendor[data-bascule] .card__vendor-c {
    display: none;
  }
}

/* ==========================================================================
   Écoles qui l'enseignent
   ========================================================================== */
.ecoles {
  display: grid;
  gap: .5rem;
}

.ecole {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .5rem;
  padding: .55rem .75rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
}

.ecole__nom {
  font-weight: 600;
}

.ecole__usage {
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  padding: .1rem .45rem;
}

/* La précision passe à la ligne : c'est une phrase, pas une étiquette. */
.ecole__note {
  flex: 1 1 100%;
  font-size: .85rem;
  color: var(--text-2);
}

.ecoleform {
  display: grid;
  gap: .5rem;
  margin-top: .9rem;
}

.ecoleform__ligne {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
}

.ecoleform__ligne>.input {
  flex: 1 1 12rem;
  min-width: 0;
}

.ecoleform__ligne>.btn {
  flex: 0 0 auto;
}

.ecoleform__invite {
  margin-top: .9rem;
  font-size: .88rem;
  color: var(--text-3);
}

@media (max-width: 560px) {

  /* Sur téléphone, chaque champ prend la ligne : côte à côte, le nom de
     l'école se réduirait à « ENSA G… ». */
  .ecoleform__ligne {
    flex-direction: column;
  }

  .ecoleform__ligne>.btn {
    align-self: flex-start;
  }
}

/* ==========================================================================
   Répertoire — le journal en frise

   Une ligne verticale relie les mouvements dans l'ordre du temps. Les
   pastilles pleines marquent ceux qui ont changé l'état d'une fiche — une
   validation, une restauration — pour les distinguer d'une simple proposition,
   qui n'a encore rien fait.
   ========================================================================== */
.frise {
  display: grid;
  gap: 0;
}

.frise__item {
  position: relative;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .6rem;
  padding: .55rem 0 .55rem 1.6rem;
  font-size: .88rem;
}

/* Le trait, tiré d'une pastille à l'autre. Il s'arrête au premier et au
   dernier élément plutôt que de dépasser dans le vide. */
.frise__item::before {
  content: '';
  position: absolute;
  left: .32rem;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--line);
}

.frise__item:first-child::before {
  top: .95rem;
}

.frise__item:last-child::before {
  bottom: calc(100% - .95rem);
}

.frise__item::after {
  content: '';
  position: absolute;
  left: 0;
  top: .8rem;
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: var(--surface);
  border: 1.5px solid var(--line-strong);
}

.frise__item--fort::after {
  background: var(--accent);
  border-color: var(--accent);
}

.frise__quand {
  flex: 0 0 auto;
  color: var(--text-3);
  font-size: .8rem;
}

.frise__quoi {
  font-weight: 600;
}

.frise__cible {
  color: var(--accent);
  font-weight: 560;
}

.frise__cible:hover {
  text-decoration: underline;
}

.frise__qui {
  color: var(--text-3);
  font-size: .82rem;
}

@media (max-width: 640px) {

  /* Sur téléphone, la date prend sa ligne : côte à côte, le nom de la fiche
     se retrouverait coupé au troisième mot. */
  .frise__quand {
    flex: 1 1 100%;
  }
}

/* Le compteur d'une légende de fieldset — combien de fiches dans la section.
   Aligné à droite du titre, dans le même gris que les intitulés secondaires :
   c'est une indication, pas une alerte. */
.legend__n {
  display: inline-grid;
  place-items: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 .4rem;
  margin-left: .55rem;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: .72rem;
  font-weight: 700;
  line-height: 1;
  vertical-align: middle;
}

/* ==========================================================================
   Fiche à la corbeille

   Le panneau change de nature : il n'administre plus, il annonce une échéance
   et propose deux issues opposées. Le bouton de destruction est plein et
   rouge — c'est le seul geste du site qui efface vraiment, il ne doit pas
   ressembler aux autres.
   ========================================================================== */
/* Le panneau d'une fiche à la corbeille.

   Il héritait du fond bleu de .panel--admin, celui des commandes ordinaires :
   seuls sa bordure et son titre étaient rouges, et l'ensemble se lisait comme
   un panneau d'administration comme un autre. Un bandeau qui annonce une
   suppression prochaine doit être rouge de bout en bout — la couleur porte ici
   l'essentiel du message. */
.panel--corbeille {
  background: var(--danger-soft);
  border-color: var(--danger-line);
}

.panel--corbeille .panel__title {
  color: var(--danger);
}

.panel--corbeille .panel__lead {
  color: color-mix(in srgb, var(--danger) 72%, var(--text));
}

.panel__lead {
  margin: .4rem 0 .9rem;
  font-size: .85rem;
  color: var(--text-2);
  line-height: 1.55;
}

/* Rétablir est un geste qui répare : le vert le dit, là où le bleu de l'accent
   ne disait rien de particulier — c'est la couleur de n'importe quelle action
   principale. Le fond reste clair : sur le rouge pâle du panneau, un aplat vert
   plein pèserait autant que la suppression, alors que ce n'est pas le geste qui
   engage.

   « Clair » et non « blanc » : c'est le fond des cartes de la charte, blanc en
   thème clair et sombre en thème sombre. Un blanc écrit en dur trouerait la
   page une fois la nuit tombée. */
.btn--retablir {
  background: var(--surface);
  color: var(--ok);
  border: 1px solid var(--ok);
  font-weight: 600;
}

.btn--retablir:hover {
  background: var(--ok-soft);
}

/* Le seul geste du site qui efface vraiment, dans le panneau qui l'annonce :
   plein, rouge, impossible à confondre avec autre chose. */
.btn--detruire {
  background: var(--danger);
  color: var(--on-danger);
  border: 1px solid var(--danger);
  font-weight: 600;
}

.btn--detruire:hover {
  background: var(--danger-hi);
  border-color: var(--danger-hi);
}

/* Le même geste dans le bandeau, à côté du site officiel : en creux.

   Il y est à portée de main, mais le bandeau n'est pas l'endroit où l'on
   explique ce qu'on efface — c'est le panneau qui le fait. Deux aplats rouges
   identiques sur la même page se disputeraient l'attention et banaliseraient
   le geste ; en creux, celui-ci reste lisible sans réclamer le clic. */
.btn--detruire-creux {
  background: var(--surface);
  color: var(--danger);
  border: 1px solid var(--danger);
  font-weight: 600;
}

.btn--detruire-creux:hover {
  background: var(--danger-soft);
}

/* Le jour restant avant la purge, sur chaque ligne de la corbeille. */
.trashrow__delai {
  color: var(--danger, #c0392b);
  font-weight: 600;
}

/* Le lien de retour du bandeau, aligné sur la colonne de contenu.

   Posé directement sur .hero, il se calait à la gouttière de l'écran — quarante
   pixels du bord — alors que le titre, le logo et tout le contenu de la fiche
   commencent à la colonne centrée, cent pixels plus loin sur grand écran.
   L'enveloppe reprend cette colonne : le lien retombe exactement sur la
   verticale du reste.

   Elle est absolue et pleine largeur : sans pointer-events désactivé, ce ruban
   invisible intercepterait les clics sur toute la largeur du bandeau, y compris
   là où il n'y a rien à cliquer. Le lien, lui, les reprend. */
.hero__retour {
  position: absolute;
  top: 1.1rem;
  left: 0;
  right: 0;
  z-index: 2;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
  pointer-events: none;
}

.hero__retour .backlink {
  position: static;
  pointer-events: auto;
}

/* Le pied d'une carte extension : le bloc de gauche y est vide — une
   extension n'a ni écoles ni sous-extensions — mais il tient sa place pour que
   le régime de tarif tombe au même endroit que sur une carte logiciel. Deux
   grilles côte à côte doivent aligner leurs derniers éléments. */
/* Sur la carte extension, la pastille de tarif tient la droite de la ligne des
   logiciels compatibles. Les noms occupent tout ce qui reste et se coupent aux
   points de suspension ; la pastille garde sa largeur, un tarif tronqué ne
   voulant rien dire. */
.card--ext .card__fortext {
  flex: 1 1 auto;
}

.card--ext .card__tarif {
  flex: 0 0 auto;
  margin-left: auto;
  display: flex;
  gap: .3rem;
  align-items: center;
}

.card--ext .card__tarif .tag {
  white-space: nowrap;
}

/* ==========================================================================
   La feuille d'extension

   Une extension ouverte depuis un logiciel monte du bas de l'écran et se pose
   par-dessus sa fiche, qui reste visible dessous. Ouvrir une extension n'est
   pas quitter le logiciel : on regarde un détail, puis on referme et on reprend
   la lecture où on l'avait laissée.

   Elle ne recouvre pas tout : une bande du logiciel reste visible en haut, ce
   qui dit d'où l'on vient et donne où cliquer pour revenir. C'est la raison
   d'être du format — un panneau plein écran n'aurait rien dit de plus qu'une
   navigation ordinaire.
   ========================================================================== */

.feuille {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.feuille[hidden] {
  display: none;
}

.feuille__voile {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, #000 42%, transparent);
  animation: feuille-voile .2s ease-out;
}

@keyframes feuille-voile {
  from {
    opacity: 0;
  }
}

/* Le panneau monte du bas. La hauteur laisse voir le haut de la page : on garde
   le fil du logiciel sous les yeux, et le vide au-dessus est cliquable. */
/* .archiverse-search impose une hauteur minimale de six dixiemes d ecran et
   sa propre colonne flex : la feuille a deja les siennes. */
.feuille__panneau.archiverse-search {
  min-height: 0;
}

.feuille__panneau {
  position: relative;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  height: 88vh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom: 0;
  border-radius: var(--r-card) var(--r-card) 0 0;
  box-shadow: 0 -8px 40px rgb(0 0 0 / .22);
  overflow: hidden;
  isolation: isolate;
  animation: feuille-monte .28s cubic-bezier(.16, 1, .3, 1);
}

@keyframes feuille-monte {
  from {
    transform: translateY(100%);
  }
}

/* La tête reste en place pendant que le corps défile : la croix ne doit jamais
   être à chercher.

   Sa hauteur est celle de la croix, pas celle de la poignée. Réglée sur la
   poignée seule, elle mesurait dix-huit pixels — et la croix, qui en fait
   trente-quatre et se centre dessus, dépassait de huit pixels de part et
   d'autre : elle sortait par-dessus le coin arrondi du panneau. */
.feuille__tete {
  position: relative;
  flex: none;
  min-height: 3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 1rem;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

/* La poignée ne sert à rien techniquement. Elle dit d'où vient le panneau et
   qu'il peut repartir — c'est la convention des feuilles qui montent. */
.feuille__poignee {
  width: 42px;
  height: 4px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--line-strong);
}

.feuille__croix {
  position: absolute;
  right: .8rem;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.feuille__croix:hover {
  background: var(--surface-2);
  color: var(--text);
}

/* Le corps defile verticalement et coupe l'horizontale : la fiche d'extension
   est dessinee pour la largeur d'une page, et dans un panneau plus etroit ses
   rangees — logiciels compatibles, etiquettes — poussaient une barre de
   defilement laterale sous la feuille. */
.feuille__corps {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Ce qui doit vraiment defiler de cote le fait dans sa propre boite. */
.feuille__corps .hostgrid,
.feuille__corps .carousel {
  overflow-x: auto;
}

/* La bannière de la fiche est plus basse ici : la feuille a déjà sa tête, et
   deux bandeaux l'un sur l'autre mangeraient le tiers de la hauteur. */
.feuille__corps .hero {
  min-height: 0;
}

.feuille__corps .exthead {
  padding-top: 1.2rem;
}

/* Le corps de page ne défile plus tant que la feuille est ouverte. */
body.feuille-ouverte {
  position: fixed;
  width: 100%;
  overflow: hidden;
}

@media (max-width: 720px) {

  /* Sur téléphone la feuille prend presque tout : la bande laissée visible ne
     servirait qu'à rétrécir un contenu déjà à l'étroit. */
  .feuille__panneau {
    height: 94vh;
    border-radius: 14px 14px 0 0;
  }
}