/* ══════════════════════════════════════════════════════════════
   Barre de contrôles et panneau de filtres des pages de liste
   ══════════════════════════════════════════════════════════════
   Voir templates/components/_list_toolbar.html.twig pour le contrat.

   @grammaire v2

   Extrait de `zones/content.css`, qui avait grossi à 5 310 lignes et servait
   de fourre-tout. Surtout : cette feuille était chargée par 37 gabarits, dont
   29 n'affichent aucune liste (fiche d'article, guide, formulaire d'adhésion,
   tableau de bord…). Ils téléchargeaient sept cents lignes de règles qu'aucun
   de leurs éléments ne pouvait consommer.

   À charger UNIQUEMENT dans les gabarits qui rendent `_list_toolbar`, juste
   APRÈS `zones/content.css` — l'ordre compte, plusieurs règles d'ici affinent
   des sélecteurs qui y vivent encore.
   ══════════════════════════════════════════════════════════════ */

.content-list__count {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    line-height: 1.4;
}

.content-list__count strong {
    color: var(--color-primary-dark);
    font-size: var(--font-size-base);
    font-weight: 700;
    margin-right: 0.25rem;
}

/* ── Rangée de contrôles ──
   Recherche, accès au panneau, regroupement, tri. Elle ne porte JAMAIS les
   facettes : leur nombre varie de deux à sept selon la page, et posées ici
   elles faisaient déborder la rangée sur deux lignes. */
/* Hauteur UNIQUE des contrôles de la rangée. Sans elle, le champ faisait 32 px,
   le bouton 32, la bascule 34 (bordure comprise) et le tri 30 : quatre contrôles
   alignés par le bas, donc quatre intitulés à quatre hauteurs différentes.
   L'écart se voit sur les étiquettes, pas sur les champs — c'est ce qui le rend
   difficile à nommer et facile à laisser passer. */
.content-list__controls {
    --control-height: 2rem;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--spacing-sm);
    padding-bottom: var(--spacing-md);
    margin-bottom: var(--spacing-md);
    border-bottom: 1px solid var(--color-border);
}

/* ── LA RANGEE EN CARTE ──
   Ce que la maquette pose quand la barre ne porte plus qu'un compteur et un axe
   de regroupement : une surface blanche qui les REUNIT. Sans elle, deux
   controles isoles sur le fond gris se lisent comme des restes de la barre
   d'avant, pas comme un bloc.

   `ui-card` est emise par le gabarit et porte la surface, la bordure et le
   rayon. Ne restent ici que les corrections propres a l'usage : le rembourrage
   se resserre — une rangee de controles n'est pas un bloc de contenu — et le
   trait de separation disparait, la carte separant deja. */
.content-list__controls--card {
    align-items: center;
    gap: var(--spacing-ms);
    padding: var(--spacing-ms) var(--spacing-md);
    margin-bottom: 0;
    /* LE TRAIT DE SEPARATION DE LA BARRE NUE DEVIENT L'ARETE DE LA CARTE.
       `border-bottom: 0` retirait bien le trait, mais emportait aussi la
       bordure basse que `ui-card` pose : mesure, la carte rendait
       `1px 1px 0px 1px` et restait OUVERTE en bas. Le defaut ne se voit pas
       tant qu'une rangee la suit et la ferme ; sans filtre actif, elle
       s'ouvrait sur le fond de page. */
    border-bottom: 1px solid var(--color-border);
}

/* Le compteur, dans la carte, garde sa chasse fixe mais cesse d'etre un titre :
   il annonce, il ne domine pas. */
.content-list__controls--card .content-list__count {
    margin: 0;
    white-space: nowrap;
}

/* Deux groupes : ce qu'on cherche à gauche, comment on le présente à droite. */
.content-list__controls-group {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--spacing-sm);
    /* `auto` et non une base de 20 rem : sur une page SANS champ de recherche,
       le groupe de gauche ne contient que le bouton « Filtres » (96 px), mais
       il réclamait quand même 320 px — donc toute la largeur d'un téléphone,
       donc une seconde ligne pour l'affichage et le tri, alors que les trois
       contrôles tiennent ensemble dès 360 px. C'est le champ de recherche qui
       porte la croissance, pas le groupe qui l'entoure. */
    flex: 1 1 auto;
    min-width: 0;
}

