/* =====================================================================
   ESS — Mobile (site public)

   RÈGLE UNIQUE de ce fichier : tout est enfermé dans
   @media (max-width: 768px). Aucune règle desktop n'est touchée, aucune
   autre feuille n'est modifiée. mobile.css est chargé en DERNIER dans le
   <head>, donc il l'emporte à spécificité égale.

   Cible de référence : 375px de large (iPhone SE / 12 mini).
   Portée de cette passe : index.html (accueil) + l'en-tête et le pied de
   page partagés, qui sont injectés par js/layout.js sur toutes les pages.
   ===================================================================== */

@media (max-width: 768px) {

  /* ===================================================================
     0. Jetons ajustés pour le mobile
     =================================================================== */

  :root {
    /* 17px de gouttière sur 375px collait le texte aux bords. */
    --gutter: 1.25rem;
    /* L'en-tête mesure réellement moins haut ici (logo réduit) : les
       décalages « sticky » calculés sur ce jeton restent justes. */
    --header-h: 64px;

    /* ---- Échelle typographique mobile ------------------------------
       SOURCE : UNDP Design System 2.0.1 — @undp/design-system-assets,
       css/base-minimal.min.css. Le PNUD est en mobile-first : ses
       valeurs sans media query SONT les valeurs mobiles.
       Rampe et correspondance documentées dans CLAUDE.md.

       Les paliers sont repris par RÔLE et non par nom de balise : le
       `h1` du PNUD est un titre héros en capitales, en SohneBreit — ce
       n'est pas le `h1` de ce projet. Chaque valeur ci-dessous est un
       échelon réel de leur échelle (12·14·16·20·24·30·32·36·40·48…).

       Motif du remplacement : les `clamp()` du desktop s'écrasent à
       375px sur leur borne basse et produisent h3 22,4px contre h4 22px
       — 0,4px d'écart, hiérarchie morte. */
    /* Corps à 14 et non 16 : écart ASSUMÉ avec le PNUD, demandé par le
       client. Conséquence en cascade : l'échelle PNUD ne propose que 12
       et 14 sous 16, il ne reste donc pas de palier libre pour les
       métadonnées. --fs-sm descend à 13 — seul échelon hors échelle,
       consigné dans CLAUDE.md. L'alternative aurait été de laisser
       --fs-sm à 14, donc égal au corps, et de perdre un niveau. */
    --fs-xs:      0.75rem;    /* 12 — échelon PNUD 12 */
    --fs-sm:      0.8125rem;  /* 13 — HORS échelle PNUD (voir CLAUDE.md) */
    --fs-base:    0.875rem;   /* 14 — écart assumé (PNUD : 16) */
    --fs-lead:    1.25rem;    /* 20 — h5 PNUD / body-default */
    /* Titres redescendus d'un cran de plus (36 jugé encore trop gros).
       L'échelle PNUD n'offre rien entre 24 et 30 : abaisser h1 à 32
       obligeait donc à redescendre h2 à 24, faute de quoi les deux
       n'auraient plus été séparés que par 2px.
       h3 et h4 se retrouvent à égalité — assumé : ils portent le même
       rôle ici (titres de cartes), et le PNUD lui-même fait coïncider
       ses h2/h3 en ne les distinguant que par la graisse. */
    --fs-h4:      1.25rem;    /* 20 — h5 PNUD */
    --fs-h3:      1.25rem;    /* 20 — h5 PNUD */
    --fs-h2:      1.5rem;     /* 24 — échelon PNUD 24 */
    --fs-h1:      2rem;       /* 32 — échelon PNUD 32 */
    --fs-display: 2.5rem;     /* 40 — h2/h3 PNUD */
    --fs-stat:    2.5rem;     /* 40 — échelon PNUD 40 */

    /* Interlignage du corps PNUD. */
    --lh-body: 1.4;
  }

  /* ===================================================================
     1. Garde-fous globaux
     =================================================================== */

  /* Un libellé long ne doit jamais pousser la page en débordement
     horizontal : sur 375px, « Trouver mon accompagnement » frôle la
     largeur disponible avec le `white-space: nowrap` du desktop. */
  .btn { white-space: normal; text-align: center; }

  /* Tout le texte courant à 16px. Les chapôs du desktop sont à 18px
     (--fs-lead) : sur une colonne de 68 caractères l'écart se lit comme
     une mise en avant, sur 40 caractères il ne produit qu'un paragraphe
     plus large qui pousse le reste vers le bas.
     Le jeton --fs-lead reste à 18px pour les TITRES de composants qui
     l'utilisent — c'est là qu'un cran au-dessus du corps a du sens. */
  .lead,
  .section-head .lead,
  .prose .lead,
  .prose blockquote,
  .fiche2__desc,
  .quote-card blockquote,
  .hero__lead,
  .obj2__lead,
  .footer-hi p { font-size: var(--fs-base); }

  /* Cible tactile de 44px sur les commandes d'interface. */
  .icon-btn { width: 44px; height: 44px; }

  /* --- Fil d'Ariane réduit au parent --------------------------------
     Sur 375px, « Accueil » et la page courante n'apprennent rien : on
     sait où l'on est, et le logo ramène à l'accueil. Seul le maillon
     parent porte une information — c'est le seul qu'on garde, sous
     forme de retour, avec la flèche posée par js/layout.js.
     Les <li> restent DANS le DOM, simplement masqués : le balisage
     conserve sa valeur pour les moteurs de recherche. */
  .breadcrumb li:not(:nth-last-child(2)) { display: none; }
  /* Le séparateur « / » vient de `li + li` : le parent devenant le
     premier maillon visible, il traînerait une barre oblique en tête. */
  .breadcrumb li:nth-last-child(2)::before { content: none; }
  /* Ce lien n'est plus un repère décoratif : c'est le retour vers le
     parent, donc une VRAIE commande. Il lui faut la hauteur de frappe
     des commandes, 44px, et non les ~18px d'un fil d'Ariane desktop.
     Le rembourrage part vers la droite : le bord gauche reste aligné sur
     la gouttière, donc sur le titre en dessous. */
  .breadcrumb a {
    display: inline-flex; align-items: center; gap: 8px;
    min-height: 44px; padding-right: var(--sp-3);
    font-size: var(--fs-base); font-weight: var(--fw-semi);
    color: var(--c-blue);
  }
  .breadcrumb .ico { width: 18px; height: 18px; flex: none; }

  /* Les titres de l'échelle PNUD sont taillés pour des manchettes de deux
     ou trois mots. Le français en aligne de bien plus longs :
     « Accompagnement » fait 14 caractères et, à 40px sur 335px, débordait
     à droite — un mot ne peut pas revenir à la ligne tout seul.
     `hyphens: auto` coupe proprement (la page déclare lang="fr", le
     navigateur applique donc les règles françaises) ; `overflow-wrap`
     reste le filet de sécurité si le dictionnaire manque. */
  h1, h2, h3, h4, h5 {
    hyphens: auto;
    overflow-wrap: break-word;
  }

  /* EXCEPTION au corps à 14px — les champs de saisie restent à 16px.
     Ce n'est pas un choix de style : en dessous de 16px, Safari iOS
     agrandit automatiquement la page à la mise au point d'un champ et
     l'utilisateur se retrouve décadré, sans moyen simple de revenir.
     Concerne la recherche, la newsletter et les filtres. */
  .input, .select, .textarea, .search input { font-size: 1rem; }

  /* ===================================================================
     2. En-tête + menu off-canvas
     =================================================================== */

  /* La nav principale est masquée sous 1040px : sans elle, ses marges
     automatiques disparaissent et le logo se retrouve collé aux actions. */
  .header__inner { gap: var(--sp-3); justify-content: space-between; }
  .brand img { height: 36px; }
  .header__actions { gap: var(--sp-2); }

  /* La recherche revient dans la barre. css/layout.css la masque sous
     1040px : elle n'était plus atteignable qu'en ouvrant le menu, alors
     que le logo ne mesure que 41px de large et laisse la place. */
  .header__actions .search-open { display: grid; }

  .mobile-menu__panel { width: min(92vw, 360px); padding: var(--sp-4); }
  .mobile-nav a { padding-block: 0.95em; }
  .mobile-menu__cta .btn { width: 100%; }

  /* Rubrique dépliante (Académie). Le chevron vient de la bibliothèque
     HugeIcons via icon('chevron') — pas d'un tracé CSS. */
  .mobile-nav__group > summary {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0.95em 0.5em;
    border-bottom: 1px solid var(--c-line);
    font-weight: var(--fw-medium); color: var(--c-ink);
    cursor: pointer; list-style: none;
  }
  .mobile-nav__group > summary::-webkit-details-marker { display: none; }
  .mobile-nav__group > summary .ico {
    color: var(--c-blue);
    transition: transform var(--dur-fast) var(--ease);
  }
  .mobile-nav__group[open] > summary { color: var(--c-blue); }
  .mobile-nav__group[open] > summary .ico { transform: rotate(180deg); }

  /* ---- Recherche surgissante ---------------------------------------
     La coque .mobile-menu fournit déjà le fixe plein écran, l'état
     masqué et le fondu du voile ; il ne reste que la barre du haut. */
  [data-search] .mobile-menu__scrim { background: rgba(0, 0, 0, 0.3); }
  .search-pop {
    position: absolute; top: 0; left: 0; right: 0;
    padding: var(--sp-4);
    padding-top: max(var(--sp-4), env(safe-area-inset-top));
    background: var(--c-paper);
    border-bottom: 1px solid var(--c-line);
    box-shadow: var(--sh-md);
    transform: translateY(-100%);
    transition: transform var(--dur) var(--ease);
  }
  .mobile-menu.is-open .search-pop { transform: translateY(0); }
  /* Rembourrage horizontal seul : la hauteur vient de --control-h. */
  .search-pop .search { padding-inline: 1em 4px; }
  /* 16px minimum : en dessous, iOS zoome sur le champ à la mise au point. */
  .search-pop .search input { min-width: 0; font-size: var(--fs-base); }
  .search-pop .icon-btn { border: 0; color: var(--c-slate); }
  .search-pop .icon-btn:hover { background: var(--c-mist); border-color: transparent; }

  /* Le choix de la langue passe dans le menu burger (globe + déroulant,
     rendu par js/layout.js) : la pastille FR|ع quitte la barre du haut,
     déjà chargée sur 375px. */
  .header__actions .lang-toggle { display: none; }

  /* La rangée « Langue » se lit comme un lien de navigation de plus. */
  .mobile-menu__panel .acct__btn {
    width: 100%; padding: 0.95em 0.5em;
    border: 0; border-bottom: 1px solid var(--c-line); border-radius: 0;
    font-weight: var(--fw-medium);
  }
  .mobile-menu__panel .acct__btn .ico { width: 20px; height: 20px; color: var(--c-blue); }
  .mobile-menu__panel .acct__btn .ico:last-child { margin-left: auto; color: var(--c-slate); }
  .mobile-menu__panel .acct__menu { left: 0; right: auto; width: 100%; }
  .mobile-menu__panel .acct__menu button { padding: 0.8rem 0.7rem; font-size: var(--fs-base); }

  /* Le compte quitte la barre du haut : l'avatar et son déroulant
     répétaient « Mon espace ESS » et « Déconnexion », déjà présents dans
     le menu burger. La barre ne garde qu'un seul appel à l'action.
     Le sélecteur reste borné à .header__actions : le menu « Langue » du
     panneau burger réutilise ces mêmes classes .acct et n'est pas visé. */
  .header__actions .acct { display: none; }
  /* Le bouton libellé reste au desktop (masqué ici par layout.css) ; le
     mobile le révèle : c'est le même bouton « S'inscrire » aux deux
     largeurs, pas une doublure à maintenir en double. */
  .header__actions .btn { display: inline-flex; }

  /* Les actions du compte tombent en bas du panneau. */
  .mobile-menu__cta { margin-top: auto; }
  /* Déconnexion en rouge de REFUS — en contour, jamais en aplat : c'est
     une action secondaire, même règle que .btn--danger (components.css). */
  .mobile-menu__cta [data-logout-ext] {
    background: transparent;
    color: var(--c-danger);
    border-color: var(--c-danger);
  }
  .mobile-menu__cta [data-logout-ext]:hover {
    background: var(--c-danger);
    border-color: var(--c-danger);
    color: #fff;
  }
  .mobile-menu__cta [data-logout-ext]:focus-visible { outline-color: var(--c-danger); }

  /* ===================================================================
     3. Héros plein écran
     =================================================================== */

  /* Le titre garde sa taille desktop : son clamp descend déjà à 2,1rem
     sur 375px, ce qui est juste. */
  .hero-full { min-height: 78svh; }
  .hero-full__inner { padding-block: var(--sp-7) var(--sp-6); }
  .hero-full__lead { font-size: var(--fs-base); margin-top: var(--sp-4); }
  .hero-full__cta { margin-top: var(--sp-5); }
  /* Deux CTA empilés pleine largeur : plus lisibles et plus faciles à
     viser que deux boutons à moitié coupés sur une même ligne. */
  .hero-full__cta .btn { width: 100%; }

  /* ===================================================================
     4. « Qu'est-ce que l'ESS ? »
     =================================================================== */

  /* Ordre demandé : titre → image → texte. Le titre et le texte sont
     enfermés ensemble dans .ess-def__body, l'image est leur voisine :
     `display: contents` dissout cette boîte pour que les six blocs
     deviennent frères dans la grille et se réordonnent librement.
     La grille passe à gap:0 — chaque bloc porte déjà ses marges. */
  .ess-def__grid { gap: 0; }
  .ess-def__body { display: contents; }
  .ess-def__body > .eyebrow { order: 1; }
  .ess-def__title { order: 2; }
  .ess-def__media { order: 3; margin-block: var(--sp-5); }
  .ess-def__lead { order: 4; }
  .ess-def__text { order: 5; }
  .ess-def__initiative { order: 6; }

  .ess-def__media img { height: clamp(240px, 56vw, 320px); }
  .ess-def__badge { padding: var(--sp-3) var(--sp-4); gap: var(--sp-3); max-width: 88%; }
  .ess-def__badge-k { width: 46px; height: 46px; font-size: var(--fs-base); }
  .ess-def__initiative { margin-top: var(--sp-6); padding-top: var(--sp-5); }
  .ess-def__orgs { gap: var(--sp-3) var(--sp-4); }
  .ess-def__orgs img { height: 32px; }

  /* ===================================================================
     5. Nos objectifs (cartes impact)
     =================================================================== */

  /* Toutes les têtes de section de l'accueil à gauche — deux d'entre
     elles sont centrées sur desktop (« Nos objectifs » et
     « Accompagnement »). Sur 375px un titre centré perd : ses deux bords
     sont irréguliers et il ne partage plus de marge de départ avec le
     texte qui le suit, ce qui casse la ligne de lecture.
     Ciblé par body[data-page="accueil"] — l'attribut n'existe que sur
     index.html, les autres pages gardent leurs titres centrés. */
  body[data-page="accueil"] .section-head.center { text-align: left; }
  /* !important forcé : l'alignement de l'œilleton est posé en style en
     ligne dans index.html, que je n'ai pas le droit de modifier. */
  body[data-page="accueil"] .section-head.center .eyebrow {
    justify-content: flex-start !important;
  }

  /* Une seule carte à l'écran, pleine largeur : les deux autres restent
     hors champ à droite. Pas de débord vers les bords, pas d'aperçu de
     la suivante. */
  /* Empilées : les trois objectifs se comparent, un rail les rendait
     mutuellement invisibles. */
  .impact { grid-template-columns: 1fr; max-width: none; gap: var(--sp-4); }
  /* Photo raccourcie de 4/3 à 16/9 : 251px → 188px par carte, soit près
     de 190px gagnés sur la section, sans que l'image cesse de porter. */
  .impact-card__media { aspect-ratio: 16 / 9; }
  .impact-card__num { width: 26px; height: 26px; }
  .impact-card__title { gap: var(--sp-2); }

  /* Points de progression : cible tactile de 28×44px, pastille visuelle
     de 7px. Seules la couleur et l'échelle changent d'un état à l'autre —
     ni largeur ni marge animées, donc aucun recalcul de mise en page. */
  .rail-dots { display: flex; flex-wrap: wrap; justify-content: center; margin-top: var(--sp-2); }
  .rail-dots__dot {
    width: 28px; height: 44px; padding: 0;
    display: grid; place-items: center;
    border-radius: var(--r-pill);
  }
  .rail-dots__dot::before {
    content: "";
    width: 7px; height: 7px; border-radius: var(--r-pill);
    background: var(--c-line-strong);
    transition: background var(--dur-fast) var(--ease),
                transform var(--dur-fast) var(--ease);
  }
  .rail-dots__dot.is-active::before {
    background: var(--c-blue);
    transform: scale(1.6);
  }
  .impact-card__body { padding: var(--sp-4) var(--sp-4) var(--sp-5); }

  /* ===================================================================
     6. Accompagnement (parcours en 4 étapes)
     =================================================================== */

  /* La grille passe déjà en une colonne sous 860px (home.css) : l'image
     est donc au-dessus des étapes. On garde cet ordre et on retravaille
     les étapes en parcours vertical numéroté.
     L'interaction existe déjà — js/home.js:92 bascule .is-active au tap,
     avec aria-current. Rien à recâbler, seulement à révéler. */
  .accomp2 { gap: var(--sp-5); margin-top: var(--sp-6); max-width: none; }
  /* Le cadre desktop impose 440px de haut : sur 335px de large cela
     donne un portrait qui mange l'écran. Un 16/10 reste large sans
     dominer, et conserve les coins arrondis du desktop. */
  .accomp2__frame { height: auto; min-height: 0; aspect-ratio: 16 / 10; }
  .accomp2__toggle { top: var(--sp-3); right: var(--sp-3); }

  /* Un parcours continu, pas une suite de lignes : les filets de
     séparation disparaissent au profit d'un trait vertical qui relie
     les pastilles numérotées. */
  .accomp2__step { position: relative; border-top: 0; }
  .accomp2__step::before {
    content: "";
    position: absolute; left: 16px; width: 2px;
    /* Départ fixe à 40px, entre les deux rembourrages possibles (8+34 et
       12+34) : la pastille se peint APRÈS le ::before du parent, elle
       recouvre donc le léger dépassement au lieu de le laisser voir. */
    top: 40px; bottom: 0;
    background: var(--c-line);
    transition: background var(--dur) var(--ease);
  }
  .accomp2__step:last-child::before { content: none; }
  /* Le segment sous l'étape active reprend le vert de parcours. */
  .accomp2__step.is-active::before { background: var(--c-green); }

  /* Seule l'étape ouverte a besoin de respirer. Les trois en veille se
     resserrent — c'est ce qui permet de garder l'image à l'écran quand
     la DERNIÈRE étape est dépliée : ~48px récupérés sur les trois. */
  .accomp2__stepbtn { padding: var(--sp-3) 0; gap: var(--sp-3); align-items: start; }
  .accomp2__step:not(.is-active) .accomp2__stepbtn { padding-block: var(--sp-2); }
  /* 18px : HORS échelle PNUD, demandé explicitement (voir CLAUDE.md).
     Le corps ayant été fixé à 14, l'échelle n'offre plus rien entre 14 et
     20 — d'où le recours à un palier intermédiaire. 16px, lui, serait
     resté sur l'échelle si vous préférez y revenir. */
  .accomp2__title { font-size: 1.125rem; }
  /* --c-slate-300 ne donne que ~2,9:1 sur blanc. Les titres en veille
     sont ici la navigation de la section : ils doivent rester lisibles.
     --c-slate vaut ~5,6:1 et reste visiblement en retrait de l'encre. */
  .accomp2__title { color: var(--c-slate); }

  /* Étape repliée par défaut, dépliée à l'ouverture.
     Le corps de l'étape devient une grille de 3 rangées — titre, texte,
     barre — et seule celle du milieu passe de 0fr à 1fr. Contrairement à
     une hauteur maximale animée, la piste se mesure toute seule (aucune
     valeur plafond à deviner) et le navigateur n'a plus à recalculer la
     mise en page à chaque image.
     L'espacement passe en `padding-top` plutôt qu'en marge : posé DANS la
     rangée, il se replie avec elle au lieu d'être animé séparément. */
  .accomp2__body {
    display: grid;
    grid-template-rows: auto 0fr auto;
    transition: grid-template-rows var(--dur) var(--ease);
  }
  .accomp2__desc {
    overflow: hidden; min-height: 0;
    margin-top: 0; padding-top: var(--sp-2);
    opacity: 0; transition: opacity var(--dur) var(--ease);
  }
  .accomp2__step.is-active .accomp2__body { grid-template-rows: auto 1fr auto; }
  .accomp2__step.is-active .accomp2__desc { opacity: 1; }

  .accomp-cta { margin-top: var(--sp-6); }
  .accomp-cta .btn { width: 100%; }

  /* ===================================================================
     7. L'ESS en chiffres + carte des wilayas
     =================================================================== */

  /* Ordre demandé : titre → chiffres → carte. Le titre et les chiffres
     sont enfermés ensemble dans .reach__stats, la carte est leur voisine :
     `display: contents` dissout cette boîte pour que les quatre blocs
     deviennent frères dans la grille et se réordonnent.
     La légende des wilayas passe juste avant la carte — elle annonce ce
     que les points vont montrer. */
  .reach { gap: var(--sp-5); }
  .reach__stats { display: contents; }
  .reach__stats > .section-head { order: 1; }
  .kpi-cards { order: 2; }
  /* La légende des wilayas passe SOUS la carte : elle en devient la
     lecture, la liste nommant les points qu'on vient de voir. */
  .reach__map { order: 3; max-width: none; }
  .reach__legend { order: 4; margin: 0; font-size: var(--fs-xs); }

  /* La grille 2×2 est conservée (4 chiffres tiennent bien en deux
     colonnes) : seuls les rembourrages et les tailles sont resserrés. */
  .kpi-card { padding: var(--sp-4) var(--sp-3); gap: var(--sp-1); }
  .kpi-card__ico { width: 44px; height: 44px; margin-bottom: var(--sp-1); }
  .kpi-card__ico .ico { width: 22px; height: 22px; }
  .kpi-card__label { font-size: var(--fs-xs); }

  /* ===================================================================
     8. Têtes de section (titre + lien)
     =================================================================== */

  .section-head { margin-bottom: var(--sp-5); }
  .head-row { margin-bottom: var(--sp-5); gap: var(--sp-3); }

  /* ===================================================================
     8 bis. Sélection de projets
     =================================================================== */

  /* « Tous les projets » repasse à droite : dans une ligne flex qui
     revient à la ligne, `space-between` laisse l'élément esseulé collé à
     gauche. Ciblé sur cette tête de section seule — celle de l'agenda
     n'est pas concernée. */
  .head-row:has(+ #home-projects) .link-arrow { margin-left: auto; }

  /* Exactement le rail de « L'actualité de l'ESS » : piste fixe à 86 %,
     accroche au défilement, barre de défilement masquée.
     Rien n'est retiré de la carte — étiquettes, wilaya, titre, résumé et
     lien reprennent leurs réglages desktop : à 288px de large ils tiennent
     tous, ce qui n'était pas le cas dans la grille à deux colonnes.
     La vignette suit d'elle-même : .card__media et .feat-card__media sont
     toutes deux en 16/10 dans components.css. */
  #home-projects {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 86%;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: var(--sp-3);
    scrollbar-width: none;
  }
  #home-projects::-webkit-scrollbar { display: none; }
  #home-projects > * { min-width: 0; scroll-snap-align: start; }

  /* ===================================================================
     9. Un mot de la direction
     =================================================================== */

  /* Ordre demandé : titre → portrait → texte. Le chapeau, la citation et
     le texte sont enfermés ensemble dans .edito__text, le portrait est
     leur voisin : `display: contents` dissout la boîte pour que les cinq
     blocs deviennent frères et se réordonnent. Gouttière à zéro — chaque
     bloc porte déjà sa marge. */
  .edito { gap: 0; }
  .edito__text { display: contents; }
  .edito__chip { order: 1; }
  .edito__quote { order: 2; }
  .edito__lead { order: 3; }
  /* Le portrait passe SOUS le texte, et la signature reste accrochée à
     lui — c'est son <figcaption>, elle légende l'image. */
  .edito__media { order: 4; max-width: none; margin-block: var(--sp-5); }
  .edito__author { order: 5; }

  /* ===================================================================
     10. Agenda « À venir »
     =================================================================== */

  /* Rail horizontal de deux cartes empilées par écran. Les points de
     progression sont ajoutés par js/home.js et comptent les COLONNES,
     pas les cartes. */
  #home-agenda {
    grid-template-columns: none;
    grid-template-rows: auto auto;
    grid-auto-flow: column;
    grid-auto-columns: 100%;
    gap: var(--sp-3);
    margin-top: var(--sp-5);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: var(--sp-2);
    scrollbar-width: none;
  }
  #home-agenda::-webkit-scrollbar { display: none; }
  #home-agenda > * { scroll-snap-align: start; min-width: 0; }

  /* Cartes allégées : le résumé disparaît et la carte reprend sa forme
     horizontale (vignette à gauche), bien plus compacte que l'empilement
     vertical imposé sous 460px par components.css. */
  #home-agenda .ev-card { flex-direction: row; }
  #home-agenda .ev-card__media { flex: 0 0 32%; max-width: 32%; aspect-ratio: auto; }
  #home-agenda .ev-card__desc { display: none; }
  #home-agenda .ev-card__body { padding: var(--sp-3); gap: var(--sp-3); }
  #home-agenda .ev-card__title { font-size: var(--fs-base); }
  #home-agenda .ev-card__tag { margin-top: var(--sp-2); }

  /* ===================================================================
     11. Actualités (carrousel)
     =================================================================== */

  .featured__head { margin-bottom: var(--sp-5); }
  /* 86% : la carte suivante reste visible en bord d'écran, ce qui
     signale que le rail défile. */
  /* Pourcentage SIMPLE, pas minmax(0, 86%) : avec un minimum de 0, le
     moteur de grille se contente de répartir l'espace disponible entre
     les 8 pistes sans jamais atteindre le plafond. Le conteneur ne
     déborde alors pas, il n'y a plus de défilement, et les cartes sont
     écrasées à ~57px en se chevauchant. Une valeur fixe force le
     débordement, donc le rail. */
  .featured .carousel__track {
    grid-auto-columns: 86%;
    gap: var(--sp-4);
    align-items: stretch;
    scrollbar-width: none;
  }
  .featured .carousel__track::-webkit-scrollbar { display: none; }
  /* `min-width: 0` est la correction du chevauchement : par défaut un
     enfant de grille refuse de descendre sous la largeur minimale de son
     contenu. Ici le pied de carte aligne trois libellés en
     `white-space: nowrap` (portée, catégorie, date) — dès que leur somme
     dépasse la piste, la carte déborde par-dessus la suivante au lieu de
     se replier. */
  .feat-card { min-width: 0; height: 100%; scroll-snap-align: start; }
  .feat-card__title { font-size: var(--fs-lead); }
  .feat-card__foot { padding-top: var(--sp-4); gap: var(--sp-2); }
  .feat-card__cat, .feat-card__date { font-size: var(--fs-xs); white-space: normal; }
  /* La date cesse d'être poussée à droite : sur une carte étroite elle
     creusait un trou au milieu du pied. */
  .feat-card__date { margin-left: 0; }
  .featured__arrows { justify-content: center; }

  /* ===================================================================
     12. FAQ
     =================================================================== */

  .faq-grid { gap: var(--sp-6); }
  /* 4,2rem de « FAQ » écrasent l'écran sur 375px : on redescend sur le
     palier H1 de l'échelle, qui vaut 2rem à cette largeur. */
  .faq-aside__title { font-size: var(--fs-h1); }
  .faq-aside__text { font-size: var(--fs-base); margin-top: var(--sp-4); }
  .faq-proof { margin-top: var(--sp-5); }
  .faq-home summary { padding: var(--sp-4); font-size: var(--fs-base); gap: var(--sp-3); }
  .faq-home__a { padding: 0 var(--sp-4) var(--sp-4); }
  .faq-home__links { gap: var(--sp-3) var(--sp-4); }

  /* ===================================================================
     12 bis. Découvrir l'ESS (decouvrir.html)
     =================================================================== */

  /* --- Définition & principes : l'image remonte sous le titre ---------
     .prose est un simple flux de blocs, `order` n'y a aucun effet. On le
     passe en colonne flex — les marges de .prose > * + * y sont
     préservées à l'identique, aucune ne se chevauchait — puis on remonte
     seulement le titre et la figure. Tout le reste garde order:0, donc
     l'ordre du document. */
  /* GRILLE d'une colonne, pas `flex` : `order` fonctionne dans les deux,
     mais une colonne flex laisse un enfant ÉLARGIR le conteneur dès que
     son contenu minimal dépasse la largeur — le flux de blocs, lui, ne le
     permet jamais. C'est ce qui provoquait un défilement horizontal de
     toute la page. `minmax(0, 1fr)` plafonne la piste à la largeur
     disponible, et `min-width: 0` autorise chaque enfant à se replier
     au lieu de pousser. */
  .prose {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    max-width: none;
  }
  .prose > * { min-width: 0; }
  .prose > #definition { order: -2; }
  .prose > figure:first-of-type { order: -1; margin-top: var(--sp-5); }

  /* Même faille un cran au-dessus : .docpage passe en `1fr` sous 900px,
     et une piste `1fr` a pour minimum le contenu minimal de son enfant.
     Sans `minmax(0, …)`, .prose pouvait donc élargir .docpage, qui
     élargissait la page. */
  .docpage { grid-template-columns: minmax(0, 1fr); }

  /* Ceintures de sécurité sur les composants à défilement interne : sans
     min-width, leur contenu minimal remonte jusqu'à la page. */
  .dzm, .dzm-list, .dzm-map, .dzm-cats { min-width: 0; }

  /* --- Rythme éditorial ----------------------------------------------
     La page est un document long : six sections de texte suivi, sans
     carte ni encadré pour rompre le flux. Sur 375px elle se lit comme un
     mur. Quatre gestes lui rendent de la respiration. */

  /* 1. Un filet au-dessus de chaque titre de section : sur mobile on ne
        voit jamais deux sections à la fois, il faut un signal net que
        l'on change de sujet. Pas sur le premier, qui ouvre la page. */
  .prose h2 {
    margin-top: 2em;
    padding-top: var(--sp-5);
    border-top: 1px solid var(--c-line);
  }
  .prose > #definition { padding-top: 0; border-top: 0; }
  .prose h3 { margin-top: 1.8em; }

  /* 2. L'interlignage de 1,72 vient du desktop, où la colonne fait 68
        caractères. Ici elle en fait ~40 : le même réglage disperse le
        bloc au lieu de l'aérer. */
  .prose p, .prose li { line-height: 1.6; }
  .prose > * + * { margin-top: 1.25em; }

  /* 3. Les puces respirent et s'alignent : cinq principes d'affilée sur
        deux ou trois lignes chacun forment sinon un pavé unique. */
  .prose ul li { margin-top: var(--sp-3); padding-left: 1.5em; }
  .prose ul li::before { top: 0.5em; }

  /* 4. Encadré et citation prennent un fond : c'est ce qui les distingue
        du texte courant quand la marge ne suffit plus. */
  .prose .callout { padding: var(--sp-4); }
  .prose blockquote {
    padding: var(--sp-4);
    background: var(--c-mist);
    border-radius: var(--r-md);
    font-size: var(--fs-base);
  }
  .prose figure { margin-top: var(--sp-6); }
  .prose figcaption { font-size: var(--fs-xs); }

  /* --- Où trouver un appui : fiches AU-DESSUS de la carte ------------- */
  .dzm-body {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    height: auto;
  }
  /* La liste passe du défilement vertical à un rail horizontal. La
     hauteur imposée par le desktop saute — chaque fiche fait la largeur
     du panneau moins un aperçu de la suivante. */
  .dzm-list {
    flex: none;
    grid-auto-flow: column;
    display: grid;
    grid-auto-columns: 86%;
    gap: var(--sp-3);
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .dzm-list::-webkit-scrollbar { display: none; }

  /* --- Barre de filtres : une rangée qui glisse ----------------------
     Les 6 pastilles totalisent ~815px : sur 335px elles s'empilent sur
     trois rangées et repoussent la carte hors de l'écran. En interdisant
     le retour à la ligne, la barre occupe UNE rangée quel que soit le
     nombre de catégories — c'est le motif standard des filtres mobiles,
     et le seul dont la hauteur ne dépend pas du contenu. */
  .dzm-cats {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .dzm-cats::-webkit-scrollbar { display: none; }
  /* flex: none — sans lui, les pastilles se compriment pour entrer dans
     la rangée au lieu de la faire défiler, et les libellés se coupent. */
  .dzm-cat { flex: none; padding-inline: var(--sp-3); gap: 5px; }
  /* Pastilles de filtre à 13px (demande explicite). En rem et non en px :
     les réglages A+ / A++ du pied de page agissent sur la taille racine,
     un px y resterait figé. */
  .dzm-cat { font-size: 0.8125rem; }
  /* L'icône rétrécit mais reste : sa couleur est celle de la catégorie
     sur la carte, c'est le lien visuel entre le filtre et les épingles. */
  .dzm-cat__ico .ico { width: 13px; height: 13px; }
  .dzm-list > * { min-width: 0; scroll-snap-align: start; }
  /* Les points se posent dans le panneau, sous le rail. */
  .dzm-panel .rail-dots { padding-bottom: var(--sp-3); }
  .dzm-map { height: 320px; }

  /* --- Chiffres clés : 2×2, une seule couleur ------------------------
     `.grid--4` retombe sur une colonne sous 620px (base.css). Ici les
     quatre chiffres doivent rester en carré.
     Les variantes .stat--green / .stat--sky donnaient trois couleurs pour
     quatre nombres de même nature : la couleur y portait une différence
     qui n'existe pas. Tout revient au bleu de marque. */
  .prose .grid--4 { grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
  .prose .stat__num { color: var(--c-blue); }

  /* ===================================================================
     12 ter. Projets (projets.html)
     =================================================================== */

  /* Confinement — même faille que sur .docpage. `.res-layout` passe en
     `1fr` sous 900px, et une piste `1fr` a pour minimum le contenu
     minimal de son enfant. Ma rangée de pastilles en `nowrap` mesure
     ~700px de contenu minimal : elle élargissait .res-filters, donc la
     piste, donc la page. `minmax(0, …)` plafonne, `min-width: 0` laisse
     chaque bloc se replier. */
  .res-layout { grid-template-columns: minmax(0, 1fr); }
  .res-filters, .res-main, .res-quick, #projects-grid { min-width: 0; }

  /* --- Bouton d'ouverture des filtres -------------------------------- */
  .res-filters__open {
    display: flex; align-items: center; gap: var(--sp-3);
    width: 100%; padding: 0.9em var(--sp-4);
    border: 1.5px solid var(--c-line-strong); border-radius: var(--r-lg);
    background: var(--c-paper); color: var(--c-ink);
    font-weight: var(--fw-semi); font-size: var(--fs-base);
  }
  .res-filters__open .ico { color: var(--c-blue); }
  /* Nombre de critères actifs : un volet fermé ne dit rien de ce qui
     filtre encore, la pastille le rattrape. */
  .res-filters__badge {
    margin-left: auto; min-width: 22px; padding: 2px 7px;
    border-radius: var(--r-pill);
    background: var(--c-green); color: #fff;
    font-size: var(--fs-xs); font-weight: var(--fw-bold);
    text-align: center;
  }

  /* Filtre rapide « Secteur » : une rangée qui glisse, jamais deux.
     Même motif que la barre de la carte des structures. */
  .res-quick {
    display: flex; flex-wrap: nowrap; gap: var(--sp-2);
    margin-top: var(--sp-3);
    overflow-x: auto; scrollbar-width: none;
  }
  .res-quick::-webkit-scrollbar { display: none; }
  .res-quick .chip { flex: none; font-size: 0.8125rem; padding-inline: 0.9em; }

  /* --- Volet glissant depuis la droite -------------------------------- */
  .res-filters__scrim {
    position: fixed; inset: 0; z-index: 140;
    background: rgba(0, 0, 0, 0.3);
    opacity: 0; visibility: hidden;
    transition: opacity var(--dur) var(--ease), visibility var(--dur);
  }
  .res-filters.is-open .res-filters__scrim { opacity: 1; visibility: visible; }

  .res-filters .proj-filters {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 150;
    width: min(88vw, 380px);
    display: flex; flex-direction: column;
    background: var(--c-paper); box-shadow: var(--sh-lg);
    padding: var(--sp-4);
    padding-top: max(var(--sp-4), env(safe-area-inset-top));
    overflow-y: auto; overscroll-behavior: contain;
    transform: translateX(100%);
    visibility: hidden;
    transition: transform var(--dur) var(--ease), visibility var(--dur);
  }
  .res-filters.is-open .proj-filters { transform: translateX(0); visibility: visible; }

  /* L'en-tête colle en haut : le volet défile, le titre et la fermeture
     doivent rester atteignables. */
  .res-filters__head {
    position: sticky; top: 0; z-index: 1;
    background: var(--c-paper);
    padding-top: var(--sp-2);
  }
  .res-filters__close {
    width: 40px; height: 40px; flex: none;
    display: grid; place-items: center;
    border-radius: var(--r-pill); color: var(--c-ink);
  }
  .res-filters__close:hover { background: var(--c-mist); }
  /* `margin-top: auto` colle le bouton au bas du volet quand les filtres
     n'en remplissent pas la hauteur. */
  .res-filters__done { width: 100%; margin-top: auto; margin-bottom: var(--sp-2); }

  /* --- Cartes projet, style de la maquette ---------------------------
     Vignette à gauche détourée dans une carte rembourrée, et l'ordre du
     corps corrigé : le DOM place le lieu AVANT le titre, la maquette veut
     étiquettes → titre → lieu → résumé → lien. */
  #projects-grid { grid-template-columns: 1fr; gap: var(--sp-4); }
  #projects-grid .card {
    flex-direction: row;
    gap: var(--sp-3);
    padding: var(--sp-3);
    border-radius: var(--r-xl);
  }
  #projects-grid .card__media {
    flex: 0 0 34%; max-width: 34%;
    aspect-ratio: auto;
    border-radius: var(--r-lg);
  }
  #projects-grid .card__body { padding: 0; gap: var(--sp-2); min-width: 0; }
  #projects-grid .card__badges { order: 1; }
  #projects-grid .card__title { order: 2; font-size: var(--fs-base); }
  #projects-grid .card__loc { order: 3; }
  #projects-grid .card__text { order: 4; }
  #projects-grid .card__cta { order: 5; padding-top: var(--sp-2); }
  /* Résumé conservé mais borné : sans limite, une carte longue décale
     tout le rythme de la liste. */
  #projects-grid .card__text {
    font-size: var(--fs-xs);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
  }

  /* ===================================================================
     12 quater. Fiche projet (pages/projet.html)
     =================================================================== */

  /* --- « En bref » et son CTA remontent au-dessus du contenu ---------
     Le DOM place l'encadré APRÈS les sept blocs de texte : sur mobile,
     « Contacter le porteur » se trouvait à sept écrans de défilement du
     titre. Sur une fiche, l'action principale doit être atteignable sans
     avoir lu la page — c'est un appel à l'action, pas une conclusion. */
  .fiche2__grid { grid-template-columns: minmax(0, 1fr); }
  .fiche2__aside { order: -1; min-width: 0; }
  .fiche2__panel { min-width: 0; }

  /* Deux colonnes pour les faits : sept lignes empilées occupaient la
     hauteur d'un écran entier avant même d'arriver au bouton. Les filets
     de séparation cèdent la place à une gouttière — en deux colonnes ils
     ne s'alignent plus, et une ligne masquée (le budget, facultatif)
     décalerait le motif. */
  .fiche2__facts {
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-3) var(--sp-4);
  }
  .fiche2__facts > div { border-top: 0; padding: 0; }

  /* Un pictogramme par fait, posé par js/projet-detail.js. Il porte le
     repérage à la place du libellé, qui peut donc passer en 12px sans
     redevenir illisible — c'est là qu'est le gain de hauteur. */
  .fiche2__facts dt {
    display: flex; align-items: center; gap: 6px;
    font-size: var(--fs-xs);
  }
  .fiche2__facts-ico { display: inline-flex; flex: none; color: var(--c-blue); }
  .fiche2__facts-ico .ico { width: 14px; height: 14px; }
  .fiche2__facts dd { margin-top: 2px; }

  /* Le bouton prend toute la largeur et la taille des CTA majeurs. */
  .fiche2__factcta { padding: 1.05em 1.9em; font-size: var(--fs-base); }

  /* --- Titres de la fiche remis sur l'échelle ------------------------
     Ces deux-là portaient leur propre clamp() : 36,8px et 20px à 375px,
     sans rapport avec les jetons. Ils reprennent les paliers h1 et h4.
     `.fiche2__block p` était à 1,05rem en dur — c'est du texte courant,
     il rejoint les 14px comme le reste. */
  .fiche2__title { font-size: var(--fs-h1); }
  .fiche2__label { font-size: var(--fs-h4); }
  .fiche2__block p { font-size: var(--fs-base); }

  /* Le chapeau de fiche est centré sur desktop. Sur 375px un titre de
     trois lignes centré n'a plus de bord d'appui commun avec le texte. */
  .fiche2__masthead { text-align: left; margin-inline: 0; }
  .fiche2__meta-row { justify-content: flex-start; }
  .fiche2__desc { margin-inline: 0; }
  .fiche2__cta { justify-content: flex-start; }

  /* --- Projets similaires en rail ------------------------------------ */
  [data-fiche-related] {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 86%;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: var(--sp-3);
    scrollbar-width: none;
    min-width: 0;
  }
  [data-fiche-related]::-webkit-scrollbar { display: none; }
  [data-fiche-related] > * { min-width: 0; scroll-snap-align: start; }

  /* ===================================================================
     12 sexies. Académie (academie.html, pages/formation.html)
     =================================================================== */

  /* Cartes de module en format horizontal — même raison que sur les
     projets : empilées pleine largeur elles font ~360px pièce, soit deux
     modules par écran sur un catalogue. */
  #academie-grid { grid-template-columns: 1fr; gap: var(--sp-4); min-width: 0; }
  #academie-grid .card { flex-direction: row; gap: var(--sp-3); padding: var(--sp-3); border-radius: var(--r-xl); }
  #academie-grid .card__media { flex: 0 0 34%; max-width: 34%; aspect-ratio: auto; border-radius: var(--r-lg); }
  #academie-grid .card__body { padding: 0; gap: var(--sp-2); min-width: 0; }
  #academie-grid .card__title { font-size: var(--fs-base); }
  #academie-grid .card__text {
    font-size: var(--fs-xs);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
  }

  /* « Autres modules » en rail, comme les projets similaires. */
  [data-fo-related] {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 86%;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: var(--sp-3);
    scrollbar-width: none;
    min-width: 0;
  }
  [data-fo-related]::-webkit-scrollbar { display: none; }
  [data-fo-related] > * { min-width: 0; scroll-snap-align: start; }

  /* ===================================================================
     12 quinquies. Accompagnement (accompagnement.html)
     =================================================================== */

  /* --- Les trois cartes d'orientation --------------------------------
     Empilées pleine largeur avec le rembourrage desktop, une icône de
     56px et un h3 à 30px, chacune occupait la moitié d'un écran : les
     trois parcours ne se voyaient jamais ensemble, alors que leur seule
     raison d'être est d'être COMPARÉS.

     Grille de deux colonnes : l'icône et le titre partagent la première
     rangée, le texte et le lien passent en pleine largeur dessous. La
     hauteur tombe d'environ un tiers sans rien retirer. */
  .feature {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-4);
  }
  .feature > .feature__icon { grid-row: 1; grid-column: 1; }
  .feature > h3 { grid-row: 1; grid-column: 2; }
  .feature > p,
  .feature > .link-arrow { grid-column: 1 / -1; }

  /* Icône réduite : à 56px elle pesait plus lourd que le titre. */
  .feature__icon { width: 40px; height: 40px; }
  .feature__icon .ico { width: 20px; height: 20px; }

  /* 30px pour « Acteurs & dispositifs » forçait deux lignes et écrasait
     la carte. Le palier 20 (h5 PNUD) suffit à porter un titre de carte. */
  .feature > h3 { font-size: var(--fs-lead); line-height: 1.2; }

  /* La teinte passe de la pastille à la CARTE : les variantes existantes
     ne coloraient que l'icône, ce qui ne se voit plus une fois les trois
     cartes empilées. Fond clair, liseré assorti, trois parcours
     distinguables d'un coup d'œil. */
  .feature {
    background: var(--tag-blue-bg);
    border-color: transparent;
  }
  .feature--green { background: var(--tag-green-bg); }
  .feature--sky { background: var(--tag-sky-bg); }
  .feature--orange { background: var(--tag-orange-bg); }
  /* Sur ces fonds teintés, la pastille repasse en blanc pour rester
     lisible — sinon elle disparaît dans la carte. */
  .feature .feature__icon { background: var(--c-paper); }

  /* ===================================================================
     12 septies. Participation (participation.html)
     =================================================================== */

  /* La .subnav reste collante (comportement du composant). Elle ne coûte
     rien tant qu'on est sur le chapô — `sticky` la laisse dans le flux
     jusqu'à ce qu'elle atteigne le haut — et une fois épinglée elle porte
     l'état actif, donc la position dans la page. C'est ce qui justifie
     les ~45px qu'elle occupe ensuite : un repère de position qui
     disparaîtrait au défilement ne servirait à rien.
     Le rembourrage est resserré pour tenir en 45px tout en gardant une
     cible tactile correcte. */
  .subnav .container { gap: var(--sp-5); }
  .subnav__link { padding-block: var(--sp-3); font-size: var(--fs-base); }
  /* Le décalage d'ancre compense les DEUX barres épinglées : sans lui, le
     titre visé se range derrière la subnav qui vient de s'y coller. */
  .subnav ~ section[id] { scroll-margin-top: calc(var(--header-h) + 4rem); }
  /* L'effectif est une précision sur le lien, jamais à la même force que
     son libellé — même traitement que .chip__n. */
  .subnav__link span {
    margin-left: 4px;
    font-variant-numeric: tabular-nums;
    font-weight: var(--fw-regular);
    color: var(--c-slate);
  }

  /* --- Panneau « À propos » d'une consultation -----------------------
     Les libellés portent un pictogramme : le repérage passe par l'icône,
     le libellé peut donc rester en 12px sans redevenir illisible. Même
     traitement que la fiche projet. */
  .fiche2__facts--ico dt {
    display: flex; align-items: center; gap: 6px;
    font-size: var(--fs-xs);
  }
  .fiche2__facts--ico dt .ico { width: 14px; height: 14px; color: var(--c-blue); flex: none; }

  /* ===================================================================
     12 octies. Centre de ressources (ressources.html)
     =================================================================== */

  .res-list { min-width: 0; }

  /* Tri : le libellé « Trier par » disparaît — « Plus récent » se
     comprend seul — et la commande file à droite, sous le compteur.
     Sa TAILLE de texte reste à 16px : c'est un <select>, et en dessous
     Safari iOS zoome à l'ouverture. Ce sont les rembourrages qui
     rétrécissent, pas la police. */
  .res-topbar { gap: var(--sp-3); }
  .res-topbar__tools { width: 100%; gap: var(--sp-2); }
  .res-sort { margin-left: auto; }
  /* AUDIT #2 — « Trier par » enveloppe le <select> : c'est ce texte qui
     lui donne son nom. `display: none` le retirait aussi de l'arbre
     d'accessibilité, et un lecteur d'écran n'annonçait plus qu'une
     « liste déroulante » anonyme (WCAG 4.1.2).
     Même effet visuel, nom conservé. */
  .res-sort > span {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .res-sort .select {
    min-width: 0; width: auto;
    padding: 0 2.2em 0 0.75em;
    background-position: right 0.6em center;
  }

  /* Carte de publication compacte. pages.css:459 traite déjà la carte
     sous 640px — vignette à 68px, méta repliée sous le titre. On ne
     redéfinit donc que ce qui doit rétrécir davantage, et la PISTE de
     grille suit la vignette : la réduire seule aurait laissé un trou de
     12px entre elle et le texte. */
  /* Carte de publication, d'après la maquette : vignette carrée pleine
     couleur surmontant une pastille de format, texte à droite, filet,
     puis la ligne de métadonnées ; le téléchargement en pictogramme rond
     au bout de cette ligne. */
  .pub {
    position: relative;
    grid-template-columns: 44px minmax(0, 1fr);
    gap: 0 var(--sp-3);
    /* La réserve pour le bouton est prise sur la CARTE, pas sur chaque
       enfant : posée au coup par coup, un élément oublié passait dessous.
       12px de marge + 44px de bouton + 6px de dégagement. */
    padding: var(--sp-3) 62px var(--sp-3) var(--sp-3);
    align-items: start; border-radius: var(--r-lg);
  }
  .pub__coverwrap { display: block; }
  /* Aplat plutôt que dégradé : la maquette pose une couleur franche, et
     l'icône s'y détache mieux. */
  /* Couleurs prises dans les JETONS et non recopiées des dégradés de
     pages.css : ces trois littéraux n'y servaient qu'une fois chacun, les
     reprendre ici les aurait triplés hors de toute palette documentée.
     La palette « tag » du projet couvre exactement ce besoin — un fond
     clair et une encre assortie par famille. */
  /* Format portrait plutôt que carré : une vignette de document se lit
     comme une couverture, et les 12px gagnés en hauteur ne coûtent rien
     — le texte à droite est déjà plus haut qu'elle. */
  .pub__cover { width: 44px; height: 56px; border-radius: var(--r-md); background: var(--c-blue); }
  .pub__cover--loi { background: var(--c-blue-900); }
  .pub__cover--etude { background: var(--c-green-700); }
  .pub__cover--outils { background: var(--tag-orange-fg); }
  .pub__cover .ico { width: 20px; height: 20px; }
  /* Pastille de format masquée : elle répétait exactement ce que dit
     déjà .pub__file (« XLSX · 0,5 Mo »). Une rangée entière sous la
     vignette pour une information en double. */
  .pub__fmt { display: none; }

  /* La catégorie prend la couleur de son type : c'est le repère qui
     permet de balayer la liste sans lire. */
  .pub__cat { color: var(--tag-blue-fg); }
  .pub--loi .pub__cat { color: var(--c-blue-900); }
  .pub--etude .pub__cat { color: var(--tag-green-fg); }
  .pub--outils .pub__cat { color: var(--tag-orange-fg); }

  /* (réserve désormais posée sur .pub lui-même)



  .pub__cat { line-height: 1.2; }
  .pub__title {
    font-size: var(--fs-base); line-height: 1.25; margin-top: 2px;
    display: -webkit-box; -webkit-box-orient: vertical;
    -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
  }
  /* Résumé retiré : sur une liste de téléchargements, la famille, le
     titre et le format suffisent à décider, et deux lignes de plus par
     carte se paient sur le nombre de ressources visibles d'un coup
     d'œil. Le desktop, lui, a la place de le garder. */
  .pub__desc { display: none; }

  /* `grid-column: 2` et non `1 / -1` : la méta se range sous le TITRE,
     dans sa colonne, alignée sur le texte qu'elle décrit. Le filet la
     sépare du résumé, comme sur la maquette. */
  /* Filet et grands écarts supprimés : sans le résumé, ils séparaient le
     titre de sa propre ligne de méta. Réserve à droite pour le bouton,
     qui est sorti du flux. */
  .pub__meta {
    grid-column: 2;
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 2px var(--sp-3);
    justify-items: start; text-align: left;
    min-width: 0; margin-top: 6px; padding-top: 0; border-top: 0;
  }
  .pub__year, .pub__lang, .pub__file {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: var(--fs-xs); line-height: 1.3; white-space: nowrap;
  }
  .pub__meta .ico { width: 13px; height: 13px; color: var(--c-slate); flex: none; }
  /* Le bouton QUITTE le flux : à 44px il imposait sa hauteur à toute la
     ligne de métadonnées, qui n'en fait que 16. Positionné et centré, il
     garde sa cible de frappe sans peser sur la hauteur de la carte.
     Le libellé reste dans le DOM pour le desktop, et l'aria-label de
     l'ancre porte déjà le titre du document. */
  .pub__dl {
    position: absolute; right: var(--sp-3); top: 50%;
    transform: translateY(-50%);
    width: 44px; height: 44px; padding: 0; margin: 0;
    justify-content: center; border-radius: var(--r-pill); flex: none;
  }
  .pub__dl-label { display: none; }
  .pub__dl .ico { width: 20px; height: 20px; }

  /* ===================================================================
     12 nonies. Contact (contact.html)
     =================================================================== */

  /* En une colonne, « Coordonnées » suivait le bouton « Envoyer » à la
     gouttière de grille près — deux blocs distincts qui se lisaient
     comme un seul. 40px les séparent. */
  .contact-grid { grid-template-columns: 1fr; gap: 40px; }
  /* Le message de statut sous un bouton pleine largeur : centré, il
     s'aligne sur ce qu'il commente. `:not(:empty)` est indispensable —
     mobile.css est chargé APRÈS pages.css et, à spécificité égale, sa
     marge écraserait l'annulation faite là-bas tant que le message est
     vide. */
  .contact-grid .form-msg:not(:empty) { text-align: center; margin-top: var(--sp-2); }
  .map-embed { aspect-ratio: 4 / 3; }

  /* ===================================================================
     13. Pied de page
     =================================================================== */

  /* Le pied de page suit le modèle Open Society : une seule taille de texte
     dans le plan du site, titres signalés par la couleur. Sur mobile il n'y
     a donc presque rien à corriger — juste les colonnes à empiler et les
     cibles tactiles à ouvrir. */

  .footer-hi { padding-block: var(--sp-7) var(--sp-6); gap: var(--sp-6); }
  .footer-hi p { max-width: none; }

  /* Une seule colonne : à 375px, deux colonnes de liens donnent des lignes
     de six caractères qui reviennent à la ligne. */
  .footer-map { grid-template-columns: 1fr; gap: var(--sp-6); padding-block: var(--sp-6); }
  /* 2.15 × 14px ≈ 30px de hauteur de ligne : déjà au-dessus des 24px
     recommandés pour des liens en liste, la cible tactile est donc bonne
     sans rembourrage supplémentaire. On l'ouvre juste un peu. */
  .footer-map__list a { line-height: 2.4; }
  .footer-map__col--id { order: -1; }

  /* Newsletter : l'<input> garde une largeur intrinsèque d'environ 20
     caractères, qui pousse « S'abonner » hors du champ sur 375px. On
     autorise la coupure et on passe le bouton en pleine largeur. */
  .footer-newsletter .search {
    flex-wrap: wrap; row-gap: var(--sp-3);
    padding: var(--sp-2) var(--sp-4); border-radius: var(--r-lg);
  }
  .footer-newsletter .search input { min-width: 0; }
  .footer-newsletter .search .btn { flex: 1 0 100%; }

  .partner-strip { gap: var(--sp-4) var(--sp-5); }
  .partner-logo--mtess img { height: 44px; }
  .partner-logo--pnud  img { height: 46px; }
  .partner-logo--eu    img { height: 32px; }

  /* La barre utilitaire s'empile ; `margin-left:auto` sur l'accessibilité
     n'a plus de sens une fois en colonne. */
  .footer-util { gap: var(--sp-4); padding-block: var(--sp-5); }
  .footer-util .footer-a11y { margin-left: 0; }
  .footer-a11y { flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); }
  .a11y-btn { padding: 8px 10px; }
  .socials a { width: 44px; height: 44px; }

}
