/* sommaire des promotions et trombinoscopes */

/* ---------- promotions ---------- */
.promo-annee{margin:0 0 10px!important;font-family:Montserrat,sans-serif;font-size:12px;font-weight:500;
  letter-spacing:.16em;color:var(--crimson)}
.sec-head h2 sup{font-size:.5em;vertical-align:.72em;margin-left:1px}

/* ---------- trombinoscopes ---------- */
.trombi{display:grid;grid-template-columns:repeat(3,1fr);gap:26px}
.trombi a{display:block;background:#fff;box-shadow:0 12px 32px rgba(28,28,28,.14);
  transition:transform .35s cubic-bezier(.2,.7,.3,1),box-shadow .35s ease}
.trombi a:hover{transform:translateY(-4px);box-shadow:0 18px 44px rgba(28,28,28,.20)}
.trombi img{width:100%;display:block}
@media (max-width:1040px){.trombi{grid-template-columns:1fr;max-width:520px;gap:22px}}

/* ---------- sommaire des promotions ---------- */
/* Les cases sont toutes illustrées : un filet noir franc sépare les photos
   nettement, là où le filet clair d'origine se perdait dans les images.
   À 1 px il se perdait encore dans les arrondis de rendu : il passe à 4 px. */
/* Une rangée souple plutôt qu'une grille rigide : à cinq promotions, la grille
   à trois colonnes laissait une case vide, c'est-à-dire un rectangle noir au
   bout de la dernière rangée. En flex, les cases de la rangée incomplète
   s'élargissent et la remplissent. */
/* ---------- la matière du fond ----------
   Des croix semées tous les 44 px, écloses du coin haut droit et dissipées en
   descendant vers la gauche : elles occupent la bande qui sépare le bandeau
   photo de la grille, et la marge qui la longe à droite.

   Chaque endroit a sa matière — le quadrillage à la bande du parrain, les
   points à Candidater, les filets serrés à la présentation du diplôme, le
   quadrillage et les lueurs au bloc des alumni. La même partout aurait fait un
   papier peint.

   La croix est le seul motif du site tracé par une image : deux traits de neuf
   pixels centrés dans une tuile de quarante-quatre, ce qu'aucun dégradé ne
   sait faire. Elle pèse moins de trois cents octets, écrits dans la feuille
   elle-même : rien à télécharger. */