/* `flex: 0 1 auto` ET NON `0 0 auto`, avec repli. Les deux groupes de pastilles
   — regrouper, trier — tiennent CHACUN sur sa ligne, mais cote a cote ils
   depassent des que leurs libelles s'allongent : le `flex-wrap` de chaque groupe
   ne peut rien, ce sont les GROUPES qu'il faut replier, pas leurs pastilles.

   Mesure sur le catalogue de formations, dont les libelles sont plus longs que
   ceux de `/ressources` : 72 px hors de la carte a 1440 et 1280, 191 a 1024,
   pour huit pastilles des deux cotes. `/ressources` tenait par chance, a 17 px
   pres. `0 0 auto` interdisait tout retrecissement, donc tout repli. */
.content-list__controls-group--end {
    flex: 0 1 auto;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* ── UNE RANGEE QUI NE PORTE QUE LE DECLENCHEUR DU TIROIR N'EXISTE PAS ──
   Au-dela du palier, le rail de filtres est permanent et le bouton « Filtres »
   est masque. Une page dont la barre ne porte QUE lui — le glossaire, dont les
   facettes et le champ vivent dans le rail — n'affichait donc plus rien, mais
   gardait sa hauteur et son filet de separation : 888 x 17 px de rien, avec un
   trait sous du vide. Mesure du 2026-08-31.

   Le selecteur decrit exactement ce cas — un seul groupe, dont le seul enfant
   est le declencheur — plutot qu'un drapeau a passer par l'appelant : la regle
   suit ce que la rangee CONTIENT, donc elle ne peut pas etre oubliee au
   douzieme gabarit. Les barres qui portent un compteur, des pastilles ou un
   champ ne la voient jamais. */
@media (min-width: 64em) {
    .content-list__controls:has(> .content-list__controls-group:only-child > .filter-panel__trigger:only-child) {
        display: none;
    }
}

/* Le champ tient sa hauteur de son propre `padding` : il faut la lui imposer
   comme aux autres, sinon il reste a 32 px quand la rangee passe a 44 sur
   telephone. */
.content-list__controls .search-field__group {
    height: var(--control-height, 2rem);
}

.content-list__controls-search {
    /* Plafonné : étiré sur toute la largeur, le champ faisait 998 px pour une
       saisie de quelques mots — une boîte vide qui occupait la ligne entière.
       Il garde la priorité sur l'espace disponible, sans le prendre tout. */
    flex: 1 1 18rem;
    min-width: 12rem;
    max-width: 28rem;
}

/* L'intitulé passe AU-DESSUS du contrôle. Placé à côté, il consommait la
   largeur de son propre texte sur chaque liste. */
.content-list__controls .dropdown,
.content-list__filters .dropdown {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.3rem;
}

.content-list__controls .dropdown__wrapper,
.content-list__controls .dropdown__trigger,
.content-list__filters .dropdown__wrapper,
.content-list__filters .dropdown__trigger {
    width: 100%;
}

.content-list__controls .dropdown__label,
.content-list__filters .dropdown__label,
/* ══════════════════════════════════════════════════════════════
   ÉTIQUETTE ET CONTRÔLE — la grammaire, une fois.

   L'ÉTIQUETTE NE PORTE QUE SA TYPOGRAPHIE. L'écart qui la sépare de son
   contrôle appartient au CONTENEUR — son `gap` —, jamais à elle-même — sa
   marge. La règle n'est pas de style : une marge basse ne connaît qu'une
   direction, alors que la même étiquette se pose tantôt AU-DESSUS de son
   contrôle, tantôt À CÔTÉ.

   Ce qu'elle coûtait avant d'être écrite : `margin-bottom: 0.3rem` posée sur
   l'étiquette décalait « GROUPER » de 3 px vers le haut dès qu'elle partageait
   la ligne avec ses puces — centre à 645 quand les puces et le compteur étaient
   à 648. Invisible au diff, visible à l'œil, et le défaut se serait rejoué sur
   chaque page adoptant la même forme.

   Un `gap` de conteneur, lui, suit l'axe : vertical en colonne, horizontal en
   ligne. La même déclaration sert les deux orientations, et il devient
   impossible de se tromper en en ajoutant une troisième.
   ══════════════════════════════════════════════════════════════ */
.content-list__filters-label {
    /* 11 px : l'intitulé est une étiquette, pas un titre. */
    margin: 0;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    /* `1` et non la hauteur de ligne héritée : une étiquette d'une seule ligne
       centrée dans une rangée doit avoir une boîte qui épouse son texte, sinon
       le demi-interligne du haut la décale de ce que le bas ne rattrape pas. */
    line-height: 1;
    text-transform: uppercase;
    color: var(--color-text-light);
}

/* Un contrôle et son étiquette AU-DESSUS — la forme par défaut. */
.content-list__field {
    display: flex;
    flex-direction: column;
    /* 4 px, le cran de l'echelle le plus proche des 0,3 rem que portait la
       marge remplacee : l'ecart est reconduit, pas redecide. */
    gap: var(--spacing-xs);
    min-width: 0;
}

/* Un contrôle et son étiquette À CÔTÉ, sur la même ligne, CENTRÉS. */
.content-list__field--inline {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
}

/* Bouton d'accès au panneau — aligné sur la base des autres contrôles. */
.content-list__filters-trigger {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    /* La hauteur vient des contrôles voisins, pas d'un chiffre choisi à part :
       à 44 px il dépassait d'un tiers le champ de recherche (32 px) et la liste
       de tri (30 px), posés sur la même ligne. Il reprend 44 px sous 48em, où
       il devient une cible tactile. */
    height: var(--control-height, 2rem);
    padding: 0 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    color: var(--color-text);
    font-size: var(--font-size-sm);
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.content-list__filters-trigger:hover {
    background: var(--color-bg-light);
    border-color: var(--color-primary);
}

.content-list__filters-trigger .content-list__filter-badge {
    min-width: 1.25rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.25rem;
    text-align: center;
}

@media (width < 48em) {
    .content-list__controls {
        --control-height: 2.75rem;
    }

    .content-list__filters-trigger {
        padding: 0 0.9rem;
    }

    /* Les deux groupes cessent d'être des boîtes : leurs enfants deviennent
       enfants directs de la rangée et se réagencent librement. Sans cela, le
       champ de recherche remplissait la ligne DANS son groupe, le bouton
       « Filtres » passait dessous — toujours dans le même groupe — et le groupe
       de droite était rejeté sur une troisième ligne. Trois lignes pour quatre
       contrôles dont trois tiennent côte à côte. */
    .content-list__controls-group {
        display: contents;
    }

    /* Les trois contrôles qui restent tiennent sur une ligne : le champ prend
       la place disponible, le bouton « Filtres » passe en icône seule (son
       intitulé reste lu, cf. plus bas) et la bascule ne coûte que ses deux
       icônes. À 375 px : 44 + 74 + gouttières, donc ~217 px pour la saisie. */
    .content-list__controls-search {
        flex: 1 1 8rem;
        min-width: 7rem;
        max-width: none;
    }

    .content-list__filters-trigger {
        width: var(--control-height, 2.75rem);
        padding: 0;
    }

    /* 16 px dans le champ : en dessous, iOS ZOOME la page a la prise de focus
       et l'utilisateur se retrouve a devoir dezoomer pour voir ses resultats.
       La variante `compact` descend a 14 px, ce qui convient au bureau. */
    .content-list__controls-search .search-field__input {
        font-size: 1rem;
    }

    /* `sr-only` et non `display: none` : le bouton n'a pas d'`aria-label`, son
       nom vient de ce texte. */
    .content-list__filters-trigger > span:not(.content-list__filter-badge) {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
        border: 0;
    }

    /* Regroupement et tri quittent la rangée pour le panneau, qui s'appelle
       « Filtrer et trier » et les presente en sections nommees. Il ne reste
       donc que trois contrôles, et ils tiennent sur une ligne. */
    .content-list__controls-present {
        display: none;
    }

    .content-list__view {
        flex: 0 0 auto;
    }}

@media (width < 40em) {
    .content-list__controls .content-list__filters-label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
        border: 0;
    }}

@media (width < 48em) {
    .content-list__controls .dropdown__menu {
        right: auto;
        left: 0;
        max-width: calc(100vw - 2rem);
    }}

/* ── Bascule d'affichage ── */
/* Pas de `gap` ici : l'étiquette porte déjà sa propre marge basse
   (`.content-list__filters-label`). Les deux s'additionnaient, et la bascule
   partait cinq pixels plus haut que ses voisines — un écart invisible sur les
   contrôles, mais lisible sur la ligne des étiquettes. */
.content-list__view {
    display: flex;
    flex-direction: column;
}

/* Masquée sous 640 px, où la carte couchée reprend sa forme verticale
   (`.media-card--row`, même seuil) : les deux modes y rendent alors la MÊME
   chose — colonne unique, visuel pleine largeur en haut. Mesure à 375 px :
   349 × 196 de visuel dans les deux cas, 12 px d'écart de hauteur de carte.
   Un contrôle qui ne change rien est pire qu'absent : il fait douter de ce
   qu'on vient de cliquer. Le paramètre d'URL, lui, reste honoré. */
@media (width < 40em) {
    .content-list__view {
        display: none;
    }
}

.content-list__view-options {
    display: inline-flex;
    /* `box-sizing` hérité : la bordure est COMPRISE dans la hauteur, sinon la
       bascule dépasse ses voisines de deux pixels. */
    height: var(--control-height, 2rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--surface-2);
}

.content-list__view-option {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 100%;
    color: var(--color-text-light);
    text-decoration: none;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.content-list__view-option + .content-list__view-option {
    border-left: 1px solid var(--color-border);
}

.content-list__view-option:hover {
    background: var(--color-bg-light);
    color: var(--color-text);
}

.content-list__view-option--active {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

/* Le déclencheur d'une liste déroulante tient sa hauteur de son propre
   `padding` : 30 px, deux de moins que ses voisines. Dans cette rangée, la
   hauteur vient de la rangée. */
.content-list__controls .dropdown__trigger {
    height: var(--control-height, 2rem);
}

/* ── Sections du panneau ── */
.content-list__filters-section {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

.content-list__filters-section-title {
    margin: 0;
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--color-navy);
}

/* Dans une section « Regroupement » ou « Tri », l'étiquette du contrôle répète
   le titre. Elle est masquée à l'œil mais CONSERVÉE : c'est elle que vise le
   `aria-labelledby` du déclencheur, la retirer le laisserait sans nom. */
.content-list__filters-present .dropdown__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Le duo regroupement + tri du panneau n'existe que sous 48em : au-dessus, il
   vit dans la rangée, où il est atteignable sans ouvrir quoi que ce soit. */
.content-list__filters-present {
    display: none;
}

@media (width < 48em) {
    .content-list__filters-present {
        display: flex;
        flex-direction: column;
        gap: var(--spacing-md);
    }}

/* ── Proximité dans le panneau ──
   Le bloc vient du rail, où il portait sa propre carte grise, un titre en gras
   navy et des intitulés en minuscules. Posé sous cinq listes déroulantes à
   l'étiquette grise en capitales de 11 px, il ressemblait à une pièce
   rapportée. On ne touche PAS aux classes `sidebar-filters__*` elles-mêmes :
   elles servent encore les rails de /dossiers et /newsletters. */
.content-list__filters-proximity .sidebar-filters__group--proximity {
    padding: 0;
    border: 0;
    background: none;
}

.content-list__filters-proximity .sidebar-filters__group-header {
    margin-bottom: 0.3rem;
}

.content-list__filters-proximity .sidebar-filters__group-title,
.content-list__filters-proximity .sidebar-filters__field-label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

.content-list__filters-proximity .sidebar-filters__group-link {
    font-size: var(--font-size-xs);
    font-weight: 600;
}

/* Les deux champs se partagent la ligne, chacun aligné sur le gabarit des
   listes déroulantes : intitulé au-dessus, contrôle pleine largeur. */
.content-list__filters-proximity .sidebar-filters__field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
}

.content-list__filters-proximity .sidebar-filters__input {
    width: 100%;
    height: 2rem;
    padding: 0 0.6rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    font-size: var(--font-size-sm);
    color: var(--color-text);
}

.content-list__filters-proximity .sidebar-filters__input:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-navy) 12%, transparent);
}

