/* @grammaire v2
   ══════════════════════════════════════════════════════════════════════════
   LA COQUILLE DU MINISITE EVENEMENT

   Elle remplace la pile de bandes pleine largeur posees a meme le plateau gris
   par le SQUELETTE DE FICHE du site : une colonne d'appui a gauche, une carte
   blanche a droite, et le rythme des sections a l'interieur de cette carte.

   ── POURQUOI CE CHANGEMENT DE FORME ──

   Releve du 2026-09-01 sur `/evenements/2026-angers`, a 1440 px et a 390 px :

   · aucune colonne. Neuf sections pleine largeur s'empilaient sur le plateau,
     chacune posant sa propre carte, ses propres gouttieres et son propre fond.
     Les bords droits de deux rangees voisines ne tombaient pas au meme pixel
     (358 pour l'une, 366 pour l'autre) parce que chaque section declarait sa
     grille ;
   · rien ne tenait l'ensemble. Le plateau gris ne porte JAMAIS de contenu dans
     cette grammaire, il porte des cartes — c'est le defaut n°2 releve sur la
     fiche CESU, et c'est le meme ici ;
   · 5 938 px de hauteur sur telephone, dont pres d'un tiers en fonds alternes
     qui ne signifiaient rien ;
   · la barre d'onglets et son bouton rouge coupaient la page en deux, et
     l'engagement — s'inscrire — n'existait qu'a cet endroit-la.

   ── CE QUE LA COQUILLE POSE ──

   1. LE RAIL EST A GAUCHE, ET IL PORTE L'ENGAGEMENT. Identite de l'evenement,
      etat des inscriptions, bouton, menu du minisite, reperes. Il est PREMIER
      dans le balisage, pas seulement a l'ecran : dans une grille, l'ordre du
      source est l'ordre de lecture. Meme choix, et meme raison, que la fiche
      CESU dont cette coquille reprend le squelette.

   2. LE CONTENU EST UNE CARTE BLANCHE, et ses sections se separent par un
      filet plutot que par un changement de fond. Un filet coute une ligne,
      un fond coute une bande.

   3. SUR TELEPHONE, LE RAIL S'EMPILE AU-DESSUS et le menu se replie derriere
      un declencheur qui porte le nom de la page courante. Ce qui reste visible
      est ce qui sert : l'identite, l'etat, le bouton.
   ══════════════════════════════════════════════════════════════════════════ */


/* ══════════════════════════════════════════════════════════════
   LA GRILLE
   ══════════════════════════════════════════════════════════════ */

/* Les deux pistes d'`article-single__layout` sont ECHANGEES : le rail prend la
   premiere. Le squelette du site reste, seule la place de l'appui change. */
@media (width >= 64em) {
    .minisite-shell__layout {
        grid-template-columns: 20rem minmax(0, 1fr);
    }

    /* ── LES COLONNES SONT PLACEES, PAS DEDUITES DE L'ORDRE ──
       Le contenu precede desormais le rail dans le BALISAGE, pour que la page
       s'ouvre dessus sur telephone. Sans placement explicite, le contenu
       tomberait donc dans la premiere piste — celle de 20 rem — et le rail dans
       la seconde : la page entiere inversee et illisible au bureau.

       Le placement est ce qui rend les deux ordres independants : le balisage
       decide de la pile sur telephone, la grille decide des colonnes au bureau,
       et aucun `order` ne vient dissocier l'ordre de lecture du clavier de ce
       que l'oeil voit. */
    .minisite-shell__layout > .article-sidebar {
        grid-column: 1;
        grid-row: 1;
    }

    .minisite-shell__layout > .article-single__main {
        grid-column: 2;
        grid-row: 1;
    }
}


/* ── UN SEUL PAS SEPARE TOUT CE QUI EST EMPILE ──
   La banniere se detachait du contenu de 32 px au bureau et 52 sur telephone,
   quand deux cartes du rail sont a 16. Trois declarations s'additionnaient — la
   marge basse de la banniere, le rembourrage haut du squelette de fiche, et la
   marge du rail empile — chacune raisonnable seule.

   L'ecart vient desormais d'ICI seulement, et il vaut le meme `gap` que celui
   des cartes du rail (`article-sidebar__sticky`). Les deux se lisent comme une
   seule pile. */
.minisite-shell__layout {
    padding-top: var(--spacing-md);
}

/* Sous le palier, le rail est le DERNIER element de la pile depuis que le
   contenu ouvre la page. Sa marge d'element empile valait zero du temps ou il
   la fermait — elle se serait ajoutee au rembourrage ci-dessus. En dernier, il
   n'a plus rien qui le separe du contenu : les deux cartes se touchaient, ce
   qui les fait lire comme une seule. La valeur est celle qui separe deja deux
   cartes du rail entre elles, donc toute la pile respire au meme pas. */
@media (width < 64em) {
    .minisite-rail.article-sidebar--stacked {
        margin-top: var(--spacing-md);
    }
}

/* ── UN SEUL RYTHME, ET IL VIENT DU SEPARATEUR ──

   La carte posait `gap: var(--rhythm-section)` ET chaque section separee
   ajoutait `padding-top: var(--rhythm-section)` : les deux s'additionnaient.
   Mesure du 2026-09-02 : 64 px entre deux sections au bureau, 40 sur telephone,
   avec le filet flottant au milieu de ce vide. Chaque declaration etait
   raisonnable seule, et personne ne les avait vues ensemble.

   Le `gap` tombe a zero. L'ecart vient desormais du SEPARATEUR, et il est
   symetrique de part et d'autre du filet — c'est la forme que la maquette pose
   (`margin-top: 24; padding-top: 24; border-top`), et elle se lit mieux qu'un
   trait perdu au milieu de deux fois plus de blanc. */
.minisite-card {
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* Sur telephone, la carte perd son rembourrage lateral genereux : a 390 px,
   32 px de chaque cote laissent 326 px de colonne de lecture. */
@media (width < 48em) {
    .minisite-card {
        padding: var(--spacing-lg) var(--spacing-md);
    }
}

/* ── LE FILET PLUTOT QUE LA BANDE ──
   Chaque section qui suit la premiere se separe par un filet. Un filet coute
   une ligne, un changement de fond coute une bande.

   L'ECART EST SYMETRIQUE : autant au-dessus du filet qu'en dessous. Le trait
   marque alors le milieu de la respiration, au lieu d'etre colle a la section
   qui suit. */
.minisite-section + .minisite-section {
    margin-top: var(--spacing-lg);
    padding-top: var(--spacing-lg);
    border-top: 1px solid var(--color-border);
}

/* ── LE RYTHME INTERNE, ET IL VAUT LA MOITIE DU RYTHME ENTRE SECTIONS ──
   24 px dans une section, 24 + 24 entre deux : une seule echelle, et la
   respiration double quand on change de sujet. */
.minisite-section {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

/* `_section_header` porte `margin-bottom: var(--spacing-lg)` pour les pages qui
   le posent a meme le plateau, sans conteneur a `gap`. Ici la section EST ce
   conteneur : les deux s'additionnaient, et l'ecart entre un en-tete et son
   contenu valait 40 px pour un rythme declare a 16. Meme defaut de double
   propriete que celui corrige entre les sections, un niveau plus bas. */
.minisite-section > .section-header {
    margin-bottom: 0;
}

/* MEME DEFAUT, UN CRAN PLUS BAS : le corps editorial. La section porte deja
   son `gap`, et son premier bloc y ajoute sa propre marge haute — les deux
   valent `--spacing-lg`, donc l'ecart valait 48 px pour un rythme declare a
   24. Mesure du 2026-09-02 sur `/evenements/2026-angers`, entre « Le theme »
   et le teaser video, identique a 1440 et a 375 px.

   `.prose-content > * + *` ne couvre pas ce cas : c'est une regle ENTRE
   freres, et le coupable est le premier enfant. Le seul reset existant vise
   `h2:first-child` — un corps qui s'ouvre sur une figure passait a travers.

   Le `:last-child` est PREVENTIF, et il n'est pas verifiable sur cette page :
   son corps se termine par un `<p>`, dont la marge basse est deja nulle. Mais
   `.prose-content .editor-video` porte `margin: var(--spacing-lg) 0` : un
   corps qui se TERMINE par une video, une image DAM ou un tableau doublerait
   au bas exactement comme celui-ci doublait en haut. */
.minisite-section > .prose-content > :first-child {
    margin-top: 0;
}

.minisite-section > .prose-content > :last-child {
    margin-bottom: 0;
}

/* Deux blocs cote a cote DANS la carte (tarifs / appel, pratique / participer).
   `minmax(0, 1fr)` et non `1fr` : sans le minimum a zero, un contenu
   insecable — une URL, un tableau — pousse sa piste et fait deborder la
   grille. */
.minisite-duo {
    display: grid;
    gap: var(--spacing-lg);
}

/* —— L'ACCROCHE D'UN APPEL EST ECRETEE ——
   Deux blocs de corps suffisent a poser le sujet, mais un appel bavard etire
   toute la RANGEE : les cartes etant a hauteur egale, sa voisine se retrouve
   avec un grand vide sous son texte. Mesure du 2026-09-03 : 448 px pour trois
   lignes utiles a droite.

   Trois lignes sur 782 px, la ou il en fallait quatre sur 379 pour en dire
   autant. Le reste se lit sur la fiche, ou
   il a la place. Meme parti que la carte de rebond de la grammaire, dont le
   texte est ecrete a trois lignes pour la meme raison.

   `-webkit-line-clamp` reste la seule facon d'ecreter un nombre de LIGNES : ni
   `max-height` ni `text-overflow` ne savent le faire sur plusieurs lignes, et
   la propriete standard `line-clamp` n'est pas encore servie partout. Le
   prefixe est donc porte a dessein, pas par oubli. */
.minisite-call__text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

/* Le corps editorial rend des `<p>` : leurs marges casseraient l'ecretage, qui
   compte des lignes dans une seule boite. */
.minisite-call__text.prose-content > * {
    margin: 0;
}

/* —— UNE COLONNE, UN APPEL PAR LIGNE ——
   Ils tenaient sur deux colonnes, ce qui obligeait a EGALISER leurs hauteurs
   puis a ECRETER leur accroche : a 379 px, une carte n'a la place que de trois
   lignes, et la voisine se retrouve avec un vide des que l'une parle plus que
   l'autre. Les deux correctifs ont ete livres, puis retires ici — une colonne
   unique n'a rien a egaliser.

   Un appel a contribution n'est pas une vignette de catalogue : c'est une
   decision a prendre, et il y en a deux ou trois par edition. */
.minisite-calls {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

@media (width >= 60em) {
    .minisite-duo {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        align-items: start;
    }

    /* ── UN BLOC SEUL PREND LES DEUX PISTES ──
       Les deux moities d'un duo sont conditionnelles chacune de son cote :
       les tarifs disparaissent sur une edition passee, l'appel a contribution
       n'existe pas partout, et le pratique vient de disparaitre du passe. Un
       bloc restant seul se rangeait alors dans la premiere piste et laissait la
       seconde vide — une demi-page blanche a cote d'un bloc, sans que rien
       n'indique qu'il manque quelque chose.

       Aucune donnee d'aujourd'hui ne produit ce cas : sur les neuf editions
       passees, aucune n'a de bloc « participer autrement ». C'est justement
       pourquoi la regle est posee maintenant — le defaut n'apparaitrait qu'a la
       premiere edition qui en aura un, et personne ne le relierait a ce lot. */
    .minisite-duo > :only-child {
        grid-column: 1 / -1;
    }
}


/* ══════════════════════════════════════════════════════════════
   LE RAIL
   ══════════════════════════════════════════════════════════════ */

/* Il porte cinq blocs et depasse la fenetre : rien ne le plafonne et rien ne
   l'ecrete, sans quoi il devient un conteneur a ascenseur interne ou le doigt
   attrape tantot la boite, tantot la page. `sticky` reste : sur un contenu plus
   haut que la fenetre, il se comporte comme un bloc ordinaire jusqu'a ce que
   son bas soit atteint. Meme correction, meme cause, que sur la fiche CESU. */
.minisite-rail .article-sidebar__sticky {
    max-height: none;
    overflow: visible;
    gap: var(--spacing-md);
}

/* ── L'AFFICHE TIENT LIEU D'IDENTITE DANS LE RAIL ──

   Elle remplace un bloc de titre, sous-titre, dates et lieu : quatre lignes de
   texte pour redire ce que l'en-tete de la page dit deja, et qui poussaient le
   menu plus bas a chaque page selon la longueur du nom.

   La carte n'a ni rembourrage ni fond : l'affiche EST le bloc. Un cadre autour
   d'une affiche fait un cadre dans un cadre. */
.minisite-poster.article-sidebar__section {
    padding: 0;
    background: none;
    overflow: hidden;
    border-radius: var(--radius-md);
}

.minisite-poster__img {
    display: block;
    width: 100%;
    height: auto;
}

/* ── L'ENGAGEMENT ──
   Le bloc qui porte l'etat des inscriptions et le bouton. Il suit le visiteur
   sur toutes les pages du minisite : c'est le seul endroit du site ou l'on
   s'inscrit, et il n'avait auparavant qu'une place — le coin droit d'une barre
   d'onglets, perdu des que la barre passait en menu replie sur telephone. */
.minisite-cta__state {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin: 0 0 var(--spacing-sm);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
}

/* La pastille dit l'etat A L'OEIL ; le mot qui suit le dit a tout le monde. Une
   couleur seule ne porte jamais une information. */
.minisite-cta__dot {
    flex: none;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--color-text-light);
}

.minisite-cta__state--open .minisite-cta__dot { background: var(--color-success); }
.minisite-cta__state--soon .minisite-cta__dot { background: var(--color-warning); }
.minisite-cta__state--closed .minisite-cta__dot { background: var(--color-text-disabled); }

/* Le bouton prend toute la largeur du rail : un bouton court y laisse un vide
   qui se lit comme un defaut de rendu. */
.minisite-cta__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-xs);
    width: 100%;
}

/* L'echeance sous le bouton, pas dedans : c'est ce qui aide a decider, pas une
   action. Elle faisait trois cents pixels dans le libelle du bouton, ce qui
   faisait passer l'ancienne barre sur deux lignes. */
.minisite-cta__note {
    margin: var(--spacing-sm) 0 0;
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}


/* ── LE MENU DU MINISITE ──
   Meme forme que « Dans cette fiche » de l'annuaire : une liste verticale ou la
   cible fait toute la largeur du rail. Dans une liste, viser la ligne est plus
   facile que viser le mot. */
