/* @grammaire v2
   ══════════════════════════════════════════════════════════════
   Event List — Liste des événements
   ══════════════════════════════════════════════════════════════

   ── CE QUE LA DECLARATION `v2` ENGAGE ──────────────────────────
   `node tools/css-grammar.mjs` refuse desormais sur cette feuille : un
   litteral de couleur dans une propriete, un `var()` orphelin (graphe des
   replis suivi), un pendant `max-width` a decimale.

   Etat au 2026-08-30, jour du passage : 157 litteraux, ramenes a ZERO en
   propriete. Ce qui reste sont des DECLARATIONS de jetons, ce que la grammaire
   autorise — declarer une couleur n'est pas la recopier.

   Les quatre familles, et ce qu'elles ont appris :

   1. LE BLANC SUR APLAT SOMBRE, 89 occurrences a lui seul. Le releve a
      l'echelle du depot donne 171 occurrences dans 27 feuilles pour
      QUARANTE-HUIT valeurs d'alpha distinctes. On ne decide pas quarante-huit
      fois de la lisibilite d'une legende sur du marine. D'ou l'echelle
      `--ink-on-dark*` / `--rule-on-dark` / `--veil-on-dark`, posee dans
      `root.css` parce que le motif n'a rien de propre a l'evenement.
   2. LES OMBRES, quinze valeurs pour trois paliers deja nommes
      (`--shadow-sm/md/lg`).
   3. LES REPLIS MORTS : `var(--color-bg-light, #f8f8f8)` et consorts. Le jeton
      existe et vaut autre chose que son repli — le repli est donc une seconde
      valeur qui n'attend qu'une regression du build pour s'appliquer.
   4. LES TEINTES D'ETAT, declarees plus bas plutot que rebranchees sur la
      marque : ce sont des couleurs de CONTRASTE (7:1 a 9:1), quand les jetons
      de callout sont des couleurs d'IDENTITE. Les echanger changerait la
      lisibilite de dix pastilles, ce qui est une decision produit.
   ══════════════════════════════════════════════════════════════ */

.event-list {
    padding: var(--spacing-xl) 0 var(--spacing-3xl);
}

.event-list__header {
    margin-bottom: var(--spacing-lg);
}

.event-list__title {
    font-size: var(--font-size-2xl);
    font-weight: 300;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

@media (min-width: 40em) {
    .event-list__title { font-size: var(--font-size-3xl); }
}

.event-list__subtitle {
    margin-top: var(--spacing-xs);
    color: var(--color-text-light);
}

/* Onglets */
.event-list__tabs {
    display: flex;
    gap: var(--spacing-xs);
    margin-bottom: var(--spacing-xl);
    border-bottom: 2px solid var(--color-border);
}

.event-list__tab {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    padding: var(--spacing-sm) var(--spacing-lg);
    margin-bottom: -2px;
    font-size: var(--font-size-sm);
    font-weight: 500;
    text-decoration: none;
    color: var(--color-text-light);
    border-bottom: 2px solid transparent;
    transition: color 0.15s ease, border-color 0.15s ease;
}

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

.event-list__tab--active {
    color: var(--color-primary);
    border-bottom-color: var(--color-primary);
    font-weight: 600;
}

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

.event-list__tab--active .event-list__tab-count {
    background: var(--color-primary);
    color: var(--ink-on-dark);
}

.event-list__grid {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

.event-list__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-3xl) var(--spacing-md);
    color: var(--color-text-light);
    text-align: center;
}

.event-list__empty svg { opacity: 0.4; }

/* ══════════════════════════════════════════════════════════════
   Event Card — Card liste (reprise du style agenda homepage)
   ══════════════════════════════════════════════════════════════ */

.event-card {
    background: var(--surface-2);
    border-radius: var(--radius-md);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: box-shadow 0.2s ease;
}

.event-card:hover {
    box-shadow: var(--shadow-md);
}

.event-card__link {
    display: flex;
    align-items: stretch;
    text-decoration: none;
    color: inherit;
}

/* Date column */
.event-card__date {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    min-width: 5rem;
    padding: var(--spacing-md);
    background: var(--color-primary);
    color: var(--ink-on-dark);
}

.event-card__date--partner { background: var(--evt-state-partner); }

.event-card__date-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1;
}

.event-card__day {
    font-size: var(--font-size-xl);
    font-weight: 700;
}

.event-card__month {
    font-size: var(--font-size-xs);
    font-weight: 600;
    opacity: 0.85;
}

.event-card__date-arrow {
    opacity: 0.6;
}

.event-card__year {
    font-size: 0.625rem;
    opacity: 0.6;
    margin-top: 0.125rem;
}

/* Body */
.event-card__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: var(--spacing-md) var(--spacing-lg);
    min-width: 0;
}

.event-card__tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
    margin-bottom: var(--spacing-xs);
}

.event-card__type-badge {
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--color-primary);
}

.event-card__format-badge {
    font-size: 0.625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.0625rem 0.375rem;
    border-radius: var(--radius-sm);
    background: var(--color-bg-light);
    color: var(--color-text-light);
}

.event-card__format-badge--online { background: var(--evt-state-ok-bg); color: var(--evt-state-ok-ink); }
.event-card__format-badge--hybrid { background: var(--evt-state-warn-bg); color: var(--evt-state-warn-ink); }

.event-card__organizer {
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.event-card__type-badge + .event-card__organizer::before,
.event-card__format-badge + .event-card__organizer::before {
    content: '·';
    margin-right: var(--spacing-xs);
}

.event-card__title {
    font-size: var(--font-size-base);
    font-weight: 600;
    line-height: var(--line-height-tight);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

@media (min-width: 40em) {
    .event-card__title { font-size: var(--font-size-lg); }
}

.event-card__excerpt {
    margin-top: var(--spacing-xs);
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.event-card__meta {
    margin-top: auto;
    padding-top: var(--spacing-sm);
}

.event-card__location {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.event-card__arrow {
    flex-shrink: 0;
    align-self: center;
    color: var(--color-border);
    margin-right: var(--spacing-md);
    transition: color 0.15s ease, transform 0.15s ease;
}

.event-card:hover .event-card__arrow {
    color: var(--color-primary);
    transform: translateX(2px);
}

/* ══════════════════════════════════════════════════════════════
   Event Show — Détail simple événement
   ══════════════════════════════════════════════════════════════ */

.event-show {
    padding: var(--spacing-xl) 0 var(--spacing-3xl);
}

.event-show__container {
    max-width: 56rem;
    margin: 0 auto;
    padding: 0 var(--spacing-md);
}

.event-show__header {
    padding-bottom: var(--spacing-xl);
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--spacing-xl);
}

.event-show__badges {
    display: flex;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
}

.event-show__type-badge {
    display: inline-flex;
    padding: 0.1875rem 0.625rem;
    border-radius: 100px;
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    background: var(--color-primary-light);
    color: var(--color-primary);
}

.event-show__format-badge {
    display: inline-flex;
    padding: 0.1875rem 0.625rem;
    border-radius: 100px;
    font-size: var(--font-size-xs);
    font-weight: 600;
    background: var(--color-bg-light);
    color: var(--color-text-light);
}

.event-show__title {
    font-size: var(--font-size-2xl);
    font-weight: 700;
    line-height: var(--line-height-tight);
    margin-bottom: var(--spacing-lg);
}

@media (min-width: 40em) {
    .event-show__title { font-size: var(--font-size-3xl); }
}

.event-show__key-info {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.event-show__info-item {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.event-show__info-item svg { flex-shrink: 0; color: var(--color-primary); }

.event-show__cta {
    margin-top: var(--spacing-lg);
}

.event-show__register-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: 0.625rem 1.5rem;
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-decoration: none;
    color: var(--ink-on-dark);
    background: var(--color-primary);
    transition: background-color 0.15s ease;
}

.event-show__register-btn:hover { background: var(--color-primary-dark); }

.event-show__description {
    font-size: var(--font-size-lg);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
    margin-bottom: var(--spacing-xl);
}

.event-show__section-title {
    font-size: var(--font-size-lg);
    font-weight: 600;
    margin-bottom: var(--spacing-md);
}

.event-show__venue {
    margin-top: var(--spacing-xl);
    padding-top: var(--spacing-xl);
    border-top: 1px solid var(--color-border);
}

.event-show__venue-card {
    padding: var(--spacing-md) var(--spacing-lg);
    background: var(--color-bg-light);
    border-radius: var(--radius-md);
}

.event-show__venue-name { font-weight: 600; }
.event-show__venue-address { font-size: var(--font-size-sm); color: var(--color-text-light); margin-top: var(--spacing-xs); }

.event-show__footer {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    margin-top: var(--spacing-xl);
    padding-top: var(--spacing-xl);
    border-top: 1px solid var(--color-border);
}

.event-show__share-label { font-size: var(--font-size-sm); font-weight: 600; color: var(--color-text-light); }
.event-show__share-links { display: flex; gap: var(--spacing-sm); }

/* ══════════════════════════════════════════════════════════════
   Event Minisite — Layout, navigation, pages
   ══════════════════════════════════════════════════════════════ */

/* ── Jetons du minisite ───────────────────────────────────────────
   Une seule couche de jetons, lue par TOUTES les pages du minisite. Elle
   n'invente aucune couleur : chaque valeur pointe un jeton de marque de
   `app.css`. La maquette de refonte proposait sa propre palette (#1E3A5F,
   #2E4079, #C8262C, #A3B516) ; elle se superpose a un ou deux points pres a
   celle de l'ANCESU, et c'est cette derniere qui fait foi — un minisite
   d'evenement appartient au site, il n'a pas sa marque a lui.

     maquette   ->  jeton ANCESU
     #1E3A5F        --color-primary-dark  var(--color-primary-dark)  (aplats : hero, pied)
     #2E4079        --color-primary       var(--color-primary)  (bleu roy : liens, chiffres)
     #C8262C        --color-section-colloques var(--color-callout-danger) (appels a l'action)
     #A3B516        --color-section-ancesu    var(--color-callout-success) (trait signature)

   La police de titrage reste celle de la marque (Barlow depuis la v2) : la maquette
   propose Poppins, qui n'est chargee nulle part sur le site et ferait du
   minisite la seule page a telecharger une fonte supplementaire. */
.minisite {
    /* Aplats et surfaces */
    --evt-ink: var(--color-primary-dark);
    --evt-blue: var(--color-primary);
    --evt-cta: var(--color-section-colloques);
    --evt-cta-hover: #a81e23;
    --evt-signature: var(--color-section-ancesu);
    /* Vert eclairci pour le texte pose SUR l'aplat marine : le vert de marque
       y rend 2,4:1. Celui-ci rend 6,1:1 sur --color-primary-dark. */
    --evt-signature-on-dark: #c8d94a;

    /* Ambre du sous-titre sur l'aplat marine du hero, valeur de la maquette.
       Le rouge de rubrique rend 3,2:1 sur ce fond, l'ambre 8,4:1. */
    --evt-hero-subtitle: #f5c069;

    /* Le degrade qui fond l'affiche vers le marine. Le dernier palier est le
       marine PLEIN : sans lui, la jonction entre le bas de l'image et le corps
       de la carte se voit comme une couture.

       Les paliers de la maquette (0,55 a 46 % ; 0,94 a 82 %) ont ete REMONTES,
       et la mesure dit pourquoi. Le texte remonte de 190 px sur une image haute
       de 420 : il couvre donc l'image a partir de 55 %, la ou le degrade de la
       maquette ne vaut encore que 0,63. Le placeholder de la maquette etant un
       hachure neutre, la difference ne s'y voyait pas ; nos affiches, elles,
       portent leur PROPRE titre en tres grand — on lisait « Lumiere sur la
       pedagogie » deux fois, l'un derriere l'autre.

       Opaque des 62 %, le degrade laisse voir l'affiche sur toute sa moitie
       haute et rend au titre un fond plein. */
    /* Texture diagonale du fond, exploration 1b. Un marine plein est plat sur
       une carte de cette taille ; les deux teintes sont a un cheveu l'une de
       l'autre, donc on lit une matiere, pas des rayures. */
    --evt-hero-texture: repeating-linear-gradient(
        135deg,
        #22345e,
        #22345e 12px,
        #1e2f56 12px,
        #1e2f56 24px
    );

    /* Halo ambre, sous le coin bas gauche. Un DEGRADE et non un aplat : a
       bord franc, 14 % d'ambre sur le marine donnent rgb(60,63,78), c'est-a-dire
       un disque GRIS parfaitement decoupe — on lit une tache, pas une lumiere,
       et la mention de tarif tombe dessus. Le degre monte a 22 % au centre
       puisque le fondu fait chuter la moyenne. */
    --evt-hero-glow: radial-gradient(
        closest-side circle,
        color-mix(in srgb, var(--color-section-formations) 22%, transparent) 0%,
        transparent 100%
    );

    /* ── Les surfaces viennent de la grammaire v2, elles ne sont plus
       redeclarees ici ──
       Le minisite s'etait bati une echelle de surfaces PARALLELE a celle du
       site (`#fff`, `#e4e8f2`, `#edf0f6`), a l'epoque ou son contenu se lisait
       sur une etendue bleue et n'avait donc rien a accorder avec le reste. Le
       resultat, mesure a la relecture des maquettes du 2026-08-30 : le meme
       filet valait `#e4e8f2` ici et `--color-border` (`#dadee2`) partout
       ailleurs, et l'ecart se voit des qu'une carte du minisite en cotoie une
       du site.

       Les quatre surfaces v2 (`root.css`) portent exactement ce que la
       maquette demande — plateau `--color-canvas`, carte `--surface-2`, rappel
       de contexte `--surface-3` sans bordure, incise `--surface-4` — et UNE
       seule ombre. Les jetons `--evt-*` restent, comme noms locaux : ils
       disent le ROLE dans le minisite, la valeur vient du site. */
    --evt-surface: var(--surface-2);
    --evt-surface-veil: var(--surface-3);
    --evt-surface-muted: var(--surface-4);
    --evt-rule: var(--color-border);
    --evt-rule-soft: color-mix(in srgb, var(--color-border) 55%, var(--surface-2));

    /* Rythme. La maquette borne ses sections en clamp ; on garde le meme
       principe pour que le minisite respire pareil du telephone au grand
       ecran, sans multiplier les points de rupture. */
    /* Moitie de la respiration voulue entre deux sections : elle est portee
       des deux cotes, donc elle se somme d'une section a l'autre. */
    --evt-section-y: clamp(1.5rem, 2.6vw, 2.5rem);
    --evt-gap: clamp(1.75rem, 4vw, 3.25rem);
    /* Les rayons de la maquette sont ceux de la charte : 14 px pour une carte
       interieure, 16 pour une carte de premier plan, la pastille pour les
       commandes. Le minisite en portait deux a lui (8 et 10 px), assez proches
       pour passer inapercus isolement et assez differents pour que ses cartes
       aient l'air taillees plus dur que celles du site. */
    /* ── LES TEINTES D'ETAT ────────────────────────────────────
       Pastilles de format (en ligne, hybride) et de statut d'une soumission.
       Ce sont des couleurs de la palette Material, calees pour leur CONTRASTE
       sur fond clair — 7:1 a 9:1 — la ou les jetons de callout de la marque
       sont des couleurs d'IDENTITE : l'olive `--color-callout-success` rend
       2,1:1 en texte, il ne peut pas porter un libelle.

       Elles sont DECLAREES ici plutot que recopiees : chacune servait a deux
       endroits (une pastille de format et un statut de soumission), donc
       divergerait au premier ajustement. Les rebrancher sur la marque
       changerait le contraste de dix pastilles, ce qui est une decision
       produit — pas un effet de bord de migration. */
    --evt-state-ok-bg: #e8f5e9;
    --evt-state-ok-ink: #2e7d32;
    --evt-state-warn-bg: #fff3e0;
    --evt-state-warn-ink: #e65100;
    --evt-state-info-bg: #e3f2fd;
    --evt-state-info-ink: #1565c0;
    --evt-state-off-bg: #f5f5f5;
    --evt-state-off-ink: #757575;
    --evt-state-ko-bg: #ffebee;
    --evt-state-partner: #16a34a;

    /* Teintes de l'echeance : un ambre d'alerte, puis un ambre d'urgence.
       Declarees pour la meme raison — chacune servait a deux regles. */
    --evt-deadline-bg: #fdf4e3;
    --evt-deadline-ink: #8a6410;
    --evt-deadline-urgent-bg: #fffbeb;
    --evt-deadline-urgent-rule: #f4e3bd;
    --evt-deadline-urgent-ink: #6b4e16;

    /* Deux gris de texte sur aplat, hors echelle `--ink-on-dark` parce qu'ils
       sont TEINTES et non du blanc attenue : un bleu-gris sur marine, un
       brun-gris sur l'ambre de l'echeance. */
    --evt-ink-on-navy-soft: #a7b1d2;
    --evt-ink-on-navy-faint: #b6bfcc;
    --evt-ink-on-amber: #5b4144;

    /* Le voile de lecture pose sur une image a REJOINT LA GRAMMAIRE
       (`--scrim-bottom`, dans `root.css`) : il existait ici et dans la carte de
       tete des listes, avec le meme arret a 42 % de part et d'autre. Son encre
       y est reprise a l'identique, donc rien ne change a l'ecran.
       Reste l'ombre de relief, propre a cette zone. */
    --evt-lift: rgb(27 46 90 / 0.45);
    --evt-lift-strong: rgb(27 46 90 / 0.6);
    --evt-tint: #eef1f9;
    --evt-tint-cool: #dfe5f3;
    /* Voile de la visionneuse plein ecran : un noir quasi opaque, et c'est
       voulu — sous une photo, un voile teinte de marine deteint sur l'image. */

    --evt-radius: var(--radius-md);
    --evt-radius-lg: var(--radius-lg);
    --evt-shadow: var(--shadow-card);

    /* Hauteur du bloc de tete collant : barre du haut (3rem, `position: fixed`)
       plus barre d'evenement (66 px, deux lignes d'identite plus son filet),
       soit 114 px. La valeur est volontairement 2 px EN DESSOUS : une barre
       collante calee 6 px trop bas laissait voir le programme defiler dans
       l'interstice, entre la navigation et les filtres. Mieux vaut un
       chevauchement de deux pixels — les deux barres ont un fond blanc, il ne
       se voit pas — qu'une fente ou passe le contenu. */
    --minisite-chrome-h: 7rem;

    /* Hauteur COMMUNE a tous les controles d'une barre : pastille de jour,
       etiquette de filtre, bouton d'action. Ils etaient a 61, 44 et 36 px dans
       la meme rangee — trois hauteurs pour trois objets qui se lisent comme
       une seule famille de commandes. 44 px est aussi la cible tactile
       minimale. */
    --evt-control-h: 2.75rem;

    /* Colonne de LECTURE, distincte de la largeur de page. Le hero, le
       programme et les grilles profitent des 1240 px ; le texte courant,
       lui, reste sous la centaine de caracteres par ligne. */
    --evt-measure: 62ch;
}

/* ── Primitives partagees ─────────────────────────────────────────
   La maquette repose sur une grammaire courte, repetee de page en page :
   une section porte un NUMERO en vert, un titre, un trait signature, puis
   son contenu. Le tout est declare ici une fois — sept pages le reutilisent,
   et une correction se paie une seule fois. */
/* ── Rythme vertical ──
   Rembourrage SYMETRIQUE, et une valeur calee pour que la SOMME de deux
   sections voisines fasse la respiration voulue (~88 px), pas le double.

   Deux modeles ont ete essayes et ecartes :
   - rembourrage haut ET bas a pleine valeur : les deux s'additionnaient,
     150 px de blanc entre deux blocs, qu'on lit comme la fin de la page ;
   - rembourrage HAUT seul : la section qui suivait un fond teinte demarrait
     alors au ras de l'aplat, sans respiration, et le blanc se retrouvait
     entierement du mauvais cote.

   Symetrique, l'ecart est le meme partout, teinte ou non, et la moitie de
   l'espace tombe a l'interieur de l'aplat — ce qui est precisement ce qu'on
   veut d'une bande de couleur. */
.evt-section {
    padding-block: var(--evt-section-y);
}

/* Sans rembourrage bas, la marge du DERNIER element d'un contenu editorial
   s'echappe de la section (fusion des marges) et va se poser entre les deux
   sections : l'aplat teinte de la suivante commencait 48 px plus bas que
   prevu, et l'ecart n'etait le meme sur aucune page — il dependait du dernier
   bloc saisi en administration. */
.evt-section .prose-content > :last-child {
    margin-bottom: 0;
}

/* Variante resserree : elle suit un bloc dont elle est le prolongement (les
   chiffres-cles sous le hero, l'appel a l'action apres la derniere section).
   Elle garde tout de meme une respiration EN HAUT : a zero, les cartes de
   chiffres venaient se coller au bord de l'aplat du hero, et les deux se
   lisaient comme un seul bloc mal decoupe. */
/* Variante resserree EN HAUT : la section prolonge le bloc qui la precede
   (les chiffres-cles sous le hero, l'appel a l'action apres la derniere
   section). Le bas garde le rythme commun. */
/* Corps d'une page interieure du minisite : la colonne bornee et son
   rembourrage vertical. Il vivait en utilitaires repetes dans NEUF
   gabarits (`container py-8 sm:py-12`) — donc neuf endroits a reprendre
   pour changer une respiration, et un palier (`sm:`) qui n'appartenait a
   aucune echelle du site. */
.evt-page-body {
    padding-block: var(--spacing-xl);
}

@media (min-width: 40em) {
    .evt-page-body {
        padding-block: var(--spacing-2xl);
    }
}

/* ── LA COLONNE LATERALE DES PAGES INTERIEURES ───────────────────────────
   Maquette « Pages minisite » : le contenu a gauche, une colonne de service a
   droite. Elle n'est pas un ornement — les pages interieures du minisite
   s'ouvrent souvent par un lien direct (recherche, partage, courriel), donc
   sans avoir vu l'accueil, et rien n'y disait ni quand, ni ou, ni comment
   s'inscrire.

   UNE GRILLE NE MARCHE PAS ICI, et l'essai a coute une mesure. En placant
   l'aside en colonne 2 rangee 1 et tout le reste en colonne 1, on evite le
   conteneur d'emballage — mais la RANGEE 1 prend alors la hauteur de son plus
   grand element, c'est-a-dire la carte. Sur la page de rediffusions, le chapo
   se retrouvait seul en haut d'une rangee de 275 px, suivi de 250 px de vide
   avant le champ de recherche. Aucun reglage de `gap` n'y change quoi que ce
   soit : c'est la hauteur de la RANGEE qui est en cause, et un element de
   grille ne peut pas s'en abstraire.

   Une rangee flex de deux elements n'a pas ce probleme : chacun prend la
   hauteur de son propre contenu. Le prix est un conteneur d'emballage dans le
   gabarit — deux lignes, sans reindenter le contenu, l'indentation n'ayant
   aucun effet en HTML.

   `999` en facteur de croissance : le contenu absorbe TOUTE la largeur libre,
   la carte reste a sa base de 17rem. Ecrit `1 1`, les deux se partageaient le
   surplus a parts egales et la carte finissait a la moitie de la page.

   Sous la largeur ou les deux bases ne tiennent plus, la rangee se replie :
   l'aside tombe APRES le contenu — ce que prescrit la maquette « Vues
   mobiles », ou la colonne laterale disparait et le contexte remonte en fin
   d'article. Aucun palier a declarer, c'est le repli qui decide. */
.evt-page-body--with-aside {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--evt-gap);
}

.evt-page-body--with-aside > .evt-page-main {
    order: 1;
    flex: 999 1 28rem;
    min-width: 0;
}

.evt-page-body--with-aside > .evt-page-aside {
    order: 2;
    flex: 1 1 17rem;
}

/* Collante seulement quand elle est A COTE du contenu : repliee sous lui, elle
   n'a plus rien a accompagner. Le palier vaut la somme des deux bases plus la
   gouttiere — au-dessous, le repli a deja eu lieu. */
@media (min-width: 64em) {
    .evt-page-body--with-aside > .evt-page-aside {
        position: sticky;
        top: calc(var(--minisite-chrome-h, 7rem) + 1.5rem);
    }
}

/* ── LA COLONNE DE COMMANDES DU PROGRAMME ────────────────────────────────
   Maquette « Pages minisite ». Elle porte le meme bloc que la barre collante
   d'hier — jour, type, compteur, filtres, telecharger, imprimer — SANS le
   rendre une seconde fois : c'est la mise en page qui bouge, pas le balisage.

   SOUS 64em, RIEN NE CHANGE. `order: 0` et une base pleine largeur ramenent le
   bloc au-dessus du deroule, ou il redevient exactement la barre
   d'aujourd'hui. C'est voulu, et c'est mesure : une session precedente a
   consolide TROIS rangees en une et rendu la barre collante parce que, sur
   vingt-six creneaux, changer de jour depuis le milieu de la page est le geste
   le plus frequent. Une colonne laterale repliee EN BAS du document sur
   telephone perdrait exactement cela. Au bureau la colonne est collante, donc
   la propriete est conservee. */
.programme__aside {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

/* Au bureau, la colonne devient une CARTE. Sans elle, les pastilles de jour,
   les etiquettes de type et les deux actions flottaient sur le fond de page,
   sans rien qui dise qu'elles forment un seul organe — c'est la barre qui
   jouait ce role, et elle n'existe plus a cette largeur. */
@media (min-width: 64em) {
    .programme__aside {
        padding: var(--spacing-md);
        background: var(--evt-surface);
        border: 1px solid var(--evt-rule);
        border-radius: var(--evt-radius);
    }
}

@media (width < 64em) {
    .programme .evt-page-body--with-aside {
        /* La rangee flex se replie deja seule sous ce palier ; l'ordre force
           le bloc de commandes AVANT le deroule, la ou le repli naturel le
           mettrait apres. */
        flex-wrap: wrap;
    }

    /* SELECTEUR ENFANT, et ce n'est pas du style. La regle de la colonne
       (`.evt-page-body--with-aside > .evt-page-aside`) pose `order: 2` a
       (0,2,0) ; `.programme__aside` seul vaut (0,1,0) et PERD. Mesure : a
       390 px, le bloc de commandes tombait a y=2486, c'est-a-dire tout en bas
       du document, apres le deroule — donc introuvable sur la page ou il sert
       le plus. Rien ne le signalait : il etait dans le DOM, visible, et
       simplement ailleurs. Troisieme collision de specificite de la session,
       toutes sur le meme axe. */
    /* `min-width: 0` : sans lui, un element de flex ne peut pas descendre sous
       la largeur de son CONTENU — `min-width` vaut `auto` par defaut sur un
       enfant de flex, et `flex-basis: 100%` n'y change rien. Mesure a 390 px :
       la rangee de pastilles de jour fait 470 px, la colonne refusait donc de
       passer sous 470, et le document entier debordait de 92 px.

       Le symptome trompe : on cherche une largeur imposee quelque part, il n'y
       en a aucune. C'est une valeur PAR DEFAUT qui empeche le retrecissement. */
    .evt-page-body--with-aside > .programme__aside {
        order: 0;
        flex: 1 1 100%;
        min-width: 0;
    }

    .evt-page-body--with-aside > .evt-page-main {
        order: 1;
        flex: 1 1 100%;
        min-width: 0;
    }
}

/* Au bureau, les commandes s'empilent : la rangee horizontale de la barre
   n'a plus 1 200 px mais 272. Les pastilles de jour passent donc en colonne,
   et les deux actions partagent une ligne. */
@media (min-width: 64em) {
    .programme__aside .programme__header {
        position: static;
        padding-block: 0;
        margin-bottom: 0;
        border-bottom: 0;
        background: transparent;
    }

    .programme__aside .programme__title-row,
    .programme__aside .programme__days,
    .programme__aside .programme__typebar {
        flex-direction: column;
        align-items: stretch;
        gap: var(--spacing-sm);
    }

    /* L'ORDRE DE LA BARRE NE VAUT PAS EN COLONNE. La barre horizontale
       impose `order` — jour et actions d'abord, filtres et compteur ensuite —
       parce que c'est l'ordre de sacrifice quand elle se replie. Empile, cet
       ordre glissait les deux boutons ENTRE l'intitule « Type de seance » et
       les etiquettes qu'il annonce : le libelle designait Telecharger et
       Imprimer. On rend donc la main a l'ordre du DOM, et les actions passent
       en dernier — ce ne sont pas des filtres.

       TROIS SELECTEURS, et c'est ce qu'il faut : ecrits
       `.programme__aside .programme__typebar` (0,2,0), ils sont a EGALITE avec
       `.programme__title-row .programme__typebar`, qui vit huit cents lignes
       plus bas. A specificite egale, l'ordre tranche, et le mien perdait — la
       media query correspondait, la regle etait dans le fichier servi, et
       l'ordre calcule restait l'ancien. Le depot documente ce piege ; je l'ai
       rejoue quand meme, et seule la MESURE de `getComputedStyle().order`
       l'a montre. */
    .programme__aside .programme__title-row .programme__typebar {
        order: 0;
    }

    /* `margin-left: auto` poussait les actions au bord droit de la barre. En
       colonne, il les colle a droite de la carte au lieu de les etirer. */
    .programme__aside .programme__title-row .programme__actions {
        order: 1;
        margin-left: 0;
        flex-direction: row;
        flex-wrap: wrap;
    }

    .programme__aside .programme__action {
        flex: 1 1 auto;
        justify-content: center;
    }

    /* Intitule de groupe. Il n'existait pas dans la barre : a l'horizontale,
       la nature des pastilles se lisait de leur contenu (« Jour 1 », un nom de
       type). Empilees en colonne, deux groupes de pastilles se suivent sans
       rien qui les separe, et l'on ne sait plus lequel filtre quoi. */
    .programme__aside .programme__group-label {
        display: block;
        font-size: var(--font-size-xs);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--color-text-light);
    }
}

/* Sous le palier, la barre retrouve exactement sa forme d'hier : les
   intitules de groupe n'y ont pas leur place, elle est horizontale. */
@media (width < 64em) {
    .programme__group-label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

/* ── La carte de service ──
   Un bandeau colore qui porte l'etat, un corps qui porte les faits et le
   geste. Le bandeau change de teinte selon l'etat, pas de forme : rouge tant
   qu'il reste quelque chose a faire, marine quand il n'y a plus qu'a
   regarder. */
.evt-service {
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    /* Le bandeau porte un aplat jusqu'au bord. */
    overflow: hidden;
}

.evt-service__head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.375rem 0.75rem;
    padding: 1rem 1.125rem;
    background: var(--evt-cta);
    /* Le blanc du texte sur aplat de marque a un nom : le poser en litteral
       ici en ferait un 25e dans cette feuille, et un de plus a retrouver le
       jour ou la marque bouge. */
    color: var(--color-on-primary);
}

.evt-service--past .evt-service__head {
    display: block;
    background: var(--color-primary-dark);
}

.evt-service__countdown {
    font-size: 2.25rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.evt-service__when {
    display: flex;
    flex-direction: column;
    gap: 0.1875rem;
    min-width: 0;
}

/* Le sur-titre du bandeau. Il ne peut pas etre `.evt-eyebrow` : celui-ci est
   pose en bleu roy, illisible sur l'aplat rouge. Meme graisse, meme chasse,
   meme approche — seule la couleur change, et elle est HERITEE du bandeau, ce
   qui la rend juste dans les deux etats sans une regle de plus. */
.evt-service__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: var(--font-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: inherit;
    opacity: 0.82;
}

.evt-service__dates {
    font-size: var(--font-size-sm);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.evt-service__name {
    margin: 0.5rem 0 0;
    font-size: var(--font-size-lg);
    font-weight: 700;
    line-height: 1.2;
}

.evt-service__figures {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem 1.375rem;
    margin-top: 0.75rem;
}

.evt-service__figure {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.evt-service__figure-value {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1;
}

.evt-service__figure-label {
    /* Bornee a treize caracteres, comme la maquette : au-dela, deux chiffres
       cote a cote se disputent la largeur et le second passe sous le premier. */
    max-width: 13ch;
    font-size: var(--font-size-xs);
    line-height: 1.35;
    opacity: 0.78;
}

.evt-service__body {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    padding: 1rem 1.125rem 1.125rem;
}

/* Le bouton prend toute la largeur de la carte : c'est le seul geste qu'elle
   propose, il n'a rien avec quoi partager sa ligne. */
.evt-service__cta {
    justify-content: center;
    width: 100%;
    min-height: var(--touch-target-min);
}

/* Chapo d'une page interieure : la phrase qui suit le titre. */
.evt-page-lead {
    max-width: var(--evt-measure);
    font-size: var(--font-size-lg);
    line-height: 1.7;
    color: var(--color-text-light);
}

/* Blocs qui se succedent dans le corps d'une page interieure. */
.evt-page-block {
    margin-top: var(--spacing-xl);
}

.evt-page-block--loose {
    margin-top: var(--spacing-2xl);
}

.evt-section--tight {
    padding-top: clamp(1rem, 2.2vw, 1.75rem);
}

/* ── L'EN-TETE DE SECTION : UN FILET, UN SUR-TITRE, UN TITRE ───────
   Il s'ouvrait sur un NUMERO en vert (« 01 Le theme »). Deux objections, et
   la seconde compte plus que la premiere :

   1. le numero ne dit rien. Il annonce un rang dans une liste que le lecteur
      ne parcourt pas dans l'ordre — on arrive sur l'accueil d'un minisite par
      un partage, on y cherche une date ou un tarif ;
   2. aucune autre page du site ne numerote ses sections. La grammaire
      publique ouvre par un SUR-TITRE qui dit de quoi la section parle
      (`_section_header`), et c'est ce que reprend la maquette : « Heure par
      heure » au-dessus de « Programme », « Sur place » au-dessus de « Infos
      pratiques ». Le sur-titre porte une information, le numero portait un
      compte.

   Le filet haut remplace l'alternance de fonds teintes qui separait les
   sections. Sur le plateau, cette alternance redecoupait la page en bandes
   pleine largeur ; un trait de deux pixels suffit a dire « nouvelle section »
   sans ajouter de surface. */
.evt-section__head {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: baseline;
    margin-bottom: 0.5rem;
    /* PLUS DE FILET AU-DESSUS. Il tirait un trait plein d'un bord a l'autre
       devant chaque intitule : sur une page qui compte cinq sections, cinq
       traits horizontaux decoupent la lecture en tranches et font lire des
       blocs sans rapport la ou il y a une seule page. C'est le rythme vertical
       qui separe les sections, pas un trait — et il le fait sans rien ajouter
       a l'ecran. */
}

/* `flex: 1 0 100%` lui donne sa propre ligne, au-dessus du titre, sans que le
   gabarit ait a envelopper les deux dans un bloc de plus : le titre et le lien
   de rebond se partagent la ligne suivante, exactement comme avant. */
.evt-section__kicker {
    flex: 1 0 100%;
    font-size: var(--font-size-xs);
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

/* Lien de rebond pose sur la ligne du titre, contre le bord droit. Sur la
   ligne de base du titre, pas au milieu de sa boite : les deux textes se
   lisent alors sur le meme rail. */
.evt-section__aside-link {
    margin-left: auto;
}

.evt-section__title {
    margin: 0;
    font-size: clamp(1.4rem, 2.8vw, 2rem);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.01em;
    color: var(--evt-ink);
}

/* Trait signature. Il porte l'identite de l'evenement partout ou un aplat
   ne peut pas le faire, et il remplace la pastille de section : un trait ne
   se lit pas comme un objet cliquable. */
/* Arrondi, comme le trait de la fiche evenement dont il reprend le role : sur
   un site ou tout le reste est en coins adoucis, un rectangle a angles vifs se
   remarque pour de mauvaises raisons. */
.evt-rule {
    width: 3rem;
    height: 0.25rem;
    border-radius: var(--radius-pill);
    /* ── La couleur du trait se DECLARE, elle n'est plus figee ─────
       Il etait toujours vert de marque. Sur le plateau, cinq sections d'affilee
       ouvertes par le meme trait vert font une page qui se repete ; la maquette
       change d'accent d'une section a l'autre (rouge, orange, olive, bleu
       ciel), ce qui donne un reperage visuel au defilement.

       Le repli est le rouge de la rubrique « colloques », c'est-a-dire la
       couleur que portent deja les filets des onglets juste au-dessus : une
       section qui ne declare rien reste donc accordee a sa barre. */
    background: var(--evt-rule-color, var(--evt-cta));
    margin-bottom: 1.375rem;
}

.evt-rule--lg {
    width: 3.5rem;
}

/* Sur aplat marine, le vert de marque passe sous le seuil : variante
   eclaircie. Meme trait, meme role. */
.evt-panel .evt-rule {
    background: var(--evt-signature-on-dark);
}

/* Le sur-titre `.evt-eyebrow` a ete retire le 2026-08-31 : les cinq appelants
   du minisite sont passes sur `ui.kicker`, la brique du site. Il en refaisait
   la typographie a l'identique — meme corps, meme graisse, meme interlettrage,
   meme capitales — a une couleur pres, et cette couleur etait justement ce qui
   faisait lire un second titre la ou le site lit une etiquette. */

/* Carte : la surface de base du minisite. Filet 1 px, pas d'ombre — la
   profondeur vient des aplats marine, pas d'un empilement de cartons. */
.evt-card {
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    padding: clamp(1.375rem, 3vw, 1.875rem);
}

/* Variante cliquable : le filet passe au rouge, rien d'autre ne bouge.
   Un deplacement ou une ombre au survol ferait sauter la grille entiere. */
a.evt-card {
    display: block;
    color: inherit;
    transition: border-color var(--transition-fast);
}

a.evt-card:hover,
a.evt-card:focus-visible {
    border-color: var(--evt-cta);
}

.evt-card--muted {
    background: var(--evt-surface-muted);
}

/* Aplat marine : hero, encarts d'appel, pave de contact. */
.evt-panel {
    background: var(--evt-ink);
    color: var(--ink-on-dark);
    border-radius: var(--evt-radius);
    padding: clamp(1.5rem, 3vw, 1.875rem);
}

.evt-panel a:not(.evt-btn) {
    color: var(--ink-on-dark);
}

/* Etiquette de type (« Atelier », « Pleniere »). */
.evt-tag {
    display: inline-block;
    padding: 0.25rem 0.625rem;
    border-radius: var(--radius-sm);
    background: var(--evt-tint);
    color: var(--evt-blue);
    font-size: var(--font-size-xs);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.evt-tag--alert {
    background: var(--evt-deadline-bg);
    color: var(--evt-deadline-ink);
}

/* Les regles `.evt-btn*` ont ete retirees le 2026-08-31 : les douze boutons du
   minisite sont passes sur `ui.button`, la brique du site, qui porte six
   variantes et trois tailles la ou le minisite en refaisait deux.

   Ce que la migration a rendu au passage : `full_width` remplace
   `.evt-btn--block`, qui n'avait plus aucun appelant, et les boutons heritent
   desormais des etats de focus et des cibles tactiles du site — qu'un bouton
   maison doit sinon rejouer, et qu'il finit toujours par rejouer de travers. */

/* Lien d'action en fin de section (« Le programme → »). */
.evt-link {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-weight: 600;
    font-size: var(--font-size-sm);
    color: var(--evt-cta);
}

.evt-link:hover,
.evt-link:focus-visible {
    color: var(--evt-cta-hover);
}

/* Colonne de lecture bornee, a poser sur les paragraphes courants. */
.evt-measure {
    max-width: var(--evt-measure);
}

/* Chapo editorial : la voix intermediaire entre le titre et le corps. */
.evt-lead {
    font-size: clamp(1.0625rem, 1.9vw, 1.3125rem);
    font-weight: 500;
    line-height: 1.5;
    color: var(--evt-blue);
    max-width: 54ch;
}

.evt-panel .evt-lead {
    color: var(--ink-on-dark-soft);
    font-weight: 400;
}

/* Deux colonnes : corps a gauche, panneau lateral collant a droite. Le
   `minmax(0, …)` n'est pas decoratif — sans lui, une grille de sous-cartes
   ou un tableau dans la colonne de gauche l'empeche de descendre sous la
   largeur de son contenu et fait deborder la page. */
.evt-split {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 18.75rem), 1fr));
    gap: var(--evt-gap);
    align-items: start;
}

.evt-split > * {
    min-width: 0;
}

/* La colonne laterale colle SOUS le bloc de tete : barre du haut (3rem,
   `position: fixed`) + barre d'evenement (`sticky` a 3rem). La hauteur de
   cette derniere depend de son contenu, d'ou une variable plutot qu'une
   constante — `--minisite-chrome-h` vaut la somme des deux et se surcharge
   depuis la page si une edition a une barre plus haute. Elle n'est PAS
   mesuree en JavaScript : le collant n'a besoin d'etre juste qu'a quelques
   pixels pres, et une mesure au navigateur ferait dependre la mise en page du
   chargement d'un script. */
.evt-aside {
    display: grid;
    gap: 1rem;
}

@media (min-width: 62em) {
    .evt-aside {
        position: sticky;
        top: calc(var(--minisite-chrome-h, 7rem) + 1.5rem);
    }
}

/* Fil d'Ariane des pages de detail. */
.evt-crumb {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    margin-bottom: 1.5rem;
}

.evt-crumb a {
    color: var(--evt-blue);
}

.evt-crumb a:hover {
    color: var(--evt-cta);
}

.evt-crumb__sep {
    color: var(--evt-ink-on-navy-faint);
    margin-inline: 0.25rem;
}

/* Liste numerotee (objectifs pedagogiques, reglement d'un concours). Le
   numero est en vert et aligne sur la premiere ligne, pas sur le bloc. */
.evt-numbered {
    display: grid;
    gap: 0.75rem;
}

.evt-numbered__row {
    display: grid;
    grid-template-columns: 1.875rem 1fr;
    gap: 0.75rem;
    font-size: var(--font-size-base);
    line-height: 1.7;
    color: var(--color-text-light);
}

.evt-numbered__n {
    font-weight: 700;
    font-size: var(--font-size-sm);
    color: var(--evt-signature);
    padding-top: 0.125rem;
    font-variant-numeric: tabular-nums;
}

/* Bloc de definition d'un panneau lateral : intitule en capitales, valeur
   en dessous. Repete sur toutes les fiches. */
.evt-def {
    display: grid;
    gap: 0.375rem;
}

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

.evt-panel .evt-def__label {
    color: var(--evt-signature-on-dark);
}

.evt-def__value {
    font-size: var(--font-size-base);
    color: var(--color-text);
}

.evt-panel .evt-def__value {
    color: var(--ink-on-dark-soft);
}

/* `position: fixed` (aligné newsletter) : la barre reste visible en
   permanence au scroll, indépendamment du parent `<header>` qui se
   termine quand on entre dans `<main>`. Compensation hauteur via
   padding-top sur `.minisite-header` pour éviter que le hero soit
   masqué au chargement. */
/* ── Un seul bloc en tete : barre, bandeau, onglets ────────────────
   Les trois portent le MEME fond : le degrade de marque, et par-dessus le
   trace d'ondes en `background-attachment: fixed`.

   C'est ce `fixed` qui fait tout le travail. Il ancre l'image sur la FENETRE
   et non sur chaque element : les trois y decoupent donc leur propre fenetre
   dans un seul et meme dessin, qui se poursuit d'un bloc a l'autre sans
   raccord. Aucune autre technique ne le permet ici — la barre du haut est en
   `position: fixed` et les onglets en `sticky`, donc leurs positions relatives
   changent au defilement : des decalages calcules a la main seraient justes au
   repos et faux des le premier pixel de scroll.

   L'image est un FICHIER et non un SVG inline : trois copies d'un dessin de
   23 Ko dans le HTML de chaque page seraient absurdes, et un fond ne se style
   pas depuis la page — le trait, son opacite et son pointille sont donc cuits
   dans le fichier (`assets/images/minisite-waves.svg`). Pour retoucher la
   densite ou la teinte, c'est le fichier qu'on ouvre. */
/* Refonte 2026-08-20 : la barre d'ONGLETS a quitte ce groupe. Elle porte
   desormais l'identite de l'evenement sur fond blanc, et le bloc de tete
   marine se reduit a la barre du haut. Le trace d'ondes reste la ou il y a un
   aplat — barre du haut, hero de l'accueil, pied de page — c'est-a-dire la ou
   il fait une texture et non un fond derriere du texte de navigation. */
/* ── LE PIED DE PAGE EST CLAIR ─────────────────────────────────────
   Quatrieme et dernier aplat marine de l'accueil. Il portait le degrade de
   marque et le trace d'ondes en `background-attachment: fixed`, pour faire
   matiere commune avec la barre du haut et le hero — les deux ayant depuis
   rejoint le plateau, il ne faisait plus continuite avec rien : il fermait la
   page sur un pave sombre isole.

   La maquette pose un pied CLAIR, separe par un simple filet, avec l'embleme
   et le nom en tete puis des colonnes a filet colore. C'est aussi ce que fait
   le pied du site — un minisite d'evenement n'a pas de raison de se terminer
   autrement que les autres pages. */
/* Pas de filet non plus avant le pied de page : il vit deja sur un fond
   distinct de celui du contenu, ce qui suffit a dire ou la page s'arrete. Un
   trait par-dessus un changement de fond dit deux fois la meme chose. */
.minisite-footer {
    color: var(--color-text);
}

/* ── LE SOL DU MINISITE EST LE PLATEAU DU SITE ─────────────────────
   La maquette `Minisite evenement ANCESU.dc.html` pose le minisite sur
   `#eceef0`, c'est-a-dire trait pour trait `--color-canvas` : le plateau que
   toutes les pages v2 du site emploient deja. Ce n'est pas une teinte de plus,
   c'est la fin d'une exception.

   Ce qui s'en va avec, et c'est le vrai sujet : le minisite portait TROIS
   aplats marine pleins sur une meme page — la barre du haut, le hero, le pied.
   Chacun se defendait isolement ; ensemble ils font une page qu'on lit comme
   chargee, parce que rien n'y respire entre deux blocs pleins. La maquette
   n'en garde aucun sur l'accueil : elle pose des cartes claires sur un plateau,
   et reserve le marine aux accents (un chiffre, un en-tete de carte laterale).

   Le degrade et le trace d'ondes restent la ou ils font une TEXTURE derriere
   une image ou un pied de page, jamais derriere du texte de navigation. */
body.minisite {
    background: var(--color-canvas);
}

/* La ligne de service : « Un evenement du reseau des CESU · retour au site ».
   Elle n'est plus une barre — ni fond, ni `position: fixed`, ni hauteur
   imposee. Une barre fixe coutait 3 rem d'ecran en permanence pour un lien de
   retour et trois icones ; la maquette la reduit a une ligne de texte alignee
   a droite, au-dessus de la barre d'evenement, qui defile avec la page.

   Consequence a ne pas manquer : ses commandes de partage etaient habillees
   POUR LE MARINE (translucide sur blanc). Sur le plateau, ces surcharges sont
   retirees plutot que reecrites — les composants partages
   (`share-dropdown-group`, `list-hero__share-buttons`) sont dessines pour un
   fond clair, c'est le minisite qui les depaysait. */
.minisite-header__bar {
    background: transparent;
    color: var(--color-text-light);
}

/* Aligné sur `nl-minisite-header__bar-inner` (newsletter) : ligne flex
   à 3rem de haut, retour à gauche / centre / actions à droite. */
.minisite-header__bar-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 3rem;
}

.minisite-header__back {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: var(--font-size-sm);
    color: var(--color-primary);
    font-weight: 600;
    transition: color 0.15s ease;
}

.minisite-header__back:hover {
    color: var(--color-primary-dark);
}

.minisite-header__info {
    display: none;
    align-items: center;
    gap: 0.5rem;
    padding-inline: 1rem;
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1;
    justify-content: center;
}

@media (min-width: 40em) {
    .minisite-header__info { display: flex; }
}

.minisite-header__title {
    font-weight: 600;
    color: var(--color-text);
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Le détail (date · ville) est masqué tant que la largeur ne libère pas
   au moins lg (1024px) : sur tablette / petit desktop, le lien retour
   long et les 6 boutons d'actions ne laissent pas assez de place pour
   afficher titre + détail sans tronquer brutalement. */
.minisite-header__detail {
    display: none;
    opacity: 0.75;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (min-width: 64em) {
    .minisite-header__detail { display: inline; }
}

/* Actions à droite : partage, impression, marque-page.
   Alignées sur le pattern `nl-minisite-header__actions` (newsletter). */
.minisite-header__actions {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

/* Trois groupes separes visuellement : partage social · impression ·
   marque-page. Les surcharges de COULEUR ont ete retirees le 2026-08-30 : la
   ligne de service est passee sur le plateau, et `.list-hero__share-buttons`
   (content.css) est deja dessine pour un fond clair. Les rejouer en clair
   aurait recree, en trois regles, ce que le composant fait tout seul — et
   c'est exactement ce qui avait produit la divergence d'origine. */
.minisite-header__actions .list-hero__share-buttons {
    gap: 0.25rem;
}

.minisite-header__actions .list-hero__share-buttons .share-buttons__btn--print,
.minisite-header__actions .list-hero__share-buttons .share-buttons__btn--bookmark {
    margin-left: 0.5rem;
}

.minisite-header__actions .list-hero__share-buttons .share-buttons__btn {
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    opacity: 1;
}

/* ── Variante « menu nommé » du partage ──
   Même composant que /portraits (`share-dropdown-group`), dont les pilules
   sont dessinées pour un fond CLAIR. Le minisite les repeignait en
   translucide-sur-marine parce que sa barre etait un aplat ; depuis qu'elle
   est une ligne sur le plateau, ces surcharges n'avaient plus d'objet et sont
   retirees. Le composant reprend son habillage d'origine, l'etat actif
   compris — il est deja dessine pour un fond clair et n'a plus a etre
   contre-dessine ici.

   Cette variante remplace la bulle flottante `.share-fab` sur le minisite :
   le partage vit dans la ligne de service, plus rien ne recouvre le
   programme. */
.minisite-header__share {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/* Sous 48em, « Lire plus tard » et « Imprimer » perdent leur libellé au
   profit de leur icône : trois pilules nommées plus le lien de retour ne
   tiennent pas dans une barre de 3 rem. « Partager » garde le sien, c'est
   l'action que la barre existe pour offrir. Repli visuel seulement
   (`clip-path`), pas `display: none` — le nom reste lu à voix haute. */
@media (width < 48em) {
    .minisite-header__share .share-dropdown-group__btn > span {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .minisite-header__share .share-dropdown-group__btn {
        position: relative;
        width: 1.75rem;
        padding-inline: 0;
        justify-content: center;
    }
}

/* Sous 48rem le bandeau est etroit et le texte occupe toute sa largeur : le
   motif passerait derriere les lettres, ou le contraste du titre blanc n'est
   plus garanti. On le retire plutot que de le reduire. */


/* Appel a l'action de la card d'agenda — style de BASE, hors de toute requete
   de media. Toutes les regles de la pilule vivaient dans le `@media (min-width: 48em)` du mode couche : sur telephone le libelle retombait donc brut dans la
   rangee flex, sans pastille, et le chevron passait a la ligne sous lui. C'est
   le defaut classique d'un style pose uniquement dans une requete de media —
   il n'existe pas en dehors, et personne ne le voit tant qu'on regarde en
   grand. */
.event-agenda-card__cta {
    /* HORS DU FLUX, a toutes les largeurs. En flux, il forme une colonne a
       cote du bloc de texte : le titre ET le sous-titre s'y replient, et le
       bouton se centre sur toute la hauteur au lieu de tenir la ligne du lieu.
       Le positionnement etait reserve au mode couche ; sur telephone, le
       defaut revenait donc en entier. */
    position: absolute;
    bottom: calc(var(--spacing-md) - 6px);
    right: var(--spacing-md);
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--color-navy) 8%, var(--surface-2));
    color: var(--color-navy);
    font-size: var(--font-size-xs);
    font-weight: 700;
    letter-spacing: 0.03em;
    /* Le libelle et sa fleche ne se separent jamais. */
    white-space: nowrap;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.event-agenda-card:hover .event-agenda-card__cta {
    background: var(--color-navy);
    color: var(--ink-on-dark);
}

/* La ligne du lieu reserve la place du bouton — c'est la SEULE ligne qui la
   partage. Le titre et le sous-titre courent sur toute la largeur. */
.event-agenda-card:has(.event-agenda-card__cta) .event-agenda-card__location {
    padding-right: 7rem;
}

/* Sur telephone, la note de type est EMPILEE sous la card : sans marge, son
   titre venait toucher le bord de la card. En grand ecran elle est a cote, la
   marge n'a pas lieu d'etre. */

/* Cas d'un seul evenement : la ligne porte la card a gauche et l'encart de
   type a droite. C'est ce qui compense la largeur de la bande — sans lui, une
   card couchee laissait un tiers de vide a sa droite. */


/* Le bandeau de tete de cette page s'aligne sur sa carte. */
.bio-page:has(> .container > .event-single) .bio-page__topline,
.bio-page .bio-page__topline:has(+ .event-single) {
    max-width: 72rem;
    margin-inline: auto;
}

/* Colonne unique (panneau masque) : le contenu se centre au lieu de rester
   cale a gauche d'un vide. */
.article-single__layout:not(:has(.article-sidebar__section)):not(:has(.article-toc__list li)) .article-single__main {
    margin-inline: auto;
}

/* `contain` et non `cover` : l'affiche garde ses proportions et son cadrage.
   Le fond clair lui redonne le sien — la plupart sont composées sur blanc et
   se perdraient sur le marine. */

/* Sous 48rem la vignette prendrait la moitié de la largeur pour une
   information secondaire : le titre passe d'abord. */

/* Navigation onglets */
/* Barre collante sous la topbar fixe (3rem). Sur une grille de vingt-deux
   vignettes ou un programme de trois jours, la navigation disparaissait des le
   premier defilement.

   Sous 48rem, elle NE colle PAS : la topbar occupe deja 3rem, une barre de
   plus porterait le bandeau fixe a pres de 6,5rem, soit un huitieme d'un ecran
   de telephone mange en permanence — pour une barre qui, a cette largeur,
   defile deja horizontalement et demande donc de la place pour etre lue. */
/* ── Largeur commune du minisite ──────────────────────────────────
   Le bandeau, la barre d'onglets, le contenu et le pied de page lisent la
   MEME variable. Avant, chaque page posait la sienne : 56rem sur l'accueil et
   les contributions, 60rem sur le programme, l'inscription, les partenaires
   et les infos, et rien du tout (donc 80rem) sur les intervenants et les
   rediffusions — pendant que l'en-tete restait a 80rem partout. Sur quatre
   pages sur six, l'embleme commencait donc a 160 pixels a gauche du premier
   mot du contenu, ce qui se lit comme un en-tete mal cale alors que c'est le
   contenu qui bougeait.

   UNE seule mesure : 60rem, celle de la LECTURE. Au-dela, une ligne de texte
   depasse la centaine de caracteres et l'oeil perd le debut de la ligne
   suivante.

   Un temps, les pages en GRILLE (intervenants, rediffusions) avaient droit a
   80rem, au motif qu'on y balaie des cartes plutot qu'on n'y suit des lignes.
   Depuis que le contenu est une carte blanche posee sur le bleu, cette
   exception se voit : la feuille change de largeur d'un onglet a l'autre, et
   le saut est plus couteux que la colonne gagnee. Mesure faite avant de
   trancher : a 60rem les rediffusions gardent TROIS colonnes et le
   trombinoscope QUATRE — l'exception ne payait meme pas ce qu'elle coutait.

   Une page qui aurait besoin d'autre chose pose `--minisite-width` sur son
   conteneur plutot que de redeclarer un `max-width` : la regle reste unique.

   La barre d'ONGLETS suit desormais la meme mesure que le reste : depuis
   qu'elle porte l'identite de l'evenement a gauche et ses onglets a droite,
   elle n'a plus rien a centrer, et son bord gauche doit tomber sur celui du
   contenu.

   Mesure portee a 77,5rem (1240 px) le 2026-08-20, avec la refonte. Les 60rem
   etaient la mesure de la LECTURE, appliquee a la page entiere : elle
   convenait a une colonne de texte et etranglait tout le reste — un programme
   a gouttiere horaire, une grille de tarifs, un trombinoscope. La lecture est
   desormais bornee la ou elle se lit (`--evt-measure`, 62 caracteres) plutot
   qu'au niveau de la page, ce qui rend la largeur aux blocs qui en ont besoin
   sans rallonger une seule ligne de texte. */
.minisite {
    --minisite-width: 77.5rem;
}

.minisite .minisite-header .container,
.minisite .minisite-nav > .container,
.minisite main .container,
.minisite .minisite-footer > .container {
    max-width: var(--minisite-width);
}

/* ── Le contenu se lit sur le fond de page, comme partout ailleurs ──
   Le minisite posait son contenu sur une etendue bleue (degrade + trace
   d'ondes ancres a la fenetre), dans une feuille blanche a ombre portee. Le
   resultat tenait debout tout seul, mais il ne ressemblait a aucune autre
   page du site : on quittait l'ANCESU pour entrer dans un autre site, alors
   qu'un minisite d'evenement en fait partie.

   La marque reste portee par le BLOC DE TETE — barre, bandeau, onglets — qui
   garde le degrade et le trace d'ondes, exactement comme une fiche s'ouvre
   sur sa card navy. En dessous, le contenu revient sur le fond de page
   standard : plus de feuille flottante, plus d'ombre, plus de fond fixe qui
   suit le defilement. */
/* Plus de rembourrage HAUT sur le `main` : depuis la refonte, c'est
   l'en-tete de page qui ouvre le contenu et qui porte sa propre respiration.
   Les pages sans en-tete (accueil, fiches de detail) portent la leur. Cumuler
   les deux rouvrait l'ecart que la suppression du bandeau venait de fermer. */
.minisite main {
    padding-block: 0 var(--spacing-2xl);
}

/* Les pages du minisite portent leur propre `py-8 sm:py-12`, herite du temps
   ou le contenu etait une feuille posee sur le bleu et devait respirer a
   l'interieur. Cumule avec le rythme du `main`, cela ouvrait 80 px entre les
   onglets et la premiere ligne. Le `main` fait foi. */
.minisite main > .container,
.minisite main > * > .container {
    padding-block: 0;
}

/* Fond herite de la regle groupee : la barre d'onglets appartient au bloc de
   tete, elle n'est plus une bande claire rapportee dessous.

   Aucun filet de separation, et c'est le point : un trait, meme a 10 % de
   blanc, redecoupe en deux ce qu'on vient de reunir. La continuite du trace
   d'ondes suffit a faire lire l'ensemble comme un seul bloc.

   En revanche le trace y est VOILE. La bande la plus dense du dessin tombe
   pile a la hauteur des onglets : la meme encre qui fait une texture derriere
   une affiche fait un grouillement derriere sept libelles en majuscules, et
   c'est le texte qui trinque. Un voile de la couleur du fond, pose PAR-DESSUS
   l'image et SOUS le texte, la calme sans la supprimer — la continuite du
   dessin reste lisible d'un bloc a l'autre, elle passe simplement au second
   plan la ou on lit. */
/* Barre d'evenement : fond blanc, un filet dessous. Elle etait marine et
   texturee, dans la continuite du bandeau ; elle porte maintenant l'identite
   de l'evenement, donc un titre et une vignette — c'est-a-dire du contenu, et
   du contenu ne se lit pas sur une texture. */
/* ── LA BARRE D'EVENEMENT EST UNE CARTE, PAS UNE BANDE ─────────────
   C'est le geste central de la maquette, et il regle le grief « ca ne
   ressemble plus au site » : le plateau porte des cartes, la barre en est une.
   Elle flotte, on voit le plateau de chaque cote et au-dessus, et le contenu
   passe DESSOUS au defilement au lieu de venir buter contre un filet.

   La grille est portee par DEUX elements et il faut les distinguer, sinon la
   carte se colle aux bords de la fenetre :
     `.minisite-nav`             l'enveloppe collante — elle porte le plateau
                                 et la gouttiere ;
     `.minisite-nav__card` la carte elle-meme.

   L'enveloppe DOIT porter le fond du plateau : sans lui, le contenu de la page
   se voit defiler dans les 8 px de gouttiere au-dessus de la carte, ce qui se
   lit comme un defaut de rendu et non comme une transparence voulue. */
.minisite-nav {
    color: var(--color-text);
    background: var(--color-canvas);
    padding-block: 0.5rem 0;
}

.minisite-nav__card {
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius-lg);
    box-shadow: var(--evt-shadow);
    padding-block: 0.75rem;
}

/* Identite : vignette + nom de l'evenement + dates. C'est aussi le retour a
   l'accueil du minisite. */
.minisite-nav__identity {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    padding-block: 0.6875rem;
    min-width: 0;
    /* Elle ne s'etire pas : les onglets ont besoin de la place, et un titre
       long doit s'ecreter plutot que les repousser a la ligne. */
    flex: 0 1 auto;
}

/* Bornee par la HAUTEUR, largeur libre. Un carre de 46 px conviendrait a une
   affiche verticale et ecraserait tout le reste : les visuels d'evenement
   reels vont de l'affiche 3:4 au bandeau 2,8:1, et ce dernier, ramene dans un
   carre, rend une bande de seize pixels de haut au milieu de trente de vide —
   on lit un emplacement vide, pas un embleme. Avec une hauteur fixe, les deux
   formats occupent la meme ligne et restent lisibles.

   Ni cadre ni fond : la barre est blanche, un filet autour d'un visuel deja
   compose sur blanc dessine une boite qui n'existe pas. */
/* ── LE CARRE DE DATE, a la place du logo ─────────────────────────
   La vignette de l'evenement tenait ici, a 38 px de haut. A cette taille une
   affiche ne montre rien, et le logo de l'ANCESU figure deja dans la barre
   quarante pixels au-dessus : deux marques empilees, dont l'une illisible.

   Le carre rend un service que le titre ne rend pas — quand a lieu
   l'evenement, d'un coup d'oeil, depuis n'importe quelle page du minisite.
   Carre et non rectangle : c'est la forme d'un jour de calendrier, et elle se
   reconnait avant d'etre lue. */
.minisite-nav__date {
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    min-width: 3.75rem;
    padding: 0.4375rem 0.5625rem;
    border-radius: var(--evt-radius);
    background: var(--color-primary-dark);
    color: var(--ink-on-dark);
    line-height: 1;
}

.minisite-nav__date-day {
    font-family: var(--font-title);
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -0.03em;
}

.minisite-nav__date-month {
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-on-dark-muted);
}

.minisite-nav__identity-text {
    display: block;
    min-width: 0;
}

.minisite-nav__event-title {
    display: block;
    font-weight: 700;
    font-size: clamp(0.9375rem, 1.7vw, 1.0625rem);
    line-height: 1.2;
    color: var(--evt-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.minisite-nav__event-detail {
    display: block;
    margin-top: 0.125rem;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Sous 48rem l'identite tient seule sur sa ligne, les onglets defilent
   dessous : a cette largeur, les ecreter tous les deux ne laisserait lire ni
   l'un ni l'autre. */
@media (width < 48em) {
    .minisite-nav__identity {
        flex: 1 1 100%;
    }
}

/* `top: 0` et non plus `3rem` : la ligne de service qui la precedait etait en
   `position: fixed` et lui volait cette hauteur en permanence. Elle defile
   maintenant avec la page, donc la carte colle au bord haut de la fenetre. */
@media (min-width: 48em) {
    .minisite-nav {
        position: sticky;
        top: 0;
        z-index: 9;
    }
}

/* Identite a gauche, onglets ET appel a l'action groupes a droite.

   `space-between` sur TROIS elements repartissait le vide entre eux : mesure a
   1240 px, il restait 148 px de blanc de chaque cote des onglets, qui
   flottaient au milieu sans etre ni a gauche ni a droite. Une marge auto sur
   les onglets les pousse contre le bouton, et les deux contre le bord droit :
   un seul bloc, une seule respiration. */
.minisite-nav__card {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0 var(--spacing-md);
}

.minisite-nav__card > .minisite-nav__list {
    flex: 0 1 auto;
    margin-left: auto;
}

.minisite-nav__cta {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    flex: 0 0 auto;
    align-self: center;
    padding: 0.625rem 1.25rem;
    /* Pastille, comme la maquette et comme les commandes du site. Un rectangle
       a coin doux au milieu d'une carte a coin doux ne se distingue pas de
       la carte ; la pastille, si. */
    border-radius: var(--radius-pill);
    background-color: var(--evt-cta);
    color: var(--ink-on-dark);
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--transition-fast);
}

.minisite-nav__cta:hover,
.minisite-nav__cta:focus-visible {
    background-color: var(--evt-cta-hover);
    color: var(--ink-on-dark);
}

.minisite-nav__cta--disabled {
    background-color: transparent;
    border: 1px solid var(--evt-rule);
    color: var(--color-text-light);
    font-weight: 500;
}

/* ══ SUR TELEPHONE, L'ACTION SE COLLE EN BAS ══════════════════════════════

   La maquette « Vues mobiles » l'ecrit dans sa table des transpositions :
   l'action principale est « dans la carte, a sa place dans le flux » au
   bureau, et « une barre contextuelle collee en bas, une seule action » sur
   telephone. Ici elle etait pleine largeur EN HAUT, coincee entre la rangee
   d'onglets et le bandeau d'echeance.

   Ce que ca coutait, mesure a 390 px sur l'accueil d'Angers : barre du haut
   48 px, identite 64, onglets 53, bouton 44 — 209 px de chassis, soit 27 %
   d'un ecran de 780, avant le premier mot. Et la redondance se voyait : le
   nom de l'evenement, ses dates et « S'inscrire » etaient rendus DEUX FOIS
   en moins de 500 px, une fois par le chassis, une fois par le hero.

   En bas, le bouton ne coute plus rien au premier ecran, il reste sous le
   pouce a tout moment, et il ne rivalise plus avec le trait de l'onglet
   actif.

   `a.` et non `.` : la variante desactivee (« Inscriptions closes ») est un
   `<span>`, et c'est une INFORMATION, pas un geste. Collee en bas de chaque
   ecran, elle occuperait en permanence la place de l'action qu'elle dit
   impossible. */
@media (width < 48em) {
    .minisite {
        /* Lue par `components/floating-stack.css` pour relever la colonne de
           lanceurs. Declaree ICI, donc absente au-dela du palier : le repli
           `0rem` du calcul suffit alors, sans regle a annuler. */
        --minisite-action-h: 3.5rem;
    }

    .minisite-nav__cta {
        flex: 1 1 100%;
        justify-content: center;
    }

    a.minisite-nav__cta {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 20;
        margin-inline: 0;
        min-height: var(--minisite-action-h);
        border-radius: 0;
        /* Le rembourrage bas absorbe la zone de securite des ecrans a
           encoche : sans lui, le libelle se glisse sous la barre de gestes. */
        padding: 0 var(--spacing-md) env(safe-area-inset-bottom, 0px);
        font-size: var(--font-size-base);
        /* L'ombre monte, aucun jeton ne decrit une ombre vers le haut : elle
           se compose donc a partir du marine plutot que d'ecrire son rgb. */
        box-shadow: 0 -6px 18px color-mix(in srgb, var(--color-primary-dark) 16%, transparent);
    }

    /* ── UN SEUL « S'inscrire » A L'ECRAN ──
       Une fois l'action collee en bas, les deux autres deviennent du bruit :
       mesure a 390 px sur « Contribuer », en bas de page, TROIS boutons
       identiques tenaient dans le meme ecran de 780 px — celui de la colonne
       de service, celui du pied de page, et la barre. Les dates et le lieu s'y
       repetaient aussi, une fois dans la carte, une fois dans le pied.

       `:has()` plutot qu'une condition recopiee en Twig : ce qu'il faut
       savoir, c'est si la BARRE EXISTE — c'est-a-dire si la barre d'onglets a
       rendu son `<a>`. Recopier sa condition (fenetre ouverte, cible
       resolue) dans deux gabarits de plus, c'est trois endroits a garder
       d'accord, et la divergence ne se verrait pas : elle rendrait juste un
       bouton en trop, ce que personne ne signale.

       Repli sur un navigateur sans `:has()` : les trois boutons restent, soit
       l'etat d'avant ce commit. On ne casse rien, on n'ameliore pas. */
    .minisite:has(a.minisite-nav__cta) .evt-service__cta--register,
    .minisite:has(a.minisite-nav__cta) .minisite-footer__cta {
        display: none;
    }

    /* ── ET LA CARTE ELLE-MEME DISPARAIT ──
       Son bouton retire, il ne lui restait que « Dates » et « Lieu » — que le
       pied de page redit VERBATIM cent pixels plus bas, sur la meme capture.
       La colonne de service existe pour donner un second appui a une page
       trop vide EN LARGEUR ; sur une colonne unique, il n'y a pas de vide a
       remplir, et elle devient un doublon du pied.

       Seulement quand la barre existe, donc sur une edition A VENIR. Sur une
       edition PASSEE la carte porte des chiffres et le lien vers les
       rediffusions, qu'on ne trouve nulle part ailleurs sur ces pages : elle
       reste. C'est la meme sonde que ci-dessus — la presence de la barre — et
       elle repond exactement a la bonne question.

       `:has(.evt-service)` et non `.evt-page-aside` tout court : c'est la
       CARTE DE SERVICE qui fait doublon avec le pied, pas la colonne. Ecrite
       sur la colonne, la regle effacerait sur telephone tout ce qu'on y
       poserait un jour — des filtres, un sommaire — et l'effacerait en
       SILENCE, puisqu'une colonne masquee ne se signale pas. Le defaut n'avait
       pas encore de victime : il l'aurait eue au premier aside qui ne porte
       pas cette carte. */
    .minisite:has(a.minisite-nav__cta) .evt-page-aside:has(.evt-service) {
        display: none;
    }

    /* Le contenu ne finit pas SOUS la barre. La valeur est celle de la barre
       plus une respiration : sans elle, la derniere ligne du pied de page est
       recouverte, et c'est la barre legale — donc precisement ce qu'un
       visiteur peut avoir besoin d'atteindre. */
    .minisite main,
    .minisite .minisite-footer {
        scroll-margin-bottom: var(--minisite-action-h);
    }

    .minisite .minisite-footer__legal {
        padding-bottom: calc(var(--minisite-action-h) + var(--spacing-md));
    }
}

.minisite-nav__list {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    justify-content: flex-end;
    list-style: none;
    padding: 0;
    margin: 0;
}

/* Les onglets prennent TOUTE la hauteur de la barre. Elle est fixee par
   l'identite (deux lignes, 65 px) : les liens n'en faisaient que 52, donc le
   trait de l'onglet actif flottait treize pixels au-dessus du filet du bas au
   lieu de s'y poser. */
.minisite-nav__item {
    list-style: none;
    display: flex;
}

.minisite-nav__list > .minisite-nav__item > .minisite-nav__link {
    height: 100%;
}

/* Sous 64em, la barre défile horizontalement au lieu de se replier — motif
   `.search-tabs` de /recherche. Cinq onglets en majuscules produisaient trois
   rangées centrées, soit ~150 px avalés avant le moindre contenu, et un ordre
   de lecture brisé (la troisième rangée d'un seul onglet centré ne se lit plus
   comme une suite). Le repli était d'autant plus coûteux que la barre est déjà
   précédée d'une topbar fixe et d'un bandeau d'affiche. */
@media (width < 64em) {
    .minisite-nav__card {
        justify-content: flex-start;
        /* La bande touche les deux bords de l'écran : un onglet coupé au ras
           du bord est le seul indice fiable qu'il reste des onglets à droite
           (le site n'utilise pas de masque en dégradé). */
        padding-inline: 0;
    }

    .minisite-nav__list {
        flex-wrap: nowrap;
        justify-content: flex-start;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        white-space: nowrap;
        scroll-padding-inline: var(--spacing-md);
    }

    .minisite-nav__list::-webkit-scrollbar { display: none; }

    .minisite-nav__item { flex: 0 0 auto; }

    .minisite-nav__link {
        padding-inline: var(--spacing-md);
    }

    .minisite-nav__link::after {
        left: var(--spacing-md);
        right: var(--spacing-md);
    }

    /* La pastille garde ses coins, mais colle les bords de son onglet : sur
       une barre qui défile, le rembourrage lateral est plus serré. */
    .minisite-nav__item--active .minisite-nav__link {
        border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    }

    /* Un menu déroulant en `position: absolute` serait rogné par le
       conteneur défilant, et il n'est de toute façon pas atteignable au
       doigt : il s'ouvre sur `:hover`/`:focus-within`, alors qu'une tape
       déclenche la navigation. L'onglet mène à sa page, qui liste les
       mêmes entrées. */
    .minisite-nav__dropdown { display: none; }
    .minisite-nav__caret { display: none; }

    .minisite-nav__cta {
        margin-inline: var(--spacing-md);
    }
}

/* ── Au-dela de 64em, la barre ne se replie JAMAIS ──
   Mesure a 1240 px : identite (346) + six onglets (656) + bouton (105) +
   gouttieres = 1147, ca passe. Ajoutez l'onglet « Inscription » et un titre
   d'evenement long, et l'on depasse — la barre passe alors sur deux lignes.
   Elle est COLLANTE : le debordement coute une bande d'ecran en permanence,
   sur toutes les pages, pour un evenement dont le seul tort est d'avoir sept
   onglets.

   L'ordre de sacrifice est donc explicite : c'est l'IDENTITE qui se resserre
   (son titre et sa ligne de dates s'ecretent deja proprement), pas les
   onglets, qui sont la navigation. En dernier recours seulement, la rangee
   d'onglets defile horizontalement. */
@media (min-width: 64em) {
    .minisite-nav__card {
        flex-wrap: nowrap;
    }

    .minisite-nav__identity {
        flex: 0 1 auto;
        min-width: 0;
    }

    .minisite-nav__list {
        flex: 0 1 auto;
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .minisite-nav__list::-webkit-scrollbar {
        display: none;
    }

    .minisite-nav__item {
        flex: 0 0 auto;
    }
}

/* Libelles en casse normale. Ils etaient en capitales espacees : sur une
   barre blanche qui porte deja un titre d'evenement en gras, sept libelles
   en capitales font une seconde ligne de titres et on ne sait plus lequel
   des deux lire en premier. */
.minisite-nav__link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.25rem;
    /* Le rembourrage bas fait la place au filet d'onglet actif, qui se pose
       au ras du filet de la barre. */
    padding: 1rem var(--spacing-md) 0.9375rem;
    font-size: var(--font-size-sm);
    font-weight: 500;
    text-decoration: none;
    color: var(--color-text);
    transition: color var(--transition-fast);
}

/* Filet d'onglet, en ROUGE de section. Il etait en vert de marque, parce
   qu'il se posait sur un aplat marine ou le rouge criait. Sur fond blanc
   c'est l'inverse : le vert var(--color-callout-success) rend 1,9:1 sur blanc, il ne se voit
   pas. Le rouge y rend 5,7:1, et c'est la couleur de la rubrique
   « colloques ». */
.minisite-nav__link::after {
    content: '';
    position: absolute;
    /* LA GEOMETRIE DE L'APEX, mesuree sur `.navbar__link::after` : 34 x 5,
       entierement arrondi, centre sous le libelle. Le filet du minisite courait
       sur toute la largeur du libelle, en 3 px, colle au bas de la carte : il se
       lisait comme un SOULIGNEMENT d'onglet, pas comme le trait signature du
       reseau. Court et epais, c'est le meme objet que sur la barre du site. */
    left: 50%;
    transform: translateX(-50%);
    bottom: 0.5rem;
    width: 2.125rem;
    height: 5px;
    border-radius: var(--radius-pill);
    background: var(--evt-cta);
    /* ── Le filet est TOUJOURS la, il change d'INTENSITE ──────────
       Il etait escamote (`scaleX(0)`) et ne se revelait qu'au survol ou sur
       l'onglet actif. Deux consequences, et la seconde est la vraie :
       au repos la rangee d'onglets n'avait aucune signature graphique, et
       surtout ce n'est pas ainsi que le site ecrit ses rubriques — la barre de
       navigation principale porte un filet colore SOUS CHAQUE rubrique, en
       demi-teinte, plein sur l'active. Le minisite avait invente un autre
       geste pour dire la meme chose.

       C'est aussi ce que pose la maquette (`opacity` .4 puis 1). Une
       transition d'opacite, pas d'echelle : le trait ne s'etire plus depuis
       son centre a chaque survol. */
    opacity: 0.4;
    transition: opacity var(--transition-fast);
}

.minisite-nav__link:hover,
.minisite-nav__link:focus-visible {
    color: var(--evt-cta);
}

.minisite-nav__link:hover::after,
.minisite-nav__link:focus-visible::after {
    opacity: 1;
}

/* L'onglet actif se signale par son filet et par le poids de son libelle,
   pas seulement par sa couleur : un etat qui ne tient qu'a la teinte n'est
   pas percu par tout le monde. */
.minisite-nav__item--active .minisite-nav__link {
    color: var(--evt-ink);
    font-weight: 700;
}

.minisite-nav__item--active .minisite-nav__link::after {
    opacity: 1;
}

/* ── Bandeau d'echeance ──────────────────────────────────────────
   Une bande claire teintee de la couleur de section, sous la barre d'onglets.
   Elle ne colle pas : elle s'annonce une fois puis se laisse depasser. */
/* ── L'ECHEANCE EST UNE CARTE, ELLE AUSSI ──────────────────────────
   Elle etait une bande rose pleine largeur, posee juste sous la barre. Le
   raisonnement d'alors — « une annonce de niveau site se rend pleine largeur,
   comme les deux barres au-dessus » — reposait sur le fait que ces barres
   etaient elles-memes pleine largeur. Elles sont devenues des cartes ; la
   bande est donc restee seule a traverser l'ecran, et c'etait le dernier
   rectangle qui coupait la page en deux.

   `--color-border` plutot que le `#f3dadb` en dur : ce rose-gris etait la
   seule couleur du minisite a n'etre ni un jeton ni une valeur derivee d'un
   jeton. */
/* ── L'ECHEANCE EST UNE PASTILLE, sur la ligne du fil d'Ariane ──
   Elle occupait un BANDEAU pleine largeur sous les onglets : 56 px de rose sur
   1 440 de large pour une ligne de texte, franchis avant d'atteindre le titre
   de l'evenement. Une annonce qui prend une bande d'ecran a chaque page finit
   par se lire comme du decor.

   Sur la ligne du fil d'Ariane, elle occupe une place qui existait deja et
   qui etait vide a droite. Elle y garde son rang : c'est une mention, pas une
   action. */
.minisite-deadline {
    /* NI CADRE NI FOND. La pastille etait un bloc rose bordé de 34 px de haut
       pose a cote d'un fil d'Ariane de 14 px : deux objets de hauteurs
       differentes sur la meme ligne, dont l'un pese trois fois l'autre. On ne
       lisait plus une ligne, on lisait une bande interrompue par du texte.

       Ne reste que l'etiquette rouge — elle, doit se voir — et la mention en
       texte courant, a la meme hauteur de ligne que le chemin. Les deux moities
       de la ligne s'alignent alors sur la meme ligne de base. */
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--color-text-light);
    font-size: var(--font-size-xs);
    line-height: 1.4;
    white-space: nowrap;
}

/* ── LA LIGNE DU FIL D'ARIANE PORTE DEUX CHOSES ───────────────────
   Le chemin a gauche, l'echeance a droite. Borne au `.minisite` : le fil
   d'Ariane est un composant du site entier, et la rangee ne vaut que la ou
   quelqu'un remplit sa fente. */
.minisite .breadcrumb-bar > .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
}

/* Sans cela le chemin, seul enfant restant quand aucune echeance n'est
   active, se laisse etirer par `space-between` — sans effet visible, mais sa
   zone cliquable s'etendrait sur toute la largeur. */
.minisite .breadcrumb-bar .breadcrumb {
    min-width: 0;
}

.minisite-deadline__tag {
    background: var(--evt-cta);
    color: var(--ink-on-dark);
    font-size: var(--font-size-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 0.1875rem 0.5625rem;
    border-radius: var(--radius-sm);
}

/* Derniere ligne droite : meme grammaire, teinte d'alerte. Le rouge de
   section dirait « offre » la ou il faut dire « il reste peu de temps ». */
/* Paire fond doux / texte fonce autoportee : `app.css` n'expose pas de teinte
   douce pour l'alerte (`--color-warning` est la couleur pleine, illisible en
   fond de bandeau). Les deux valeurs sont indissociables et rendent 8,1:1. */
.minisite-deadline--closing {
    color: var(--evt-deadline-urgent-ink);
}

.minisite-deadline--closing .minisite-deadline__tag {
    background: var(--evt-deadline-ink);
    color: var(--ink-on-dark);
}

/* ── En-tete de page ─────────────────────────────────────────────
   Deux variantes, et la difference n'est pas cosmetique : `panel` ouvre un
   dossier (programme, inscription) et pose un aplat marine qui marque le
   changement de registre ; `plain` entre directement dans le sujet
   (partenaires, infos pratiques) et n'a pas besoin d'un aplat pour cela.
   Un troisieme cas — la page qui rend son propre en-tete — ne passe pas ici. */
/* ── L'EN-TETE DE PAGE EST UNE CARTE ───────────────────────────────
   Il etait une BANDE teintee pleine largeur, et le raisonnement qui l'avait
   produite etait juste a l'epoque : le contenu se lisait sur du blanc d'un
   bout a l'autre — barre blanche, en-tete blanc, corps blanc — et rien ne
   disait ou l'un finissait. La bande donnait ce reperage sans couter de
   hauteur.

   Le sol ayant change, la premisse est tombee : sur le plateau, cette bande
   n'est plus qu'un gris a peine distinct d'un autre gris, et elle redecoupe la
   page en rubans. La maquette en fait une CARTE — la meme que celle de la
   barre juste au-dessus et que celles du corps juste en dessous — et le
   reperage vient alors du contraste carte / plateau, qui est le contraste de
   base de tout le site.

   L'enveloppe ne porte plus que la gouttiere : c'est `__inner` qui est la
   carte, pour que le plateau reste visible sur ses quatre cotes. */
.minisite-pagehead,
.minisite-pagehead--plain {
    padding-block: var(--spacing-lg) 0;
    background: transparent;
}

.minisite-pagehead__inner {
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius-lg);
    box-shadow: var(--evt-shadow);
    padding: clamp(1.5rem, 3vw, 2rem) clamp(1.5rem, 3vw, 1.75rem);
}

/* Titre a gauche, faits de la page a droite, sur la MEME ligne de base.

   Le `baseline` est le point : cale sur le bas des BLOCS, le bloc de faits
   tombait au niveau du trait signature, sous le titre — on ne lisait plus
   qu'il le qualifie. Ici c'est la premiere ligne des faits qui s'aligne sur la
   ligne de base du titre, quelle que soit la difference de corps (46 px contre
   14). Un en-tete qui ne porte qu'un titre laisse les trois quarts de sa
   largeur vides : c'est ce qui faisait paraitre la page vide. */
.minisite-pagehead__title-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.25rem 2.5rem;
}

/* `min-width: 0` : sans lui, un titre long ne peut pas descendre sous la
   largeur de son contenu et pousse les faits hors du conteneur au lieu de les
   faire passer a la ligne. */
.minisite-pagehead__title {
    min-width: 0;
}

.minisite-pagehead__lead {
    max-width: var(--evt-measure);
    margin: 0.875rem 0 0;
    color: var(--color-text-light);
    font-size: var(--font-size-lg);
    line-height: 1.6;
}

/* `flex: 0 1 auto` : les faits ne s'etirent pas, mais ils peuvent se resserrer
   avant de passer a la ligne. */
.minisite-pagehead__facts {
    display: flex;
    flex: 0 1 auto;
    flex-direction: column;
    gap: 0.375rem;
    min-width: 0;
    margin: 0;
    text-align: right;
}

/* Une paire par ligne : l'intitule en petites capitales, la valeur en marine.
   `flex-end` plutot qu'un `text-align` seul — les deux parties doivent rester
   solidaires quand la valeur passe a la ligne. */
.minisite-pagehead__fact {
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: 0.5rem;
    font-size: var(--font-size-sm);
}

.minisite-pagehead__fact-label {
    color: var(--color-text-light);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: var(--font-size-xs);
    font-weight: 600;
}

.minisite-pagehead__fact-value {
    color: var(--evt-ink);
    font-weight: 600;
}

/* Sous 48em les faits passent a gauche, sous le titre : une colonne alignee a
   droite sur un telephone se lit comme une erreur de mise en page. */
@media (width < 48em) {
    .minisite-pagehead__facts {
        text-align: left;
    }

    .minisite-pagehead__fact {
        justify-content: flex-start;
    }
}

.minisite-pagehead__title {
    margin: 0 0 0.875rem;
    font-size: clamp(1.75rem, 4.2vw, 2.875rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.015em;
    text-wrap: balance;
}

.minisite-pagehead__title {
    color: var(--evt-ink);
}

.minisite-pagehead__meta {
    margin: 0;
    font-size: var(--font-size-base);
    color: var(--ink-on-dark-soft);
}

.minisite-pagehead--plain .minisite-pagehead__meta {
    color: var(--color-text-light);
}

/* Marqueur d'edition passee. Sur l'aplat marine, un fond translucide ; sur
   fond clair, la teinte d'etat. Dans les deux cas il porte un pictogramme en
   plus de sa couleur — un etat qui ne tient qu'a la teinte se perd. */
.minisite-pagehead__archived {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin-bottom: 0.875rem;
    padding: 0.25rem 0.625rem;
    border-radius: var(--radius-sm);
    font-size: var(--font-size-xs);
    font-weight: 600;
    background: var(--veil-on-dark);
    color: var(--ink-on-dark);
}

.minisite-pagehead--plain .minisite-pagehead__archived {
    background: var(--color-bg-light);
    color: var(--color-text-light);
}

/* Le sur-titre et le marqueur d'edition passee peuvent coexister : le premier
   dit la nature de l'evenement, le second son etat. Ils tiennent sur deux
   lignes plutot que sur une, sinon le marqueur se lit comme une suite du
   sur-titre. */
.minisite-pagehead__archived + .minisite-pagehead__title {
    margin-top: 0;
}

/* ══ Accueil du minisite ═══════════════════════════════════════════
   Hero, chiffres-cles, journees en bref, tarifs, portes de sortie. Chaque
   bloc est rendu par le gabarit UNIQUEMENT si sa donnee existe : les regles
   ci-dessous ne prevoient donc aucun etat vide. */

.evt-hero-band {
    padding-block: clamp(1.25rem, 3vw, 2.125rem) 0;
}

/* ── LE HERO EST UNE CARTE CLAIRE ──────────────────────────────────
   Il etait un aplat marine a degrade, et c'est lui qui portait l'essentiel du
   grief « je le trouve charge » : deux ecrans plus bas venait un second aplat
   marine (l'appel a l'action de fin), puis un troisieme (le pied). Trois
   blocs pleins de la meme couleur sur une page, entre lesquels rien ne
   respire.

   La maquette n'en garde AUCUN sur l'accueil. Elle pose l'affiche et le texte
   dans une carte claire, et reserve le marine aux accents — un prix mis en
   avant, un en-tete de carte laterale — ou il vaut precisement parce qu'il est
   rare.

   Ce que la carte gagne au passage, et qui n'etait pas atteignable sur
   l'aplat : le titre, le sur-titre, le trait signature, le chapo et les
   boutons reprennent leurs couleurs de BASE. Cinq surcharges « sur aplat
   marine » ont donc ete supprimees plutot que retournees en clair — le vert
   eclairci, le fantome en blanc translucide, le chapo a 85 % de blanc
   n'existaient que pour compenser le fond. */
.evt-hero {
    position: relative;
    overflow: hidden;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius-lg);
    padding: clamp(1.75rem, 4vw, 2.75rem);
    color: var(--color-text);
    background: var(--evt-surface);
    box-shadow: var(--evt-shadow);
}

/* Filigrane de marque. Ancre a droite et deborde : c'est ce qui en fait une
   TEXTURE et non un logo pose dans un coin. Le reglage attend le SYMBOLE
   SEUL — un logo qui porte son lettrage redevient lisible une fois agrandi et
   se lit comme un second logo, en concurrence avec l'affiche a cote. */
.evt-hero--motif::before {
    content: '';
    position: absolute;
    top: 50%;
    right: -6rem;
    width: 26rem;
    height: 26rem;
    transform: translateY(-50%);
    /* Repli explicite : `--minisite-motif` n'est declare dans AUCUNE feuille —
       il est pose en ligne par le gabarit, qui seul connait l'URL du media, sous
       la forme d'un attribut `style` portant une fonction `url`. Ne PAS ecrire
       cette fonction ici, meme en commentaire : `CssAssetUrlCompiler` resout
       les references d'asset sans distinguer le code du commentaire, et fait
       echouer tout le `asset-map:compile` sur un chemin qui n'existe pas.
       Un `var()` sans repli sur un jeton
       absent rend la declaration invalide a l'analyse et le navigateur la jette
       en silence ; ici le repli dit ce qu'on veut vraiment quand aucun motif
       n'est regle — pas d'image. C'est aussi ce qui permet a la feuille de
       tenir sa declaration `@grammaire v2`, dont le controle d'orphelins ne
       peut pas savoir qu'un jeton vient du HTML. */
    background-image: var(--minisite-motif, none);
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
    /* 9 % convenait sur un aplat marine, ou le motif se lisait en clair sur
       sombre. Sur blanc, la meme valeur dessine une tache grise a cote de
       l'affiche ; a 5 % il redevient une texture. */
    opacity: 0.05;
    pointer-events: none;
}

/* ── Corps editorial : texte a gauche, medias a droite ──
   La bande-annonce vivait AU MILIEU du texte, dans la colonne de lecture :
   elle y rendait sur moins de 400 px et coupait le propos en deux. A droite,
   elle a la place d'etre vue, et le texte se lit d'un trait.

   `1.15fr / 1fr` et non deux colonnes egales : le texte est ce qu'on vient
   lire, la video ce qu'on regarde ensuite. */
.show__editorial {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
    gap: var(--evt-gap);
    align-items: start;
}

@media (min-width: 62em) {
    .show__editorial {
        grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    }
}

/* Sans media, le texte ne s'etale pas sur les 1240 px de la page : une ligne
   y depasserait la centaine de caracteres. */
.show__editorial--solo {
    display: block;
    max-width: var(--evt-measure);
}

.show__editorial .show__body {
    min-width: 0;
}

/* Les medias s'empilent quand il y en a plusieurs, et le premier s'aligne sur
   la premiere ligne du texte plutot que sur le milieu de la colonne. */
.show__media {
    min-width: 0;
    display: grid;
    gap: var(--spacing-lg);
}

.show__media > :first-child {
    margin-top: 0;
}

.show__editorial-more {
    margin: var(--spacing-lg) 0 0;
}
/* ── L'ALTERNANCE DE FONDS EST TOMBEE ──────────────────────────────
   Une section sur deux portait un aplat teinte pleine largeur, pour marquer
   la coupure. C'etait juste tant que le contenu se lisait sur du blanc : la
   bande teintee tranchait.

   Sur le plateau, elle ne tranche plus — elle fait un damier de deux gris tres
   proches, qui redecoupe la page en rubans pleine largeur sans dire ou l'on
   passe d'un sujet a l'autre. Ce que la maquette emploie a la place, et qui
   est deja en place : le FILET HAUT de l'en-tete de section. Il coute deux
   pixels et il tombe exactement a la coupure, la ou l'aplat commencait
   toujours un peu avant ou un peu apres.

   La classe est conservee, vide de fond : neuf gabarits la posent, et la
   retirer partout serait un balayage sur du texte utilisateur pour un gain
   nul. Elle garde sa valeur de MARQUEUR — une section qu'on a voulue
   detachee — le jour ou on lui redonne un traitement. */
.evt-section--muted {
    background: transparent;
}

/* ── Le programme en bref ── */
.evt-daycards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
    gap: clamp(0.875rem, 2vw, 1.375rem);
}

.evt-daycard__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
    margin-bottom: 1.125rem;
}

.evt-daycard__label {
    font-weight: 700;
    font-size: var(--font-size-lg);
    color: var(--evt-ink);
}

.evt-daycard__date {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* Gouttiere horaire fixe : c'est elle qui fait lire la colonne des heures
   comme une echelle de temps plutot que comme un prefixe de chaque ligne. */
.evt-daycard__row {
    display: grid;
    grid-template-columns: 3.875rem minmax(0, 1fr);
    gap: 1rem;
    padding-block: 0.75rem;
    border-top: 1px solid var(--evt-rule-soft);
}

.evt-daycard__time {
    font-weight: 600;
    font-size: var(--font-size-sm);
    color: var(--evt-blue);
    font-variant-numeric: tabular-nums;
}

.evt-daycard__title {
    font-size: var(--font-size-base);
    line-height: 1.45;
}

.evt-daycard__more {
    margin: 0.75rem 0 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* ── Tarifs ── */
.evt-prices {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 11.5rem), 1fr));
    gap: 1rem;
}

.evt-price {
    display: grid;
    gap: 0.625rem;
    align-content: start;
    padding: 1.625rem;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    background: var(--evt-surface);
}

/* Le premier palier sur aplat marine. Il n'est pas « meilleur » : il est
   celui qui concerne la majorite des visiteurs de ce minisite. */
.evt-price--featured {
    background: var(--evt-ink);
    border-color: var(--evt-ink);
    color: var(--ink-on-dark);
}

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

.evt-price--featured .evt-price__category {
    color: var(--evt-signature-on-dark);
}

.evt-price__amount {
    font-size: clamp(1.75rem, 3.4vw, 2.375rem);
    font-weight: 700;
    line-height: 1;
    color: var(--evt-ink);
}

.evt-price--featured .evt-price__amount {
    color: var(--ink-on-dark);
}

.evt-price__note {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.evt-price--featured .evt-price__note {
    color: var(--ink-on-dark-muted);
}

/* ── Portes de sortie ── */
.evt-doors {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16.875rem), 1fr));
    gap: clamp(0.875rem, 2vw, 1.375rem);
}

/* `a.evt-card` pose `display: block` avec une specificite (0,1,1) SUPERIEURE a
   celle de `.evt-door` (0,1,0) : la grille declaree ici ne s'appliquait pas, et
   les trois `<span>` de la carte se suivaient sur une seule ligne
   (« CONTRIBUTIONS Concours video Consultez le reglement… »). Rien ne le
   signale — la page se rend, elle est seulement illisible.

   Le selecteur monte donc au meme rang (`a.evt-door`, 0,1,1) et l'emporte par
   l'ordre. Corriger par la plutot qu'en posant `display: block` sur les enfants
   garde le `gap` de la grille, qui espace les trois lignes. */
a.evt-door,
.evt-door {
    display: grid;
    gap: 0.625rem;
    align-content: start;
}

.evt-door__eyebrow {
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--evt-cta);
}

.evt-door__title {
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--evt-ink);
}

.evt-door__text {
    font-size: var(--font-size-sm);
    line-height: 1.7;
    color: var(--color-text-light);
}

/* ── APPEL A L'ACTION FINAL : UNE CARTE, PLUS UN APLAT ─────────────
   C'etait le TROISIEME aplat marine de l'accueil, apres la barre du haut et
   le hero. Les deux premiers sont tombes ; celui-ci, laisse seul, devenait le
   seul bloc plein de la page et attirait l'oeil plus que le contenu qu'il
   conclut.

   Il reste un appel a l'action, donc il reste distinct : filet rouge en tete,
   fond d'incise, bouton plein. Ce qui change est le RANG — une carte parmi
   les cartes, avec un accent, et non un pave qui ferme la page.

   `.evt-panel` n'est pas touche : d'autres surfaces du minisite s'en servent
   legitimement comme accent (la carte laterale des pages interieures, ou la
   maquette pose elle-meme un en-tete marine). C'est ici que l'aplat n'avait
   plus lieu d'etre, pas dans la brique. */
/* CARTE MARINE, et sans filet de bord. Le bloc etait un voile clair borde a
   gauche d'un trait rouge de 4 px : le trait faisait lire une NOTE — c'est la
   grammaire de l'avertissement — quand ce bloc est l'appel a l'action qui
   ferme la page. Un bord colore signale, il n'invite pas.

   L'aplat est ici a sa place, et il l'est parce qu'il est RARE : c'est le
   seul de la page avec le hero, et les deux se repondent — la page ouvre et
   ferme sur le meme fond. */
.evt-closing {
    background: var(--color-primary-dark);
    color: var(--ink-on-dark);
    border: 0;
    border-radius: var(--evt-radius-lg);
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 1.5rem;
    padding: clamp(1.625rem, 4vw, 2.5rem);
}

.evt-closing__title {
    margin: 0 0 0.375rem;
    font-size: clamp(1.1875rem, 2.3vw, 1.5rem);
    font-weight: 700;
}

.evt-closing__hint {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.evt-closing__title {
    color: var(--ink-on-dark);
}

.evt-closing__hint {
    color: var(--ink-on-dark-muted);
}

/* `ui.kicker` rend un sur-titre calibre pour fond clair. Sur l'aplat il
   tombait a 2,4:1 — c'est le meme piege que le vert de signature, et il ne se
   voit pas a la relecture puisque la macro est correcte partout ailleurs. */
.evt-closing .ui-kicker {
    color: var(--ink-on-dark-muted);
}

/* Le bouton du minisite est rouge sur fond clair. Sur le marine il rend 3,9:1,
   sous le seuil : ici il passe en blanc plein, comme les appels du hero — les
   deux aplats de la page portent alors le meme bouton. */
/* `.minisite .evt-closing .btn--primary` et non `.evt-closing .btn` : le
   bouton du minisite est peint par `.minisite .btn--primary`, de MEME
   specificite (0,2,0) et servi plus tard dans la cascade. A egalite c'est
   l'ordre qui tranche, et l'ordre ne m'appartient pas — la feuille du paquet
   est chargee apres la feuille de zone. Un cran de specificite ferme la
   question sans dependre de l'ordre de chargement. */
.minisite .evt-closing .btn--primary {
    background: var(--surface-2);
    border-color: transparent;
    color: var(--color-primary-dark);
}

.minisite .evt-closing .btn--primary:hover,
.minisite .evt-closing .btn--primary:focus-visible {
    background: var(--evt-tint);
    color: var(--color-primary-dark);
}

/* Texte courant du minisite. */
.evt-body {
    font-size: var(--font-size-base);
    line-height: 1.75;
    color: var(--color-text-light);
    margin: 0 0 1.5rem;
}

/* Contenu minisite.

   La respiration entre l'en-tete de page et le contenu vit ICI et nulle part
   ailleurs. Elle etait portee par un `py-8 sm:py-12` repete sur le conteneur
   de chaque page, herite du temps ou le contenu etait une feuille blanche
   posee sur un fond bleu et devait respirer a l'INTERIEUR — et neutralise
   depuis par une regle du `main`. Le resultat, apres la refonte : les
   commandes du programme collaient au bord de l'aplat marine. */
.minisite-content {
    padding-top: clamp(1.5rem, 3vw, 2.25rem);
}

.minisite-content__intro {
    max-width: 48rem;
}

.minisite-content__page-title {
    font-size: var(--font-size-xl);
    font-weight: 300;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--spacing-xl);
}

.minisite-content__highlights {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--spacing-md);
}

@media (min-width: 40em) {
    .minisite-content__highlights { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64em) {
    .minisite-content__highlights { grid-template-columns: repeat(3, 1fr); }
}

.minisite-highlight {
    display: flex;
    gap: var(--spacing-md);
    padding: var(--spacing-md);
    background: var(--color-bg-light);
    border-radius: var(--radius-md);
}

.minisite-highlight svg { flex-shrink: 0; color: var(--color-primary); margin-top: 0.125rem; }
.minisite-highlight__label { font-size: var(--font-size-xs); color: var(--color-text-light); }
.minisite-highlight__value { font-weight: 600; }

.minisite-content__cta { margin-top: var(--spacing-xl); }

/* Cap la largeur du programme sur celle de l'image hero (60rem ≈ 960px)
   pour une cohérence visuelle entre l'en-tête et le contenu. Le
   `.container` global (max-width 68.125rem) est resserré localement. */
/* ── Barre de pilotage du programme, collante ──
   Une seule rangee : le choix du jour, les etiquettes de type, le compteur,
   puis les commandes de la page. Elles etaient sur trois rangees distinctes,
   soit pres de 200 px avant la premiere ligne du programme.

   Collante sous le bloc de tete : sur vingt-six sessions, les filtres
   sortaient de l'ecran au premier defilement. Fond blanc opaque obligatoire —
   sans lui, le programme defile VISIBLEMENT derriere. Le plan d'empilement se
   place sous la barre d'evenement (`--z-navbar`, 1000) et au-dessus du
   contenu. */
.programme__header {
    position: sticky;
    top: var(--minisite-chrome-h, 7.5rem);
    z-index: 8;
    background: var(--evt-surface);
    border-bottom: 1px solid var(--evt-rule);
    padding-block: 0.75rem;
    margin-bottom: var(--spacing-lg);
}

/* Sous 48rem la barre d'evenement ne colle pas (cf. `.minisite-nav`) : celle-ci
   se calerait alors sous une barre qui defile, et flotterait au milieu de
   l'ecran. Elle suit le flux. */
@media (width < 48em) {
    .programme__header {
        position: static;
    }
}

/* Le h2 hérite d'un `margin-bottom: var(--spacing-xl)` qui décale son
   centre visuel en flex `align-items: center` (la boîte flex inclut le
   margin). On l'annule dans le header — le gap horizontal et le
   margin-bottom du header gèrent l'espace. Font-weight relevé en local
   (l'override global `font-weight: 300` du minisite-content__page-title
   reste light sur les autres pages minisite). */
.programme__title-row .minisite-content__page-title {
    margin-bottom: 0;
    line-height: 1;
    font-weight: 600;
}

/* Titre à gauche, actions de la page à droite, sur une seule rangée. */
/* Trois groupes sur une rangee : jours, etiquettes de type + compteur,
   commandes. Ils se replient dans cet ordre de priorite quand la place
   manque, les commandes passant a la ligne les premieres. */
.programme__title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem var(--spacing-md);
    width: 100%;
    flex-wrap: wrap;
}

/* ── Deux rangees VOULUES, pas subies ──
   Mesure a 1240 px : trois pastilles de jour (391 px, chacune sur deux lignes),
   quatre etiquettes de type (769) et les actions (257) font 1417 pour 1176
   disponibles. Une seule rangee est donc impossible des que les libelles de
   type sont longs — « Conference inaugurale » a lui seul en prend 175.

   Plutot qu'un repli au hasard de la largeur, l'ordre est impose :
     rangee 1 — le jour a gauche, les actions de la page a droite ;
     rangee 2 — les filtres et leur compteur.
   « Ce que je regarde » d'abord, « ce que j'en retire » ensuite. Les actions
   etaient sinon renvoyees seules sur la seconde ligne, calees a gauche sous
   les etiquettes, et l'on ne voyait plus a quoi elles se rattachaient. */
.programme__title-row .programme__days {
    margin-bottom: 0;
    order: 0;
}

.programme__title-row .programme__actions {
    order: 1;
    margin-left: auto;
}

.programme__title-row .programme__typebar {
    order: 2;
    margin-bottom: 0;
    flex: 1 1 100%;
    justify-content: flex-start;
    gap: 0.75rem;
}

/* Le compteur se colle a droite de sa rangee d'etiquettes, pas au bord de la
   page : c'est le resultat des filtres qui sont juste a cote. */
.programme__typebar .programme__count {
    margin-left: 0.25rem;
}

/* Les trois actions partagent un seul vocabulaire : même pastille, même
   poids. Elles portaient trois traitements différents — pilule ourlée pour
   le téléchargement, segment gris pour la vue, pastille pleine pour les
   filtres — qui hiérarchisaient sans raison des gestes de même rang. */
.programme__actions {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    flex-shrink: 0;
}

.programme__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    min-height: var(--evt-control-h);
    padding: 0 1rem;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: transparent;
    color: var(--color-primary);
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}

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

.programme__action:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

.programme__action.is-active {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--ink-on-dark);
}

/* Sous 64em, les actions se réduisent à leur icône : le titre « PROGRAMME »
   et trois libellés ne cohabitent pas dans 412 px, et c'est cet
   empilement-là qui donnait à la tête de page son air encombré. Repli
   visuel seulement — le nom reste lu à voix haute, et `title` le rend au
   survol sur les appareils qui en ont un. */
@media (width < 64em) {
    .programme__action {
        width: 2.75rem;
        min-height: var(--evt-control-h);
        padding: 0;
        position: relative;
    }

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

    .programme__action--print { display: none; }
}

.programme__filters-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1rem;
    height: 1rem;
    padding: 0 0.3125rem;
    margin-left: 0.125rem;
    border-radius: 999px;
    background: var(--color-accent);
    color: white;
    font-size: 0.625rem;
    font-weight: 700;
    line-height: 1;
}

.programme__action.is-active .programme__filters-badge {
    background: white;
    color: var(--color-primary);
}

/* En mobile le libellé disparaît : la pastille de compteur devient le seul
   signe qu'un filtre est posé. Elle se détache donc sur le coin de l'icône,
   au lieu de suivre un texte qui n'est plus là. */
@media (width < 64em) {
    .programme__filters-badge {
        position: absolute;
        top: -0.125rem;
        right: -0.125rem;
        margin-left: 0;
        border: 2px solid var(--ink-on-dark);
    }
}

/* Tracks (parcours) — badges header (legacy, n'est plus rendu côté
   programme depuis l'introduction des facets, conservé au cas où une
   autre surface les réutilise). */
.programme__tracks {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-xl);
}

.programme__track-badge {
    padding: 0.25rem 0.75rem;
    border-radius: 100px;
    font-size: var(--font-size-xs);
    font-weight: 600;
    background: var(--track-color, var(--color-primary-light));
    color: var(--color-text);
}

/* Facets de filtrage : 3 rangées (Type, Parcours, Thématique) + bouton
   « Tout désélectionner ». Chaque chip est un bouton toggle. */
.programme__facets {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-xl);
    padding: var(--spacing-md);
    border-radius: var(--radius-md);
    background: var(--color-bg-light);
}

/* Le panneau dans le flux est la surface DESKTOP. Sous 1024px — le seuil de
   `.filters-overlay` — c'est le tiroir bas qui prend le relais ; les deux
   partagent `filtersOpen`, donc sans cette bascule ils s'ouvriraient ensemble,
   l'un derrière l'autre. */
@media (width < 64em) {
    .programme > .container > .programme__facets { display: none !important; }
}

/* Dans le tiroir, les facettes ne sont plus une carte posée sur la page :
   le panneau porte déjà son fond et ses marges, et chaque axe prend sa
   hauteur plutôt que de tenir sur une ligne. */
.programme__facets--sheet {
    margin-bottom: 0;
    padding: 0;
    background: transparent;
    gap: var(--spacing-lg);
}

.programme__facets--sheet .programme__facet {
    flex-direction: column;
    align-items: stretch;
    gap: var(--spacing-sm);
}

/* Plancher tactile de `mobile.css` : les pastilles de facette font 0,25 rem
   de padding pour 0,75 rem de texte en desktop, soit une cible bien sous les
   2,75 rem exigés au doigt. */
.programme__facets--sheet .programme__chip {
    min-height: var(--evt-control-h);
    padding-inline: var(--spacing-md);
    font-size: var(--font-size-sm);
}

.programme__facets--sheet .programme__facet-label {
    min-width: 0;
}

.programme__facet {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.programme__facet-label {
    flex-shrink: 0;
    min-width: 5.5rem;
    font-size: 0.6875rem;
    font-weight: 700;
    color: var(--color-text-light);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.programme__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    flex: 1;
    min-width: 0;
}

/* Etiquette de filtre. Elle vivait dans un panneau replie, sur fond blanc et
   sans bordure : posee en permanence dans la page, elle avait l'air d'un texte
   inerte. Fond teinte, comme les etiquettes de type des sessions — c'est le
   meme vocabulaire, la premiere designe ce que la seconde nomme.

   Cible tactile de 44 px : c'est un bouton, on le prend au doigt. */
.programme__chip {
    --chip-color: var(--evt-blue);
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: var(--evt-control-h);
    padding: 0.4375rem 0.8125rem;
    border: 1px solid transparent;
    border-radius: 999px;
    background: var(--evt-tint);
    color: var(--evt-blue);
    font-size: var(--font-size-sm);
    font-weight: 500;
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.programme__chip:hover,
.programme__chip:focus-visible {
    background: var(--evt-tint-cool);
    border-color: var(--chip-color);
    color: var(--evt-ink);
}

.programme__chip.is-active {
    background: var(--chip-color);
    border-color: var(--chip-color);
    color: white;
}

.programme__chip-count {
    font-size: 0.6875rem;
    font-weight: 700;
    padding: 0.0625rem 0.375rem;
    border-radius: 999px;
    background: var(--ink-on-dark-muted);
    color: inherit;
    font-variant-numeric: tabular-nums;
}

.programme__chip.is-active .programme__chip-count {
    background: var(--rule-on-dark);
}

.programme__clear-filters {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin-left: auto;
    padding: 0.25rem 0.625rem;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--color-text-light);
    font-size: 0.75rem;
    font-weight: 500;
    cursor: pointer;
    transition: color 120ms ease;
    flex-shrink: 0;
}

.programme__clear-filters:hover { color: var(--color-primary); }

/* Filtre actif : masquer les éléments qui ne matchent pas. `!important`
   pour overrider l'`x-show` Alpine sur le jour (qui pose un style inline
   `display: none|block` selon la vue). */
.programme__session.is-filter-hidden,
.programme__group.is-filter-hidden,
.programme__slot.is-filter-hidden,
.programme__day.is-filter-hidden {
    display: none !important;
}

/* Tabs jour */
/* Onglets de jour — même motif que la nav du minisite : au-delà de deux ou
   trois jours, un repli coûterait plus de hauteur que le premier créneau. */
/* Selecteur de journee. En pastilles bordees plutot qu'en onglets soulignes :
   la page porte deja DEUX rangs d'onglets au-dessus (les onglets du minisite,
   puis la bascule agenda/liste). Un troisieme rang de la meme forme se lisait
   comme une sous-navigation du site, alors que c'est un filtre. */
.programme__days {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.5rem;
    margin-bottom: var(--spacing-lg);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.programme__days::-webkit-scrollbar { display: none; }

.programme__day-tab {
    display: inline-flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.125rem;
    /* 44 px de haut au minimum : cible tactile. */
    /* Hauteur commune de la barre (cf. `--evt-control-h`). Le rembourrage est
       reduit et les deux lignes serrees pour que le contenu TIENNE dans cette
       hauteur : a 0.5rem et interligne par defaut, les deux lignes faisaient
       59 px et la pastille debordait sa propre hauteur minimale — d'ou trois
       hauteurs de controle differentes dans une meme barre (61, 44 et 36). */
    min-height: var(--evt-control-h);
    padding: 0.25rem 0.875rem;
    white-space: nowrap;
    border: 1px solid var(--evt-rule);
    border-radius: var(--radius-sm);
    background: var(--evt-surface);
    color: var(--evt-blue);
    cursor: pointer;
    transition: color 150ms ease, border-color 150ms ease, background-color 150ms ease;
}

.programme__day-tab:hover {
    border-color: var(--evt-blue);
    color: var(--evt-ink);
}

/* L'etat actif ne tient pas qu'a la couleur : fond plein ET contraste
   inverse, lisibles sans percevoir la teinte. */
.programme__day-tab.is-active {
    background: var(--evt-ink);
    border-color: var(--evt-ink);
    color: var(--ink-on-dark);
}

.programme__day-tab-label { font-size: var(--font-size-sm); font-weight: 700; line-height: 1.2; }
.programme__day-tab-date { font-size: var(--font-size-xs); font-weight: 500; line-height: 1.2; opacity: 0.75; }

/* ── Rangee des etiquettes de type, toujours visible ── */
.programme__typebar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-lg);
}

.programme__typebar .programme__facet {
    margin: 0;
}

/* L'intitule « Type » ne sert a rien ici : quatre etiquettes nommees
   « Atelier », « Pleniere », « Conference inaugurale » se lisent pour ce
   qu'elles sont. Il reste dans le panneau, ou il distingue « Parcours » de
   « Thematique ». */
.programme__typebar .programme__facet-label {
    display: none;
}

.programme__count {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Conteneur jour */
.programme__day { padding-top: var(--spacing-sm); }
.programme__day + .programme__day { margin-top: var(--spacing-2xl); }

/* Titre du jour : la meme grammaire que les sections du minisite — un
   intitule, un trait signature dessous. Il etait rendu en bande verte pleine
   largeur, avec une pastille et une date en vert : trois objets colores pour
   dire « jour 1 », et un aplat qui, sticky, redecoupait la page en deux a
   chaque defilement.

   Il ne colle plus. La barre d'evenement, elle, colle deja et porte le nom de
   l'evenement ; empiler un second bandeau collant coutait 45 px d'ecran
   supplementaires en permanence, sur une page qu'on parcourt precisement en
   defilant. Le jour reste reperable : le titre est gros, et le selecteur de
   journee au-dessus permet d'en isoler une. */
.programme__day-title {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.75rem;
    margin: 0 0 0.5rem;
    font-size: clamp(1.3125rem, 2.5vw, 1.75rem);
    font-weight: 700;
    color: var(--evt-ink);
}

/* Le trait signature, pose sous le titre par un pseudo-element : le gabarit
   n'a pas a rendre une balise vide pour un ornement. */

.programme__day-title-num {
    font-weight: 700;
}

/* `capitalize` mettait une majuscule a CHAQUE mot : « Jeudi 3 Décembre
   2026 ». En francais, le mois ne prend pas de capitale. `::first-letter` ne
   touche que la premiere. */
.programme__day-title-date {
    font-size: var(--font-size-base);
    font-weight: 500;
    color: var(--color-text-light);
}

.programme__day-title-date::first-letter {
    text-transform: uppercase;
}

/* Plus de retrait lateral : il compensait la bande verte pleine largeur du
   titre, qui n'existe plus. La gouttiere horaire s'aligne donc sur le bord du
   contenu, comme les cartes de journee de l'accueil. */
.programme__slots {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Gouttiere horaire de 84 px et rembourrage de 20 px, comme la maquette. Elle
   etait a 104 px et 32 px : sur vingt-six creneaux, l'ecart cumule ajoutait
   pres de 300 px de defilement, et chaque ligne flottait dans son blanc. */
.programme__slot {
    display: grid;
    grid-template-columns: minmax(4.25rem, 5.25rem) minmax(0, 1fr);
    gap: clamp(0.875rem, 2vw, 1.75rem);
    align-items: baseline;
    padding: 1.25rem 0;
}

/* Filet entre tranches horaires. Il etait au gris de bordure du site
   (var(--color-border)) : sur vingt-six lignes, vingt-six traits appuyes font une grille
   de tableau. Le filet doux du minisite (#edf0f6) separe sans decouper. */
.programme__slot + .programme__slot {
    border-top: 1px solid var(--evt-rule-soft);
}

.programme__slot:first-child { padding-top: var(--spacing-md); }

/* L'heure : cran secondaire, comme les autres reperages. Sans taille
   explicite elle heritait du corps de texte (16 px) et pesait autant que le
   titre qu'elle date. Bleu roy, en chiffres a chasse fixe pour que la colonne
   s'aligne d'une ligne a l'autre. */
.programme__slot-time {
    font-size: var(--font-size-sm);
    color: var(--evt-blue);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.programme__slot-time-start {
    font-size: var(--font-size-base);
    font-weight: 700;
}

/* Sur téléphone, la colonne d'heures fixe à 6,5 rem mangeait plus du tiers
   de la largeur utile : les titres tombaient sur quatre lignes et les
   pilules d'action s'empilaient une par ligne. L'heure passe donc en
   surtitre pleine largeur, et le contenu récupère ces ~110 px. */
@media (width < 40em) {
    .programme__slots { padding: 0; }

    .programme__slot {
        display: block;
        padding: var(--spacing-md) 0;
    }

    .programme__slot-time {
        margin-bottom: var(--spacing-sm);
        font-size: var(--font-size-sm);
        letter-spacing: 0.04em;
    }
}

/* Contenu d'un créneau : un ou plusieurs groupes par type empilés (ET implicite) */
.programme__slot-content {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

/* Groupe de sessions partageant le même type dans un même créneau */
.programme__group { --session-color: var(--color-primary); }
.programme__group--cat-program   { --session-color: var(--color-primary); }
.programme__group--cat-social    { --session-color: var(--color-accent); }
.programme__group--cat-logistics { --session-color: var(--color-text-light); }

/* Sessions logistiques et conviviales (pauses, repas, accueil, networking,
   dîner débat…) : ton désaturé pour les distinguer du programme. Eyebrow
   masqué côté template, titre italique gris uniforme entre les deux. */
.programme__group--cat-logistics .programme__session-title,
.programme__group--cat-social .programme__session-title {
    font-style: italic;
    font-weight: 600;
    color: var(--color-text-light);
}

.programme__group-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: var(--spacing-sm);
}

/* Salle poussée à droite de l'eyebrow du groupe — utilisée uniquement
   dans le cas single session (pour les alternatives, chaque card a sa
   propre salle dans son meta). */
.programme__group-room {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
    font-size: 0.75rem;
    color: var(--color-text-light);
}

/* Etiquette de type. Elle etait un aplat plein de `--session-color` avec du
   texte BLANC dessus. Deux defauts : la couleur vient de la saisie admin (un
   type peut etre pose en jaune pale, sur lequel le blanc devient illisible, et
   rien ne le signale au moment de la saisie) ; et sur un programme de vingt-six
   sessions, vingt-six aplats satures se disputent l'attention avec les titres,
   qui sont pourtant ce qu'on vient lire.

   Pastille claire uniforme, texte bleu roy : 8,3:1, quelle que soit la saisie.
   La couleur du type reste portee par le rail vertical des groupes
   (`--session-color`), ou elle est decorative et ou aucun texte ne s'y pose. */
.programme__group-type {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.25rem 0.5625rem;
    border-radius: var(--radius-sm);
    background: var(--evt-tint);
    color: var(--evt-blue);
    /* Meme taille que TOUTES les autres etiquettes du minisite (`.evt-tag`,
       sur-titres, nature d'un appel a contribution) : elle etait a 11 px,
       seule valeur de la page a ne pas figurer dans l'echelle. */
    font-size: var(--font-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.programme__group-choose {
    font-size: var(--font-size-xs);
    font-style: italic;
    color: var(--color-text-light);
}

/* Sessions du groupe — deux régimes seulement :
     - une seule session : pleine largeur, sans cadre ;
     - plusieurs alternatives : la MÊME liste à rail que les sous-sessions
       d'une plénière (`.programme__subsessions`).

   Le cadre gris qui les distinguait portait l'exclusivité — « voici un
   ensemble, prenez-en un » — mais l'eyebrow le dit déjà en toutes lettres,
   « au choix parmi N », juste au-dessus. Le cadre le répétait en plus lourd,
   et tranchait avec un programme par ailleurs sans bordures. Le nombre de
   formes descend de trois à deux : l'ancienne paire côte à côte séparée par
   un « OU » était le même objet — choisir parmi N — sous une troisième
   apparence, dépendante du seul fait qu'il y en ait exactement deux. */
.programme__sessions { display: block; }

/* ── Choix multiples : une grille de cartes, plus un rail ──
   Six ateliers au choix alignes verticalement contre un filet se lisent comme
   une SUITE — on croit qu'ils s'enchainent — alors qu'il faut en prendre un.
   En cartes cote a cote, numerotees, l'alternative se voit du premier coup
   d'oeil, et six titres tiennent sur deux rangees au lieu de six.

   Meme traitement pour les interventions d'une pleniere (`__subsessions`) :
   c'est le meme objet, une liste d'elements egaux sous un creneau. */
.programme__sessions--alternatives {
    display: grid;
    /* `auto-fit` et non `auto-fill` : les pistes vides sont FUSIONNEES, donc
       deux communications d'une pleniere se partagent toute la rangee au lieu
       d'occuper deux colonnes sur quatre et de laisser la moitie droite vide.
       Un titre long y passait sur quatre lignes dans 265 px alors que 1160
       etaient disponibles. Avec six ateliers, la grille garde ses quatre
       pistes et les deux dernieres cartes reprennent la largeur des
       premieres : le calibrage reste le meme d'une rangee a l'autre. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15.625rem), 1fr));
    gap: 0.75rem;
    padding-left: 0;
    border-left: 0;
    /* Hauteur EGALE dans une rangee. C'est ce que permet le fond teinte : sur
       des cartes BLANCHES a filet fin, un cadre vide sous un titre court se
       voyait comme un trou, d'ou la consigne inverse a l'origine. Une carte
       teintee qui descend un peu plus bas ne se lit pas comme un vide, tandis
       que des hauteurs inegales, elles, dessinent une rangee dentelee — et la
       pastille de rediffusion, calee en bas, n'alignerait plus rien. */
    align-items: stretch;
}


/* Carte session — pas de bordure, typo + espacement. Le titre s'enchaîne
   directement sous l'eyebrow du groupe, qui sert d'attache visuelle. */
.programme__session {
    padding: 0;
    border-radius: var(--radius-md);
    background: transparent;
    border: 0;
}

/* Trois regles heritees de l'ancienne presentation en LISTE ont ete retirees
   ici : un filet entre elements consecutifs (qui, dans une grille, dessine un
   trait au-dessus de chaque carte sauf la premiere), un rembourrage
   `12px 0` et un `border-radius: 0`. Portees par `.programme__sessions--alternatives >
   .programme__session` (0,2,0), elles l'emportaient sur la regle de carte
   (0,1,0) : les cartes rendaient sans coins ni rembourrage lateral, et le
   programme paraissait brouillon sans qu'on voie pourquoi. */

/* Le code ne passe jamais à la ligne : il reste la colonne d'attaque de
   la liste. Autorisé à se replier, il repoussait le titre sous lui une
   ligne sur deux, et le bord gauche de la liste devenait dentelé. */
.programme__sessions--alternatives .programme__session-title-row,
.programme__subsession-title-row {
    flex-wrap: nowrap;
    align-items: baseline;
}

/* Plus de largeur plancher sur le code. Elle valait quand les alternatives
   s'empilaient en LISTE : les codes formaient une colonne, et il fallait
   aligner les titres derriere le plus long. Depuis qu'elles sont en cartes
   cote a cote, chaque code est seul dans la sienne — la largeur plancher n'y
   aligne plus rien et creuse 52 px de vide entre le numero et le titre, sur
   une carte qui en fait 255. */
.programme__sessions--alternatives .programme__session-code,
.programme__subsession-title-row .programme__session-code {
    align-self: baseline;
    min-width: 0;
}

/* Title-row : code + titre de session. Les actions (« Voir le résumé »,
   « Voir le replay ») descendent dans .programme__session-actions. */
.programme__session-title-row {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.375rem 0.625rem;
}

/* ── Echelle du programme, a crans NETS ──
   Titre de journee 21-28 px, titre de session imposee 18, titre de choix 15,
   texte secondaire 14, etiquette 13. Les crans etaient trop rapproches
   (19 / 16 / 16) : trois niveaux a trois pixels d'ecart ne se lisent pas comme
   une hierarchie, ils se lisent comme une irregularite. */
.programme__session-title {
    font-size: var(--font-size-lg);
    font-weight: 600;
    margin: 0;
    color: var(--evt-ink);
    line-height: 1.35;
}

/* Code de session (ex : « A3 » pour un atelier) — pastille discrète
   devant le titre. Aide les participants a reperer un atelier sur le
   plan / la signaletique. */
/* Declencheur de rediffusion dans la carte : blanc sur le fond pale, pour la
   meme raison que la pastille ci-dessous. */
.programme__subsession .programme__session-action,
.programme__session--alternative .programme__session-action {
    background: var(--surface-2);
    border-color: var(--evt-rule);
    color: var(--evt-blue);
}

.programme__subsession .programme__session-action:hover,
.programme__session--alternative .programme__session-action:hover {
    border-color: var(--color-primary);
    background: var(--surface-2);
    color: var(--color-primary-dark);
}

/* ── Textes de la carte de choix ──
   Le titre en marine, un cran plus fonce que le corps : c'est lui qui doit
   sortir en premier dans la carte. */
.programme__subsession .programme__session-title,
.programme__session--alternative .programme__session-title,
.programme__subsession .programme__subsession-title {
    color: var(--color-primary-dark);
}

/* Titre de CHOIX : nettement plus petit qu'un titre de session imposee. A
   l'echelle des titres de premier rang (21 px) dans une carte de 250 px, il
   partait sur trois lignes et se cognait aux bords — c'est ce qui donnait au
   programme son air de brouillon. */
.programme__session--alternative .programme__session-title,
.programme__subsession .programme__subsession-title,
.programme__subsession .programme__session-title {
    font-size: var(--font-size-md);
    font-weight: 600;
    line-height: 1.45;
}

/* Le numero garde la pastille claire des codes du programme : sur le fond
   `--evt-tint`, c'est le contraste du TEXTE qui compte (bleu roy, 8,3:1), pas
   un aplat de plus. */
.programme__subsession .programme__session-code,
.programme__session--alternative .programme__session-code {
    color: var(--evt-blue);
}

/* ── TOUT le contenu d'une carte suit son fond ──
   Une carte ne porte pas qu'un titre : elle peut porter une description, une
   salle, des intervenants (nommes, lies ou non a une fiche), un separateur et
   le marqueur « intervention filmee ». Chaque passage d'un fond a l'autre doit
   les reprendre TOUS — c'est ce qui avait ete manque au passage sur l'aplat
   marine, ou « Intervenants : » rendait a 1,9:1 et le pictogramme de
   rediffusion en bleu roy SUR bleu roy, donc invisible. Verification : relever
   les classes reellement presentes dans le bloc, pas celles qu'on croit y
   trouver. */
.programme__subsession .programme__session-desc,
.programme__session--alternative .programme__session-desc,
.programme__subsession .programme__subsession-desc,
.programme__subsession .programme__session-speakers,
.programme__session--alternative .programme__session-speakers,
.programme__subsession .programme__session-room,
.programme__session--alternative .programme__session-room,
.programme__subsession .programme__session-speaker-sep,
.programme__session--alternative .programme__session-speaker-sep {
    color: var(--color-text-light);
}

/* Le role n'est plus ecrit : c'est un pictogramme (une silhouette, deux quand
   ils sont plusieurs), et le mot vit en `sr-only`. Ecrit en capitales,
   « INTERVENANTS : » occupait une ligne entiere d'une carte de 250 px et
   rivalisait avec le titre de la session, pour ne nommer qu'une etiquette de
   champ dont la ligne suivante — des noms de personnes — dit deja la nature. */
.programme__subsession .programme__session-speakers-label,
.programme__session--alternative .programme__session-speakers-label {
    color: var(--color-text-light);
}

/* Sur le fond clair, les deux formes de nom reprennent le traitement commun :
   bleu roy souligne quand il mene a une biographie, texte simple sinon. */
.programme__subsession .programme__session-speaker,
.programme__session--alternative .programme__session-speaker {
    color: var(--color-primary);
}

.programme__subsession .programme__session-speaker--static,
.programme__session--alternative .programme__session-speaker--static {
    color: var(--color-text);
}

/* La pastille de rediffusion se detache du fond de la carte : blanche sur
   `--evt-tint`, elle serait invisible en reprenant ce meme fond (c'est sa
   couleur par defaut). */
.programme__subsession .programme__session-filmed,
.programme__session--alternative .programme__session-filmed {
    border-color: var(--evt-rule);
    background: var(--surface-2);
}

/* ── Rythme interne d'une carte de choix ──
   Le corps de carte est une COLONNE FLEX a `gap`, et non une pile de marges.
   Deux raisons, dans cet ordre :

   1. Un seul cran (0,5 rem) entre le titre et ce qui le documente. Les regles
      heritees de la presentation en LISTE posaient 4 px : dans une carte, le
      titre et « Intervenants : » se touchaient, et l'ensemble se lisait comme
      un seul bloc de texte.
   2. La pastille de rediffusion se cale en BAS de carte (`margin-top: auto`).
      Les cartes d'un meme creneau ont deja la meme hauteur — la grille les
      etire — mais des textes de longueurs differentes : posee a la suite du
      texte, la pastille flottait a trois hauteurs distinctes sur une meme
      rangee. En bas, elles forment une ligne.

   Le `gap` est ce qui rend le point 2 sur : une marge automatique absorbe
   l'espace libre, mais tombe a zero quand il n'y en a plus — le `gap`, lui,
   s'ajoute toujours, donc la pastille ne peut jamais toucher le texte. */
.programme__subsession-body,
.programme__session--alternative > .programme__session-body {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 0.5rem;
}

.programme__subsession-body > *,
.programme__session--alternative > .programme__session-body > * {
    margin-top: 0;
}

.programme__subsession .programme__session-filmed,
.programme__session--alternative .programme__session-filmed {
    margin-top: auto;
}

/* Le titre de session EST le lien vers sa page. Couleur du texte au repos,
   rouge au survol : un titre entierement bleu sur vingt-six lignes ferait une
   colonne de liens, ou l'oeil ne distingue plus la hierarchie. */
.programme__session-title a,
.programme__subsession-title a {
    color: inherit;
    transition: color var(--transition-fast);
}

.programme__session-title a:hover,
.programme__session-title a:focus-visible,
.programme__subsession-title a:hover,
.programme__subsession-title a:focus-visible {
    color: var(--evt-cta);
}

/* Dans une carte, le titre ne change PAS de couleur au survol : c'est la carte
   entiere qui repond, par son anneau. Un titre qui s'allume pendant que la
   carte s'entoure donnait deux reponses pour un seul geste. */
.programme__subsession .programme__session-title a:hover,
.programme__session--alternative .programme__session-title a:hover,
.programme__subsession .programme__subsession-title a:hover {
    color: inherit;
}

/* Code de session : le reperage que porte la signaletique sur place et le
   bulletin d'inscription. Rendu comme le numero d'une section — vert, sans
   pastille — et non plus comme une etiquette bleue : deux etiquettes de meme
   forme sur une ligne (le type, puis le code) se lisaient comme deux
   categories, alors que la seconde est un numero. */
.programme__session-code {
    flex-shrink: 0;
    align-self: baseline;
    display: inline-flex;
    align-items: center;
    padding: 0;
    border-radius: 0;
    background: none;
    color: var(--evt-signature);
    font-size: var(--font-size-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.programme__session-code--sub {
    font-size: calc(var(--font-size-xs) * 0.95);
    padding: 0.05rem 0.35rem;
}

.programme__session-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: var(--spacing-sm);
}

.programme__session-room,
.programme__session-track {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.75rem;
    font-weight: 500;
}

.programme__session-room { color: var(--color-text-light); }
.programme__session-track {
    padding: 0.125rem 0.5rem;
    border-radius: var(--radius-sm);
    background: var(--track-color, var(--color-primary-light));
    color: var(--color-text);
}

/* Texte bleu roy, mesure a 7,2:1 sur son fond : le CONTRASTE n'a jamais ete le
   defaut, et la docblock qui annoncait 8,3:1 le disait deja — a un chiffre
   pres, et surtout a cote de la question.

   CE QUI NE SE LISAIT PAS, C'ETAIT LA PUCE. Son fond valait `--evt-tint`
   (238, 241, 249) sur une ligne de programme a (243, 245, 246) : cinq points
   d'ecart sur chaque canal, donc aucune forme. On lisait une ligne de texte
   bleu egaree sous les intervenants, sans comprendre que c'etait une
   etiquette de thematique.

   D'ou le FILET plutot qu'un fond plus fonce : c'est le contour qui fait
   l'etiquette, et il tient sur les DEUX surfaces ou cette puce se rend — la
   ligne teintee d'un creneau simultane comme la ligne blanche ordinaire.
   Foncer le fond aurait demande une valeur par surface, donc une divergence a
   la premiere nouvelle. */
.programme__session-tag {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.5rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--evt-blue);
    font-size: 0.75rem;
    font-weight: 500;
}

/* Intervenants de la session : « Avec Nom1, Nom2 » sous la description.
   Affiché seulement si event.features.speakers est activé. */
.programme__session-speakers {
    margin-top: var(--spacing-sm);
    font-size: var(--font-size-sm);
    color: var(--color-text);
}

/* Le pictogramme de role, aligne sur la premiere ligne de noms. `translateY`
   plutot que `vertical-align` : le glyphe est cale sur sa boite, pas sur la
   ligne de base du texte, et il flottait un pixel trop haut. */
.programme__session-speakers-label {
    display: inline-flex;
    margin-right: 0.375rem;
    color: var(--color-text-light);
    transform: translateY(2px);
}

.programme__session-speakers-label svg {
    flex-shrink: 0;
}

.programme__session-speaker {
    color: var(--color-primary);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    transition: color 120ms ease;
}

.programme__session-speaker:hover { color: var(--color-primary-dark); }

/* Le survol d'un nom epaissit AUSSI le soulignement : dans une carte, le seul
   changement de teinte se remarque mal a cote du titre et du filet. */
.programme__subsession .programme__session-speaker:hover,
.programme__subsession .programme__session-speaker:focus-visible,
.programme__session--alternative .programme__session-speaker:hover,
.programme__session--alternative .programme__session-speaker:focus-visible {
    text-decoration-thickness: 2px;
}

/* Intervenant sans biographie publique : nom affiché en texte simple,
   sans lien (pas d'underline ni de couleur de lien trompeuse). */
.programme__session-speaker--static {
    color: var(--color-text);
    text-decoration: none;
}

.programme__session-speaker-sep {
    margin-right: 0.25rem;
    color: var(--color-text-light);
}

/* Ligne d'actions d'une session : « Voir le résumé » + « Voir le replay »,
   pilules homogènes alignées sur une même ligne (programme → résumés / replays). */
.programme__session-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-top: var(--spacing-sm);
}

.programme__session-action {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.55rem;
    border: 1px solid var(--color-primary);
    border-radius: 999px;
    background: none;
    color: var(--color-primary);
    font: inherit;
    font-size: var(--font-size-xs);
    line-height: 1.3;
    text-decoration: none;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}

.programme__session-action:hover { background: var(--color-primary); color: var(--ink-on-dark); }
.programme__session-action-icon { flex: 0 0 auto; }

/* Variante résumé : même pilule, teinte neutre pour distinguer la lecture
   du résumé (texte) de celle du replay (vidéo). */
.programme__session-action--abstract {
    border-color: var(--color-border);
    color: var(--color-text-light);
}

.programme__session-action--abstract:hover {
    background: var(--color-bg-light);
    border-color: var(--color-text-light);
    color: var(--color-text);
}

/* Abstract révélé sous la description par le toggle title-row. */
.programme__session-abstract {
    margin-top: var(--spacing-sm);
    padding: var(--spacing-md);
    background: var(--color-bg-light);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    color: var(--color-text);
    line-height: 1.6;
}

.programme__session-abstract > :first-child { margin-top: 0; }
.programme__session-abstract > :last-child { margin-bottom: 0; }

/* Bloc parcours + thématique sous la description : signale la
   classification (à qui s'adresse / sur quoi porte la session) une
   fois le contenu lu, plutôt que de polluer l'attaque visuelle. */
.programme__session-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-top: var(--spacing-sm);
}

.programme__session-chips .programme__session-track,
.programme__session-chips .programme__session-tag {
    font-size: 0.75rem;
    font-weight: 500;
}

.programme__session-desc {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    margin-top: var(--spacing-sm);
    line-height: 1.5;
}

/* Sous-sessions — les interventions qui composent une plénière.
   Sans marque d'appartenance, elles se lisaient comme une suite de
   paragraphes détachés du titre qui les gouverne : même graisse, même
   couleur, aucun retrait. Un rail vertical à la couleur du type les
   rattache visuellement à leur session, et un filet fin entre chaque
   entrée redonne un rythme régulier quand elles portent des
   intervenants, un résumé ou un replay de hauteurs inégales. */
.programme__subsessions {
    list-style: none;
    display: grid;
    /* `auto-fit` et non `auto-fill` : les pistes vides sont FUSIONNEES, donc
       deux communications d'une pleniere se partagent toute la rangee au lieu
       d'occuper deux colonnes sur quatre et de laisser la moitie droite vide.
       Un titre long y passait sur quatre lignes dans 265 px alors que 1160
       etaient disponibles. Avec six ateliers, la grille garde ses quatre
       pistes et les deux dernieres cartes reprennent la largeur des
       premieres : le calibrage reste le meme d'une rangee a l'autre. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15.625rem), 1fr));
    gap: 0.75rem;
    margin: var(--spacing-md) 0 0;
    padding: 0;
    border: 0;
    /* Hauteur EGALE dans une rangee. La consigne inverse valait quand les
       cartes etaient blanches a filet fin : un cadre vide sous un titre court
       se voyait comme un trou. Depuis qu'elles sont des aplats pleins, c'est
       l'inverse — des hauteurs inegales dessinent une rangee dentelee, et un
       aplat qui descend un peu plus bas ne se lit pas comme un vide. */
    align-items: stretch;
}

/* ── La carte de CHOIX, en bleu tres pale ──
   Elle etait blanche a filet fin : sur un programme qui empile des rangees de
   texte, six cartes blanches sur fond blanc ne se detachaient pas, et la page
   paraissait brouillonne — on ne voyait pas d'un coup d'oeil ou commencait un
   choix et ou finissait la liste.

   Elle est ensuite passee au degrade marine plein — trop lourd : six aplats
   sombres par creneau, sur un programme qui en compte plusieurs par jour,
   assombrissent toute la page et tirent l'oeil vers eux plus fort que les
   titres de session eux-memes.

   Le juste milieu est le fond `--evt-tint` (le bleu tres pale des pastilles du
   minisite) borde d'un filet : la carte reste un OBJET — c'est ce qui
   distingue « voici six ateliers, prenez-en un » du fil des sessions imposees,
   qui restent en texte nu sur le fond de page — sans peser comme un aplat.

   PAS de compteur CSS : ces sessions portent deja un CODE saisi en
   administration (« A01 », « 3 »), qui est leur identifiant reel — celui de la
   signaletique sur place et du bulletin d'inscription.

   Une COLONNE FLEX et non une grille a deux colonnes : la carte contient
   plusieurs enfants de premier niveau (titre, salle, description,
   intervenants, actions), qu'une grille repartirait dans les cellules au lieu
   de les empiler. La colonne est ce qui permet a la pastille de rediffusion de
   se caler en bas (cf. « Rythme interne d'une carte de choix » plus haut) — un
   `margin-top: auto` ne pousse rien dans un bloc. */
.programme__subsession,
.programme__session--alternative {
    display: flex;
    flex-direction: column;
    position: relative;
    padding: 1rem 1.125rem;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    background: var(--evt-tint);
    color: var(--color-text);
    transition: box-shadow var(--transition-fast), border-color var(--transition-fast);
}

/* ── TOUTE la carte est cliquable, pas seulement son titre ──
   Le lien du titre projette une zone cliquable sur la carte entiere. C'est ce
   qu'on attend d'une carte : viser trois mots dans un aplat de 250 px, alors
   que tout le rectangle a l'air d'un bouton, est une cible inutilement etroite
   — et le survol ne repondait que sur le texte, ce qui donnait un effet
   incoherent avec l'anneau qui, lui, entourait la carte.

   Un pseudo-element etendu, et non une balise `<a>` enveloppante : celle-ci
   engloberait les liens vers les fiches d'intervenants, et un lien dans un
   lien n'est pas un HTML valide. Les liens internes remontent au-dessus de la
   zone (`z-index: 1`) et restent donc cliquables. */
.programme__subsession .programme__subsession-title a::after,
.programme__subsession .programme__session-title a::after,
.programme__session--alternative .programme__session-title a::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

/* Les liens de la carte autres que le titre passent AU-DESSUS de la zone
   etendue : sans cela, cliquer le nom d'un intervenant ouvrirait la session. */
.programme__subsession a:not(.programme__subsession-title a):not(.programme__session-title a),
.programme__session--alternative a:not(.programme__session-title a),
.programme__subsession button,
.programme__session--alternative button {
    position: relative;
    z-index: 1;
}

/* Au survol, un anneau bleu roy plutot qu'un changement de fond : le fond pale
   est ce qui range la carte dans la page, l'assombrir au survol la ferait
   changer de nature sous le curseur. */
.programme__subsession:hover,
.programme__session--alternative:hover,
.programme__subsession:focus-within,
.programme__session--alternative:focus-within {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 1px var(--color-primary);
}

/* La zone etendue n'a pas de contour propre : au clavier, c'est l'anneau de la
   carte qui signale le focus (`:focus-within` ci-dessus). Sans cette
   suppression, le navigateur dessinerait en plus un liseré autour des seuls
   mots du titre. */
.programme__subsession .programme__subsession-title a:focus-visible,
.programme__subsession .programme__session-title a:focus-visible,
.programme__session--alternative .programme__session-title a:focus-visible {
    outline: none;
}

/* Une carte masquee par un filtre ne laisse pas de trou dans la grille. */
.programme__subsession.is-filter-hidden,
.programme__session--alternative.is-filter-hidden {
    display: none;
}

/* Trois regles heritees de l'ancienne presentation en LISTE ont ete retirees
   ici, exactement comme pour les alternatives : `:first-child { padding-top: 0 }`,
   `:last-child { padding-bottom: 0 }` et un filet entre elements consecutifs.

   Dans une GRILLE, elles font trois degats invisibles a la relecture du CSS :
   la premiere carte perd son rembourrage haut — son texte demarrait 16 px plus
   haut que celui des deux autres, ce qui donnait trois cartes de meme hauteur
   dont les contenus ne s'alignaient pas — et chaque carte sauf la premiere
   recevait un trait en travers du degrade. */

.programme__subsession-title-row {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.375rem 0.625rem;
}

.programme__subsession-title {
    font-size: var(--font-size-md);
    font-weight: 600;
    margin: 0;
    line-height: 1.45;
    color: var(--color-text);
}

.programme__subsession-desc {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    margin-top: var(--spacing-xs);
    line-height: 1.5;
}

/* Sous les interventions, le même rythme que dans une carte session :
   intervenants et actions décollent d'un cran, pas de deux. */
.programme__subsession .programme__session-speakers,
.programme__subsession .programme__session-actions {
    margin-top: var(--spacing-xs);
}

/* ══ LA VOIE DEVIENT UNE CARTE ═══════════════════════════════════════════

   C'est la forme de la maquette « Pages minisite » : chaque voie d'un
   creneau — une pleniere, un atelier, une table ronde — est une carte
   blanche bordee, coiffee d'un bandeau gris qui porte le format, le nombre
   d'options et la salle. Les interventions vivent dans le corps.

   CE BLOC ANNULE UNE DECISION ECRITE PLUS HAUT DANS CETTE FEUILLE, et il
   faut le dire plutot que de laisser deux commentaires se contredire. Le
   raisonnement d'origine tenait : « le cadre gris portait l'exclusivite —
   voici un ensemble, prenez-en un — mais l'eyebrow le dit deja en toutes
   lettres, et il tranchait avec un programme par ailleurs sans bordures ».
   Il visait le cadre qui entourait LES ALTERNATIVES, pour dire « au choix ».

   Ce n'est pas ce que la carte fait ici. Elle n'exprime plus l'exclusivite :
   elle donne un CONTENANT a la voie, choix ou pas, et c'est le bandeau qui
   rattache le format et la salle a ce qu'ils qualifient. Sur vingt-six
   creneaux sans aucun contenant, l'oeil ne savait plus ou une voie
   commencait ni ou elle finissait — la seule frontiere etait le filet
   horaire, qui separe des HEURES, pas des seances.

   Le rayon vient de la grammaire du minisite (`--evt-radius`, 8 px, mesure
   des cartes de journee de l'accueil), pas des 16 px bruts de la maquette :
   deux rayons differents sur la meme page se voient, et c'est la coherence
   interne qui l'emporte sur le releve pixel. */
.programme__group--cat-program {
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    /* Le bandeau porte un aplat jusqu'au bord : sans decoupe, ses angles
       depasseraient ceux de la carte. */
    overflow: hidden;
}

.programme__group--cat-program .programme__group-header {
    /* La marge basse devient le rembourrage du bandeau : deux espacements
       superposes auraient decolle le filet de son contenu. */
    margin-bottom: 0;
    padding: 0.625rem 0.875rem;
    background: var(--evt-surface-muted);
    border-bottom: 1px solid var(--evt-rule-soft);
}

/* La salle se cale a droite du bandeau — elle y est deja poussee par
   `margin-left: auto`, il ne lui manquait qu'un contenant. */
.programme__group--cat-program .programme__sessions {
    padding: 0.875rem;
}

/* ── Le creneau de SERVICE : ni carte, ni voie ──
   Pause, dejeuner, accueil, cocktail. La maquette leur donne une forme a
   part, et elle a raison : ce ne sont pas des seances qu'on choisit, ce sont
   des reperes dans la journee. Encart pale a filet POINTILLE — le pointille
   dit « ceci n'est pas du programme » sans avoir a l'ecrire — et tout sur une
   ligne, le lieu pousse a droite. */
.programme__group--cat-logistics,
.programme__group--cat-social {
    padding: 0.625rem 1rem;
    border: 1px dashed var(--color-border);
    border-radius: var(--evt-radius);
    background: var(--evt-surface-muted);
}

.programme__group--cat-logistics .programme__session,
.programme__group--cat-social .programme__session {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.875rem;
}

.programme__group--cat-logistics .programme__session-desc,
.programme__group--cat-social .programme__session-desc {
    margin: 0;
}

.programme__group--cat-logistics .programme__session-meta,
.programme__group--cat-social .programme__session-meta {
    margin: 0 0 0 auto;
}

/* ══════════════════════════════════════════════════════════════
   Impression — programme événement

   Stratégie : un programme dense de 2-3 jours doit tenir sur 2 pages
   max — pas 6. Objectifs :
     - masquer header minisite, navigation, toolbar, filtres, footer ;
     - dégrader l'abstract (déjà cachable par toggle) en bruit muet ;
     - réduire fortement padding/gap/font-size sans casser la lecture ;
     - jours enchaînés sans page-break-before systématique : on laisse
       le contenu couler, seul le titre du jour reste solidaire de son
       premier slot ;
     - sessions et slots `page-break-inside: avoid` pour éviter les
       coupes au milieu d'un groupe.

   Le cartouche (`.print-page`) et l'en-tête courant (`@page @top-right`)
   sont gérés par `components/print.css` — on n'y touche pas ici, on se
   contente d'ajouter les hides spécifiques au programme.
   ══════════════════════════════════════════════════════════════ */
@media print {
    /* ── Hides interface mini-site + outils interactifs ── */
    body > header,
    .minisite-header,
    .minisite-topbar,
    .minisite-nav,
    /* Remplace `.minisite-banner`, supprime avec la refonte 2026-08-20 : le
       titre imprime est celui du cartouche `_print_page`, pas celui de
       l'en-tete d'ecran, qui ferait doublon. */
    .minisite-pagehead,
    .minisite-deadline,
    .minisite-hero__bookmark,
    .programme__actions,
    .programme__days,
    .programme__facets,
    .filters-overlay,
    .programme__session-actions,
    .programme__session-abstract,
    .floating-actions,
    footer,
    .footer,
    .site-footer { display: none !important; }

    /* ── Container plein papier ── */
    .container { max-width: none; padding: 0; margin: 0; }
    .minisite-content { padding: 0; }
    .programme { padding: 0; }

    /* ── Header de la page ── */
    .programme__header { margin: 0 0 0.2cm; }
    .minisite-content__page-title {
        font-size: 12pt;
        margin: 0;
    }

    /* ── Wrapper : pas de bordure tab ── */
    .programme__wrapper { border: 0; padding: 0; }

    /* ── Reset des marges p/ul héritées de print.css (0.3em sinon)
         qui s'accumulent sur des dizaines de sessions. On gère
         localement avec margin-top par bloc à la place. ── */
    .programme p,
    .programme ul,
    .programme ol,
    .programme h2,
    .programme h3,
    .programme h4,
    .programme h5 {
        margin-top: 0;
        margin-bottom: 0;
    }

    /* ── Jour : enchaîné, le bandeau vert devient un simple titre noir
         pour éviter de gaspiller des aplats colorés à l'impression. ── */
    .programme__day {
        display: block !important;
        page-break-before: auto;
        padding-top: 0;
    }
    .programme__day + .programme__day {
        margin-top: 0.2cm;
        page-break-before: auto;
    }

    .programme__day-title {
        position: static !important;
        display: block;
        margin: 0 0 0.12cm;
        padding: 0.05cm 0 0.08cm;
        border-radius: 0;
        border-bottom: 1.2pt solid var(--print-ink);
        background: transparent !important;
        color: var(--print-ink) !important;
        font-size: 10pt;
        page-break-after: avoid;
        page-break-inside: avoid;
        line-height: 1.2;
    }

    .programme__day-title-num {
        display: inline-block;
        padding: 0 0.18cm;
        margin-right: 0.15cm;
        background: var(--print-ink) !important;
        color: var(--print-paper) !important;
        font-size: 7.5pt;
    }

    .programme__day-title-date {
        font-size: 9.5pt;
        color: var(--print-ink) !important;
        font-weight: 600;
    }

    /* ── Slots : grille compacte, pas de padding latéral, divider fin ── */
    .programme__slots { padding: 0 !important; margin: 0; }

    .programme__slot {
        grid-template-columns: 1.4cm 1fr;
        gap: 0.18cm;
        padding: 0.08cm 0;
        /* Pas de `page-break-inside: avoid` ici : un slot qui contient
           plusieurs groupes peut faire 10+ cm et provoquerait un gros
           blanc en bas de page. On laisse couler ; seules les sessions
           individuelles restent solidaires (cf. ci-dessous). */
    }

    .programme__slot:first-child { padding-top: 0; }

    .programme__slot + .programme__slot {
        border-top: 0.4pt solid var(--print-rule);
    }

    .programme__slot-time { color: var(--print-ink); }
    .programme__slot-time-start { font-size: 8pt; font-weight: 700; }

    /* ── Contenu du slot : gap minimal entre groupes ── */
    .programme__slot-content { gap: 0.12cm; }

    /* ── Groupe : pas de fond, eyebrow noir compact. Pas d'avoid ici
         non plus : sur des plénières avec sous-sessions, le groupe fait
         plusieurs cm et casse la pagination s'il refuse de se couper. ── */
    .programme__group { }
    .programme__group-header {
        gap: 0.15cm;
        margin-bottom: 0.04cm;
    }
    .programme__group-type {
        background: transparent !important;
        color: var(--print-ink) !important;
        border: 0.5pt solid var(--print-ink);
        padding: 0 0.12cm;
        font-size: 6.5pt;
        line-height: 1.4;
    }
    .programme__group-room {
        font-size: 7pt;
        color: var(--print-ink) !important;
    }
    .programme__group-choose {
        font-size: 7pt;
        color: var(--print-ink-soft) !important;
    }

    /* ── Sessions : suppression aplats, padding réduit ── */
    .programme__session {
        background: transparent !important;
        border: 0 !important;
        padding: 0 !important;
        page-break-inside: avoid;
    }
    /* Alternatives : même rail fin que les sous-sessions, aucun aplat. */
    .programme__sessions--alternatives {
        background: transparent !important;
        padding-left: 0.2cm;
        border-left: 0.5pt solid var(--print-rule) !important;
    }
    .programme__sessions--alternatives > .programme__session--alternative {
        border: 0 !important;
        padding: 0.03cm 0 !important;
    }
    .programme__sessions--alternatives > .programme__session + .programme__session {
        border-top: 0 !important;
    }

    .programme__session-title-row { gap: 0.1cm 0.4cm; }
    .programme__session-title { font-size: 8.5pt; line-height: 1.2; }
    .programme__session-desc {
        font-size: 7.5pt;
        color: var(--print-ink-soft) !important;
        margin-top: 0.04cm;
        line-height: 1.25;
    }
    .programme__session-meta { margin-top: 0.02cm; gap: 0.2cm; }
    .programme__session-room { color: var(--print-ink) !important; font-size: 7pt; }

    /* ── Intervenants compacts : pas d'underline, pas de couleur ── */
    .programme__session-speakers {
        margin-top: 0.04cm;
        font-size: 7.5pt;
        color: var(--print-ink) !important;
        line-height: 1.25;
    }
    .programme__session-speakers-label { color: var(--print-ink-soft) !important; font-weight: 600; }
    .programme__session-speaker {
        color: var(--print-ink) !important;
        text-decoration: none !important;
    }
    .programme__session-speaker-sep { color: var(--print-ink-soft) !important; }

    /* ── Chips parcours + thématique : texte simple, pas de fond ── */
    .programme__session-chips {
        gap: 0.1cm;
        margin-top: 0.04cm;
    }
    .programme__session-chips .programme__session-track,
    .programme__session-chips .programme__session-tag {
        background: transparent !important;
        color: var(--print-ink-soft) !important;
        border: 0.4pt solid var(--print-rule);
        padding: 0 0.12cm;
        font-size: 6.5pt;
        line-height: 1.4;
    }

    /* ── Sous-sessions : retrait modéré, rail noir fin ── */
    .programme__subsessions {
        margin: 0.05cm 0 0;
        padding: 0 0 0 0.2cm;
        border-left: 0.5pt solid var(--print-rule) !important;
    }
    .programme__subsession {
        padding: 0.02cm 0;
        page-break-inside: avoid;
    }
    .programme__subsession + .programme__subsession { border-top: 0 !important; }
    .programme__subsession-title { font-size: 8pt; line-height: 1.2; }
    .programme__subsession-desc { font-size: 7pt; color: var(--print-ink-soft) !important; line-height: 1.25; margin-top: 0.02cm; }

    /* ── Liens : noir, pas d'underline parasite (déjà géré par le
         reset global de print.css, on insiste sur les surfaces qui
         survivent). ── */
    .programme__session a { color: var(--print-ink) !important; }
}

/* Les regles `.speakers__*` qui vivaient ici sont supprimees : la page des
   intervenants rend desormais le meme trombinoscope que l'annuaire des
   portraits (`components/people-grid.css`). Elles n'avaient qu'un appelant, et
   ce dernier presentait les memes personnes autrement que le reste du site.
   Ne pas les reintroduire : une seconde grammaire de carte-personne se lit
   comme un second site. */

/* Infos pratiques */
/* ══════════════════════════════════════════════════════════════
   Pratique (infos) — minisite event

   Layout : container 60rem, TOC sticky sur lg+ (10rem à gauche),
   main content (50rem). Stack mobile (TOC masquée — pour gagner
   de la verticalité). Sections en bandeau vert ANCESU (vocabulaire
   inscription/programme).
   ══════════════════════════════════════════════════════════════ */

/* Fond retire : depuis que le minisite est bleu de bout en bout, c'est la
   CARTE de contenu qui porte le blanc. Un fond blanc pose sur la SECTION
   s'etend sur toute la largeur et recouvre le bleu de part et d'autre de la
   carte — c'est ce qui donnait deux bandes blanches le long du contenu. */

.infos__header {
    margin-bottom: var(--spacing-xl);
}

.infos__header .minisite-content__page-title {
    margin-bottom: 0;
    line-height: 1;
    font-weight: 600;
}

/* ── Layout : TOC + main sur lg+, stack sinon ── */
/* Deux colonnes de CONTENU, plus un sommaire et son contenu. La grille est
   portee par `.evt-split` ; il ne reste ici que ce qui lui est propre. */
.infos__layout {
    align-items: start;
}

.infos__main,
.infos__side {
    min-width: 0;
    display: grid;
    gap: var(--evt-section-y);
    align-content: start;
}

/* La premiere section de chaque colonne demarre au meme niveau. */
.infos__main > .infos__section:first-child,
.infos__side > .infos__section:first-child {
    margin-top: 0;
}

/* ── Main content ── */
.infos__main {
    min-width: 0;
}

.infos__section {
    margin: 0;
}

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

/* Meme grammaire que les intitules de section de l'inscription et du
   programme : un titre, un trait signature. Plus de bande vert pale, ou le
   vert de marque rend 2,1:1 — sous le seuil AA pour du texte. */
.infos__section-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin: 0 0 0.5rem;
    font-size: clamp(1.25rem, 2.2vw, 1.5rem);
    font-weight: 700;
    color: var(--evt-ink);
}

.infos__section-title svg {
    flex-shrink: 0;
    color: var(--evt-signature);
}

/* ── Lieu : adresse formatée ── */
/* ── Le lieu, en aplat marine ──
   C'est l'information que l'on vient chercher sur cette page, et la seule qui
   ne se devine pas : le reste (acces, hebergement, restauration) s'y rattache.
   Elle etait rendue comme les autres sections, en texte gris sur blanc, au
   milieu de six blocs identiques. L'aplat la designe sans qu'il faille lire. */
/* L'APLAT MARINE EST VOULU. Il a ete allege en incise le 2026-09-03 au motif
   que la charte reserve ce fond aux appels a l'action — et l'arbitrage est
   revenu dessus : sur une page qui n'a qu'une section, c'est lui qui donne le
   contraste, et l'adresse est bien ce qu'on vient chercher.

   La regle de la charte reste vraie pour un aplat POSE SANS RAISON. Ici il en a
   une, et elle a ete tranchee. */
.infos__venue {
    background: var(--evt-ink);
    color: var(--ink-on-dark);
    border-radius: var(--evt-radius);
    padding: clamp(1.5rem, 3vw, 1.875rem);
}

/* ── Le plan, a DROITE de l'adresse, dans le meme aplat ──
   Deux colonnes seulement quand il y a un plan a montrer : `--mapped` n'est
   pose par le gabarit que si le lieu porte des coordonnees. Sans lui, le bloc
   reste la colonne unique qu'il a toujours ete, et aucune regle ci-dessous ne
   s'applique — pas de piste vide a compenser.

   Le plan passe SOUS l'adresse en colonne etroite : cote a cote, il tomberait
   sous les 200 px ou l'on ne distingue plus une rue. */
.infos__venue--mapped {
    display: grid;
    gap: clamp(1.25rem, 3vw, 1.875rem);
}

@media (min-width: 48em) {
    .infos__venue--mapped {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
        align-items: start;
    }
}

/* La hauteur vient du RATIO, pas d'une valeur en pixels : le plan garde sa
   forme a toutes les largeurs, et la colonne de texte ne le tire pas. */
.infos__venue-map {
    /* Le rognage et le ratio descendent sur le CANEVAS : le credit est un frere
       du cadre, sous lui, et ne doit ni etre rogne ni compter dans le ratio. */
    display: flex;
    flex-direction: column;
}

.infos__venue-map-canvas {
    aspect-ratio: 4 / 3;
    border-radius: var(--evt-radius);
}

@media (min-width: 48em) {
    .infos__venue-map-canvas { aspect-ratio: 1 / 1; }
}

/* Les tuiles sont posees en absolu dans un cadre qui les rogne. Le conteneur
   est le repere : chaque image porte son decalage en ligne, calcule par
   `static_map()`. */
.infos__venue-map-canvas {
    position: relative;
    overflow: hidden;
    width: 100%;
    height: 100%;
    /* Le fond de plan est clair : sous lui, la teinte de la carte plutot que le
       marine, sinon chaque tuile manquante ouvre un trou sombre. */
    background: var(--evt-tint);
}

/* LE FOND MONOCHROME SE FAIT ICI, PAS A LA SOURCE.
   Les tuiles servies sont les tuiles standard d'OpenStreetMap, colorees. Le
   fond gris est obtenu au navigateur, ce qui garde une source LIBRE et SANS
   CLEF : CARTO Positron, qui rendait exactement ce style, exige desormais une
   clef d'API et estampille ses tuiles quand on n'en fournit pas.

   LE VIRAGE AU BLEU SE FAIT EN TROIS TEMPS, et l'ordre compte :

     grayscale(1)      efface les couleurs d'origine — sans lui, le vert des
                       parcs tourne au vert-bleu et non au bleu ;
     sepia(0.55)       reteinte l'image d'une couleur UNIQUE, autour de 35°.
                       C'est le seul filtre CSS qui sache colorer un gris ;
     hue-rotate(185deg) amene ces 35° vers 220°, la famille du marine de la
                       carte. La teinte du fond de plan est alors celle de la
                       page, ce qu'un gris neutre ne donnait pas.

   `brightness` et `contrast` finissent de l'eclaircir : un fond de carte se
   tient au second plan, et le point rouge reste la seule couleur chaude de
   l'image — donc la premiere chose que l'oeil trouve. */
.infos__venue-map-canvas img {
    position: absolute;
    max-width: none;
    filter: grayscale(1) sepia(0.55) hue-rotate(185deg) saturate(1.4) brightness(1.06) contrast(0.9);
}

/* ── Les commandes de zoom, posees par le script ── */
.infos__venue-zoom {
    position: absolute;
    top: var(--spacing-sm);
    right: var(--spacing-sm);
    display: flex;
    flex-direction: column;
    gap: 1px;
    border-radius: var(--radius-sm);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
}

.infos__venue-zoom-btn {
    width: 1.875rem;
    height: 1.875rem;
    border: 0;
    /* Sur un fond de carte dont on ne maitrise pas le contenu, un bouton doit
       porter son propre aplat : pose en transparence, il disparait des qu'un
       batiment clair passe dessous. */
    background: var(--color-on-primary);
    color: var(--color-text);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.infos__venue-zoom-btn:hover:not(:disabled) {
    background: var(--evt-tint);
}

.infos__venue-zoom-btn:disabled {
    color: var(--color-text-light);
    cursor: default;
}

/* La carte ne se saisit que lorsque le script l'a rendue deplacable : sans lui
   le curseur annoncerait un geste qui ne repond pas. */
.infos__venue-map-canvas--live {
    cursor: grab;
    touch-action: pan-y;
}

.infos__venue-map-canvas--dragging {
    cursor: grabbing;
}

/* Les tuiles ne se selectionnent pas au deplacement : sans cela, un glisser
   surligne l'image et laisse un voile bleu sur la carte. */
.infos__venue-map-canvas--live img {
    user-select: none;
    -webkit-user-drag: none;
}

/* Le point, au centre exact de la boite. Un disque cercle de blanc plutot
   qu'une goutte : a cette taille une goutte n'est qu'une tache, et le blanc
   est ce qui le detache d'un fond clair comme d'un parc vert. */
/* Sans script, le lieu est au centre exact du cadre par construction. Des que
   le script prend la main, il pose `left`/`top` en pixels : la carte se
   deplace, le point reste sur le lieu. Le `translate` vaut dans les deux cas —
   il recentre le disque sur son propre point. */
.infos__venue-pin {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 1rem;
    height: 1rem;
    transform: translate(-50%, -50%);
    border-radius: var(--radius-pill);
    background: var(--color-section-colloques);
    box-shadow: 0 0 0 3px var(--color-on-primary), var(--shadow-sm);
}

/* Le credit vit SOUS le cadre, sur l'aplat marine, et non par-dessus la carte :
   pose dessus, il faudrait lui donner un voile pour rester lisible, c'est-a-dire
   remettre la bande que l'on venait de retirer. */
.infos__venue-credit {
    margin: 0.5rem 0 0;
    font-size: 0.75rem;
    color: var(--ink-on-dark-soft);
    display: flex;
    gap: 0.375rem;
}

.infos__venue-credit a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

.infos__venue-credit a:hover,
.infos__venue-credit a:focus-visible {
    color: var(--ink-on-dark);
}

/* ── Les coordonnees, en fonte de donnees ── */
.infos__venue-coords {
    margin: 0.5rem 0 0;
    font-family: var(--font-data);
    font-size: 0.8125rem;
    letter-spacing: 0.02em;
    color: var(--ink-on-dark-soft);
    display: flex;
    gap: 0.5rem;
}

.infos__venue-name {
    margin: 0;
    font-size: clamp(1.25rem, 2.4vw, 1.5625rem);
    font-weight: 700;
    color: var(--ink-on-dark);
}

.infos__venue-address {
    margin: 0.75rem 0 0;
    font-style: normal;
    color: var(--ink-on-dark-soft);
    line-height: 1.75;
}

.infos__access-text {
    margin: 0;
    line-height: 1.6;
}

/* ── Lieu : bouton OSM en outline primary ── */
/* Sur l'aplat, le lien vers le plan est SOULIGNE de vert plutot qu'enferme
   dans une pilule bordee : une pilule blanche sur marine se lirait comme le
   bouton principal de la page, qu'il n'est pas. */
.infos__map-cta {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin-top: var(--spacing-lg);
    padding-bottom: 0.125rem;
    border: 0;
    border-bottom: 2px solid var(--evt-signature-on-dark);
    border-radius: 0;
    background: transparent;
    color: var(--ink-on-dark);
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-decoration: none;
    transition: border-color 150ms ease;
}

.infos__map-cta:hover,
.infos__map-cta:focus-visible {
    background: transparent;
    border-bottom-color: var(--ink-on-dark);
    color: var(--ink-on-dark);
}

.infos__map-cta:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* ── Accès en ligne ── */
.infos__online {
    padding: var(--spacing-md) var(--spacing-lg);
    background: var(--color-bg-light);
    border-radius: var(--radius-md);
    line-height: 1.6;
}

.infos__online p {
    margin: 0 0 0.5rem;
}

.infos__online p:last-child {
    margin-bottom: 0;
}

.infos__online-label {
    font-weight: 700;
    color: var(--color-text-light);
}

.infos__online-value {
    font-weight: 600;
    color: var(--color-text);
}

.infos__online-hint {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* ── Contacts : channels en chips ── */
.infos__contact-channels {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: var(--spacing-md);
}

.infos__contact-channel {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 0.875rem;
    border-radius: var(--radius-sm);
    background: var(--evt-tint);
    color: var(--evt-blue);
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-decoration: none;
    transition: background 150ms ease;
}

.infos__contact-channel:hover {
    background: var(--color-accent-light, var(--color-bg-light));
}

.infos__contact-channel svg {
    flex-shrink: 0;
}

/* ── Print : pas de TOC ni de carte interactive, sections continues ── */
@media print {
    .infos__layout {
        display: block;
        gap: 0;
    }
    .infos__section {
        margin-bottom: 0.5cm;
        page-break-inside: avoid;
    }
    .infos__section-title {
        background: transparent;
        color: var(--color-section-ancesu);
        border-bottom: 1px solid var(--color-section-ancesu-light);
        padding: 0.1cm 0;
        margin-bottom: 0.2cm;
        border-radius: 0;
    }
    .infos__map-cta { display: none; }
    .infos__contact-channels {
        gap: 0.25rem;
    }
    .infos__contact-channel {
        background: transparent;
        color: var(--color-text);
        padding: 0;
        font-weight: 500;
    }
}

/* ══════════════════════════════════════════════════════════════
   Inscription — minisite event

   Reprise du vocabulaire visuel du programme : container 60rem,
   bandeaux de section verts ANCESU, cards sans bordure.

   Structure :
     - header : titre + badge statut (ouvert / early bird / fermé / à venir)
     - cta-zone : grand bouton primary si URL et état ouvert
     - section timeline : étapes ouverture / early / clôture
     - section tarifs : grid cards par PricingTier
     - section moyens de paiement : chips horizontaux
     - section conditions : TipTap render
   ══════════════════════════════════════════════════════════════ */

/* ── Header : titre + badge statut accolés ── */
.inscription__header {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: var(--spacing-xl);
}

.inscription__header .minisite-content__page-title {
    margin-bottom: 0;
    line-height: 1;
    font-weight: 600;
}

.inscription__status {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.75rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.inscription__status--open {
    background: var(--tint-success);
    color: var(--color-text);
}

.inscription__status--upcoming {
    background: var(--color-section-ancesu-light);
    color: var(--color-section-ancesu);
}

.inscription__status--closed {
    background: var(--color-bg-light);
    color: var(--color-text-light);
}

/* ── CTA principal : grande zone surlignée ── */
/* Aplat marine, comme l'appel a l'action de fin de l'accueil : c'est le meme
   geste, il doit avoir la meme apparence. Il etait sur un vert pale qui ne
   figure nulle part ailleurs sur le minisite et qui, sur cette page, se
   confondait avec les intitules de section qui portaient la meme teinte. */
.inscription__cta-zone {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--spacing-lg);
    margin: 0 0 var(--spacing-2xl);
    padding: clamp(1.625rem, 4vw, 2.5rem);
    border-radius: var(--evt-radius);
    background: var(--evt-ink);
    color: var(--ink-on-dark);
}

/* Sur l'aplat marine, le titre et l'indication passent en blanc. Scopees par
   la zone (0,2,0) et non posees a plat sur la classe (0,1,0) : les regles
   d'origine, ecrites pour un fond clair, vivent PLUS BAS dans le fichier et
   l'emportaient a specificite egale — le pave rendait alors du marine sur du
   marine, illisible. */
.inscription__cta-zone .inscription__cta-title {
    color: var(--ink-on-dark);
}

.inscription__cta-zone .inscription__cta-hint {
    color: var(--ink-on-dark-muted);
}

.inscription__cta-zone--muted {
    background: var(--color-bg-light);
}

.inscription__cta-text {
    flex: 1;
    min-width: 0;
}

.inscription__cta-title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--color-text);
    line-height: 1.3;
}

.inscription__cta-hint {
    margin: 0.25rem 0 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.inscription__cta-zone--muted .inscription__cta-title {
    color: var(--color-text-light);
}

/* Rouge de section et coins droits, comme tous les appels a l'action du
   minisite. En pilule bleue sur un aplat marine, le bouton se serait fondu
   dans son propre fond. */
.inscription__cta-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: var(--evt-control-h);
    padding: 0.75rem 1.5rem;
    background: var(--evt-cta);
    color: var(--ink-on-dark);
    border-radius: var(--radius-sm);
    font-weight: 600;
    text-decoration: none;
    font-size: var(--font-size-sm);
    transition: background-color 150ms ease;
}

.inscription__cta-btn:hover,
.inscription__cta-btn:focus-visible {
    background: var(--evt-cta-hover);
    color: var(--ink-on-dark);
}

.inscription__cta-btn:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* ── Sections : bandeau de titre vert ANCESU style programme__day-title ── */
.inscription__section {
    margin: 0 0 var(--spacing-2xl);
}

/* Intitule de section : la grammaire commune du minisite — un titre, un trait
   signature dessous. Il etait rendu en bande vert pale pleine largeur ; trois
   de ces bandes s'empilaient sur la page, et le vert de marque y rend 2,1:1
   sur son propre fond pale, donc sous le seuil AA pour du texte. */
.inscription__section-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin: 0 0 0.5rem;
    font-size: clamp(1.25rem, 2.2vw, 1.5rem);
    font-weight: 700;
    color: var(--evt-ink);
}

.inscription__section-title svg {
    flex-shrink: 0;
    color: var(--evt-signature);
}

/* ── Deux colonnes ──
   La colonne de lecture ne s'etire pas au-dela de sa mesure : les conditions
   d'inscription sont du texte suivi, pas un tableau. */
.inscription__main {
    min-width: 0;
}

/* Colonne unique : le contenu se borne a la mesure de lecture au lieu de
   courir sur 1 216 px. Sans cette borne, l'adresse d'un lieu s'etalerait sur
   toute la largeur de la page. */
/* LA BORNE PORTE SUR LES SECTIONS, PLUS SUR LA COLONNE — et le resultat est
   IDENTIQUE pour tout ce qui est du texte. Elle est ecrite ainsi pour qu'une
   seule section puisse s'en affranchir : celle du lieu, quand elle porte un
   plan.

   La mesure de lecture borne une LONGUEUR DE LIGNE. Une adresse de deux lignes
   courtes flanquee d'une carte n'en a pas : bornee, elle laissait 191 px au
   texte et 211 au plan, ou l'on ne distingue plus une rue. Le reste de la page
   garde ses 493 px au pixel pres. */
.infos__layout--single .infos__main {
    max-width: none;
}

.infos__layout--single .infos__section {
    max-width: var(--evt-measure);
}

.infos__layout--single .infos__section:has(.infos__venue--mapped) {
    max-width: none;
}

/* Le panneau lateral est plus etroit que la colonne de lecture. `evt-split`
   partage a parts egales par defaut, ce qui donnait une carte de bouton aussi
   large que tout le corps de la page. */
@media (min-width: 62em) {
    .inscription__layout {
        grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
    }

    /* Le panneau SUIT la lecture. Les conditions d'inscription font souvent
       plusieurs ecrans (texte saisi en administration) : fixe en haut, le
       bouton disparaissait des le premier defilement et la moitie droite de la
       page restait vide jusqu'au pied. `align-self: start` est indispensable —
       un element de grille est etire par defaut, et `sticky` n'a alors aucune
       marge de manoeuvre. */
    .inscription__aside {
        position: sticky;
        top: calc(var(--minisite-chrome-h, 7rem) + 1rem);
        align-self: start;
    }
}

/* Pastille d'etat dans le sur-titre : un point de couleur PLUS un libelle en
   toutes lettres. Le point seul ne dirait rien a qui ne percoit pas la
   teinte. */
.inscription__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

/* LES TROIS POINTS D'ETAT SONT PARTIS pour la pastille de la grammaire
   (`ui.pill`, composant 65). Ils portaient deja la trace de deux corrections —
   un point blanc devenu invisible quand l'en-tete est passe sur fond clair,
   puis un vert de marque a 2,0:1 sous le seuil de 3:1 d'un indicateur
   graphique. Les deux disent la meme chose : un etat rendu par une COULEUR
   seule finit toujours par tomber. La pastille le rend en TEXTE, et le ton ne
   fait que redire ce que le libelle dit deja. */

/* Dans la colonne laterale, le pave d'appel a l'action passe en carte
   verticale : le bouton sous son texte, pas a cote. */
.inscription__aside .inscription__cta-zone {
    display: block;
    margin: 0;
}

.inscription__aside .inscription__cta-btn {
    display: flex;
    width: 100%;
    margin-top: var(--spacing-lg);
}

/* Variante « rien a faire pour le moment » (inscriptions a venir, closes,
   formulaire en preparation) : pas d'aplat marine, qui promettrait une action.
   Un encart neutre, qui informe. */
.inscription__aside .inscription__cta-zone--muted {
    background: var(--evt-surface-muted);
    border: 1px solid var(--evt-rule);
    color: var(--color-text);
}

.inscription__cta-zone.inscription__cta-zone--muted .inscription__cta-title {
    color: var(--evt-ink);
}

.inscription__cta-zone.inscription__cta-zone--muted .inscription__cta-hint {
    color: var(--color-text-light);
}

.inscription__contacts-card .prose-content {
    font-size: var(--font-size-sm);
    line-height: 1.7;
}

.inscription__contacts-card .evt-def__label {
    margin: 0 0 var(--spacing-sm);
}

/* La liste d'adresses aligne ses puces sur le bord du texte, pas 24 px plus
   loin : dans une carte etroite, un retrait de liste mange un mot par ligne. */
.inscription__contacts-card .prose-content ul {
    padding-left: 1.125rem;
    margin-block: 0.5rem;
}

.inscription__contacts-card .prose-content > :first-child {
    margin-top: 0;
}

.inscription__contacts-card .prose-content > :last-child {
    margin-bottom: 0;
}

/* ── Timeline : étapes avec marker + ligne reliante.
   Layout vertical par défaut (mobile-first) ; bascule horizontal en
   stepper à partir de lg (1024px) où la largeur du container 60rem
   suffit à présenter 3 étapes côte à côte. ── */
.inscription__timeline {
    list-style: none;
    margin: 0;
    padding: 0 0 0 0.5rem;
    position: relative;
}

.inscription__timeline-step {
    display: grid;
    grid-template-columns: 1.5rem 1fr;
    gap: var(--spacing-md);
    padding: var(--spacing-sm) 0;
    position: relative;
}

/* Ligne verticale qui relie les markers — calée sur le centre du marker
   (0.75rem from left of 1.5rem column + padding-left 0.5rem). */
.inscription__timeline::before {
    content: '';
    position: absolute;
    left: calc(0.5rem + 0.75rem - 1px);
    top: var(--spacing-md);
    bottom: var(--spacing-md);
    width: 2px;
    background: var(--color-border);
    z-index: 0;
}

/* ── Horizontal stepper sur lg+ ──
   Markers en haut, label en dessous, ligne horizontale entre eux.
   Justifie chaque étape sur sa propre colonne flex pour une distribution
   régulière, et redresse le ::before en ligne horizontale alignée sur le
   centre vertical des markers. */
@media (min-width: 64em) {
    .inscription__timeline {
        display: flex;
        align-items: flex-start;
        gap: var(--spacing-md);
        padding: 0;
    }

    .inscription__timeline-step {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 0.5rem;
        padding: 0;
        min-width: 0;
    }

    /* Ligne horizontale entre les markers extrêmes. On utilise des
       pseudo-positions sur les steps eux-mêmes (::after sur chaque step
       sauf le dernier) pour éviter de dépasser au-delà des markers
       extrêmes — l'approche `::before` global de OL ne sait pas où se
       trouvent les markers du premier/dernier step. */
    .inscription__timeline::before {
        display: none;
    }

    .inscription__timeline-step:not(:last-child)::after {
        content: '';
        position: absolute;
        top: 0.75rem;
        left: 50%;
        right: calc(-50% - var(--spacing-md));
        height: 2px;
        background: var(--color-border);
        z-index: 0;
    }
}

.inscription__timeline-marker {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 100px;
    background: white;
    border: 2px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-light);
    z-index: 1;
    flex-shrink: 0;
}

.inscription__timeline-step--done .inscription__timeline-marker {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: white;
}

.inscription__timeline-step--current .inscription__timeline-marker {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: white;
    box-shadow: 0 0 0 4px var(--color-accent-light);
}

/* —— LE LIBELLE ET SA DATE SONT DEUX LIGNES ——
   Ce sont deux `<span>`, donc deux boites EN LIGNE : « Ouverture des
   inscriptions 1 mars 2026 » se lisait d'un trait, et sur l'echeance la plus
   longue la date se coupait en deux — « 12 novembre » sur une ligne, « 2026 »
   sur la suivante. Une date ne se coupe pas.

   Les marges declarees plus bas etaient d'ailleurs inertes depuis toujours :
   une marge verticale ne s'applique pas a une boite en ligne. Elles decrivaient
   une mise en page que personne ne voyait. */
.inscription__timeline-body {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.inscription__timeline-label {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* La marge vit sur la DATE, qui suit le libelle dans le document. Elle etait
   posee sur le libelle, c'est-a-dire sur le premier des deux : elle aurait
   creuse au-dessus du bloc au lieu de separer les deux lignes, le jour ou elle
   aurait servi a quelque chose. */
.inscription__timeline-date {
    margin: 0.125rem 0 0;
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--color-text);
}

.inscription__timeline-step--current .inscription__timeline-date {
    color: var(--color-accent);
}

.inscription__timeline-step--pending .inscription__timeline-date,
.inscription__timeline-step--pending .inscription__timeline-label {
    color: var(--color-text-light);
}

/* ── Tarifs : grid cards sans bordure ── */
.inscription__tiers {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: var(--spacing-md);
}

/* Le PREMIER palier sur aplat marine, les suivants sur filet. Il n'est pas
   « meilleur » : c'est celui qui concerne la majorite des visiteurs d'un
   minisite ANCESU, les adherents. Meme traitement que la grille de tarifs de
   l'accueil, pour que les deux surfaces se reconnaissent. */
.inscription__tier {
    padding: 1.625rem;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    background: var(--evt-surface);
}

.inscription__tier:first-child {
    background: var(--evt-ink);
    border-color: var(--evt-ink);
    color: var(--ink-on-dark);
}

.inscription__tier-category {
    margin: 0 0 var(--spacing-sm);
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-light);
}

.inscription__tier:first-child .inscription__tier-category {
    color: var(--evt-signature-on-dark);
}

.inscription__tier-price {
    margin: 0;
    font-size: clamp(1.75rem, 3.4vw, 2.375rem);
    font-weight: 700;
    color: var(--evt-ink);
    line-height: 1;
}

.inscription__tier:first-child .inscription__tier-price {
    color: var(--ink-on-dark);
}

.inscription__tier:first-child .inscription__tier-mention,
.inscription__tier:first-child .inscription__tier-next-label {
    color: var(--ink-on-dark-muted);
}

.inscription__tier:first-child .inscription__tier-next {
    border-top-color: var(--rule-on-dark);
}

.inscription__tier:first-child .inscription__tier-next-amount {
    color: var(--ink-on-dark);
}

/* Mention temporelle sous le prix : « Jusqu'au DATE » avant la deadline,
   « Depuis le DATE » après. Discrète, en italique pour signaler que
   c'est une note de contexte, pas une donnée principale. */
.inscription__tier-mention {
    margin: 0.375rem 0 0;
    font-size: 0.75rem;
    font-style: italic;
    color: var(--color-text-light);
}

/* Prix de bascule visible pendant la période early bird : permet à
   l'utilisateur d'anticiper combien il paiera s'il s'inscrit après la
   deadline. Présenté comme une ligne secondaire — séparée par un
   filet, montant moins prominent que le prix courant mais lisible. */
.inscription__tier-next {
    display: flex;
    align-items: baseline;
    gap: 0.375rem;
    margin: 0.625rem 0 0;
    padding-top: 0.5rem;
    border-top: 1px solid var(--color-border);
}

.inscription__tier-next-amount {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--color-text);
}

.inscription__tier-next-label {
    font-size: 0.75rem;
    font-style: italic;
    color: var(--color-text-light);
}

/* ── Moyens de paiement : chips horizontaux ── */
.inscription__methods {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.inscription__method {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    background: var(--color-bg-light);
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--color-text);
}

.inscription__method svg {
    color: var(--color-text-light);
    flex-shrink: 0;
}

/* ── Note capacité ── */
.inscription__capacity-note {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin: 0 0 var(--spacing-xl);
    padding: 0.5rem 0.875rem;
    background: var(--color-bg-light);
    border-radius: var(--radius-md);
    font-size: 0.75rem;
    color: var(--color-text-light);
}

.inscription__capacity-note svg {
    flex-shrink: 0;
    color: var(--color-text-light);
}

/* ── Conditions + Contacts : bloc TipTap dans bg-light ── */
.inscription__conditions,
/* Ni fond ni rembourrage : le bloc vit DANS une carte qui porte deja les
   deux. Il dessinait un second cadre a l'interieur du premier, et son
   rembourrage de 24 px decalait le texte de l'intitule « Contacts » juste
   au-dessus — les deux ne partaient pas du meme bord. */
.inscription__contacts {
    padding: 0;
    background: none;
    border-radius: 0;
    font-size: var(--font-size-sm);
    line-height: 1.6;
}

.inscription__conditions > :first-child,
.inscription__contacts > :first-child { margin-top: 0; }
.inscription__conditions > :last-child,
.inscription__contacts > :last-child { margin-bottom: 0; }

.inscription__excerpt {
    color: var(--color-text-light);
    font-size: var(--font-size-base);
}

@media (width < 40em) {
    .inscription__cta-zone { flex-direction: column; align-items: stretch; }
    .inscription__cta-btn { justify-content: center; }
}

/* ══════════════════════════════════════════════════════════════════════════
   PARTENAIRES
   ══════════════════════════════════════════════════════════════════════════ */

.partners__intro {
    margin-bottom: var(--evt-section-y);
}

/* Le rythme est porte par le HAUT, jamais par une marge basse : la derniere
   rubrique n'a rien apres elle, et une marge basse s'ajouterait a celle du
   bloc suivant. */
.partners__section + .partners__section,
.partners__join {
    margin-top: var(--evt-section-y);
}

/* `auto-fill` ET NON `auto-fit`, ET C'EST L'INVERSE DU CHOIX HABITUEL.

   Ailleurs sur le minisite, `auto-fit` evite qu'un element seul soit serre a
   gauche avec des pistes vides a sa droite. Ici on veut precisement ces pistes
   vides : `auto-fit` les fusionne, donc une rubrique de deux partenaires leur
   donnait 379 px chacun quand la rubrique voisine, qui en compte trois, les
   posait a 244. Mesure a l'ecran : la carte changeait de taille d'une rubrique
   a l'autre, sur une page qui n'est qu'une suite de rubriques.

   Une page de partenaires est une GRILLE DE VIGNETTES, pas une suite de listes
   independantes : la vignette garde le meme calibre partout, et une rubrique
   courte laisse du blanc. C'est ce blanc qui dit qu'elle est courte.

   Le maximum est `1fr` et non une longueur fixe : ecrit en longueur, Chrome
   calcule le nombre de pistes sur ce maximum et n'en placait que deux dans les
   782 px de la colonne, laissant 262 px morts — dix de moins qu'il n'en
   faudrait pour une troisieme. */
.partners__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
    gap: var(--spacing-lg);
    margin-top: var(--spacing-lg);
}

/* Un logo est presque toujours compose sur blanc : le poser sur un aplat gris
   lui dessine un cadre qui n'existe pas dans le fichier. */
.partners__card {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: var(--spacing-lg);
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    transition: border-color var(--transition-fast);
}

/* LA CARTE ENTIERE EST CLIQUABLE, par un pseudo-element etire depuis le lien
   du nom. Viser trois mots dans une carte qui a l'air d'un bouton est une
   cible inutilement etroite. */
.partners__card--link .partners__name a::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

.partners__card--link:hover,
.partners__card--link:focus-within {
    border-color: var(--evt-cta);
}

/* HAUTEUR FIXE : c'est elle qui aligne les noms d'une carte a l'autre, quelles
   que soient les proportions des fichiers. Le bloc est rendu VIDE sur une
   carte sans logo dont la rubrique en compte — c'est tout son objet. */
.partners__logo {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    height: 3.5rem;
    margin-bottom: var(--spacing-md);
}

.partners__logo img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.partners__name {
    margin: 0;
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--evt-ink);
}

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

.partners__desc {
    margin: var(--spacing-xs) 0 0;
    font-size: var(--font-size-sm);
    line-height: 1.55;
    color: var(--color-text-light);
}

/* ══════════════════════════════════════════════════════════════════════════
   LE MUR DES PARTENAIRES, SUR L'ACCUEIL DU MINISITE
   ══════════════════════════════════════════════════════════════════════════ */

.partner-wall {
    list-style: none;
    margin: var(--spacing-lg) 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: clamp(1.5rem, 4vw, 2.5rem);
}

/* Une hauteur COMMUNE, jamais une largeur : les logos ont des proportions
   incomparables, et les caler sur la largeur ferait un carre minuscule a cote
   d'un bandeau. A hauteur egale, ils pesent le meme poids optique. */
.partner-wall__item {
    display: flex;
    align-items: center;
    height: 3rem;
}

.partner-wall__item a {
    display: flex;
    align-items: center;
    height: 100%;
    text-decoration: none;
}

.partner-wall__item img {
    max-height: 100%;
    max-width: 10rem;
    /* `contain` et jamais `cover` : recadre, un logo perd son nom. */
    object-fit: contain;

    /* ── LE GRIS, ET CE QU'IL PROTEGE ──
       Une rangee de logos aux couleurs de vingt marques tire l'oeil plus fort
       que le contenu de l'edition, et se lit comme une bande publicitaire.
       Grises, ils forment une famille. `opacity` en plus du `grayscale` :
       certains logos sont deja monochromes et le seul filtre ne les
       calmerait pas. */
    filter: grayscale(1);
    opacity: 0.65;
    transition: filter var(--transition-fast), opacity var(--transition-fast);
}

/* LE FOCUS FAIT LA MEME CHOSE QUE LE SURVOL, et ce n'est pas une precaution :
   la charte interdit une reponse reservee au survol. Sans `:focus-visible`, ce
   que voit qui navigue au clavier n'est pas ce que voit qui navigue a la
   souris. */
.partner-wall__item a:hover img,
.partner-wall__item a:focus-visible img,
.partner-wall__item:hover img {
    filter: none;
    opacity: 1;
}

/* CE QUI RESTE VRAI SANS ANIMATION. Le passage du gris a la couleur est un
   changement d'ETAT, pas un mouvement : il doit avoir lieu meme quand
   l'utilisateur demande a ce que rien ne bouge. Seule la transition tombe. */
@media (prefers-reduced-motion: reduce) {
    .partner-wall__item img {
        transition: none;
    }
}

/* Un partenaire sans logo : son nom, a la meme hauteur que les autres, pour
   que la rangee garde sa ligne. */
.partner-wall__item--wordmark {
    font-weight: 600;
    color: var(--color-text-light);
}

.partner-wall__item--wordmark a:hover,
.partner-wall__item--wordmark a:focus-visible {
    color: var(--evt-ink);
}

/* ══════════════════════════════════════════════════════════════════════════
   CANDIDATURE AU PARTENARIAT — formulaire public et page de suivi
   ══════════════════════════════════════════════════════════════════════════ */

/* La rangee d'une personne : civilite, prenom, nom, fonction.

   ELLE ETAIT MISE EN PAGE PAR ACCIDENT. Sans regle, le conteneur restait en
   `display: block` et les quatre champs tenaient sur une ligne parce que des
   champs de saisie sont en ligne par defaut — donc sans `gap`, sans colonnes
   stables, et rien ne garantissait qu'ils y tiennent a une autre largeur ou
   avec un autre contenu. Mesure : 129/211/211/211 px, un espacement venu des
   marges des champs. */
.partnership-people__row {
    display: grid;
    /* 8,5 rem et non 7 : « Non précisée » y etait tronque en « Non précis ». */
    grid-template-columns: 8.5rem repeat(3, minmax(0, 1fr));
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-sm);
}

/* LES SAISIES SONT HABILLEES ICI, et il a fallu le mesurer. L'habillage commun
   du formulaire est porte par `.call-card__field` ; ce bloc-ci est un
   `.call-card__fieldset`, qui est le SEUL a habiller le champ de televersement.
   En passant de l'un a l'autre pour reparer le bouton « Choisir un fichier »,
   les quatre champs d'une personne ont perdu leurs bordures d'un coup — ils
   rendaient comme du texte nu.

   Les deux classes ne sont pas interchangeables : `__fieldset` groupe, `__field`
   habille. Le formulaire de contribution imbrique les deux ; ici la rangee tient
   lieu de groupe, et l'habillage se pose donc dessus. */
.partnership-people__row input,
.partnership-people__row select {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.95rem;
    font-family: inherit;
    background: var(--color-bg);
    color: var(--color-text);
    min-width: 0;
}

/* En colonne etroite, quatre champs cote a cote tombent sous la largeur ou
   l'on peut lire ce qu'on tape. Ils s'empilent. */
@media (width < 40em) {
    .partnership-people__row {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Le logo deja depose, montre en petit. `contain` et jamais `cover` : recadre,
   un logo perd son nom. La hauteur est bornee — un fichier en haute definition
   occuperait sinon la moitie du formulaire. */
.partnership-logo__current {
    margin: 0 0 var(--spacing-sm);
}

.partnership-logo__current img {
    max-width: 12rem;
    max-height: 4rem;
    object-fit: contain;
}

/* L'erreur d'envoi, rendue DANS la page et non en message flash : aucun
   gabarit du minisite ne rend les flashes. Le conteneur porte `tabindex` et
   `autofocus` cote gabarit — il se fait defiler dans la vue ET annoncer.

   Pas d'anneau de focus : ce n'est pas un controle, rien ne s'y fait. */
.partnership-apply__error {
    margin-bottom: var(--spacing-lg);
    padding: var(--spacing-md) var(--spacing-lg);
    border-radius: var(--evt-radius);
    /* LES JETONS SONT CEUX QUI EXISTENT. `--color-danger-bg` et
       `--color-danger-text` ont ete ecrits d'abord : ils ne sont declares nulle
       part, et leur repli aurait rendu l'encadre dans la teinte NEUTRE — une
       erreur qui ne se voit pas comme une erreur, sans que rien ne le signale.
       Les vrais noms sont `--tint-danger` et `--color-danger-ink`. */
    background: var(--tint-danger);
    color: var(--color-danger-ink);
    font-size: var(--font-size-sm);
}

.partnership-apply__error:focus {
    outline: none;
    box-shadow: none;
}

/* ── Page de suivi ── */

/* UNE LIGNE, PAS UN ENCADRE. Le bandeau bleu et l'encadre de statut disaient la
   meme chose l'un sous l'autre — c'est ce que Luc a releve. L'etat est porte par
   la frise ; cette ligne ne dit que ce que la frise ne peut pas dire : ou le
   courriel est parti. */
.partnership-track__mail {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-sm);
    margin: 0 0 var(--evt-section-y);
    padding: var(--spacing-md) var(--spacing-lg);
    border-radius: var(--evt-radius);
    background: var(--evt-tint);
    font-size: var(--font-size-sm);
    line-height: 1.55;
}

.partnership-track__mail svg {
    flex: none;
    margin-top: 0.15em;
    color: var(--color-primary);
}

/* La decision a son bloc, et sa TEINTE ne suffit jamais : le libelle la dit en
   toutes lettres, la phrase dit ce qu'elle implique. */
.partnership-track__decision {
    margin: 0 0 var(--evt-section-y);
    padding: var(--spacing-lg);
    border-radius: var(--evt-radius);
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
}

.partnership-track__decision--accepted {
    background: var(--tint-success, var(--evt-tint));
}

.partnership-track__decision--rejected {
    background: var(--evt-surface);
}

.partnership-track__decision-label {
    margin: 0 0 var(--spacing-xs);
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--evt-ink);
}

.partnership-track__decision-text {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.partnership-track__logo {
    max-width: 10rem;
    max-height: 3.5rem;
    object-fit: contain;
}

.partnership-track__actions {
    margin: var(--evt-section-y) 0 0;
}

/* Partir sans enregistrer n'est pas une action du formulaire : un LIEN, jamais
   un second bouton de meme poids. */
.partnership-apply__cancel {
    align-self: center;
    margin-right: auto;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.partnership-track__notice {
    margin-bottom: var(--evt-section-y);
    padding: var(--spacing-lg);
    border-radius: var(--evt-radius);
    background: var(--evt-tint);
}

.partnership-track__notice p {
    margin: 0 0 var(--spacing-xs);
}

.partnership-track__notice p:last-child {
    margin-bottom: 0;
}

/* L'ETAT NE TIENT PAS A LA SEULE COULEUR. Le libelle le dit en toutes lettres,
   et la phrase qui suit dit ce qu'il implique — « Acceptee » seul laisse se
   demander s'il faut encore agir. La teinte ne fait que confirmer. */
.partnership-track__status {
    margin-bottom: var(--evt-section-y);
    padding: var(--spacing-lg);
    border-radius: var(--evt-radius);
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
}

.partnership-track__status-label {
    margin: 0 0 var(--spacing-xs);
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--evt-ink);
}

.partnership-track__status-hint {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* LE RYTHME EST PORTE PAR LE TITRE, PAS PAR LE RESUME. La marge haute du
   resume s'AJOUTAIT a la marge basse de l'en-tete : 48 px la ou la grammaire en
   pose 24. Deux moities dans deux fichiers, qui valent le meme jeton — c'est le
   defaut que `design-system.md` decrit, et il ne se voit qu'a la mesure. */
.partnership-track__heading {
    margin-top: var(--evt-section-y);
}

.partnership-track__summary {
    margin: 0;
    display: grid;
    gap: var(--spacing-xs) var(--spacing-lg);
}

@media (min-width: 40em) {
    .partnership-track__summary {
        grid-template-columns: 10rem minmax(0, 1fr);
    }
}

.partnership-track__summary dt {
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-light);
}

.partnership-track__summary dd {
    margin: 0;
    color: var(--evt-ink);
}

/* ── La page sans partenaire ──
   Ces deux rubriques ne se rendent que lorsque la page n'a rien d'autre a
   montrer. Elles suivent le rythme du minisite : l'ecart est porte par le
   HAUT, jamais par une marge basse. */
.partners__pitch + .partners__pitch,
.partners__pitch:first-child {
    margin-top: 0;
}

.partners__pitch + .partners__pitch {
    margin-top: var(--evt-section-y);
}

/* Les etapes sont NUMEROTEES PAR LE CSS et non ecrites a la main : un
   numero saisi dans le gabarit se desynchronise des qu'on insere une etape,
   et personne ne le voit avant de relire la page en entier. */
.partners__steps {
    counter-reset: partners-step;
    list-style: none;
    margin: var(--spacing-lg) 0 0;
    padding: 0;
    display: grid;
    gap: var(--spacing-lg);
}

@media (min-width: 48em) {
    .partners__steps {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* PAS DE FILET SUR UNE ETAPE. J'en avais pose un, vert, en tete de chaque
   etape — et le titre de rubrique juste au-dessus porte deja le filet
   signature de la grammaire. Les deux tombaient a quelques pixels l'un de
   l'autre : une ligne rouge, puis trois lignes vertes, qu'on lit comme un
   defaut d'alignement plutot que comme deux objets.

   Le NUMERO suffit a marquer le rang, et c'est le seul marqueur dont une
   etape a besoin. Signale par Luc a l'ecran ; invisible en lisant le CSS,
   les deux traits venant de deux fichiers differents. */
.partners__steps li {
    counter-increment: partners-step;
}

.partners__step-title {
    margin: 0 0 var(--spacing-xs);
    font-weight: 600;
    color: var(--evt-ink);
}

.partners__step-title::before {
    content: counter(partners-step) '. ';
    color: var(--color-text-light);
}

.partners__step-text {
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: 1.55;
    color: var(--color-text-light);
}

/* Les formes de partenariat : des mots, pas des cartes. Ce sont des
   intitules d'une ligne — les enfermer dans des cartes leur donnerait un
   poids qu'ils n'ont pas, et ferait attendre une description qui n'existe
   pas. */
.partners__kinds {
    list-style: none;
    margin: var(--spacing-lg) 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

.partners__kinds li {
    padding: 0.375rem 0.875rem;
    border: 1px solid var(--evt-rule);
    border-radius: var(--radius-pill);
    font-size: var(--font-size-sm);
    color: var(--evt-ink);
    background: var(--evt-surface);
}

/* ── Devenir partenaire ──
   Aplat marine, comme les autres appels a l'action du minisite. En gris clair,
   il se confondait avec les cartes de partenaires juste au-dessus. */
.partners__join {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-lg);
    align-items: center;
    justify-content: space-between;
    padding: clamp(1.625rem, 4vw, 2.5rem);
    background: var(--evt-ink);
    color: var(--ink-on-dark);
    border-radius: var(--evt-radius);
}

.partners__join-text {
    flex: 1 1 20rem;
}

.partners__join-kicker {
    margin: 0 0 var(--spacing-sm);
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-weight: 700;
    /* Le vert de marque est DECORATIF sur fond clair (2,1:1). Sur l'aplat, la
       variante prevue pour le fond sombre rend 6,1:1. */
    color: var(--evt-signature-on-dark);
}

.partners__join-title {
    margin: 0 0 var(--spacing-xs);
    font-size: clamp(1.1875rem, 2.3vw, 1.5rem);
    font-weight: 700;
    color: var(--ink-on-dark);
}

.partners__join-lead {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--ink-on-dark-muted);
    max-width: 52ch;
}

.partners__join-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

.partners__join-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--evt-control-h);
    padding: 0.75rem 1.5rem;
    background: var(--evt-cta);
    color: var(--ink-on-dark);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    text-decoration: none;
    font-weight: 600;
    font-size: var(--font-size-sm);
    white-space: nowrap;
    transition: background-color var(--transition-fast);
}

.partners__join-btn:hover,
.partners__join-btn:focus-visible {
    background: var(--evt-cta-hover);
    color: var(--ink-on-dark);
}

/* Le second rang. `background` en toutes lettres et non `transparent` seul :
   la regle de base pose un raccourci, et une variante qui ne declarerait que
   la couleur du bord serait reecrite par elle. */
.partners__join-btn--quiet {
    background: transparent;
    border-color: var(--ink-on-dark-soft);
}

.partners__join-btn--quiet:hover,
.partners__join-btn--quiet:focus-visible {
    background: transparent;
    border-color: var(--ink-on-dark);
}

@media (width < 40em) {
    .partners__join-actions { width: 100%; }
    .partners__join-btn { flex: 1 1 100%; }
}

/* Contributions */
.contributions__list {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    max-width: 48rem;
}

.contributions__item {
    padding: var(--spacing-lg);
    background: var(--color-bg-light);
    border-radius: var(--radius-md);
}

.contributions__title { font-weight: 600; margin-bottom: var(--spacing-xs); }
.contributions__authors { font-size: var(--font-size-sm); color: var(--color-primary); font-weight: 500; }
.contributions__abstract { font-size: var(--font-size-sm); color: var(--color-text-light); margin-top: var(--spacing-xs); }

.contributions__download {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    margin-top: var(--spacing-sm);
    font-size: var(--font-size-sm);
    color: var(--color-primary);
    font-weight: 500;
}

.programme__replays {
    margin: 0 0 var(--spacing-lg);
    padding: var(--spacing-md) var(--spacing-lg);
    background: var(--color-bg-light);
    border-radius: var(--radius-md);
}

.programme__replays-title {
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-primary);
    margin: 0 0 var(--spacing-sm);
}

.programme__replays-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

.programme__replay-card {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--color-text);
    font: inherit;
    font-size: var(--font-size-sm);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: border-color 120ms ease, box-shadow 120ms ease;
}

.programme__replay-card:hover {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-sm);
}

.programme__replay-card-icon { flex: 0 0 auto; color: var(--color-primary); }
.programme__replay-card-title { font-weight: 600; }
.programme__replay-card-duration { color: var(--color-text-light); font-size: var(--font-size-xs); }

/* ══ LE CONTEXTE SUR FOND NOIR ══════════════════════════════════════════════

   La boite de lecture est noire — une video n'est presque jamais au format de
   sa boite, et les bandes qui restent doivent disparaitre. Tout ce que j'ai
   pose dedans (reperes, intervenants, lien, chapitres, navigation) etait ecrit
   pour une carte CLAIRE : sur le noir, le gris de texte secondaire rend a
   moins de 2:1 et les boutons a filet sombre deviennent invisibles.

   Les couleurs sont donc reprises ici, et seulement ici : la meme grammaire
   posee sur un fond inverse n'est pas la meme grammaire. */
.modal--media .overlay__media-context {
    padding: var(--spacing-ms) var(--spacing-lg) 0;
    gap: var(--spacing-ms);
}

/* PLUS GRAND QUE DANS UNE CARTE, et c'est la distance qui le commande : sur une
   vignette de 240 px on lit les reperes a 30 cm du texte, dans une boite de
   1 380 px on les lit du fond du fauteuil. Le corps de la grille (2xs) y
   rendait minuscule, et la ligne de navigation avec.

   Les tailles montent d'un cran chacune, la hierarchie ne change pas. */
.modal--media .overlay__media-origin,
.modal--media .overlay__media-marks {
    font-size: var(--font-size-sm);
}

.modal--media .overlay__media-speakers {
    font-size: var(--font-size-base);
}

.modal--media .overlay__media-position {
    font-size: var(--font-size-sm);
}

.modal--media .overlay__media-nav .btn {
    font-size: var(--font-size-sm);
    padding-block: var(--spacing-sm);
    padding-inline: var(--spacing-ms);
}

.modal--media .overlay__media-origin {
    color: var(--color-on-primary);
    opacity: 0.82;
}

.modal--media .overlay__media-marks,
.modal--media .overlay__media-chapters-title,
.modal--media .overlay__media-chapter-time,
.modal--media .overlay__media-position {
    color: var(--color-on-primary);
    opacity: 0.72;
}

.modal--media .overlay__media-speakers,
.modal--media .overlay__media-chapter {
    color: var(--color-on-primary);
}

.modal--media .overlay__media-link,
.modal--media .overlay__media-chapter:hover,
.modal--media .overlay__media-chapter:focus-visible {
    color: var(--color-on-primary);
    text-decoration: underline;
}

.modal--media .overlay__media-nav {
    padding: var(--spacing-ms) var(--spacing-lg) var(--spacing-lg);
    border-top-color: color-mix(in srgb, var(--color-on-primary) 16%, transparent);
    margin-top: var(--spacing-ms);
}

/* Les deux commandes de navigation doivent se RESSEMBLER : l'une rendait en
   pastille claire et l'autre en pastille pleine, alors qu'elles font le meme
   geste dans deux directions. Filet clair sur le noir pour les deux. */
.modal--media .overlay__media-nav .btn {
    border: 1px solid color-mix(in srgb, var(--color-on-primary) 34%, transparent);
    background: transparent;
    color: var(--color-on-primary);
}

.modal--media .overlay__media-nav .btn:hover:not(:disabled),
.modal--media .overlay__media-nav .btn:focus-visible:not(:disabled) {
    background: color-mix(in srgb, var(--color-on-primary) 14%, transparent);
}

.modal--media .overlay__media-nav .btn:disabled {
    opacity: 0.38;
    cursor: default;
}

/* Le bouton de consentement est l'ACTION du repli : c'est lui qui repare, le
   lien vers la plateforme n'est qu'une issue de secours. Il porte donc le
   plein, l'autre le filet. */
.modal--media .overlay__media-fallback-actions .btn {
    border: 1px solid color-mix(in srgb, var(--color-on-primary) 34%, transparent);
    background: transparent;
    color: var(--color-on-primary);
}

.modal--media .overlay__media-fallback-actions [data-replay-consent] {
    border-color: transparent;
    background: var(--color-on-primary);
    color: var(--color-navy);
    font-weight: 600;
}

/* ── Le repli du lecteur ──
   Chaque partie est un BLOC : sur une seule ligne, la phrase et le lien se
   centraient separement et le point final finissait isole a droite. */
.overlay__media-fallback {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-ms);
    padding: var(--spacing-lg);
    text-align: center;
}

.overlay__media-fallback-text {
    margin: 0;
    max-width: 40ch;
    color: var(--color-on-primary);
}

.overlay__media-fallback-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--spacing-sm);
    margin: 0;
}

/* ── D'une rediffusion a l'autre ── */
.overlay__media-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    padding-top: var(--spacing-ms);
    border-top: 1px solid var(--color-border);
    margin-top: var(--spacing-ms);
}

.overlay__media-position {
    font-family: var(--font-data);
    font-size: var(--font-size-2xs);
    color: var(--color-text-light);
}

/* ── Origine et chapitrage ── */
.overlay__media-origin {
    margin: 0;
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-primary);
}

.overlay__media-chapters {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    padding-top: var(--spacing-sm);
}

.overlay__media-chapters-title {
    margin: 0;
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

.overlay__media-chapters-list {
    /* Bornee en hauteur : un chapitrage de trente entrees pousserait la
       navigation d'une rediffusion a l'autre hors de l'ecran. */
    max-height: 11rem;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
}

.overlay__media-chapter {
    display: flex;
    gap: var(--spacing-sm);
    width: 100%;
    padding: var(--spacing-xs) 0;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
    font-size: var(--font-size-sm);
    color: var(--color-text);
}

.overlay__media-chapter:hover,
.overlay__media-chapter:focus-visible {
    color: var(--color-primary);
}

.overlay__media-chapter-time {
    flex: 0 0 auto;
    font-family: var(--font-data);
    font-size: var(--font-size-2xs);
    color: var(--color-text-light);
}

/* ── Le contexte de la modale de lecture ──
   Meme grammaire que les reperes d'une vignette : c'est la meme information,
   et la lire deux fois de deux facons obligerait a la relire. */
.overlay__media-context {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    padding-top: var(--spacing-ms);
}

.overlay__media-marks {
    margin: 0;
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

.overlay__media-speakers {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text);
}

.overlay__media-link {
    align-self: flex-start;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-primary);
}

/* ══ COMPOSANT 51 · REPLAYS EN GRILLE ══════════════════════════════════════

   Une VIGNETTE nue, sans bordure ni corps, posée à même la surface — et non la
   carte illustrée du composant 60. Ce qui distingue les deux n'est pas la
   richesse mais le POIDS : onze cartes bordées à fond gris sur la colonne d'une
   fiche se lisent comme un catalogue, onze vignettes se parcourent.

   Mesures de la maquette, reprises telles quelles : piste minimale de 140 px,
   gouttière 14, visuel en 16/9 arrondi à 9 px, repères en capitales à 10,5 px
   et interlettrage .08em, titre à 15 px. */
.replay-tiles {
    display: grid;

    /* 17rem sur la pleine largeur : a 1 192 px, cela rend QUATRE colonnes de
       286, ce que la maquette pose. A 14rem on en obtenait cinq — une de trop,
       et des cartes plus etroites que la planche.

       Ce n'est pas la valeur de la maquette (140 px) et ce ne peut pas l'etre : La planche montre des titres de
       trois mots (« Seance d'ouverture ») ; les notres font sept lignes
       (« Recommandations formalisees d'expert sur les gestes et soins d'urgence
       (RFE 2026) »). A 140 px de piste, mesure le 2026-08-29 : quatre colonnes
       de 143 px a 768 px de fenetre, deux de 142 sur un telephone.

       C'est la mesure que la grille portait AVANT le passage au composant 51 —
       `media-cards--dense` la donnait, et la classe a disparu avec la
       reecriture sans que rien ne le signale. */
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
    gap: var(--spacing-md);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* LE CADRE EST AUTOUR DE CHAQUE VIGNETTE, pas autour de la grille — la section
   des rediffusions vit deja dans la carte de la fiche, et un panneau de plus
   ferait deux cadres emboites pour une seule liste.

   Il reste LEGER : le filet ordinaire de la grammaire, un rayon moyen, et le
   fond de carte. C'est ce qui donne a chaque rediffusion sa surface propre sans
   ramener le poids de la carte illustree — ni chapo, ni pied, ni action. */
.replay-tile {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    min-width: 0;

    padding: var(--spacing-ms);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--surface-2);
}

/* Le visuel EST le déclencheur de lecture : c'est un bouton, donc il faut
   défaire l'apparence que le navigateur lui donne. */
/* PISTE PLUS ETROITE dans une COLONNE de page. La fiche d'evenement pose sa
   grille dans 750 px, pas sur la pleine largeur : a la piste par defaut elle
   n'y tiendrait que deux cartes de 367 px, une vignette de la taille d'une mise
   en avant pour une liste qu'on parcourt. A 14rem elle en tient trois de 239.

   Le meme minimum ne peut pas servir les deux largeurs — c'est l'APPELANT qui
   sait dans laquelle il pose sa grille, et le parametre existe pour qu'il le
   dise. */
.replay-tiles--dense {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
}

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

.replay-tile__visual {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    cursor: pointer;
    overflow: hidden;
}

.replay-tile__image {
    display: block;
    aspect-ratio: 16 / 9;
    width: 100%;
    background-color: var(--surface-4);
}

.replay-tile__image img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;

    /* Les variantes DAM des affiches importées portent une colonne sombre d'un
       pixel sur leurs bords. Mesuré par neutralisation : masquer l'ombre ou le
       fond ne change rien, masquer l'image fait disparaître les traits. Un
       cheveu d'agrandissement la pousse hors du cadre, le visuel étant en
       `overflow: hidden`.

       CE QUE CE ROGNAGE NE FAIT PAS : certaines affiches sont de vraies vidéos
       pillarboxées, 25 % de noir de chaque côté. Aucun agrandissement
       raisonnable ne les nettoie — elles demandent un recadrage à l'import. */
    scale: 1.015;
}

/* Le triangle de lecture, et non la grosse pastille de la carte illustrée : à
   140 px de large, un rond de 52 px mangeait le tiers du visuel. */
.replay-tile__play {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    color: var(--color-primary);
}

/* LE FOND DU TRIANGLE EST UN DISQUE, PAS UN VOILE PLEIN. Etale sur `inset: 0`,
   il teintait l'affiche ENTIERE — onze diapositives passees au bleu pour rendre
   lisible un glyphe de 18 px. Le disque ne couvre que ce qu'il doit couvrir.

   Sur la hachure il n'y a rien a couvrir : le triangle s'y pose nu, comme dans
   la maquette. Le selecteur suit donc l'etat du visuel, pas l'inverse. */
.replay-tile__play::before {
    content: "";
    position: absolute;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--color-navy) 62%, transparent);
    transition: background-color 120ms ease;
}

.replay-tile__image--empty ~ .replay-tile__play::before {
    background: none;
}


.replay-tile__image--empty ~ .replay-tile__play {
    color: var(--color-primary);
}

.replay-tile__image:not(.replay-tile__image--empty) ~ .replay-tile__play {
    color: var(--color-on-primary);
}

/* Le glyphe passe AU-DESSUS du disque, que le pseudo-element pose derriere. */
.replay-tile__play svg {
    position: relative;
}

/* AU SURVOL, LE DISQUE APPARAIT — ET LE GLYPHE DOIT SUIVRE.

   Sur la hachure, le triangle se pose nu en bleu et le disque n'existe pas. Au
   survol le disque marine apparaissait SANS que la couleur du glyphe change :
   bleu sur marine, donc un rond uniformement bleu sombre ou l'on ne
   distinguait plus le triangle. La regle de couleur du survol doit gagner sur
   celle de l'etat de repos, pour les deux cas — d'ou le meme selecteur, et non
   une regle ajoutee a cote. */
.replay-tile__visual:hover .replay-tile__play::before,
.replay-tile__visual:focus-visible .replay-tile__play::before {
    background: var(--color-navy);
}

.replay-tile__visual:hover .replay-tile__play,
.replay-tile__visual:focus-visible .replay-tile__play,
.replay-tile__visual:hover .replay-tile__image--empty ~ .replay-tile__play,
.replay-tile__visual:focus-visible .replay-tile__image--empty ~ .replay-tile__play {
    color: var(--color-on-primary);
}

/* Les repères sur UNE ligne, sous le visuel : rang, jour, durée. C'est ce qui
   remplace la pastille de durée posée SUR l'image et le rond de rang mordu par
   l'angle — deux objets à dessiner, deux zones à réserver, pour ce qui tient
   en six mots. */
.replay-tile__marks {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    margin: 0;
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

.replay-tile__dot {
    flex: 0 0 auto;
    width: 0.4375rem;
    height: 0.4375rem;
    border-radius: var(--radius-pill);

    /* CENTRE SUR LES CAPITALES, PAS SUR LA BOITE DE LIGNE.

       `align-items: center` centre le rond sur la boite de la ligne. Or ce
       texte est en capitales, et la fonte reserve beaucoup d'espace au-dessus
       d'elles : mesure du 2026-08-29 sur Source Sans 3 a 11 px, hauteur de
       capitale 8 px, jambage 0, centre optique a 9,75 px du haut de la boite
       contre 8,25 px pour son centre geometrique. Le rond flottait donc 1,5 px
       trop haut, ce qui se voit a cette taille.

       Le decalage n'est pas un nombre choisi : c'est l'ecart mesure. */
    transform: translateY(1.5px);

    /* UNE seule teinte, et c'est un constat de donnée : la maquette fait varier
       la pastille par type de session, or `evt_event_type_config.color` est vide
       sur les quatre types en base. Le jour où elle sera renseignée, la teinte
       viendra de là ; en attendant une couleur inventée par vignette dirait
       quelque chose que rien ne porte. */
    background: var(--color-section-ressources);
}

.replay-tile__title {
    margin: 0;
    font-family: var(--font-title);
    font-size: var(--font-size-base);
    font-weight: 600;
    line-height: 1.3;
    color: var(--color-navy);
}

.replay-tile__title a {
    color: inherit;
    text-decoration: none;
}

.replay-tile__title a:hover,
.replay-tile__title a:focus-visible {
    text-decoration: underline;
}

.replay-tile__bookmark {
    align-self: flex-start;
    margin-top: var(--spacing-2xs);
}

/* CE BLOC EST APRES LES REGLES DE BASE, ET CE N'EST PAS UN HASARD : a
   specificite egale, c'est l'ORDRE qui tranche, y compris pour une media
   query. Pose plus haut dans la feuille — ou il l'etait il y a cinq minutes —
   il etait reecrit par les regles qu'il devait surcharger, et le symptome
   trompait : la media query correspondait bien, le style calcule etait
   l'ancien. Le module documente deja ce piege. */
/* ══ SOUS 48em : LA VIGNETTE DEVIENT UNE RANGEE ═══════════════════════════

   C'est le composant 52 de la maquette, « replays en liste » — la grille et la
   liste y sont deux formes du MEME objet, et la planche pose les deux cote a
   cote. Sur un telephone, la grille ne tient pas : mesure a 375 px, deux
   colonnes de 142 px, des titres sur sept lignes et des cartes de hauteurs
   inegales.

   En rangee, le visuel passe a gauche a largeur fixe et tout le texte a droite.
   Le titre dispose alors de la largeur de l'ecran moins une vignette, au lieu
   d'une demi-colonne.

   Le meme balisage sert les deux formes : seule la mise en page change. */
@media (width < 48em) {
    .replay-tiles {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--spacing-sm);
    }

    .replay-tile {
        display: grid;
        grid-template-columns: 7.5rem minmax(0, 1fr);
        align-items: center;
        column-gap: var(--spacing-ms);
    }

    /* Le visuel garde son 16/9 : c'est le format de ce qu'il montre, et le
       deformer sur telephone rendrait les affiches illisibles. */
    .replay-tile__visual {
        width: 7.5rem;
    }

    .replay-tile__body {
        gap: var(--spacing-2xs);
    }

    /* Le disque de lecture se resserre avec la vignette : a 120 px de large,
       les 36 px du bureau en couvraient le tiers. */
    .replay-tile__play::before {
        width: 1.75rem;
        height: 1.75rem;
    }

    .replay-tile__play svg {
        width: 0.875rem;
        height: 0.875rem;
    }

    /* « Lire plus tard » est la seule commande de la vignette, et elle
       mesurait 34 px de haut : sous la cible de 44 px que la maquette
       « Vues mobiles » pose pour tout ce qui se touche. `btn--sm` porte cette
       hauteur pour tout le site — on la releve ICI, sur la vignette, plutot
       que dans la grammaire ou elle vaut aussi pour des barres d'outils
       denses ou 44 px de haut chasseraient tout le reste. */
    .replay-tile__bookmark {
        min-height: var(--touch-target-min);
    }
}


/* ── En pratique ──
   Le rappel des faits en pied de fiche. Il n'est pas une redite du rail : le
   rail est en `display: none` sous 1024 px, donc sur tablette et telephone il
   est le SEUL endroit ou le lieu, l'organisateur et l'iCal existent. */
.event-practical {
    margin-top: var(--spacing-2xl);
}

.event-practical__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    margin: var(--spacing-md) 0 0;
}

/* L'attente, quand l'evenement n'a pas encore eu lieu : une phrase, pas un
   encart. Ce n'est pas un etat vide a meubler — c'est une reponse a une
   question que le lecteur se pose, et elle tient en huit mots. */
.event-replays__pending {
    margin: 0;
    color: var(--color-text-light);
}

/* ── Le pied de la fiche d'evenement ──

   `.article-single` pose `padding-bottom: 3xl` (64 px). Sur la fiche
   d'ACTUALITE c'est juste : la bande « A lire aussi » suit, et 64 px la
   detachent du contenu. Sur la fiche d'EVENEMENT, plus rien ne suit depuis le
   retrait de « A l'agenda egalement » — ces 64 px s'ajoutent alors aux 24 du
   bandeau d'abonnement, et la page se termine sur 88 px de gris.

   La valeur n'est pas mauvaise, c'est son CONTEXTE qui a disparu. On la ramene
   ici, et ici seulement : la fiche d'actualite garde la sienne, qui espace
   encore quelque chose. */
.article-single.event-single {
    padding-bottom: var(--spacing-xl);
}

/* ── Rediffusions sur la fiche simple ──
   Il ne reste que l'écart au-dessus de la section : la grille et ses cartes
   sont celles de la grammaire (`.media-cards` + `_media_card`), posées par
   `components/_replay_grid.html.twig`, partagé avec le minisite. */
.event-replays {
    margin: var(--spacing-xl) 0 0;
}

/* La modale de lecture vidéo (replays event + cartes ressource vidéo) est
   la coquille partagée, variante `modale--media` :
   `components/modal.css` + `components/_video_replay_modal.html.twig`.
   Elle ne vit pas ici parce qu'elle est incluse aussi hors minisite event
   (layout `front`). */

/* Minisite — état vide commun */
/* Etat vide : un encart hachure, pas une phrase seule au milieu du blanc.
   Une page qui affiche « Le dispositif sera detaille prochainement » en une
   ligne perdue se lit comme une page ratee ; un emplacement balise dit qu'il y
   a bien quelque chose ici, et que ce n'est pas encore pret. */
.minisite-empty {
    text-align: center;
    padding: var(--spacing-2xl) var(--spacing-lg);
    /* Le motif vient de `.ui-hatch`, posee par le gabarit : seules ses trois
       entrees sont redeclarees ici, ce qui rend EXACTEMENT les memes couleurs et
       la meme bande qu'avant — verifie en comparant les deux formes calculees.
       Le degrade etait ecrit DEUX FOIS dans cette feuille. */
    --hatch-ground: var(--evt-surface-muted);
    --hatch-ink: var(--evt-surface);
    --hatch-band: 10px;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    color: var(--color-text-light);
}

.minisite-empty svg { margin: 0 auto var(--spacing-md); }

@media (width < 48em) {
    .inscription__card { flex-direction: column; }
}

/* ══════════════════════════════════════════════════════════════
   Événements ANCESU — layout sidebar + featured + passés par année
   Classes WordPress (event-layout, event-sidebar, event-featured,
   event-main, event-grid, event-card) — adaptées aux variables locales
   ══════════════════════════════════════════════════════════════ */

/* Page header */
.event-page__header {
    margin-bottom: var(--spacing-xl);
}

.event-page__title {
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--color-text);
    margin: 0 0 var(--spacing-xs);
}

.event-page__subtitle {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    margin: 0;
}

@media (min-width: 48em) {
    .event-page__title { font-size: 2rem; }
}

/* Layout 2 colonnes : sidebar + main */
.event-layout {
    display: flex;
    gap: var(--spacing-2xl);
}

/* Bouton filtres mobile (masqué en desktop) */
.event-filters-toggle {
    display: none;
}

/* Mobile : sidebar masquée, bouton filtres visible */
.event-sidebar {
    display: none;
}

@media (width < 64em) {
    .event-filters-toggle {
        display: inline-flex;
        align-items: center;
        gap: var(--spacing-sm);
        padding: 0.625rem var(--spacing-md);
        background: var(--color-bg-light);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-lg);
        font-size: var(--font-size-sm);
        font-weight: 600;
        color: var(--color-text);
        cursor: pointer;
        margin-bottom: var(--spacing-md);
        width: 100%;
        justify-content: center;
        -webkit-tap-highlight-color: transparent;
        transition: background-color var(--transition-fast);
    }

    .event-filters-toggle:active { background: var(--color-border); }

    .event-filters-toggle__badge {
        font-size: var(--font-size-xs);
        font-weight: 700;
        color: var(--color-primary);
        background: var(--color-primary-light);
        padding: 0.125rem 0.5rem;
        border-radius: 100px;
    }

    /* Sidebar mobile : affichée quand filtersOpen via Alpine toggle class */
    .event-sidebar--open {
        display: block;
        width: 100%;
        position: static;
        margin-bottom: var(--spacing-md);
        background: var(--color-bg-light);
        border-radius: var(--radius-lg);
        padding: var(--spacing-md);
        border: 1px solid var(--color-border);
    }

    .event-layout {
        flex-direction: column;
        gap: 0;
    }
}

/* Desktop : sidebar sticky normale */
@media (min-width: 64em) {
    .event-sidebar {
        display: block;
        flex-shrink: 0;
        width: 15rem;
        position: sticky;
        top: 5rem;
        align-self: flex-start;
        max-height: calc(100vh - 6rem);
        overflow-y: auto;
    }
}

.event-sidebar__inner {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

.event-main {
    flex: 1;
    min-width: 0;
}

/* Recherche sidebar */
.event-sidebar__search { margin: 0; }
.event-sidebar__search-field { position: relative; }

.event-sidebar__search-icon {
    position: absolute;
    left: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-text-light);
    pointer-events: none;
}

.event-sidebar__search-input {
    width: 100%;
    padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-sm) 2.375rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-family: inherit;
    font-size: var(--font-size-sm);
    color: var(--color-text);
    background: var(--surface-2);
    transition: border-color 0.15s ease;
}

.event-sidebar__search-input:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 12%, transparent);
}

.event-sidebar__search-input::placeholder { color: var(--color-text-light); }

/* Sections sidebar */
.event-sidebar__section {
    border-top: 1px solid var(--color-border);
    padding-top: var(--spacing-md);
}

.event-sidebar__title {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-size: var(--font-size-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-text-light);
    margin: 0 0 var(--spacing-sm);
}

.event-sidebar__title svg { flex-shrink: 0; opacity: 0.6; }

.event-sidebar__list { list-style: none; margin: 0; padding: 0; }
.event-sidebar__list li + li { margin-top: 1px; }

.event-sidebar__list-link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
    padding: 0.375rem var(--spacing-sm);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-sm);
    color: var(--color-text);
    text-decoration: none;
    transition: all 0.15s ease;
}

.event-sidebar__list-link:hover {
    background: var(--color-bg-light);
    color: var(--color-primary);
}

.event-sidebar__list-link--active {
    background: var(--color-primary-light);
    color: var(--color-primary);
    font-weight: 600;
}

.event-sidebar__count {
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
    background: var(--color-bg-light);
    padding: 1px 0.375rem;
    border-radius: 0.625rem;
    min-width: 1.375rem;
    text-align: center;
}

.event-sidebar__list-link--active .event-sidebar__count {
    background: var(--color-primary);
    color: var(--ink-on-dark);
}

.event-sidebar__reset {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-size: var(--font-size-sm);
    color: var(--color-primary);
    text-decoration: none;
    padding: var(--spacing-xs) 0;
}

.event-sidebar__reset:hover { text-decoration: underline; }

/* Main header */
.event-main__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--spacing-lg);
    padding-bottom: var(--spacing-sm);
    border-bottom: 1px solid var(--color-border);
}

.event-main__count {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    margin: 0;
}

/* Section titles */
.event-main__section { margin-bottom: var(--spacing-2xl); }
.event-main__section:last-child { margin-bottom: 0; }

.event-main__section-title {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-size: var(--font-size-base);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-text-light);
    margin: 0 0 var(--spacing-lg);
}

.event-main__section-title svg { flex-shrink: 0; color: var(--color-primary); }

.event-main__section-count {
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--color-text-light);
    background: var(--color-bg-light);
    padding: 1px 0.375rem;
    border-radius: 0.625rem;
    min-width: 1.375rem;
    text-align: center;
}

/* Featured event — grille image + body */
.event-featured {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--spacing-xl);
    margin-bottom: var(--spacing-xl);
    padding-bottom: var(--spacing-xl);
    border-bottom: 1px solid var(--color-border);
}

.event-featured__image {
    display: block;
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.event-featured__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.2s ease;
}

.event-featured__image:hover img { transform: scale(1.03); }

.event-featured__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--spacing-sm);
}

.event-featured__meta-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    align-items: center;
}

.event-featured__type {
    display: inline-block;
    padding: 2px var(--spacing-sm);
    background: var(--color-primary-light);
    color: var(--color-primary);
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-radius: var(--radius-sm);
}

.event-featured__title {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: var(--line-height-tight);
    margin: 0;
}

.event-featured__title a { color: var(--color-text); text-decoration: none; }
.event-featured__title a:hover { color: var(--color-primary); }

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

.event-featured__details {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-md);
}

.event-featured__detail {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.event-featured__detail svg { flex-shrink: 0; opacity: 0.6; }

.event-featured__actions {
    display: flex;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-xs);
}

/* Grid upcoming cards */
.event-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--spacing-lg);
}

/* Card upcoming */
.event-card--upcoming { border-top: 3px solid var(--color-primary); }

/* Date badge overlay sur image */
.event-card__date-badge {
    position: absolute;
    top: var(--spacing-sm);
    left: var(--spacing-sm);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 3rem;
    padding: var(--spacing-xs) var(--spacing-sm);
    background: var(--ink-on-dark);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    z-index: 1;
}

.event-card__date-day {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-primary);
}

.event-card__date-month {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--color-primary);
    letter-spacing: 0.5px;
}

.event-card__image-link {
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    position: relative;
}

.event-card__image--placeholder {
    background: var(--color-bg-light);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

/* Empty */
.event-empty {
    text-align: center;
    padding: var(--spacing-3xl) var(--spacing-md);
    color: var(--color-text-light);
}

.event-empty svg { margin-bottom: var(--spacing-md); }
.event-empty p { font-size: var(--font-size-lg); margin-bottom: var(--spacing-xl); }

/* ── Agenda card (liste avec bloc date bleu) ── */
.event-agenda__card {
    display: flex;
    align-items: stretch;
    text-decoration: none;
    color: inherit;
    background: var(--surface-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
    margin-bottom: var(--spacing-md);
    transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.event-agenda__card:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}

.event-agenda__body {
    flex: 1;
    min-width: 0;
    padding: var(--spacing-md);
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

/* Legacy — garder pour compatibilité */
.event-past__year {
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--color-text);
    margin: var(--spacing-xl) 0 var(--spacing-sm);
    padding-bottom: var(--spacing-xs);
    border-bottom: 2px solid var(--color-border);
}

.event-past__year:first-child { margin-top: 0; }

.event-past__item { border-bottom: 1px solid var(--color-border); }
.event-past__item:last-of-type { border-bottom: none; }

.event-past__link {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-md);
    padding: var(--spacing-md) var(--spacing-sm);
    text-decoration: none;
    color: inherit;
    border-radius: var(--radius-sm);
    transition: background 0.15s ease;
}

.event-past__link:hover { background: var(--color-bg-light); }

.event-past__date {
    flex-shrink: 0;
    min-width: 10rem;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    padding-top: 0.125rem;
    line-height: var(--line-height-base);
}

.event-past__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.event-past__title {
    display: block;
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--color-text);
    line-height: var(--line-height-tight);
}

.event-past__link:hover .event-past__title { color: var(--color-primary); }

.event-past__location {
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.event-past__arrow {
    flex-shrink: 0;
    color: var(--color-text-light);
    margin-top: 0.375rem;
    transition: color 0.15s ease, transform 0.15s ease;
}

.event-past__link:hover .event-past__arrow {
    color: var(--color-primary);
    transform: translateX(2px);
}

/* ── Responsive ── */
@media (width < 64em) {
    .event-featured { grid-template-columns: 1fr; }
    .event-featured__image { max-height: 17.5rem; }
}

@media (width < 48em) {
    .event-grid { grid-template-columns: 1fr; }
    .event-featured__title { font-size: 1.375rem; }
    .event-featured__details { flex-direction: column; gap: var(--spacing-xs); }

    .event-past__link { flex-direction: column; gap: var(--spacing-xs); }
    .event-past__date { min-width: auto; }
}

@media (width < 36em) {
    .event-sidebar__inner { flex-direction: column; }
    .event-sidebar__section { min-width: 0; }
}

@media print {
    .event-sidebar, .event-main__header { display: none; }
    .event-layout { display: block; }
}

/* ══════════════════════════════════════════════════════════════
   Fiche événement « simple » (sans minisite) — sidebar blocs
   ══════════════════════════════════════════════════════════════
   Le layout `.article-single` (zones/article.css) porte la grille
   contenu + sidebar. Cette section ajoute uniquement les blocs
   propres à la fiche événement : nom + adresse du lieu, et bouton
   CTA d'inscription pleine largeur en sidebar.
   ══════════════════════════════════════════════════════════════ */

.event-single__panel {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
}

.event-single__venue-name {
    margin: 0;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
}

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

/* CTA inscription : version pleine largeur dans la sidebar pour
   appeler à l'action sans noyer le visuel. */
.event-single__register-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    width: 100%;
}

/* ── Hero `_list_hero` variante `event` ─────────────────────────
   La fiche événement utilise une image de fond sur la card et
   n'a pas besoin du dégradé navy par défaut autour du breadcrumb.
   On annule donc le fond du hero parent et on accentue le radius
   de la card editoriale pour un visuel un peu plus marqué. */
/* L'exception a la bande de tete du site est levee (2026-08-10) : la fiche
   evenement la porte comme les autres pages, depuis que son contenu est une
   carte blanche qui a besoin d'un fond pour se detacher. La regle qui la
   retirait dans `app.css` est supprimee ; il ne reste ici que le retrait du
   fond propre au hero, qui lui n'a jamais eu de rapport avec la bande. */
.list-hero--event {
    background: none;
}

.list-hero--event .list-hero__container {
    border-radius: 1.5rem;
}

/* ══════════════════════════════════════════════════════════════
   Accueil minisite (show) — landing page de l'événement

   Style landing percutant : grosses citations, gros nombres, cards
   avec shadow et hover lift, CTA gradient. Couleur de section prise
   sur `var(--section-color)` qui adapte automatiquement la palette
   selon le `body.section--*` (colloques rouge pour event minisite,
   etc.). Hero rendu par le layout `event-minisite.html.twig`.

   Sections :
     - status-bar : badge temporel + CTA pill rapide
     - excerpt : citation éditoriale grande typo + accent latéral
     - body : TipTap rendu via `|body|raw`
     - stats : très gros nombres (3xl), nu, séparateurs verticaux
     - section : eyebrow + titre éditorial + contenu
     - programme-preview : cards avec time chunk en section-color
     - speakers : cards avec avatar large + hover lift + shadow
     - cta-final : bandeau gradient avec gros bouton primary
   ══════════════════════════════════════════════════════════════ */

/* ── Status bar : badge + CTA rapide accolés ── */
.show__status-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-xl);
}

.show__status {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.3125rem 0.875rem;
    border-radius: 999px;
    font-size: 0.6875rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.show__status--upcoming {
    background: var(--section-color);
    color: white;
}

.show__status--ongoing {
    background: var(--color-success);
    color: white;
}

.show__status--past {
    background: var(--color-bg-light);
    color: var(--color-text-light);
}

.show__quick-cta {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.4375rem 1rem;
    border: 2px solid var(--section-color);
    border-radius: 999px;
    background: transparent;
    color: var(--section-color);
    font-size: var(--font-size-sm);
    font-weight: 700;
    text-decoration: none;
    transition: background 150ms ease, color 150ms ease;
}

.show__quick-cta:hover {
    background: var(--section-color);
    color: white;
}

.show__quick-cta:focus-visible {
    outline: 2px solid var(--section-color);
    outline-offset: 2px;
}

/* ── Excerpt : grande citation éditoriale avec accent latéral ── */
.show__excerpt {
    position: relative;
    margin: 0 0 var(--spacing-2xl);
    padding: 0.5rem 0 0.5rem 1.5rem;
    border-left: 4px solid var(--section-color);
}

.show__excerpt p {
    margin: 0;
    font-size: clamp(1.125rem, 2vw, 1.375rem);
    line-height: 1.45;
    color: var(--color-text);
    font-weight: 500;
}

/* ── Body éditorial : prose, espacement supérieur sobre ── */
.show__body {
    margin-bottom: var(--spacing-2xl);
    font-size: var(--font-size-md);
    line-height: 1.65;
}

/* ── CTA inscription final : bandeau gradient section-color + gros bouton ── */
.show__cta-final {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--spacing-lg);
    margin: var(--spacing-2xl) 0 0;
    padding: var(--spacing-xl) var(--spacing-2xl);
    border-radius: var(--radius-lg);
    background: linear-gradient(135deg, var(--section-color) 0%, var(--color-primary) 100%);
    color: white;
    box-shadow: var(--shadow-lg);
}

.show__cta-text {
    flex: 1;
    min-width: 0;
}

.show__cta-eyebrow {
    margin: 0 0 0.25rem;
    font-size: 0.6875rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    opacity: 0.8;
}

.show__cta-title {
    margin: 0;
    font-size: clamp(1.25rem, 2.5vw, 1.625rem);
    font-weight: 700;
    color: white;
    line-height: 1.2;
}

.show__cta-hint {
    margin: 0.375rem 0 0;
    font-size: var(--font-size-sm);
    color: var(--ink-on-dark-soft);
}

.show__cta-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.875rem 1.75rem;
    background: white;
    color: var(--section-color);
    border-radius: 999px;
    font-weight: 800;
    text-decoration: none;
    font-size: var(--font-size-base);
    transition: transform 150ms ease, box-shadow 150ms ease;
}

.show__cta-btn:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

.show__cta-btn:focus-visible {
    outline: 3px solid white;
    outline-offset: 3px;
}

/* ── Print : status bar et CTA masqués, chapô en blockquote sobre ── */
@media print {
    .show__status-bar,
    .show__quick-cta,
    .show__cta-final { display: none; }
    .show__excerpt {
        border-left: 2px solid var(--color-text);
        padding: 0 0 0 0.4cm;
    }
}

/* ═════════════════════════════════════════════════════════════════════
   Appel à communications — liste d'appels + formulaire de soumission
   ═════════════════════════════════════════════════════════════════════ */

.contributions {
    padding: clamp(2rem, 4vw, 3rem) 0;
}

.contributions__header {
    margin-bottom: 2rem;
}

.contributions__heading {
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    color: var(--color-text);
    margin: 0 0 0.5rem;
}

/* Aligne a GAUCHE, comme le titre juste au-dessus. Le chapo etait centre
   sous un titre cale a gauche : deux axes de lecture pour deux lignes qui se
   suivent. Le centrage venait du temps ou la page n'avait pas d'en-tete a
   elle. */
.contributions__lead {
    font-size: var(--font-size-base);
    line-height: 1.7;
    color: var(--color-text-light);
    margin: 0;
    max-width: var(--evt-measure);
}

/* Etat vide : un encart hachure plutot qu'une phrase seule au milieu du
   blanc. Il dit qu'il y a bien quelque chose a cet endroit, mais pas
   maintenant — une phrase isolee se lit comme une page ratee. */
.contributions__empty {
    text-align: center;
    padding: 3rem 1rem;
    /* Le motif vient de `.ui-hatch`, posee par le gabarit : seules ses trois
       entrees sont redeclarees ici, ce qui rend EXACTEMENT les memes couleurs et
       la meme bande qu'avant — verifie en comparant les deux formes calculees.
       Le degrade etait ecrit DEUX FOIS dans cette feuille. */
    --hatch-ground: var(--evt-surface-muted);
    --hatch-ink: var(--evt-surface);
    --hatch-band: 10px;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    color: var(--color-text-light);
}

.contributions__empty p {
    margin: 0.75rem 0 0;
    font-size: 0.95rem;
}

.contributions__breadcrumb {
    font-size: 0.875rem;
    color: var(--color-text-light);
    margin: 0 0 1.5rem;
}

.contributions__breadcrumb a {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    color: inherit;
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
}

.contributions__breadcrumb a:hover {
    color: var(--section-color, var(--color-primary));
}

/* Grid d'index des appels */
/* `auto-fill` et non `auto-fit` : les pistes vides sont CONSERVEES, donc un
   appel unique occupe une colonne de la grille (620 px a pleine largeur) au
   lieu de s'etirer sur les 1240 px de la page. Une carte de 1240 px pour
   quatre lignes de texte se lit comme un bandeau, pas comme une carte. */
/* `auto-fit` et non `auto-fill` — meme piege que la grille des choix du
   programme : `auto-fill` conserve les pistes vides, et un evenement qui
   n'ouvre qu'UN appel (le cas de la seule edition qui en a un) laissait une
   carte a gauche et la moitie de la page vide a droite.

   Plafond a 30rem sur la piste : une carte seule qui prendrait les 76rem du
   conteneur ne ressemblerait plus a une carte. Entre le plancher et le
   plafond, l'espace restant se lit comme une marge, pas comme un trou. */
.contributions__grid {
    display: grid;
    gap: clamp(1rem, 2vw, 1.5rem);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 30rem));
    justify-content: start;
    align-items: start;
}

.contributions-card__head-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.875rem;
}

.contributions-card__rank {
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--evt-signature);
    font-variant-numeric: tabular-nums;
}

/* Carte d'appel : filet 1 px, pas d'ombre ni de liseré coloré en tête. Le
   liseré rouge de 3 px la faisait lire comme une alerte, et l'ombre en faisait
   la seule surface flottante d'un minisite par ailleurs plat. */
.contributions-card {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: clamp(1.625rem, 3vw, 2.25rem);
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
}

.contributions-card:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.contributions-card--closed {
    opacity: 0.7;
    border-top-color: var(--color-border);
}

.contributions-card--closed:hover {
    transform: none;
    box-shadow: var(--shadow-sm);
}

.contributions-card__header {
    border-bottom: 1px solid var(--color-border);
    padding-bottom: 0.75rem;
}

/* Meme pastille que les etiquettes de type du programme : c'est le meme
   objet, une nature d'element. */
.contributions-card__type {
    display: inline-block;
    padding: 0.25rem 0.625rem;
    border-radius: var(--radius-sm);
    background: var(--evt-tint);
    color: var(--evt-blue);
    font-size: var(--font-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    margin-bottom: 0;
}

.contributions-card__title {
    font-size: clamp(1.375rem, 2.6vw, 1.75rem);
    font-weight: 700;
    color: var(--evt-ink);
    margin: 0;
    line-height: 1.25;
}

.contributions-card__description {
    font-size: var(--font-size-base);
    line-height: 1.75;
    color: var(--color-text-light);
    margin: 0;
    max-width: 46ch;
}

/* Les reperages de l'appel (dates, capacite, reglement) sur une rangee
   bordee en haut et en bas : ils se consultent d'un coup d'oeil, ils ne se
   lisent pas ligne a ligne. Chaque paire garde son intitule au-dessus de sa
   valeur, comme les panneaux lateraux des fiches. */
.contributions-card__meta {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.75rem), 1fr));
    gap: 1.125rem;
    margin: 0;
    padding-block: 1.125rem;
    border-top: 1px solid var(--evt-rule-soft);
    border-bottom: 1px solid var(--evt-rule-soft);
    font-size: var(--font-size-sm);
}

.contributions-card__meta dt {
    font-size: var(--font-size-xs);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--color-text-light);
    margin-bottom: 0.375rem;
}

.contributions-card__meta dd {
    margin: 0;
    font-size: var(--font-size-base);
    color: var(--color-text);
}

.contributions-card__meta dt {
    font-weight: 600;
    color: var(--color-text-light);
}

.contributions-card__meta dd {
    margin: 0;
    color: var(--color-text);
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.contributions-card__footer {
    margin-top: auto;
}

/* L'appel a l'action de la carte parle la meme langue que ceux du reste du
   minisite : rouge de section, coins adoucis, 44 px de haut. `.btn--primary`
   est la pilule marine du site, qui ici se confondait avec les liens. */
.contributions-card__footer .btn--primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: var(--evt-control-h);
    padding: 0.75rem 1.5rem;
    border-radius: var(--radius-sm);
    background: var(--evt-cta);
    border-color: var(--evt-cta);
    color: var(--ink-on-dark);
    font-weight: 600;
    font-size: var(--font-size-sm);
}

.contributions-card__footer .btn--primary:hover,
.contributions-card__footer .btn--primary:focus-visible {
    background: var(--evt-cta-hover);
    border-color: var(--evt-cta-hover);
    color: var(--ink-on-dark);
}

.contributions-card__status {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.875rem;
    background: var(--color-bg-light);
    color: var(--color-text-light);
    border-radius: 0.5rem;
    font-size: 0.875rem;
}

/* Dropdown nav minisite (onglet Contributions avec sous-menu) */
.minisite-nav__item--has-dropdown {
    position: relative;
}

.minisite-nav__caret {
    margin-left: 0.25rem;
    transition: transform 0.15s;
}

.minisite-nav__item--has-dropdown:hover .minisite-nav__caret,
.minisite-nav__item--has-dropdown:focus-within .minisite-nav__caret {
    transform: rotate(180deg);
}

.minisite-nav__dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 50;
    min-width: 18rem;
    margin: 0;
    padding: 0.5rem;
    list-style: none;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-top: 3px solid var(--section-color, var(--color-primary));
    border-radius: 0.5rem;
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity 0.15s, transform 0.15s, visibility 0.15s;
}

.minisite-nav__item--has-dropdown:hover > .minisite-nav__dropdown,
.minisite-nav__item--has-dropdown:focus-within > .minisite-nav__dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.minisite-nav__dropdown-link {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    padding: 0.625rem 0.875rem;
    border-radius: 0.375rem;
    text-decoration: none;
    color: var(--color-text);
    transition: background 0.1s;
}

.minisite-nav__dropdown-link:hover,
.minisite-nav__dropdown-link:focus-visible {
    background: var(--color-bg-light);
}

.minisite-nav__dropdown-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--color-text);
}

.minisite-nav__dropdown-meta {
    font-size: 0.75rem;
    color: var(--color-text-light);
}

/* Carte d'appel */
.call-card {
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    padding: clamp(1rem, 3vw, 2rem);
    margin-bottom: 2rem;
    box-shadow: var(--shadow-sm);
}

.call-card__header {
    border-bottom: 1px solid var(--color-border);
    padding-bottom: 1rem;
    margin-bottom: 1.5rem;
}

.call-card__title-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

/* Marine, pas rouge de section. Sur la fiche d'un appel c'est le titre de la
   PAGE : en rouge, il se lisait comme une alerte, et il entrait en concurrence
   avec l'appel a l'action qui porte deja cette couleur au bas du formulaire.
   L'echelle suit celle des autres titres de premier niveau du minisite. */
.call-card__title {
    font-size: clamp(1.5rem, 3vw, 2.25rem);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.01em;
    color: var(--evt-ink);
    margin: 0;
}

.call-card__type {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--section-color, var(--color-primary));
    background: var(--section-color-light, var(--color-bg-light));
    padding: 0.25rem 0.625rem;
    border-radius: 999px;
}

.call-card__dates {
    margin: 0.25rem 0 0;
    font-size: 0.875rem;
    color: var(--color-text-light);
}

.call-card__status {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin: 0.5rem 0 0;
    padding: 0.375rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 600;
    border-radius: 0.5rem;
}

.call-card__status--closed {
    background: var(--color-bg-light);
    color: var(--color-text-light);
}

.call-card__description {
    font-size: 1rem;
    line-height: 1.6;
    color: var(--color-text);
    margin: 0 0 1rem;
}

.call-card__body {
    font-size: 0.95rem;
    line-height: 1.6;
    margin-bottom: 1.5rem;
}

.call-card__pdf {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 1.5rem;
    font-size: 0.9rem;
}

.call-card__pdf a {
    color: var(--section-color, var(--color-primary));
    text-decoration: underline;
}

/* Formulaire de soumission */
.call-card__form {
    margin-top: 1.5rem;
}

/* —— UN GROUPE DE CHAMPS N'EST PAS UNE BOITE ——
   Trois `fieldset` bordes, dans une carte, elle-meme dans la carte de contenu
   du minisite : quatre cadres emboites pour un formulaire. Et leur legende
   etait peinte en `--section-color`, c'est-a-dire en ROUGE sur un colloque —
   la couleur que le reste du site reserve aux erreurs et aux alertes.

   Le `<fieldset>` reste : grouper des controles est exactement ce qu'il sert a
   faire, et son `<legend>` est ce qui nomme le groupe pour un lecteur d'ecran.
   C'est son HABILLAGE qui disparait. La legende prend le registre du sur-titre
   de la grammaire (capitales, interlettrage, encre secondaire), et un filet
   separe les groupes au lieu de les encadrer. */
.call-card__fieldset {
    border: 0;
    border-top: 1px solid var(--color-border);
    padding: var(--spacing-lg) 0 0;
    margin: 0 0 var(--spacing-xl);
}

.call-card__fieldset:first-of-type {
    border-top: 0;
    padding-top: 0;
}

.call-card__fieldset legend {
    padding: 0;
    font-size: var(--font-size-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-light);
}

/* —— LA CASE A COCHER ——
   Le seul controle du formulaire dont l'etiquette se place APRES lui, et le seul
   qui ne doit PAS s'etirer : `align-items: center` sur une rangee, et une taille
   fixe, sinon le conteneur en colonne l'aplatit sur toute la largeur.

   `flex-shrink: 0` sur la case : un intitule long la comprimerait autrement
   jusqu'a la faire disparaitre, et rien ne le signalerait — elle resterait
   cliquable, simplement invisible. */
.call-card__check {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
    font-size: var(--font-size-sm);
    color: var(--color-text);
    cursor: pointer;
}

.call-card__check input[type="checkbox"] {
    flex-shrink: 0;
    width: 1rem;
    height: 1rem;
    margin: 0;
    accent-color: var(--color-primary);
}

.call-card__check em {
    color: var(--color-danger);
    font-style: normal;
    margin-left: 0.15rem;
}

.call-card__field {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin-bottom: 1rem;
}

.call-card__field:last-child {
    margin-bottom: 0;
}

.call-card__label {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--color-text);
}

.call-card__label em {
    color: var(--color-danger, var(--color-callout-danger));
    font-style: normal;
    margin-left: 0.25rem;
}

.call-card__hint {
    font-size: 0.8rem;
    color: var(--color-text-light);
    margin: 0.25rem 0 0;
}

.call-card__field input[type="text"],
.call-card__field input[type="email"],
.call-card__field input[type="number"],
.call-card__field input[type="date"],
.call-card__field input[type="url"],
.call-card__field textarea,
.call-card__field select {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: 0.375rem;
    font-size: 0.95rem;
    font-family: inherit;
    background: var(--color-bg);
    color: var(--color-text);
    transition: border-color 0.15s, box-shadow 0.15s;
}

/* —— LES PIECES DEJA DEPOSEES ——
   Une rangee par fichier : son nom, qui l'ouvre, son poids, et la case qui le
   retire. Le retrait est une CASE et non un bouton, parce qu'il ne prend effet
   qu'a l'enregistrement : un bouton laisserait croire a une suppression
   immediate, et il n'y aurait plus de retour en arriere avant l'envoi. */
.call-card__files {
    list-style: none;
    margin: 0 0 var(--spacing-md);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.call-card__file {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs) var(--spacing-md);
    padding: var(--spacing-sm) var(--spacing-ms);
    background: var(--surface-4);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-sm);
}

.call-card__file > a {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    min-width: 0;
    color: var(--color-primary);
}

.call-card__file-size {
    color: var(--color-text-light);
    font-size: var(--font-size-xs);
}

/* La case de retrait se cale a DROITE : c'est l'action de la rangee, et les
   trois rangees alignent alors leur case sur une meme verticale. */
.call-card__file-remove {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-xs);
    margin-left: auto;
    color: var(--color-text-light);
    cursor: pointer;
}

/* —— UN CHAMP DE FICHIER EST UN CHAMP ——
   Il etait le SEUL du formulaire a n'avoir ni boite ni bordure : le controle
   brut du navigateur, pose au milieu de six champs encadres. On n'y voyait pas
   de bouton, et le nom du fichier choisi se confondait avec la prose voisine
   — rien ne distinguait « Aucun fichier choisi » d'une phrase d'aide.

   ET LA REGLE D'ORIGINE NE MATCHAIT RIEN : elle visait
   `.call-card__field input[type="file"]`, alors que ce champ est enfant DIRECT
   du `<fieldset>` — les autres champs sont enveloppes dans un `<label>`, lui
   non, parce qu'il porte son intitule dans la legende du groupe. Un selecteur
   qui ne matche rien ne rend rien, et rien ne le signale.

   La boite est celle des autres champs. Le bouton, lui, est
   `::file-selector-button` : c'est le seul moyen de l'habiller sans le
   remplacer par un declencheur en JavaScript, qui perdrait le glisser-deposer
   et le clavier que le controle natif porte deja. */
.call-card__fieldset input[type="file"] {
    padding: var(--spacing-sm) var(--spacing-ms);
    border: 1px solid var(--color-border);
    /* Le MEME rayon que ses voisins, ecrit comme eux : un champ qui s'arrondit
       differemment des cinq autres se remarque plus qu'il ne s'integre. */
    border-radius: 0.375rem;
    background: var(--color-bg);
    font-size: var(--font-size-sm);
    font-family: inherit;
    color: var(--color-text);
    transition: border-color var(--transition-fast);
    /* PLEINE LARGEUR, comme ses voisins. Un champ de fichier se dimensionne sur
       son CONTENU : sa boite s'arretait donc au nom du fichier choisi, et
       changeait de largeur a chaque selection — la seule du formulaire a bouger
       sous l'oeil. */
    width: 100%;
}

.call-card__fieldset input[type="file"]::file-selector-button {
    margin-right: var(--spacing-md);
    padding: var(--spacing-2xs) var(--spacing-ms);
    border: 1px solid var(--color-primary);
    border-radius: var(--radius-pill);
    background: var(--color-bg);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-primary);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.call-card__fieldset input[type="file"]::file-selector-button:hover {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.call-card__field input:focus,
.call-card__field textarea:focus,
.call-card__field select:focus {
    /* PAS `--section-color` : un champ au focus n'appartient pas a une rubrique,
       et sur un colloque cette variable rend du ROUGE — la couleur que le reste
       du site reserve aux erreurs. Un champ qu'on vient de selectionner se
       peignait donc comme un champ refuse. */
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--section-color-light);
}

.call-card__honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* —— UN CONSENTEMENT N'EST PAS UNE ERREUR ——
   Ce bloc portait un filet GAUCHE de 3 px en `--section-color` sur un fond
   `--section-color-light` : sur un colloque, du rouge sur du rose. Mesure du
   2026-09-03 : bordure `rgb(205, 31, 38)`, fond `rgb(245, 222, 222)`. C'est le
   dessin d'un message d'erreur, pose sur une case a cocher que personne n'a
   encore eu l'occasion de mal remplir — on lit un reproche avant d'avoir agi.

   Le depot interdit par ailleurs le filet lateral colore comme motif.

   Ce qui reste : une surface d'incise, qui distingue le consentement des
   champs sans lui donner un ton. L'asterisque d'obligation suffit a dire qu'il
   est requis, et le refus de soumission le dira le moment venu. */
.call-card__regulation {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-sm);
    padding: var(--spacing-md) var(--spacing-lg);
    margin: var(--spacing-lg) 0 0;
    background: var(--surface-4);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text);
    cursor: pointer;
}

.call-card__regulation input[type="checkbox"] {
    flex-shrink: 0;
    width: 1rem;
    height: 1rem;
    margin-top: 0.15rem;
    accent-color: var(--color-primary);
}

.call-card__regulation em {
    color: var(--color-danger, var(--color-callout-danger));
    font-style: normal;
    margin-left: 0.15rem;
}

/* Styles ALTCHA partagés dans components/altcha-widget.css */

.call-card__actions {
    display: flex;
    justify-content: flex-end;
    margin: 1.5rem 0;
}

.call-card__legal {
    font-size: 0.8rem;
    color: var(--color-text-light);
    line-height: 1.5;
    margin: 0;
    padding-top: 1rem;
    border-top: 1px solid var(--color-border);
}

/* ═════════════════════════════════════════════════════════════════════
   Page de consultation auteur d'une soumission
   ═════════════════════════════════════════════════════════════════════ */

.submission {
    padding: clamp(2rem, 4vw, 3rem) 0;
}

.submission__container {
    max-width: 48rem;
}

.submission__breadcrumb {
    font-size: 0.875rem;
    color: var(--color-text-light);
    margin: 0 0 1rem;
}

.submission__breadcrumb a {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
}

.submission__breadcrumb a:hover {
    color: var(--section-color, var(--color-primary));
}

.submission__breadcrumb span {
    margin: 0 0.5rem;
    color: var(--color-text-light);
}

.submission__header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

.submission__title {
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    color: var(--color-text);
    margin: 0;
    flex: 1;
    min-width: 60%;
}

.submission__status {
    display: inline-flex;
    align-items: center;
    padding: 0.375rem 0.875rem;
    font-size: 0.875rem;
    font-weight: 600;
    border-radius: 999px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.submission__status--submitted { background: var(--evt-state-info-bg); color: var(--evt-state-info-ink); }
.submission__status--under_review { background: var(--evt-state-warn-bg); color: var(--evt-state-warn-ink); }
.submission__status--accepted { background: var(--evt-state-ok-bg); color: var(--evt-state-ok-ink); }
.submission__status--rejected { background: var(--evt-state-ko-bg); color: var(--color-callout-danger); }
.submission__status--withdrawn { background: var(--evt-state-off-bg); color: var(--evt-state-off-ink); }

.submission__meta {
    font-size: 0.875rem;
    color: var(--color-text-light);
    margin: 0 0 2rem;
}

/* —— L'ECART APPARTIENT A CE QUI SUIT ——
   La section posait `margin-bottom: 2rem` et la rangee d'actions
   `margin-top: --spacing-xl` : les deux s'AJOUTAIENT, soit 64 px entre la carte
   « Auteur principal » et « Actions » pour un rythme voulu a 32. Septieme
   occurrence de ce doublement dans le depot, et toujours la meme cause — une
   marge basse sur TOUTES les sections, plus une marge haute sur ce qui les
   suit.

   Une marge basse sur toutes les sections en met d'ailleurs une sous la
   DERNIERE, qui n'a rien apres elle. `+` et `margin-top` ferment les deux
   defauts d'un coup. */
.submission__section {
    margin: 0;
    padding: var(--spacing-lg);
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

/* AUCUNE MARGE : le conteneur (`minisite-section`) est un flex en colonne avec
   son propre `gap`. Ma marge s'y AJOUTAIT — 24 de gouttiere plus 32 de marge,
   soit 56 px la ou la page en veut 24. Deuxieme fois dans le meme correctif :
   j'ai retire le doublement d'un cran et je l'ai recree au cran d'au-dessus,
   faute d'avoir regarde le PARENT avant d'ecrire l'ecart.

   Le rythme de cette page est donc celui de toutes les autres du minisite, ce
   qui est la bonne reponse : rien ici ne justifie un ecart particulier. */

.submission__section--review {
    background: var(--section-color-light);
    border-color: var(--section-color);
}

.submission__section-title {
    font-size: 0.875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--section-color, var(--color-text));
    margin: 0 0 1rem;
}

.submission__details {
    display: grid;
    grid-template-columns: 1fr 2fr;
    gap: 0.5rem 1rem;
    margin: 0;
}

.submission__details dt {
    font-weight: 600;
    color: var(--color-text-light);
    font-size: 0.875rem;
}

.submission__details dd {
    margin: 0;
    color: var(--color-text);
}

.submission__coauthors {
    list-style: none;
    padding: 0;
    margin: 0;
}

.submission__coauthors li {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--color-border);
}

.submission__coauthors li:last-child {
    border-bottom: none;
}

.submission__attachments {
    list-style: none;
    padding: 0;
    margin: 0;
}

.submission__attachments li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0;
    border-bottom: 1px solid var(--color-border);
}

.submission__attachments li:last-child {
    border-bottom: none;
}

.submission__attachment-meta {
    margin-left: auto;
    font-size: 0.8rem;
    color: var(--color-text-light);
}

/* —— LES DEUX ACTIONS SUR UNE MEME LIGNE DE BASE ——
   « Modifier » etait cale a gauche et « Retirer » a droite, a des hauteurs
   differentes : deux gestes de meme rang, presentes comme s'ils s'opposaient.
   Ils s'opposent en CONSEQUENCE, pas en rang — c'est le ton du bouton qui le
   dit (secondaire contre danger), pas sa position.

   Une rangee qui se replie : sous 30 rem, deux boutons de cette longueur ne
   tiennent pas cote a cote, et les empiler vaut mieux que les ecraser. */
.submission__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--spacing-md);
}

/* L'EN-TETE PREND LA RANGEE ENTIERE. Il est le premier enfant de la rangee
   d'actions, donc un element de flex comme les boutons : il s'est retrouve A
   COTE d'eux, comme s'il en etait un. Defaut introduit en passant les actions
   en rangee — c'est le prix a payer quand on change le `display` d'un
   conteneur sans regarder ce qu'il contient DEJA. */
.submission__actions > .section-header {
    flex: 1 0 100%;
    margin-bottom: 0;
}

/* Le depliant d'edition prend la largeur quand il est OUVERT : son formulaire
   ne se lit pas dans la moitie d'une rangee. Ferme, il reste un bouton. */
.submission__edit[open] {
    flex: 1 0 100%;
}

/* —— LA REFERENCE, LA DATE ET L'ECHEANCE SUR UNE RANGEE ——
   Elles etaient une phrase separee par des points medians, qui se lisait comme
   une seule ligne de prose alors que ce sont trois FAITS qu'on releve. */
.submission__facts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs) var(--spacing-lg);
    /* AUCUNE MARGE : le conteneur porte son `gap`. Elle s'y ajoutait — 24 de
       gouttiere plus 24 de marge, soit 48 px avant l'avis de courriel quand
       tout le reste de la page est a 24. */
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.submission__reference {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.submission__reference-label {
    font-size: var(--font-size-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* La reference est une VALEUR qu'on recopie : chasse fixe, encre pleine. C'est
   exactement l'emploi pour lequel la fonte de donnees existe — a l'inverse des
   phrases de la carte d'appel, qui n'auraient jamais du la porter. */
.submission__reference-value {
    font-family: var(--font-data);
    font-size: var(--font-size-sm);
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--color-text);
}

/* —— LA DECISION ——
   Elle ouvre la page, parce que c'est ce qu'on vient apprendre. Un aplat teinte
   et non une simple ligne : c'est le seul bloc de la page qui annonce un
   RESULTAT, et il doit se distinguer des faits qui l'entourent.

   LA TEINTE SUIT LA DECISION, pas la rubrique — vert pour un accord, rouge
   pour un refus, ambre pour une demande. Le texte reste en ENCRE : les trois
   tons servent de fond, jamais de couleur de lettre, faute de quoi le contraste
   depend du ton et se degrade sans qu'on le voie. */
.submission__decision {
    padding: var(--spacing-lg);
    border-radius: var(--radius-md);
    background: var(--surface-4);
}

.submission__decision--accepted { background: var(--tint-success); }
.submission__decision--rejected { background: var(--tint-danger); }
.submission__decision--revision_requested { background: var(--tint-warning); }

.submission__decision-title {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    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-text);
}

.submission__decision-notes {
    margin: var(--spacing-md) 0 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text);
}

/* La consigne d'action se detache du motif : l'un explique, l'autre dit quoi
   faire, et les confondre fait lire la consigne comme la fin du motif. */
.submission__decision-hint {
    margin: var(--spacing-md) 0 0;
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--color-border);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
}

/* —— OU EN EST LE DOSSIER —— (frise partagee)
   Employee par le suivi d'une CONTRIBUTION et par celui d'une CANDIDATURE AU
   PARTENARIAT. Elle s'appelait `submission__step*`, du nom de son premier
   appelant : un prefixe tire du premier usage condamne sa propre reutilisation,
   et c'est le defaut que `design-system.md` decrit sous « un style nomme d'apres
   son premier appelant ne se partage pas sans mentir sur son domaine ».

   Le balisage vit dans `components/_progress_steps.html.twig` : deux pages qui
   recopient la meme frise finissent par en avoir deux.
   —— CE QUE LA FORME PROTEGE ——
   Trois etapes en colonne, reliees par un filet continu. La colonne et non la
   rangee : les libelles portent une phrase d'explication chacun, et trois
   colonnes de texte cote a cote sur 782 px donneraient trois blocs de quatre
   lignes.

   L'ETAPE COURANTE se distingue par son ENCRE et son marqueur plein, jamais par
   la seule couleur : elle porte aussi `aria-current="step"`, qui est ce qu'un
   lecteur d'ecran annonce. Les etapes a venir restent lisibles — elles disent
   ce qui reste, et c'est la question de qui vient consulter son suivi. */
.evt-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    position: relative;
}

.evt-steps__item {
    display: grid;
    grid-template-columns: 1.25rem 1fr;
    gap: var(--spacing-md);
    align-items: start;
    position: relative;
}

/* Le filet relie les marqueurs, et s'arrete au DERNIER : sous lui il ne
   menerait nulle part. */
.evt-steps__item:not(:last-child)::before {
    content: '';
    position: absolute;
    left: 0.5625rem;
    top: 1.25rem;
    bottom: calc(-1 * var(--spacing-md));
    width: 2px;
    background: var(--color-border);
}

.evt-steps__marker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--radius-pill);
    border: 2px solid var(--color-border);
    background: var(--color-bg);
    color: var(--color-on-primary);
}

.evt-steps__item--done .evt-steps__marker {
    background: var(--color-primary);
    border-color: var(--color-primary);
}

.evt-steps__item--current .evt-steps__marker {
    border-color: var(--color-primary);
    border-width: 5px;
}

.evt-steps__body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-3xs, 0.125rem);
    min-width: 0;
}

.evt-steps__label {
    font-weight: 600;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.evt-steps__item--current .evt-steps__label,
.evt-steps__item--done .evt-steps__label {
    color: var(--color-text);
}

.evt-steps__detail {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* —— L'AVIS DE COURRIEL ——
   Une incise, pas une alerte : rien n'a echoue, on informe. D'ou la surface de
   niveau 4 et l'encre ordinaire, sans teinte d'etat et sans filet lateral. */
.submission__mail {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-sm);
    padding: var(--spacing-md) var(--spacing-lg);
    /* Idem, et pire : 24 de gouttiere plus 32 de marge, soit 56 px APRES. Le
       bloc paraissait flotter, ecarte de ses deux voisins par un rythme qu'il
       etait seul a porter.

       TROISIEME OCCURRENCE du meme doublement dans ce seul fichier, et les trois
       sont de moi : j'ecris une marge sans regarder si le PARENT porte deja un
       `gap`. Le controle est l'ecart RENDU entre deux blocs, jamais la valeur
       declaree — les trois fois, la declaration etait juste. */
    margin: 0;
    background: var(--surface-4);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text);
}

.submission__mail svg {
    flex-shrink: 0;
    margin-top: 0.15rem;
    color: var(--color-text-light);
}

.submission__locked {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 1rem;
    background: var(--color-bg-light);
    border-radius: 0.5rem;
    font-size: 0.9rem;
    color: var(--color-text-light);
    margin-top: 2rem;
}

.submission__edit summary {
    cursor: pointer;
    user-select: none;
}

.submission__edit-form {
    margin-top: 1rem;
    padding: 1.25rem;
    background: var(--color-bg-light);
    border-radius: 0.5rem;
}

.submission__field {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin-bottom: 1rem;
}

.submission__field input {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: 0.375rem;
    font-size: 0.95rem;
}

.submission__hint {
    font-size: 0.85rem;
    color: var(--color-text-light);
    margin: 0.5rem 0;
}

.submission__form-actions,
.submission__withdraw {
    display: flex;
    justify-content: flex-end;
    margin: 0;
}

@media (width < 37.5em) {
    .submission__details {
        grid-template-columns: 1fr;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   Blocs TipTap événement — présentation pilotée par `EventBlockLayout`
   ══════════════════════════════════════════════════════════════════════════
   Les réglages du rédacteur arrivent en `data-*` sur `.tiptap-event-block`
   (largeur, fond, variante, colonnes). Le RESPONSIVE n'en fait pas partie :
   il est porté ici par `auto-fit`, pour que le rédacteur n'ait jamais à
   garantir une propriété que la feuille de style garantit déjà. Le nombre de
   colonnes est donc un PLAFOND, pas une contrainte.

   `data-*` non déclaré dans `html_sanitizer.yaml` (`tiptap.sanitizer.trusted`)
   = attribut retiré en silence. Tout nouveau réglage se whiteliste là-bas.
   ────────────────────────────────────────────────────────────────────────── */

.tiptap-event-block {
    --tiptap-event-cols: 3;

    margin: var(--spacing-xl) 0;
}

/* ── Largeur ─────────────────────────────────────────────────────────────── */

.tiptap-event-block[data-width="large"] {
    /* Déborde symétriquement de la colonne de texte, sans casser le flux. */
    margin-inline: calc(var(--spacing-2xl) * -1);
}

.tiptap-event-block[data-width="pleine-largeur"] {
    /* Pleine largeur de la fenêtre depuis un conteneur centré, et la barre de
       défilement est RETRANCHÉE : `100vw` l'inclut, la zone de contenu non.
       Sans cette correction la bande dépasse de la moitié de la barre de chaque
       côté et la page gagne un défilement horizontal.

       Le défaut est introuvable en navigateur sans interface, dont les barres
       sont superposées et larges de zéro — signalé trois fois le 2026-08-29 et
       mesuré à zéro de 320 à 1600 px avant qu'on comprenne que c'était
       l'instrument. `--scrollbar-width` est posée sur la racine par `app.js` ;
       le repli à `0px` rend la règle identique à l'ancienne sans script.

       Cette explication vivait sur `.event-single__related`, l'autre bande bord
       à bord de la feuille, retirée avec sa section. Un renvoi vers une règle
       supprimée ne renvoie nulle part : elle est recopiée ici plutôt que
       perdue, et cette bande est désormais la seule concernée. */
    margin-inline: calc(50% - 50vw + var(--scrollbar-width, 0px) / 2);
    padding-inline: var(--spacing-xl);
}

@media (width < 60em) {
    /* Sous cette largeur, la colonne de texte occupe déjà tout l'écran :
       déborder n'a plus de sens et provoquerait un défilement horizontal. */
    .tiptap-event-block[data-width="large"],
    .tiptap-event-block[data-width="pleine-largeur"] {
        margin-inline: 0;
        padding-inline: 0;
    }
}

/* ── Fond ────────────────────────────────────────────────────────────────── */

.tiptap-event-block[data-bg="teinte"],
.tiptap-event-block[data-bg="accentue"] {
    padding: var(--spacing-xl);
    border-radius: var(--radius-md);
}

.tiptap-event-block[data-bg="teinte"] {
    background-color: var(--color-bg-light);
}

.tiptap-event-block[data-bg="accentue"] {
    background-color: var(--section-color, var(--color-primary));
    color: var(--ink-on-dark);
}

.tiptap-event-block[data-bg="accentue"] a {
    color: inherit;
}

/* ── Colonnes ────────────────────────────────────────────────────────────── */

.tiptap-event-block[data-cols="2"] { --tiptap-event-cols: 2; }
.tiptap-event-block[data-cols="3"] { --tiptap-event-cols: 3; }
.tiptap-event-block[data-cols="4"] { --tiptap-event-cols: 4; }

.tiptap-event-block[data-variant="grille"] .tiptap-event-speakers__grid,
.tiptap-event-block[data-variant="grille"] .tiptap-event-sponsors__grid,
.tiptap-event-block[data-variant="logos"] .tiptap-event-sponsors__grid {
    display: grid;
    grid-template-columns: repeat(
        auto-fit,
        minmax(calc((100% - (var(--tiptap-event-cols) - 1) * var(--spacing-md)) / var(--tiptap-event-cols)), 1fr)
    );
    gap: var(--spacing-md);
    margin: 0;
    padding: 0;
    list-style: none;
}

.tiptap-event-block[data-variant="liste"] .tiptap-event-speakers__grid,
.tiptap-event-block[data-variant="liste"] .tiptap-event-sponsors__grid {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* ── Titres de bloc ──────────────────────────────────────────────────────── */

.tiptap-event-block > h3 {
    margin: 0 0 var(--spacing-md);
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: inherit;
}

.tiptap-event-block[data-variant="compact"] > h3 {
    font-size: var(--font-size-base);
}

/* ── Intervenants ────────────────────────────────────────────────────────── */

.tiptap-event-speakers__card {
    padding: var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--ink-on-dark);
}

.tiptap-event-speakers__name {
    margin: 0;
    font-weight: 600;
    color: var(--color-text);
}

.tiptap-event-speakers__name-link {
    color: var(--color-primary);
    text-decoration: none;
}

.tiptap-event-speakers__name-link:hover {
    text-decoration: underline;
}

.tiptap-event-speakers__org {
    margin: var(--spacing-xs) 0 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.tiptap-event-speakers__sessions {
    margin: var(--spacing-sm) 0 0;
    padding: 0;
    list-style: none;
    font-size: var(--font-size-sm);
}

.tiptap-event-speakers__sessions li + li {
    margin-top: var(--spacing-xs);
}

.tiptap-event-speakers__role {
    display: inline-block;
    margin-right: var(--spacing-xs);
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-primary);
}

.tiptap-event-speakers__session {
    color: var(--color-text-light);
}

/* ── Partenaires ─────────────────────────────────────────────────────────── */

.tiptap-event-sponsors__item {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 5rem;
    padding: var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--ink-on-dark);
}

.tiptap-event-sponsors__link {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    text-decoration: none;
}

.tiptap-event-sponsors__logo {
    max-width: 100%;
    max-height: 4rem;
    /* Un mur de logos mélange des formats très hétérogènes : `contain` évite
       qu'un logo panoramique écrase la hauteur de sa ligne. */
    object-fit: contain;
}

/* Les partenaires de premier rang méritent d'être vus comme tels. */
.tiptap-event-sponsors__item[data-level="institutional"],
.tiptap-event-sponsors__item[data-level="platinum"] {
    grid-column: span 2;
    min-height: 7rem;
}

.tiptap-event-sponsors__item[data-level="institutional"] .tiptap-event-sponsors__logo,
.tiptap-event-sponsors__item[data-level="platinum"] .tiptap-event-sponsors__logo {
    max-height: 5.5rem;
}

.tiptap-event-sponsors__name {
    font-weight: 600;
    text-align: center;
    color: var(--color-text);
}

/* ── Programme ───────────────────────────────────────────────────────────── */

.tiptap-event-program__day {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--spacing-xs) var(--spacing-sm);
    margin: var(--spacing-lg) 0 var(--spacing-sm);
    font-size: var(--font-size-base);
    font-weight: 700;
    color: var(--color-primary);
}

.tiptap-event-program__day-date,
.tiptap-event-program__day-theme {
    font-weight: 400;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.tiptap-event-program__session {
    display: grid;
    grid-template-columns: minmax(6rem, max-content) 1fr;
    gap: var(--spacing-xs) var(--spacing-md);
    padding: var(--spacing-sm) 0;
    border-top: 1px solid var(--color-border);
}

@media (width < 40em) {
    .tiptap-event-program__session {
        grid-template-columns: 1fr;
    }
}

.tiptap-event-program__time {
    font-variant-numeric: tabular-nums;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.tiptap-event-program__session-title {
    font-weight: 600;
    color: var(--color-text);
}

.tiptap-event-program__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
    grid-column: 2;
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

@media (width < 40em) {
    .tiptap-event-program__meta,
    .tiptap-event-program__desc {
        grid-column: 1;
    }
}

.tiptap-event-program__track,
.tiptap-event-program__room {
    padding: 0.1rem 0.4rem;
    border-radius: var(--radius-sm);
    background-color: var(--color-bg-light);
}

.tiptap-event-program__desc {
    grid-column: 2;
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* ── États vides ─────────────────────────────────────────────────────────── */

.tiptap-event-speakers__empty,
.tiptap-event-sponsors__empty,
.tiptap-event-program__empty {
    margin: 0;
    font-size: var(--font-size-sm);
    font-style: italic;
    color: var(--color-text-light);
}

/* ── Appel à l'action ────────────────────────────────────────────────────── */

.tiptap-event-cta {
    text-align: center;
}

.tiptap-event-cta__title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: inherit;
}

.tiptap-event-cta__subtitle {
    margin: var(--spacing-xs) 0 0;
    font-size: var(--font-size-sm);
    color: inherit;
    opacity: 0.85;
}

.tiptap-event-cta__action {
    margin: var(--spacing-md) 0 0;
}

.tiptap-event-cta__note {
    margin: var(--spacing-sm) 0 0;
    font-size: var(--font-size-sm);
    font-style: italic;
    color: inherit;
    opacity: 0.85;
}

/* Sur fond accentué, le bouton primaire disparaîtrait dans la couleur de
   marque : on l'inverse. */
.tiptap-event-block[data-bg="accentue"] .tiptap-event-cta__action .btn--primary {
    background-color: var(--ink-on-dark);
    color: var(--color-primary);
}

/* ── Foire aux questions ─────────────────────────────────────────────────── */

.tiptap-event-faq__toc {
    margin: var(--spacing-md) 0 var(--spacing-lg);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-light);
}

.tiptap-event-faq__toc ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--spacing-2xs);
}

.tiptap-event-faq__toc a {
    font-size: var(--font-size-sm);
    color: var(--color-primary);
    text-decoration: none;
}

.tiptap-event-faq__toc a:hover,
.tiptap-event-faq__toc a:focus-visible {
    text-decoration: underline;
}

.tiptap-event-faq__list {
    display: grid;
    gap: var(--spacing-xs);
}

.tiptap-event-faq__item {
    border-bottom: 1px solid var(--color-border);
    padding-bottom: var(--spacing-sm);
}

.tiptap-event-faq__item:last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

/* `list-style: none` seul ne retire pas le triangle sous Safari : il faut
   aussi neutraliser le pseudo-element WebKit. */
.tiptap-event-faq__question {
    list-style: none;
    cursor: pointer;
    padding: var(--spacing-sm) 0;
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--color-text);
}

.tiptap-event-faq__question::-webkit-details-marker {
    display: none;
}

/* Chevron dessine en CSS : il tourne a l'ouverture, sans image ni script. */
.tiptap-event-faq__question::before {
    content: '';
    display: inline-block;
    width: 0.45em;
    height: 0.45em;
    margin-right: var(--spacing-xs);
    border-right: 2px solid var(--color-primary);
    border-bottom: 2px solid var(--color-primary);
    transform: rotate(-45deg) translateY(-0.1em);
    transition: transform 0.15s ease;
}

.tiptap-event-faq__item[open] > .tiptap-event-faq__question::before {
    transform: rotate(45deg) translateY(-0.15em);
}

.tiptap-event-faq__answer {
    padding: 0 0 var(--spacing-sm) 1.1em;
    font-size: var(--font-size-sm);
    line-height: 1.65;
    color: var(--color-text-light);
}

@media (prefers-reduced-motion: reduce) {
    .tiptap-event-faq__question::before {
        transition: none;
    }
}

/* ── Code de conduite ────────────────────────────────────────────────────── */

.minisite-conduct__pledge {
    margin: var(--spacing-lg) 0 0;
    padding: var(--spacing-md) var(--spacing-lg);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-light);
}

.minisite-conduct__pledge-title {
    margin: 0 0 var(--spacing-2xs);
    font-weight: 700;
    color: var(--color-text);
}

.minisite-conduct__pledge p:last-child {
    margin: 0;
    color: var(--color-text-light);
}

.minisite-conduct__report {
    margin: var(--spacing-xl) 0 0;
    padding: var(--spacing-lg);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-light);
}

.minisite-conduct__report-title {
    margin: 0 0 var(--spacing-2xs);
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--color-text);
}

.minisite-conduct__report p {
    margin: 0;
    color: var(--color-text-light);
}

.minisite-conduct__report-channels {
    margin: var(--spacing-md) 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-md);
}

.minisite-conduct__report-channels a {
    font-weight: 600;
    color: var(--color-primary);
}

/* ── Indicateurs d'accès au lieu ─────────────────────────────────────────── */

.access-routes {
    margin: 0 0 var(--spacing-md);
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--spacing-sm);
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.access-routes__item {
    display: flex;
    align-items: flex-start;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-light);
}

.access-routes__icon {
    flex: none;
    display: inline-flex;
    color: var(--color-primary);
}

.access-routes__body {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.access-routes__mode {
    display: block;
    font-size: var(--font-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-light);
}

.access-routes__label {
    font-size: var(--font-size-sm);
    color: var(--color-text);
}

.access-routes__time {
    font-size: var(--font-size-base);
    font-weight: 700;
    color: var(--color-primary);
}

.access-routes__details {
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

/* Sur fond accentué, les jetons doivent rester lisibles sur la couleur de
   marque : on les repose sur un voile clair plutôt que sur le fond de page. */
.tiptap-event-block[data-bg="accentue"] .access-routes__item {
    background-color: var(--veil-on-dark);
}

.tiptap-event-block[data-bg="accentue"] .access-routes__icon,
.tiptap-event-block[data-bg="accentue"] .access-routes__time,
.tiptap-event-block[data-bg="accentue"] .access-routes__label,
.tiptap-event-block[data-bg="accentue"] .access-routes__mode,
.tiptap-event-block[data-bg="accentue"] .access-routes__details {
    color: inherit;
}

/* ── Bloc « Le lieu » ────────────────────────────────────────────────────── */

.tiptap-event-venue__name {
    margin: 0 0 var(--spacing-2xs);
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: inherit;
}

.tiptap-event-venue__address {
    margin: 0 0 var(--spacing-md);
    font-style: normal;
    font-size: var(--font-size-sm);
    color: inherit;
    opacity: 0.85;
}

.tiptap-event-venue__access-text {
    margin: 0 0 var(--spacing-md);
    font-size: var(--font-size-sm);
    color: inherit;
}

.tiptap-event-venue__more {
    margin: 0;
}

.tiptap-event-venue__more a {
    font-weight: 600;
    color: var(--color-primary);
}

.tiptap-event-block[data-bg="accentue"] .tiptap-event-venue__more a {
    color: inherit;
    text-decoration: underline;
}

/* ── Pied de page du mini-site ───────────────────────────────────────────── */

/* Le pied de page porte EXACTEMENT le meme fond que la tete et le contenu :
   meme degrade, meme trace, meme ancrage a la fenetre. Il est donc joint a la
   regle groupee plus haut, et n'a plus de fond a lui.

   Un premier essai l'avait differencie — dessin retourne sur les deux axes et
   voile sombre — au motif qu'un pied de page ne doit pas rivaliser avec la
   tete. A l'ecran, le resultat etait l'inverse de l'intention : le changement
   de teinte et d'orientation dessinait une COUTURE horizontale nette a
   l'endroit precis ou l'on voulait une continuite. Une matiere commune ne se
   decline pas, sinon ce n'est plus la meme matiere.

   Aucune marge haute non plus : elle laissait passer le blanc du `body`. La
   respiration est portee par la marge basse du `main`. */
/* La couleur d'encre est declaree AVEC le fond, plus haut dans cette feuille.
   Elle etait redeclaree ici, a 7 500 lignes de la : a specificite egale c'est
   l'ordre qui tranche, donc cette seconde declaration gagnait, et repeindre le
   pied en clair en amont n'avait aucun effet visible. Deux declarations de la
   meme propriete sur le meme selecteur dans une feuille de 9 000 lignes ne se
   voient pas a la relecture — seule la valeur CALCULEE le dit. */
.minisite-footer {
    /* volontairement vide : cf. la declaration groupee avec le fond */
}

/* Le filet borne au conteneur a ete retire : il existait parce que le pied
   partageait son fond avec la page, et qu'il fallait marquer la coupure sans
   trancher le degrade. Le pied ayant desormais son propre filet pleine
   largeur (ci-dessus), les deux se seraient superposes a huit pixels d'ecart. */

.minisite-footer__grid {
    display: grid;
    gap: var(--spacing-xl);
    padding: var(--spacing-2xl) 0;
    grid-template-columns: 1fr;
}

@media (min-width: 48em) {
    .minisite-footer__grid {
        /* Quatre colonnes possibles ; celles qui n'ont rien à dire ne sont
           pas rendues, la grille se resserre d'elle-même. */
        grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    }

}

.minisite-footer__title {
    margin: 0 0 var(--spacing-xs);
    font-size: var(--font-size-lg);
    font-weight: 700;
}

.minisite-footer__meta {
    margin: 0 0 var(--spacing-md);
    font-size: var(--font-size-sm);
    line-height: 1.6;
    color: var(--color-text-light);
}

/* Le bouton d'inscription a ete ajoute entre les dates et ce lien de retour :
   sans marge, les deux se touchaient. La marge est portee par le BOUTON, pas
   par le lien, pour que le pied de page garde la meme allure quand les
   inscriptions sont fermees et que le bouton n'est pas rendu. */
.minisite-footer__cta {
    margin-block: var(--spacing-lg) var(--spacing-md);
}

.minisite-footer__back {
    margin: 0;
}

/* Nom de l'organisateur, en tete de la colonne « Organisation ». Plein blanc
   et en gras : c'est une identite, pas une coordonnee de plus. */
.minisite-footer__organizer {
    margin: 0 0 var(--spacing-sm);
    font-weight: 700;
    font-size: var(--font-size-sm);
    color: var(--color-text);
}

.minisite-footer__back a {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2xs);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-primary);
    text-decoration: none;
}

.minisite-footer__back a:hover,
.minisite-footer__back a:focus-visible {
    text-decoration: underline;
}

.minisite-footer__heading {
    margin: 0 0 var(--spacing-sm);
    font-size: var(--font-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-light);
}

.minisite-footer__nav ul,
.minisite-footer__editions ul,
.minisite-footer__contact ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--spacing-2xs);
}

.minisite-footer__nav a,
.minisite-footer__editions a,
.minisite-footer__contact a {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2xs);
    font-size: var(--font-size-sm);
    color: var(--color-text);
    text-decoration: none;
}

.minisite-footer__nav a:hover,
.minisite-footer__nav a:focus-visible,
.minisite-footer__editions a:hover,
.minisite-footer__editions a:focus-visible,
.minisite-footer__contact a:hover,
.minisite-footer__contact a:focus-visible {
    color: var(--color-primary);
    text-decoration: underline;
}

/* L'édition en cours se distingue des archives : c'est le seul lien de la
   colonne qui mène vers l'avant. */
.minisite-footer__edition--latest {
    font-weight: 700;
    color: var(--color-primary);
}

/* Grille explicite plutôt que flex + espace blanc : dans un conteneur flex,
   le nœud de texte blanc entre l'année et le titre est SUPPRIMÉ, et rien ne
   les sépare plus si le `gap` fait défaut. C'est ce qui donnait
   « 2017Oser pour enseigner ». Deux colonnes alignent en prime les années
   entre elles. */
/* Sélecteur volontairement redondant (`a.classe`) : la règle partagée avec la
   navigation et les contacts est `.minisite-footer__editions a`, plus
   spécifique qu'une classe seule. Écrite en classe seule, cette règle était
   perdante et le `display: inline-flex` partagé continuait de s'appliquer —
   la grille n'avait alors aucun effet, seul le maigre `gap` restait, d'où
   l'année collée au titre.
   Le lien « plus récente » n'a PAS cette classe : c'est un seul nœud de texte,
   qui dans une colonne de 2,75 rem se casserait à chaque mot. */
.minisite-footer__editions a.minisite-footer__edition {
    display: grid;
    grid-template-columns: 2.75rem 1fr;
    gap: var(--spacing-sm);
    align-items: baseline;
}

.minisite-footer__edition-year {
    font-variant-numeric: tabular-nums;
    opacity: 0.7;
}

/* Aucun filet entre le pied de page et sa barre legale : meme raison qu'entre
   le bandeau et les onglets, un trait redecoupe en deux ce que le fond commun
   vient de reunir. La hierarchie se fait par la taille du texte et l'espace,
   pas par une ligne. */
.minisite-footer__legal {
    padding-top: var(--spacing-xs);
}

.minisite-footer__legal .container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm) var(--spacing-lg);
    padding-top: var(--spacing-md);
    padding-bottom: var(--spacing-md);
}

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

/* Le menu CMS `footer-legal` rend sa propre liste de liens : la mise en
   ligne vaut donc pour nos ancres comme pour les siennes. */
.minisite-footer__legal-links,
.minisite-footer__legal-links ul {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs) var(--spacing-lg);
    margin: 0;
    padding: 0;
    list-style: none;
}

.minisite-footer__legal-links a {
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
    text-decoration: none;
}

.minisite-footer__legal-links a:hover,
.minisite-footer__legal-links a:focus-visible {
    color: var(--color-primary);
    text-decoration: underline;
}

/* ── Cibles tactiles du chassis minisite ─────────────────────────────────────
   La maquette « Vues mobiles » pose une seule regle chiffree, et c'est la
   seule qu'elle repete a chaque ecran : « cibles de 44 px ». Le depot la
   nomme depuis longtemps — `--touch-target-min`, dans `root.css` — et
   l'applique deja au bandeau du site, au mega-menu, aux panneaux et aux
   curseurs de plage. Le CHASSIS DU MINISITE etait le seul a l'avoir manquee.

   Mesure du 2026-08-29 a 390 px, sur les huit pages des deux editions
   servies : 22 a 33 cibles sous 44 px par page, et TOUJOURS les memes —
   liens du pied (21,7 px), annees d'edition (21,7), barre legale (18),
   retour et marque du bandeau (21,7), commandes de partage (28) et leurs
   entrees de menu (37,7), bouton d'inscription des onglets (41,7). Ce ne
   sont pas des cas isoles d'une page : c'est le chassis, donc les huit.

   Ce qui N'EST PAS repris ici, et c'est deliberé : les liens EN LIGNE dans
   une phrase (`.cms-mention`, `.evt-link` d'un paragraphe, le lien mineur du
   hero). WCAG les exempte, et pour une bonne raison — leur hauteur est celle
   de la ligne de texte ; l'etirer creverait l'interligne du paragraphe qui
   les contient. Une cible se dimensionne quand elle est un ELEMENT de
   navigation, pas quand elle est un mot.

   Bornee au telephone : au-dela, la souris vise, et 44 px de hauteur sur une
   colonne de liens de pied de page l'aereraient sans rien apporter. */
@media (width < 48em) {
    .minisite-footer__nav a,
    .minisite-footer__editions a,
    .minisite-footer__contact a,
    .minisite-footer__back a,
    .minisite-footer__legal-links a {
        min-height: var(--touch-target-min);
    }

    /* `min-height` NE S'APPLIQUE PAS a un element en ligne, et la barre
       legale est la seule des cinq listes dont les liens le sont restes : les
       quatre autres portent deja `display: inline-flex`. La regle ci-dessus
       les a donc tous agrandis SAUF ceux-la, sans rien signaler — mesure
       apres coup : 18 px inchanges pour « Mentions legales »,
       « Confidentialite » et « Politique cookies ». Le mode de panne est
       celui du repli : la declaration est acceptee, elle ne fait rien. */
    .minisite-footer__legal-links a {
        display: inline-flex;
        align-items: center;
    }

    /* L'annee et le titre d'une edition sont deux colonnes alignees sur leur
       ligne de base (`align-items: baseline`, plus haut). Une hauteur
       minimale ne recentre pas cet alignement : sans cette ligne, un titre
       d'une seule ligne collerait au haut de sa cible de 44 px. */
    .minisite-footer__editions a.minisite-footer__edition {
        align-content: center;
    }

    /* Le bandeau du haut fait 3 rem : une cible de 2,75 rem y tient sans le
       faire grandir. C'est pourquoi la regle porte sur `min-height` et non
       sur `height` — un `height` fixe aurait pousse la barre a 44 px de
       contenu plus ses marges. */
    .minisite-header__back,
    .minisite-header__brand,
    .minisite-header__actions .share-dropdown__summary,
    .minisite-header__actions .share-dropdown-group__btn,
    .minisite-header__actions .share-dropdown__item {
        min-height: var(--touch-target-min);
    }

    .minisite-nav__cta {
        min-height: var(--touch-target-min);
    }
}

/* ── Programme en liste ──────────────────────────────────────────────────── */

.programme-list {
    display: grid;
    gap: var(--spacing-md);
    margin-top: var(--spacing-lg);
}

/* ── Chapitrage d'une rediffusion ────────────────────────────────────────── */

.replay-chapters {
    margin-top: var(--spacing-md);
    padding: var(--spacing-md);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-light);
}

.replay-chapters__title {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    margin: 0 0 var(--spacing-sm);
    font-size: var(--font-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-light);
}

.replay-chapters__list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--spacing-2xs);
}

.replay-chapters__link {
    display: grid;
    grid-template-columns: 3.5rem 1fr;
    gap: var(--spacing-sm);
    width: 100%;
    padding: 0.25rem 0.4rem;
    border: 0;
    border-radius: var(--radius-sm, 0.25rem);
    background: none;
    text-align: left;
    font-size: var(--font-size-sm);
    color: var(--color-text);
    /* Curseur de LECTURE tant que la vidéo n'est pas chargée : le sommaire
       reste informatif, mais rien ne suggère qu'un clic agirait. */
    cursor: default;
}

.replay-chapters__time {
    font-variant-numeric: tabular-nums;
    color: var(--color-text-light);
}

/* Le marqueur est posé par app.js au chargement de l'iframe : jusque-là,
   aucun survol, aucun pointeur, aucune promesse. */
.replay-chapters--seekable .replay-chapters__link {
    cursor: pointer;
}

.replay-chapters--seekable .replay-chapters__link:hover,
.replay-chapters--seekable .replay-chapters__link:focus-visible {
    background-color: var(--color-primary-light);
}

.replay-chapters--seekable .replay-chapters__link:hover .replay-chapters__time,
.replay-chapters--seekable .replay-chapters__link:focus-visible .replay-chapters__time {
    color: var(--color-primary);
}

/* ── Filtres de la grille des rediffusions ───────────────────────────────
   La rangée, ses métriques et l'alignement des contrôles viennent de
   `components/filters-row.css` : rien de local ici, c'est précisément ce qui
   faisait diverger chaque page filtrée de la précédente. */

/* Chapô d'une page de minisite : sous le titre, avant les commandes. Posé sur
   la classe générique plutôt que sur celle des rediffusions — toute page du
   minisite peut avoir deux phrases à dire, aucune n'a à les restyler. */
.minisite-content__lede {
    max-width: 46rem;
    margin: 0 0 var(--spacing-lg);
    font-size: var(--font-size-sm);
    line-height: 1.65;
    color: var(--color-text-light);
}

/* ── En-tete borne quand la fiche n'a PAS de rail ──
   Le layout partage borne sa colonne a 62 rem des lors qu'il n'y a ni panneau
   lateral ni sommaire (regle de `article.css`). Sans quoi le titre demarre
   112 px a gauche du premier mot du texte, et la page a deux bords gauches.

   La condition NE PEUT PAS s'ecrire en CSS : `:has()` est interdit a
   l'interieur d'un autre `:has()`, y compris via `:not()` — le selecteur
   entier est alors rejete, en silence. Elle est donc calculee dans le gabarit
   (`_has_rail`), qui sait aussi si le corps porte des titres de niveau 2. */
.content-header--narrow.content-header--event > .container > .content-header__body,
.content-header--narrow.content-header--event > .container > .content-header__lead {
    max-width: 62rem;
    margin-inline: auto;
}

/* ── L'affiche de l'evenement, entiere ──
   La couverture partagee recadre en 16/7 (`object-fit: cover`), ce qui convient
   a une photo d'illustration. Une AFFICHE, elle, porte un texte compose :
   recadree, elle perd son titre ou ses dates. C'est la regle de la maquette au
   composant 46 — « affiche de l'edition, fond blanc, jamais recadree ».

   ELLE PREND SA PROPRE LARGEUR, et non 100 % de la colonne. En pleine largeur
   avec `contain`, une affiche de ratio 1,78 dans une boite de 2,38 laissait
   25 % de bandes LATERALES peintes en gris — un cadre, la ou la maquette
   demande du blanc. A sa largeur, il n'y a plus de bandes du tout, donc plus de
   fond a peindre.

   VINGT REM ET NON VINGT-SIX. Mesure du 2026-08-29 sur `/evenements/2026-webinaire` :
   l'en-tete faisait 728 px, dont 416 pour la seule affiche, avant le premier mot
   du texte. Une fiche d'evenement simple porte quatre paragraphes et ses
   rediffusions ; leur faire franchir un tiers d'ecran d'illustration coute plus
   que l'illustration ne rapporte. */
.content-header--event .content-header__cover-image {
    aspect-ratio: auto;
    width: auto;
    max-width: 100%;
    max-height: 20rem;
    margin-inline: auto;
    object-fit: contain;
}

/* ── Edition terminee : le constat, puis les portes de sortie ──
   Bandeau sobre (pas d'alerte : une edition passee n'est pas un incident),
   suivi de la brique partagee `link-cards`. */
.minisite-past {
    margin-bottom: var(--spacing-xl);
    padding: var(--spacing-md) var(--spacing-lg);
    border-radius: var(--radius-lg);
    background: var(--color-bg-light);
}

.minisite-past__title {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin: 0 0 var(--spacing-2xs);
    font-size: var(--font-size-sm);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-navy);
}

.minisite-past__title svg {
    flex-shrink: 0;
    color: var(--color-text-light);
}

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

/* ── Identite du site porteur dans la barre du minisite ──
   Un minisite atteint par un partage ou par la recherche ne disait pas de
   quel site il relevait : la barre du haut proposait « Voir tous les
   evenements », ce qui suppose de savoir ou l'on est. Le nom du site est
   pose devant, avec un filet de separation. */
.minisite-header__left {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    min-width: 0;
}

.minisite-header__brand {
    flex-shrink: 0;
    padding-right: var(--spacing-sm);
    border-right: 1px solid var(--color-border);
    font-size: var(--font-size-sm);
    font-weight: 800;
    letter-spacing: 0.06em;
    color: var(--color-text);
    text-decoration: none;
}

.minisite-header__brand:hover {
    color: var(--color-primary);
}

/* Marqueur « rediffusion disponible ».

   Une PASTILLE NOMMEE, posee sur sa propre ligne en fin de carte. C'etait un
   pictogramme nu accole au titre : au retour a la ligne il se detachait du
   dernier mot et se retrouvait SEUL sur une ligne, un rond vert orphelin sous
   un titre, dont le sens n'etait lisible qu'au survol. Le libelle est visible
   parce que c'etait exactement la question posee (« on ne sait pas si on peut
   revoir »).

   `width: fit-content` : sans lui, un element de bloc dans une carte s'etire
   sur toute la largeur et la pastille devient une bande. */
.programme__session-filmed {
    display: inline-flex;
    width: fit-content;
    align-items: center;
    gap: 0.375rem;
    margin: 0.5rem 0 0;
    padding: 0.1875rem 0.5rem;
    border: 1px solid var(--evt-rule);
    border-radius: 999px;
    background: var(--evt-tint);
    color: var(--color-primary);
    font-size: var(--font-size-xs);
    font-weight: 600;
    line-height: 1.3;
}

.programme__session-filmed svg {
    flex-shrink: 0;
}

/* Libelle de retour : le long au-dessus de 40 em, le court en dessous.
   Les deux vivent dans le DOM, le CSS choisit — c'est ce qui remplace le
   couple d'utilitaires `hidden sm:inline` / `sm:hidden`, dernier palier
   Tailwind du site public et seul seuil du depot exprime en `rem`. */
.minisite-header__back-long { display: none; }
.minisite-header__back-short { display: inline; }

@media (min-width: 40em) {
    .minisite-header__back-long { display: inline; }
    .minisite-header__back-short { display: none; }
}

/* ══ MUR D'INTERVENANTS ═══════════════════════════════════════════════════════
   Maquette « Intervenants evenement ANCESU ». La page rendait le trombinoscope
   rond de l'annuaire (`bio-people`) ; la carte 3/4 porte en plus le ROLE et le
   nombre d'interventions, c'est-a-dire ce qui distingue un intervenant d'une
   personne de l'annuaire.

   Le 3/4 n'est pas un troisieme format arbitraire : c'est le cadrage d'un
   portrait. Le rond de l'annuaire cadre sur le visage, la carte partagee du
   site est batie sur du 16/9 ou un visage est mutile (cf.
   `rules/capabilities/design-system.md`). Aucun des deux ne convenait ici. */

/* ── LA RANGEE DE COMMANDES, UNE SEULE FOIS ────────────────────────
   « Un compteur a gauche, des commandes a droite, le tout dans une carte » est
   le meme objet sur le mur d'intervenants et sur la videotheque, et la
   maquette le dessine pareil aux deux endroits. Il avait ete ecrit deux fois,
   a deux jours d'intervalle dans la meme feuille — c'est exactement la
   divergence que cette refonte est en train de resorber ailleurs, recreee au
   passage.

   Les deux pages posent donc `evt-toolbar`. Celle des rediffusions la cumule
   avec `filters-row`, qui lui apporte la mise en page de sa rangee de
   facettes ; c'est pour cela que la carte ne declare que son CADRE et son
   ecart, et laisse la disposition a qui l'emploie. */
.evt-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1.25rem;
    margin-bottom: var(--spacing-lg);
    padding: 0.875rem 1.125rem;
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius-lg);
}

.evt-speakers__count {
    flex: none;
    margin: 0;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-light);
}

/* `margin-left: auto` et non `space-between` : quand le compteur est seul —
   un evenement sans role multiple, donc sans pastilles — `space-between` le
   laisserait au depart, ce qui est le comportement voulu ; mais des qu'un seul
   groupe de commandes existe, c'est LUI qu'on veut a droite, pas un vide
   reparti entre les deux. */
.evt-speakers__controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.625rem 1rem;
    margin-left: auto;
    min-width: 0;
}

.evt-speakers__pills {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem;
    min-width: 0;
}

.evt-speakers__pills-label {
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

/* Les regles `.evt-pill*` ont ete retirees le 2026-08-31 : les pastilles de
   filtre du mur d'intervenants sont passees sur `ui.chip`, la brique du site,
   qui portait deja les deux etats actifs qu'elles refaisaient. Je les avais
   ecrites la veille — c'est la divergence que ce lot resorbe, recreee au
   passage. */

.evt-speakers__clear {
    font-size: var(--font-size-sm);
    color: var(--color-primary);
}

/* ── Un groupe : etiquette, compte, filet qui court jusqu'au bord ── */
.evt-speakers__group + .evt-speakers__group {
    margin-top: var(--spacing-xl);
}

.evt-speakers__group-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.875rem;
}

.evt-speakers__group-label {
    display: grid;
    place-items: center;
    flex: none;
    min-width: 2.125rem;
    height: 2.125rem;
    padding-inline: 0.5rem;
    border-radius: var(--evt-radius);
    background: var(--evt-surface-muted);
    color: var(--color-primary);
    font-size: var(--font-size-lg);
    font-weight: 700;
}

/* Groupe par ROLE : l'etiquette porte un libelle, pas une lettre. Pastille
   teintee de la couleur de rubrique plutot que carre a chiffre. */
.evt-speakers__group-label--role {
    height: 1.875rem;
    border-radius: var(--radius-pill);
    background: var(--color-section-colloques-light);
    color: var(--evt-cta);
    font-size: var(--font-size-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.evt-speakers__group-count {
    flex: none;
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.evt-speakers__group-rule {
    flex: 1;
    height: 1px;
    background: var(--evt-rule);
}

/* `auto-fill` et non `auto-fit` : sur un groupe d'une seule personne, `auto-fit`
   etire la carte unique sur toute la largeur de la colonne — un portrait 3/4 de
   700 px de large. `auto-fill` garde les pistes vides et la carte sa taille. */
.evt-speakers__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
    gap: var(--spacing-md);
}

.evt-speaker {
    position: relative;
    display: block;
    aspect-ratio: 3 / 4;
    overflow: hidden;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    text-decoration: none;
    transition: box-shadow var(--transition-fast), border-color var(--transition-fast);
}

a.evt-speaker:hover,
a.evt-speaker:focus-visible {
    border-color: var(--evt-cta);
    box-shadow: 0 18px 40px -28px var(--evt-lift-strong);
}

.evt-speaker__photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Le voile n'existe QUE sur la variante a photo : c'est lui qui rend le blanc
   lisible en assombrissant le bas de l'image. Pose sur le hachure, il n'aurait
   rien a assombrir. */
.evt-speaker--photo::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--scrim-bottom);
}

.evt-speaker__badges {
    position: absolute;
    left: 0.625rem;
    top: 0.625rem;
    right: 0.625rem;
    z-index: 2;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.evt-speaker__badge {
    display: inline-flex;
    align-items: center;
    height: 1.375rem;
    padding-inline: 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--evt-cta);
    color: var(--ink-on-dark);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.evt-speaker__body {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    display: flex;
    flex-direction: column;
    gap: 0.1875rem;
    padding: 0.875rem;
}

.evt-speaker__name {
    font-family: var(--font-title, inherit);
    font-size: var(--font-size-base);
    font-weight: 700;
    line-height: 1.2;
}

.evt-speaker__org,
.evt-speaker__sessions {
    font-size: var(--font-size-xs);
    line-height: 1.35;
}

.evt-speaker__sessions {
    padding-top: 0.125rem;
    font-variant-numeric: tabular-nums;
}

/* ── Les deux encres, et pourquoi il en faut deux ──
   Sur photo, le texte est blanc et repose sur le voile. Sans photo, il n'y a
   pas de voile : le meme blanc rendrait 1,3:1 sur le hachure clair. La variante
   « sans portrait » ecrit donc en encre sombre. Ce n'est pas un repli
   cosmetique, c'est le cas ORDINAIRE — un intervenant sur quatre porte une
   photo (mesure du 2026-08-30). */
.evt-speaker--photo .evt-speaker__name {
    color: var(--ink-on-dark);
}

.evt-speaker--photo .evt-speaker__org,
.evt-speaker--photo .evt-speaker__sessions {
    color: var(--ink-on-dark-soft);
}

.evt-speaker--blank .evt-speaker__name {
    color: var(--evt-ink);
}

.evt-speaker--blank .evt-speaker__org,
.evt-speaker--blank .evt-speaker__sessions {
    color: var(--color-text-light);
}

/* Le badge de role, lui, reste sur aplat rouge dans les deux cas : c'est une
   pastille pleine, son contraste ne depend pas du fond de la carte. */

.evt-speakers__empty {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    padding: clamp(1.5rem, 4vw, 2.25rem);
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius-lg);
}

.evt-speakers__empty-title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--evt-ink);
}

.evt-speakers__empty-hint {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
    max-width: 52ch;
}

/* LA VIDEOTHEQUE DE L'EVENEMENT A QUITTE CETTE FEUILLE.
   Les douze regles `.evt-replays__*` dessinaient l'intitule de groupe et le
   rebond de fin de la page « Rediffusions ». L'intitule de groupe est devenu
   `_group_head`, partage avec le mur d'intervenants qui dessinait le meme
   objet de son cote ; le rebond de fin est passe sur `_link_cards`, la brique
   des portes de sortie. Les deux vivent dans `event-minisite.css`, la feuille
   `@grammaire v2` de la coquille. La grille de vignettes, elle, reste ici
   (`.replay-tiles`) : ses DEUX appelants la partagent, dont la fiche
   d'evenement simple, qui n'a pas migre. */

/* ── En-tete marine de la carte de coordonnees ──
   Seul aplat marine de la page, et c'est ce qui lui donne sa valeur : la
   maquette le reserve a UN element par ecran. Il nomme la session parente, qui
   occupait auparavant la premiere ligne de la page pour dire le nom d'un
   contenant.

   `:has()` plutot qu'une classe de plus sur la carte : c'est la PRESENCE de
   l'en-tete qui commande le retrait du rembourrage, et une carte sans en-tete
   ne doit rien changer a son rendu. Sans cela il faudrait poser une seconde
   classe dans le gabarit, que l'on oublierait au prochain appelant. */
.evt-facts:has(> .evt-facts__head) {
    padding: 0;
    overflow: hidden;
}

.evt-facts:has(> .evt-facts__head) > .evt-def {
    padding-inline: clamp(1.375rem, 3vw, 1.875rem);
}

.evt-facts:has(> .evt-facts__head) > .evt-def:last-child {
    padding-bottom: clamp(1.375rem, 3vw, 1.875rem);
}

.evt-facts__head {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1.125rem clamp(1.375rem, 3vw, 1.875rem);
    background: var(--evt-ink);
}

.evt-facts__head-eyebrow {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--font-size-xs);
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    /* Sur l'aplat marine, le gris de texte secondaire tombe sous le seuil :
       cette valeur eclaircie rend 5,4:1 sur `--color-primary-dark`. */
    color: var(--evt-ink-on-navy-soft);
}

.evt-facts__head-rule {
    flex: none;
    width: 1.25rem;
    height: 0.25rem;
    border-radius: var(--radius-pill);
    background: var(--evt-cta);
}

.evt-facts__head-title {
    font-family: var(--font-title, inherit);
    font-size: var(--font-size-lg);
    font-weight: 700;
    line-height: 1.25;
    color: var(--ink-on-dark);
}

/* ══ LE BOUTON DU SITE, TEINTE PAR LA RUBRIQUE ════════════════════════════════
   Les douze boutons du minisite sont passes sur `ui.button` (`.btn`), la brique
   du site. Elle rend le bleu de marque ; le minisite, lui, appelle a l'action
   en ROUGE — c'est la couleur de la rubrique « colloques », celle de la
   pastille de la barre d'evenement et des filets d'onglets, et celle que pose
   la maquette.

   La reponse n'est PAS une variante de plus dans la brique partagee : le site
   pose deja `--section-color` sur le corps de chaque page
   (`body.section--colloques`), et ce jeton existe precisement pour teinter un
   composant selon la rubrique qui l'accueille. Une variante `--colloques` dans
   `button.css` aurait fige dans la brique une information que le contexte
   porte deja, et il en aurait fallu une par rubrique.

   Le repli sur `--color-primary` n'est pas decoratif : `--section-color` est
   pose par une classe de rubrique, et un minisite servi sans elle rendrait
   sinon un bouton sans fond. */
/* ── LE ROUGE DE RUBRIQUE NE REPEINT PLUS TOUS LES BOUTONS ──

   Ces deux regles peignaient CHAQUE bouton du minisite avec `--section-color`,
   soit le rouge des colloques : l'aplat des boutons primaires, le contour des
   secondaires. Releve du 2026-09-02 sur l'accueil d'Angers — onze boutons, DIX
   en rouge, dont « Ajouter à mon agenda », « Déposer une proposition »,
   « Adhérer » et « Se connecter ».

   Le raisonnement d'origine se defend (« un contour bleu a cote d'un aplat
   rouge se lit comme deux familles d'actions »), et il a un defaut : il suppose
   qu'il n'y a qu'une famille. Il y en a deux — le geste que la page prepare, et
   tout le reste. Une couleur d'alerte employee en couleur de surface cesse
   d'alerter.

   Le rouge est desormais porte par la seule `.event-banner__cta`, dans
   `zones/event-minisite.css`, ce que la maquette prescrit : « S'INSCRIRE » y
   est le seul aplat rouge, et « Déposer une proposition » y est bleu.

   Les boutons du minisite reprennent donc la teinte du site : `--color-primary`
   pour l'aplat, le meme pour le contour. */

/* ══ CHASSIS MOBILE DU MINISITE ═══════════════════════════════════════════════
   Releve du 2026-08-31 sur iPhone SE (375 x 667), et il a demande de CHANGER DE
   REFERENTIEL pour le voir : les trois defauts ci-dessous ne faisaient pas
   deborder la PAGE — ils etaient rognes DANS leur conteneur. Une sonde qui ne
   regarde que `document.scrollWidth` declarait le minisite sain a 390 px, et
   elle l'a fait pendant deux jours.

       conteneur                        contenu / piste     debordement
       .minisite-header__left            296 / 202          visible (chevauche)
       .minisite-nav__list               471 / 373          rogne (defile)

   Le geste : mesurer `e.scrollWidth > e.clientWidth` sur TOUS les elements. */

/* ── LE MENU DE NAVIGATION MOBILE ──
   Le declencheur n'existe qu'en dessous du palier ou les onglets tiennent. */
.minisite-nav__toggle {
    display: none;
    align-items: center;
    gap: var(--spacing-sm);
    width: 100%;
    min-height: var(--touch-target-min);
    padding: 0 var(--spacing-md);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
    background: var(--evt-surface);
    color: var(--evt-ink);
    font-family: var(--font-title);
    font-size: var(--font-size-base);
    font-weight: 700;
    cursor: pointer;
}

/* Les DEUX etats sont rendus, le CSS choisit — meme motif que le bouton de
   menu du site. Un libelle bascule par le script serait du texte francais dans
   une expression, ce que le build CSP d'Alpine ne pardonne pas. */
.minisite-nav__toggle-icon--close,
.minisite-nav__toggle-label--close {
    display: none;
}

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

.minisite-nav__toggle[aria-expanded='true'] .minisite-nav__toggle-icon--close {
    display: inline-flex;
}

.minisite-nav__toggle[aria-expanded='true'] .minisite-nav__toggle-label--close {
    display: block;
}

.minisite-nav__toggle-icon {
    display: inline-flex;
    flex: none;
}

.minisite-nav__toggle-label {
    flex: 1;
    min-width: 0;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

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

    /* La liste cesse de DEFILER pour se DEPLIER. Le defilement horizontal
       coupait le dernier onglet en plein mot, sans scrollbar pour le dire :
       un contenu inaccessible qui a l'air d'un defaut de rendu. */
    .minisite-nav__list {
        display: none;
        flex-direction: column;
        flex-wrap: nowrap;
        overflow-x: visible;
        white-space: normal;
        margin-top: var(--spacing-sm);
        border-top: 1px solid var(--evt-rule);
    }

    /* MEME SELECTEUR que la regle de bureau, et ce n'est pas du style : celle-ci
       pose `flex: 0 1 auto; margin-left: auto` pour pousser les onglets contre
       le bouton d'inscription, et elle vaut (0,3,0) quand `.minisite-nav__list`
       seul vaut (0,1,0). `@media` n'ajoute AUCUNE specificite : la regle de
       bureau gagnait donc aussi sur telephone, et le menu deplie rendait une
       colonne de 114 px collee a 260 px du bord gauche. Quatrieme collision de
       specificite de cette feuille, toujours sur le meme axe. */
    .minisite-nav__card > .minisite-nav__list {
        flex: 1 1 100%;
        margin-left: 0;
    }

    /* Le frere qui SUIT le declencheur ouvert : `:has()` eviterait le
       selecteur d'adjacence, mais celui-ci suffit et ne coute aucun
       recalcul de sous-arbre. */
    /* L'ETAT VIENT DU MODULE PARTAGE. `mountNavigation` pose
       `navbar--sheet-open` sur le `<nav>` et bascule `aria-expanded` sur le
       declencheur ; on lit le second, qui est le contrat public du bouton et
       ne suppose rien du nom de classe interne du module. */
    .minisite-nav__toggle[aria-expanded='true'] + .minisite-nav__list {
        display: flex;
    }

    .minisite-nav__item {
        width: 100%;
    }

    /* Cible tactile pleine largeur, et le filet de l'onglet actif passe A
       GAUCHE : couche, il soulignerait toute la ligne et se lirait comme un
       separateur de plus. */
    .minisite-nav__list > .minisite-nav__item > .minisite-nav__link {
        justify-content: flex-start;
        width: 100%;
        min-height: var(--touch-target-min);
        padding-inline: var(--spacing-md);
    }

    .minisite-nav__link::after {
        top: 0.5rem;
        bottom: 0.5rem;
        left: 0;
        right: auto;
        width: 3px;
        height: auto;
        border-radius: var(--radius-pill);
    }
}

/* ── LES COMMANDES DE LA LIGNE DE SERVICE ──
   Elles etaient ramenees a 28 px sur telephone — sous les 44 px que la charte
   impose, et que le reste du site tient. Un bouton de 28 px se rate au pouce,
   et c'est precisement sur telephone qu'on vise mal. */
@media (width < 48em) {
    .minisite-header__share .share-dropdown-group__btn,
    .minisite-header__actions .list-hero__share-buttons .share-buttons__btn {
        width: var(--touch-target-min);
        min-height: var(--touch-target-min);
    }

    /* La marque se raccourcit — « Retour au site de l'ANCESU » et « Tous les
       evenements » demandaient 296 px dans une ligne qui en offre 202. */
    .minisite-header__brand-long {
        display: none;
    }

    /* ET LA LIGNE PASSE A LA LIGNE. Raccourcir les libelles ne suffit pas : a
       320 px, « ANCESU » et « Evenements » demandent encore 166 px pour 131
       disponibles, et ces deux mots ne peuvent pas etre plus courts. La hauteur
       imposee de 3 rem empechait le repli de se voir — c'est elle qui faisait
       passer la marque SOUS les commandes de partage au lieu de la renvoyer
       dessous.

       Mesure du 2026-08-31 : 320 px etait la seule largeur encore fautive apres
       le raccourcissement, sur les huit pages du minisite. */
    .minisite-header__bar-inner {
        flex-wrap: wrap;
        height: auto;
        row-gap: var(--spacing-2xs);
        padding-block: var(--spacing-2xs);
    }
}

.minisite-header__brand-short {
    display: none;
}

@media (width < 48em) {
    .minisite-header__brand-short {
        display: inline;
    }
}

/* ── LA BANNIERE D'ECHEANCE, SUR TELEPHONE ──
   Relevee sur la capture du 2026-08-31 : a 375 px elle occupait un bloc de deux
   lignes sous la barre, pastille sur la premiere et phrase sur la seconde, avec
   le rembourrage d'une carte de bureau. Elle annonce pourtant UNE echeance —
   c'est une ligne d'information, pas une section.

   Elle reste une carte (le plateau ne porte que des cartes), mais elle se
   resserre : rembourrage reduit, pastille et texte sur le meme flux, corps
   ramene a l'echelle d'une mention. */
@media (width < 48em) {
    .minisite-deadline > .container {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 0.375rem 0.5rem;
        padding-block: 0.5rem;
    }

    .minisite-deadline__tag {
        /* La pastille descend d'un cran : a 375 px, « TARIF PREFERENTIEL » en
           corps de bureau prenait a lui seul la moitie de la largeur. */
        font-size: 0.625rem;
        padding-inline: 0.5rem;
    }

    .minisite-deadline__text {
        flex: 1 1 100%;
        font-size: var(--font-size-xs);
        line-height: 1.45;
    }
}

/* ── INFOS PRATIQUES SUR L'ACCUEIL ──
   Maquette `Minisite evenement ANCESU`, section « Sur place ». Elle pose ces
   cartes sur un VOILE (`rgba(255,255,255,.62)`) et non sur une carte pleine :
   c'est du rappel, pas du contenu de premier rang, et `--surface-3` porte
   exactement ce role dans la charte — « rappel de contexte, sans bordure ».

   `auto-fit` avec une piste de 15 rem : une seule carte renseignee occupe
   toute la largeur plutot que de laisser deux tiers de vide, trois se rangent
   en rangee. Sur les deux editions servies, une seule l'est — c'est le cas
   ordinaire, pas l'exception. */
.evt-practical {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: var(--card-gap);
}

.evt-practical__card {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    padding: var(--spacing-lg);
    background: var(--evt-surface-veil);
    border-radius: var(--evt-radius);
}

.evt-practical__text {
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: 1.65;
    color: var(--color-text);
    text-wrap: pretty;
}

.evt-practical__text > :last-child {
    margin-bottom: 0;
}

/* ── LES JALONS D'ECHEANCE ──
   Maquette `Minisite evenement ANCESU`, carte « Tarifs et echeances ». Le prix
   seul ne dit pas quand il change : la frise le dit.

   La puce PLEINE marque une date passee, la puce creuse une date a venir. Une
   frise se lit a ses puces avant ses mots — c'est ce qui la distingue d'une
   liste de dates, et c'est pour cela que l'etat ne tient pas a la seule
   couleur du texte. */
.evt-jalons {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin: 0 0 var(--spacing-lg);
    padding: 0;
    list-style: none;
}

.evt-jalon {
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
    padding-block: 0.6875rem;
}

.evt-jalon__puce {
    flex: none;
    width: 0.75rem;
    height: 0.75rem;
    margin-top: 0.25rem;
    border: 2px solid var(--evt-rule);
    border-radius: var(--radius-pill);
    background: var(--evt-surface);
}

.evt-jalon--passe .evt-jalon__puce {
    border-color: var(--color-section-ancesu);
    background: var(--color-section-ancesu);
}

.evt-jalon__body {
    display: flex;
    flex-direction: column;
    gap: 0.1875rem;
    min-width: 0;
}

.evt-jalon__title {
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--evt-ink);
}

/* La date en chasse fixe, comme partout ou le minisite donne une donnee. */
.evt-jalon__date {
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

/* ── L'APPEL A CONTRIBUTION, colonne voisine des tarifs ──
   Les deux facons de participer : payer sa place, ou proposer quelque chose.
   La maquette les met cote a cote, et c'est ce qui les fait lire comme un
   choix plutot que comme deux sujets. */
.evt-callout {
    display: flex;
    flex-direction: column;
    padding: clamp(1.375rem, 3vw, 1.875rem);
    background: var(--evt-surface);
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius-lg);
}

/* L'en-tete de section perd son filet HAUT ici : il vit DANS une carte, et un
   trait a deux pixels du bord de la carte se lit comme un defaut de rendu. */
/* Le filet et son rembourrage ont disparu de la regle de base ; il ne reste
   ici qu'un selecteur sans effet, retire. */

.evt-calls {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    margin: 0 0 var(--spacing-lg);
    padding: 0;
    list-style: none;
}

.evt-call {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.875rem 1rem;
    border: 1px solid var(--evt-rule);
    border-radius: var(--evt-radius);
}

.evt-call__title {
    font-family: var(--font-title);
    font-size: var(--font-size-base);
    font-weight: 700;
    line-height: 1.3;
    color: var(--evt-ink);
    text-decoration: none;
}

.evt-call__title:hover,
.evt-call__title:focus-visible {
    color: var(--evt-cta);
}

/* Le `gap` porte l'ecart entre les deux mentions, jamais un separateur colle
   au texte : ecrit en caractere, il rend « Concours· jusqu'au 1 novembre ». */
.evt-call__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.125rem 0.75rem;
    font-family: var(--font-data);
    font-size: var(--font-size-2xs);
    color: var(--color-text-light);
}

.evt-call__text {
    font-size: var(--font-size-sm);
    line-height: 1.5;
    color: var(--color-text-light);
    text-wrap: pretty;
}

/* Les deux colonnes de « participer » : tarifs a gauche, appel a droite. Elles
   se valent, donc elles partagent la largeur. `evt-split` seul rend des pistes
   d'au moins 18,75 rem, ce qui laissait la grille tarifaire s'etaler quand
   l'appel n'existe pas — une carte de 1 200 px pour trois paliers. */
.evt-split--participer {
    align-items: start;
}

/* Les paliers DANS la carte : deux colonnes tant que la place existe, une
   seule ensuite. `auto-fit` sur 8 rem plutot qu'un nombre fixe — un evenement
   peut en avoir deux comme quatre. */
.evt-callout .evt-prices {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-lg);
}

/* ══ LE HERO DE L'ACCUEIL — exploration 1b ═══════════════════════════════════
   `Hero minisite · explorations`, variante « Deux colonnes, le visuel a
   droite ». Sa raison est enoncee dans la maquette et elle est decisive :

     « Le texte n'est jamais sur la photo : il reste lisible quelle que soit
       l'image fournie. »

   La composition incrustee qui la precedait demandait de connaitre l'image.
   Elle l'a prouve deux fois sur la seule edition d'Angers : le titre de
   l'affiche transparaissait derriere le `h1`, et le recadrage 16/9 amputait un
   bandeau 2,8:1 des deux bouts de son titre. Les deux defauts disparaissent en
   sortant le texte de l'image — pas en reglant mieux un degrade.

   Le visuel garde son 16/10 dans une colonne plus etroite, et la plaque
   d'edition mord sur son coin bas gauche. Les chiffres-cles descendent sous le
   hero, en bande legere. */
.evt-hero {
    position: relative;
    display: grid;
    grid-template-columns: 1.05fr 0.95fr;
    align-items: center;
    gap: 2.5rem;
    padding: 3rem;
    border: 0;
    border-radius: var(--evt-radius-lg);
    color: var(--ink-on-dark);
    background: var(--color-primary-dark);
}

/* Sans affiche, la seconde piste n'a rien a porter et la colonne de texte
   resterait serree sur la moitie gauche. `:has()` plutot qu'une classe : la
   condition est deja dans le gabarit, la redire serait deux verites a tenir. */
.evt-hero:not(:has(.evt-hero__aside)) {
    grid-template-columns: minmax(0, 1fr);
}

.evt-hero__texture,
.evt-hero__glow {
    position: absolute;
    pointer-events: none;
}

.evt-hero__texture {
    inset: 0;
    background: var(--evt-hero-texture);
}

.evt-hero__glow {
    left: -7.5rem;
    bottom: -9rem;
    width: 24rem;
    height: 24rem;
    background: var(--evt-hero-glow);
}

/* Les deux colonnes passent AU-DESSUS des deux fonds. */
.evt-hero__col,
.evt-hero__aside {
    position: relative;
    min-width: 0;
}

.evt-hero__col {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.evt-hero__state {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    gap: 0.5rem;
    padding: 0.375rem 0.8125rem;
    border-radius: var(--radius-pill);
    background: var(--evt-cta);
    color: var(--ink-on-dark);
    font-size: 0.65625rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}

.evt-hero__state-dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--ink-on-dark);
}

.evt-hero__title {
    margin: 0;
    max-width: 20ch;
    color: var(--ink-on-dark);
    font-family: var(--font-title);
    font-size: clamp(2rem, 3.4vw, 2.75rem);
    font-weight: 700;
    line-height: 1.04;
    letter-spacing: -0.022em;
    text-wrap: pretty;
}

.evt-hero__subtitle {
    margin: 0;
    color: var(--evt-hero-subtitle);
    font-family: var(--font-title);
    font-size: 1.1875rem;
    font-weight: 600;
    line-height: 1.35;
}

/* AMBRE, et non le vert de signature : celui-ci rend 2,1:1 sur le marine, donc
   il y est decoratif — or ce trait est ce qui separe le titre du chapo. */
.evt-hero__rule {
    display: block;
    width: 3.5rem;
    height: 0.3125rem;
    border-radius: var(--radius-pill);
    background: var(--color-section-formations);
}

.evt-hero__lead {
    margin: 0;
    max-width: 46ch;
    color: var(--ink-on-dark-soft);
    font-size: 1.03125rem;
    line-height: 1.6;
    text-wrap: pretty;
}

.evt-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding-top: 0.25rem;
}

.evt-hero__note {
    margin: 0;
    color: var(--ink-on-dark-muted);
    font-size: 0.84375rem;
    line-height: 1.5;
}

.evt-hero__cta {
    display: inline-flex;
    align-items: center;
    height: 3rem;
    padding: 0 1.5rem;
    border: 1.5px solid transparent;
    border-radius: var(--radius-md);
    background: var(--surface-2);
    color: var(--color-primary-dark);
    font-size: 0.78125rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
}

.evt-hero__cta:hover,
.evt-hero__cta:focus-visible {
    background: var(--evt-tint);
    color: var(--color-primary-dark);
}

/* `border-color` seul : la regle de base declare le raccourci `border`, et une
   variante ecrite plus haut serait reecrite par lui. */
.evt-hero__cta--ghost {
    border-color: var(--rule-on-dark);
    background: none;
    color: var(--ink-on-dark);
}

.evt-hero__cta--ghost:hover,
.evt-hero__cta--ghost:focus-visible {
    background: var(--veil-on-dark);
    color: var(--ink-on-dark);
}

/* ── LE VISUEL ET SA PLAQUE ───────────────────────────────────────
   La plaque MORD sur le coin du visuel : c'est ce debord qui la fait lire
   comme une etiquette posee dessus plutot que comme une legende en dessous.
   L'ecrin ne peut donc pas ecreter, seul le visuel le fait. */
.evt-hero__visual {
    position: relative;
    display: block;
    aspect-ratio: 16 / 10;
    border-radius: var(--evt-radius);
    overflow: hidden;
    /* Passe-partout GRIS TRES CLAIR, et le gris n'est pas un detail. L'affiche
       est en 2,80:1 dans un cadre en 16/10 : `contain` laisse 67 px de fond nu
       en haut et en bas, et c'est precisement dans cette bande que la plaque
       d'edition vient mordre. En blanc, 181 de ses 197 px etaient BLANC SUR
       BLANC — la plaque cessait d'etre une carte pour devenir du texte colle
       sur l'affiche.

       La maquette peut se permettre le clair parce que son visuel est une
       photo pleine ; le notre est une affiche posee sur un fond. */
    background: var(--evt-surface-muted);
    box-shadow: 0 30px 60px -28px var(--evt-lift);
}

.evt-hero__poster {
    display: block;
    width: 100%;
    height: 100%;
    /* `contain`, et c'est MESURE : l'affiche d'Angers fait 1250 x 446, soit
       2,80:1, quand le cadre de la 1b est en 16/10. En `cover`, 43 % de la
       largeur part — les deux bouts de « LUMIERE SUR LA PEDAGOGIE ».

       Le 16/10 se garde quand meme, parce que la plaque d'edition mord sur le
       coin du cadre : sa geometrie doit etre connue d'avance. C'est donc le
       CADRE qui reste fixe et l'affiche qui s'y inscrit, pas l'inverse. Un
       format vertical y tient aussi bien qu'un bandeau. */
    object-fit: contain;
}

.evt-hero__credit {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    padding: 0.1875rem 0.4375rem;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--surface-2) 92%, transparent);
    color: var(--color-text-light);
    font-size: 0.65625rem;
    line-height: 1.3;
}

.evt-hero__plate {
    position: absolute;
    left: -1rem;
    bottom: -1rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--evt-rule);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    /* Ombre PLUS COURTE et plus dense que celle du cadre : une ombre longue se
       dilue sur un fond clair et ne detache rien. Avec le filet, la plaque tient
       aussi bien sur le gris du passe-partout que sur le marine du hero — elle
       chevauche les deux. */
    box-shadow: 0 10px 24px -10px var(--evt-lift);
}

.evt-hero__plate-edition {
    color: var(--color-primary-dark);
    font-family: var(--font-title);
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
}

.evt-hero__plate-rule {
    width: 0.1875rem;
    align-self: stretch;
    border-radius: var(--radius-pill);
    background: var(--color-section-formations);
}

/* En chasse fixe, comme la maquette : la date et la ville sont des DONNEES,
   et la chasse fixe est ce qui les distingue d'une phrase. */
.evt-hero__plate-meta {
    display: flex;
    flex-direction: column;
    color: var(--color-primary);
    font-family: var(--font-data);
    font-size: 0.78125rem;
    font-weight: 500;
    line-height: 1.35;
}

/* ── LA BANDE DE REPERES, sous le hero ────────────────────────────
   Un filet colore, une valeur, un intitule. Pas de carte : une carte les
   mettrait au meme rang que le contenu qui suit, alors qu'ils ne font que
   qualifier ce que le titre vient d'annoncer. */
/* La bande etait etalee sur toute la largeur : trois reperes repartis sur
   1 192 px, chacun perdu au milieu de sa piste, avec une valeur au corps du
   texte courant. On lisait trois mentions egarees plutot qu'une bande.

   `max-content` et non `1fr` : les reperes se GROUPENT a gauche au lieu de se
   repartir, et la colonne de gauche du hero les surplombe. Le corps de la
   valeur passe a l'echelle d'un chiffre-cle — c'est ce qu'ils sont. */
.evt-marks {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), max-content));
    justify-content: start;
    gap: 1rem clamp(2rem, 4vw, 3.5rem);
}

.evt-mark {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    min-width: 0;
}

.evt-mark__rule {
    width: 1.75rem;
    height: 0.25rem;
    border-radius: var(--radius-pill);
    background: var(--color-section-colloques);
}

/* Les quatre couleurs du reseau, dans l'ordre de la maquette. Un seul filet
   repete quatre fois ferait une rangee de tirets ; quatre couleurs font une
   echelle, et c'est ce qui distingue les reperes les uns des autres. */
.evt-mark__rule--2 {
    background: var(--color-section-formations);
}

.evt-mark__rule--3 {
    background: var(--color-section-ancesu);
}

.evt-mark__rule--4 {
    background: var(--color-section-cesu);
}

.evt-mark__value {
    color: var(--evt-ink);
    font-family: var(--font-title);
    font-size: clamp(1.375rem, 2.4vw, 1.875rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
}

.evt-mark__label {
    color: var(--color-text-light);
    font-size: 0.84375rem;
    line-height: 1.35;
}

/* Paliers de la maquette : 900 px et 600 px, en `em` pour suivre la taille de
   police du navigateur. */
@media (width < 56.25em) {
    /* Une colonne. Le visuel passe SOUS le texte, ce que l'ordre du DOM donne
       deja : le titre reste le premier mot lu sur telephone. */
    .evt-hero {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.5rem;
        padding: 2rem;
    }
}

@media (width < 37.5em) {
    .evt-hero {
        padding: 1rem;
    }

    .evt-hero__title {
        font-size: 1.875rem;
    }

    /* La plaque NE MORD PLUS au telephone. Le debord de 16 px est calcule sur
       un hero rembourre de 48 px ; a 16 px de rembourrage, il l'amene pile sur
       le bord de la carte, ou elle se fait rogner par `overflow: hidden`. Elle
       rentre donc dans le cadre — le chevauchement est un effet de composition,
       pas une information. */
    .evt-hero__plate {
        left: 0.75rem;
        bottom: 0.75rem;
    }

    /* La chasse fixe sur 390 px coute trop de largeur pour ce qu'elle apporte. */
    .evt-hero__plate-meta {
        font-family: inherit;
    }

    .evt-marks {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .evt-hero__cta {
        justify-content: center;
        flex: 1 1 auto;
    }
}

/* ══ LA BARRE DU HAUT : deux pastilles a gauche, comme a droite ══════════════
   « Retour au site de l'ANCESU » et « Tous les evenements » etaient deux liens
   bleus nus, dans une barre dont la moitie droite porte des commandes en
   pastilles bordees. Le desequilibre se lisait comme un oubli : a gauche du
   texte, a droite des boutons.

   Ce sont deux NAVIGATIONS de meme rang — sortir du minisite, remonter d'un
   cran — et elles se rendent donc de la meme facon. Chacune porte son
   pictogramme : le libelle dit le geste, l'icone dit la destination, ce qui
   les distingue quand elles se suivent. */
.minisite-header__brand,
.minisite-header__back {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.3125rem 0.6875rem;
    border: 1px solid var(--evt-rule);
    border-radius: var(--radius-pill);
    background: var(--surface-2);
    color: var(--color-text-light);
    font-size: var(--font-size-xs);
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
    text-decoration: none;
}

.minisite-header__brand:hover,
.minisite-header__brand:focus-visible,
.minisite-header__back:hover,
.minisite-header__back:focus-visible {
    border-color: color-mix(in srgb, var(--color-primary) 35%, var(--evt-rule));
    background: var(--evt-tint);
    color: var(--color-primary-dark);
}

/* Le rembourrage droit servait a separer la marque du lien de retour quand les
   deux etaient du texte nu ; entre deux pastilles, c'est le `gap` du conteneur
   qui s'en charge, et le rembourrage dissymetrique se voit. */
.minisite-header__brand {
    padding-right: 0.6875rem;
}

/* ── CE BLOC A PERDU SON OBJET AVEC LA COQUILLE QUI LE POSAIT ──

   Il faisait survivre l'ECHEANCE DE TARIF au telephone : la coquille historique
   la logeait dans la fente du fil d'Ariane, et une regle globale masque
   `.breadcrumb-bar` sous 48 em. La ligne etait donc rendue de nouveau, mais
   VIDE de son chemin — ne restait que la pastille.

   Le bandeau d'echeance n'existe plus : la coquille v2 ne l'inclut pas, et
   `minisite-deadline` ne rend sur AUCUNE page (mesure du 2026-09-02, zero
   occurrence sur neuf pages de trois evenements).

   Ce qui restait de ce bloc etait donc une regle qui masquait le fil d'Ariane
   sur telephone — et le fil est desormais la SEULE sortie du minisite vers le
   site porteur. Elle gagnait en specificite sur la reprise ecrite dans
   `zones/event-minisite.css`, qui ne visait que `.breadcrumb-bar` : le
   conteneur etait bien affiche, le `<nav>` a l'interieur ne l'etait pas.

   Le piege pour la sonde vaut d'etre note : mesurer le `display` du CONTENEUR
   rendait « visible », et il l'etait. C'est la boite du `<nav>` — 0 px de haut
   — qui disait la verite. */
@media (width < 48em) {

    /* Le libelle complet ne tient pas sur 390 px, et la pastille est en
       `nowrap` : sans retour a la ligne autorise, elle deborderait de la
       ligne. Ici seulement, elle se replie. */
    .minisite-deadline {
        flex-wrap: wrap;
        white-space: normal;
    }
}

/* Un nombre IMPAIR de reperes laisse le dernier seul sur sa rangee, a
   demi-largeur : on lit un debordement plutot qu'une bande. Borne au palier ou
   la grille vaut exactement deux colonnes — au-dessus, `auto-fit` en range
   trois ou quatre et l'orpheline n'existe pas. */
@media (width < 37.5em) {
    .evt-marks {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .evt-mark:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