/* ── Panneau de filtres ──
   L'ENVELOPPE du panneau (position, tiroir latéral au-dessus de 48em, feuille
   qui remonte du bas en dessous, voile, barre de titre, bouton de fermeture)
   est la coquille partagée : `components/modal.css`, variante
   `overlay--drawer`. Le panneau garde ici la classe `content-list__filters`
   pour que les règles de CONTENU ci-dessous continuent de s'y accrocher.

   Un panneau plutôt qu'une rangée : le nombre de facettes va de deux
   (glossaire) à sept (catalogue), et une rangée qui s'allonge finit par
   déborder — ses menus déroulants sortaient alors du cadre. */

/* Dans le panneau, chaque contrôle occupe la ligne : c'est un formulaire, plus
   une rangée. */
.content-list__filters .dropdown,
.content-list__filters-search,
.content-list__filters-range,
.content-list__filters-proximity,
/* Deux declarations du meme selecteur ont ete fusionnees ici. Elles ne se
   contredisaient pas, mais c'est exactement la forme qui a coute trois pixels de
   decalage sur l'etiquette de controle plus tot aujourd'hui : deux blocs
   separes, l'un ajoute plus tard, et une propriete du premier qu'on ne pense
   plus a relire en modifiant le second.

   La lettre etait en `width: 100%` — juste dans la grille a six colonnes du rail
   d'ou elle vient, une lettre par ligne ici. Elle redevient un carre. */