.minisite-menu__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.minisite-menu__link {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    min-height: var(--touch-target-min);
    padding: var(--spacing-xs) var(--spacing-sm);
    margin-inline: calc(var(--spacing-sm) * -1);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
    text-decoration: none;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.minisite-menu__link:hover {
    background: var(--surface-4);
    color: var(--color-primary);
}

/* L'ONGLET COURANT SE MARQUE PAR SON FOND ET SON ENCRE, jamais par la seule
   couleur : `aria-current` le dit aux technologies d'assistance, le contraste
   le dit a l'oeil. */
/* MARINE, comme la maquette, et non le rose de rubrique : l'entree active se
   lit comme une PLACE dans une liste, pas comme une alerte. Le rose la faisait
   par ailleurs entrer en concurrence avec le seul bouton rouge de la page. */
.minisite-menu__link--on {
    background: var(--color-primary-dark);
    color: var(--color-on-primary);
}

.minisite-menu__count {
    margin-left: auto;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.minisite-menu__link--on .minisite-menu__count {
    color: var(--color-on-navy-muted);
}

/* ── LE MENU DU RAIL CEDE LA PLACE AUX ONGLETS SOUS LE PALIER ──
   Il s'y repliait derriere un declencheur portant la page courante. Il fallait
   donc un geste pour savoir ce que le minisite contient, alors que c'est la
   premiere question de qui arrive par un lien de partage. La banniere porte
   desormais la meme brique en ONGLETS, plus bas dans cette feuille.

   Tout le style du declencheur et de la liste repliee est parti avec lui. Il
   avait cesse d'etre inerte : la liste y prenait un fond blanc et un filet,
   qui se sont appliques aux onglets des leur arrivee — une rangee blanche sur
   le marine de la banniere, avec des libelles en encre claire donc invisibles.
   Un style mort n'est pas neutre, il attend un selecteur qui le reveille. */
@media (width < 64em) {
    /* Sans cela les deux navigations coexistent : deux fois les memes liens
       dans l'arbre d'accessibilite, et un lecteur d'ecran qui annonce le menu
       de l'evenement a deux endroits de la page. */
    .article-sidebar .minisite-menu {
        display: none;
    }
}


/* ── LES REPERES ──
   Deux journees, vingt-six sessions, J-93. Ils qualifient l'evenement ; ils ne
   sont donc pas au meme rang que le contenu, et n'entrent dans aucune carte. */
.minisite-key {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.minisite-key__row {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-sm);
}

.minisite-key__value {
    flex: none;
    min-width: 3rem;
    font-family: var(--font-data);
    font-size: var(--font-size-lg);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.minisite-key__label {
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

/* Sur telephone le rail est empile : les reperes passent en rangee, ou ils
   coutent une ligne au lieu de trois. */
@media (width < 64em) {
    .minisite-key {
        flex-direction: row;
        flex-wrap: wrap;
        gap: var(--spacing-lg);
    }

    .minisite-key__row {
        flex-direction: column;
        gap: var(--spacing-2xs);
    }

    .minisite-key__value {
        min-width: 0;
    }
}


/* ══════════════════════════════════════════════════════════════
   L'EN-TETE DE LA CARTE
   ══════════════════════════════════════════════════════════════ */

/* L'affiche partage la ligne du titre, elle ne lui prend pas un ecran. Sous le
   palier elle passe AU-DESSUS : une affiche reduite a 40 % de 390 px ne montre
   plus rien, et le titre est ce qu'on vient lire. */
.minisite-head {
    display: grid;
    gap: var(--spacing-lg);
}

@media (width >= 60em) {
    .minisite-head--with-poster {
        grid-template-columns: minmax(0, 1fr) 18rem;
        align-items: start;
    }
}

/* —— LE BLOC DE TITRE, AU RYTHME DE LA GRAMMAIRE ——
   Huit pixels lient l'etat, le titre et son filet ; les vingt-quatre de la
   section separent ce bloc de ce qui suit. C'est exactement ce que fait
   `section-header.css` du paquet, et la seule raison pour laquelle ce n'etait
   pas le cas ici est que les trois elements etaient enfants directs de la
   section. */
.minisite-head__title-block {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.minisite-head__title {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-2xl);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-text);
}

@media (width >= 48em) {
    .minisite-head__title {
        font-size: var(--font-size-3xl);
    }
}

.minisite-head__subtitle {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-lg);
    font-weight: 600;
    line-height: var(--line-height-tight);
    color: var(--color-primary);
}

/* La marge s'ajoutait au `gap` de la grille : 40 px entre le filet et le chapo
   pour un rythme declare a 24. Septieme occurrence de ce doublement dans cette
   feuille — dans un conteneur a `gap`, un enfant ne declare pas son ecart. */
.minisite-head__lead {
    margin: 0;
    max-width: var(--measure-prose);
    font-size: var(--font-size-md);
    line-height: var(--line-height-loose);
    color: var(--color-text-light);
}

.minisite-head__meta {
    margin: var(--spacing-sm) 0 0;
    font-family: var(--font-data);
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* ── LA LIGNE DE REPERAGE ──
   Quand, ou, dans quelle seance. Elle vivait dans une carte laterale « Ou et
   quand » : ce sont des reperes du PROPOS, et les lire obligeait a traverser la
   page depuis le titre qu'ils qualifient. Sous le titre, ils se prennent d'un
   coup d'oeil.

   Ni carte ni cadre : une carte les mettrait au meme rang que le contenu qu'ils
   qualifient, ce que la regle des reperes dit deja pour `.minisite-key` et
   `.minisite-marks`.

   L'ECART VIENT DU CONTENEUR, JAMAIS DU SEPARATEUR. Ecrit colle au texte, le
   point median rendait « 10 decembre 2025· 08:55 » : il se dessine en
   `::before` avec sa propre marge, et le `gap` porte le reste. */
.minisite-head__metas {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--spacing-2xs) var(--spacing-sm);
    margin: 0;
    padding: 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

.minisite-head__metas-item {
    display: flex;
    align-items: baseline;
}

/* Le separateur precede son repere : en `::after` du precedent il reste
   ORPHELIN en fin de rangee quand la ligne se replie, et la rangee suivante
   s'ouvre sans rien qui la rattache. Meme correction que sur le fil d'Ariane de
   la banniere. */
.minisite-head__metas-item + .minisite-head__metas-item::before {
    content: '·';
    margin-right: var(--spacing-sm);
    color: color-mix(in srgb, var(--color-text-light) 55%, transparent);
}

/* La figure ne pose aucune marge : c'est la grille qui donne l'ecart, et une
   marge de `<figure>` par defaut la doublerait. */
.minisite-head__figure {
    margin: 0;
}

/* L'affiche garde ses proportions et son cadre. `--radius-md` et non `lg` :
   elle vit DANS une carte, et deux rayons emboites de meme valeur se lisent
   comme un defaut d'alignement. */
.minisite-head__poster {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
}

.minisite-head__credit {
    display: block;
    margin-top: var(--spacing-xs);
    font-size: var(--font-size-2xs);
    color: var(--color-text-light);
}


/* ══════════════════════════════════════════════════════════════
   LE PAVE DE CLOTURE
   ══════════════════════════════════════════════════════════════ */

/* Dernier bloc de la carte : il redit l'engagement au bas d'une page longue,
   la ou le rail a defile hors de vue sur telephone. Sur grand ecran le rail est
   collant et le porte deja — d'ou sa forme de RAPPEL, pas de bandeau. */
.minisite-close {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    padding: var(--spacing-lg);
    border-radius: var(--radius-md);
    background: var(--color-primary-dark);
    color: var(--color-on-primary);
}

.minisite-close__text {
    min-width: 0;
}

.minisite-close__title {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--color-on-primary);
}

.minisite-close__note {
    margin: var(--spacing-2xs) 0 0;
    font-size: var(--font-size-sm);
    color: var(--color-on-navy-muted);
}


/* ── LA NOTE D'UNE SECTION ──
   La phrase qui borde un bloc sans en etre le contenu : « le detail se trouve
   sur la page d'inscription ». Elle n'est ni un chapo — elle ne suit pas le
   titre — ni un corps. */
.minisite-note {
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}


/* ── LES PALIERS TARIFAIRES DANS UNE DEMI-COLONNE ──
   `.evt-prices` est dimensionnee pour la pleine largeur du plateau : ses pistes
   ne descendent pas sous 11,5 rem, donc dans une colonne de duo (355 px a
   1440) elles retombent a UNE par ligne, et chaque palier rend 150 px de haut
   pour un montant. Deux paliers occupaient alors plus de place que la frise
   d'echeances au-dessus d'eux.

   Meme correction que celle qu'`events.css` applique deja a `.evt-callout` :
   `auto-fit` sur 8 rem, un rembourrage et un corps de montant a la mesure de la
   colonne. */
.minisite-duo .evt-prices {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
    gap: var(--spacing-sm);
}

.minisite-duo .evt-price {
    padding: var(--spacing-md);
    gap: var(--spacing-2xs);
}

.minisite-duo .evt-price__amount {
    font-size: var(--font-size-2xl);
}


/* ══════════════════════════════════════════════════════════════
   LES COMMANDES D'UNE PAGE, DANS LE RAIL
   ══════════════════════════════════════════════════════════════ */

/* Elles suivent la forme du menu : une liste verticale ou la cible fait toute
   la largeur du rail. Un choix de jour et un choix de page se prennent du meme
   geste, ils n'ont pas a se presenter differemment. */
.minisite-cmd__list {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.minisite-cmd__tab {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-sm);
    width: 100%;
    min-height: var(--touch-target-min);
    padding: var(--spacing-xs) var(--spacing-sm);
    margin-inline: calc(var(--spacing-sm) * -1);
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
    text-align: left;
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.minisite-cmd__tab:hover {
    background: var(--surface-4);
    color: var(--color-primary);
}

/* L'ETAT ACTIF SE MARQUE PAR SON FOND ET SON ENCRE, jamais par la seule
   couleur : `aria-selected` le dit aux technologies d'assistance, le contraste
   le dit a l'oeil. */
/* MARINE, comme l'entree de menu active juste au-dessus : deux listes de choix
   dans la meme colonne ne peuvent pas marquer leur selection de deux facons. */
.minisite-cmd__tab.is-active {
    background: var(--color-primary-dark);
    color: var(--color-on-primary);
}

.minisite-cmd__tab-label {
    min-width: 0;
}

/* La date se cale au bout, en chasse fixe : c'est une VALEUR. */
.minisite-cmd__tab-note {
    margin-left: auto;
    flex: none;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    font-weight: 400;
    color: var(--color-text-light);
}

.minisite-cmd__tab.is-active .minisite-cmd__tab-note {
    color: var(--color-on-navy-muted);
}

/* Le compteur ferme le bloc des types. Sans lui, une combinaison qui ne laisse
   rien passer rend une page vide sans un mot, et l'on croit le programme non
   publie. */
.minisite-cmd__count {
    margin: var(--spacing-sm) 0 0;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.minisite-cmd__actions {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.minisite-cmd__action {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    width: 100%;
    min-height: var(--touch-target-min);
    padding: var(--spacing-xs) var(--spacing-sm);
    margin-inline: calc(var(--spacing-sm) * -1);
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.minisite-cmd__action:hover,
.minisite-cmd__action.is-active {
    background: var(--surface-4);
    color: var(--color-primary);
}

.minisite-cmd__action svg {
    flex: none;
    color: var(--color-text-light);
}

.minisite-cmd__badge {
    margin-left: auto;
    min-width: 1.25rem;
    padding: 0 var(--spacing-xs);
    border-radius: var(--radius-pill);
    background: var(--color-section-colloques);
    font-family: var(--font-data);
    font-size: var(--font-size-2xs);
    line-height: 1.25rem;
    text-align: center;
    color: var(--color-on-primary);
}

/* L'impression n'a pas de sens au doigt : masquee sous le palier plutot que de
   disputer sa place aux commandes qui, elles, servent. */
@media (width < 64em) {
    .minisite-cmd__action--print {
        display: none;
    }
}

/* ── LES ETIQUETTES DE FACETTE, DANS UN RAIL DE 20 REM ──
   `.programme__facet` est une RANGEE : intitule a gauche, etiquettes a droite.
   Dans le rail, l'intitule prenait sa colonne et poussait les etiquettes contre
   le bord droit, en escalier. Il fait de surcroit doublon avec le titre du bloc
   (« TYPE » sous « TYPE DE SEANCE »).

   La rangee devient donc une COLONNE, et l'intitule du partiel disparait : le
   titre de bloc du rail le dit deja, et une seule facette est rendue ici. */
.minisite-cmd .programme__facet {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--spacing-sm);
}

.minisite-cmd .programme__facet-label {
    display: none;
}

.minisite-cmd .programme__chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: var(--spacing-xs);
}


/* ══════════════════════════════════════════════════════════════
   L'ACTION D'UNE PAGE, DANS LE RAIL
   ══════════════════════════════════════════════════════════════ */

/* Le bloc que pose la page d'inscription a la place du bouton generique :
   modalite reelle (plateforme externe, formulaire PDF, ou l'annonce d'une
   ouverture a venir), et ce qui aide a decider juste en dessous. */
.minisite-act__hint {
    margin: 0 0 var(--spacing-sm);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

/* La note qui SUIT le bouton n'a pas de marge basse : c'est le `gap` du rail
   qui separe les blocs. */
.minisite-act .minisite-cta__btn + .minisite-act__hint {
    margin: var(--spacing-sm) 0 0;
}

/* —— L'ACTION DANS LE CONTENU ——
   Meme partial que la carte d'appui, meme bouton, mais pas la meme largeur : le
   rail impose `width: 100%` parce qu'une colonne de 320 px n'a pas d'autre
   choix ; un contenu de 782 px, si. Le bouton y garde sa largeur naturelle et se
   cale a gauche, comme tous les appels a l'action du site. */
.minisite-act--content .minisite-act__cta {
    /* `align-self`, ET SURTOUT PAS `display`. La section est un conteneur
       FLEX (`minisite-section`), donc le `display: inline-flex` du bouton est
       BLOCKIFIE en `flex` par le navigateur, et `align-items: stretch` l'etire
       a toute la largeur. J'ai d'abord cru a un defaut de cascade et monte la
       specificite : sans effet, evidemment — les deux regles declaraient deja
       `inline-flex`, et le calcule rendait `flex`. Un ecart entre ce qu'on
       DECLARE et ce qui est CALCULE sur la meme propriete ne se resout jamais
       par la specificite.

       Mesure : 782 px avant, largeur du contenu du bouton apres. */
    align-self: flex-start;
}

.minisite-act--content .minisite-act__hint {
    margin: 0 0 var(--spacing-md);
    max-width: var(--measure-prose);
    color: var(--color-text);
}

.minisite-act__contacts {
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

/* ── L'ETAT, AU-DESSUS DU TITRE DE PAGE ──
   La pastille tient sa propre ligne : posee en ligne avec le titre, elle se
   lisait comme un mot de plus dans le titre. */
.minisite-head__state {
    margin: 0 0 var(--spacing-sm);
}

.minisite-head__state:empty {
    display: none;
}


/* ══════════════════════════════════════════════════════════════
   LA BANNIERE D'ENGAGEMENT
   Maquette `Minisite événement v2 ANCESU`, ecran 2a
   ══════════════════════════════════════════════════════════════ */

/* ── UNE CARTE QUI PART AU DEFILEMENT ──

   Elle a d'abord ete collee : c'etait juste tant qu'elle portait l'IDENTITE de
   l'evenement — « arrive sur Pratique, on ne savait plus de quelle journee il
   s'agissait ». L'identite est depuis descendue dans le rail, qui est colle lui
   aussi : la banniere ne portait plus que l'etat et le bouton, c'est-a-dire ce
   que le rail peut porter sans occuper une bande en haut de chaque ecran.

   Elle defile donc avec le contenu, et le RAIL reprend l'engagement. Ce qui
   change pour le lecteur : au bureau, rien — le rail est colle, le bouton reste
   sous les yeux. Sur telephone, ou le rail est empile, le bouton est en tete de
   page a l'arrivee et le pied en porte un second ; entre les deux il faut
   defiler, ce qui est le cas de toutes les pages du site.

   Ce qu'on gagne : 62 px d'ecran rendus au contenu sur toute la hauteur de la
   page, et un seul objet colle au lieu de deux qui se poussaient. */
/* ── L'ECART AU-DESSUS EST UN REMBOURRAGE, PAS UNE MARGE ──

   La banniere est le PREMIER element en flux du corps : une marge haute s'y
   fusionne avec celle du corps et deplace la page entiere au lieu de creuser un
   ecart au-dessus d'elle. Mesure du 2026-09-02 : `margin-top` declare a 8 px,
   banniere rendue a `top: 0`, collee au bord de la fenetre.

   Un rembourrage ne se fusionne jamais. Il vaut le meme pas que tout le reste
   de la pile — l'ecart sous la banniere, et celui entre deux cartes du rail. */
.event-banner {
    padding-top: var(--spacing-md);
}

.event-banner__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-ms) var(--spacing-md);
    padding: var(--spacing-sm) var(--spacing-ms);
    border-radius: var(--radius-md);
    background: var(--color-primary-dark);
    box-shadow: var(--shadow-md);
}

/* Les actions se calent a droite. `margin-left: auto` plutot qu'un separateur
   souple, qui n'aurait rien tenu une fois la rangee passee sur deux lignes. */
.event-banner__actions {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-left: auto;
    flex: none;
}

/* Sous le palier, les actions vivent DANS le panneau, en derniere rangee.

   PAS DE `space-between` ICI, et c'est mesure : la rangee n'a qu'UN enfant, le
   groupe de partage, donc la repartition ne repartit rien — elle se lit dans la
   feuille comme une intention qui n'a aucun effet. C'est le piege deja
   documente dans `design-system.md`, sur son cas le plus discret : l'ecart
   entre les deux pastilles vient du `gap` du groupe, pas d'ici. */
@media (width < 64em) {
    .event-banner__actions {
        margin-left: 0;
        width: 100%;
    }
}

/* ── LE RAIL COLLE PRES DU BORD, ET IL EST LE SEUL ──
   `article-sidebar__sticky` se colle a `top: 6rem`, valeur heritee du squelette
   de fiche du site : elle degageait la barre de navigation du site, que le
   minisite n'a pas.

   Le `top` doit rester INFERIEUR a la position naturelle du rail, sans quoi le
   rail descend des le premier rendu et ne s'aligne plus sur la carte de
   contenu. Mesure du 2026-09-02 : `top` a 96 px pour une position naturelle a
   78 — le rail demarrait 18 px plus bas que le contenu, a hauteur nulle de
   defilement. */
@media (width >= 64em) {
    .minisite-rail .article-sidebar__sticky {
        top: var(--spacing-md);
    }
}


/* ══════════════════════════════════════════════════════════════
   LA COUVERTURE DE L'ACCUEIL
   Maquette `Minisite événement v2 ANCESU`, ecran 2a
   ══════════════════════════════════════════════════════════════ */

/* L'AFFICHE AYANT PRIS LA PLEINE LARGEUR au-dessus du titre, la couverture n'a
   plus qu'une colonne : le texte. La grille a deux pistes rendait une banniere
   large sur 0,9 fraction — 300 px de haut contre 550 pour la colonne de texte,
   soit un vide sous l'image sur toute la hauteur restante. */
.minisite-cover {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xl);
}

.minisite-cover__text {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-ms);
    min-width: 0;
}

/* ── PLUS DE TITRE, DE SOUS-TITRE NI DE META DANS LA COUVERTURE ──
   Le type, le titre, le sous-titre, les dates et le lieu vivaient ici ET dans
   la carte d'identite du rail, a deux cents pixels d'ecart. Les quatre regles
   qui les habillaient partent avec eux : une regle sans element est une regle
   que personne ne peut mesurer, et qui survit a tous les nettoyages parce
   qu'elle n'a l'air de gener personne.

   Le `h1` reste, en `sr-only` : le titre est affiche graphiquement par
   l'affiche juste au-dessus. */
/* Le chapo etait a `--font-size-md`, soit 15 px : PLUS PETIT que le corps de
   texte a 16. Un chapo se lit comme une entree en matiere, il ne peut pas etre
   compose plus petit que ce qu'il introduit — c'est ce qui le faisait passer
   pour une legende sous l'affiche. `--font-size-lg` le remonte a 18. */
.minisite-cover__lead {
    margin: 0;
    max-width: var(--measure-prose);
    font-size: var(--font-size-lg);
    line-height: var(--line-height-loose);
    color: var(--color-text);
    text-wrap: pretty;
}

/* ── L'AFFICHE GARDE SON FORMAT, ET ELLE OUVRE LA CARTE ──
   La maquette la dessine en 4/3, sur un gabarit hachure portant « affiche de
   l'edition · 4/3 ». C'est un PLACEHOLDER, pas une promesse sur nos fichiers :
   l'affiche d'Angers est une banniere large, et un `object-fit: cover` dans une
   boite 4/3 la coupait en plein titre — mesure du 2026-09-02, « LUMIERE » perdu,
   il restait « E SUR LA PEDAGOGIE ».

   Recadrer une image qui porte du TEXTE detruit l'information qu'elle porte. Le
   ratio est donc laisse a l'image, et seule sa hauteur est bornee pour qu'une
   affiche portrait ne prenne pas l'ecran a elle seule.

   Elle n'a ni ombre ni filet : posee en tete de carte et sur toute sa largeur,
   elle EST le bord haut du contenu — une ombre y ferait flotter une carte dans
   une carte. Le rayon reprend celui de la carte pour que les deux angles
   coincident. */
.minisite-cover__figure {
    margin: 0;
}

.minisite-cover__poster {
    display: block;
    width: 100%;
    height: auto;
    max-height: 22rem;
    object-fit: contain;
    border-radius: var(--radius-md);
}

.minisite-cover__credit {
    display: block;
    margin-top: var(--spacing-xs);
    font-size: var(--font-size-2xs);
    color: var(--color-text-light);
}

/* ── LES REPERES, EN RANGEE SOUS LE CHAPO ──
   Ils qualifient ce que le titre vient d'annoncer. Pas de carte : une carte les
   mettrait au meme rang que le contenu qui suit. */
/* ── LES REPERES SE LISENT COMME UNE RANGEE DE DONNEES ──
   Ils etaient poses en `flex` a 4 px sous le chapo, separes par un simple
   espace : trois paires valeur/libelle qui flottaient sous un paragraphe, sans
   rien pour dire ou l'une finit et ou la suivante commence.

   La grille leur donne des colonnes egales et un filet superieur chacune. Le
   filet est ce qui les constitue en RANGEE — c'est la meme figure que celle des
   listes de faits, et elle dit « ces trois choses sont de meme nature » sans
   qu'on ait a l'ecrire.

   `auto-fit` sur 6 rem : les reperes tiennent sur une rangee des 390 px, et
   le nombre de colonnes suit la place sans palier declare. A 8 rem, mesure du
   2026-09-02, le troisieme tombait seul sur une deuxieme rangee et la laissait
   a moitie vide — des reperes se lisent d'un coup ou pas du tout.

   PAS DE `max-width: var(--measure-prose)` ICI, contrairement au chapo juste
   au-dessus. Le gabarit de prose borne un TEXTE, pour qu'on puisse le lire sans
   perdre sa ligne ; une rangee de donnees n'a pas ce probleme. Sur une edition
   passee les reperes sont CINQ, et la borne les cassait en 4 + 1 au bureau. */
.minisite-marks {
    list-style: none;
    margin: var(--spacing-lg) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
    gap: var(--spacing-md);
}

.minisite-marks__item {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    padding-top: var(--spacing-sm);
    border-top: 1px solid var(--color-border);
}

.minisite-marks__value {
    font-family: var(--font-data);
    font-size: var(--font-size-xl);
    font-weight: 500;
    line-height: 1;
    color: var(--color-primary-dark);
}

.minisite-marks__label {
    font-size: var(--font-size-xs);
    line-height: var(--line-height-tight);
    color: var(--color-text-light);
}


/* ══════════════════════════════════════════════════════════════
   QUI VOUS PARLERA
   ══════════════════════════════════════════════════════════════ */

/* `auto-fit` sur 14 rem : quatre fiches sur une rangee au bureau, deux sur une
   tablette, une sur un telephone — sans palier declare, donc sans saut a une
   largeur qu'on n'aurait pas prevue. */
.minisite-people {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
    gap: var(--spacing-ms);
}

.minisite-person {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    min-width: 0;
    padding: var(--spacing-md);
    border-radius: var(--radius-md);
    background: var(--surface-4);
}

/* Le portrait est DECORATIF : le nom est en texte juste en dessous. Sans photo,
   aucune image de remplacement n'est rendue — un aplat gris rond a la place
   d'un visage se lit comme un chargement qui a echoue. */
.minisite-person__photo {
    width: 4rem;
    height: 4rem;
    border-radius: var(--radius-pill);
    object-fit: cover;
}

.minisite-person__name {
    font-family: var(--font-title);
    font-size: var(--font-size-md);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.minisite-person__role {
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

/* La seance est ce qui relie la personne au programme : c'est la seule ligne de
   la fiche qui porte l'encre de lien, parce que c'est la seule qui repond a
   « quand est-ce que je l'entends ». */
.minisite-person__session {
    font-size: var(--font-size-sm);
    font-weight: 600;
    line-height: var(--line-height-base);
    color: var(--color-primary);
}


/* ══════════════════════════════════════════════════════════════
   LE PROGRAMME, A PLAT
   Maquette `Minisite événement v2 ANCESU`, ecran 2b
   ══════════════════════════════════════════════════════════════ */

/* Defaut n°5 : « chaque seance est une carte blanche qui contient une carte
   grise qui contient deux cartes bleues. Trois niveaux d'encadrement pour une
   ligne d'horaire et un titre. »

   ── POURQUOI DE NOUVEAUX NOMS DE CLASSE ──

   Le creneau, le groupe et le jour gardent leurs `data-*` — c'est ce que le
   moteur de filtrage d'`app.js` lit, et les retirer casserait les facettes —
   mais ils changent de CLASSE. Les anciennes (`programme__slot`,
   `programme__group`, `programme__day`) portent 112 regles dans `events.css`,
   ecrites pour la mise en page a cartes gigognes qui disparait ici.

   Ce n'est pas de la cosmetique : `.programme__slot` y declare
   `align-items: baseline`, ce qui, sur un conteneur en colonne, empeche
   l'etirement en LARGEUR. Mesure du 2026-09-02 : les lignes rendaient 314, 403
   et 638 px au lieu de 782, chacune s'arretant a la fin de son titre. Le defaut
   ne venait pas de ma feuille mais de l'ancienne, qui habillait encore un nom
   que j'avais reemploye. */
.programme-days,
.programme-day__slots,
.programme-slot,
.programme-group {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    /* EXPLICITE, et pas seulement par defaut : c'est la declaration qui a
       manque. Un conteneur en colonne dont les enfants ne s'etirent pas rend
       des lignes de largeurs inegales, ce qui se lit comme un defaut de grille
       et se cherche dans la grille. */
    align-items: stretch;
}

.programme-days {
    gap: var(--rhythm-section);
}

.programme-day__slots {
    gap: var(--spacing-sm);
    margin-top: var(--spacing-md);
}

.programme-slot,
.programme-group {
    gap: var(--spacing-sm);
}

.programme-day__head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--spacing-sm) var(--spacing-md);
}

.programme-day__title {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-2xl);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.programme-day__date {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* ── LA LIGNE ──
   Trois colonnes : quand, quoi, ou et le geste. La colonne d'heure a une
   largeur FIXE — c'est elle qui donne au deroule sa reglure verticale, et une
   colonne qui s'ajuste au contenu la briserait a chaque seance sans duree. */
.programme-line {
    display: grid;
    grid-template-columns: 5rem minmax(0, 1fr) auto;
    gap: var(--spacing-md) var(--spacing-lg);

    /* LIGNE DE BASE, ET NON BORD HAUT. L'heure est en 14 px de chasse fixe, le
       sur-titre de la ligne en 11 px de capitales : cales par le HAUT de leur
       boite, leurs textes ne partagent aucune ligne, et l'heure flotte au-dessus
       du type. `baseline` aligne les PREMIERES lignes de base des trois
       colonnes, ce qui est la seule chose que l'oeil compare ici.

       `start` n'etait pas fautif tant que la colonne d'heure portait DEUX
       lignes — l'heure et la duree — et formait un bloc de hauteur voisine. La
       duree retiree, il ne reste qu'une ligne, et le decalage se voit. */
    align-items: baseline;
    padding: var(--spacing-ms) var(--spacing-md);
    border-radius: var(--radius-md);
    background: var(--surface-4);
    transition: background var(--transition-fast);
}

/* Une seance de LOGISTIQUE ou de vie sociale — accueil, pause, diner — ne se
   choisit pas : elle a lieu. Sans surface, elle ponctue le deroule au lieu d'y
   peser autant qu'une conference. */
.programme-line--fixed {
    background: none;
    padding-block: var(--spacing-sm);
}

.programme-line--fixed .programme-line__title {
    font-family: var(--font-sans);
    font-size: var(--font-size-base);
    font-weight: 400;
    color: var(--color-text-light);
}

/* LA SEANCE RETENUE SE MARQUE PAR SON FOND ET PAR SON BOUTON, jamais par la
   seule couleur : `aria-pressed` le dit aux technologies d'assistance. */
.programme-line.is-picked {
    background: var(--color-primary-light);
}

.programme-line__when {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

/* Chasse fixe : une heure est une VALEUR, et c'est elle qui aligne la colonne.
   L'heure du CRENEAU partage cette regle plutot que d'en redeclarer une : c'est
   la meme grandeur au meme rang, et deux declarations auraient diverge au
   premier reglage. */
.programme-slot__time,
.programme-line__time {
    font-family: var(--font-data);
    font-size: var(--font-size-sm);
    font-weight: 500;
    line-height: var(--line-height-tight);
    color: var(--color-primary);
}


.programme-line__body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    min-width: 0;
}

.programme-line__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

/* Le type est NOMME et non reduit a une couleur : une pastille seule
   n'apprend rien a qui ne distingue pas les teintes. */
.programme-line__type {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--color-text-light);
}

/* La couleur vient du type de seance, saisie en administration ; le repli est
   la teinte de rubrique, jamais une valeur en dur. */
.programme-line__dot {
    flex: none;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--type-color, var(--section-color));
}

/* « 1 des 6 » remplace le pave « au choix parmi 6 » qui coiffait six cartes :
   la contrainte se lit sur chaque ligne qu'elle concerne. */
.programme-line__choice {
    font-family: var(--font-data);
    font-size: var(--font-size-2xs);
    color: var(--color-text-light);
}

.programme-line__title {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-lg);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
    text-wrap: pretty;
}