#vue-promotions .sec{position:relative;isolation:isolate}
#vue-promotions .sec::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='44' height='44'%3E%3Cpath d='M22 17.5v9M17.5 22h9' stroke='%231C1C1C' stroke-opacity='.26' stroke-width='1'/%3E%3C/svg%3E");
  -webkit-mask-image:radial-gradient(88% 78% at 100% 0%,#000 6%,transparent 74%);
  mask-image:radial-gradient(88% 78% at 100% 0%,#000 6%,transparent 74%)}

.promos-grille{display:flex;flex-wrap:wrap;gap:4px;background:var(--ink-deep);
  border:4px solid var(--ink-deep);box-shadow:var(--ombre-bloc)}
.promos-grille>.promo-case{flex:1 1 calc(33.333% - 4px);min-width:0}
.promo-case{background:#fff;padding:34px 32px 36px;display:block;transition:background .25s ease}
.promo-case:hover{background:var(--stone-soft)}
.promo-case b{display:block;font-family:Spectral,serif;font-size:26px;font-weight:400;color:var(--ink)}
.promo-case b sup{font-size:.5em;vertical-align:.72em}
.promo-case span{display:block;margin-top:8px;font-family:Montserrat,sans-serif;font-size:12px;
  font-weight:500;letter-spacing:.14em;color:var(--muted)}
.promo-case i{display:inline-block;margin-top:14px;padding:4px 11px 3px;background:var(--crimson);color:#fff;
  font-family:Montserrat,sans-serif;font-style:normal;font-size:11px;font-weight:500;letter-spacing:.12em}
.page-head h1 sup{font-size:.46em;vertical-align:.8em}
.page-head h1 .promo-cycle{vertical-align:.34em}
@media (max-width:1040px){.promos-grille>.promo-case{flex-basis:calc(50% - 4px)}}
@media (max-width:680px){.promos-grille>.promo-case{flex-basis:100%}}

/* ---------- l'encart de la promotion en Master I ----------
   Elle n'a pas passé le diplôme : elle n'a donc pas sa place dans la grille,
   qui réunit celles qui l'ont obtenu ou le passent. Mais elle existe, et la
   montrer à part dit mieux les choses qu'une case de plus au milieu des
   autres.

   La case est celle de la grille, à l'identique — même photo voilée, même
   survol, même pastille. Seule la forme change : une seule case, pleine
   largeur, plus haute, pour qu'une photo de groupe y tienne autrement que par
   une bande. Le cadre sombre est celui de la grille, pour que les deux blocs
   se répondent. */
.encart-m1{background:var(--ink-deep);border:4px solid var(--ink-deep);
  box-shadow:var(--ombre-bloc)}
.encart-m1 .promo-case{min-height:300px;display:flex;flex-direction:column;
  justify-content:flex-end;padding:38px 36px 36px}
.encart-m1 .promo-case b{font-size:32px}
@media (max-width:680px){
  .encart-m1 .promo-case{min-height:220px;padding:28px 24px 26px}
  .encart-m1 .promo-case b{font-size:26px}
}

/* ---------- sous la grille ---------- */
/* Le bouton qui mène aux promotions d'avant la 50e. */
.promos-suite{display:flex;justify-content:center;margin:40px 0 0}
/* La pastille est un « inline-block » : sans cela elle s'étirerait d'un bord
   à l'autre dans une case devenue colonne flex. */
.promo-case i{align-self:flex-start}

/* ---------- l'annuaire des anciennes promotions ----------
   La page « Les promotions » montre les mêmes promotions en grandes cases
   illustrées ; ici on cherche une année, pas une image. D'où des lignes denses,
   alignées sur trois colonnes, qui se parcourent du regard. */
#vue-anciennes-promotions .sec{padding:68px 0 116px}
.annuaire{border-top:1px solid var(--line)}
.annuaire-ligne{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;
  gap:16px 32px;align-items:baseline;
  padding:22px 4px 22px;border-bottom:1px solid var(--line);color:inherit;
  transition:background .22s ease,padding-left .22s ease}
.annuaire-ligne:hover,.annuaire-ligne:focus-visible{background:var(--stone-soft);padding-left:16px}
.annuaire-ligne b{font-family:Spectral,serif;font-size:21px;font-weight:400;color:var(--ink);
  transition:color .22s ease}
.annuaire-ligne b sup{font-size:.5em;vertical-align:.72em}
.annuaire-ligne:hover b,.annuaire-ligne:focus-visible b{color:var(--crimson)}
.annuaire-annees{font-family:Montserrat,sans-serif;font-size:12.5px;font-weight:500;
  letter-spacing:.14em;color:var(--muted)}
.annuaire-effectif{font-family:Montserrat,sans-serif;font-size:12.5px;color:var(--muted);
  justify-self:end;white-space:nowrap}
.annuaire-effectif::after{content:" \2192";margin-left:12px;color:var(--crimson)}
.annuaire-note{margin:34px 0 0;max-width:68ch;font-size:15px;line-height:1.7;color:var(--muted)}
/* Tant qu'aucune promotion ancienne n'est renseignée, la page n'a qu'un message
   à donner : il prend la place d'un bloc, encadré et centré, au lieu de flotter
   en petit caractère au milieu d'une page vide. Le filet rouge du haut reprend
   celui des fiches. */
.annuaire-note.annuaire-seule{margin:0;max-width:none;background:#fff;
  border:1px solid var(--line);border-top:2px solid var(--crimson);
  padding:46px 48px 48px;text-align:center;font-size:16.4px;color:var(--ink)}
@media (max-width:680px){.annuaire-note.annuaire-seule{padding:34px 24px 36px}}
@media (max-width:680px){
  .annuaire-ligne{grid-template-columns:1fr auto;gap:6px 18px}
  .annuaire-annees{grid-column:1}
  .annuaire-effectif{grid-row:1 / span 2}
}

/* ---------- trombinoscope ---------- */
.trombi-grille{display:grid;grid-template-columns:repeat(5,1fr);gap:30px}
.tete{margin:0}
.tete img{width:100%;aspect-ratio:1;object-fit:cover;display:block;background:var(--stone-soft);
  transition:transform .4s cubic-bezier(.2,.7,.3,1)}
.tete:hover img{transform:scale(1.03)}
.tete figcaption{margin-top:14px;padding-top:12px;border-top:2px solid var(--crimson);line-height:1.35}
.tete b{display:block;font-family:Spectral,serif;font-size:17px;font-weight:400;color:var(--ink)}
.tete span{display:block;font-family:Montserrat,sans-serif;font-size:12px;font-weight:500;
  letter-spacing:.09em;text-transform:uppercase;color:var(--muted);margin-top:3px}
@media (max-width:1040px){.trombi-grille{grid-template-columns:repeat(3,1fr);gap:24px}}
@media (max-width:680px){.trombi-grille{grid-template-columns:repeat(2,1fr);gap:18px}}

/* ---------- trombinoscope : voile au survol ----------
   Le portrait est enfermé dans .portrait, qui masque le débordement :
   le voile monte du bas et l'image s'agrandit sans sortir du cadre. */
.tete .portrait{position:relative;overflow:hidden;background:var(--stone-soft)}
.voile{
  position:absolute;inset:0;display:flex;flex-direction:column;justify-content:flex-end;
  padding:18px 16px 16px;
  background:linear-gradient(to top,rgba(17,17,17,.88) 0%,rgba(17,17,17,.62) 42%,rgba(17,17,17,.18) 72%,rgba(17,17,17,0) 100%);
  opacity:0;transition:opacity .32s ease;
}
.tete:hover .voile,
.tete:focus-within .voile{opacity:1}

/* les boutons glissent légèrement vers le haut en apparaissant */
.voile-liens{display:flex;flex-wrap:wrap;gap:8px;
  transform:translateY(10px);transition:transform .32s cubic-bezier(.2,.7,.3,1)}
.tete:hover .voile-liens,.tete:focus-within .voile-liens{transform:translateY(0)}
.pastille{
  display:inline-flex;align-items:center;gap:7px;
  padding:7px 11px;border:1px solid rgba(255,255,255,.62);
  font-family:Montserrat,sans-serif;font-size:10.5px;font-weight:600;
  letter-spacing:.11em;text-transform:uppercase;color:#fff;
  background:rgba(255,255,255,.06);
  transition:background .22s ease,border-color .22s ease;
}
.pastille:hover{background:var(--crimson);border-color:var(--crimson)}
.pastille svg{width:13px;height:13px;flex:none;fill:currentColor}
/* l'icône CV est un tracé : un peu plus grande pour que les lettres restent lisibles */
.pastille .ico-cv{width:14px;height:14px}

/* écrans tactiles : pas de survol possible, le voile reste visible */
@media (hover:none){
  .voile{opacity:1;background:linear-gradient(to top,rgba(17,17,17,.9) 0%,rgba(17,17,17,.55) 45%,rgba(17,17,17,0) 85%)}
  .voile-liens{transform:none}
}
@media (max-width:680px){
  .voile{padding:12px 10px 10px}
  .pastille{padding:6px 8px;font-size:9.5px;letter-spacing:.08em}
}

/* ---------- l'en-tête d'une page de promotion ----------
   Il est plus haut qu'ailleurs. Sur les autres pages, le bandeau est un décor
   derrière un titre ; ici, la photo est le sujet — c'est la promotion
   elle-même, et on vient la regarder.

   À 396 px de haut pour 1380 de large, une photo de groupe se réduisait à une
   bande de visages hauts comme un ongle. Le retrait monte donc d'environ la
   moitié, et il suit la largeur de l'écran pour que le rapport tienne du
   portable au grand écran.

   Le voile, lui, ne bouge pas. Il paraît déjà plus léger sur un bandeau haut
   — la même teinte étalée sur deux fois plus de hauteur laisse voir bien
   davantage —, et l'éclaircir en plus mettrait en péril la lisibilité du
   titre, qui passe au milieu de la photo et non au-dessus.

   La règle porte les trois sélecteurs qu'il faut pour l'emporter : au-delà de
   1500 px, pages.css en pose une de même nature sur « .page-head:not(.sobre) »,
   qui est plus précise qu'une classe seule et reprenait la main — le bandeau
   rapetissait en passant sur grand écran. */
/* Le titre descend au bas du bandeau. Au milieu, il coupait la photo de groupe
   en deux et se posait sur les visages ; en bas, il laisse voir tout ce qui est
   au-dessus et se lit comme une légende sous une estampe. Le retrait du haut
   grandit donc, celui du bas se resserre. */
.page-head.page-head-promo:not(.sobre){padding:clamp(262px,26vw,500px) 0 clamp(54px,4.4vw,94px)}
@media (max-width:860px){
  .page-head.page-head-promo:not(.sobre){padding:196px 0 44px}
}

/* ---------- le titre et son parrain, sur une ligne ----------
   La promotion et l'entreprise qui l'accompagne se nomment d'un seul tenant.
   Une barre claire les sépare, assez haute pour tenir tête au titre.

   Le parrain forme un seul objet et non trois pièces en file : la pastille à
   gauche, et contre elle l'étiquette et le nom empilés. Deux lignes serrées
   font le poids d'un titre de cinquante pixels, là où une ligne unique se
   serait perdue à côté.

   Le logo est sur une pastille claire : ces logos sont dessinés pour du papier
   blanc, et les noirs comme les bleu marine disparaîtraient sur une photo de
   groupe assombrie. */
.promo-rang{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:12px 28px}
/* Le titre s'efface d'un cran. « Les promotions » le surmonte dans la même
   fonte, et c'est elle qui ouvre : le numéro vient après, et n'a plus besoin
   de cinquante pixels pour se faire entendre. Il fait désormais le poids du
   nom du parrain qui lui fait face. */
.promo-rang h1{margin:0;font-size:clamp(26px,2.7vw,36px)}
.promo-barre{width:1px;align-self:stretch;min-height:40px;background:rgba(255,255,255,.3);flex:none}
.promo-blason{display:flex;align-items:center;gap:15px;text-decoration:none}
.promo-blason-ecu{display:flex;align-items:center;justify-content:center;flex:none;
  background:rgba(255,255,255,.96);padding:9px 14px;min-width:78px;
  box-shadow:0 12px 30px -14px rgba(0,0,0,.7);
  transition:transform .32s cubic-bezier(.22,.68,.3,1),box-shadow .32s ease}
.promo-blason-ecu img{display:block;max-height:26px;max-width:112px;width:auto;height:auto}
.promo-blason-dire{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left}
.promo-blason-mot{font-family:Montserrat,sans-serif;font-size:9px;font-weight:600;
  letter-spacing:.19em;text-transform:uppercase;color:rgba(255,255,255,.58);
  text-shadow:0 1px 10px rgba(0,0,0,.5)}
.promo-blason-nom{font-family:Spectral,Georgia,serif;font-size:17.5px;color:rgba(255,255,255,.95);
  text-shadow:0 1px 12px rgba(0,0,0,.55);border-bottom:1px solid transparent;padding-bottom:1px;
  transition:border-color .24s ease}
.promo-blason:hover .promo-blason-ecu{transform:translateY(-1px);
  box-shadow:0 16px 34px -14px rgba(0,0,0,.78)}
.promo-blason:hover .promo-blason-nom{border-bottom-color:rgba(255,255,255,.55)}

/* Repliés, le titre et le parrain ne sont plus côte à côte : la barre n'a plus
   rien à séparer, et le parrain se centre sous le titre. */
@media (max-width:1040px){
  .promo-rang{gap:16px}
  .promo-barre{display:none}
  .promo-blason{margin:0 auto}
}
@media (max-width:620px){
  .promo-blason{gap:12px}
  .promo-blason-nom{font-size:16px}
  .promo-blason-ecu{padding:8px 12px;min-width:68px}
  .promo-blason-ecu img{max-height:22px;max-width:94px}
}

/* ---------- case de promotion illustrée ----------
   La photo de groupe passe en fond, voilée de sombre pour que le texte reste
   lisible. Au survol, le voile s'allège : la photo se révèle un peu. */
.promo-case.avec-photo{position:relative;overflow:hidden;background:#1C1C1C;
  background-size:cover;background-position:var(--case-x, center) var(--case-y, center)}
/* La photo est reprise par un calque interne, seul à pouvoir s'agrandir sans
   entraîner le texte : un fond d'élément ne se met pas à l'échelle. */
.promo-case.avec-photo::after{content:"";position:absolute;inset:0;
  background-image:inherit;background-size:cover;
  background-position:var(--case-x, center) var(--case-y, center);
  transition:transform .75s cubic-bezier(.2,.7,.3,1)}
.promo-case.avec-photo::before{content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(to bottom,rgba(17,17,17,.72),rgba(17,17,17,.82));
  transition:background .35s ease}
.promo-case.avec-photo:hover::after{transform:scale(1.045)}
.promo-case.avec-photo:hover{background-color:#1C1C1C}
.promo-case.avec-photo:hover::before{
  background:linear-gradient(to bottom,rgba(17,17,17,.56),rgba(17,17,17,.72))}
.promo-case.avec-photo b,.promo-case.avec-photo span{position:relative;z-index:2;color:#fff}
.promo-case.avec-photo span{color:rgba(255,255,255,.78)}
.promo-case.avec-photo i{position:relative;z-index:2}

/* Le survol soulève la case et la détache de la grille. */
.promo-case{position:relative;transition:background .25s ease,transform .4s cubic-bezier(.2,.7,.3,1),
  box-shadow .4s ease}
.promo-case:hover{z-index:2;transform:translateY(-3px);
  box-shadow:0 14px 30px rgba(28,28,28,.15)}
/* Un filet rouge se déploie sous le numéro de promotion. */
.promo-case b{position:relative;padding-bottom:10px}
.promo-case b::after{content:"";position:absolute;left:0;bottom:0;width:40px;height:2px;
  background:var(--crimson);transform:scaleX(0);transform-origin:left;
  transition:transform .45s cubic-bezier(.2,.7,.3,1)}
.promo-case:hover b::after{transform:scaleX(1)}
@media (prefers-reduced-motion:reduce){
  .promo-case,.promo-case.avec-photo::after,.promo-case b::after{transition:none}
  .promo-case:hover{transform:none}
}

/* ---------- arrivée des portraits ----------
   À l'ouverture d'une page de promotion, les vignettes paraissent l'une après
   l'autre. Le décalage est court : au-delà, l'attente se sent. */
@keyframes paraitre{
  from{opacity:0;transform:translateY(16px) scale(.985)}
  to{opacity:1;transform:none}
}
.trombi-grille .tete{animation:paraitre .9s cubic-bezier(.22,.7,.3,1) backwards}
.trombi-grille .tete:nth-child(1){animation-delay:0.05s}
.trombi-grille .tete:nth-child(2){animation-delay:0.10s}
.trombi-grille .tete:nth-child(3){animation-delay:0.15s}
.trombi-grille .tete:nth-child(4){animation-delay:0.20s}
.trombi-grille .tete:nth-child(5){animation-delay:0.25s}
.trombi-grille .tete:nth-child(6){animation-delay:0.30s}
.trombi-grille .tete:nth-child(7){animation-delay:0.35s}
.trombi-grille .tete:nth-child(8){animation-delay:0.40s}
.trombi-grille .tete:nth-child(9){animation-delay:0.45s}
.trombi-grille .tete:nth-child(10){animation-delay:0.50s}
.trombi-grille .tete:nth-child(11){animation-delay:0.55s}
.trombi-grille .tete:nth-child(12){animation-delay:0.60s}
.trombi-grille .tete:nth-child(13){animation-delay:0.65s}
.trombi-grille .tete:nth-child(14){animation-delay:0.70s}
.trombi-grille .tete:nth-child(15){animation-delay:0.75s}
.trombi-grille .tete:nth-child(16){animation-delay:0.80s}
.trombi-grille .tete:nth-child(17){animation-delay:0.85s}
.trombi-grille .tete:nth-child(18){animation-delay:0.90s}
.trombi-grille .tete:nth-child(19){animation-delay:0.95s}
.trombi-grille .tete:nth-child(20){animation-delay:1.00s}
.trombi-grille .tete:nth-child(21){animation-delay:1.05s}
.trombi-grille .tete:nth-child(22){animation-delay:1.10s}
.trombi-grille .tete:nth-child(23){animation-delay:1.15s}
.trombi-grille .tete:nth-child(24){animation-delay:1.20s}
.trombi-grille .tete:nth-child(25){animation-delay:1.25s}
.trombi-grille .tete:nth-child(26){animation-delay:1.30s}
.trombi-grille .tete:nth-child(27){animation-delay:1.35s}
.trombi-grille .tete:nth-child(28){animation-delay:1.40s}
.trombi-grille .tete:nth-child(29){animation-delay:1.45s}
.trombi-grille .tete:nth-child(30){animation-delay:1.50s}
.trombi-grille .tete:nth-child(n+31){animation-delay:1.55s}
@media (prefers-reduced-motion:reduce){
  .trombi-grille .tete{animation:none}
}