.content-list__filters-alphabet {
    flex: 0 0 auto;
    width: 100%;
    max-width: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
}

.content-list__filters-alphabet .glossary-alphabet__letter {
    width: 1.75rem;
}

/* Verrou de défilement pendant que le panneau est ouvert. Posé sur `<html>`
   par `filtersPanel`. */
.u-scroll-locked {
    overflow: hidden;
}

/* Toolbar (compteur + tri + chips + toggle filtres)
   Deux rangees verticales :
     - Rangee 1 : compteur a gauche + tri/filtre a droite.
     - Rangee 2 : chips pleine largeur (wrap si nombreux).
   Pas de border-bottom — l'enchainement avec la liste se fait par
   le margin-bottom standard, sans separateur visible. */
.content-list__toolbar {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    /* PAS DE MARGE BASSE. La colonne qui la contient (`content-list__main`)
       porte desormais une gouttiere de 16 px ; la marge s'y AJOUTAIT, donc 32 px
       entre le compteur et la premiere carte quand la maquette en pose 16.

       Meme regle que pour les etiquettes, un cran plus haut : l'ecart entre deux
       freres appartient a leur parent, jamais a l'un des deux. Un frere qui
       porte sa propre marge ne peut pas savoir si son voisin en porte une
       aussi. */
    margin-bottom: 0;
}