/* ── UN TITRE QUI MENE A SA COMMUNICATION LE DIT ──
   Le titre est un LIEN quand la seance a une page de communication, et rien ne
   le disait : `text-decoration: none` au repos, souligne au survol seulement.
   Mesure du 2026-09-03 sur l'edition de Nice — 53 titres sur 66 sont des liens,
   et aucun ne se distinguait des treize autres. La seule difference etait la
   couleur, qui dit la CATEGORIE de la seance (une conference contre une pause),
   pas sa cliquabilite.

   Le souligne au repos, comme les noms d'intervenants de la meme ligne : c'est
   la convention de la page, et elle repond a la question « existe-t-il une
   communication pour cette seance » sans ajouter une pastille sur cinquante-
   trois lignes.

   Meme trait et meme decalage que ces noms, pour que les deux se lisent comme
   des liens du meme rang. */
.programme-line__title a,
.programme-line__child-title a {
    color: inherit;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--color-border);
    text-underline-offset: 3px;
    transition: text-decoration-color var(--transition-fast);
}

.programme-line__title a:hover,
.programme-line__child-title a:hover {
    text-decoration-color: currentcolor;
}

.programme-line__code {
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    font-weight: 500;
    color: var(--color-text-light);
}

.programme-line__desc {
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

.programme-line__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
}

.programme-line__end {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--spacing-sm);
    flex: none;
}

/* Chasse fixe : un nom de salle est une VALEUR qu'on releve pour s'y rendre. */
.programme-line__room {
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
    white-space: nowrap;
}

.programme-line__pick {
    display: flex;
    align-items: center;
    min-height: var(--touch-target-min);
    padding: 0 var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-primary);
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.programme-line__pick:hover {
    border-color: var(--color-primary);
}

.programme-line__pick.is-picked {
    background: var(--color-primary-dark);
    border-color: var(--color-primary-dark);
    color: var(--color-on-primary);
}

/* Les interventions d'une session : une liste a filets, sans surface propre.
   Ce ne sont pas des cartes gigognes mais un rattachement, et l'aplatir au meme
   rang que la seance parente le perdrait. */
/* ── CE QUI EST DEDANS SE SERRE, CE QUI EST A COTE S'ECARTE ──
   Mesure du 2026-09-03 : huit pixels PARTOUT — entre le titre d'une
   intervention et ses intervenants, et entre deux interventions. Rien ne disait
   donc a quel titre un nom se rattachait, et l'oeil pouvait le lire comme
   appartenant a la ligne suivante. C'est le cas le plus voyant sur une pleniere
   a trois interventions, ou trois titres et trois noms alternent au meme pas.

   La liste ecarte ses entrees d'un cran de plus, et chaque entree serre son
   titre contre ses intervenants. C'est le rapport qui porte le sens, pas les
   valeurs : deux ecarts egaux ne peuvent rien dire, quels qu'ils soient. */
.programme-line__children {
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--spacing-md);
    border-left: 2px solid var(--color-border);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