.content-list__toolbar-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    min-height: 1.75rem;
}

.content-list__controls + .content-list__toolbar-row .content-list__toolbar-left {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-sm) var(--spacing-md);
}

.content-list__toolbar-left {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    min-width: 0;
    flex: 1;
}

/* Conteneur des chips — pleine largeur sous la rangee compteur/tri. */
.content-list__toolbar-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs);
}

/* .content-list__rss supprime — bouton RSS vit desormais dans
   components/rss-button.css (brique design-system, dropdown 3 formats). */

.content-list__toolbar-right {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    flex-shrink: 0;
}

.content-list__filter-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.3rem;
    border-radius: 100px;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
    background: var(--color-primary);
    color: var(--color-on-primary);
}

/* ── LE SEPARATEUR ENTRE DEUX GROUPES DE CONTROLES ──
   « Grouper » et « Trier » se suivaient sans rien entre eux : les sept
   pastilles se lisaient comme une seule rangee, et l'etiquette du second groupe
   arrivait au milieu sans annoncer qu'un nouveau jeu commencait. La maquette
   pose un filet vertical entre les deux.

   PORTE PAR UN PSEUDO-ELEMENT du second bloc, donc AUCUN balisage en plus : un
   `<span>` separateur serait un element vide que les technologies d'assistance
   annoncent, pour un trait qui ne dit rien qu'elles ne sachent deja par le
   `role="group"` et son etiquette. */
.content-list__controls-present + .content-list__controls-present::before {
    content: '';
    flex: none;
    align-self: center;
    width: 1px;
    height: 1.375rem;
    background: var(--color-border);
}