.programme-line__child {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

/* Les marges des blocs internes s'ajouteraient au `gap` ci-dessus, et le
   rapport qu'il installe serait perdu — le defaut de double propriete corrige
   quatre fois ailleurs dans cette feuille. */
.programme-line__child > * {
    margin: 0;
}

/* ── LA MARQUE DE REDIFFUSION SUIT LE TITRE ──
   Elle porte `margin: 0.5rem 0 0` pour son emploi en bloc, dans la coquille
   historique. Dans la continuite du libelle, cette marge la decalerait vers le
   bas d'une demi-ligne.

   L'INTERLIGNE EST RAMENE A 1. La pastille est deja centree — icone, libelle et
   boite partagent leur centre au pixel, mesure — mais son libelle porte un
   interligne de 1,3 : la boite du texte depasse le glyphe en haut et en bas, et
   l'oeil lit ce blanc comme un decalage. Un centrage juste peut paraitre faux
   quand ce qu'on centre est plus haut que ce qu'on voit. Le corps descend d'un
   cran, la pastille cessant d'etre un objet a lire pour devenir une marque. */
.programme-line__title .programme__session-filmed {
    margin: 0 0 0 var(--spacing-sm);
    padding-block: var(--spacing-2xs);
    font-size: var(--font-size-2xs);
    line-height: 1;
    vertical-align: middle;
}

/* ── LES INTERVENANTS TIENNENT AU TITRE, ICI AUSSI ──
   Seize pixels entre le titre d'une conference et son intervenant, la ou le
   corps declare huit : la marge haute du bloc d'intervenants s'ajoutait au
   `gap`. C'est le SIXIEME endroit ou ce doublement se produit dans cette
   feuille, et le troisieme aujourd'hui.

   Les marges des blocs du corps sont donc neutralisees en bloc, comme elles
   l'ont ete pour les sous-seances : dans un conteneur a `gap`, un enfant ne
   declare pas son ecart. */
.programme-line__body > * {
    margin: 0;
}

.programme-line__child-title {
    display: block;
    font-size: var(--font-size-base);
    font-weight: 600;
    line-height: var(--line-height-base);
    color: var(--color-text);
}

.programme-line__child-title a {
    color: inherit;
}

/* La regle du jeu, sous le deroule : sans elle, un bouton « Ajouter » qui en
   desactive un autre passe pour un defaut. */
.programme-days__rule {
    margin: 0;
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--color-border);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

/* Sur telephone, la ligne se replie en colonne : trois pistes dans 326 px
   donnaient 5 rem d'heure, une piste de titre de 120 px et un bouton coupe. */
@media (width < 48em) {
    .programme-line {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--spacing-sm);
    }

    .programme-line__when {
        flex-direction: row;
        align-items: baseline;
        gap: var(--spacing-sm);
    }

    .programme-line__end {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        width: 100%;
    }
}


/* ── MON PROGRAMME, DANS LE RAIL ── */

/* Chasse fixe et gros corps : c'est un COMPTE, et c'est le seul retour qu'ait
   le visiteur sur un geste qui, sur la ligne, ne change qu'un fond. */
.minisite-pick__count {
    display: flex;
    align-items: baseline;
    gap: var(--spacing-xs);
    margin: 0 0 var(--spacing-xs);
    font-family: var(--font-data);
    font-size: var(--font-size-lg);
    font-weight: 500;
    line-height: 1;
    color: var(--color-primary-dark);
}

.minisite-pick__count span + span {
    font-family: var(--font-sans);
    font-size: var(--font-size-sm);
    font-weight: 400;
    color: var(--color-text-light);
}

.minisite-pick__hint {
    margin: 0;
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}


/* ── LE MASQUAGE DES FACETTES SUIT LE SCRIPT, PAS LES CLASSES ──

   `applyFilters` d'`app.js` pose `is-filter-hidden` sur `[data-session]`,
   `[data-group]`, `[data-slot]` et `[data-day]`. La regle qui MASQUE vivait
   dans `events.css`, accrochee aux anciens noms de classe
   (`.programme__session.is-filter-hidden`, …). Renommer les conteneurs l'aurait
   donc rendue inerte EN SILENCE : le script aurait continue de poser la classe,
   et plus rien n'aurait disparu — un filtre qui ne filtre pas, sans erreur ni
   journal.

   La regle est donc ancree sur les MEMES attributs que le script vise. Un
   renommage de classe ne peut plus la desaccorder ; seul un changement de
   `data-*` le pourrait, et il casserait le script au meme endroit, donc
   visiblement. */
.programme-days [data-session].is-filter-hidden,
.programme-days [data-group].is-filter-hidden,
.programme-days [data-slot].is-filter-hidden,
.programme-days[data-day].is-filter-hidden,
.programme-days [data-day].is-filter-hidden,
.programme-days [data-parallel-note].is-filter-hidden {
    display: none;
}

/* —— `hidden` DOIT VRAIMENT CACHER ——
   L'attribut ne tient que par une regle d'agent utilisateur, de specificite
   nulle : n'importe quel `display` ecrit dans une feuille la bat. Or les deux
   surfaces que le module vanilla replie en portent un — le panneau est
   `display: flex`, le tiroir `display: block`. Sans cette regle, `hidden` est
   pose, l'attribut est bien dans le DOM, et RIEN ne se cache : le panneau de
   filtres s'ouvrirait des le chargement et ne se refermerait jamais.

   Le defaut serait de ceux qui ne se signalent pas : le script ferait
   exactement ce qu'on lui demande, l'inspecteur montrerait `hidden`, et l'ecran
   dirait le contraire. C'est pourquoi la regle est posee EN MEME TEMPS que la
   bascule, et non le jour ou l'on constate qu'elle manque.

   Bornee au minisite : `[hidden]` avec `!important` a l'echelle du site
   retirerait a toute autre surface la possibilite de rendre un element cache
   autrement, ce qui n'est pas a decider ici. */
body.minisite [hidden] {
    display: none !important;
}


/* ══════════════════════════════════════════════════════════════
   LES TARIFS
   Maquette `Minisite sections ANCESU`, section Inscription
   ══════════════════════════════════════════════════════════════ */

.minisite-tiers {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
    gap: var(--spacing-ms);
    align-items: start;
}

.minisite-tier {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    min-width: 0;
    padding: var(--spacing-lg);
    border-radius: var(--radius-md);
    background: var(--surface-4);
}

/* Le PREMIER palier sur aplat marine. Il n'est pas « meilleur » : il est celui
   qui concerne les adherents, donc la majorite des visiteurs de ce minisite. */
.minisite-tier--lead {
    background: var(--color-primary-dark);
}

.minisite-tier__category {
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--color-text-light);
}

/* Le vert de marque rend 2,4:1 sur ce marine. Sur aplat, le sur-titre prend
   donc l'encre claire du fond plutot que la teinte de rubrique. */
.minisite-tier--lead .minisite-tier__category {
    color: var(--color-on-navy-muted);
}

/* Chasse fixe et grand corps : c'est LA valeur de la carte. */
.minisite-tier__price {
    font-family: var(--font-data);
    font-size: var(--font-size-3xl);
    font-weight: 500;
    letter-spacing: -0.02em;
    line-height: 1;
    color: var(--color-primary-dark);
}

.minisite-tier--lead .minisite-tier__price {
    color: var(--color-on-primary);
}

.minisite-tier__note {
    font-size: var(--font-size-sm);
    line-height: var(--line-height-tight);
    color: var(--color-text-light);
}

.minisite-tier--lead .minisite-tier__note {
    color: var(--color-on-navy-muted);
}

/* Le prix d'apres, sous un filet : c'est une autre echeance, pas une precision
   sur celle du dessus. */
.minisite-tier__after {
    padding-top: var(--spacing-sm);
    border-top: 1px solid var(--color-border);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-primary-dark);
}

.minisite-tier--lead .minisite-tier__after {
    border-top-color: var(--veil-on-dark);
    color: var(--color-on-primary);
}


/* ══════════════════════════════════════════════════════════════
   LES INTERVENANTS, EN LISTE
   Maquette `Minisite sections ANCESU`, section Intervenants
   ══════════════════════════════════════════════════════════════ */

/* Le MUR de cartes 3/4 devient une LISTE. Ce n'est pas un changement de gout :
   la carte disait « 3 interventions » sans dire lesquelles ni quand, et c'est
   precisement ce qu'on vient chercher ici. La ligne porte le quand et la
   seance, et elle y mene. */
.minisite-speakers {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.minisite-speaker {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--spacing-md);
    align-items: center;
    padding: var(--spacing-ms) var(--spacing-md);
    border-radius: var(--radius-md);
    background: var(--surface-4);
}

/* Le portrait est DECORATIF : le nom est en texte juste a cote. Sans photo,
   aucun aplat de remplacement — un rond gris a la place d'un visage se lit
   comme un chargement qui a echoue, et l'absence est ici le cas ordinaire :
   un intervenant sur quatre porte une photo. */
.minisite-speaker__photo {
    width: 3.5rem;
    height: 3.5rem;
    flex: none;
    border-radius: var(--radius-pill);
    object-fit: cover;
}

/* ── LA BULLE GENERIQUE ──
   Elle occupe EXACTEMENT la place d'une photo : c'est sa raison d'etre. Trois
   intervenants sur quatre n'en ont pas, et sans elle leur nom demarrait 68 px a
   gauche de celui des autres — la colonne ondulait sur toute la longueur de la
   liste.

   Une silhouette, et non un aplat vide : un rond gris se lit comme un
   chargement qui a echoue, une silhouette dit « une personne, sans photo ». */
.minisite-speaker__photo--generic,
.minisite-person__photo--generic {
    display: flex;
    align-items: center;
    justify-content: center;

    /* LE CERNE EST CE QUI EN FAIT UNE BULLE. Sans lui, `--surface-4` vaut le
       fond de la ligne : la silhouette flottait dans le vide, et l'objet ne se
       lisait plus comme un avatar mais comme un pictogramme egare. Mesure du
       2026-09-03 : fond de la bulle et fond de la ligne a la meme valeur. */
    border: 1px solid var(--color-border);
    background: var(--color-bg);
    color: var(--color-text-light);
}

.minisite-speaker__identity {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
}

.minisite-speaker__name {
    font-family: var(--font-title);
    font-size: var(--font-size-md);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.minisite-speaker__name a {
    color: inherit;
    text-decoration: none;
}

.minisite-speaker__name a:hover {
    text-decoration: underline;
}

.minisite-speaker__org {
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

.minisite-speaker__roles {
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--color-text-light);
}

/* La colonne de droite porte le RATTACHEMENT : quand, et a quelle seance.
   Alignee a droite, elle forme une seconde reglure verticale qui se parcourt
   seule — c'est par elle qu'on cherche « qui parle jeudi matin ». */
.minisite-speaker__when {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--spacing-2xs);
    text-align: right;
    flex: none;
    max-width: 16rem;
}

/* Chasse fixe : une date et une heure sont des VALEURS. */
.minisite-speaker__slot {
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
    white-space: nowrap;
}

.minisite-speaker__session {
    font-size: var(--font-size-sm);
    font-weight: 600;
    line-height: var(--line-height-tight);
}

.minisite-speaker__more {
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

/* Les pastilles de facette dans un rail de 20 rem : elles passent a la ligne
   au lieu de defiler, ce qu'une rangee pleine largeur leur imposait. */
.minisite-facets {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
}

.minisite-facets .article-sidebar__section-title {
    flex: 1 0 100%;
}

/* Sur telephone, la ligne se replie : trois pistes dans 326 px laissaient au
   titre de seance une colonne de quatre-vingts pixels. */
@media (width < 48em) {
    .minisite-speaker {
        grid-template-columns: auto minmax(0, 1fr);
        align-items: start;
    }

    .minisite-speaker__when {
        grid-column: 1 / -1;
        align-items: flex-start;
        text-align: left;
        max-width: none;
        padding-top: var(--spacing-xs);
        border-top: 1px solid var(--color-border);
        width: 100%;
    }
}


/* ══════════════════════════════════════════════════════════════
   LES COMMANDES D'UNE LISTE, DANS LE FIL DE LA PAGE
   ══════════════════════════════════════════════════════════════ */

/* AUCUNE SURFACE, ET C'EST LE POINT. Ces commandes ont vecu dans une carte
   grise posee entre le titre de la page et la premiere vignette : une carte est
   un objet, et elle les mettait au meme rang que ce qu'elles filtrent. Elles
   sont dans une `.minisite-section`, donc separees de la presentation par le
   filet du rythme de carte et de la liste par le suivant — c'est ce filet qui
   les delimite, pas un fond.

   L'ecart interne est plus serre que celui d'une section ordinaire : une rangee
   de controles et ses pastilles sont UNE chose, pas trois blocs successifs. */
.minisite-filters {
    gap: var(--spacing-sm);
}

.minisite-filters__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-sm) var(--spacing-md);
}

/* Le champ de recherche prend la place qu'il lui faut et pas davantage : a
   pleine largeur, une saisie de deux mots s'etirait sur 848 px. Il reste
   PREMIER et le plus large des deux controles — c'est le geste le plus
   frequent. */
.minisite-filters__search {
    flex: 1 1 18rem;
    max-width: 26rem;
    min-width: 0;
}

.minisite-filters__field {
    flex: 1 1 14rem;
    max-width: 20rem;
    min-width: 0;
}

/* `margin-left: auto` et non `space-between` : quand le lien est seul sur sa
   ligne, `space-between` le laisserait au depart. */
.minisite-filters__clear {
    flex: none;
    margin-left: auto;
    font-size: var(--font-size-sm);
    color: var(--color-primary);
}

/* Une ligne de pastilles precedee de son axe. Un `<p>` et non une liste : ce
   sont des LIENS vers une liste filtree, et leur intitule se lit dans la meme
   ligne qu'eux. */
.minisite-filters__group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs);
    margin: 0;
}

.minisite-filters__label {
    flex: none;
    margin-right: var(--spacing-2xs);
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--color-text-light);
}


/* ── L'EN-TETE D'UN GROUPE, DANS LA CARTE ──
   Rendu par `event/minisite/_group_head.html.twig`.

   Leger, parce qu'un groupe n'est pas une section : le groupement par lettre du
   mur d'intervenants produit une vingtaine de groupes pour trente-trois
   personnes, dont plusieurs d'un seul membre, et un en-tete de SECTION complet
   y coute plus de hauteur que les lignes qu'il coiffe.

   IL ETAIT DESSINE DEUX FOIS : `minisite-speakers__group-label` ici, et
   `evt-replays__group-head` dans `events.css` — la feuille v1 — pour la page
   des rediffusions, avec un filet en `<span>` plutot qu'en pseudo-element, un
   corps plus gros et un ecart de moitie. Deux dessins du meme objet dans la
   meme carte, sur deux onglets voisins. */
.minisite-group {
    gap: var(--spacing-sm);
}

/* ── LA RANGEE NE PASSE PAS A LA LIGNE ──
   Elle le faisait, et sur un intitule long le compte tombait au DEPART de la
   seconde ligne, sous le titre : un « 1 vidéo » orphelin, la ou il qualifie le
   groupe depuis la droite partout ailleurs. La marge automatique le poussait
   bien a droite, mais il restait sur une ligne a lui, sous un titre qui ne
   l'annoncait pas. Mesure du 2026-09-03 sur `/evenements/2025-nice/replays`,
   deuxieme groupe — un titre de seance de quatre-vingt-dix signes.

   En `nowrap`, c'est le TITRE qui se replie dans sa propre colonne (`min-width:
   0`), et le filet se resorbe jusqu'a son minimum. Le repere et le compte
   restent aux deux bords, quelle que soit la longueur.

   Sous 48 em, le repli revient : trois pistes plus un compte dans 326 px ne
   laisseraient au titre qu'une colonne de quelques dizaines de pixels. */
.minisite-group__label {
    display: flex;
    flex-wrap: nowrap;
    align-items: baseline;
    gap: var(--spacing-sm);
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-base);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

/* CE QUI SITUE LE GROUPE, avant son nom : « Jour 1 · 13:45 ». En chasse fixe,
   comme partout ou le minisite donne une donnee, et en poids normal — c'est le
   nom de la seance qu'on parcourt, pas son horaire. */
.minisite-group__meta {
    flex: none;
    order: -1;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    font-weight: 400;
    color: var(--color-primary);
}

/* `min-width: 0` : sans lui, un titre de seance long pousse la ligne et le
   filet disparait au lieu de se resorber. `flex: 0 1 auto` le laisse RETRECIR
   sous sa largeur intrinseque — c'est ce qui lui fait prendre plusieurs lignes
   plutot que de chasser le compte hors de la rangee. */
.minisite-group__name {
    flex: 0 1 auto;
    min-width: 0;
}

@media (width < 48em) {
    .minisite-group__label {
        flex-wrap: wrap;
    }
}

/* Le trait remplit la ligne apres l'intitule : c'est ce qui fait lire une
   SEPARATION plutot qu'un titre de plus dans la colonne.

   `min-width` non nul : a zero, un intitule qui remplit la rangee le reduit a
   rien et la ligne parait tronquee plutot que terminee. */
/* LE FILET SE CALE SUR LA LIGNE DE BASE, comme le reste de la rangee : il
   prolonge le titre au lieu de flotter a mi-hauteur. Un pseudo-element vide
   n'ayant pas de ligne de base propre, c'est son bord inferieur qui sert — donc
   exactement la ligne d'ecriture. */