/* Le bloc doit etre une rangee pour que le filet se pose devant son contenu.

   SOUS 48EM CETTE REGLE NE DOIT PAS S'APPLIQUER : le regroupement et le tri
   quittent la rangee pour le tiroir, et une regle `display: none` les y envoie
   plus haut dans ce fichier. Une media query N'AJOUTE AUCUNE SPECIFICITE — a
   specificite egale, c'est la DERNIERE ecrite qui gagne, donc celle-ci
   annulait le masquage et les huit pastilles restaient sur telephone, 178 px
   avant le premier resultat. Mesure a 390 px.

   Le defaut est invisible a la lecture de l'une ou l'autre regle : il ne nait
   que de leur ORDRE dans le fichier. */
@media (width >= 48em) {
    .content-list__controls-present {
        display: flex;
        align-items: center;
        gap: var(--spacing-sm);
        flex-wrap: wrap;
    }
}

/* ══════════════════════════════════════════════════════════════
   LA BARRE EN CARTE : L'ETIQUETTE AU-DESSUS DE SES PASTILLES
   ══════════════════════════════════════════════════════════════

   En rangee, « GROUPER » + quatre pastilles + « TRIER » + quatre pastilles ne
   tiennent pas dans la colonne de resultats : le compteur restait seul sur la
   premiere ligne, avec six cents pixels de vide a sa droite, et les huit
   pastilles s'entassaient sur la seconde. La carte ne « tenait » plus ce
   qu'elle annonce.

   Chaque groupe devient une COLONNE — son etiquette au-dessus, ses pastilles
   dessous, le tout aligne a gauche. Les groupes restent cote a cote tant qu'il
   y a la place, et passent a la ligne ensemble sinon : c'est l'etiquette qui
   redevient le repere, au lieu d'un mot perdu au milieu d'une file.

   BORNE A LA VARIANTE CARTE. Les listes qui posent leurs controles hors carte
   gardent la rangee : la contrainte de largeur y est differente, et changer les
   deux d'un coup ferait bouger six pages pour le probleme d'une. */
.content-list__controls--card .content-list__field--inline {
    align-items: center;
    gap: var(--spacing-xs);
}

/* SEULE L'ETIQUETTE PREND SA LIGNE. Un `flex-direction: column` sur le groupe
   empilait AUSSI les pastilles, une par ligne — mesure a l'ecran. C'est la
   base a 100 % qui isole l'etiquette et laisse les pastilles s'enrouler en
   rangee dessous. */
/* ── LE GROUPE EST UNE COLONNE : ETIQUETTE, PUIS RANGEE DE PASTILLES ──
   Les pastilles ont desormais leur propre conteneur (`__pills`), et c'est ce
   qui rend la largeur DETERMINISTE. Avant, le bloc etait un flex qui enroule :
   sa largeur intrinseque se calculait sur tous ses enfants mis sur UNE ligne,
   etiquette comprise, puis il retrecissait pour tenir — et s'arretait plus loin
   que ses pastilles. Mesure : 55 px de vide a droite sous « Grouper », 35 sous
   « Trier », donc deux filets a des distances differentes de leurs pastilles.

   J'ai essaye deux reglages de `flex` avant de comprendre que le defaut etait
   STRUCTUREL. C'est la mesure du vide A DROITE de la derniere pastille, et non
   celle des ecarts entre blocs (8 px, homogenes), qui l'a montre. */
.content-list__controls--card .content-list__field--inline {
    flex-direction: column;
    align-items: flex-start;
}

/* LES DEUX GROUPES DOIVENT POUVOIR SE RESSERRER, sans quoi le `flex-wrap` de
   leurs pastilles ne sert a rien : `min-width: auto` empeche un enfant de flex
   de descendre sous la largeur de son CONTENU, et ce contenu est calcule avec
   toutes les pastilles sur une seule ligne.

   Mesure sur le catalogue de formations, quatre pastilles de regroupement plus
   quatre de tri : 72 px hors de la carte a 1440 et 1280, 191 px a 1024. Les
   pastilles ne se repliaient jamais, elles debordaient. */
.content-list__controls--card .content-list__controls-present,
.content-list__controls--card .content-list__field--inline {
    min-width: 0;
}

/* LA RANGEE DE PASTILLES SE TIENT PARTOUT, PAS SEULEMENT DANS LA BARRE.

   Cette regle vivait sous `.content-list__controls--card`, donc `_pill_group`
   ne savait se rendre qu'a l'interieur de la barre d'outils d'une page de
   liste. Employee ailleurs — le filtre de periode d'une fiche de formation —
   la brique rendait un `<span>` en `display: inline`, ses pastilles a la
   queue leu leu sans gouttiere ni repli. Rien ne le signalait : un composant
   partage qui ne s'applique pas se lit comme un composant applique.

   Mesure du 2026-09-01 : `inline` hors barre, `flex` dedans, pour le meme
   balisage. C'est la definition d'une brique qui ne tient pas sa promesse. */
.content-list__pills {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs);
}

/* Le compteur rejoint la rangee des controles plutot que d'occuper une ligne
   a lui seul : aligne sur la base des etiquettes, il se lit comme le premier
   des reperes. */
.content-list__controls--card {
    align-items: flex-start;
}

/* Le filet monte sur toute la hauteur du groupe le plus haut, sinon il ne
   separe que les etiquettes et laisse les deux files de pastilles se toucher. */
.content-list__controls--card .content-list__controls-present + .content-list__controls-present::before {
    align-self: stretch;
    height: auto;
}

/* LE COMPTEUR SUR LA MEME LIGNE QUE LES ETIQUETTES.
   Le premier bloc de la barre porte `flex: 1 1 auto` : mesure, il prenait 854 px
   des 888 de la carte et repoussait les groupes a la ligne suivante. Le compteur
   se retrouvait seul en haut, avec six cents pixels de vide a sa droite.

   Reduit a son contenu, il laisse la place aux deux groupes — 150 + 722 tiennent
   dans 888 — et `margin-left: auto` les garde plaques a droite. En dessous, le
   manque de place les fait passer a la ligne, ce qui reste le bon comportement. */
.content-list__controls--card > .content-list__controls-group:first-child {
    /* `0 1 auto` LE LAISSAIT SE COMPRIMER SOUS SON CONTENU : mesure, le groupe
       rendait 99 px pour un compteur de 121, et le texte passait sous le filet
       du groupe suivant. C'est le bug d'affichage signale — pas une couleur ni
       un rembourrage, un element plus large que la boite qui le porte. */
    flex: 0 0 auto;
    /* CENTRE VERTICALEMENT. La barre aligne ses blocs en haut, parce que les
       groupes de pastilles y posent leur etiquette ; le compteur, lui, n'en a
       pas et se retrouvait cale sur la ligne des etiquettes, deux crans
       au-dessus du centre optique de la rangee. */
    align-self: center;
}
/* MAIS QUAND LE GROUPE PORTE LE CHAMP DE RECHERCHE, il doit CROITRE.

   Le `0 0 auto` ci-dessus a ete ecrit pour une barre qui ne porte qu'un
   compteur et des pastilles — /actualites, /evenements. Le glossaire y met en
   plus le champ : compteur (41) + champ (328) + « Filtres » (85) reclament
   470 px, le groupe en obtenait 376, et la rangee passait a TROIS lignes,
   113 px de haut, dans une barre large de 824. Mesure au rendu, 2026-08-31.

   `:has()` plutot qu'un modificateur a passer par l'appelant : la regle suit ce
   que le groupe CONTIENT, donc elle ne peut pas etre oubliee au douzieme
   gabarit. Les barres sans champ gardent exactement le comportement d'avant. */
.content-list__controls--card > .content-list__controls-group:first-child:has(.content-list__controls-search) {
    flex: 1 1 auto;
}

/* ── LE COMPTEUR SUR DEUX LIGNES ──
   Le chiffre d'abord, son libelle dessous. C'est ce que Luc demandait, et ca
   regle deux choses d'un coup : le nombre se lit d'un coup d'oeil au lieu de se
   chercher dans une phrase, et le bloc devient assez etroit pour ne plus
   toucher le filet.

   `display: flex` en colonne SUFFIT : le noeud de texte qui suit le `<strong>`
   devient un element de flux anonyme, donc il prend sa propre ligne. Aucun
   balisage a changer dans la brique partagee. */