.minisite-group__label::after {
    content: '';
    align-self: baseline;
    flex: 1;
    min-width: var(--spacing-lg);
    height: 1px;
    background: var(--color-border);
}

/* `margin-left: auto` EN PLUS du filet qui pousse : sur un intitule long, la
   rangee passe a la ligne et le compte tombe au DEPART de la seconde — un
   « 1 vidéo » orphelin sous le titre, la ou il qualifie le groupe depuis la
   droite partout ailleurs. Le filet ne le pousse que sur sa propre ligne.
   Mesure du 2026-09-03 sur `/evenements/2025-nice/replays`, deuxieme groupe. */
.minisite-group__count {
    order: 1;
    flex: none;
    margin-left: auto;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    font-weight: 400;
    color: var(--color-text-light);
}

/* La separation par filet du rythme de carte ferait double emploi avec le trait
   de l'en-tete de groupe. */
.minisite-group + .minisite-group {
    padding-top: 0;
    border-top: 0;
}


/* ══════════════════════════════════════════════════════════════
   LES APPELS A CONTRIBUTION
   Maquette `Minisite sections ANCESU`, section Contributions
   ══════════════════════════════════════════════════════════════ */

.minisite-call {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--spacing-ms);
    min-width: 0;
    padding: var(--spacing-lg);
    border-radius: var(--radius-md);
    background: var(--surface-4);
}

/* Un appel clos garde sa carte et sa sortie : le reglement et le sujet gardent
   leur interet. Il perd seulement son fond, qui le mettait au meme rang qu'un
   appel ou l'on peut encore deposer. */
.minisite-call--closed {
    background: none;
    border: 1px solid var(--color-border);
}

.minisite-call__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    width: 100%;
}

.minisite-call__type {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--color-text-light);
}

.minisite-call__dot {
    width: 0.5625rem;
    height: 0.5625rem;
    border-radius: var(--radius-pill);
    background: var(--color-section-formations);
}

.minisite-call--closed .minisite-call__dot {
    background: var(--color-text-disabled);
}

.minisite-call__title {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-xl);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
    text-wrap: pretty;
}

.minisite-call__text {
    margin: 0;
    font-size: var(--font-size-base);
    line-height: var(--line-height-loose);
    color: var(--color-text);
}

/* Chasse fixe : une echeance et un quota sont des VALEURS qu'on releve pour
   decider s'il reste le temps de proposer quelque chose. */
.minisite-call__facts {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    /* PAS `--font-data` : la fonte de donnees est celle des NOMBRES et des
       valeurs qu'on releve — un montant, un compte, un code. Ces trois lignes
       sont des phrases (« Depot du 1 mars 2026 au 1 novembre 2026 »,
       « Reglement sur la fiche de l'appel »), et en chasse fixe elles se
       lisaient comme une sortie de terminal au milieu d'une carte. */
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

.minisite-call__note {
    margin: 0;
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}


/* ── LES DEUX COMMANDES DE LA BANNIERE, SUR APLAT MARINE ──

   `_share_buttons` en variante `dropdown` rend deux pilules BLANCHES a filet
   gris : c'est sa forme sur le plateau clair du site, et elle est juste la-bas.
   Posees sur le marine de la banniere, elles y font deux cartes claires
   flottantes, plus voyantes que le bouton rouge qu'elles cotoient — alors
   qu'elles sont des commandes de second rang.

   Elles perdent donc leur surface et leur filet : encre claire, fond
   transparent, et un voile au survol. Le seul objet plein de la banniere reste
   celui qui porte l'action. */
.event-banner__share .share-dropdown-group__btn,
.event-banner__share .share-dropdown__summary {
    background: transparent;
    border-color: var(--veil-on-dark);
    color: var(--color-on-navy);
}

.event-banner__share .share-dropdown-group__btn:hover,
.event-banner__share .share-dropdown-group__btn:focus-visible,
.event-banner__share .share-dropdown__summary:hover,
.event-banner__share .share-dropdown__summary:focus-visible {
    background: var(--veil-on-dark);
    border-color: var(--color-on-navy-muted);
    color: var(--color-on-primary);
}

/* L'etat « range » garde son signal, mais dans l'encre du fond sombre. */
.event-banner__share .share-dropdown-group__btn--active {
    background: var(--veil-on-dark);
    color: var(--color-on-primary);
}

/* Le MENU deroulant, lui, retombe sur une surface claire : il s'ouvre SUR LE
   CONTENU et non sur le marine. L'habiller en sombre le rendrait illisible des
   qu'il depasse la banniere. */
.event-banner__share .share-dropdown__menu {
    color: var(--color-text);
}


/* ── L'ACTION DE L'ENGAGEMENT EST UN APLAT ROUGE ──

   `_rail_card` rend son action en `btn--outline-dark`, un contour marine, et
   c'est juste pour un rebond de colonne : la carte accompagne un contenu sans
   lui disputer l'attention.

   UNE SEULE deroge, et c'est celle-la : s'inscrire est le seul geste que ce
   site attend d'un visiteur d'evenement, et la maquette la peint en aplat
   rouge. La derogation est portee par une classe de l'APPELANT
   (`minisite-act--open`), pas par une variante ajoutee a la brique : une brique
   partagee qui gagne une option pour un seul appelant finit par en porter dix.

   Le rouge reste donc l'unique aplat de couleur de la page. */
.minisite-act--open .rail-card__cta {
    background: var(--color-section-colloques);
    border-color: var(--color-section-colloques);
    color: var(--color-on-primary);
}

.minisite-act--open .rail-card__cta:hover,
.minisite-act--open .rail-card__cta:focus-visible {
    background: color-mix(in srgb, var(--color-section-colloques) 86%, var(--color-shade));
    border-color: color-mix(in srgb, var(--color-section-colloques) 86%, var(--color-shade));
    color: var(--color-on-primary);
}


/* ══════════════════════════════════════════════════════════════
   LE FIL D'ARIANE, SUR LE MARINE DE LA BANNIERE
   ══════════════════════════════════════════════════════════════ */

/* Le composant est ecrit pour la bande claire du site : ses maillons sont en
   `--color-primary` et son maillon actif en `--color-primary-dark`. Sur le
   marine de la banniere, les deux disparaissent — le second EST le fond.

   Les encres passent donc a celles que la grammaire designe pour le marine.
   Mesure du 2026-09-02 : `--color-on-navy` rend 10,31:1 sur ce fond,
   `--color-on-navy-muted` 6,22 — les deux au-dessus du seuil AA, pour un
   composant qui rendait 1:1 sans cette reprise. */
.event-banner .breadcrumb-bar {
    min-width: 0;
    flex: 1 1 auto;
}

/* Le composant pose `padding-block: var(--spacing-md) 0` sur sa liste, pour la
   bande du site ou il vit seul. Dans la banniere il partage sa rangee avec les
   actions : le rembourrage l'y decalerait vers le bas. */
.event-banner .breadcrumb__list {
    padding-block: 0;
}

.event-banner .breadcrumb__item {
    color: var(--color-on-navy-muted);
}

.event-banner .breadcrumb__item a {
    color: var(--color-on-navy);
}

.event-banner .breadcrumb__item a:hover {
    color: var(--color-on-primary);
}

.event-banner .breadcrumb__item--active {
    color: var(--color-on-primary);
    /* ── LE MAILLON COURANT SE BORNE, IL NE PREND PAS LA BANDE ──
       `app.css` lui donne deja l'ecretage, et il se declenchait — mais seulement
       quand la place manquait. Mesure du 2026-09-03 sur la fiche d'une
       communication : 541 px de titre a 1280 px comme a 1600, soit un chemin
       dont le dernier maillon pese plus que les trois premiers reunis et court
       jusqu'au bord de la banniere.

       Le fil d'Ariane sert a SE SITUER, pas a relire : le titre entier est juste
       en dessous, en grand, et il reste dans le DOM ici — donc lu par un lecteur
       d'ecran et affiche en infobulle au survol.

       LA BORNE EST 16 REM, ET ELLE A ETE MESUREE PLUTOT QUE CHOISIE. Les cinq
       maillons rendent, a 1440 px : 101 + 82 + 146 + 79 px pour les quatre
       premiers, dans une bande de 1 192. A 26 rem, le dernier en pesait 416 a
       lui seul — plus que les quatre autres reunis, et le chemin occupait les
       trois quarts de la bande. A 16 rem il en occupe 62 %, et les quatre
       maillons parcourables restent entiers : ce sont eux qui servent a
       remonter. */
    max-width: min(100%, 16rem);
}

/* ── GARDE-FOU SUR LES MAILLONS PARCOURABLES ──
   Ils sont `flex-shrink: 0` (app.css) : ce sont des rubriques courtes, et les
   tronquer ferait perdre le chemin. Le troisieme fait exception — il porte le
   TITRE DE L'EVENEMENT, saisi en administration, donc de longueur inconnue.
   « Réflexivité - Nice - 2025 » tient en 146 px ; rien ne garantit le suivant,
   et un maillon inextensible de 400 px pousserait la bande sur deux lignes sans
   qu'aucune ellipse ne se declenche.

   La borne ne coupe donc RIEN aujourd'hui : c'est un plafond, pas un
   raccourcissement. `min-width: 0` est indispensable — sans lui un element de
   flex ne descend pas sous la largeur de son contenu, et `text-overflow` ne
   coupe rien. */
.event-banner .breadcrumb__item > a {
    display: block;
    min-width: 0;
    max-width: min(100%, 14rem);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* ── LE SEPARATEUR PRECEDE SON MAILLON, IL NE SUIT PAS LE PRECEDENT ──
   `app.css` le pose en `::after` du maillon precedent, ce qui est juste tant
   que le chemin tient sur une ligne. Des qu'il se replie — le cas normal ici,
   le troisieme maillon portant un titre d'evenement — le chevron reste ORPHELIN
   en fin de premiere rangee, et la seconde s'ouvre sans rien qui la rattache.
   Mesure du 2026-09-02 a 375 px : « ancesu.localhost › Evenements › » puis, a
   la ligne, le titre.

   En `::before` du maillon SUIVANT, le chevron descend avec lui : la rangee se
   termine sur un mot et la suivante s'ouvre sur le signe qui l'annonce. */
.event-banner .breadcrumb__item:not(:last-child)::after {
    content: none;
}

.event-banner .breadcrumb__item:not(:first-child)::before {
    content: '›';
    color: var(--color-on-navy-muted);
    font-size: 0.875rem;
    line-height: 1;
}

/* ── IL RESTE VISIBLE SUR TELEPHONE ──
   `app.css` masque `.breadcrumb-bar` sous 48 em pour toutes les pages du site :
   sur une bande dediee, un chemin de quatre maillons y passe sur deux lignes et
   ne sert plus a rien.

   Ici il est la SEULE sortie du minisite vers le site porteur. Le masquer
   laisserait un visiteur arrive par un partage sans aucun moyen de savoir de
   quel site releve la page, ni d'y aller. Le maillon actif s'ecrete deja par
   `text-overflow`, ce qui suffit a le faire tenir.

   LES DEUX SELECTEURS SONT REPRIS, et il en fallait deux : `events.css` masquait
   le `<nav>` a l'interieur, pas le conteneur. Une reprise sur le seul conteneur
   laissait donc une boite affichee et vide — ce que la sonde a d'abord lu comme
   « visible ». */
@media (width < 48em) {
    .event-banner .breadcrumb-bar,
    .event-banner .breadcrumb-bar .breadcrumb {
        display: block;
    }

    /* ── UN MAILLON DU MINISITE PORTE UN TITRE, PAS UNE RUBRIQUE ──
       `app.css` pose `nowrap` sur la liste et `flex-shrink: 0` sur les maillons
       non actifs. Son motif est juste POUR LE SITE : ce sont des rubriques
       courtes, `nowrap` est ce qui permet a la page courante de s'ecreter, et en
       `wrap` l'ellipse ne se declencherait jamais.

       Ici le troisieme maillon est le TITRE de l'evenement. Sur l'accueil il est
       le maillon actif, donc il s'ecrete ; des la premiere page interieure il
       devient un LIEN, cesse de s'ecreter, et 249 px inextensibles s'ajoutent a
       un chemin de quatre maillons. La page debordait de 102 px sur 390 et de
       172 sur 320, avec ascenseur horizontal.

       PREMIERE TENTATIVE, CONSERVEE COMME AVERTISSEMENT : rendre les maillons
       compressibles. Le debordement partait, et le resultat etait pire que le
       defaut. La compression du flex se repartit sur la taille de base, pas sur
       l'utilite : le nom d'hote gardait ses 109 px pendant que « Programme », la
       page courante, tombait a « Pr… » et « Evenements » a « Even ». Quatre
       maillons illisibles valent moins qu'un ascenseur.

       Sur 390 px, un chemin de quatre maillons ne TIENT pas sur une ligne. Il
       passe donc a la ligne, et chacun reste entier. La bande gagne une ligne,
       ce qui est le prix honnete de l'information. */
    .event-banner .breadcrumb__list {
        flex-wrap: wrap;
        row-gap: var(--spacing-2xs);
    }

    /* Garde-fou pour un titre plus long que la ligne : sans lui, un evenement au
       nom a rallonge redeborderait, et le `wrap` ne peut rien couper a
       l'interieur d'un maillon. */
    .event-banner .breadcrumb__item {
        max-width: 100%;
        min-width: 0;
    }

    .event-banner .breadcrumb__item > a,
    .event-banner .breadcrumb__item > span {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* ── UNE CIBLE TACTILE SUR UN ELEMENT QU'ON NE PEUT PAS TOUCHER ──
       `app.css` pose `min-height: 2.75rem` sous 64 em sur `.breadcrumb a` ET
       sur `.breadcrumb li:last-child`. Le premier est une cible tactile, le
       second n'en est pas une : le maillon actif est la page COURANTE, un
       `<span>` sans lien. Rien ne s'y clique, et les 44 px n'y protegent rien.

       Sur le minisite le chemin se replie, et ce maillon occupe une rangee a
       lui seul : il coutait 44 px de banniere pour une ligne de texte de 22.
       Les LIENS gardent leurs 44 px, eux — c'est la moitie du chemin qui se
       touche, et elle ne bouge pas. */
    .event-banner .breadcrumb__item--active,
    .event-banner .breadcrumb__item:last-child {
        min-height: 0;
    }
}


/* ── LA CARTE D'IDENTITE DU RAIL, SUR L'ACCUEIL ──
   Elle occupe le creneau que l'affiche prend sur les pages interieures :
   l'affiche y est deja en couverture, et laisser le creneau vide ferait
   descendre le menu d'une page a l'autre. */
.minisite-ident__kicker {
    margin: 0 0 var(--spacing-xs);
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--color-text-light);
}

.minisite-ident__title {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-md);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.minisite-ident__subtitle {
    margin: var(--spacing-2xs) 0 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-tight);
    color: var(--color-text);
}

/* Chasse fixe : une date et un lieu sont des VALEURS. */
.minisite-ident__meta {
    margin: var(--spacing-sm) 0 0;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}


/* ── UN APPEL A L'ACTION QUI CONCLUT UNE SECTION ──
   Il prend sa LARGEUR PROPRE et se cale a gauche : pleine largeur, il barrerait
   la carte et peserait plus que le titre de la section qu'il conclut. Meme
   parti que `link_inline` de `_rail_card`. */
.minisite-section__cta {
    align-self: flex-start;
}


/* ── UNE COLONNE DE DUO EST UN CONTENEUR A RYTHME ──
   Elles etaient des `<div>` nus : leurs enfants s'empilaient avec les marges
   qu'ils portent chacun — l'en-tete la sienne, la frise la sienne, les cartes de
   tarif aucune. La note se retrouvait collee aux cartes, et l'ecart changeait
   d'une colonne a l'autre.

   Meme rythme que dans une section : 24 px. Une seule echelle sur toute la
   page, quel que soit le niveau d'imbrication. */
.minisite-block {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
    min-width: 0;
}

/* ── LES ENFANTS NE DECLARENT PLUS LEURS ECARTS ──
   `_section_header` porte `margin-bottom: var(--spacing-lg)` pour les pages qui
   le posent sans conteneur a `gap` ; `evt-jalons` et `evt-calls` en portent une
   aussi, heritee de la mise en page a bandes d'`events.css`. Ici le bloc EST le
   conteneur a `gap` : les deux s'additionnaient, et l'ecart valait 48 px la ou
   ses voisins en font 24. Meme defaut de double propriete que celui corrige
   entre les sections, et que celui entre l'en-tete et son contenu — trois fois
   le meme, a trois niveaux d'imbrication.

   Le selecteur porte sur les ENFANTS DIRECTS du bloc : ce qui vit plus bas
   garde ses marges, elles n'entrent en concurrence avec aucun `gap`. */
.minisite-block > .section-header,
.minisite-block > .evt-jalons,
.minisite-block > .evt-calls,
.minisite-block > .evt-prices,
.minisite-block > .minisite-tiers {
    margin-bottom: 0;
}

/* ══════════════════════════════════════════════════════════════
   LE BAS DE PAGE : LE BANDEAU D'ABONNEMENT SUIT LE RYTHME DES CARTES
   ══════════════════════════════════════════════════════════════ */

/* L'ecart entre la carte de contenu et la carte d'abonnement valait 72 px au
   bureau et 48 sur telephone, la ou deux cartes du rail sont separees de 16.
   Deux rembourrages s'additionnaient, et aucun des deux n'est fautif pris
   seul :

     .minisite main        padding-block: 0 var(--spacing-2xl)   48 px
     .subscriptions        padding-block: var(--spacing-lg) 0    24 px

   C'est le meme defaut de double propriete que celui deja corrige trois fois
   plus haut dans cette feuille, a un quatrieme niveau : ici les deux moities
   ne sont meme pas dans le meme fichier, ni dans le meme paquet.

   LA REPRISE SE FAIT ICI, ET C'EST LE MOTIF QUE `grammar/subscriptions.css`
   DEMANDE : « la section qui precede cede son rembourrage, et elle le fait
   chez elle » — `.article-single` et `.helpcenter` le font deja dans leur
   propre feuille. La regle partagee n'est pas touchee, et l'asymetrie 24/48
   qu'elle documente reste vraie partout ailleurs.

   Cette feuille n'est chargee que par la coquille v2, et apres `events.css` :
   la reprise ne peut atteindre ni le site, ni les pages restees sur l'ancienne
   coquille.

   16 px, et pas 24 : c'est l'ecart entre deux cartes du rail, mesure. Le
   bandeau EST une carte de la meme famille, il se range au meme rythme. */
.minisite main {
    padding-bottom: 0;
}

.minisite .subscriptions {
    padding-block: var(--spacing-md) 0;
}

/* ══════════════════════════════════════════════════════════════
   LE PIED DU MINISITE : LA GRAMMAIRE DU SITE, DEUX APPARTENANCES
   ══════════════════════════════════════════════════════════════ */

/* Le gabarit emprunte les classes `c-footer*` : tout ce qui suit est un DELTA,
   pas une seconde implementation. Ce qui n'est pas ecrit ici est donc voulu
   identique au pied du site, y compris le repli mobile des rubriques.

   Trois anciennes regles d'`events.css` visent encore des classes que ce
   gabarit rend toujours (`__meta`, `__back`, `__legal .container`). Cette
   feuille etant chargee APRES et seulement par la coquille v2, la reprise se
   fait ici. Les autres regles `minisite-footer__*` d'`events.css` sont
   devenues mortes le jour de cette refonte : elles visent des classes que plus
   personne n'emet, et l'ancienne coquille n'a plus aucun appelant. */

/* ── LE BANDEAU NOMME L'EDITION, PAS L'ASSOCIATION ── */
.minisite-footer__meta {
    margin: 0;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    line-height: 1.5;
    color: var(--color-text-light);
}

/* ── LA COLONNE DE GAUCHE PORTE L'ETAT, PAS UNE MISSION ──
   Sur un colloque, savoir si les inscriptions sont ouvertes decide de tout ;
   une phrase de mission n'y apprend rien que le reste de la page ne dise. */
.minisite-footer__state {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin: 0;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
}

.minisite-footer__note {
    margin: 0;
    max-width: 38ch;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-loose);
    color: var(--color-text-light);
    text-wrap: pretty;
}