.content-list__controls--card .content-list__count {
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1.25;
}

.content-list__controls--card .content-list__count strong {
    font-size: var(--font-size-lg);
    line-height: 1.1;
}

/* LE COMPTEUR SUR LA MEME LIGNE QUE LES GROUPES, au-dela de 80em.

   Le navigateur decide de couper d'apres la taille HYPOTHETIQUE d'un element,
   c'est-a-dire sa base — `auto`, donc la largeur max-content : toutes les
   pastilles sur un seul rang. Elle depassait la place restante, donc coupure,
   alors meme que le bloc ENROULE fait 722 px et tient a cote des 120 du
   compteur dans les 888 de la carte.

   Prouve par neutralisation : en forcant `nowrap`, les deux passent a la meme
   hauteur sans le moindre debordement de page.

   UNE BASE NULLE (`flex: 1 1 0`) reglait bien la coupure, mais empilait
   « GROUPER » et « TRIER » l'un sous l'autre : la carte passait de 103 a 119 px,
   soit l'inverse de ce qu'on cherche. C'est donc l'enroulement qu'on desactive,
   et SEULEMENT la ou les trois tiennent — sous ce palier la carte n'a plus la
   largeur, et l'enroulement redevient le bon comportement. */
/* SOUS LE PALIER OU LES TROIS TIENNENT, LE REPLI S'ALIGNE A GAUCHE.

   Aligne a droite, chaque rangee se cale sur le bord droit : deux rangees de
   largeurs differentes commencent donc a deux endroits differents, et la barre
   se lit en drapeau avec un grand vide a gauche. Signale comme laid, et ca
   l'est — un repli doit se lire comme deux lignes d'un meme bloc, pas comme
   deux blocs sans rapport.

   Au-dela du palier, la rangee tient sur UNE ligne et l'alignement a droite
   reste le bon : c'est lui qui separe ce qu'on cherche (a gauche) de la facon
   dont on le presente (a droite). */
@media (width < 80em) {
    .content-list__controls--card > .content-list__controls-group--end {
        justify-content: flex-start;
        margin-left: 0;
    }
}

@media (width >= 80em) {
    .content-list__controls--card {
        flex-wrap: nowrap;
    }

    /* `0 1 auto` ET NON `0 0 auto` : la base reste `auto`, donc les deux groupes
       restent cote a cote TANT QU'ILS TIENNENT — c'est l'intention ci-dessus, et
       elle est conservee. Mais interdire le retrecissement les faisait DEBORDER
       des que les libelles s'allongent : mesure sur le catalogue de formations,
       72 px hors de la carte a 1440 et 1280, la ou `/ressources` tenait a 17 px
       pres. Avec `0 1`, le groupe se resserre quand il le faut et son propre
       enroulement met « TRIER » sous « GROUPER » — deux lignes valent mieux
       qu'un depassement. */
    .content-list__controls--card > .content-list__controls-group--end {
        flex: 0 1 auto;
        margin-left: auto;
    }
}

/* LES JETONS DE FILTRES ACTIFS RESTENT HORS DE LA CARTE.

   Je les y avais soudes — carte ouverte en bas, rangee refermant la surface —
   pour qu'ils cessent de flotter. Luc a tranche l'inverse, et sa lecture tient :
   la carte porte les CONTROLES, les jetons disent l'ETAT courant du filtrage.
   Deux natures, deux surfaces, et c'est aussi ce que pose la maquette, dont la
   rangee de jetons est un bloc libre entre la barre et les resultats.

   Ce que la soudure a tout de meme laisse : la bordure basse retablie
   ci-dessus. Sans elle la carte s'ouvre sur le fond de page, et le defaut
   restait invisible tant qu'une rangee la fermait. */

/* ── LE FILET APRES LE COMPTEUR ──
   « 4 ressources filtrees » touchait « GROUPER » : deux informations de nature
   differente — ce qu'on a trouve, comment on le presente — collees sans rien
   entre elles. Meme trait que celui qui separe deja les deux groupes. */
@media (width >= 80em) {
    .content-list__controls--card > .content-list__controls-group--end::before {
        content: '';
        flex: none;
        align-self: stretch;
        width: 1px;
        margin-right: var(--spacing-ms);
        background: var(--color-border);
    }
}