.minisite-footer__contact {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--font-size-xs);
}

.minisite-footer__contact a {
    display: inline-flex;
    align-items: center;

    /* HUIT PIXELS, ET NON DEUX. `--spacing-2xs` vaut 2 px : « Jour 1 » et sa
       date se touchaient, et l'on lisait un seul mot coupe plutot que deux
       rangs. La valeur egale le rembourrage lateral de la pastille — l'ecart
       interne et l'ecart au bord sont alors les memes, ce qui est la seule
       facon de ne pas voir la couture.

       L'alignement, lui, n'etait PAS en cause : les deux corps ne different que
       d'un pixel (14 contre 13), donc `center` les cale a moins d'un demi-pixel
       de leurs lignes de base. Mesure a l'appui ci-dessous. */
    gap: var(--spacing-sm);
    color: var(--color-text-light);
}

.minisite-footer__contact a:hover,
.minisite-footer__contact a:focus-visible {
    color: var(--color-primary);
}

/* ── LA BARRE DU BAS : L'ASSOCIATION REPREND LA MAIN ──
   Un ton plus sombre, et le retour au site a gauche : on quitte l'edition PAR
   LE BAS, ce qu'un lien perdu au milieu d'une colonne ne permettait pas.

   `events.css` pose ici une rangee unique en `space-between`. Le bas porte
   desormais DEUX rangees — qui organise, puis par ou sortir — d'ou la reprise
   en colonne. */
.minisite-footer__legal {
    /* PAS DE RESERVE POUR LE LANCEUR D'AIDE. `footer.css` pose jusqu'a 72 px de
       rembourrage bas sur la bande legale pour que la bulle d'assistance, objet
       FIXE du coin bas droit, ne recouvre pas les mentions. Le motif est juste
       pour le site.

       Le minisite ne rend AUCUN lanceur : mesure du 2026-09-02, zero classe
       `assistance*` sur ses pages, quand `/actualites` en porte six — le temoin
       importe, un compte nul ne prouverait rien sans lui. Ces 72 px protegeaient
       donc un objet absent, et laissaient un blanc en fin de barre que l'oeil
       lit comme la fin de la page.

       Le rembourrage vertical de la barre vit dans son `.container`, ci-dessous.
       Si un lanceur arrive un jour sur le minisite, c'est ICI qu'il faudra
       rendre la reserve. */
    padding-block: 0;

    /* AUCUN FOND PROPRE : la bande porte le fond de page, comme le reste du
       minisite. Elle a longtemps ete peinte d'un ton plus sombre
       (`--color-bg-light` assombri de `--color-shade`, d'apres la maquette qui
       peint `#cfd9e5`), pour « fermer » la page par le bas. La demande du
       2026-09-05 tranche l'inverse : les mentions legales et les organisateurs
       ne se detachent pas du plateau. La separation reste portee par le filet
       de `.minisite-footer__bottom`, qui suffit. */
    background: none;
}

.minisite-footer__legal > .container {
    display: flex;

    /* `flex-wrap: nowrap` N'EST PAS DECORATIF ICI. La regle d'`events.css` que
       celle-ci reprend posait une RANGEE, donc un `wrap` legitime. Passer en
       colonne sans le neutraliser laisse `column` + `wrap` : le conteneur
       fabrique alors des lignes sur l'axe principal, `align-content: stretch`
       les etire, et la bande des organisateurs rendait 148 px pour un contenu
       de 39.

       Le defaut ne se voit dans aucune des deux regles prise seule, et la
       cellule mesurait bien 39 px de haut NATURELLEMENT : c'est la boite de
       grille qui etait etiree, ce qui envoie chercher dans la grille. Meme
       famille que le `gap` et la marge qui s'ajoutent — changer la mise en page
       d'un conteneur, c'est neutraliser ce que l'ancienne y avait laisse. */
    flex-wrap: nowrap;
    flex-direction: column;
    align-items: stretch;
    gap: var(--spacing-md);
    padding-block: var(--spacing-md);
}

/* Une bande a EMPLACEMENTS, et non une colonne a un mot. Elle se contente
   d'une cellule sans se redessiner : `evt_event_organizer` est vide sur tous
   les evenements au 2026-09-02, donc une seule est rendue aujourd'hui. */
.minisite-footer__orga {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
    gap: var(--spacing-md);
}

.minisite-footer__orga-item {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
}

.minisite-footer__orga-role {
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

.minisite-footer__orga-name {
    font-family: var(--font-title);
    font-size: var(--font-size-base);
    font-weight: 700;
    line-height: 1.25;
    color: var(--color-primary-dark);
}

.minisite-footer__bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm) var(--spacing-lg);
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--color-border);
}

/* `.c-footer__legal a` (0,2,1) bat `.minisite-footer__back` (0,1,0) : le lien de
   sortie rendait dans l'encre discrete des mentions legales, mesure a la couleur
   CALCULEE et non a la lecture du CSS — les cinq liens de la barre rendaient le
   meme 4,72:1, ce qui est ce qui l'a signale. Il est la SORTIE du minisite : il
   se voit, ou il ne sert a rien. */
.minisite-footer__legal .minisite-footer__back {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    margin: 0;
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--color-primary);
    text-decoration: none;
}

.minisite-footer__legal .minisite-footer__back:hover,
.minisite-footer__legal .minisite-footer__back:focus-visible {
    color: var(--color-primary-dark);
}

/* ── LES MENTIONS SE REPLIENT, ELLES NE S'EMPILENT PAS ──
   `footer.css` passe `.c-footer__legal-links ul` en COLONNE sous 60 em, et son
   motif est juste POUR LE SITE : sa bande legale porte davantage d'entrees plus
   un lanceur d'aide, et « sur telephone chaque mot coute une ligne ».

   La barre du minisite en porte trois, courtes. Empilees, elles rendaient
   quatre lignes et 102 px pour ce qui tient en deux — mesure du 2026-09-02 sur
   iPhone SE. Le conteneur n'ayant lui-meme aucune regle de disposition, ses
   enfants (le copyright, les pages legales de l'evenement, la liste du menu
   CMS) s'empilaient aussi. */
.minisite-footer__legal .c-footer__legal-links {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--spacing-xs) var(--spacing-md);
}

.minisite-footer__legal .c-footer__legal-links ul {
    flex-direction: row;
    gap: var(--spacing-xs) var(--spacing-md);
}

/* Sous le palier, la rangee du bas passe en colonne PLUTOT QUE de se replier :
   en `space-between` repliee, la sortie et les mentions se retrouvaient calees
   chacune d'un bord, ce qui les fait lire comme deux blocs sans rapport. */
@media (width < 48em) {
    .minisite-footer__bottom {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--spacing-md);
    }

    /* ── NI RESERVE POUR UNE BARRE D'ACTION QUI N'EXISTE PLUS ──
       `events.css` reserve `--minisite-action-h` + une marge en bas de la bande
       legale, sous 48 em : l'ancienne navigation posait son bouton
       d'inscription en barre FIXE au bas de l'ecran, et le pied devait cesser
       de s'etendre dessous. La coquille v2 ne rend plus cette barre —
       `minisite-nav__cta` compte zero occurrence sur les huit chemins mesures,
       quand le temoin `back-to-top`, lui, en compte une.

       Le selecteur d'origine est `.minisite .minisite-footer__legal` (0,2,0) :
       la reprise doit porter le meme rang, sans quoi elle est ignoree en
       silence — c'est ce qui est arrive au premier essai, qui reglait le bureau
       et laissait 88 px de blanc sur telephone. */
    .minisite .minisite-footer__legal {
        padding-bottom: 0;
    }
}

/* ══════════════════════════════════════════════════════════════
   LE MENU DE LA BANNIERE, SOUS 64 EM
   ══════════════════════════════════════════════════════════════ */

/* ── POURQUOI UN DECLENCHEUR PLUTOT QU'UNE RANGEE D'ONGLETS ──

   Les pages ont ete rendues un temps en onglets defilant lateralement, pour
   qu'on sache sans un geste ce que le minisite contient. Mesure a 375 px :
   la rangee n'en montrait que trois et demi — « Accueil, Programme,
   Inscription, Contributio… » coupe au bord — donc elle ne disait pas ce
   qu'elle etait censee dire, et elle occupait la CINQUIEME ligne d'une
   banniere qui en faisait deja quatre (fil sur trois lignes, actions sur une).

   Le panneau les montre TOUTES, sur la pleine largeur, avec une cible de
   44 px par entree. La rangee de tete retombe a 44 px.

   ── LE PANNEAU EST `display: contents` AU-DESSUS DU PALIER ──

   Ses enfants redeviennent alors enfants directs de la rangee, et la banniere
   du bureau est exactement celle d'avant. C'est ce qui evite de rendre DEUX
   fois la barre de partage : deux boutons de marque-page pour un meme contenu,
   deux hydratations reseau, et deux etats qui divergent des le premier clic. */

/* La liste du panneau et la colonne du rail sont la MEME brique : une seule des
   deux est dans l'arbre d'accessibilite a la fois, et c'est le CSS qui
   tranche. */
.minisite-menu--panel {
    display: none;
}

.event-banner__top {
    display: none;
}

@media (width >= 64em) {
    /* Le bureau ne connait pas l'etat replie : le declencheur y est hors de
       portee, et la regle qui replie vit dans l'autre palier. */
    .event-banner__panel {
        display: contents;
    }
}

@media (width < 64em) {
    /* La banniere passe en COLONNE : la rangee de tete, puis le panneau. En
       `wrap`, le panneau serait venu se ranger a cote du declencheur plutot
       qu'en dessous.

       `nowrap` : la barre est en `wrap` pour sa rangee unique du bureau, et le
       passage en colonne ne le neutralise pas tout seul. En `column` + `wrap`,
       la LIGNE prend la largeur du plus large enfant et `align-items: stretch`
       etire les autres a cette largeur. */
    .event-banner__bar {
        flex-wrap: nowrap;
        flex-direction: column;
        align-items: stretch;
        gap: var(--spacing-xs);
        padding: var(--spacing-2xs) var(--spacing-ms);
    }

    /* `min-width: auto` est le defaut d'un element flex, et il l'empeche de
       descendre SOUS la largeur de son contenu : un titre d'evenement long
       poussait la barre a 571 px dans une fenetre de 375, et toute la page
       debordait d'autant. Le defaut ne se voit pas sur le titre — ce sont ses
       VOISINS qui debordent d'abord. */
    .event-banner__bar > * {
        min-width: 0;
    }

    /* ── LE FIL VISIBLE NE SURVIT PAS AU PALIER, SON NOEUD SI ──
       Trois lignes pour un chemin dont le maillon le plus long — le titre de
       l'evenement, sa ville et son annee — se coupait au milieu d'un mot. Le
       nom en tete de rangee le dit, et les SORTIES sont rendues en clair au
       pied du panneau. Le composant continue d'emettre son `BreadcrumbList` :
       c'est lui que les moteurs lisent. */
    .event-banner__panel .breadcrumb-bar {
        display: none;
    }

    /* ── LA RANGEE DE TETE ── */
    .event-banner__top {
        display: flex;
        align-items: center;
        gap: var(--spacing-sm);
        min-height: var(--touch-target-min);
    }

    /* Le nom de l'evenement, sur UNE ligne. Il s'ecrete plutot que de revenir a
       la ligne : une rangee de tete qui change de hauteur d'une page a l'autre
       se lit comme une erreur, et le titre complet est a un doigt de la — dans
       le rail, et dans l'onglet du navigateur. */
    .event-banner__ident {
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        font-size: var(--font-size-sm);
        font-weight: 700;
        line-height: var(--line-height-tight);
        color: var(--color-on-primary);
        text-decoration: none;
    }

    .event-banner__ident:hover,
    .event-banner__ident:focus-visible {
        text-decoration: underline;
    }

    /* ── LE DECLENCHEUR ──

       Il GARDE SON MOT : un pictogramme seul ne dit pas « toutes les pages sont
       ici ». Cible de 44 px, minimum RGAA.

       ── PAS DE FILET, ET C'EST LA REGLE DE LA MAISON ──

       Il a porte un contour clair. Sur le marine de la banniere ce filet est la
       chose la plus visible de la rangee — plus que le nom de l'evenement qu'il
       cotoie — alors qu'il ne dessine qu'un bouton utilitaire. Le depot ne pose
       pas de bordure coloree, et surtout pas dans une bande de marque : ce sont
       les DEUX etats qui doivent se distinguer, pas le bouton du fond.

       Au repos il n'est donc que son glyphe et son mot, en encre claire ; le
       hachurage sombre le designe au survol ; ouvert, il prend l'aplat clair,
       parce qu'il n'est alors plus une entree mais l'etat courant de la
       banniere. Trois etats, aucun filet. */
    .event-banner__burger {
        flex: none;
        display: inline-flex;
        align-items: center;
        gap: var(--spacing-2xs);
        min-height: var(--touch-target-min);
        padding-inline: var(--spacing-sm);
        border: 0;
        border-radius: var(--radius-pill);
        background: transparent;
        font-size: var(--font-size-xs);
        font-weight: 600;
        color: var(--color-on-primary);
        cursor: pointer;
    }

    .event-banner__burger:hover,
    .event-banner__burger:focus-visible {
        background: var(--veil-on-dark);
        color: var(--color-on-primary);
    }

    .event-banner__burger[aria-expanded='true'] {
        background: var(--color-on-primary);
        color: var(--color-primary-dark);
    }

    /* ── LE PANNEAU ──
       L'ETAT EST LU SUR LE DECLENCHEUR, jamais recopie sur le panneau :
       `aria-expanded` est ce qu'annonce un lecteur d'ecran, et une classe posee
       a cote aurait fini par en diverger.

       L'attribut `hidden` avait ete essaye d'abord, et il ne convient pas : la
       feuille de l'agent utilisateur le pose en `display: none` IMPORTANT dans
       Chrome, que le `display: contents` du bureau ne peut pas neutraliser —
       mesure du 2026-09-05, banniere du bureau a 32 px, fil d'Ariane et barre
       de partage disparus. Le defaut ne se voyait pas sous ce palier, ou le
       panneau DOIT etre masque : seule la mesure au bureau l'a dit. */
    .event-banner__panel {
        display: flex;
        flex-direction: column;
        gap: var(--spacing-sm);
        padding-top: var(--spacing-sm);
        padding-bottom: var(--spacing-2xs);
        border-top: 1px solid var(--veil-on-dark);
    }

    .event-banner__bar:has(.event-banner__burger[aria-expanded='false']) .event-banner__panel {
        display: none;
    }

    /* Sur le marine de la banniere, l'encre courante rend 1:1. Les jetons
       d'encre sur marine sont ceux que la grammaire designe pour ce fond. */
    .minisite-menu--panel {
        display: block;
    }

    .minisite-menu--panel .minisite-menu__link {
        min-height: var(--touch-target-min);
        margin-inline: 0;
        color: var(--color-on-navy);
    }

    .minisite-menu--panel .minisite-menu__link:hover,
    .minisite-menu--panel .minisite-menu__link:focus-visible {
        background: var(--veil-on-dark);
        color: var(--color-on-primary);
    }

    /* L'entree courante s'inverse : encre marine sur fond clair. Le marine sur
       marine du rail ne dirait rien ici. */
    .minisite-menu--panel .minisite-menu__link--on {
        background: var(--color-on-primary);
        color: var(--color-primary-dark);
    }

    .minisite-menu--panel .minisite-menu__count {
        color: var(--color-on-navy-muted);
    }

    .minisite-menu--panel .minisite-menu__link--on .minisite-menu__count {
        color: var(--color-text-light);
    }

    /* Les commandes de partage prennent la CIBLE du panneau. Elles rendaient a
       30 px de haut — la hauteur qu'elles ont dans une rangee du bureau, ou
       elles se visent a la souris. Dans une liste qui se touche au doigt, elles
       etaient les seules entrees sous le minimum RGAA. */
    .event-banner__share .share-dropdown-group__btn,
    .event-banner__share .share-dropdown__summary {
        min-height: var(--touch-target-min);
    }

    /* ── LES SORTIES ──
       Le site porteur et l'agenda. Deux DESTINATIONS, pas un chemin : rendues
       en fil elles coutaient trois lignes, et le chevron qui les relie n'a rien
       a dire une fois le maillon de l'evenement retire. */
    .event-banner__exits {
        list-style: none;
        margin: 0;
        padding: 0;
        display: flex;
        flex-wrap: wrap;
        gap: 0 var(--spacing-md);
    }

    .event-banner__exits a {
        display: inline-flex;
        align-items: center;
        gap: var(--spacing-2xs);
        min-height: var(--touch-target-min);
        font-size: var(--font-size-xs);
        color: var(--color-on-navy-muted);
        text-decoration: none;
    }

    .event-banner__exits a:hover,
    .event-banner__exits a:focus-visible {
        color: var(--color-on-primary);
        text-decoration: underline;
    }
}

@media (width >= 64em) {
    .event-banner__exits {
        display: none;
    }
}

/* ── LES DEUX ETATS DU DECLENCHEUR VIVENT DANS LE DOM ──
   Le CSS choisit sur `aria-expanded`. `display: none` et non `visibility` :
   l'etat masque doit sortir de l'arbre d'accessibilite, sans quoi le nom du
   bouton concatene les deux — « Menu Fermer ». */
.event-banner__burger-icon--close,
.event-banner__burger-label--close {
    display: none;
}

.event-banner__burger[aria-expanded='true'] .event-banner__burger-icon--open,
.event-banner__burger[aria-expanded='true'] .event-banner__burger-label--open {
    display: none;
}

.event-banner__burger[aria-expanded='true'] .event-banner__burger-icon--close,
.event-banner__burger[aria-expanded='true'] .event-banner__burger-label--close {
    display: inline-flex;
}

/* ══════════════════════════════════════════════════════════════
   UN CRENEAU A PLUSIEURS SEANCES SE VOIT COMME UN BLOC
   ══════════════════════════════════════════════════════════════ */

/* Sept lignes qui commencent toutes a 16:30, de meme poids, ne disent pas
   qu'elles sont SIMULTANEES. Le filet vertical les tient ensemble et l'en-tete
   le nomme : le creneau redevient un objet, sans redevenir une carte — les
   trois niveaux d'encadrement que la maquette a fait tomber ne reviennent pas.

   Le filet plutot qu'une surface : c'est ce qui separe « ces lignes vont
   ensemble » de « ces lignes sont un bloc a part ». Une seance se choisit
   DANS le creneau, elle n'en sort pas. */
.programme-slot--parallel {
    position: relative;
    padding-left: var(--spacing-md);
}

.programme-slot--parallel::before {
    content: '';
    position: absolute;
    inset-block: var(--spacing-xs) var(--spacing-sm);
    inset-inline-start: 0;
    width: 2px;
    border-radius: var(--radius-pill);
    background: var(--color-border);
}

.programme-slot__head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--spacing-2xs) var(--spacing-sm);
    margin: 0 0 var(--spacing-xs);
}

/* ══════════════════════════════════════════════════════════════
   LES COMMANDES DU PROGRAMME, EN TETE DU DEROULE
   ══════════════════════════════════════════════════════════════ */

/* Elles vivent dans la MEME section que l'en-tete de page : un filet separe
   deux choses, et il n'en separe aucune entre un titre et ses commandes. Le
   rythme est celui de la carte — un cran entre les rangees. */
/* UNE SEULE RANGEE, QUI SE REPLIE. Journee, types, compte et parcours coulent
   dans un meme flux : ils repondent tous a « que montre le deroule ». Deux
   rangees a sur-titres prenaient quatre lignes pour ce qui tient en une. */
.programme-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;

    /* La gouttiere de COLONNE separe trois familles — les journees, le
       declencheur, le compte — et elle est plus large que celle qui separe deux
       pastilles d'une meme famille. C'est elle qui les fait lire comme des
       groupes sans qu'aucun intitule ne le dise. */
    gap: var(--spacing-xs) var(--spacing-md);
    min-width: 0;

    /* —— ELLE EST SON PROPRE CONTENEUR DE REQUETE ——
       Ce qui decide si le jour de semaine tient n'est pas la fenetre, c'est la
       LARGEUR DE LA BARRE — et les deux ne varient pas dans le meme sens.
       Mesure du 2026-09-03, edition a trois journees :

           fenetre 1080 -> barre 622    fenetre 1024 -> barre 566
           fenetre  960 -> barre 846    fenetre  800 -> barre 686

       A 1024 px le rail apparait et ecrase le contenu a 566 px ; a 960 il
       disparait et la barre remonte a 846. Une media query aurait donc retire
       le jour de semaine sur les fenetres ETROITES, ou il y a de la place, et
       l'aurait garde a 1024, ou il n'y en a pas : elle aurait conclu l'inverse
       de la mesure. */
    container-type: inline-size;
    container-name: programme-bar;

    /* ── LA HAUTEUR DES CONTROLES VIENT DE LA GRAMMAIRE ──
       Elle valait `--touch-target-min`, soit 2,75 rem A TOUTE LARGEUR : 44 px
       de boite pour 20 px de texte, mesure — deux fois plus de vide que de
       lettres. Le remplissage n'y etait pour rien (4 px), c'est le plancher
       tactile qui portait tout l'ecart.

       `list-toolbar.css` a deja tranche ce cas, et pose la seule regle qui
       tienne les deux exigences : 2 rem la ou l'on pointe, 2,75 la ou l'on
       touche. Le meme jeton, la meme bascule, le meme palier.

       LA VALEUR EST HISSEE SUR `body` parce qu'elle a DEUX lecteurs : la barre,
       qui en tire la hauteur de ses controles, et la reserve d'ancre des titres
       de journee, qui doit degager exactement la hauteur que la barre COLLANTE
       recouvre. Recopiee aux deux endroits, elle aurait derive au premier
       reglage — et le defaut se serait vu non pas au rendu de la barre, mais
       au saut d'une ancre, cinq ecrans plus bas. */
    --control-height: var(--programme-bar-height);

    /* —— ELLE RESTE A L'ECRAN ——
       Le deroule d'un colloque fait plusieurs ecrans de haut. Sans cela,
       filtrer ou changer de journee depuis le milieu du programme demande de
       remonter en tete, de viser, puis de retrouver ou l'on en etait.

    ELLE TIENT PARCE QU'ELLE EST FILLE DE LA CARTE, pas de l'en-tete : un
       element collant ne depasse jamais son bloc conteneur, et la section de
       l'en-tete ne fait que 127 px. La raison complete vit dans
       `programme.html.twig`, a l'endroit ou le gabarit la pose — c'est la
       qu'on la cherchera le jour ou quelqu'un voudra la ranger « proprement »
       dans l'en-tete.

       LE FOND EST OBLIGATOIRE : sans lui, le deroule defile A TRAVERS la barre.
       Il vaut celui de la carte (`ui-card--lead` porte `--surface-1`), sinon
       la barre se dessine comme un bandeau au repos, alors qu'elle ne doit se
       remarquer qu'une fois collee.

       Plan LOCAL (`1`) et non un jeton de l'echelle nommee : la barre n'arbitre
       qu'avec le contenu de sa propre carte, jamais avec un flottant de la
       page. L'echelle nommee commence a 100, et n'a rien a faire ici.

       LE FILET EST EN DESSOUS, et porte par la barre elle-meme. Il separait
       auparavant deux sections voisines, donc il tombait ENTRE le titre de la
       page et ses commandes — il coupait le titre de ce qu'il commande. Ici
       il separe les commandes du contenu, ce qu'un filet doit faire, et il
       reste sous la barre quand elle colle : c'est lui qui dit ou finit la
       barre et ou reprend le deroule. */
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface-1);
    margin-top: var(--spacing-lg);
    padding-block: var(--spacing-sm);
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--spacing-lg);
}

body.minisite {
    --programme-bar-height: 2rem;
}

/* —— ELLE NE COLLE PAS SUR TELEPHONE ——
   En dessous du palier, la rangee se replie sur deux ou trois lignes : collee,
   elle mangerait le tiers de l'ecran en permanence, sur la surface ou il y en a
   le moins. Le programme s'y lit d'un trait, et la barre revient a sa place
   dans le flux. */
@media (width < 48em) {
    body.minisite {
        --programme-bar-height: 2.75rem;
    }

    .programme-toolbar {
        position: static;
    }
}

/* ── LE PANNEAU, SOUS SON BOUTON ──
   Il prend la rangee entiere : c'est un flex a `wrap`, donc une base de 100 %
   le fait passer a la ligne sans qu'aucun ordre n'ait a changer. */
.programme-toolbar__panel {
    flex: 1 0 100%;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);

    /* Le panneau se decollait de quatre pixels de la rangee qui l'ouvre — la
       gouttiere de la barre, pensee pour des pastilles voisines et non pour
       une zone qui s'ouvre. Le rembourrage est porte par le PANNEAU et non par
       la gouttiere : celle-ci vaut aussi entre deux rangees d'etiquettes
       repliees sur telephone, ou ce meme ecart serait de trop.

       Mesure au haut de la premiere pastille, et non au bord du panneau : le
       rembourrage est INTERIEUR, il ne deplace pas la boite. Un releve pris sur
       la boite disait 10 px quel que soit le reglage. */

    /* PAS DE SURFACE PROPRE. `events.css` lui donne un aplat gris et un
       rembourrage de carte : dans la carte blanche du minisite, cela fait une
       boite dans une boite, et les etiquettes pales y devenaient illisibles —
       bleu pale sur gris pale. Le panneau n'est pas un objet, c'est le
       prolongement de sa rangee.

       LE RACCOURCI PORTE LES QUATRE COTES, DONC IL PORTE AUSSI L'ECART DU HAUT.
       Un `padding-top` declare avant ce `padding: 0` etait ecrase par lui, dans
       la MEME regle : rembourrage calcule a zero, et l'ecart restait de 4 px
       quel que soit le reglage. C'est le defaut que le depot documente pour les
       briques partagees — « ne jamais declarer un raccourci la ou une variante
       devra poser un longhand » — commis ici a trois lignes d'intervalle. */
    margin: 0;
    padding: var(--spacing-md) 0 0;
    border: 0;
    background: none;
}

/* ── SOUS LE PALIER, C'EST LA FEUILLE QUI PREND LE RELAIS ──
   `events.css` porte deja cette bascule, et son commentaire decrit exactement
   ce qui arrive sans elle : « les deux partagent `filtersOpen`, donc sans cette
   bascule ils s'ouvriraient ensemble, l'un derriere l'autre ».

   Son selecteur visait l'ANCIEN emplacement du panneau — `.programme >
   .container > .programme__facets` — et le panneau ayant remonte dans la barre,
   il ne matchait plus rien. Mesure a 375 px avant correction : dix etiquettes
   visibles au lieu de cinq, donc deux fois les memes controles dans l'arbre
   d'accessibilite.

   C'est le mode de panne d'un selecteur lie a une POSITION plutot qu'a un
   role : deplacer le balisage l'eteint en silence. */
@media (width < 64em) {
    .programme-toolbar__panel {
        display: none;
    }
}

/* Une rangee par famille : l'intitule a gauche, ses etiquettes a droite. Sur un
   panneau a deux familles, l'empilement vertical du CSS d'origine coutait deux
   fois la hauteur pour la meme information. */
.programme-toolbar__panel .programme__facet {
    display: flex;
    flex-wrap: wrap;

    /* CENTRE, ET NON LIGNE DE BASE. La rangee porte trois objets de hauteurs
       differentes — un intitule de 11 px, des pastilles de 31, une action
       textuelle — et un alignement sur les lignes de base posait l'action
       3,5 px au-dessus du centre des pastilles. Une ligne de base aligne des
       TEXTES ; ici on aligne des boites. */
    align-items: center;
    gap: var(--spacing-2xs) var(--spacing-sm);
    margin: 0;
    padding: 0;
    min-width: 0;
}

/* Le pictogramme et le texte de l'action se centrent l'un sur l'autre : sans
   cela le premier se pose sur la ligne de base du second et flotte au-dessus.
   `ui-textlink` porte le reste — encre, graisse, soulignement. */
.programme-toolbar__panel .programme__clear-filters {
    display: inline-flex;
    align-items: center;

    /* HUIT PIXELS, ET NON DEUX. `--spacing-2xs` vaut 2 px : « Jour 1 » et sa
       date se touchaient, et l'on lisait un seul mot coupe plutot que deux
       rangs. La valeur egale le rembourrage lateral de la pastille — l'ecart
       interne et l'ecart au bord sont alors les memes, ce qui est la seule
       facon de ne pas voir la couture.

       L'alignement, lui, n'etait PAS en cause : les deux corps ne different que
       d'un pixel (14 contre 13), donc `center` les cale a moins d'un demi-pixel
       de leurs lignes de base. Mesure a l'appui ci-dessous. */
    gap: var(--spacing-sm);
    min-height: var(--control-height);
    cursor: pointer;
}

.programme-toolbar__panel .programme__facet-label {
    flex: none;
    min-width: 6rem;
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

.programme-toolbar__panel .programme__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-2xs);
    min-width: 0;
}

/* Le compteur d'une etiquette : une VALEUR, donc la chasse fixe, et une encre
   secondaire pour qu'il ne dispute pas le libelle. La pastille elle-meme vient
   de `ui-chip` — rien a redeclarer. */
.programme-toolbar__panel .programme__chip-count {
    margin-left: var(--spacing-xs);
    font-family: var(--font-data);
    font-size: var(--font-size-2xs);
    font-weight: 500;
    color: var(--color-text-light);
}

.programme-toolbar__panel .ui-chip--selected .programme__chip-count {
    color: var(--color-primary);
}

/* Les journees coulent dans la rangee au lieu de former un bloc. Les facettes
   n'y sont plus : elles vivent dans le panneau. */
.programme-toolbar__days {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs);
    margin: 0;
    padding: 0;
    min-width: 0;
    list-style: none;
}

/* ── LES JOURNEES ──
   Des liens d'ancre, donc pas d'etat actif : rien ne dit ou l'on est puisque
   l'on est PARTOUT — le programme entier est rendu. Une pastille active
   mentirait sur ce que le lien fait. */

.programme-toolbar__day {
    display: inline-flex;
    /* CENTRE, ET NON `baseline`. Sur une pastille a hauteur imposee, aligner
       deux corps differents sur leur ligne de base les cale en HAUT de la
       boite : le texte cesse d'etre centre verticalement, et c'est exactement
       le defaut corrige deux fois sur cette barre. L'ecart de ligne de base
       entre 13 et 11 px reste sous le pixel. */
    align-items: center;

    /* HUIT PIXELS, ET NON DEUX. `--spacing-2xs` vaut 2 px : « Jour 1 » et sa
       date se touchaient, et l'on lisait un seul mot coupe plutot que deux
       rangs. La valeur egale le rembourrage lateral de la pastille — l'ecart
       interne et l'ecart au bord sont alors les memes, ce qui est la seule
       facon de ne pas voir la couture.

       L'alignement, lui, n'etait PAS en cause : les deux corps ne different que
       d'un pixel (14 contre 13), donc `center` les cale a moins d'un demi-pixel
       de leurs lignes de base. Mesure a l'appui ci-dessous. */
    gap: var(--spacing-sm);
    min-height: var(--control-height);
    font-size: var(--font-size-sm);
    font-weight: 600;
    padding: 0 var(--spacing-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    background: var(--color-bg);
    color: var(--color-text);
    text-decoration: none;
    transition: border-color var(--transition-fast), color var(--transition-fast);
}

/* —— LE JOUR DE SEMAINE CEDE LE PREMIER ——
   Sous 40 rem de BARRE, les trois pastilles datees, le declencheur et le compte
   demandent 611 px pour 566 disponibles, et la rangee passe a deux lignes.
   Collee, elle couterait alors 72 px d'ecran en permanence. Le jour de semaine
   est ce qui se retire : il situe la journee dans la semaine, la date la situe
   dans le calendrier — et c'est la date qui figure sur les billets et la
   signaletique. Le titre de journee, lui, garde les deux en toutes lettres. */
@container programme-bar (width < 40rem) {
    .programme-toolbar__day-weekday {
        display: none;
    }
}

/* Les deux morceaux de la date sont des boites, pas du texte separe par une
   espace : une espace litterale survivrait au retrait du jour de semaine et
   decalerait la date d'un blanc. */
.programme-toolbar__day-date {
    display: inline-flex;
    gap: 0.25em;
}

/* La date est un SECOND RANG dans la pastille : meme ligne, corps plus petit,
   couleur secondaire. Au meme rang que « Jour 2 », les deux se disputeraient la
   lecture et la pastille cesserait d'etre une cible pour devenir une fiche. */
.programme-toolbar__day-date {
    font-weight: 400;
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

/* Au survol, la pastille entiere passe au bleu : une date restee grise y
   lirait comme desactivee. */
.programme-toolbar__day:hover .programme-toolbar__day-date,
.programme-toolbar__day:focus-visible .programme-toolbar__day-date {
    color: inherit;
}

.programme-toolbar__day:hover,
.programme-toolbar__day:focus-visible {
    border-color: var(--color-primary);
    color: var(--color-primary);
}


.programme-toolbar__count {
    margin: 0;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.programme-toolbar__more {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    min-height: var(--control-height);
    padding: 0 var(--spacing-ms);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    background: var(--color-bg);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
    cursor: pointer;
}

.programme-toolbar__more:hover,
.programme-toolbar__more.is-active {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.programme-toolbar__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    padding: 0 var(--spacing-2xs);
    border-radius: var(--radius-pill);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-family: var(--font-data);
    font-size: var(--font-size-2xs);
}

/* ── L'ANCRE NE DOIT PAS SE COLLER AU BORD ──
   Sans reserve, `#jour-2` amene le titre de journee au ras du haut de la
   fenetre : on ne voit plus ce qui le precede, et rien ne dit qu'on a saute.
   La valeur est celle du rythme entre deux sections. */
.programme-day__head {
    /* La barre COLLANTE recouvre le haut de la fenetre : sans sa hauteur dans
       la reserve, `#jour-2` amene le titre de journee EXACTEMENT DESSOUS, donc
       invisible — et l'on croit que l'ancre a manque sa cible alors qu'elle
       l'a atteinte. L'etalement de son ombre compte autant que ses controles.
       Sous le palier ou la barre ne colle plus, la reserve reste : elle n'y
       coute qu'un peu de contexte au-dessus du titre. */
    scroll-margin-top: calc(
        var(--programme-bar-height) + 2 * var(--spacing-sm) + 1px
        + var(--spacing-lg)
    );
}

/* ── LA RESERVE DU SITE NE PROTEGE RIEN SUR LE MINISITE ──
   `app.css` pose `scroll-padding-top: 6rem` sur la racine, pour que la barre
   COLLANTE DU SITE ne recouvre pas la cible d'une ancre. Le minisite ne rend
   pas cette barre-la, et la reserve s'ajoutait a la marge de la cible : 120 px
   de vide au-dessus du titre de journee, pour un element qui n'est pas servi
   ici.

   CE COMMENTAIRE A DIT « aucun element collant sur le minisite », et c'etait
   vrai le 2026-09-03 au matin. La barre de commandes du programme colle depuis
   le meme jour : une mesure datee lue comme une propriete permanente est
   exactement le defaut que ce depot paye le plus souvent. Ce qui reste vrai est
   plus etroit et ne perime pas — la reserve de SIX REM d'`app.css` est
   dimensionnee pour une barre que cette surface ne rend pas, et une barre
   collante propre au minisite se reserve ELLE-MEME, sur la cible
   (`scroll-margin-top` ci-dessus) et non sur la racine.

   `:has()` sur la racine parce que `scroll-padding` s'applique au CONTENEUR DE
   DEFILEMENT, c'est-a-dire `html`, et que la classe qui identifie le minisite
   est sur `body`. La marge de la cible suffit alors seule. */
html:has(> body.minisite) {
    scroll-padding-top: 0;
}


/* ══════════════════════════════════════════════════════════════
   LA FICHE D'UNE COMMUNICATION
   ══════════════════════════════════════════════════════════════ */

/* ── LA SIGNATURE ──
   Les auteurs, sous l'en-tete de page. Elle n'est pas un chapo — elle ne dit
   pas de quoi parle la communication — ni un corps : c'est une attribution, et
   elle se lit d'un coup d'oeil. */
.minisite-byline {
    margin: 0;
    font-size: var(--font-size-md);
    line-height: var(--line-height-base);
    font-weight: 600;
    color: var(--color-primary-dark);
}

.minisite-byline a {
    color: var(--color-primary);
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

/* Le survol EPAISSIT le soulignement plutot que de foncer l'encre : sur un nom
   deja marine, foncer le rend illisible au moment precis ou l'on pointe
   dessus. Meme parti que dans les cartes de choix du programme. */
.minisite-byline a:hover,
.minisite-byline a:focus-visible {
    text-decoration-thickness: 2px;
}

/* ── QUI PARLE : PORTRAIT, RATTACHEMENT, BIOGRAPHIE ──

   Distinct de `.minisite-person` (l'apercu en grille de l'accueil, quatre
   fiches sans texte) et de `.minisite-speaker` (la ligne a trois colonnes de la
   page Intervenants, qui porte un horaire et non une biographie). Ici le
   contenu est un PARAGRAPHE : une piste de 14 rem ou une colonne du milieu
   coincee entre deux colonnes fixes ne peuvent pas le porter.

   Une ligne par personne, sur toute la largeur de la carte. Il y en a une a
   trois sur une communication. */
.minisite-bios {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

.minisite-bio {
    display: flex;
    gap: var(--spacing-md);
    min-width: 0;
    padding: var(--spacing-ms) var(--spacing-md);
    border-radius: var(--radius-md);
    background: var(--surface-4);
}

/* Le portrait est DECORATIF : le nom est en texte juste a cote. L'avatar
   generique n'est pas un aplat vide — il porte une silhouette, donc il se lit
   « une personne, sans photo » et non « une image qui n'a pas charge ». Sans
   lui, les noms ne demarreraient pas a la meme abscisse d'une ligne a l'autre
   et la colonne ondulerait : trois intervenants sur quatre n'ont pas de photo. */
.minisite-bio__photo {
    flex: none;
    width: 4rem;
    height: 4rem;
    border-radius: var(--radius-pill);
    object-fit: cover;
}

.minisite-bio__photo--generic {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-3);
    color: var(--color-text-light);
}

/* `min-width: 0` sur la colonne de texte : sans lui, un mot insecable — une URL
   dans une biographie — l'empeche de descendre sous la largeur de son contenu
   et fait deborder la carte. */
.minisite-bio__body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
}

.minisite-bio__name {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-md);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.minisite-bio__name a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

.minisite-bio__name a:hover,
.minisite-bio__name a:focus-visible {
    text-decoration-thickness: 2px;
}

/* Le role suit le nom sur la MEME ligne quand la place le permet : il le
   qualifie, il ne le remplace pas. Une ligne a lui seul lui donnerait le meme
   poids que le nom. */
.minisite-bio__role {
    margin-left: var(--spacing-sm);
    font-family: var(--font-sans);
    font-size: var(--font-size-sm);
    font-weight: 400;
    color: var(--color-text-light);
}

.minisite-bio__slot {
    margin: 0;
    font-size: var(--font-size-sm);
    font-weight: 600;
    line-height: var(--line-height-base);
    color: var(--color-primary);
}

.minisite-bio__text {
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text);
}

/* Le corps editorial d'une biographie porte ses propres marges de paragraphe ;
   la colonne est deja un conteneur a `gap`, et les deux s'additionneraient.
   Meme defaut de double propriete que celui corrige entre les sections, et
   entre un en-tete et son contenu. */
.minisite-bio__text.prose-content > :first-child {
    margin-top: 0;
}

.minisite-bio__text.prose-content > :last-child {
    margin-bottom: 0;
}

.minisite-bio__more {
    margin: 0;
    font-size: var(--font-size-sm);
}

/* Sur telephone, le portrait passe AU-DESSUS : a 326 px de colonne utile, une
   bande de 64 px plus sa gouttiere laissent 246 px au texte, ou une biographie
   tombe a trois mots par ligne. */
@media (width < 30em) {
    .minisite-bio {
        flex-direction: column;
    }
}

/* ══════════════════════════════════════════════════════════════
   LE FIL DES COMMUNICATIONS
   ══════════════════════════════════════════════════════════════ */

/* Il s'appelait `.resume-pager` et vivait dans `events.css`, a meme le plateau :
   il y posait lui-meme son ecart, son filet et son rembourrage
   (`margin-top` 2xl, `padding-top` lg, `border-top`). Dans la carte, il est
   fils d'une `.minisite-section` qui pose deja les trois — d'ou DEUX filets
   separes de 76 px de vide, le second colle au pager. Mesure du 2026-09-03.

   Il n'avait qu'UN appelant, la fiche de communication, passee en v2 : la
   feuille suit le gabarit plutot que de recevoir une surcharge locale. */
.minisite-pager {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-md);
    align-items: stretch;
}

@media (width >= 48em) {
    .minisite-pager {
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    }
}

.minisite-pager__link {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    min-width: 0;
    padding: var(--spacing-ms) var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--surface-4);
    text-decoration: none;
}

/* LA CARTE SUIVANTE SE LIT DE DROITE A GAUCHE : son chevron ferme la rangee,
   son texte s'aligne au bord. Sa place dans la grille dit deja le sens, et
   l'inversion le confirme sans un mot. */
.minisite-pager__link--next {
    flex-direction: row-reverse;
    text-align: right;
}

.minisite-pager__link:hover,
.minisite-pager__link:focus-visible {
    border-color: var(--color-primary);
    background: var(--surface-2);
}

/* ── LE CHEVRON EST UNE PASTILLE ──
   Il etait colle au libelle, a 14 px, dans le meme gris : l'orientation ne se
   prenait qu'en LISANT « precedente » ou « suivante ». En pastille, elle se
   prend d'un coup d'oeil. `flex: none` sans quoi la pastille se resserre quand
   un titre long tire sur la rangee, et le rond devient un ovale. */
.minisite-pager__chevron {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: var(--radius-pill);
    background: var(--surface-2);
    border: 1px solid var(--color-border);
    color: var(--color-primary);
}

.minisite-pager__link:hover .minisite-pager__chevron,
.minisite-pager__link:focus-visible .minisite-pager__chevron {
    border-color: var(--color-primary);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.minisite-pager__body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
}

/* ── LE LIBELLE EST SECONDAIRE, LE TITRE EST L'INFORMATION ──
   Il rendait en capitales, graisse 700, encre de marque, quand le titre rendait
   en 14 px gris : l'etiquette pesait plus lourd que la cible. La hierarchie est
   rendue a l'endroit. */
.minisite-pager__label {
    font-size: var(--font-size-xs);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--color-text-light);
}

/* Deux lignes au plus, puis points de suspension : un intitule de communication
   peut faire une phrase entiere, et sans borne les deux cartes prennent des
   hauteurs differentes. */
.minisite-pager__title {
    font-family: var(--font-title);
    font-size: var(--font-size-md);
    font-weight: 600;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

.minisite-pager__link:hover .minisite-pager__title,
.minisite-pager__link:focus-visible .minisite-pager__title {
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

/* ── LE RANG ──
   « 4 sur 57 » rendait en 12 px gris, cale en HAUT de la rangee, entre deux
   cartes et sans rien a quoi s'aligner : il etait la premiere chose qu'on
   cherche et la derniere qu'on voit. Meme grammaire que les reperes du rail —
   le nombre en fonte de donnees, son intitule en dessous — dans une pastille
   qui lui donne un cadre. */
.minisite-pager__position {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    align-self: center;
    gap: var(--spacing-2xs);
    margin: 0;
    padding: var(--spacing-sm) var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--surface-4);
    white-space: nowrap;
}

.minisite-pager__position-value {
    font-family: var(--font-data);
    font-size: var(--font-size-lg);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.minisite-pager__position-label {
    font-size: var(--font-size-xs);
    line-height: var(--line-height-tight);
    color: var(--color-text-light);
}

/* La piste de gauche est reservee meme vide : sans elle, la carte suivante
   glisse au centre au lieu de rester a droite. Sous le palier il n'y a qu'une
   piste, donc rien a reserver — une boite vide y couterait une rangee. */
.minisite-pager__spacer {
    display: none;
}

@media (width >= 48em) {
    .minisite-pager__spacer {
        display: block;
    }
}

/* ── SOUS LE PALIER, LES TROIS BLOCS SE RANGENT COMME UNE PILE ──
   La colonne unique rendait deux defauts que la rangee cachait :

   · la carte suivante gardait son sens inverse. Alignee a droite sous une carte
     alignee a gauche, l'inversion ne disait plus le sens de lecture — la place
     dans la grille ne le portait plus — elle passait pour une erreur ;
   · le rang s'etirait sur toute la largeur, en deux lignes. Une pastille de
     332 px de large pour dire « 4 sur 57 » pese plus lourd que les cartes
     qu'elle separe. Elle se ramasse au centre, sur une seule ligne. */
@media (width < 48em) {
    .minisite-pager__link--next {
        flex-direction: row;
        text-align: left;
    }

    .minisite-pager__position {
        flex-direction: row;
        align-items: baseline;
        justify-self: center;
        gap: var(--spacing-xs);
        padding: var(--spacing-2xs) var(--spacing-md);
    }
}

