/*
 * Systeme de design du produit Rektora Sites, version 2.
 *
 * La version 1 decrivait une structure. Le verdict porte sur le premier jet en
 * ligne etait sans appel, et juste : c'etait une maquette filaire, pas un
 * design. Cette version applique des directives chiffrees, tirees des releves
 * faits sur deux sites universitaires de reference.
 *
 * Regles opposables a toute evolution de ce fichier :
 *  - aucune valeur d'identite : couleurs et polices arrivent par le bloc :root
 *    injecte depuis les reglages ; ce qui est ici est neutre et fixe ;
 *  - aucun !important, aucun style inline, aucune police distante ;
 *  - mobile d'abord : la base est mobile, puis min-width 768 et 1024 seulement.
 */

/* ══ 0. Polices auto-hebergees ══════════════════════════════════════════════ */

/*
 * Archivo pour les titres, Source Sans 3 pour le texte. Licence SIL OFL, donc
 * redistribuables avec le produit. Les deux sont des polices variables : un
 * seul fichier par sous-ensemble couvre toutes les graisses utilisees, ce qui
 * divise par deux le poids a telecharger sur une connexion lente.
 *
 * Deux sous-ensembles : `latin` couvre le francais courant, `latin-ext` prend
 * le relais pour le reste. Le navigateur ne telecharge que ce dont la page a
 * besoin.
 */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/source-sans-3-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/source-sans-3-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ══ 1. Jetons ══════════════════════════════════════════════════════════════ */

:root {
  /* Echelle de gris, fixe au produit. Jamais de noir pur. */
  --gray-100: #f8f9fa;
  --gray-200: #eceef0;
  --gray-300: #dde1e5;
  --gray-400: #c2c8ce;
  --gray-500: #98a1a9;
  --gray-600: #6c757d;
  --gray-700: #495057;
  --gray-800: #343a40;
  --gray-900: #1d1d1d;

  /* Bleu-noir des titres et du pied : donne le serieux institutionnel sans
     l'agressivite du noir pur. Fixe au produit, pas a l'etablissement. */
  --c-encre: #12263a;
  --c-encre-profond: #0d1c2c;

  --c-text: var(--gray-900);
  --c-text-doux: var(--gray-700);
  --c-heading: var(--c-encre);
  --c-bg: #ffffff;
  --c-bg-alt: var(--gray-100);
  --c-bordure: var(--gray-300);

  /* Filet fin. Repli neutre ici ; les reglages le remplacent par un degre tres
     clair de la couleur principale. Distinct de --c-bordure, qui appartient aux
     champs de saisie et ne doit pas prendre la teinte de l'etablissement. */
  --c-filet: var(--c-bordure);

  /* Replis neutres. Les reglages les remplacent par la charte du client. */
  --c-primary: var(--gray-800);
  --c-primary-light: var(--gray-600);
  --c-primary-dark: var(--gray-900);
  --c-primary-pale: var(--gray-100);
  --c-accent: var(--gray-700);
  --c-accent-dark: var(--gray-800);
  --c-accent-darker: var(--gray-900);
  --c-sur-primary: #ffffff;
  --c-sur-accent: #ffffff;

  /* Voile pale de la couleur principale, pour badges et fonds discrets. */
  --c-primary-voile: #e8f1fa;

  --f-heading: 'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
  --f-body: 'Source Sans 3', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;

  /* Echelle typographique, base 17 px. Les valeurs mobiles sont la base ; les
     valeurs bureau sont posees au palier 768. */
  --fs-body: 17px;
  --fs-h1: 32px;
  --fs-h2: 25px;
  --fs-h3: 22px;
  --fs-meta: 14px;
  --lh-body: 1.65;
  --lh-heading: 1.2;

  --w-content: 1140px;
  --w-narrow: 720px;

  --sp-1: 0.5rem;
  --sp-2: 1rem;
  --sp-3: 1.5rem;
  --sp-4: 2rem;
  --sp-6: 3rem;
  --sp-8: 4rem;

  /*
   * Signature de l'etablissement dans l'en-tete. La hauteur du logo est la
   * valeur maitresse ; la bande blanche se calcule a partir d'elle, jamais
   * l'inverse. Un client dont le logo est carre ou tres horizontal garde donc
   * un en-tete correct : seule sa largeur suit le ratio de son fichier.
   *
   * Repere de metier : la signature occupe 55 a 70 % de la hauteur de sa bande.
   *
   * VALEUR DE SECURITE POUR LES TRES PETITS ECRANS (< 360 px). Elle est
   * relevee des 360 px, et de nouveau au palier bureau -- voir §4.2 et le
   * `PROMPT-118`, ou chaque marche est mesuree.
   */
  --h-logo: 44px;
  --marge-logo: 10px;

  --radius: 8px;
  --radius-petit: 4px;
  --shadow: 0 1px 3px rgba(18, 38, 58, 0.08), 0 4px 12px rgba(18, 38, 58, 0.06);
  --shadow-fort: 0 6px 24px rgba(18, 38, 58, 0.16);
  --transition: 150ms ease;
}

@media (min-width: 768px) {
  :root {
    --fs-h1: 44px;
    --fs-h2: 30px;
  }
}

/* ══ 2. Fondations ══════════════════════════════════════════════════════════ */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body.rkt {
  margin: 0;
  font-family: var(--f-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--c-text);
  background: var(--c-bg);
  -webkit-text-size-adjust: 100%;
}

.rkt img {
  max-width: 100%;
  height: auto;
  display: block;
}

.rkt h1,
.rkt h2,
.rkt h3,
.rkt h4 {
  font-family: var(--f-heading);
  line-height: var(--lh-heading);
  letter-spacing: -0.01em;
  margin: 0 0 var(--sp-2);
  color: var(--c-heading);
}

.rkt h1 { font-size: var(--fs-h1); font-weight: 700; }
.rkt h2 { font-size: var(--fs-h2); font-weight: 700; }
.rkt h3 { font-size: var(--fs-h3); font-weight: 600; }
.rkt h4 { font-size: 1.1rem; font-weight: 600; }

.rkt p { margin: 0 0 var(--sp-2); }

.rkt a { color: var(--c-primary-dark); }

/* Les liens du corps de texte sont soulignes : la couleur seule ne suffit pas. */
.rkt-prose a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Surtitre et meta : capitales espacees, la respiration institutionnelle. */
.rkt-surtitre,
.rkt-meta-cap {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
}

/* Lien d'evitement : premier element du document, visible au clavier seulement. */
.rkt-evitement {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 1000;
  padding: var(--sp-1) var(--sp-2);
  background: var(--c-bg);
  color: var(--c-text);
  border: 2px solid var(--c-primary);
  border-radius: 0 0 var(--radius) 0;
}

.rkt-evitement:focus {
  left: 0;
}

/* Reserve aux lecteurs d'ecran. Le produit possede la sienne. */
.rkt-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Indicateur de focus, absent des sept plugins examines au recensement. */
.rkt :focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Sur fond sombre, un contour bleu ne se voit pas : on passe au blanc. */
.rkt-entete-haut :focus-visible,
.rkt-banniere :focus-visible,
.rkt-pied :focus-visible,
.rkt-chiffres :focus-visible {
  outline-color: #ffffff;
}

@media (prefers-reduced-motion: reduce) {
  .rkt *,
  .rkt *::before,
  .rkt *::after {
    animation-duration: 0.01ms;
    animation-iteration-count: 1;
    transition-duration: 0.01ms;
    scroll-behavior: auto;
  }
}

/* ══ 3. Mise en page ════════════════════════════════════════════════════════ */

.rkt-conteneur {
  width: 100%;
  max-width: var(--w-content);
  margin: 0 auto;
  padding: 0 var(--sp-2);
}

.rkt-conteneur--etroit { max-width: var(--w-narrow); }

/*
 * `padding-top`/`padding-bottom`, JAMAIS le raccourci `padding`. Dix-huit
 * gabarits posent `rkt-conteneur rkt-section` sur le MEME element -- un
 * `main` de fiche ou d'archive, par exemple. Les deux classes ont la meme
 * specificite (une seule classe chacune) ; le raccourci `padding` remet les
 * QUATRE cotes a chaque fois, donc celle qui vient en dernier dans le fichier
 * efface le cote horizontal pose par l'autre, meme quand elle ne voulait
 * regler que le vertical. C'est le defaut signale par Michelot le 31 juillet
 * (capture mobile, texte d'article collé aux deux bords) : `.rkt-conteneur`
 * posait `padding: 0 var(--sp-2)`, et cette regle, plus bas dans le fichier,
 * remettait `0` a gauche et a droite sans le vouloir. Cibler seulement le
 * haut et le bas rend les deux classes additives, quel que soit leur ordre
 * dans le fichier ou lequel des deux gabarits les combine.
 */
.rkt-section { padding-top: var(--sp-6); padding-bottom: var(--sp-6); }
.rkt-section--alt { background: var(--c-bg-alt); }

/* Filet orange devant chaque titre de section : la couleur entre dans la page
   ailleurs que sur les boutons, ce qui manquait a la version 1. */
.rkt-section-titre {
  margin-bottom: var(--sp-4);
}

.rkt-section-titre::before {
  content: '';
  display: block;
  width: 48px;
  height: 4px;
  border-radius: 2px;
  background: var(--c-accent);
  margin-bottom: var(--sp-2);
}

/* Introduction d'archive : meme colonne de lecture que le corps d'une page. */
.rkt-archive-intro {
  max-width: 720px;
  margin-top: var(--sp-2);
}

/* ── Encadre : un argument, pas un paragraphe ─────────────────────────────── */

/* Nom distinct de `.rkt-encadre`, deja pris par le bloc de renseignements
   d'une fiche : deux encadres, deux roles, aucun heritage accidentel. */
.rkt-page-encadre {
  max-width: var(--w-narrow);
  margin: var(--sp-3) 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg-alt);
  border-left: 4px solid var(--c-accent-filet, var(--c-accent));
  border-radius: 0 var(--radius) var(--radius) 0;
}

.rkt-page-encadre p { margin: 0; }
.rkt-page-encadre p + p { margin-top: var(--sp-1); }

/* ── Calendrier academique, groupe par mois (PROMPT-161, remplace le
 *    regroupement par categorie en cartes du PROMPT-158) ─────────────────
 *
 * Les mois reprennent l'accordeon de base (`.rkt-accordeon-*`, §23) : depuis
 * le `PROMPT-159`, le socle porte deja le remplissage plein sur `[open]`,
 * herite sans une ligne de plus ici. Seul `.rkt-calendrier-mois-liste`
 * ajoute un espacement au-dessus, propre a cette page.
 *
 * La ligne de jalon REPREND LA DISPOSITION D'AVANT LE `PROMPT-158` (date en
 * gras a gauche, titre a droite, filet fin entre les lignes), sur demande
 * explicite de Michelot -- avec un badge de categorie en plus, a droite
 * (`.rkt-badge`, deja generique, aucune classe de plus pour lui).
 */

.rkt-calendrier-mois-liste { margin-top: var(--sp-4); }

.rkt-calendrier-mois-etat {
  font-weight: 400;
  color: var(--c-text-doux);
  font-size: var(--fs-meta);
}

.rkt-accordeon-section[open] .rkt-calendrier-mois-etat { color: rgba(255, 255, 255, 0.75); }

.rkt-calendrier-ligne {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.15rem;
  padding: var(--sp-1) 0;
  border-bottom: 1px solid var(--c-bordure);
  align-items: baseline;
}

.rkt-calendrier-ligne:last-child { border-bottom: 0; }

.rkt-calendrier-quand {
  font-family: var(--f-heading);
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-calendrier-precision {
  display: block;
  font-size: 0.9rem;
  color: var(--c-text-doux);
}

.rkt-calendrier-badge { justify-self: start; }

@media (min-width: 768px) {
  .rkt-calendrier-ligne {
    grid-template-columns: 16rem 1fr auto;
    gap: var(--sp-2);
  }

  .rkt-calendrier-badge { justify-self: end; }
}

/* ── Plages de rendez-vous ────────────────────────────────────────────────── */

.rkt-plages {
  list-style: none;
  margin: var(--sp-3) 0;
  padding: 0;
  max-width: var(--w-narrow);
}

.rkt-plage {
  padding: var(--sp-1) 0;
  border-bottom: 1px solid var(--c-bordure);
}

.rkt-plage-quand {
  font-family: var(--f-heading);
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-plage-fuseau,
.rkt-plage-objet {
  display: block;
  font-size: 0.9rem;
  color: var(--c-text-doux);
}

.rkt-plages-repli {
  max-width: var(--w-narrow);
  margin: var(--sp-3) 0;
  color: var(--c-text-doux);
}

.rkt-plages-contact {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin-top: var(--sp-3);
}

/* ── Groupes d'archive ────────────────────────────────────────────────────── */

.rkt-groupe + .rkt-groupe { margin-top: var(--sp-4); }
.rkt-groupe h2 { margin-bottom: var(--sp-2); }

/* ── Tuiles d'une page carrefour ──────────────────────────────────────────── */

.rkt-tuiles {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: 0;
}

.rkt-tuile { margin: 0; }

.rkt-tuile a {
  display: block;
  height: 100%;
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.rkt-tuile a:hover,
.rkt-tuile a:focus-visible {
  border-color: var(--c-primary);
  box-shadow: var(--shadow);
}

.rkt-tuile-titre {
  display: block;
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-tuile-desc {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--c-text-doux);
}

@media (min-width: 768px) {
  .rkt-tuiles { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .rkt-tuiles { grid-template-columns: repeat(3, 1fr); }
}

.rkt-section-titre--centre { text-align: center; }
.rkt-section-titre--centre::before { margin-left: auto; margin-right: auto; }

.rkt-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
}

@media (min-width: 768px) {
  .rkt-conteneur { padding: 0 var(--sp-3); }
  .rkt-section { padding-top: var(--sp-8); padding-bottom: var(--sp-8); }
  .rkt-grille--2,
  .rkt-grille--3,
  .rkt-grille--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .rkt-grille--3 { grid-template-columns: repeat(3, 1fr); }
  .rkt-grille--4 { grid-template-columns: repeat(4, 1fr); }
}

/* ══ 4. En-tete ═════════════════════════════════════════════════════════════ */

/*
 * En-tete a deux bandes.
 *
 *   .rkt-entete-haut   bande de couleur principale : services, aligne a droite
 *   .rkt-entete-bas    bande blanche : carte du logo et menu principal
 *   .rkt-recherche     panneau deroulant, replie par defaut
 *
 * La carte du logo est un bloc blanc pose a cheval sur les deux bandes. Elle est
 * remontee par une marge negative, compensee en bas par la marge opposee : la
 * carte ne modifie donc pas la hauteur de la bande blanche.
 *
 * Mobile d'abord : les trois bandes sont reordonnees par la flexion, ce qui met
 * le logo et le hamburger en haut, la recherche ensuite, et la pilule d'appel a
 * l'action en pleine largeur en bas. Rien n'est duplique dans le document :
 * l'ordre du balisage reste celui du bureau.
 */

.rkt-entete {
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--c-bg);
  border-bottom: 1px solid var(--c-bordure);
  transition: box-shadow var(--transition);
}

.rkt-entete.est-defilee { box-shadow: var(--shadow); }

.rkt-entete-bas { order: 1; }
.rkt-recherche { order: 2; }
.rkt-entete-haut { order: 3; }

/* ── 4.1 Bande de couleur ─────────────────────────────────────────────────── */

.rkt-entete-haut {
  background: var(--c-primary);
  color: #ffffff;
  font-size: var(--fs-meta);
}

.rkt-entete-haut-interieur {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1) var(--sp-3);
  padding-top: var(--sp-1);
  padding-bottom: var(--sp-1);
}

.rkt .rkt-entete-haut a {
  color: #ffffff;
  text-decoration: none;
}

.rkt .rkt-entete-haut a:hover { text-decoration: underline; }

/* La pilule est le seul appel a l'action de l'en-tete. Sur mobile elle prend
   toute la largeur et passe en premier dans la bande.
   Le selecteur descend jusqu'a `a.rkt-pilule` : la regle generique des liens de
   la bande, plus specifique d'un element, l'emportait sinon et ecrivait la
   pilule en blanc sur blanc. Defaut vu sur la capture, puis corrige. */
.rkt .rkt-entete-haut a.rkt-pilule {
  order: -1;
  flex: 1 0 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem var(--sp-3);
  border-radius: 999px;
  background: #ffffff;
  /* Teinte principale assombrie si besoin jusqu'au niveau AA sur blanc. Le
     repli sert au cas ou aucune couleur n'est configuree. */
  color: var(--c-primary-lisible, var(--c-primary));
  font-family: var(--f-heading);
  font-weight: 700;
  font-size: var(--fs-meta);
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
  transition: background var(--transition);
}

.rkt .rkt-entete-haut a.rkt-pilule:hover {
  background: var(--gray-100);
  text-decoration: none;
}

.rkt-lien-haut {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.rkt-lien-haut svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
}

/* Le carre de recherche est masque sur mobile : la recherche s'y ouvre avec le
   menu, dans le meme geste, plutot que derriere un second bouton. */
.rkt-recherche-bascule { display: none; }

/* ── 4.2 Bande blanche : carte du logo et menu ────────────────────────────── */

.rkt-entete-bas-interieur {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  /* La bande sert le logo : sa hauteur est celle du logo plus deux marges. */
  min-height: calc(var(--h-logo) + 2 * var(--marge-logo));
}

.rkt-marque {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--f-heading);
  font-weight: 700;
  text-decoration: none;
  color: var(--c-heading);
  /* Sans cela, la marque est un element de flex qui peut se reduire a zero, et
     le `max-width: 100%` de l'image se calcule alors sur une largeur nulle :
     le logo disparait. Defaut mesure puis corrige. */
  flex-shrink: 0;
  min-width: 0;
}

.rkt-marque img {
  height: var(--h-logo);
  width: auto;
  max-width: none;
}

/* ── Le logo agrandi (PROMPT-118, point 2) ────────────────────────────────
 *
 * Michelot demande « le logo, deux fois plus grand ». Les trois
 * verifications que le prompt rend obligatoires ont ete faites au
 * navigateur, et DEUX D'ENTRE ELLES COMMANDENT UNE VALEUR PLUS PETITE QUE
 * LE DOUBLE. Les mesures, plutot que la conclusion seule :
 *
 * 1. TELEPHONE -- le logo partage sa ligne avec le bouton de menu.
 *      44 px (etat anterieur) ... une ligne, a 320, 360 et 375 px
 *      66 px .................... une ligne, a 360 et 375 px
 *      72 px .................... DEUX lignes des 360 px
 *      88 px (le double) ........ DEUX lignes des 375 px, en-tete a 291 px
 *                                 soit 44 % d'un ecran de 667 px de haut
 *    Retenu : 66 px des 360 px de large. 360 px est la largeur d'ecran
 *    Android la plus repandue ; sous 360, la valeur de base (44 px) reste,
 *    parce que 66 px y renvoie deja le bouton a la ligne.
 *
 * 2. BUREAU -- le logo partage sa ligne avec les six rubriques ET avec la
 *    barre « Acces par public ». Largeur reellement disponible a 1024 px :
 *    976 px. Ce qu'il faut y loger :
 *      carte du logo a 52 px ......... 172 px
 *      les six entrees ............... 628 px  (+ 16 px de gouttiere)
 *      acces par public .............. 237 px
 *      total ......................... 1053 px  ->  IL MANQUE 77 px
 *    Le menu deborde donc DEJA sur le logo aujourd'hui, avant tout
 *    changement : 60 px de chevauchement mesures a 1024 px, « ETUDES »
 *    imprime par-dessus la signature. C'est corrige plus bas (§4.2 bis).
 *    Meme corrige, il ne reste aucune place : porter le logo a 104 px
 *    ajouterait 156 px a une ligne qui n'en a plus.
 *
 * 3. LE DOUBLE EST POSSIBLE, ET IL EST ECRIT -- il s'applique le jour ou
 *    la barre « Acces par public » quitte cette ligne, ce qui est
 *    justement le point 1 du MEME `PROMPT-118`. Mesure, barre retiree :
 *      1024 px, logo 104 px ... 16 px de degagement, aucune superposition
 *      1440 px, logo 104 px ... 53 px de degagement
 *    La regle le dit en `:has()` plutot que d'attendre un lot de plus. Un
 *    navigateur qui ne connait pas `:has()` ignore la regle et garde
 *    52 px : le repli est le comportement d'aujourd'hui, jamais un
 *    en-tete casse.
 *
 * DEFINITION DU FICHIER, mesuree : `logo-iuac-600.webp` fait 600 x 200 px.
 *   rendu a 52 px ... 156 px de large, 312 px demandes en densite 2 -> OK
 *   rendu a 66 px ... 198 px de large, 396 px demandes en densite 2 -> OK
 *   rendu a 104 px .. 312 px de large, 624 px demandes en densite 2 ->
 *      le fichier en donne 600, soit 96 % : un ecart de 4 %, invisible.
 *      En densite 3 il n'en donne que 64 % : le trait s'adoucit.
 *   Conclusion : le fichier tient pour toutes les valeurs posees ici. Pour
 *   le double sur ecran en densite 3, il faudrait un fichier de 1200 x 400
 *   -- c'est une piece a refournir, pas une ligne de feuille de style.
 */
@media (min-width: 360px) {
  :root { --h-logo: 66px; }

  /*
   * Au defilement, sur telephone, la bande de couleur disparait mais le
   * logo restait a sa taille pleine : l'en-tete collant serait monte a
   * 129 px, soit 19 % d'un ecran de 667 px. Il redescend a 48 px -- meme
   * rapport que le palier bureau (52 -> 38, x 0,73) -- ce qui ramene
   * l'en-tete collant a 111 px, quatre pixels au-dessus de ce qu'il valait
   * avant ce lot.
   *
   * La regle vit DANS ce palier, pas au-dessus : sous 360 px le logo au
   * repos vaut 44 px, et un repli a 48 px l'aurait fait GRANDIR au
   * defilement. Defaut vu a la mesure, corrige avant depot.
   */
  .rkt-entete.est-compacte { --h-logo: 48px; }
}

/* Les trois etats sont ecrits ensemble et portes a deux classes. Le theme
   conteneur declare `button:focus` avec un fond gris fonce et du texte blanc :
   plus specifique qu'une classe seule, il reprenait la main des que le bouton
   recevait le focus, et le bouton de menu virait au gris. Defaut vu sur la
   capture mobile, puis corrige. */
.rkt .rkt-bascule-menu,
.rkt .rkt-bascule-menu:hover,
.rkt .rkt-bascule-menu:focus {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius-petit);
  padding: var(--sp-1) var(--sp-2);
  font-family: var(--f-heading);
  font-weight: 600;
  font-size: 1rem;
  color: var(--c-heading);
  cursor: pointer;
  background: transparent;
}

.rkt .rkt-bascule-menu:hover,
.rkt .rkt-bascule-menu:focus { background: var(--c-primary-voile); }

/* Le panneau de menu reste dans le flux : un panneau en position absolue sur un
   en-tete colle finit sous le contenu des que la liste s'allonge. */
.rkt-nav { display: none; }

.rkt-nav.est-ouvert {
  display: block;
  flex: 1 0 100%;
  border-top: 1px solid var(--c-bordure);
  padding: var(--sp-2) 0;
  max-height: calc(100vh - 160px);
  overflow-y: auto;
}

.rkt-nav ul { list-style: none; margin: 0; padding: 0; }
.rkt-nav li { margin-bottom: var(--sp-1); }

.rkt-nav a {
  display: block;
  padding: var(--sp-1) 0;
  font-family: var(--f-heading);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  color: var(--c-heading);
}

.rkt-nav a:hover,
.rkt-nav .current-menu-item > a {
  color: var(--c-primary);
}

.rkt-nav .sub-menu { padding-left: var(--sp-2); }

/* ── 4.2b Mega-menu, en accordeon d'abord ─────────────────────────────────── */

/*
 * Mobile d'abord : le panneau est une section du menu replie, pas un panneau
 * flottant. Le meme balisage devient un mega-menu au palier bureau, plus bas.
 */

.rkt-mega[hidden] { display: none; }

/* Le lien occupe la ligne, le bouton se pose a sa droite, le panneau passe
   dessous : trois roles, une seule rangee flexible. */
.rkt-nav .rkt-menu > li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.rkt-nav .rkt-menu > li > a { flex: 1 1 auto; }

.rkt-mega-bascule {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--c-heading);
  cursor: pointer;
}

.rkt-mega-bascule svg {
  width: 16px;
  height: 16px;
  transition: transform var(--transition);
}

.rkt-a-mega.est-ouvert > .rkt-mega-bascule svg { transform: rotate(180deg); }

/* Panneau et liste deroulante passent tous deux sous le lien : sans cette
   ligne, la flexion les remonterait a cote de lui, sur la meme rangee. */
.rkt-nav .rkt-menu > li > .sub-menu { flex: 1 0 100%; }

.rkt-mega {
  flex: 1 0 100%;
  padding-bottom: var(--sp-2);
}

/* Le conteneur ne sert qu'au palier bureau : replie, il doublerait la marge. */
.rkt-mega .rkt-conteneur {
  max-width: none;
  padding: 0;
}

.rkt-mega-colonne + .rkt-mega-colonne { margin-top: var(--sp-2); }

/*
 * REPLI SOUS 1024 px : L'ACCORDEON RESTE CE QU'IL ETAIT (`PROMPT-121`).
 *
 * Le bloc de gauche du grand panneau -- titre de rubrique, phrase, lien de
 * sortie -- ne se rend pas ici, et ce n'est pas un oubli : dans le menu replie,
 * le lien de la rubrique est deja sur la rangee, juste au-dessus du panneau.
 * Le titre en doublerait l'intitule et le lien de sortie doublerait la
 * destination. `/admission/` reste donc atteignable au telephone par ce lien-la,
 * qui n'a pas bouge.
 */
.rkt-mega-intro { display: none; }

/*
 * Une rubrique a entrees plates est coupee en deux colonnes POUR LE PALIER
 * BUREAU. Repliee, elle redevient une seule liste : sans cette ligne, un blanc
 * s'ouvrirait au milieu des huit entrees d'Admission, au point exact de la
 * coupe, et rien a l'ecran ne l'expliquerait. Une rubrique a familles, elle,
 * garde son ecart : chaque famille y porte un intitule.
 */
.rkt-mega-colonnes--plates .rkt-mega-colonne + .rkt-mega-colonne { margin-top: 0; }

.rkt-mega-titre {
  margin: 0 0 var(--sp-1);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--c-text-doux);
}

.rkt-mega-titre a { padding: 0; }

.rkt-mega ul { padding-left: var(--sp-2); }

.rkt-mega a { padding: 0.35rem 0; }

.rkt-mega-entree { display: block; font-weight: 600; }

/* ── 4.2c Acces par public ────────────────────────────────────────────────── */

/* Une seconde navigation, courte. Repliee, elle suit le menu principal ; au
   palier bureau, elle se pose a sa droite, en retrait typographique pour ne
   pas concurrencer les rubriques. */
.rkt-publics { flex: 1 0 100%; }

.rkt-publics ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  list-style: none;
  margin: 0;
  padding: var(--sp-1) 0 0;
}

.rkt-publics a {
  display: block;
  padding: var(--sp-1) 0;
  font-family: var(--f-heading);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--c-text-doux);
  text-decoration: none;
}

.rkt-publics a:hover,
.rkt-publics a:focus-visible { color: var(--c-primary-dark); }

/* ── 4.3 Panneau de recherche ─────────────────────────────────────────────── */

.rkt-recherche {
  background: var(--c-bg-alt);
  border-top: 1px solid var(--c-bordure);
  border-bottom: 1px solid var(--c-bordure);
  padding: var(--sp-2) 0;
}

.rkt-recherche[hidden] { display: none; }

.rkt-recherche-formulaire {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
}

.rkt-recherche-formulaire input[type="search"] {
  flex: 1 1 12rem;
  min-width: 0;
  padding: 0.7rem var(--sp-2);
  font-family: var(--f-body);
  font-size: 1rem;
  color: var(--c-text);
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius-petit);
}

/* ── 4.4 Bureau ───────────────────────────────────────────────────────────── */

/*
 * Le palier est 1024 px, pas 768.
 *
 * A 768 px, la carte du logo et le menu ne tiennent pas sur une ligne : le menu
 * passait dessous et la carte restait seule, enorme et detachee, sans rien a
 * cote. Mesure entre 768 et 999 px, signale par Michelot, corrige ici. Sous
 * 1024 px, l'en-tete garde donc sa disposition compacte : logo a plat, bouton
 * de menu, pilule en pleine largeur.
 */
@media (min-width: 1024px) {
  .rkt-entete-haut { order: 1; }
  .rkt-entete-bas { order: 2; }
  .rkt-recherche { order: 3; }

  .rkt-entete-haut-interieur {
    flex-wrap: nowrap;
    justify-content: flex-end;
    gap: var(--sp-3);
    min-height: 48px;
    padding-top: 0;
    padding-bottom: 0;
  }

  /* `.rkt-lien-haut--gauche` a ete retiree avec le courriel qu'elle calait
     (`PROMPT-118`, point 3). Plus rien ne porte cette classe : la bande est
     desormais alignee a droite par son seul `justify-content: flex-end`. */

  /* Les acces par public se rangent a droite du menu, sur la meme ligne. */
  .rkt-publics {
    flex: 0 0 auto;
    margin-left: var(--sp-2);
    padding-left: var(--sp-2);
    border-left: 1px solid var(--gray-300);
  }

  .rkt-publics ul { gap: var(--sp-1); padding: 0; flex-wrap: nowrap; }
  .rkt-publics a { font-size: 0.78rem; white-space: nowrap; }

  .rkt .rkt-entete-haut a.rkt-pilule {
    order: 0;
    flex: 0 0 auto;
    padding: 0.4rem var(--sp-2);
  }

  /* Carre plus fonce, colle au bord du conteneur : la marge negative annule
     exactement la marge interieure du conteneur, sans debordement lateral. */
  .rkt .rkt-recherche-bascule,
  .rkt .rkt-recherche-bascule:hover,
  .rkt .rkt-recherche-bascule:focus {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    margin-right: calc(-1 * var(--sp-3));
    border: 0;
    background: var(--c-primary-dark);
    color: #ffffff;
    cursor: pointer;
    transition: background var(--transition);
  }

  .rkt .rkt-recherche-bascule:hover { background: var(--c-primary-light); }
  .rkt-recherche-bascule svg { width: 18px; height: 18px; }

  .rkt-entete-bas-interieur { flex-wrap: nowrap; }

  /*
   * La carte du logo est CONTENUE dans la bande blanche, sans deborder ni en
   * haut ni en bas. Elle chevauchait les deux limites a la fois, ce qui
   * n'appartenait a aucune grille : mesure a 10 px de debordement de chaque
   * cote, signale par Michelot.
   *
   * Le calcul est celui du prompt : hauteur de carte = hauteur de bande moins
   * deux fois la marge interieure, la meme en haut et en bas.
   *   bande 88 px, marge 14 px, carte 60 px, logo 44 px.
   * La bande passe de 64 a 88 px pour que le logo reste lisible une fois
   * contenu : la contenir sans l'agrandir l'aurait reduit a 32 px de haut.
   */
  /*
   * Le logo occupait 50 % de sa bande au bureau, contre 55 a 70 % attendus : il
   * ne debordait plus, il se noyait. Il passe a 52 px dans une bande de 76 px,
   * soit 68 %. La regle de non-debordement du CR-28 reste entiere.
   */
  :root { --h-logo: 52px; --marge-logo: 12px; }

  /*
   * LE DOUBLE EXACT, DES QUE LA LIGNE A LA PLACE (`PROMPT-118`, point 2).
   *
   * La seule chose qui empeche le logo de doubler est la barre « Acces par
   * public » posee a droite du menu : 205 px, plus 32 px de filet et de
   * marge. Son retrait est le POINT 1 DU MEME PROMPT, deja tranche par
   * Michelot et encore en attente d'une ecriture en base.
   *
   * Plutot que d'attendre un lot de plus, la condition est ecrite : sans
   * cette barre dans l'en-tete, le logo passe a 104 px, soit exactement le
   * double des 52 px d'aujourd'hui. Mesure, barre masquee :
   *   1024 px -> 16 px de degagement entre le logo et la premiere rubrique
   *   1440 px -> 53 px
   *
   * `:has()` est ici le bon outil parce que la condition EST une condition
   * de contenu : « cette ligne porte-t-elle encore trois entrees de plus ».
   * Un navigateur qui ne la connait pas ignore ces deux regles et garde
   * 52 px -- le repli est l'etat actuel, pas un en-tete casse.
   *
   * ⚠ Ne pas retirer la barre « Acces par public » sans relire le
   * `SIGNALEMENT-T2-vers-T3-le-118-orpheline-trois-pages` : trois pages
   * n'ont aucun autre chemin, elles doivent d'abord entrer au pied de page.
   */
  /*
   * `PROMPT-168`. 104px jugee trop grande une fois vue en production par
   * Michelot -- ramenee a 76px, LA VALEUR DEJA EN USAGE JUSTE EN DESSOUS
   * POUR L'ETAT DEFILE DE CE MEME SELECTEUR, pas une valeur inventee pour ce
   * lot. Consequence assumee et voulue : le logo ne change plus de taille
   * entre l'etat au repos et l'etat defile a ce palier, en l'absence de la
   * barre « Accès par public ».
   */
  .rkt-entete:not(:has(.rkt-publics)) { --h-logo: 76px; }
  .rkt-entete.est-compacte:not(:has(.rkt-publics)) { --h-logo: 76px; }

  .rkt-marque {
    height: var(--h-logo);
    margin-top: 0;
    margin-bottom: 0;
    padding: 0 var(--sp-2) 0 0;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
    position: relative;
    z-index: 2;
  }

  /* Meme portee que la regle des trois etats plus haut : ecrite a une seule
     classe, elle perdait, et le bouton de menu restait affiche sur le bureau.
     Regression introduite par la correction du focus, vue sur la capture. */
  .rkt .rkt-bascule-menu { display: none; }

  /* `.est-ouvert` est repris ici : sans cela, un menu laisse ouvert sur mobile
     puis redimensionne garderait la disposition en panneau sur le bureau. */
  .rkt-nav,
  .rkt-nav.est-ouvert {
    display: block;
    flex: 0 1 auto;
    min-width: 0;
    margin-left: auto;
    max-height: none;
    overflow: visible;
    border-top: 0;
    padding: 0;
  }

  .rkt-nav ul {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-end;
    align-items: stretch;
  }

  .rkt-nav li { margin-bottom: 0; position: relative; }

  /* Filet vertical entre les entrees : une bordure, pas un caractere. */
  .rkt-nav > ul > li + li { border-left: 1px solid var(--gray-300); }

  /* Six rubriques plus les acces par public : la bande doit tenir sur UNE
     ligne. Le calage horizontal et l'interlettrage se resserrent ici, une
     seule fois, plutot que de laisser le menu se replier en deux rangees. */
  .rkt-nav > ul > li > a {
    position: relative;
    padding: 0.5rem 0.7rem;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--c-heading);
  }

  /* Soulignement epais a l'accent, pour le survol et la page courante. La teinte
     est celle du filet, assombrie jusqu'a 3:1 sur blanc : un indicateur d'etat
     doit se voir. Les boutons et les chiffres gardent l'accent de charte. */
  .rkt-nav > ul > li > a::after {
    content: '';
    position: absolute;
    left: 0;
    right: 100%;
    bottom: 0;
    height: 3px;
    background: var(--c-accent-filet, var(--c-accent));
    transition: right var(--transition);
  }

  .rkt-nav > ul > li > a:hover::after,
  .rkt-nav > ul > li.current-menu-item > a::after,
  .rkt-nav > ul > li.current-menu-ancestor > a::after,
  .rkt-nav > ul > li.current-menu-parent > a::after { right: 0; }

  /* Le filet orange seul ne suffit pas a signaler l'etat : la couleur du texte
     change aussi, pour ne pas dependre d'un unique indice visuel. */
  .rkt-nav > ul > li > a:hover,
  .rkt-nav > ul > li.current-menu-item > a,
  .rkt-nav > ul > li.current-menu-ancestor > a,
  .rkt-nav > ul > li.current-menu-parent > a { color: var(--c-primary-dark); }

  .rkt-nav .sub-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 15rem;
    background: var(--c-bg);
    border: 1px solid var(--c-bordure);
    border-radius: 0 0 var(--radius-petit) var(--radius-petit);
    box-shadow: var(--shadow);
    padding: var(--sp-1);
    z-index: 80;
  }

  /* Les dernieres entrees sont pres du bord : leur panneau s'ouvre vers la
     gauche, sinon il sort de la fenetre et la page defile lateralement. */
  .rkt-nav > ul > li:last-child .sub-menu,
  .rkt-nav > ul > li:nth-last-child(2) .sub-menu { left: auto; right: 0; }

  .rkt-nav .sub-menu a {
    padding: 0.45rem var(--sp-1);
    font-size: 0.95rem;
    text-transform: none;
    letter-spacing: 0;
  }

  .rkt-nav .sub-menu a:hover { color: var(--c-primary-dark); }

  .rkt-nav li:hover > .sub-menu,
  .rkt-nav li:focus-within > .sub-menu { display: block; }

  /* ── Mega-menu au palier bureau ──────────────────────────────────────── */

  /*
   * Le panneau prend toute la largeur de l'en-tete, pas celle de son entree.
   * Il se cale donc sur la bande blanche : l'entree passe en position statique,
   * sinon elle servirait de reference et le panneau ferait 120 px de large.
   */
  .rkt-entete-bas { position: relative; }

  .rkt-nav > ul > li.rkt-a-mega { position: static; }

  /*
   * LE GRAND PANNEAU (`PROMPT-121`). Aplat `--c-primary` sur toute la largeur
   * de la fenetre : `.rkt-entete-bas` est la bande blanche pleine largeur, et
   * `left: 0; right: 0` s'y cale. La bande de couleur du haut de l'en-tete est
   * deja `--c-primary` avec `#ffffff` par-dessus : le panneau reprend cette
   * convention du produit, il n'en invente pas une seconde.
   */
  .rkt-mega {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 90;
    padding: var(--sp-4) 0;
    background: var(--c-primary);
    color: #ffffff;
    border-top: 0;
    border-bottom: 3px solid var(--c-accent);
    box-shadow: var(--shadow);
  }

  .rkt-mega .rkt-conteneur {
    max-width: var(--w-content);
    padding: 0 var(--sp-3);
  }

  /*
   * FILET DE SECURITE, ET IL EST DELIBERE. `.rkt a` (0,1,1) et `.rkt-nav a`
   * (0,1,1) posent une couleur SOMBRE sur tout lien du menu. Sur cet aplat, un
   * lien qui echapperait aux regles nommees plus bas sortirait en bleu fonce
   * sur bleu. Cette ligne, en (0,2,1), les couvre tous d'avance -- y compris
   * ceux qu'un lot futur ajoutera au panneau.
   */
  .rkt-nav .rkt-mega a { color: #ffffff; }

  /* Un intitule de famille peut etre une destination chez un autre client :
     souligne, parce que le blanc ne le distingue plus du texte voisin. */
  .rkt-nav .rkt-mega .rkt-mega-titre a {
    padding: 0;
    color: #ffffff;
    text-decoration: underline;
    text-underline-offset: 3px;
  }

  /*
   * DEUX ZONES, PAS UNE GRILLE DE COLONNES EGALES : a gauche le bloc de la
   * rubrique sur 300 px, a droite ses entrees. `minmax(0, 1fr)` et non `1fr` --
   * une piste `1fr` prend pour plancher la largeur de son contenu, et un
   * intitule long y aurait pousse la seconde zone au-dela du conteneur.
   */
  .rkt-mega-grille {
    display: grid;
    grid-template-columns: 18.75rem minmax(0, 1fr); /* 18.75rem = 300 px */
    gap: var(--sp-4);
    align-items: start;
    text-align: left;
  }

  /* ── Le bloc de gauche : titre, phrase, sortie ───────────────────────── */

  .rkt-mega .rkt-mega-intro { display: block; }

  /*
   * `.rkt p` et `.rkt a` sont en (0,1,1) et ecrasent une classe seule (0,1,0) :
   * sept morsures a ce jour dans ce chantier, dont un texte sorti a 1,00:1 sur
   * un aplat de sa propre couleur. Sur un panneau plein de liens blancs, c'est
   * exactement le terrain du piege. TOUTES les regles qui suivent portent donc
   * au moins deux classes.
   */
  .rkt-mega .rkt-mega-rubrique {
    margin: 0 0 var(--sp-1);
    font-family: var(--f-heading);
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.15;
    text-transform: none;
    letter-spacing: 0;
    color: #ffffff;
  }

  /*
   * La phrase vient du champ Description de l'entree de menu. Vide, elle n'est
   * pas rendue du tout -- pas cachee : le titre remonte alors contre le lien de
   * sortie, sans blanc a expliquer.
   *
   * Blanc PLEIN, pas un blanc voile. Un `rgba(255,255,255,.85)` sur cette
   * charte tombe a 4,81:1, soit trois dixiemes au-dessus du seuil : la moindre
   * retouche de la couleur du client le ferait passer sous 4,5:1 sans que
   * personne le voie. La hierarchie se fait a la taille, pas a l'opacite.
   */
  .rkt-mega .rkt-mega-phrase {
    margin: 0 0 var(--sp-2);
    font-family: var(--f-body);
    font-size: 0.95rem;
    font-weight: 400;
    line-height: 1.5;
    color: #ffffff;
  }

  /*
   * LE LIEN DE SORTIE. Sans lui, le panneau recouvre l'entree de la rubrique et
   * sa page mere devient inatteignable depuis le menu. Souligne, parce qu'un
   * lien blanc sur un aplat n'a aucune couleur pour se distinguer du texte qui
   * l'entoure.
   */
  .rkt-nav .rkt-mega .rkt-mega-sortie {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0;
    font-family: var(--f-heading);
    font-size: 0.95rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    color: #ffffff;
    text-decoration: underline;
    text-underline-offset: 4px;
  }

  .rkt-mega .rkt-mega-sortie svg {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    transition: transform var(--transition);
  }

  .rkt-nav .rkt-mega .rkt-mega-sortie:hover svg,
  .rkt-nav .rkt-mega .rkt-mega-sortie:focus-visible svg { transform: translateX(3px); }

  /* ── Les colonnes d'entrees ──────────────────────────────────────────── */

  /*
   * `auto-fit` replie les pistes vides : deux colonnes pour une rubrique plate,
   * trois pour une rubrique a trois familles, sans qu'un compte soit ecrit
   * nulle part. Le nombre de colonnes se lit donc du menu, comme tout le reste.
   *
   * LA MESURE DE 12rem N'EST PAS UN GOUT, ELLE EST CALCULEE AU PALIER LE PLUS
   * ETROIT. A 1024 px, le conteneur fait 976 px, moins 300 px de bloc de gauche
   * et 32 px de gouttiere : il reste 644 px pour les colonnes. Trois pistes de
   * 14rem (224 px) plus deux gouttieres de 32 px demandaient 736 px : la
   * troisieme famille de `L'Institut` passait a la ligne, et le lot demande
   * UNE COLONNE PAR FAMILLE. Trois pistes de 12rem plus deux gouttieres de
   * 24 px font 624 px, et tiennent avec 20 px de reste.
   */
  .rkt-mega .rkt-mega-colonnes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: var(--sp-3);
  }

  /*
   * PLUS DE FILET ENTRE LES COLONNES. Il etait en `--c-bordure`, un gris de
   * champ de saisie : sur un aplat de charte il est soit invisible, soit un
   * gris etranger. Le lot ne nomme qu'un seul geste graphique, la puce carree.
   */
  .rkt-mega .rkt-mega-colonne + .rkt-mega-colonne {
    margin-top: 0;
    padding-left: 0;
    border-left: 0;
  }

  /* La regle de menu du palier bureau met TOUTES les listes de la navigation
     en flexion alignee a droite. Dans un panneau, elle poussait chaque entree
     contre le bord de sa colonne : le panneau reprend une liste ordinaire. */
  .rkt-mega ul {
    display: block;
    padding-left: 0;
    text-align: left;
  }

  .rkt-mega li + li { margin-top: 0.35rem; }

  .rkt-mega .rkt-mega-titre {
    margin: 0 0 var(--sp-1);
    font-family: var(--f-heading);
    font-size: var(--fs-meta);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #ffffff;
  }

  /*
   * LA PUCE CARREE, seul geste graphique du panneau. Elle est posee en contenu
   * genere : purement decorative, jamais lue, et le libelle du lien reste
   * exactement l'intitule saisi dans le menu.
   *
   * `li > a` et non `a` : l'intitule d'une famille est un `p`, il ne prend pas
   * de puce. L'alignement se fait sur la LIGNE DE BASE du texte, ce qui la tient
   * juste sur une entree qui passe a deux lignes.
   */
  .rkt-nav .rkt-mega-colonnes li > a {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    padding: 0.35rem 0;
    font-size: 0.95rem;
    text-transform: none;
    letter-spacing: 0;
    text-decoration: none;
    color: #ffffff;
  }

  .rkt-nav .rkt-mega-colonnes li > a::before {
    content: '';
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    background: var(--c-accent);
  }

  /*
   * SURVOL : SOULIGNEMENT, PAS CHANGEMENT DE COULEUR. La regle d'avant passait
   * l'entree survolee a `--c-primary-dark` -- une teinte plus foncee de l'aplat
   * sur lequel elle est maintenant posee. Elle aurait produit un texte presque
   * illisible sur sa propre couleur de fond, le defaut exact deja paye au
   * `CR-120`. Le blanc ne bouge donc plus, c'est le soulignement qui repond.
   */
  .rkt-nav .rkt-mega-colonnes li > a:hover .rkt-mega-entree,
  .rkt-nav .rkt-mega-colonnes li > a:focus-visible .rkt-mega-entree {
    text-decoration: underline;
    text-underline-offset: 3px;
  }

  /* Sur l'aplat de charte, un contour de la meme couleur ne se voit pas : meme
     remede que pour la bande de couleur de l'en-tete et le pied de page. */
  .rkt-mega :focus-visible { outline-color: #ffffff; }

  /* Le bouton reprend la hauteur de la rangee pour rester sur la ligne du
     libelle, et son filet de survol ne doit pas se declencher : il n'est pas
     une destination. */
  .rkt-mega-bascule {
    width: 1.75rem;
    height: auto;
    align-self: stretch;
    margin-left: calc(-1 * var(--sp-1));
    margin-right: var(--sp-1);
  }

  /*
   * LE LIEN ET SON BOUTON RESTENT SUR UNE SEULE RANGEE (`PROMPT-126`).
   *
   * DEFAUT MESURE EN LIGNE le 2026-07-30, sur toutes les pages, dans la bande
   * 1024-1048 px : le chevron passait SOUS son libelle et les entrees se
   * retrouvaient a deux hauteurs (86 px et 94 px), la rangee montant de 36 a
   * 52 px de haut.
   *
   * Les deux lignes fautives sont celles de §4.2b, ecrites pour le MOBILE :
   * `flex-wrap: wrap` sur l'entree, pour que le panneau passe sous le lien, et
   * `flex: 1 1 auto` sur le lien, pour qu'il occupe la rangee de l'accordeon.
   * Rien ne les reprenait au palier bureau. Le lien y reclamait donc tout
   * l'espace de son entree, et la marge restante pour le bouton etait NULLE a
   * TOUTES les largeurs -- mesure : entree 127 px = lien 98 + bouton 28 + 1.
   * Au-dessus de 1050 px la barre ne tenait donc pas parce qu'elle allait
   * bien, elle tenait a un pixel pres. Sous 1050 px, la liste depassait de
   * 19 px, les entrees se comprimaient, et le `wrap` renvoyait le bouton a la
   * ligne.
   *
   * LA REGLE PORTE SUR TOUTE ENTREE, PAS SUR LES SEULES RUBRIQUES A PANNEAU.
   * Le bouton est pose des qu'une rubrique a des enfants ; le grand panneau,
   * lui, depend d'un seuil reglable. Chez un client dont une rubrique aurait
   * trois entrees, le bouton serait la SANS panneau : une regle ecrite sur
   * `.rkt-a-mega` l'aurait manque.
   *
   * `.rkt-mega` est en `position: absolute` quinze lignes plus haut, donc hors
   * du flux : `nowrap` ne le remonte pas a cote du lien. Verifie au navigateur
   * avant d'ecrire ces lignes -- valeur calculee `absolute` sur les quatre
   * panneaux. Le palier mobile n'est pas touche : il garde son `wrap`, dont
   * l'accordeon depend.
   */
  .rkt-nav .rkt-menu > li { flex-wrap: nowrap; }

  .rkt-nav .rkt-menu > li > a { flex: 0 0 auto; }
}

/* ── 4.2 bis Le point ou la ligne d'en-tete ne rentre plus ────────────────
 *
 * DEFAUT MESURE EN LIGNE, ANTERIEUR A CE LOT, trouve en faisant la
 * verification que le `PROMPT-118` rend obligatoire (« la barre de
 * navigation reste sur une ligne a 1024 px, sans que les six entrees se
 * chevauchent »). ELLE NE LA RESPECTAIT PAS.
 *
 *   a 1024 px, largeur utile 976 px :
 *     carte du logo .............. 172 px
 *     les six rubriques .......... 628 px  (+ 16 px de gouttiere)
 *     acces par public ........... 237 px
 *     total ...................... 1053 px
 *   `.rkt-nav` est en `flex: 0 1 auto` et sa liste en `flex-wrap: nowrap` :
 *   la liste ne se replie pas, elle DEBORDE vers la gauche, sous la carte
 *   du logo. Chevauchement mesure : 60 px. A l'ecran, « ETUDES » s'imprime
 *   par-dessus « Institut Universitaire Afrique Caraibes ».
 *
 *   La bande fautive est etroite mais reelle : de 1024 px, ou la
 *   disposition bureau commence, jusqu'a environ 1100 px, ou le conteneur
 *   devient assez large. Au-dela, 16 px de degagement suffisent.
 *
 * LE REMEDE EST LE MOINDRE POSSIBLE : les six entrees se resserrent sur
 * cette seule bande -- marge horizontale 0,7 -> 0,4 rem et corps 0,8 ->
 * 0,75 rem. Rien au-dela de 1199 px, rien en dessous de 1024 px, rien sur
 * le contenu. Mesure apres correction :
 *     1024 px ... liste 551 px au lieu de 627 -> 16 px de DEGAGEMENT
 *     1100 px ... 20 px de degagement
 *     1199 px ... 60 px de degagement
 *
 * Ce n'est pas ce que le prompt demandait ; c'est ce qu'il fallait pour
 * pouvoir certifier ce qu'il demandait de verifier. Signale au
 * compte-rendu comme un ajout, avec sa mesure.
 */
@media (min-width: 1024px) and (max-width: 1199px) {
  .rkt-nav > ul > li > a {
    padding-left: 0.4rem;
    padding-right: 0.4rem;
    font-size: 0.75rem;
  }

  /*
   * LE DEGAGEMENT MESURE PLUS HAUT A ETE MANGE PAR LES CHEVRONS (`PROMPT-126`).
   *
   * Le calcul de 2026-07-26 donnait 551 px de liste a 1024 px, soit 16 px de
   * degagement. Le `PROMPT-121` a pose un bouton de 28 px sur QUATRE entrees :
   * la liste est remontee a 651 px pour 632 px disponibles. Le `flex-wrap: wrap`
   * absorbait ce depassement en renvoyant le bouton a la ligne -- c'est-a-dire
   * qu'il CACHAIT le manque de place derriere un defaut d'alignement.
   *
   * Le `nowrap` pose au palier bureau interdit ce repli, et le depassement
   * redevient ce qu'il est : un debordement vers la gauche, sous la carte du
   * logo. MESURE, avec le seul `nowrap` et rien d'autre : degagement -3 px a
   * 1024 px, soit le defaut du `PROMPT-118` reintroduit. La correction serait
   * donc restee a mi-chemin.
   *
   * LE REMEDE EST LE MOINDRE POSSIBLE, et il porte sur ce que le `121` a
   * ajoute, pas sur ce que le `118` avait deja resserre : le bouton passe de
   * 1,75 a 1,25 rem et sa marge droite de 0,5 a 0,25 rem, sur cette seule
   * bande. Le pictogramme fait 16 px : il tient dans les 20 px du bouton.
   *
   * MESURE APRES CORRECTION, degagement sous la carte du logo :
   *     1024 px ... 45 px   (au lieu de -3)
   *     1040 px ... 61 px
   *     1100 px ... 121 px
   *     1199 px ... 161 px
   *
   * La regle vise `.rkt-mega-bascule` -- le BOUTON -- et non `.rkt-a-mega`,
   * pour la meme raison qu'au palier bureau : le bouton peut exister sans le
   * panneau. Deux classes, `(0,2,0)`, pour passer devant la regle du palier
   * bureau qui n'en porte qu'une.
   */
  .rkt-nav .rkt-mega-bascule {
    width: 1.25rem;
    margin-right: 0.25rem;
  }
}

/* ── 4.5 Repli au defilement ──────────────────────────────────────────────── */

/*
 * Passe ~120 px, l'en-tete se compacte : la bande de couleur disparait, la carte
 * du logo redescend a plat et retrecit, le menu tient sur une ligne. La
 * transition est annulee par la regle `prefers-reduced-motion` globale.
 */

.rkt-entete.est-compacte .rkt-entete-haut { display: none; }

/* La hauteur reste pilotee par la variable, y compris une fois compacte : une
   valeur en dur ici ecrasait le reglage et ramenait le logo a 34 px, soit 53 %
   de sa bande en mobile. */
.rkt-entete.est-compacte .rkt-marque img {
  transition: height var(--transition);
}

@media (min-width: 1024px) {
  /* Meme regle une fois compacte, en plus serre : logo 38, marge 10, bande 58. */
  .rkt-entete.est-compacte { --h-logo: 38px; --marge-logo: 10px; }

  .rkt-entete.est-compacte .rkt-marque {
    height: var(--h-logo);
    transition: height var(--transition);
  }
}

/* ══ 5. Boutons ═════════════════════════════════════════════════════════════ */

/* La specificite est portee a `.rkt .rkt-bouton` : sans cela, la regle
   generique `.rkt a` l'emporte et le texte du bouton reprend la couleur des
   liens, ce qui detruit le contraste. Defaut mesure puis corrige. */
.rkt .rkt-bouton,
.rkt-bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  border-radius: var(--radius-petit);
  border: 2px solid transparent;
  font-family: var(--f-heading);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.3;
  text-decoration: none;
  cursor: pointer;
  background: var(--c-primary);
  color: var(--c-sur-primary);
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
}

.rkt .rkt-bouton:hover {
  background: var(--c-primary-dark);
  color: var(--c-sur-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

/* L'accent porte du texte : c'est la teinte assombrie, mesuree au niveau AA,
   qui sert de fond. La teinte de charte reste aux usages non textuels. */
.rkt .rkt-bouton--accent { background: var(--c-accent-dark); color: var(--c-sur-accent); }
.rkt .rkt-bouton--accent:hover { background: var(--c-primary-dark); color: var(--c-sur-primary); }

.rkt .rkt-bouton--secondaire {
  background: transparent;
  color: var(--c-primary-dark);
  border-color: var(--c-primary);
}

.rkt .rkt-bouton--secondaire:hover { background: var(--c-primary-voile); color: var(--c-primary-dark); }

/* Sur fond sombre, le bouton fantome se decline en blanc. */
.rkt .rkt-bouton--clair {
  background: transparent;
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.7);
}

.rkt .rkt-bouton--clair:hover {
  background: rgba(255, 255, 255, 0.12);
  color: #ffffff;
}

.rkt-bouton--large { width: 100%; }

@media (min-width: 768px) {
  .rkt-bouton--large { width: auto; padding: 0.9rem 1.9rem; font-size: 1.05rem; }
}

/* ══ 6. Fil d'Ariane ════════════════════════════════════════════════════════ */

.rkt-fil {
  background: var(--c-bg-alt);
  border-bottom: 1px solid var(--c-bordure);
  font-size: var(--fs-meta);
}

.rkt-fil ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0.6rem 0;
}

.rkt-fil li { display: flex; gap: 0.4rem; align-items: center; }
.rkt-fil a { color: var(--c-text-doux); }
.rkt-fil [aria-current="page"] { color: var(--c-text); }
.rkt-fil-sep { color: var(--c-text-doux); }

/* Dans une banniere sombre, le fil passe en blanc et perd son fond. */
.rkt-banniere .rkt-fil {
  background: transparent;
  border-bottom: 0;
}

.rkt-banniere .rkt-fil a,
.rkt-banniere .rkt-fil [aria-current="page"],
.rkt-banniere .rkt-fil-sep { color: rgba(255, 255, 255, 0.8); }

/* ══ 7. Cartes ══════════════════════════════════════════════════════════════ */

.rkt-carte {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  overflow: hidden;
  height: 100%;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow);
  transition: transform var(--transition), box-shadow var(--transition);
}

.rkt-carte:hover,
.rkt-carte:focus-within {
  transform: translateY(-4px);
  box-shadow: var(--shadow-fort);
}

.rkt-carte-media {
  aspect-ratio: 16 / 10;
  background: var(--c-bg-alt);
  overflow: hidden;
}

.rkt-carte-media img { width: 100%; height: 100%; object-fit: cover; }

/*
 * `PROMPT-165`. Modificateur SCOPE aux photos de personnes, PAS un
 * changement de `.rkt-carte-media` global : ce composant sert aussi des
 * programmes, des actualites et des ressources dont la photographie est
 * editoriale, deja en 16:10 -- une photo carree de personne (1080x1080
 * mesure) force dans ce cadre perdait le visage sur ~400px, coupe par
 * `object-fit: cover`. `object-fit: cover` reste en service : une photo pas
 * parfaitement carree a la source se recadre proprement, sans deformation.
 */
.rkt-carte--personne .rkt-carte-media { aspect-ratio: 1 / 1; }

/*
 * Sans image, la carte ne reste jamais nue : un en-tete en degrade bleu porte
 * le code officiel. C'est le defaut le plus visible de la version 1, ou une
 * carte se reduisait a une bordure et un lien souligne.
 */
.rkt-carte-chapeau {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-2);
  min-height: 84px;
  background: linear-gradient(135deg, var(--c-primary) 0%, var(--c-primary-dark) 100%);
  color: #ffffff;
}

.rkt-carte-code {
  font-family: var(--f-heading);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.02em;
  margin: 0;
}

.rkt-carte-chapeau .rkt-badge {
  background: rgba(255, 255, 255, 0.18);
  color: #ffffff;
}

.rkt-carte-corps {
  padding: var(--sp-3) var(--sp-2);
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  flex: 1;
}

.rkt-surtitre { color: var(--c-primary); }

.rkt-carte-titre {
  font-size: var(--fs-h3);
  font-weight: 600;
  margin: 0;
  color: var(--c-heading);
}

.rkt-carte-titre a {
  text-decoration: none;
  color: inherit;
}

/* Toute la carte est cliquable : le titre n'a donc pas a etre souligne, et la
   zone de clic ne se limite plus a une ligne de texte. */
.rkt-carte-titre a::after {
  content: '';
  position: absolute;
  inset: 0;
}

.rkt-carte:hover .rkt-carte-titre { color: var(--c-primary); }

.rkt-carte-extrait {
  margin: 0;
  color: var(--c-text-doux);
  font-size: 1rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.rkt-carte-meta {
  margin: var(--sp-2) 0 0;
  padding-top: var(--sp-2);
  border-top: 1px solid var(--c-bordure);
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.rkt-carte-meta:empty { display: none; }

.rkt-badge {
  display: inline-block;
  align-self: flex-start;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: var(--c-primary-voile);
  color: var(--c-primary-dark);
  font-family: var(--f-heading);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.rkt-badge--accent {
  background: var(--c-accent-dark);
  color: var(--c-sur-accent);
}

/* Cartes d'acces par cycle : icone, compte reel, fleche. */
.rkt-carte--cycle {
  padding: var(--sp-3) var(--sp-2);
  gap: var(--sp-1);
  border-top: 3px solid transparent;
}

.rkt-carte--cycle:hover { border-top-color: var(--c-accent); }

.rkt-carte-icone {
  width: 40px;
  height: 40px;
  color: var(--c-primary);
  margin-bottom: var(--sp-1);
}

.rkt-carte-icone svg { width: 100%; height: 100%; display: block; }

.rkt-carte--cycle .rkt-carte-titre { font-size: 1.15rem; }

.rkt-carte-compte {
  margin: 0;
  color: var(--c-text-doux);
  font-size: 1rem;
}

.rkt-carte-fleche {
  margin-top: auto;
  padding-top: var(--sp-2);
  color: var(--c-primary);
  font-family: var(--f-heading);
  font-weight: 600;
  font-size: var(--fs-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* ══ 8. Hero et blocs de la page d'accueil ══════════════════════════════════ */

/*
 * Le hero porte le degrade de la couleur principale, avec un motif geometrique
 * discret dessine en CSS. Pas de photographie : le produit ne peut pas inventer
 * d'image, et une photo generique vaut moins que rien.
 */
.rkt-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--c-primary) 0%, var(--c-primary-dark) 100%);
  color: #ffffff;
  padding: var(--sp-8) 0 calc(var(--sp-8) + 40px);
  min-height: 340px;
  display: flex;
  align-items: center;
}

.rkt-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.08;
  background-image:
    radial-gradient(circle at 82% 18%, #ffffff 0, #ffffff 120px, transparent 121px),
    radial-gradient(circle at 92% 62%, #ffffff 0, #ffffff 62px, transparent 63px),
    repeating-linear-gradient(135deg, #ffffff 0 1px, transparent 1px 22px);
  pointer-events: none;
}

.rkt-hero > * { position: relative; }

.rkt-hero-grille { display: grid; gap: var(--sp-3); }

/* La specificite doit atteindre celle de `.rkt h1`, sinon le titre reprend le
   bleu-noir des titres et devient illisible sur le degrade. Meme piege que
   celui des boutons, mesure puis corrige. */
.rkt .rkt-hero-titre,
.rkt-hero h1 {
  font-size: var(--fs-h1);
  color: #ffffff;
  margin-bottom: var(--sp-2);
  max-width: 18ch;
}

.rkt-hero-sous-titre {
  font-size: 1.15rem;
  color: rgba(255, 255, 255, 0.92);
  max-width: 52ch;
  margin-bottom: var(--sp-3);
}

/* Hero raccourci : le titre descend d'un cran en mobile pour continuer a tenir
   sans troncature dans les 300 px. Le prompt le demande dans cet ordre : la
   taille du texte cede, jamais la hauteur. */
.rkt .rkt-hero--diaporama .rkt-hero-titre {
  font-size: 28px;
  margin-bottom: var(--sp-1);
}

.rkt-hero--diaporama .rkt-hero-sous-titre {
  font-size: 1rem;
  margin-bottom: var(--sp-2);
}

.rkt-hero--diaporama .rkt-hero-texte { margin-bottom: var(--sp-2); }

@media (min-width: 768px) {
  .rkt .rkt-hero--diaporama .rkt-hero-titre { font-size: var(--fs-h1); }
  .rkt-hero--diaporama .rkt-hero-sous-titre { font-size: 1.15rem; }
}

@media (min-width: 1024px) {
  .rkt-hero { min-height: 420px; }
  .rkt-hero-grille { grid-template-columns: 3fr 2fr; align-items: center; }
  .rkt-hero-sous-titre { font-size: 1.25rem; }
}

/* ── 14.1 Hero en diaporama ───────────────────────────────────────────────── */

/*
 * Le diaporama remplace le degrade quand des diapositives sont publiees. Le
 * degrade reste dessous : tant qu'une image n'est pas arrivee, le hero a deja
 * sa couleur, jamais un rectangle blanc.
 *
 * La hauteur est fixee ici, jamais deduite de l'image. C'est ce qui garantit
 * qu'aucun decalage de mise en page ne se produit au chargement.
 */
.rkt-hero--diaporama {
  height: clamp(300px, 38vw, 460px);
  min-height: 300px;
  padding: 0;
  align-items: center;
}

/* Le motif geometrique du hero de repli n'a pas de sens sur une photographie. */
.rkt-hero--diaporama::before { content: none; }

.rkt-diapos {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.rkt-diapo {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 600ms ease;
}

.rkt-diapo.est-active { opacity: 1; }

/* Une diapositive non armee ne pese rien : elle n'est pas dans la mise en page,
   donc son image `loading="lazy"` n'est pas telechargee. */
.rkt-diapo[hidden] { display: none; }

.rkt-diapo-lien { display: block; height: 100%; }

.rkt .rkt-diapo-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  max-width: none;
}

/*
 * Voile de lisibilite. Le triplet permet de faire varier l'opacite a partir du
 * jeton de charte ; le repli sert quand aucune couleur n'est configuree.
 *
 * Mobile : le texte occupe toute la largeur, le voile aussi. Bureau : le voile
 * est dense a gauche, ou se pose le texte, et s'efface vers la droite pour
 * laisser voir la photographie.
 */
.rkt-diapos-voile {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.82) 0%,
    rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.94) 100%
  );
}

.rkt-hero--diaporama .rkt-hero-contenu {
  position: relative;
  z-index: 2;
  width: 100%;
}

.rkt-hero-texte { margin-bottom: var(--sp-3); }

.rkt-hero--diaporama .rkt-hero-sous-titre[hidden] { display: none; }

/* ── Commandes ────────────────────────────────────────────────────────────── */

.rkt-diapos-commandes {
  position: absolute;
  left: 0;
  right: 0;
  /*
   * Mobile : les commandes se posent EN HAUT a droite. En bas, le bouton d'appel
   * a l'action prend toute la largeur : les commandes lui passaient dessus et le
   * rendaient illisible. Defaut vu sur la capture 390, puis corrige.
   */
  top: var(--sp-2);
  bottom: auto;
  /* Mobile : en haut a droite. Le bouton d'appel a l'action occupe toute la
     largeur en bas du hero, les commandes lui passaient dessus. */
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-1);
}

@media (max-width: 767px) {
  .rkt .rkt-diapo-bouton,
  .rkt .rkt-diapo-bouton:hover,
  .rkt .rkt-diapo-bouton:focus { width: 34px; height: 34px; }

  .rkt-diapo-bouton svg { width: 17px; height: 17px; }

  .rkt .rkt-diapo-point,
  .rkt .rkt-diapo-point:hover,
  .rkt .rkt-diapo-point:focus { width: 10px; height: 10px; }
}

.rkt .rkt-diapo-bouton,
.rkt .rkt-diapo-bouton:hover,
.rkt .rkt-diapo-bouton:focus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.35);
  color: #ffffff;
  cursor: pointer;
  transition: background var(--transition);
}

.rkt .rkt-diapo-bouton:hover,
.rkt .rkt-diapo-bouton:focus { background: rgba(0, 0, 0, 0.6); }

.rkt-diapo-bouton svg { width: 20px; height: 20px; }

.rkt-diapos-points {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin-right: var(--sp-1);
}

.rkt .rkt-diapo-point,
.rkt .rkt-diapo-point:hover,
.rkt .rkt-diapo-point:focus {
  width: 12px;
  height: 12px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.8);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background var(--transition);
}

.rkt .rkt-diapo-point.est-active,
.rkt .rkt-diapo-point:hover { background: #ffffff; }

/* Le bouton de lecture ne se montre qu'en pause, et inversement. */
.rkt-diapo-pause .rkt-icone-lecture { display: none; }
.rkt-diapo-pause[aria-pressed="true"] .rkt-icone-pause { display: none; }
.rkt-diapo-pause[aria-pressed="true"] .rkt-icone-lecture { display: inline-flex; }

@media (min-width: 768px) {
  .rkt-diapos-voile {
    background: linear-gradient(
      90deg,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.94) 0%,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.86) 42%,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.35) 68%,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0) 88%
    );
  }

  /* Bureau : en bas a droite du hero. Les cartes de cycle qui chevauchaient les
     40 derniers pixels ont ete retirees au CR-21, les commandes redescendent. */
  .rkt-diapos-commandes { top: auto; bottom: var(--sp-3); }
}

/*
 * Mouvement reduit : aucun defilement automatique. Le script le sait, et la
 * transition d'opacite est ramenee a rien par la regle globale. Les fleches et
 * les points restent utilisables : on retire l'automatisme, pas la commande.
 */
@media (prefers-reduced-motion: reduce) {
  .rkt-diapo { transition: none; }
}

/* ══ 14.2 Bande d'admission ═════════════════════════════════════════════════ */

/*
 * Deux etages pleine largeur, poses sous le bandeau. La forme vient d'un releve
 * sur un grand site universitaire ; les couleurs, les libelles et les liens sont
 * ceux du produit. Le fond est le bleu-noir du produit, jamais une couleur
 * d'etablissement : la bande reste lisible quelle que soit la charte du client.
 */

.rkt-admission-haut {
  background: var(--c-heading);
  color: #ffffff;
  padding: var(--sp-3) 0 var(--sp-2);
}

.rkt-admission-mot {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-accent);
  margin: 0 0 0.35rem;
}

.rkt-admission-accroche {
  font-family: var(--f-heading);
  font-size: 1.35rem;
  font-weight: 600;
  line-height: 1.3;
  color: #ffffff;
  margin: 0;
}

/* Second etage : un degre plus profond du meme bleu-noir, pose en degrade. */
.rkt-admission-bas {
  background: linear-gradient(180deg, var(--c-heading) 0%, var(--c-encre-profond) 100%);
  color: #ffffff;
  padding-bottom: var(--sp-3);
}

.rkt-admission-grille {
  display: grid;
  gap: var(--sp-2);
}

.rkt-etapes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}

.rkt-etape { margin: 0; }

.rkt .rkt-etape-lien {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-1);
  color: #ffffff;
  text-decoration: none;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  transition: background var(--transition);
}

/* Une etape est un lien : elle doit le dire au survol et au clavier, sur toute
   sa surface. Le filet a l'accent souligne l'etat, la couleur seule ne suffit
   pas a le signaler. */
.rkt .rkt-etape-lien:hover,
.rkt .rkt-etape-lien:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-radius: var(--radius-petit);
}

.rkt .rkt-etape-lien:hover .rkt-etape-libelle { text-decoration: underline; }

.rkt-etape-rang {
  font-family: var(--f-heading);
  font-size: 44px;
  font-weight: 700;
  line-height: 1;
  color: var(--c-accent);
  flex-shrink: 0;
  min-width: 1.4ch;
  text-align: center;
}

.rkt-etape-libelle {
  font-family: var(--f-heading);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  /* Le filet vertical separe le chiffre du libelle, comme sur le modele. */
  border-left: 1px solid rgba(255, 255, 255, 0.3);
  padding-left: var(--sp-2);
}

/* Bloc de questions : plus fonce que la rangee, pour se distinguer d'une etape. */
.rkt .rkt-admission-questions {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-2);
  background: rgba(0, 0, 0, 0.28);
  border-radius: var(--radius);
  color: #ffffff;
  font-family: var(--f-heading);
  font-weight: 600;
  text-decoration: none;
  transition: background var(--transition);
}

.rkt .rkt-admission-questions:hover { background: rgba(0, 0, 0, 0.45); }

.rkt-admission-questions svg {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  color: var(--c-accent);
}

/* Sur ces deux fonds sombres, l'anneau de focus passe au blanc. */
.rkt-admission-haut :focus-visible,
.rkt-admission-bas :focus-visible { outline-color: #ffffff; }

@media (min-width: 480px) {
  .rkt-etapes { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 768px) {
  .rkt-admission-haut { padding: var(--sp-4) 0 var(--sp-2); }
  .rkt-admission-accroche { font-size: 1.6rem; }
  .rkt-admission-bas { padding-bottom: var(--sp-4); }

  .rkt-admission-grille {
    grid-template-columns: 1fr auto;
    align-items: stretch;
    gap: var(--sp-3);
  }

  .rkt-etapes { grid-template-columns: repeat(4, 1fr); }

  .rkt .rkt-etape-lien {
    align-items: flex-start;
    border-top: 0;
    padding: var(--sp-2) 0;
    gap: var(--sp-1);
  }

  /* Quatre colonnes se partagent la largeur avec le bloc de questions : le
     libelle descend d'un cran et le filet se rapproche, pour tenir en deux
     lignes plutot qu'en trois. */
  .rkt-etape-libelle {
    font-size: 0.9rem;
    padding-left: var(--sp-1);
  }

  .rkt .rkt-admission-questions { align-self: center; }
}

/* Entrees relayees : le badge sur la carte, le bandeau sur la fiche. Les deux
   disent la meme chose, a deux endroits ou la question se pose. */
.rkt .rkt-badge--partenaire {
  background: var(--c-accent-dark);
  color: var(--c-sur-accent);
}

.rkt-avertissement {
  display: inline-block;
  margin: 0 0 var(--sp-2);
  padding: var(--sp-1) var(--sp-2);
  border-left: 4px solid var(--c-accent);
  background: rgba(255, 255, 255, 0.14);
  font-family: var(--f-heading);
  font-weight: 600;
  color: #ffffff;
}

/* ══ 14.3 Domaines d'etudes ═════════════════════════════════════════════════ */

/*
 * Section pleine largeur sur le degre fonce de la charte, avec un motif de
 * losanges en surimpression. Le motif est dessine en CSS : aucun fichier image
 * de fond, donc rien de plus a telecharger.
 */
.rkt-domaines {
  position: relative;
  overflow: hidden;
  background: var(--c-primary-dark);
  color: #ffffff;
  padding: var(--sp-6) 0;
}

.rkt-domaines-motif {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image:
    linear-gradient(45deg, rgba(255, 255, 255, 0.045) 25%, transparent 25%, transparent 75%, rgba(255, 255, 255, 0.045) 75%),
    linear-gradient(45deg, rgba(255, 255, 255, 0.045) 25%, transparent 25%, transparent 75%, rgba(255, 255, 255, 0.045) 75%);
  background-size: 44px 44px;
  background-position: 0 0, 22px 22px;
}

.rkt-domaines-interieur { position: relative; z-index: 1; }

.rkt .rkt-domaines-titre {
  font-size: var(--fs-h2);
  font-weight: 700;
  color: #ffffff;
  text-align: center;
  margin: 0 0 var(--sp-1);
}

.rkt-domaines-sous-titre {
  max-width: 46ch;
  margin: 0 auto var(--sp-4);
  text-align: center;
  font-size: 1.05rem;
  color: rgba(255, 255, 255, 0.82);
}

/* Mobile : la piste defile lateralement. Une pile de six cartes repousserait
   tout le reste de la page hors de portee. */
.rkt-domaines-piste {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 72%;
  gap: var(--sp-2);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: var(--sp-1);
  -webkit-overflow-scrolling: touch;
}

/*
 * Carte translucide. Le flou d'arriere-plan est un agrement : la carte reste
 * lisible sans lui, puisque son fond blanc a 12 % suffit a la detacher.
 */
.rkt .rkt-domaine {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-3) var(--sp-2);
  scroll-snap-align: start;
  text-align: center;
  text-decoration: none;
  color: #ffffff;
  /*
   * Blanc a 6 %, pas a 12 %. Mesure au pixel : a 12 %, le fond de la carte
   * monte assez haut pour qu'AUCUNE encre n'atteigne 4,5 contre lui, pas meme
   * le blanc pur, qui plafonnait a 3,92. La carte reste translucide, elle est
   * seulement moins claire.
   */
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 16px;
  transition: background var(--transition), transform var(--transition);
}

@supports (backdrop-filter: blur(6px)) {
  .rkt .rkt-domaine { backdrop-filter: blur(6px); }
}

.rkt .rkt-domaine:hover {
  background: rgba(255, 255, 255, 0.14);
  transform: translateY(-2px);
}

.rkt-domaine-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.16);
  color: #ffffff;
}

.rkt-domaine-icone svg { width: 28px; height: 28px; }

/* Libelle dore. La teinte vient de l'accent de la charte, eclairci jusqu'au
   niveau AA contre le fond reel de la carte ; le repli sert quand aucune
   couleur n'est configuree. */
.rkt-domaine-nom {
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--c-accent-clair, #ffd89b);
}

.rkt-domaine-description {
  font-size: var(--fs-meta);
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.82);
}

.rkt-domaines-sortie {
  margin: var(--sp-4) 0 0;
  text-align: center;
}

.rkt .rkt-domaines-sortie a {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #ffffff;
  text-decoration: none;
  border-bottom: 2px solid var(--c-accent-clair, #ffd89b);
  padding-bottom: 2px;
}

.rkt .rkt-domaines-sortie a:hover { color: var(--c-accent-clair, #ffd89b); }

/* Sur ce fond sombre, l'anneau de focus passe au blanc. */
.rkt-domaines :focus-visible { outline-color: #ffffff; }

@media (min-width: 600px) {
  .rkt-domaines-piste {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(2, 1fr);
    overflow-x: visible;
  }
}

@media (min-width: 1024px) {
  .rkt-domaines { padding: var(--sp-8) 0; }
  .rkt-domaines-piste { grid-template-columns: repeat(5, 1fr); gap: var(--sp-3); }
}

/* ══ 14.4 Actualites et evenements ══════════════════════════════════════════ */

.rkt-nouvelles-grille {
  display: grid;
  gap: var(--sp-4);
}

.rkt-colonne-entete {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}

.rkt .rkt-colonne-titre {
  font-family: var(--f-heading);
  font-size: var(--fs-h2);
  font-weight: 700;
  margin: 0;
  margin-right: auto;
}

/* Le bouton carre qui mene a l'archive. Un carre plein, pas un lien souligne :
   c'est la forme relevee sur le modele. */
.rkt .rkt-plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  background: var(--c-primary);
  color: var(--c-sur-primary);
  font-family: var(--f-heading);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  border-radius: var(--radius-petit);
  transition: background var(--transition);
}

.rkt .rkt-plus:hover { background: var(--c-primary-dark); }

.rkt .rkt-flux {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  color: var(--c-primary-dark);
  text-decoration: none;
}

.rkt .rkt-flux:hover { text-decoration: underline; }
.rkt-flux svg { width: 15px; height: 15px; }

.rkt-actus-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
}

.rkt-actu { margin: 0; }

.rkt .rkt-actu-lien {
  display: block;
  text-decoration: none;
  color: inherit;
}

/* Le rapport est reserve avant l'arrivee de l'image : aucune secousse de mise
   en page quand une vignette paresseuse se pose. */
.rkt-actu-media {
  display: block;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--c-primary-pale);
  margin-bottom: var(--sp-1);
}

.rkt .rkt-actu-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  max-width: none;
  transition: transform var(--transition);
}

.rkt-actu-lien:hover .rkt-actu-image { transform: scale(1.04); }

.rkt-actu-corps { display: block; }

.rkt-actu-titre {
  display: block;
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-primary-dark);
}

.rkt-actu-lien:hover .rkt-actu-titre { text-decoration: underline; }

/* Filet vertical entre le titre et la date, la signature de cette forme. */
.rkt-actu-date {
  display: block;
  margin-top: var(--sp-1);
  padding-left: var(--sp-1);
  border-left: 3px solid var(--c-bordure);
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
}

.rkt .rkt-evt-vedette {
  display: block;
  text-decoration: none;
  color: inherit;
  margin-bottom: var(--sp-2);
}

.rkt-evt-media {
  display: block;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--c-primary-pale);
  margin-bottom: var(--sp-1);
}

.rkt .rkt-evt-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  max-width: none;
}

.rkt-evt-date {
  display: block;
  margin: 0 0 0.2rem;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  color: var(--c-text);
}

/*
 * LA PASTILLE « PASSÉ » (`PROMPT-140`). Pas une couleur d'alerte : un
 * évènement passé n'est pas une erreur. `--c-text-doux` sur `--c-bg-alt`,
 * déjà la paire du produit pour un texte secondaire discret -- reprise ici,
 * pas mesurée à nouveau.
 */
.rkt-pastille-passe {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--c-bg-alt);
  color: var(--c-text-doux);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  vertical-align: middle;
}

.rkt-evt-titre {
  display: block;
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-primary-dark);
}

.rkt-evt-vedette:hover .rkt-evt-titre { text-decoration: underline; }

.rkt-evts-liste {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Filet pointille entre les evenements de la liste. */
.rkt-evt-ligne {
  padding: var(--sp-2) 0;
  border-top: 1px dashed var(--c-bordure);
}

.rkt-evt-ligne:first-child { border-top: 0; }

.rkt .rkt-evt-titre-lien {
  font-family: var(--f-heading);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-primary-dark);
  text-decoration: none;
}

.rkt .rkt-evt-titre-lien:hover { text-decoration: underline; }

@media (min-width: 768px) {
  .rkt-actus-grille { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 1024px) {
  .rkt-nouvelles-grille { grid-template-columns: 2fr 1fr; gap: var(--sp-6); }
  .rkt-nouvelles-grille--une { grid-template-columns: 1fr; }
}

/* ══ 14.5 Temoignages ═══════════════════════════════════════════════════════ */

.rkt-temoin {
  margin: 0;
  padding: var(--sp-3);
  background: var(--c-bg-alt);
  border-radius: var(--radius);
  border-top: 4px solid var(--c-accent);
}

.rkt .rkt-temoin-photo {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: var(--sp-2);
}

.rkt-temoin-citation {
  margin: 0 0 var(--sp-2);
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 500;
  line-height: 1.45;
  color: var(--c-heading);
}

.rkt-temoin-citation::before { content: '\201C'; }
.rkt-temoin-citation::after { content: '\201D'; }

.rkt-temoin-signature {
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
}

.rkt-temoin-nom {
  display: block;
  font-family: var(--f-heading);
  font-weight: 700;
  color: var(--c-text);
}

/* ══ 14.6 Presentation et bande « Nous joindre » ════════════════════════════ */

/*
 * Presentation et chiffres reunis sur un meme fond gris tres leger, comme sur
 * le modele releve. Colonne de lecture etroite et centree, corps plus grand que
 * le texte courant, couleur de texte pleine et non un gris pale.
 */
.rkt-presentation {
  background: var(--gray-100);
  padding: var(--sp-6) 0;
}

.rkt-presentation-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  align-items: center;
}

.rkt-presentation-surtitre {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-accent-dark);
  margin: 0 0 var(--sp-1);
}

.rkt-presentation-texte {
  font-size: 18px;
  line-height: 1.6;
  color: var(--c-text);
  text-align: left;
  /* Environ 62 caracteres par ligne : au-dela, l'oeil perd son point de retour
     d'une ligne a l'autre. */
  max-width: 62ch;
  margin: 0 0 var(--sp-2);
}

.rkt-presentation-texte:last-of-type { margin-bottom: 0; }

.rkt-presentation-lien { margin: var(--sp-3) 0 0; }

.rkt .rkt-presentation-lien a {
  font-family: var(--f-heading);
  font-weight: 600;
  color: var(--c-primary-lisible, var(--c-primary));
  text-decoration: none;
  border-bottom: 2px solid var(--c-accent);
  padding-bottom: 2px;
}

.rkt .rkt-presentation-lien a:hover { border-bottom-color: var(--c-primary); }

.rkt-presentation-image {
  display: block;
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
}

.rkt .rkt-presentation-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  max-width: none;
}

/* La bande de chiffres se colle dessous, meme fond, separee par de l'espace et
   non par un filet. */
@media (min-width: 1024px) {
  .rkt-presentation { padding: var(--sp-8) 0; }
  .rkt-presentation-texte { font-size: 20px; }
  .rkt-presentation-grille { grid-template-columns: 2fr 1fr; gap: var(--sp-6); }
  .rkt-presentation-grille--seule { grid-template-columns: 1fr; }
}

/* Fin de page : la derniere section est suivie directement du pied de page
   depuis le retrait de la bande « Nous joindre » au CR-23. La marge haute du
   pied laissait une bande blanche entre deux fonds colores ; elle disparait
   quand une bande pleine couleur precede, et reste ailleurs, ou elle sert. */
.rkt main#rkt-contenu { margin-bottom: 0; }
.rkt main#rkt-contenu > :last-child { margin-bottom: 0; }

.rkt-joindre {
  background: var(--gray-100);
  border-top: 1px solid var(--c-bordure);
  padding: var(--sp-6) 0;
}

.rkt-joindre-grille {
  display: grid;
  gap: var(--sp-3);
}

.rkt .rkt-joindre-titre {
  font-family: var(--f-heading);
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0 0 var(--sp-1);
  color: var(--c-heading);
}

.rkt-joindre-liste {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rkt-joindre-liste li { margin-bottom: 0.35rem; }

.rkt .rkt-joindre-liste a { color: var(--c-primary-dark); }

@media (min-width: 768px) {
  .rkt-joindre-grille {
    grid-template-columns: 1fr 1fr auto;
    align-items: start;
    gap: var(--sp-4);
  }
  .rkt-joindre-action { align-self: center; }
}

/* Bande de cycles chevauchant le bas du hero. */
.rkt-cycles {
  margin-top: -40px;
  padding-bottom: var(--sp-6);
}

/* La bande d'admission suit directement le hero : les deux blocs se touchent,
   sans blanc intermediaire. Un filet a l'accent marque la cesure, pour que le
   bleu-noir de la bande ne se confonde pas avec une diapositive bleue. */
.rkt-hero + .rkt-admission {
  margin-top: 0;
  border-top: 4px solid var(--c-accent);
}

.rkt-cycles .rkt-grille { margin-top: 0; }

/* Bande de chiffres, sur fond bleu plein. La rupture de fond avec la section
   grise au-dessus cree le rythme qui manquait. */
.rkt-chiffres-bande {
  background: var(--c-primary);
  color: #ffffff;
  padding: var(--sp-6) 0;
}

/* Filets verticaux entre les chiffres : ils separent sans decouper. */
.rkt-chiffres > div + div { border-left: 1px solid rgba(255, 255, 255, 0.22); }

.rkt-chiffres {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-4) var(--sp-3);
  text-align: center;
}

.rkt-chiffre-valeur {
  font-family: var(--f-heading);
  font-size: 44px;
  font-weight: 700;
  line-height: 1.1;
  color: #ffffff;
  margin: 0 0 0.25rem;
}

.rkt-chiffre-libelle {
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* 85 % et non 80 % : mesure sur le bleu plein, le blanc a 80 % tombe a 4,44
     contre 4,5 exiges, quand 85 % donne 4,83. Le contraste passe devant la
     valeur d'opacite demandee. */
  color: rgba(255, 255, 255, 0.85);
  margin: 0;
}

@media (min-width: 768px) {
  .rkt-chiffres { grid-template-columns: repeat(4, 1fr); }
}

/* Appel a l'action final, en degrade d'accent. */
.rkt-cta {
  background: linear-gradient(135deg, var(--c-accent-dark) 0%, var(--c-accent-darker) 100%);
  border-radius: var(--radius);
  padding: var(--sp-6) var(--sp-3);
  text-align: center;
  color: #ffffff;
}

.rkt-cta h2 { color: #ffffff; }
.rkt-cta p { color: rgba(255, 255, 255, 0.9); max-width: 54ch; margin-left: auto; margin-right: auto; }

/* ══ 9. Banniere de fiche et d'archive ═════════════════════════════════════ */

.rkt-banniere {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--c-primary) 0%, var(--c-primary-dark) 100%);
  color: #ffffff;
  padding-bottom: var(--sp-4);
}

.rkt-banniere::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0.07;
  background-image: repeating-linear-gradient(135deg, #ffffff 0 1px, transparent 1px 22px);
  pointer-events: none;
}

.rkt-banniere > * { position: relative; }

.rkt-banniere h1 { color: #ffffff; margin-bottom: var(--sp-2); }
.rkt-banniere .rkt-chapeau { color: rgba(255, 255, 255, 0.9); }

.rkt-banniere-corps { padding-top: var(--sp-3); }

/* Variante reduite pour les archives : le contenu prime sur l'annonce. */
.rkt-banniere--reduite { padding-bottom: var(--sp-3); }
.rkt-banniere--reduite .rkt-banniere-corps { padding-top: var(--sp-2); }

/* Meta de fiche en pastilles translucides. */
.rkt-banniere-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-2);
  margin: var(--sp-3) 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-meta);
}

.rkt-banniere-meta > li,
.rkt-banniere-meta > div {
  display: flex;
  gap: 0.4rem;
  align-items: baseline;
  background: rgba(255, 255, 255, 0.14);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
}

.rkt-banniere-meta dt {
  font-family: var(--f-heading);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
}

.rkt-banniere-meta dd { margin: 0; color: #ffffff; font-weight: 600; }

/* ══ 10. Fiches ════════════════════════════════════════════════════════════ */

.rkt-fiche-entete { padding: var(--sp-4) 0 var(--sp-3); }

.rkt-fiche-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-2) 0;
  padding: 0;
  font-size: 1rem;
  color: var(--c-text-doux);
}

.rkt-fiche-meta dt { font-weight: 600; color: var(--c-heading); }
.rkt-fiche-meta dd { margin: 0; }
.rkt-fiche-meta > div { display: flex; gap: 0.35rem; }

/* Corps de fiche sur deux colonnes, la colonne laterale reste visible. */
.rkt-fiche-grille { display: grid; gap: var(--sp-4); }

@media (min-width: 1024px) {
  .rkt-fiche-grille { grid-template-columns: 2fr 1fr; align-items: start; }
  .rkt-fiche-aside { position: sticky; top: 96px; }
}

/*
 * LA LISTE DE DEFINITIONS (`PROMPT-149`, point 4) : des informations courtes
 * et heterogenes, jamais une grille de choix -- pas de carte, pas de fond de
 * couleur, pas d'icone. Chaque terme porte la couleur principale foncee,
 * separe de sa reponse par le seul espacement ; les items se separent par un
 * filet fin, pas une bordure de carte.
 */
.rkt-liste-definitions {
  margin: var(--sp-3) 0 0;
}

.rkt-liste-definitions-item {
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--c-filet);
}

.rkt-liste-definitions-item:first-child { padding-top: 0; }
.rkt-liste-definitions-item:last-child { border-bottom: 0; }

.rkt-liste-definitions-terme {
  margin: 0 0 var(--sp-1);
  font-family: var(--f-heading);
  font-weight: 700;
  color: var(--c-primary-dark);
}

.rkt-liste-definitions-reponse {
  margin: 0;
}

.rkt-encadre {
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-top: 4px solid var(--c-accent);
  border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-2);
  box-shadow: var(--shadow);
}

.rkt-encadre h2 { font-size: 1.2rem; margin-bottom: var(--sp-2); }

.rkt-encadre dl {
  margin: 0 0 var(--sp-3);
  display: grid;
  gap: 0.6rem;
}

.rkt-encadre dl > div {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-2);
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--c-bordure);
  font-size: 1rem;
}

.rkt-encadre dl > div:last-child { border-bottom: 0; padding-bottom: 0; }

.rkt-encadre dt {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt-encadre dd { margin: 0; font-weight: 600; color: var(--c-heading); text-align: right; }

.rkt-prose { max-width: var(--w-narrow); }
.rkt-prose h2 { margin-top: var(--sp-4); }
.rkt-prose ul, .rkt-prose ol { padding-left: 1.4rem; }

.rkt-prose blockquote {
  margin: var(--sp-3) 0;
  padding-left: var(--sp-2);
  border-left: 3px solid var(--c-accent);
  color: var(--c-text-doux);
}

.rkt-prose img { margin: var(--sp-2) 0; }

/* Blocs de cours : carte a en-tete gris, badge de credits en accent. */
.rkt-bloc-exigence {
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: var(--sp-3);
  background: var(--c-bg);
}

.rkt-bloc-entete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-2);
  background: var(--c-bg-alt);
  border-bottom: 1px solid var(--c-bordure);
}

.rkt-bloc-entete h3 { margin: 0; font-size: 1.15rem; }
.rkt-bloc-corps { padding: var(--sp-2); }
.rkt-bloc-regle { color: var(--c-text-doux); font-size: 1rem; margin: 0 0 var(--sp-2); }

.rkt-table-cours { width: 100%; border-collapse: collapse; font-size: 1rem; }

.rkt-table-cours th,
.rkt-table-cours td {
  text-align: left;
  padding: 0.6rem 0.5rem;
  border-bottom: 1px solid var(--c-bordure);
}

.rkt-table-cours th {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt-table-cours tr:last-child td { border-bottom: 0; }
/* Chasse fixe, comme sur `/cours/` (`.rkt-of-code`) : c'est le code qui doit
   changer de police, pas le jeton `--f-heading` employé partout ailleurs
   (`COMPTE-RENDU-130-T3`, écart signalé à T1). */
.rkt-table-cours-code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-weight: 600; white-space: nowrap; }

.rkt-tableau-defilant { overflow-x: auto; }

/* ══ 11. Actualites ════════════════════════════════════════════════════════ */

.rkt-chapeau {
  font-size: 20px;
  line-height: 1.5;
  color: var(--gray-800);
  max-width: var(--w-narrow);
}

.rkt-image-legende {
  font-size: var(--fs-meta);
  font-style: italic;
  color: var(--c-text-doux);
  margin-top: var(--sp-1);
}

/* ══ 12. Filtres d'archive ═════════════════════════════════════════════════ */

.rkt-filtres {
  display: grid;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-2);
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.rkt-filtres label {
  display: block;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-text-doux);
  margin-bottom: 0.3rem;
}

.rkt-filtres select,
.rkt-champ input,
.rkt-champ textarea,
.rkt-404 input[type="search"] {
  width: 100%;
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius-petit);
  font: inherit;
  background: var(--c-bg);
  color: var(--c-text);
}

@media (min-width: 768px) {
  .rkt-filtres { grid-template-columns: repeat(3, 1fr) auto; align-items: end; }
}

/* ══ 13. Formulaire ════════════════════════════════════════════════════════ */

.rkt-formulaire { max-width: var(--w-narrow); }
.rkt-champ { margin-bottom: var(--sp-2); }

.rkt-champ label {
  display: block;
  font-family: var(--f-heading);
  font-weight: 600;
  margin-bottom: 0.35rem;
  color: var(--c-heading);
}

.rkt-champ-requis { color: var(--c-accent-dark); }

/* Pot de miel : hors ecran plutot que display:none, que les robots detectent. */
.rkt-pot-de-miel {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.rkt-message {
  padding: var(--sp-2);
  border-radius: var(--radius-petit);
  margin-bottom: var(--sp-3);
  border-left: 4px solid var(--c-primary);
  background: var(--c-primary-voile);
}

.rkt-message--erreur {
  border-left-color: var(--c-accent-dark);
  background: var(--c-bg-alt);
}

/* ══ 14. Pied de page ══════════════════════════════════════════════════════ */

/*
 * Trois bandes, modele UQAM -- `PROMPT-133`. La colonne mission (nom, phrase,
 * reseaux) de l'ancien pied a disparu : le nom et la mission restent dits
 * ailleurs (en-tete, page Institut), et les reseaux sont montes dans la bande
 * haute avec les deux boutons d'action.
 */
.rkt-pied {
  background: var(--c-encre);
  color: #c9d4e0;
  margin-top: var(--sp-8);
}

/*
 * Sur l'accueil, la derniere section porte toujours un fond plein : bande de
 * chiffres, domaines, admission ou hero. Le blanc de separation n'a donc rien a
 * separer, il se lit comme un oubli. Le selecteur passe par le corps parce que
 * le pied n'est pas un frere des sections : il est hors du `main`.
 */
.rkt.home main#rkt-contenu + .rkt-pied { margin-top: 0; }

.rkt-pied a {
  color: #c9d4e0;
  text-decoration: none;
}

/* Soulignement au survol seulement : un pied entierement souligne est bruyant. */
.rkt-pied a:hover { color: #ffffff; text-decoration: underline; }

.rkt-pied h2 {
  color: #ffffff;
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: var(--sp-2);
}

.rkt-pied ul { list-style: none; margin: 0; padding: 0; }
.rkt-pied li { margin-bottom: 0.5rem; }

/* ── 14.1 La bande haute : deux boutons, puis les reseaux a droite ───────── */

.rkt-pied-haut {
  padding: var(--sp-4) 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}

.rkt-pied-haut-dedans {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}

.rkt-pied-boutons { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* Dans la bande haute, les reseaux suivent les boutons au lieu de suivre une
   mission qui n'existe plus ici : pas de marge haute a hériter. */
.rkt-pied-haut .rkt-pied-social { margin-top: 0; }

/* ── 14.2 Les cinq colonnes ────────────────────────────────────────────────
 *
 * `auto-fit` plutot qu'un compte de colonnes fixe : une colonne dont le menu
 * est vide ne se rend PAS DU TOUT (`templates/parts/footer.php` la retire
 * avant meme d'ouvrir la grille), et le nombre de colonnes réellement rendues
 * peut donc varier d'un client Rektora a l'autre.
 */
.rkt-pied-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--sp-4);
  padding: var(--sp-6) 0;
}

/*
 * ── LE FILET INTERIEUR D'UNE COLONNE (`PROMPT-133`, T1 point 3) ──────────
 *
 * Pas de mecanisme special : la classe `rkt-pied-filet`, posee par
 * `rkt_installer_menus_pied_uqam()` (`includes/pages.php`) sur l'entree de
 * menu qui ouvre le second groupe, EST le filet. Un client qui compose ses
 * menus autrement n'a simplement jamais cette classe, et cette regle ne
 * s'applique jamais chez lui.
 */
.rkt-pied-col li.rkt-pied-filet {
  margin-top: var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px solid rgba(255, 255, 255, 0.15);
}

/*
 * ── LA BANDE DE RESEAUX : DES CADRES, PLUS DES MOTS (`PROMPT-131`, T1)
 *
 * Le cadre est celui de la demonstration validee du 2026-07-30 : un carre de
 * 38 px a filet blanc, l'icone a 20 px au centre, le survol qui inverse -- fond
 * blanc, trait sombre. Rien n'est charge : le dessin est dans la page.
 *
 * ── SPECIFICITE, LE PIEGE DU CHANTIER (sept morsures a ce jour)
 *
 * `.rkt-pied a` vaut (0,1,1) et impose `color: #c9d4e0`. `.rkt-pied-social a`
 * vaut exactement AUTANT (une classe, un type) : ce n'est donc pas la
 * specificite qui tranche, c'est l'ordre du fichier -- et ces regles sont
 * apres. Meme raisonnement pour le survol : `.rkt-pied a:hover` (0,2,1) impose
 * `color: #fff` et un soulignement, `.rkt-pied-social a:hover` vaut autant et
 * gagne par sa place. Le soulignement doit donc etre annule ICI, sans quoi un
 * trait courrait sous un cadre vide.
 *
 * ── CONTRASTE, MESURE ET NON ESTIME
 *
 *   icone #c9d4e0 sur le fond du pied #12263a ...... 10,25:1  (clause 3:1, WCAG 1.4.11)
 *   filet blanc a 40 % sur ce meme fond ............  3,66:1  (clause 3:1)
 *   au survol, #12263a sur blanc ................... 15,40:1
 *
 * Le filet de la demonstration etait a 30 %, ce qui donne 2,66:1 sur ce fond-ci
 * et passe SOUS la clause. Il est monte a 40 % : c'est le seul ecart avec le
 * modele valide, et il est la pour que la limite du cadre se voie.
 */
.rkt-pied-social { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: var(--sp-2); }
.rkt-pied-social li { margin-bottom: 0; }

/*
 * `min-width` et non `width` : une cle reglee que la piece ne dessine pas garde
 * son nom en toutes lettres, et le cadre s'elargit pour l'accueillir au lieu de
 * le rogner. Aucun `:has()` n'est necessaire pour cela -- c'est le mot qui
 * pousse le cadre, par sa propre marge interieure, et le repli tient donc
 * meme la ou `:has()` n'existe pas.
 */
.rkt-pied-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 2.375rem;
  height: 2.375rem;
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #c9d4e0;
}

.rkt-pied-social a:hover,
.rkt-pied-social a:focus-visible {
  background: #ffffff;
  color: var(--c-encre);
  text-decoration: none;
}

.rkt-pied-social svg { display: block; width: 1.25rem; height: 1.25rem; }
.rkt-pied-social-nom { padding: 0 0.6rem; }

.rkt-pied-bas {
  background: var(--c-encre-profond);
  margin: 0;
  padding: var(--sp-2) 0;
  font-size: var(--fs-meta);
  color: #8ea0b3;
}

/*
 * ── LA LIGNE DE CREDIT (`PROMPT-131`, volet T2, rendu par T1)
 *
 * « A cote de la mention de droits » : les deux se posent donc cote a cote la
 * ou la place existe, et l'une sous l'autre quand elle manque. Un `flex` qui
 * revient a la ligne suffit -- aucune requete de media n'est necessaire, c'est
 * la largeur du texte qui decide.
 *
 * Le selecteur vaut (0,2,0) contre (0,1,0) pour `.rkt-conteneur` : il gagne par
 * la specificite et non par sa place, donc il survit a un deplacement.
 *
 * ── SPECIFICITE, LE PIEGE DU CHANTIER (sept morsures a ce jour)
 *
 * `.rkt-pied a` vaut (0,1,1) et impose `text-decoration: none`.
 * `.rkt-pied-credit a` vaut EXACTEMENT AUTANT (une classe, un type) : ce n'est
 * donc pas la specificite qui tranche mais l'ordre du fichier, et cette regle
 * est apres. La deplacer plus haut effacerait le soulignement.
 *
 * ── POURQUOI SOULIGNER, ALORS QUE LE RESTE DU PIED NE L'EST PAS
 *
 * Le pied s'interdit le soulignement permanent parce que ses liens sont seuls
 * dans leur colonne : rien ne les confond. Ici, le lien est POSE DANS UNE
 * PHRASE grise, et seule sa couleur l'en distingue :
 *
 *   lien #c9d4e0 sur le fond de la bande #0d1c2c ..... 11,46:1  (clause 4,5:1)
 *   texte #8ea0b3 sur ce meme fond ...................  6,42:1  (clause 4,5:1)
 *   le lien COMPARE au texte qui l'entoure ...........   1,79:1  SOUS 3:1
 *
 * Le fond de cette bande est `--c-encre-profond` (#0d1c2c) et non le
 * `--c-encre` (#12263a) du reste du pied : les mesures sont prises sur le bon.
 * L'ecart de 1,79:1 entre le lien et son voisinage est trop faible pour que la
 * couleur porte seule l'information (WCAG 1.4.1) : le soulignement le dit
 * autrement. Le survol reste celui du pied -- blanc, souligne.
 */
.rkt-pied-bas .rkt-conteneur {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 1.5rem;
}

.rkt-pied-credit a { text-decoration: underline; }

/* ══ 15. Page 404 ══════════════════════════════════════════════════════════ */

.rkt-404 { text-align: center; padding: var(--sp-8) 0; }
.rkt-404 form { max-width: 26rem; margin: var(--sp-3) auto; display: flex; gap: var(--sp-1); }
.rkt-404-liens { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center; }

/* ══ 16. Rubrique en deux colonnes ═════════════════════════════════════════ */

/*
 * Variante de rubrique : la page carrefour et ses sous-pages, un seul gabarit.
 * Un seul accent employe partout de la meme facon, la barre orange : sous le
 * titre, en tete de tuile, au-dessus de chaque chiffre. Le rail et les fonds de
 * bande prennent la couleur principale, jamais l'accent.
 *
 * LA PIECE MAITRESSE EST LA SURFACE. Il n'y a pas une bande puis un corps de
 * page : il y a une bande, et LA SURFACE DE PAGE qui monte dessus et qui
 * continue vers le bas en portant tout le reste. Elle n'a ni bord inferieur, ni
 * ombre, ni arrondi, parce qu'elle ne s'arrete pas. Son fond est celui de la
 * page : en descendant, on ne peut pas dire ou le bandeau s'arrete, et c'est le
 * test de reussite.
 *
 * Tout est porte par la classe `.rkt-rubrique` du `main` : la variante
 * d'origine, qui ne la porte pas, n'est touchee par aucune de ces regles.
 */

/* ── Procede 1 : la bande, et la surface qui monte dessus ─────────────────── */

/*
 * La bande a une HAUTEUR, elle n'a plus de marge interieure : c'est la surface
 * qui remonte par-dessus son bas, et non le contenu qui pousse la bande. Trois
 * hauteurs, une par palier, pour qu'il reste toujours de la photographie a voir
 * au-dessus de la surface.
 */
.rkt-rubrique .rkt-ouverture {
  position: relative;
  height: 280px;
  background: var(--c-primary);
}

/* Avec une photographie, le fond de couleur reste DERRIERE en degre fonce : il
   tient la bande pendant le chargement et si l'image manque. */
.rkt-rubrique .rkt-ouverture--photo { background: var(--c-primary-dark); }

.rkt-ouverture-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

/*
 * `object-position` a 25 % de la hauteur, et ce n'est pas un reglage esthetique :
 * la bande recadre, et la partie qui reste visible est son HAUT, la surface
 * couvrant le bas. Mesure faite sur la photographie fournie, les deux visages
 * sont a environ 30 % de la hauteur : la valeur les fait tomber dans le tiers
 * superieur de la bande, aux quatre largeurs.
 */
.rkt-ouverture-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 25%;
}

/*
 * LA SURFACE. Moins large que la bande, ce qui laisse voir la photographie de
 * part et d'autre. `position: relative` la fait passer devant la photographie,
 * qui est en position absolue. Aucun bord, aucune ombre, aucun arrondi : elle
 * continue.
 */
/*
 * LA SURFACE EST TRES LEGEREMENT TRANSLUCIDE, a 94 %. Le blanc reste largement
 * dominant et la photographie affleure la ou la surface la recouvre. Sous la zone
 * de photo, la surface repose sur le fond blanc de la page : la translucidite y
 * est invisible, et c'est exactement l'effet cherche, sans conteneur de plus.
 *
 * La valeur a ete choisie a l'oeil et verifiee au chiffre. Mesure faite sur la
 * zone la plus chargee de la photographie derriere la surface, premier centile de
 * luminance a 0,0070, soit rgb(9, 20, 39) :
 *
 *   opacite 1,00   fond rgb(255,255,255)   titre 15,40:1   lien du fil 8,18:1
 *   opacite 0,94   fond rgb(240,241,242)   titre 13,61:1   lien du fil 7,23:1
 *   opacite 0,85   fond rgb(218,220,223)   titre 11,20:1   lien du fil 5,95:1
 *
 * La lisibilite n'est donc PAS le facteur limitant : le niveau AA tient meme a
 * 85 %. Le facteur est l'oeil, et 94 % laisse l'effet se remarquer a peine. Aucun
 * flou d'arriere-plan n'a ete necessaire.
 */
.rkt-surface {
  position: relative;
  max-width: var(--w-content);
  margin-inline: auto;
  background: rgba(255, 255, 255, 0.94);
}

.rkt-surface-dedans { padding: var(--sp-4) var(--sp-2) var(--sp-8); }

/* Le fil d'Ariane est SUR la surface : il y perd son fond et son filet, qui
   feraient une bande dans une surface. */
.rkt-surface .rkt-fil {
  background: transparent;
  border-bottom: 0;
}

.rkt-surface .rkt-fil .rkt-conteneur {
  max-width: none;
  margin: 0;
  padding: 0;
}

.rkt-surface .rkt-fil ol { padding: 0 0 var(--sp-2); }

.rkt-rubrique .rkt-ouverture-titre { margin-bottom: var(--sp-6); }
.rkt-rubrique .rkt-ouverture-titre h1 { margin: 0; }

/* ── Le corps en deux colonnes : procedes 2 et 3 ──────────────────────────── */

.rkt-corps-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
}

/* La colonne de lecture garde sa largeur confortable dans sa colonne. */
.rkt-colonne-lecture { min-width: 0; }
.rkt-colonne-lecture .rkt-prose { max-width: var(--w-narrow); }

/*
 * ── La colonne d'appui commune, retiree des gabarits de rubrique au
 * `PROMPT-104` ────────────────────────────────────────────────────────────
 *
 * `.rkt-appui` et ses sous-classes (`-bloc`, `-titre`, `-liste`) n'avaient
 * plus qu'un seul appelant, `templates/variantes/contact/standard.php` (lot
 * 78). Le `PROMPT-135` remplace cette colonne par les cartes `.rkt-cc-*`
 * ci-dessous : les regles `.rkt-appui-*` sont donc retirees avec lui, elles
 * n'ont plus aucun appelant. `.rkt-appui { min-width: 0; }` disparait pour la
 * meme raison.
 */

/* ── La page de contact : cartes de coordonnees, `PROMPT-135` ─────────────
 *
 * Deux colonnes au palier bureau, Coordonnees a gauche (plus etroite, elle
 * porte des cartes courtes) puis le formulaire. Un seul palier, 768 px,
 * comme le reste des gabarits a deux colonnes du produit.
 */
.rkt-contact-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  align-items: start;
}

@media (min-width: 768px) {
  .rkt-contact-grille {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--sp-6);
  }
}

.rkt-contact-coordonnees { display: flex; flex-direction: column; gap: var(--sp-3); }

.rkt-cc-titre-colonne {
  margin: 0;
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt-cc-carte {
  display: flex;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  background: var(--c-bg);
}

/*
 * TROIS NUANCES DU MEME BLEU, PAS TROIS COULEURS. Voir le doc-bloc du
 * gabarit : le produit n'a ni orange ni vert dans ses jetons, en inventer
 * pour cette seule page romprait la charte pour un habillage cosmetique.
 */
.rkt-cc-carte--courriel .rkt-cc-icone { background: var(--c-primary-pale); color: var(--c-primary); }
.rkt-cc-carte--heures .rkt-cc-icone { background: var(--c-bg-alt); color: var(--c-accent-dark); }
.rkt-cc-carte--whatsapp .rkt-cc-icone { background: var(--c-primary-voile); color: var(--c-primary-dark); }

.rkt-cc-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius);
}

.rkt-cc-icone svg { width: 1.4rem; height: 1.4rem; }

.rkt-cc-corps { min-width: 0; }

.rkt .rkt-cc-corps h3 {
  margin: 0 0 0.3rem;
  font-size: 1rem;
  color: var(--c-heading);
}

.rkt-cc-corps p { margin: 0; }
.rkt-cc-texte { font-size: var(--fs-meta); color: var(--c-text-doux); line-height: var(--lh-body); }
.rkt-cc-texte p { margin: 0.2rem 0 0; }
.rkt-cc-bouton { margin-top: var(--sp-2); }

.rkt-cc-intro-formulaire { margin-bottom: var(--sp-3); }
.rkt-cc-intro-formulaire p { font-size: var(--fs-meta); color: var(--c-text-doux); }

/* ── « Ce qui ne passe pas par cette page » : trois blocs a filet superieur ── */

.rkt-contact-voies { margin-top: var(--sp-6); }

.rkt-contact-voies-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}

@media (min-width: 768px) {
  .rkt-contact-voies-grille { grid-template-columns: repeat(3, 1fr); }
}

.rkt-contact-voie {
  padding-top: var(--sp-2);
  border-top: 2px solid var(--c-bordure);
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
  line-height: var(--lh-body);
}

/* ── Procede 2 : le rail de sous-navigation ───────────────────────────────── */

.rkt-rail { min-width: 0; }

/*
 * Sous 1024 px le rail se replie derriere un bouton. L'etat replie ou deploye
 * est lu directement sur `aria-expanded` : un seul etat, celui que le lecteur
 * d'ecran annonce, et aucun risque que l'apparence et l'annonce divergent.
 */
.rkt-rail-bascule {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-primary-pale);
  border: 0;
  border-left: 4px solid var(--c-primary);
  font-family: var(--f-heading);
  font-size: 1rem;
  font-weight: 700;
  color: var(--c-heading);
  text-align: left;
  cursor: pointer;
}

.rkt-rail-chevron {
  font-size: 1.5rem;
  line-height: 1;
  color: var(--c-primary-lisible, var(--c-primary));
}

.rkt-rail-bascule[aria-expanded="true"] .rkt-rail-chevron { transform: rotate(90deg); }

.rkt-rail-liste {
  display: none;
  list-style: none;
  margin: 0;
  padding: 0;
}

.rkt-rail-bascule[aria-expanded="true"] + .rkt-rail-liste { display: block; }

.rkt-rail-entree + .rkt-rail-entree { margin-top: 2px; }

.rkt-rail-entree a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-primary-pale);
  border-left: 4px solid transparent;
  color: var(--c-text);
  text-decoration: none;
  font-family: var(--f-heading);
  font-size: 0.98rem;
  line-height: 1.35;
}

.rkt-rail-entree a:hover { background: var(--c-filet); }

/* L'entree courante est en plein, les autres en aplat leger. */
.rkt-rail-entree--courante a {
  background: var(--c-primary);
  border-left-color: var(--c-primary-dark);
  color: var(--c-sur-primary);
  font-weight: 700;
}

.rkt-rail-entree--courante a:hover { background: var(--c-primary); }

/* ── Le sommaire d'ancres : le rail d'une page sans rubrique ──────────────── */

/*
 * Le sommaire n'a AUCUNE regle d'apparence propre : il porte les classes du
 * rail, donc son repli, ses aplats et son entree en plein viennent des regles
 * ci-dessus, sans une declaration de plus. Ce qui suit ne concerne que ce qui le
 * distingue reellement d'un rail : il reste visible pendant qu'on lit.
 */
.rkt-rail--sommaire { min-width: 0; }

/* L'intitule ne parait qu'en bureau : sous 1024 px, le bouton de repli le porte
   deja, et deux fois le meme mot serait deux fois trop. */
.rkt-sommaire-titre { display: none; }

/*
 * LE DECALAGE D'ANCRAGE, et pourquoi il vise l'en-tete DEPLOYEE. L'en-tete est
 * collante : sans decalage, sauter a une section pose le titre exactement sous
 * elle, qui le recouvre.
 *
 * La valeur est celle de l'en-tete DEPLOYEE, et non celle de l'en-tete repliee,
 * parce que c'est le seul cas ou elle sert : quand le JavaScript repond, il vise
 * la position d'arrivee lui-meme et ce decalage n'entre pas en jeu ; quand il ne
 * repond pas, l'en-tete NE SE REPLIE JAMAIS, son repli etant justement son
 * ouvrage.
 *
 * Les valeurs sont mesurees, pas estimees : en-tete deployee de 189 px en
 * mobile et de 125 px a partir de 1024 px, d'ou 12,5 rem et 11 rem. La seconde
 * a du etre relevee de 9 a 11 rem apres mesure sans JavaScript, ou le titre
 * arrivait encore 9 px sous le bord de l'en-tete.
 */
.rkt-rubrique .rkt-prose h2 { scroll-margin-top: 12.5rem; }

/* ── Procede 3 : filets horizontaux entre les sections ────────────────────── */

/*
 * Un filet avant chaque titre de section, jamais au-dessus du premier :
 * `:not(:first-of-type)` dit exactement cela, sans qu'un gabarit ait a compter
 * ses titres.
 */
.rkt-rubrique .rkt-prose h2:not(:first-of-type) {
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--c-filet);
}

/* ── Le chapeau d'une sous-page ───────────────────────────────────────────── */

/*
 * Le premier paragraphe d'une sous-page annonce le reste : il se lit plus grand
 * et plus aere, et se detache du corps. C'est une regle de gabarit, pas une
 * exception pour une page.
 *
 * `:first-child` et non `:first-of-type` : si le contenu commence par un titre,
 * il n'y a pas de phrase d'annonce, et rien ne doit changer. Un paragraphe qui
 * n'annonce rien reste parfaitement lisible en chapeau, le risque est nul.
 */
.rkt-rubrique--sous-page .rkt-colonne-lecture .rkt-prose > p:first-child {
  font-size: 1.2rem;
  line-height: 1.55;
  color: var(--c-text);
  margin-bottom: var(--sp-4);
}

/* ── Le mur de paragraphes devient une suite de blocs ──────────────────────── */

/*
 * Un filet fin entre les paragraphes de premier niveau. Le selecteur enfant
 * direct garantit qu'aucun paragraphe imbrique dans une liste ou une citation
 * n'est touche, et `p + p` qu'il n'y a jamais de filet avant le premier.
 *
 * La classe n'est posee par le gabarit que sous deux conditions mesurees : au
 * moins quatre paragraphes, et aucun titre de section. Voir le gabarit.
 */
.rkt-prose--blocs > p + p {
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--c-filet);
}

/* ── Procede 4 : l'encadre, filet vertical epais, aucune boite ────────────── */

.rkt-rubrique .rkt-page-encadre {
  margin: var(--sp-6) 0 0;
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-3);
  max-width: var(--w-narrow);
  background: transparent;
  border: 0;
  border-left: 6px solid var(--c-primary);
  border-radius: 0;
}

/* ── Procede 5 : les tuiles ───────────────────────────────────────────────── */

/*
 * Le nombre de colonnes est DEDUIT du nombre de tuiles, dans le gabarit, pour
 * qu'aucune ne reste seule en fin de rangee. La feuille ne fait que declarer
 * les grilles possibles.
 *
 * Les tuiles sont SUR la surface, dans le meme flux que le corps : une marge
 * haute les separe du texte, pas un second conteneur ni un blanc intercalaire.
 */
.rkt-rubrique .rkt-tuiles {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
  list-style: none;
  margin: var(--sp-8) 0 0;
  padding: 0;
}

/*
 * Une porte calme : un filet fin a la place de la boite a ombre, un survol en
 * aplat leger, sans ombre ni deplacement. La colonne flexible pousse le chevron
 * en bas, donc aligne d'une tuile a l'autre quelle que soit la longueur du
 * libelle.
 */
/*
 * Resserree : icone, libelle, chevron, et rien entre. La description ne s'affiche
 * plus, le vide du milieu disparait avec elle.
 */
.rkt-rubrique .rkt-tuile a {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--sp-3) var(--sp-3) var(--sp-2);
  background: var(--c-bg);
  border: 1px solid var(--c-filet);
  border-radius: 0;
  box-shadow: none;
  text-decoration: none;
  transition: none;
}

.rkt-rubrique .rkt-tuile a::before {
  content: '';
  display: block;
  width: 32px;
  height: 3px;
  margin-bottom: var(--sp-2);
  background: var(--c-accent);
}

.rkt-rubrique .rkt-tuile a:hover,
.rkt-rubrique .rkt-tuile a:focus-visible {
  background: var(--c-primary-pale);
  border-color: var(--c-primary);
  box-shadow: none;
}

/*
 * L'icone remplace la barre d'accent : meme coin, une seule marque. Une tuile
 * sans icone garde la barre, la grille reste alignee dans les deux cas.
 */
.rkt-rubrique .rkt-tuile--icone a::before { display: none; }

/* Icone facultative, dessinee dans le gabarit, prise par le champ Classes CSS
   de l'entree de menu. Aucune icone n'est attribuee par defaut. */
.rkt-rubrique .rkt-tuile-icone {
  display: block;
  color: var(--c-primary-lisible, var(--c-primary));
  margin-bottom: var(--sp-2);
}

.rkt-rubrique .rkt-tuile-icone svg { width: 32px; height: 32px; }

.rkt-rubrique .rkt-tuile-titre {
  display: block;
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-rubrique .rkt-tuile-desc {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--c-text-doux);
}

/* Le chevron se pose en bas a droite. `sp-1` et non `sp-2` : entre la
   description et le chevron il restait un vide sans raison d'etre. */
.rkt-rubrique .rkt-tuile-chevron {
  margin-top: auto;
  align-self: flex-end;
  padding-top: var(--sp-1);
  font-family: var(--f-heading);
  font-size: 1.5rem;
  line-height: 1;
  color: var(--c-primary-lisible, var(--c-primary));
}

/* ── Procede 6 : la cloture ───────────────────────────────────────────────── */

/*
 * La bande de chiffres du produit, telle quelle, avec la barre d'accent epaisse
 * au-dessus de chaque valeur. Les filets verticaux entre les chiffres existent
 * deja dans la bande ; sous 768 px la grille passe a deux colonnes, et le filet
 * du premier element d'une rangee ne separe alors rien : il se retire.
 */
.rkt-chiffres-bande--barres .rkt-chiffres > div {
  position: relative;
  padding-top: var(--sp-3);
}

.rkt-chiffres-bande--barres .rkt-chiffres > div::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 48px;
  height: 6px;
  margin-left: -24px;
  background: var(--c-accent);
}

/* La legende tient sur deux lignes quand elle est longue, comme sur le modele :
   une largeur en `ch` laisse « Cours » sur une ligne sans couper un mot. */
.rkt-chiffres-bande--barres .rkt-chiffre-libelle {
  max-width: 12ch;
  margin-left: auto;
  margin-right: auto;
}

.rkt-chiffres-bande--barres .rkt-chiffres > div:nth-child(odd) { border-left: 0; }

/*
 * Chaque chiffre mene a sa liste, et TOUTE la tuile est cliquable, pas seulement
 * le nombre : un seul lien dans l'ordre de tabulation, une cible large a la
 * souris. Le soulignement du libelle au survol dit que c'est un lien, la couleur
 * seule ne suffisant pas.
 */
.rkt-chiffre-lien {
  display: block;
  padding: var(--sp-1) var(--sp-2);
  color: inherit;
  text-decoration: none;
}

/*
 * `margin-block`, pas `margin: 0` (`PROMPT-142`) : l'intention d'origine est
 * d'annuler les marges verticales d'un paragraphe. Le raccourci quatre cotes
 * ecrasait aussi `margin-left`/`margin-right: auto` pose par
 * `.rkt-chiffres-bande--barres .rkt-chiffre-libelle`, a specificite egale et
 * ecrit plus haut dans ce fichier : le libelle decrochait de 68px vers la
 * gauche. Nommer l'axe borne le raccourci a ce qu'il vise reellement.
 */
.rkt-chiffre-lien .rkt-chiffre-valeur,
.rkt-chiffre-lien .rkt-chiffre-libelle { display: block; margin-block: 0; }

.rkt-chiffre-lien .rkt-chiffre-valeur { margin-bottom: 0.25rem; }

.rkt-chiffre-lien:hover .rkt-chiffre-libelle,
.rkt-chiffre-lien:focus-visible .rkt-chiffre-libelle {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/*
 * La mention sous la bande : elle dit ce que les chiffres comptent, et c'est ce
 * qui les rend vrais. Une seule ligne, pas une mention par chiffre.
 */
/*
 * Selecteur a deux classes, et ce n'est pas du zele : la regle `.rkt p` du
 * produit est en (0,1,1) et bat toute regle de composant a une seule classe.
 * Mesure faite : la mention gardait `margin: 0 0 sp-2`, donc aucune marge
 * automatique, donc aucun centrage. Meme piege que `.rkt a` sur les panneaux de
 * cloture ci-dessous.
 */
.rkt-chiffres-bande .rkt-chiffres-mention {
  max-width: var(--w-content);
  margin: var(--sp-3) auto 0;
  padding: 0 var(--sp-2);
  font-size: var(--fs-meta);
  text-align: center;
  /* 85 % comme les libelles : mesure au meme rapport sur le bleu plein. */
  color: rgba(255, 255, 255, 0.85);
}

/* ── La bande des periodes d'admission ────────────────────────────────────── */

/*
 * Trois cartes lues dans le calendrier academique. L'etat se deduit des dates :
 * la carte porte donc sa mention sans qu'on l'ait saisie, et le produit ne peut
 * pas annoncer une admission ouverte apres sa cloture.
 */
.rkt-periode {
  padding: var(--sp-3);
  border: 1px solid var(--c-filet);
}

.rkt-periode-etat {
  display: inline-block;
  margin: 0 0 var(--sp-2);
  padding: 0.25rem 0.7rem;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Ouvert : le plein de la couleur principale, qui porte le blanc au niveau AA.
   Clos : l'aplat leger et le texte du corps, un etat n'est pas une alerte. */
.rkt-periode-etat--ouvert {
  background: var(--c-primary);
  color: var(--c-sur-primary);
}

.rkt-periode-etat--close {
  background: var(--c-primary-pale);
  color: var(--c-text);
}

.rkt-periode-titre {
  font-size: var(--fs-h3);
  margin-bottom: var(--sp-1);
}

.rkt-periode .rkt-periode-quand {
  margin: 0;
  font-family: var(--f-heading);
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-periode .rkt-periode-precision {
  margin: var(--sp-1) 0 0;
  font-size: 0.95rem;
  color: var(--c-text-doux);
}

/* Une periode close se lit, mais ne se lit pas la premiere : le filet suffit a
   la mettre en retrait, sans la cacher. */
.rkt-periode--close { border-color: var(--c-bordure); }

/* ── La bande d'actualites ────────────────────────────────────────────────── */

.rkt-bande-actus { background: var(--c-bg-alt); }

/* ── La bande de cloture, deux panneaux ───────────────────────────────────── */

/*
 * Deux panneaux de pleine hauteur, cote a cote, chacun une action. Ils ferment
 * la page : la marge haute du pied est deja annulee sur cette variante.
 *
 * Le lien porte tout le panneau, donc la cible est enorme et l'ordre de
 * tabulation n'a qu'une entree par panneau.
 */
.rkt-cloture {
  display: grid;
  grid-template-columns: 1fr;
}

/*
 * Le panneau porte un titre, une phrase, puis son action en bas. La colonne
 * flexible pousse l'action au pied, ce qui l'aligne d'un panneau a l'autre quelle
 * que soit la longueur des deux textes.
 */
.rkt-cloture-panneau {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-6) var(--sp-3);
  text-decoration: none;
}

.rkt-cloture-titre {
  font-family: var(--f-heading);
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: var(--lh-heading);
}

.rkt-cloture-texte {
  font-size: 1.05rem;
  line-height: 1.5;
  max-width: 34ch;
}

.rkt-cloture-pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  padding-top: var(--sp-2);
  border-top: 1px solid rgba(255, 255, 255, 0.3);
}

.rkt-cloture-action {
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: var(--lh-heading);
}

.rkt-cloture-chevron {
  font-family: var(--f-heading);
  font-size: 2rem;
  line-height: 1;
  flex: 0 0 auto;
}

/*
 * Les deux fonds prennent les degres MESURES du produit, pas les teintes brutes :
 * `--c-primary-dark` et `--c-accent-dark` sont assombris jusqu'a porter du texte
 * blanc au niveau AA, quelle que soit la charte du client. Sur l'accent brut, le
 * blanc echoue : c'est le couple le plus tendu de la charte, et c'est pour cela
 * que le produit calcule ce degre.
 */
/*
 * `a.` dans le selecteur, et c'est necessaire : la regle `.rkt a` du produit est
 * en (0,1,1) et bat une regle de composant a une seule classe. Mesure faite, le
 * texte des deux panneaux sortait en `rgb(0, 74, 140)`, soit le bleu des liens,
 * donc INVISIBLE sur le panneau bleu, qui porte exactement cette couleur.
 */
.rkt-cloture a.rkt-cloture-panneau--primaire {
  background: var(--c-primary-dark);
  color: var(--c-sur-primary);
}

.rkt-cloture a.rkt-cloture-panneau--accent {
  background: var(--c-accent-dark);
  color: var(--c-sur-accent);
}

.rkt-cloture-panneau:hover .rkt-cloture-action,
.rkt-cloture-panneau:focus-visible .rkt-cloture-action {
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* Sur ces deux fonds sombres, un anneau de focus bleu ne se verrait pas. */
.rkt-cloture :focus-visible { outline-color: #ffffff; }

/*
 * La page se ferme SUR la bande de chiffres. La marge haute du pied, faite pour
 * une page qui s'arrete sur du texte, laissait une bande blanche echouee entre
 * le bleu et le pied sombre. Sans bande de chiffres, la respiration basse de la
 * surface reste en place : la page se ferme dans les deux cas.
 */
.rkt-rubrique + .rkt-pied { margin-top: 0; }

/* ── Paliers ──────────────────────────────────────────────────────────────── */

@media (min-width: 768px) {
  /* La bande gagne en hauteur : il faut de quoi voir la photographie. */
  .rkt-rubrique .rkt-ouverture { height: 360px; }

  /* Les deux panneaux de cloture passent cote a cote, de hauteur egale. */
  .rkt-cloture { grid-template-columns: repeat(2, 1fr); }
  .rkt-cloture--une { grid-template-columns: 1fr; }
  .rkt-cloture-panneau { padding: var(--sp-8) var(--sp-6); }

  .rkt-surface-dedans { padding: var(--sp-6) var(--sp-3) var(--sp-8); }

  .rkt-chiffres-bande--barres .rkt-chiffres > div:nth-child(odd) {
    border-left: 1px solid rgba(255, 255, 255, 0.22);
  }
  .rkt-chiffres-bande--barres .rkt-chiffres > div:first-child { border-left: 0; }

  .rkt-rubrique .rkt-tuiles--2 { grid-template-columns: repeat(2, 1fr); }
  .rkt-rubrique .rkt-tuiles--3 { grid-template-columns: repeat(2, 1fr); }
  .rkt-rubrique .rkt-tuiles--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .rkt-rubrique .rkt-ouverture { height: 420px; }

  /*
   * La surface monte de 120 px sur la bande, et il reste 300 px de photographie
   * visible au-dessus d'elle.
   *
   * La LARGEUR, et non des marges laterales : `margin-left` et `margin-right`
   * fixes annulaient le centrage automatique, et la surface se calait a gauche.
   * Mesure faite au navigateur, la surface commencait a 32 px et laissait
   * 268 px de photo a droite contre 32 a gauche. Le `CR-55` ne l'avait pas vu
   * parce que sa metrique CALCULAIT la symetrie au lieu de la mesurer.
   *
   * `width` bornee plus `margin-inline: auto` donne les deux a la fois : la
   * surface reste centree, et il reste toujours de la photographie de chaque
   * cote, 150 px dans une fenetre de 1440, 32 px dans une fenetre de 1024.
   *
   * `.rkt-ouverture + .rkt-surface`, PAS `.rkt-surface` seul (`PROMPT-142`) :
   * sans bandeau, `ouverture-rubrique.php` ne rend plus aucun `<div>` (regle
   * du contenant vide). Un selecteur non qualifie continuait de monter la
   * surface de 120 px dans l'en-tete meme sans rien au-dessus a chevaucher --
   * mesure sur `/contact/`, seule page du site sans image mise en avant.
   */
  .rkt-ouverture + .rkt-surface {
    margin-top: -120px;
    width: calc(100% - 2 * var(--sp-4));
  }

  .rkt-surface-dedans { padding: var(--sp-6) var(--sp-6) var(--sp-8); }

  /* Le titre grandit avec la surface : il etait petit dans un bloc qui l'etait
     moins. La taille reste exprimee dans la grammaire de jetons. */
  .rkt-rubrique .rkt-ouverture-titre h1 { font-size: calc(var(--fs-h1) * 1.25); }

  /* Deux colonnes : le rail, puis la lecture. */
  .rkt-corps-grille {
    grid-template-columns: 15rem 1fr;
    gap: var(--sp-6);
    align-items: start;
  }

  /*
   * QUAND LA COLONNE DE GAUCHE EST VIDE, la grille n'a pas a la reserver.
   * Sans cette regle, le rail vide ne produisant aucun element, la colonne de
   * lecture glissait dans la place du rail : 224 px au lieu de 468, mesure a
   * 1440 px sur les trois pages sans rubrique le 2026-07-30. Deux classes contre
   * une, la regle l'emporte quel que soit l'ordre du fichier.
   */
  .rkt-corps-grille--sans-gauche { grid-template-columns: 1fr; }

  /*
   * Trois colonnes quand la colonne d'appui a de la matiere. Depuis
   * `PROMPT-104`, ce cas ne se produit plus que sur `contact/standard.php`
   * (bloc « Coordonnees »), les trois gabarits de rubrique ne posant plus ce
   * modificateur.
   */
  .rkt-corps-grille--appui { grid-template-columns: 14rem 1fr 16rem; }
  .rkt-corps-grille--sans-gauche.rkt-corps-grille--appui { grid-template-columns: 1fr 16rem; }

  /*
   * Un sommaire qui defile hors de l'ecran ne sert a rien : le suivi de la
   * lecture n'a de sens que si l'on voit ou il en est. Il reste donc sous
   * l'en-tete pendant toute la descente. `align-items: start` sur la grille,
   * pose plus haut, est ce qui rend ce collage possible.
   */
  .rkt-rail--sommaire {
    position: sticky;
    top: 5rem;
    max-height: calc(100vh - 7rem);
    overflow-y: auto;
  }

  .rkt-rubrique .rkt-prose h2 { scroll-margin-top: 11rem; }

  /* Deux classes, pour passer devant `.rkt p` sur les marges. */
  .rkt-rail--sommaire .rkt-sommaire-titre {
    display: block;
    margin: 0 0 var(--sp-2);
    padding-left: var(--sp-2);
    border-left: 4px solid var(--c-primary);
    font-family: var(--f-heading);
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--c-heading);
  }

  /* En bureau le rail est deploye en permanence : son bouton n'a plus d'objet. */
  .rkt-rail-bascule { display: none; }
  .rkt-rail-liste { display: block; }

  .rkt-rubrique .rkt-tuiles--3 { grid-template-columns: repeat(3, 1fr); }
  .rkt-rubrique .rkt-tuiles--4 { grid-template-columns: repeat(4, 1fr); }
}

/*
 * La transition du chevron est DECLAREE sous « no-preference », et non annulee
 * ensuite sous « reduce ». Mesure faite au navigateur : la garde generale du
 * produit porte sur `.rkt *`, de specificite (0,1,0), et perd donc contre toute
 * regle de composant a deux classes. Annuler apres coup n'aurait rien annule.
 */
@media (prefers-reduced-motion: no-preference) {
  /*
   * LE DEFILEMENT DOUX DES ANCRES, et le piege qu'il faut nommer. La garde
   * generale du produit annule `scroll-behavior` sur `.rkt *`, or `.rkt` est sur
   * le corps de page : `html`, qui est le seul element ou `scroll-behavior`
   * compte pour le defilement du document, N'EST PAS COUVERT par cette garde.
   * Declarer le mouvement ici est donc la seule facon de le rendre reellement
   * conditionnel. Sous « reduce », le saut redevient instantane, ce qui est le
   * comportement natif d'une ancre.
   */
  html { scroll-behavior: smooth; }

  .rkt-rail-chevron { transition: transform var(--transition); }
  .rkt-rubrique .rkt-tuile a { transition: background-color var(--transition), border-color var(--transition); }
  .rkt-rail-entree a { transition: background-color var(--transition); }
}

/* ══ T3 – Archive des partenaires ═══════════════════════════════════════════
 *
 * Bloc ecrit par le couloir T3 (PROMPT-56), a la fin du fichier et sans rien
 * reformater au-dessus : la feuille appartient au couloir T1.
 *
 * La forme reprend celle relevee sur l'autre site de l'etablissement : une
 * grille unique de cartes, chacune ouverte par une zone de logo sur fond clair.
 * Le logo d'un partenaire arrive dans un format qu'on ne choisit pas, carre ou
 * tres horizontal ; la zone lui donne une hauteur fixe et le contient sans le
 * deformer, ce qui aligne les noms d'une carte a l'autre.
 *
 * Les couleurs restent celles des jetons. La source distingue les natures par
 * quatre teintes ; les reproduire aurait demande d'inventer une palette que la
 * charte du produit ne porte pas. Le badge garde donc une seule teinte, et
 * c'est le libelle qui distingue.
 */

.rkt-pastilles {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin-bottom: var(--sp-4);
}

.rkt-pastille {
  display: inline-block;
  padding: 0.35rem 0.9rem;
  border: 1px solid var(--c-filet);
  border-radius: 999px;
  background: var(--c-bg);
  color: var(--c-text-doux);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  text-decoration: none;
}

.rkt-pastille:hover,
.rkt-pastille:focus-visible {
  border-color: var(--c-primary);
  color: var(--c-primary-dark);
}

/* L'etat courant se lit sans la couleur seule : le fond plein et la graisse
   portent la meme information, pour un lecteur daltonien comme pour une
   impression en noir et blanc. */
.rkt-pastille.est-active {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-sur-primary);
}

.rkt-partenaires {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
}

.rkt-partenaire {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--c-filet);
  border-radius: var(--radius);
  background: var(--c-bg);
  overflow: hidden;
}

/*
 * PROMPT-107 (T1) : la carte entiere est le lien, patron deja retenu pour
 * `rkt-chiffre-lien` et `rkt-mosaique-lien`. L'ancre remplit la carte -- un
 * seul arret dans l'ordre de tabulation, une cible large a la souris.
 */
.rkt-partenaire-lien {
  display: flex;
  flex-direction: column;
  flex: 1;
  height: 100%;
  color: inherit;
  text-decoration: none;
}

/*
 * Survol ET focus se lisent sur toute la carte, pas seulement sur le nom :
 * la bordure fonce et l'aplat pale portent la meme information que le
 * `:focus-within` de `.rkt-carte`, applique ici a l'article puisque l'ancre
 * unique en est l'unique enfant.
 */
.rkt-partenaire:hover,
.rkt-partenaire:focus-within {
  border-color: var(--c-primary);
  background: var(--c-primary-pale);
}

.rkt-partenaire:hover .rkt-partenaire-nom,
.rkt-partenaire:focus-within .rkt-partenaire-nom {
  text-decoration: underline;
}

/*
 * L'etat de focus est obligatoire (PROMPT-107). Le contour par defaut de
 * `.rkt :focus-visible` a un `outline-offset` positif, qui se ferait couper
 * par le `overflow: hidden` de `.rkt-partenaire` : meme raison que
 * `rkt-mosaique-lien:focus-visible`, l'ecart passe donc en negatif pour
 * rester a l'interieur de la carte.
 */
.rkt .rkt-partenaire-lien:focus-visible {
  outline-offset: -2px;
}

.rkt-partenaire-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 140px;
  padding: var(--sp-2);
  background: var(--c-bg-alt);
  border-bottom: 1px solid var(--c-filet);
}

.rkt-partenaire-logo img {
  max-height: 100px;
  max-width: 180px;
  width: auto;
  height: auto;
  object-fit: contain;
}

.rkt-partenaire-jeton {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--c-primary);
  color: var(--c-sur-primary);
  font-family: var(--f-heading);
  font-size: 26px;
  font-weight: 700;
  line-height: 1;
}

.rkt-partenaire-corps {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  padding: var(--sp-2);
  flex: 1;
}

/*
 * PROMPT-107 (T1) : la carte se reduit au logo et au nom -- le pays,
 * l'etiquette de nature, la description et le lien externe sont retires de
 * l'archive (ils restent sur la fiche individuelle, `fiche-generique/
 * standard.php`, non touchee par ce lot). Le titre n'est plus un lien : la
 * carte entiere l'est, via `.rkt-partenaire-lien` ci-dessus -- il ne peut pas
 * y avoir de lien dans un lien.
 */
.rkt-partenaire-nom {
  margin: 0;
  color: var(--c-heading);
  font-size: var(--fs-h3);
  line-height: var(--lh-heading);
}

.rkt-vide {
  padding: var(--sp-6) 0;
  text-align: center;
  color: var(--c-text-doux);
}

@media (min-width: 768px) {
  .rkt-partenaires { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .rkt-partenaires { grid-template-columns: repeat(3, 1fr); }
}

@media (prefers-reduced-motion: no-preference) {
  .rkt-pastille { transition: background-color var(--transition), border-color var(--transition), color var(--transition); }
}

/* ══ T3 – Les cartes d'archive au langage des tuiles ════════════════════════
 *
 * Bloc ecrit par le couloir T3 (PROMPT-65), a la fin du fichier et sans rien
 * reformater au-dessus.
 *
 * La carte du produit portait une ombre au repos et se soulevait au survol.
 * La tuile, posee au CR-52, ne fait ni l'un ni l'autre : un filet fin, et un
 * aplat au survol. Deux langages coexistaient sur des pages voisines. Les
 * regles ci-dessous alignent la carte sur la tuile SANS toucher a son
 * balisage : il n'y a toujours qu'une seule carte dans le produit.
 *
 * Le soulevement est retire pour une raison de plus que la coherence : sur une
 * grille de vingt-sept programmes, il faisait bouger la rangee entiere sous le
 * pointeur.
 */

.rkt-carte {
  box-shadow: none;
  border-color: var(--c-filet);
}

/*
 * Le survol se lit sans la couleur seule : le filet fonce ET le fond passe en
 * aplat pale. Une bordure qui change de teinte seule ne se voit pas d'un
 * ecran a l'autre, ni en niveaux de gris.
 */
.rkt-carte:hover,
.rkt-carte:focus-within {
  transform: none;
  border-color: var(--c-primary);
  background: var(--c-primary-pale);
  box-shadow: var(--shadow);
}

/* Le corps de la carte suit l'aplat : sans cela, un fond blanc pose dessus
   annulait le survol sur toute la partie basse. */
.rkt-carte:hover .rkt-carte-corps,
.rkt-carte:focus-within .rkt-carte-corps {
  background: transparent;
}

/*
 * Hauteurs egales par rangee. La carte demandait deja `height: 100 %`, mais
 * une grille dont les elements ne s'etirent pas la laissait sans effet : la
 * regle est posee sur la grille, la ou elle agit.
 */
.rkt-grille { align-items: stretch; }

@media (prefers-reduced-motion: no-preference) {
  .rkt-carte { transition: border-color var(--transition), background-color var(--transition), box-shadow var(--transition); }
}

/* ══ T3 – Vague 3 : la vedette d'archive et l'article ═══════════════════════
 *
 * Bloc ecrit par le couloir T3 (PROMPT-85), a la fin du fichier et sans rien
 * reformater au-dessus.
 *
 * Aucune couleur nouvelle : la regle 1 de la SPEC-DESIGN V2 veut que la
 * diversite vienne de la COMPOSITION, jamais de la palette. Tout ce qui suit
 * n'emploie que des jetons deja poses.
 */

/* ── Archetype E : la grille editoriale a vedette ─────────────────────────── */

.rkt-vedette {
  display: grid;
  grid-template-columns: 1fr;
  margin-bottom: var(--sp-4);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--c-encre);
}

.rkt-vedette-media { min-width: 0; }

.rkt-vedette-media img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 220px;
  object-fit: cover;
}

.rkt-vedette-corps {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-1);
  padding: var(--sp-3) var(--sp-2);
  color: #ffffff;
}

/*
 * Contrastes mesures sur l'aplat --c-encre (#12263a) : blanc pur 15,40:1,
 * chapeau a 85 % 11,40:1, date a 75 % 9,23:1. Les trois passent AAA (7:1),
 * ce qui laisse la marge necessaire si un client eclaircit sa charte.
 */
.rkt-vedette-date {
  margin: 0;
  font-size: var(--fs-meta);
  color: rgba(255, 255, 255, 0.75);
}

.rkt-vedette-titre {
  margin: 0;
  font-size: var(--fs-h2);
  line-height: var(--lh-heading);
}

.rkt-vedette-titre a {
  color: #ffffff;
  text-decoration: none;
}

.rkt-vedette-titre a:hover,
.rkt-vedette-titre a:focus-visible { text-decoration: underline; }

.rkt-vedette-chapeau {
  margin: 0;
  color: rgba(255, 255, 255, 0.85);
}

/* Sans image, la vedette garde son aplat et respire davantage : elle reste une
   vedette, elle ne redevient pas une carte. */
.rkt-vedette--sans-image .rkt-vedette-corps { padding: var(--sp-4) var(--sp-3); }

/*
 * Le fil d'Ariane sur bande foncee, pleine largeur, sous l'en-tete. Reste en
 * service pour la fiche Evenement (`PROMPT-132`) : la fiche d'article ne
 * l'appelle plus depuis le `PROMPT-138`, elle porte son propre bandeau
 * (§33.4 plus bas).
 */
.rkt-fil-bande { background: var(--c-encre); }

.rkt-fil-bande .rkt-fil {
  background: transparent;
  border-bottom: 0;
}

.rkt-fil-bande .rkt-fil a,
.rkt-fil-bande .rkt-fil [aria-current="page"],
.rkt-fil-bande .rkt-fil-sep { color: rgba(255, 255, 255, 0.85); }

.rkt-fil-bande .rkt-fil a:hover { color: #ffffff; }

@media (min-width: 768px) {
  .rkt-vedette { grid-template-columns: 1fr 1fr; }
  .rkt-vedette-corps { padding: var(--sp-4); }
  .rkt-vedette--sans-image { grid-template-columns: 1fr; }
}

@media (min-width: 1024px) {
  .rkt-vedette-titre { font-size: calc(var(--fs-h2) * 1.15); }
}

/* ══ 16bis. La fiche d'article (PROMPT-138, remplacement complet) ═══════════
 *
 * Modele suivi a la lettre : `single-post.php` d'INUFOCAD (lu en lecture
 * seule). Couleurs et polices : celles du produit, jamais celles d'un
 * etablissement -- voir le doc-bloc du gabarit pour le detail complet.
 */

/* ── 16bis.1 Le bandeau : photo floutee et assombrie, degrade par-dessus ──
 *
 * DEUX COUCHES, PAS UNE. `.rkt-art-hero-photo` (posee par le gabarit
 * seulement si une image existe) porte la photo, floutee et assombrie PAR
 * FILTRE (`brightness()`, pas une opacite melangee) : voir le doc-bloc du
 * gabarit pour la mesure qui a impose ce choix -- un degrade en rgba() par
 * dessus laissait un texte source large rester lisible en fantome. Le
 * degrade de `.rkt-art-hero` reste par-dessus pour la teinte et le
 * contraste ; il n'est plus seul a les garantir. SANS IMAGE, ce degrade est
 * le seul fond -- le bandeau ne change pas de forme, comme demande.
 */
.rkt-art-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--c-encre-profond), var(--c-encre));
  color: #ffffff;
  padding: var(--sp-4) 0 var(--sp-6);
}

.rkt-art-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(13, 28, 44, 0.86), rgba(18, 38, 58, 0.72));
  z-index: 1;
}

.rkt-art-hero-photo {
  position: absolute;
  inset: -16px;
  background-size: cover;
  background-position: center;
  /* `brightness()` multiplie chaque canal, `blur()` detruit les bords nets
     du texte source : les deux ensemble rendent une forme devinee, jamais
     lue, quel que soit le visuel pose en amont. */
  filter: blur(14px) brightness(0.32) saturate(0.85);
  transform: scale(1.08);
}

.rkt-art-hero-dedans { position: relative; z-index: 2; max-width: var(--w-content); }

.rkt-art-fil {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-meta);
  color: rgba(255, 255, 255, 0.85);
}

.rkt-art-fil a { color: rgba(255, 255, 255, 0.95); text-decoration: none; }
.rkt-art-fil a:hover { text-decoration: underline; }
.rkt-art-fil span[aria-hidden] { color: rgba(255, 255, 255, 0.55); margin: 0 0.3em; }

.rkt-art-hero-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}

.rkt .rkt-art-badge {
  display: inline-block;
  background: var(--c-accent);
  color: var(--c-sur-accent);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.3rem 0.9rem;
  border-radius: 999px;
  text-decoration: none;
}

.rkt-art-lecture { font-size: var(--fs-meta); color: rgba(255, 255, 255, 0.85); }

/*
 * LE PIÈGE DE SPÉCIFICITÉ, ENCORE : `.rkt h1` (0,1,1) impose déjà
 * `color: var(--c-heading)`, une encre sombre — sur ce bandeau, ELLE
 * COÏNCIDE PRESQUE AVEC LE FOND, rendant le titre proche de l'invisible.
 * `.rkt-art-titre` seule (0,1,0) perdait contre elle. Défaut réel signalé
 * par Michelot, corrigé ici par le préfixe `.rkt`, jamais par `!important`.
 */
.rkt .rkt-art-titre {
  margin: 0 0 var(--sp-2);
  color: #ffffff;
  font-size: clamp(1.6rem, 1.2rem + 1.8vw, 2.4rem);
  line-height: var(--lh-heading);
}

.rkt-art-date {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: var(--fs-meta);
  color: rgba(255, 255, 255, 0.85);
}

/* ── 16bis.2 Le corps, deux colonnes ───────────────────────────────────── */

.rkt-art-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-2) var(--sp-8);
}

@media (min-width: 1024px) {
  .rkt-art-grille { grid-template-columns: minmax(0, 1fr) 300px; gap: var(--sp-6); }
  .rkt-art-aside { position: sticky; top: 96px; }
}

.rkt-art-carte {
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  padding: var(--sp-4);
}

.rkt-art-image { margin: 0 0 var(--sp-3); }
.rkt-art-image img { display: block; width: 100%; height: auto; border-radius: var(--radius-petit); }

.rkt .rkt-art-chapeau {
  max-width: none;
  margin: 0 0 var(--sp-3);
  padding-left: var(--sp-2);
  border-left: 3px solid var(--c-accent);
  font-size: 1.1rem;
  font-weight: 500;
  color: var(--c-text-doux);
}

.rkt-art-etiquettes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--c-bordure);
}

.rkt .rkt-art-etiquettes a {
  font-size: var(--fs-meta);
  font-weight: 600;
  color: var(--c-primary-dark);
  background: var(--c-bg-alt);
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  text-decoration: none;
}

.rkt .rkt-art-etiquettes a:hover { background: var(--c-primary-voile); }

/* ── 16bis.3 Le partage, trois boutons texte aux couleurs des reseaux ─────
 *
 * Identite de marque publique et universelle (Facebook, X, LinkedIn), pas
 * celle d'un etablissement : la meme exception que les icones de reseaux du
 * pied de page (`PROMPT-131`), pour la meme raison.
 */
.rkt-art-partage {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1);
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--c-bordure);
}

.rkt-art-partage-intitule {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  color: var(--c-text-doux);
  margin-right: 0.3rem;
}

.rkt .rkt-art-partage-bouton {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1rem;
  border-radius: var(--radius-petit);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  color: #ffffff;
  text-decoration: none;
}

/* Trois teintes de marque, mesurees pour le blanc dessus :
   Facebook #1877f2 -> 4,51:1 ; X #000 -> 21:1 ; LinkedIn #0a66c2 -> 4,79:1. */
.rkt-art-partage-fb { background: #1877f2; }
.rkt-art-partage-x { background: #000000; }
.rkt-art-partage-li { background: #0a66c2; }
.rkt .rkt-art-partage-bouton:hover { opacity: 0.88; color: #ffffff; }

.rkt-art-nav {
  display: grid;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--c-bordure);
}

@media (min-width: 600px) {
  .rkt-art-nav { grid-template-columns: 1fr 1fr; }
}

.rkt-art-nav-lien {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: var(--sp-2);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  text-decoration: none;
}

.rkt-art-nav-lien:hover { border-color: var(--c-primary); background: var(--c-bg-alt); }
.rkt-art-nav-lien--suivant { text-align: right; align-items: flex-end; grid-column: 2; }

.rkt-art-nav-libelle {
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  color: var(--c-primary-dark);
}

.rkt .rkt-art-nav-titre { color: var(--c-heading); font-weight: 600; }

/* ── 16bis.4 La colonne : « À lire aussi » puis le bloc d'appel ──────────── */

.rkt-art-aside { display: flex; flex-direction: column; gap: var(--sp-3); }

.rkt-art-liees {
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  padding: var(--sp-3);
}

.rkt-art-liees h2 {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-h3);
  color: var(--c-heading);
}

.rkt-art-liee {
  display: flex;
  gap: var(--sp-2);
  padding: var(--sp-2) 0;
  border-top: 1px solid var(--c-bordure);
  text-decoration: none;
}

.rkt-art-liee:first-of-type { border-top: 0; padding-top: 0; }

.rkt-art-liee-media {
  flex: 0 0 4.25rem;
  width: 4.25rem;
  height: 3.4rem;
  border-radius: var(--radius-petit);
  overflow: hidden;
  background: var(--c-bg-alt);
}

.rkt-art-liee-media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.rkt-art-liee-corps { display: flex; flex-direction: column; min-width: 0; }

.rkt-art-liee-cat {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-primary-dark);
}

.rkt .rkt-art-liee-titre {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--c-heading);
  line-height: 1.35;
  margin: 0.1rem 0;
}

.rkt-art-liee:hover .rkt-art-liee-titre { color: var(--c-primary); }
.rkt-art-liee-date { font-size: 0.72rem; color: var(--c-text-doux); }

.rkt-art-appel {
  background: var(--c-primary-dark);
  color: #ffffff;
  border-radius: var(--radius);
  padding: var(--sp-3);
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}

/* Meme piege que `.rkt-art-titre` : `.rkt h2` (0,1,1) vaut autant que
   `.rkt-art-appel h2` non prefixe -- corrige avant qu'il ne se reproduise. */
.rkt .rkt-art-appel h2 { margin: 0; font-size: 1.1rem; color: #ffffff; }
.rkt-art-appel p { margin: 0; font-size: 0.88rem; color: rgba(255, 255, 255, 0.85); }

.rkt .rkt-art-appel-bouton {
  display: block;
  text-align: center;
  background: var(--c-accent);
  color: var(--c-sur-accent);
  font-weight: 700;
  padding: 0.6rem;
  border-radius: var(--radius-petit);
  text-decoration: none;
  margin-top: 0.3rem;
}

.rkt .rkt-art-appel-lien {
  display: block;
  text-align: center;
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.85rem;
  text-decoration: none;
}

.rkt .rkt-art-appel-lien:hover { color: #ffffff; }

/* ══ 17. Vague 3 – L'archetype CARREFOUR ═════════════════════════════════════
 *
 * Deux gestes, et deux seulement : le panneau mordant a l'ouverture, la mosaique
 * bord a bord a la place des tuiles a filet. Aucune couleur nouvelle : tout est
 * jeton de la charte. La diversite vient de la composition.
 */

/* ── 17.1 L'ouverture a panneau mordant ───────────────────────────────────── */

.rkt-panneau-fil { padding-top: var(--sp-2); padding-bottom: var(--sp-2); }

/*
 * La scene. Sans photographie elle n'impose aucune hauteur : le panneau seul
 * fait la bande, et rien ne parait manquer.
 */
.rkt-panneau-scene { position: relative; }

/*
 * LE CADRE PORTE LA HAUTEUR, L'IMAGE LE REMPLIT. Une seule source de verite.
 *
 * Le premier jet en avait deux : le cadre etait a 420 px et l'image a 320 px,
 * heritee du palier de 768 px. Resultat en production sur trois pages : une
 * bande de 100 px de blanc sous la photographie, et le panneau qui flottait
 * dessus sans rien mordre. Deux regles pour une meme hauteur finissent toujours
 * par diverger ; il n'y en a plus qu'une, celle du cadre.
 */
.rkt-panneau-media {
  position: relative;
  height: 220px;
  line-height: 0;
}

/*
 * SPECIFICITE : le selecteur descend a deux classes parce que la regle generique
 * des images du produit, `.rkt img { height: auto }`, est de specificite (0,1,1)
 * et l'emportait sur une classe seule. La hauteur etait ignoree et la
 * photographie prenait sa proportion naturelle. Meme piege qu'aux lots 46 et 53,
 * troisieme fois.
 */
.rkt .rkt-panneau-photo {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
}

/*
 * Le panneau. Aplat plein, sans arrondi, sans ombre : il doit trancher sur la
 * photographie, pas s'y poser en douceur.
 */
/*
 * Sous 1024 px, le panneau passe SOUS la photographie et prend la PLEINE LARGEUR
 * DE FENETRE : le conteneur ne doit donc pas lui imposer ses marges. Son propre
 * rembourrage tient le texte a distance du bord.
 */
.rkt-panneau-place { padding-left: 0; padding-right: 0; }

.rkt-panneau {
  background: var(--c-primary);
  color: var(--c-sur-primary);
  padding: var(--sp-4) var(--sp-3);
}

.rkt .rkt-panneau-titre {
  margin: 0;
  /*
   * LA COULEUR EST REDECLAREE ICI, et sans elle le titre etait INVISIBLE. La
   * regle generique des titres, `.rkt h1 { color: var(--c-heading) }`, est de
   * specificite (0,1,1) : elle ecrivait le titre en bleu nuit sur l'aplat bleu du
   * panneau. Mesure du 2026-07-30. Meme piege qu'au lot 53, et il faut deux
   * classes pour le battre.
   */
  color: var(--c-sur-primary);
  /*
   * DEUX CRANS SOUS le titre de bureau, comme la regle 4 de la spec le demande
   * pour 375 px : l'affiche perd deux crans, elle ne perd pas sa nature.
   */
  font-size: calc(var(--fs-h1) * 1.1);
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -0.02em;

  /*
   * Trois lignes au plus, puis la coupe. Un titre de rubrique tres long ne doit
   * pas pousser le panneau hors de la photographie.
   */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Sur l'aplat principal, un contour bleu ne se verrait pas. */
.rkt-panneau :focus-visible { outline-color: #ffffff; }

@media (min-width: 768px) {
  .rkt-panneau-media { height: 320px; }
}

@media (min-width: 1024px) {
  /*
   * LE MORDANT, sans une seule marge negative. La scene porte un rembourrage
   * bas ; la photographie s'arrete a la hauteur de ce rembourrage ; le panneau
   * descend jusqu'au bas de la scene. Sa partie basse repose donc sur le blanc
   * de la page, sa partie haute sur la photographie.
   *
   * Une marge negative aurait donne le meme dessin et le piege du lot 46 : elle
   * s'echappe de son bloc et remonte la bande.
   */
  /*
   * LA SCENE EST PLUS HAUTE QUE LA PHOTOGRAPHIE, d'exactement la profondeur de
   * la morsure. La photographie occupe le haut, le panneau descend jusqu'en bas :
   * sa partie basse repose donc sur le blanc de la page.
   *
   * Premier jet mesure : la scene portait un rembourrage bas et la zone du
   * panneau s'arretait au meme endroit que la photographie. Le panneau ne
   * mordait pas, il etait simplement pose dedans, en bas a droite. Le
   * chevauchement mesurait 133 px et le depassement 0.
   */
  .rkt-panneau-ouverture--photo .rkt-panneau-scene {
    min-height: calc(420px + var(--sp-6));
  }

  .rkt-panneau-ouverture--photo .rkt-panneau-media {
    position: absolute;
    inset: 0 0 auto 0;
    height: 420px;
  }

  /* Sans photographie, aucune hauteur n'est reservee a du vide : le cadre
     n'existe pas, la scene se regle sur le panneau seul. */
  .rkt-panneau-ouverture:not(.rkt-panneau-ouverture--photo) .rkt-panneau-scene { min-height: 0; }

  .rkt-panneau-place {
    position: relative;
    display: flex;
    justify-content: flex-end;
    align-items: flex-end;
    min-height: inherit;
  }

  .rkt-panneau-ouverture--photo .rkt-panneau-place {
    min-height: calc(420px + var(--sp-6));
  }

  .rkt-panneau-place {
    padding-left: var(--sp-2);
    padding-right: var(--sp-2);
  }

  .rkt-panneau {
    width: 46%;
    padding: var(--sp-4);
  }

  .rkt .rkt-panneau-titre { font-size: calc(var(--fs-h1) * 1.95); }

  /* Sans photographie, le panneau prend toute la largeur du conteneur. */
  .rkt-panneau-ouverture:not(.rkt-panneau-ouverture--photo) .rkt-panneau { width: 100%; }
}

/* Le corps du carrefour respire sous la bande. */
.rkt-carrefour-corps { padding: var(--sp-6) 0; }

/* ── 17.2 La mosaique de tuiles a fond photographique ─────────────────────── */

.rkt-mosaique {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;              /* bord a bord : c'est la moitie de l'effet */
  list-style: none;
  margin: 0;
  padding: 0;
}

.rkt-mosaique-tuile { position: relative; }

/*
 * L'aplat de repli alterne DEUX DEGRES de la couleur principale selon le rang.
 * Quatre aplats identiques ne se lisent pas comme une mosaique mais comme un
 * bloc. Aucune couleur nouvelle : ce sont deux jetons de la charte.
 */
.rkt-mosaique-tuile--degre-1 { background: var(--c-primary); }
.rkt-mosaique-tuile--degre-0 { background: var(--c-primary-dark); }

/*
 * LA COULEUR DU TEXTE EST DECLAREE A DEUX CLASSES, et ce n'est pas un exces de
 * prudence : `.rkt a { color: var(--c-primary-dark) }` est de specificite (0,1,1)
 * et l'emportait. Le titre des tuiles sortait en bleu fonce sur un fond sombre,
 * donc illisible. Mesure du 2026-07-30 : rgb(0, 74, 140) au lieu du blanc.
 * Quatrieme fois que cette regle generique bat une regle de composant sur ce
 * chantier, apres les lots 46, 53 et le titre du panneau ci-dessus.
 */
.rkt .rkt-mosaique-lien {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: 240px;
  padding: var(--sp-3);
  color: #ffffff;
  text-decoration: none;
}

.rkt .rkt-mosaique-lien:hover { color: #ffffff; }

/*
 * L'ORDRE DE PEINTURE EST EXPLICITE, et il ne l'etait pas. Le voile est un
 * `::before`, donc le PREMIER enfant du lien ; l'image vient apres dans l'arbre.
 * A egalite de plan, c'est l'ordre du document qui decide : l'image se peignait
 * PAR-DESSUS le voile, qui ne voilait donc rien.
 *
 * Invisible a la lecture du code, invisible a l'oeil sur une photographie deja
 * sombre. Trouve en echantillonnant le pixel le plus clair sous chaque titre :
 * 255,255,255 sur les tuiles a photographie, contraste 1,0 contre du texte blanc.
 */
.rkt-mosaique-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/*
 * LE VOILE N'EST PAS UN EFFET, C'EST LA GARANTIE DE CONTRASTE, et sa valeur est
 * calculee, pas choisie a l'oeil.
 *
 * Le cas defavorable est une zone BLANCHE de la photographie sous le texte. Pour
 * que du texte blanc y tienne le rapport AA de 4,5:1, la couleur composee doit
 * descendre a 119 sur 255 au plus. Un voile noir d'opacite a sur du blanc donne
 * 255 (1 - a) : il faut donc a >= 0,535. Le voile est pose a 0,62 en haut, ou le
 * texte se trouve, et ne descend jamais sous 0,58, ce qui laisse de la marge
 * meme sur une photographie surexposee.
 *
 * Consequence assumee : la photographie est nettement assombrie. C'est le prix
 * d'un texte lisible sur une image qu'on ne choisit pas, et la spec le pose comme
 * obligatoire.
 */
.rkt-mosaique-lien::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.62) 0%,
    rgba(0, 0, 0, 0.58) 55%,
    rgba(0, 0, 0, 0.62) 100%
  );
}

/* L'aplat de repli n'a pas besoin du voile : il est deja opaque et calibre. */
.rkt-mosaique-tuile:not(.rkt-mosaique-tuile--photo) .rkt-mosaique-lien::before { display: none; }

.rkt-mosaique-texte,
.rkt-mosaique-chevron { position: relative; z-index: 2; }

.rkt-mosaique-titre {
  display: block;
  font-family: var(--f-heading);
  font-size: var(--fs-h3);
  font-weight: 700;
  line-height: 1.2;
}

.rkt-mosaique-desc {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-meta);
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.92);
}

.rkt-mosaique-chevron {
  align-self: flex-start;
  font-size: 2rem;
  line-height: 1;
}

/* Le contour de focus doit se voir sur une photographie sombre. */
.rkt-mosaique-lien:focus-visible {
  outline: 3px solid #ffffff;
  outline-offset: -6px;
}

@media (min-width: 768px) {
  .rkt-mosaique { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .rkt-mosaique--3 { grid-template-columns: repeat(3, 1fr); }
  .rkt-mosaique--4 { grid-template-columns: repeat(4, 1fr); }

  .rkt-mosaique-lien { min-height: 300px; padding: var(--sp-4); }
}

/*
 * Le mouvement est DECLARE sous « no-preference », jamais annule ensuite : la
 * garde generale du produit porte sur `.rkt *`, de specificite (0,1,0), et perd
 * contre une regle de composant.
 */
@media (prefers-reduced-motion: no-preference) {
  .rkt-mosaique-photo { transition: transform var(--transition); }
  .rkt-mosaique-lien:hover .rkt-mosaique-photo { transform: scale(1.04); }
}

/*
 * Une derniere tuile seule occupe toute la rangee. Sur une mosaique bord a bord,
 * deux tiers de vide en fin de grille se voient bien plus qu'une tuile large.
 */
@media (min-width: 1024px) {
  .rkt-mosaique--3 > .rkt-mosaique-tuile:last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
}

/* ══ 18. Vague 3 – L'archetype CONVERSION ════════════════════════════════════
 *
 * Trois gestes : l'affiche, la bande d'etapes (deja en place), les sections
 * alternees. Et deux absences qui comptent autant : ni rail, ni colonne d'appui.
 */

/* ── 18.1 L'ouverture d'affiche ───────────────────────────────────────────── */

.rkt-affiche {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 320px;
  background: var(--c-primary);
}

.rkt-affiche-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  line-height: 0;
}

/*
 * Deux classes : la regle generique des images du produit, `.rkt img`, est de
 * specificite (0,1,1) et mangerait la hauteur. Piege deja paye trois fois.
 */
.rkt .rkt-affiche-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
}

/*
 * LE VOILE, DOSE PAR LE CALCUL, ET CONCENTRE LA OU LE TEXTE SE TROUVE.
 *
 * Premier jet : un aplat de 0,80 sur toute la surface. Il tenait le contraste et
 * il EFFACAIT LA PHOTOGRAPHIE, releve en production sur les quatre pages. Une
 * photographie invisible coute son poids au chargement et n'apporte rien.
 *
 * LE CRITERE APPLICABLE EST 3:1, ET NON 4,5:1. Le titre fait 110 px en gras :
 * c'est du TRES GRAND TEXTE au sens de WCAG 1.4.3, dont le seuil AA est 3:1. Le
 * premier jet retenait 4,5:1 par prudence, ce qui imposait un voile de 0,784 et
 * ne laissait aucune chance a l'image. Le calcul refait :
 *
 *   luminance relative de l'accent #e9880d ......... 0,3497
 *   pour tenir 3:1, le fond doit descendre a ....... 0,0832, soit 81 sur 255
 *   un voile noir d'opacite a sur du blanc donne ... 255 (1 - a)
 *   il faut donc ................................... a >= 0,682
 *
 * DEUX VOILES SUPERPOSES, et leurs opacites se composent : l'opacite resultante
 * vaut 1 - (1 - a1)(1 - a2). Les paliers viennent de la MESURE des rectangles de
 * ligne du titre sur les quatre pages, pas d'une estimation :
 *
 *   horizontalement  les glyphes s'arretent a 47, 49, 46 et 81 % de la bande
 *   verticalement    ils occupent 37 a 62 %, et 26 a 74 % sur le titre a deux lignes
 *
 * Le palier couvre donc 0 a 84 % en largeur et 14 a 86 % en hauteur. La borne
 * verticale tient compte de TROIS lignes de titre : a 1440 px, trois lignes de
 * 112 px centrees occupent 15 a 85 % de la bande. La borne horizontale tient parce
 * que la largeur du titre est bornee a 16ch, voir la regle du titre.
 *
 * Sous les glyphes : 1 - 0,45 x 0,64 = 0,712, soit un fond a 73 sur 255, sous les
 * 81 exiges ; mesure sur le rendu : 74. Dans les coins a droite : 0,21, soit 201
 * sur 255, ou la photographie se lit pleinement.
 *
 * L'OMBRE PORTEE DU TITRE N'ENTRE PAS DANS LE CALCUL. WCAG mesure le texte contre
 * la couleur de son fond, pas contre un halo. Elle est posee parce qu'elle aide
 * l'oeil, jamais pour tenir un seuil : le seuil est tenu par le voile seul.
 */
.rkt-affiche--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(
      180deg,
      rgba(0, 0, 0, 0.16) 0%,
      rgba(0, 0, 0, 0.55) 14%,
      rgba(0, 0, 0, 0.55) 86%,
      rgba(0, 0, 0, 0.16) 100%
    ),
    linear-gradient(
      90deg,
      rgba(0, 0, 0, 0.36) 0%,
      rgba(0, 0, 0, 0.36) 84%,
      rgba(0, 0, 0, 0.06) 100%
    );
}

.rkt-affiche-dedans {
  position: relative;
  z-index: 2;
  padding-top: var(--sp-6);
  padding-bottom: var(--sp-6);
}

/*
 * LE TITRE D'AFFICHE. Deux classes, pour passer devant `.rkt h1` qui fixe la
 * taille ET la couleur en (0,1,1) : sans cela le titre sortait en bleu nuit a la
 * taille ordinaire, defaut mesure au lot 83 sur le panneau mordant.
 *
 * Les paliers suivent la regle 4 de la spec : deux crans de moins a 1024 px,
 * quatre de moins a 375 px, sur une echelle de 1,25.
 */
/*
 * LA LARGEUR DU TITRE EST BORNEE POUR QUE LE VOILE SUFFISE TOUJOURS, et c'est la
 * raison de ce chiffre, pas une preference de mise en page.
 *
 * Avec 22ch, un titre de deux lignes atteignait 90 % de la bande a 1024 px, donc
 * AU-DELA du palier sombre qui s'arrete a 84 %. Le contraste y tenait encore, a
 * 3,28, mais PAR CHANCE : le pixel de photographie qui se trouvait la etait
 * moyen. Une image plus claire au meme endroit aurait fait tomber le titre sous le
 * seuil.
 *
 * A 16ch, l'extremite des glyphes reste sous 80 % a toutes les largeurs, mesuree.
 * La garantie ne depend plus du cliche.
 */
.rkt .rkt-affiche-titre {
  margin: 0;
  max-width: 16ch;
  font-family: var(--f-heading);
  font-size: calc(var(--fs-h1) * 1.4);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--c-accent);
  text-wrap: balance;
}

/* L'ombre aide l'oeil, elle ne tient aucun seuil : voir la regle du voile. */
.rkt-affiche--photo .rkt-affiche-titre { text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55); }

/* Sans photographie, le titre passe en blanc sur l'aplat : 6,01:1, mesure. */
.rkt-affiche:not(.rkt-affiche--photo) .rkt-affiche-titre { color: var(--c-sur-primary); }

.rkt-affiche :focus-visible { outline-color: #ffffff; }

.rkt-affiche-fil { padding-top: var(--sp-2); padding-bottom: var(--sp-2); }

@media (min-width: 768px) {
  .rkt-affiche { min-height: 400px; }
  .rkt .rkt-affiche-titre { font-size: calc(var(--fs-h1) * 1.8); }
}

@media (min-width: 1024px) {
  .rkt-affiche { min-height: 480px; }

  /*
   * De 70,4 px a 1024 px jusqu'a 110,4 px a 1440 px, en continu, puis plafonne.
   * Les deux bornes sont exactement les deux crans demandes : 110,4 / 1,25 / 1,25
   * fait 70,7.
   */
  .rkt .rkt-affiche-titre {
    font-size: min(6.9rem, calc(4.4rem + 40 * (100vw - 1024px) / 416));
  }
}

/* ── 18.2 Les sections alternees ──────────────────────────────────────────── */

.rkt-alternees { padding: var(--sp-6) 0; }

.rkt-alt + .rkt-alt { margin-top: var(--sp-6); }

/* Sans image, la section reste en pleine largeur de lecture, centree. */
.rkt-alt-texte { max-width: var(--w-narrow); margin-inline: auto; }

/* Le chapeau se lit plus grand, comme sur les pages de contenu. */
.rkt-alt--chapeau .rkt-alt-texte > p:first-child {
  font-size: 1.2rem;
  line-height: 1.55;
}

.rkt-alt-media { margin-top: var(--sp-4); }

.rkt-alt-media img {
  width: 100%;
  height: auto;
}

/* Le filet d'accent sous chaque titre de section : le rythme de la page. */
.rkt-alt .rkt-alt-texte h2 {
  padding-bottom: var(--sp-1);
  border-bottom: 3px solid var(--c-accent);
  display: inline-block;
}

@media (min-width: 1024px) {
  .rkt-alt + .rkt-alt { margin-top: var(--sp-8); }

  /*
   * L'alternance. Une section illustree passe en deux colonnes ; l'ordre visuel
   * s'inverse d'une section illustree a l'autre, SANS toucher a l'ordre du
   * document : un lecteur d'ecran et une tabulation gardent la suite logique
   * titre puis texte puis image.
   */
  .rkt-alt--illustree .rkt-alt-dedans {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-6);
    align-items: center;
  }

  .rkt-alt--illustree .rkt-alt-texte { max-width: none; margin-inline: 0; }
  .rkt-alt--illustree .rkt-alt-media { margin-top: 0; }

  .rkt-alt--gauche .rkt-alt-texte { order: 2; }
  .rkt-alt--gauche .rkt-alt-media { order: 1; }
}

/* ── 18.3 Le sommaire, seule navigation admise ici ────────────────────────── */

.rkt-conversion-sommaire { padding-top: var(--sp-4); }

@media (min-width: 1024px) {
  /*
   * En bureau le sommaire d'une page de conversion se pose en ligne, sur toute la
   * largeur de lecture, plutot qu'en colonne : il n'y a pas de colonne ou le
   * mettre, l'archetype n'en ayant pas.
   */
  .rkt-conversion-sommaire .rkt-rail-liste {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
  }

  .rkt-conversion-sommaire .rkt-rail-entree { flex: 1 1 12rem; }
  .rkt-conversion-sommaire .rkt-rail--sommaire { position: static; max-height: none; }
}

/* ══ 19. Vague 3 – Le catalogue et les questions ══════════════════════════════ */

/* ── 19.1 La barre de sous-navigation du catalogue ────────────────────────── */

/*
 * Bande foncee pleine largeur, juste sous l'ouverture. Le degre fonce de la
 * charte, pas une couleur nouvelle : c'est ce qui la distingue de la bande
 * d'admission, qui est au degre clair.
 */
.rkt-barre-catalogue { background: var(--c-primary-dark); }

.rkt-barre-liste {
  display: flex;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;

  /*
   * SOUS 1024 PX ELLE DEFILE, et c'est le point de ce composant. Replier un
   * catalogue de six entrees derriere un bouton de plus l'enterrerait ; le
   * defilement horizontal le garde sous le doigt. `-webkit-overflow-scrolling`
   * n'est pas necessaire : le defilement tactile est natif depuis longtemps.
   */
  overflow-x: auto;
  scrollbar-width: thin;
}

.rkt-barre-entree { flex: 0 0 auto; }

/*
 * Deux classes pour la couleur : `.rkt a` est en (0,1,1) et sortirait le libelle
 * en bleu fonce sur bleu fonce. Piege paye quatre fois sur ce chantier.
 */
.rkt .rkt-barre-entree a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  color: #ffffff;
  text-decoration: none;
  font-family: var(--f-heading);
  font-size: 0.98rem;
  font-weight: 600;
  white-space: nowrap;
  border-bottom: 3px solid transparent;
}

.rkt .rkt-barre-entree a:hover { background: rgba(255, 255, 255, 0.1); }

/* L'entree courante est marquee par un filet d'accent, pas par un aplat : sur une
   bande foncee, un aplat clair ferait un trou. */
.rkt .rkt-barre-entree--courante a {
  border-bottom-color: var(--c-accent);
  background: rgba(255, 255, 255, 0.08);
}

.rkt-barre-catalogue :focus-visible { outline-color: #ffffff; }

/* ── 19.2 La bande de questions ───────────────────────────────────────────── */

.rkt-questions {
  padding: var(--sp-6) 0;
  background: var(--c-bg-alt);
  border-top: 1px solid var(--c-bordure);
}

.rkt-questions-titre { margin-bottom: var(--sp-4); }

/*
 * LE REGROUPEMENT PAR THEME (`PROMPT-149`, point 2c). Le titre de groupe est
 * un cran sous `.rkt-questions-titre` (`h3` contre `h2`), comme le prompt le
 * demande -- meme echelle que §7 pose deja pour `h2`/`h3`, aucune taille en
 * dur ici.
 */
.rkt-questions-groupe {
  max-width: var(--w-narrow);
  margin: 0 auto;
}

.rkt-questions-groupe + .rkt-questions-groupe { margin-top: var(--sp-4); }

.rkt-questions-groupe-titre {
  margin-bottom: var(--sp-2);
  color: var(--c-primary-dark);
}

.rkt-questions-liste {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: var(--w-narrow);
}

.rkt-question + .rkt-question { margin-top: var(--sp-1); }

/*
 * `PROMPT-159`. Le bloc de question reprend `.rkt-accordeon-section`/
 * `.rkt-accordeon-titre`/`.rkt-accordeon-signe`/`.rkt-accordeon-corps` (§23)
 * DIRECTEMENT dans le balisage -- `.rkt-question-bloc` et `.rkt-question-
 * signe` sont retirees, elles ne portaient plus que des valeurs identiques
 * au socle. Seules deux differences reelles restent, en modificateurs :
 * la typographie du titre (un `span`, pas un `h2`) et l'absence de marge
 * basse sur le dernier paragraphe d'une reponse.
 *
 * Prefixe par `.rkt` : sans lui, `.rkt-question-titre { color: ... }`
 * (0,1,0) et `.rkt-accordeon-titre { color: var(--c-text); }` (0,1,0) sont a
 * egalite de specificite, et l'ordre du fichier deciderait -- le meme piege
 * documente ailleurs dans cette feuille.
 */
.rkt .rkt-question-titre {
  font-family: var(--f-heading);
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-question-reponse > p:last-child { margin-bottom: 0; }

/*
 * ── 19.3 Le rappel de contact (`PROMPT-149`, point 2d) ────────────────────
 *
 * Remplace la bande sombre `bande-admission.php` sur `/admission/questions-
 * frequentes/` : un encadre sobre, pas un aplat pleine largeur. Meme famille
 * de jeton que le reste du produit (`--c-primary-pale`), jamais une couleur
 * nouvelle.
 */
.rkt-rappel-contact {
  margin-top: var(--sp-4);
  padding: var(--sp-3);
  background: var(--c-primary-pale);
  border-radius: var(--radius);
  text-align: center;
}

.rkt-rappel-contact-texte {
  margin: 0 0 var(--sp-2);
  font-weight: 600;
  color: var(--c-heading);
}

/* ══ 20. L'etat d'une session de formation ═══════════════════════════════════
 *
 * Deux lignes en tete de fiche : ce que la session est, et ce que la personne
 * peut faire. Aucune couleur nouvelle. Le filet de gauche reprend le procede des
 * encadres du produit, et il change de degre selon l'etat : c'est la seule
 * distinction visuelle, le texte fait le reste.
 */

.rkt-etat-session {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: var(--sp-3) 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg-alt);
  border-left: 4px solid var(--c-primary);
}

.rkt .rkt-etat-titre {
  font-family: var(--f-heading);
  font-weight: 700;
  color: var(--c-heading);
}

.rkt .rkt-etat-suite { color: var(--c-text); }

/* Une session ouverte est la seule qui appelle une action : elle prend l'accent. */
.rkt-etat-session--ouverte { border-left-color: var(--c-accent); }

/*
 * Une fiche sans date exploitable n'affiche aucun etat : le bloc serait vide, et
 * un bloc vide se retire. Regle du contenant, appliquee a deux lignes.
 */
.rkt-etat-session--indetermine { display: none; }

/* ══ 21. Variante « Carrefour vitrine » (PROMPT-103) ═════════════════════════
 *
 * Deux pieces propres a cette variante : la section deux colonnes sous la
 * surface refermee, et la grille de quatre cartes blanches. Rien de commun
 * n'est retouche.
 */

/*
 * ── 21.0 Le vide sous le titre, corrige apres livraison ─────────────────────
 *
 * Signale par Michelot au premier coup d'oeil en ligne : un grand blanc entre
 * le titre et la section deux colonnes. Cause mesuree, pas supposee : cette
 * variante ferme la surface juste apres le titre (le contrat du `PROMPT-103`),
 * alors que `.rkt-surface-dedans` porte un padding bas de `--sp-8` (64px) et
 * `.rkt-rubrique .rkt-ouverture-titre` une marge basse de `--sp-6` (48px) --
 * les deux pensees pour separer le titre du corps de rubrique qui suit
 * D'HABITUDE dans la MEME surface (rail, texte, tuiles). Ici rien ne suit a
 * l'interieur : les deux valeurs s'empilent en 112px de vide avant meme que la
 * surface se referme, et ma section ajoutait encore son propre padding haut
 * par-dessus.
 *
 * La correction est SCOPEE a `.rkt-carrefour--vitrine`, classe posee sur le
 * `<main>` de cette seule variante : `/institut/direction-et-gouvernance/`
 * (rubrique.php), `/contact/` et `/rendez-vous/` continuent de recevoir les
 * valeurs d'origine, inchangees.
 */
.rkt-carrefour--vitrine .rkt-surface-dedans { padding-bottom: var(--sp-3); }
.rkt-carrefour--vitrine .rkt-ouverture-titre { margin-bottom: 0; }

/* ── 21.1 La section deux colonnes : texte a gauche, image a droite ────────── */

.rkt-vitrine-intro { padding-top: var(--sp-4); }

.rkt-vitrine-intro-texte { max-width: var(--w-narrow); }

.rkt-vitrine-intro-media { margin-top: var(--sp-4); }

.rkt-vitrine-intro-media img {
  width: 100%;
  height: auto;
  border-radius: var(--radius);
}

@media (min-width: 1024px) {
  .rkt-vitrine-intro--media .rkt-conteneur {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-6);
    align-items: center;
  }

  .rkt-vitrine-intro--media .rkt-vitrine-intro-texte { max-width: none; }
  .rkt-vitrine-intro--media .rkt-vitrine-intro-media { margin-top: 0; }
}

/* ── 21.2 Les quatre cartes blanches ─────────────────────────────────────── */

.rkt-cartes-blanches {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-3);
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 1024px) {
  .rkt-cartes-blanches { grid-template-columns: repeat(4, 1fr); }
}

.rkt-cartes-blanches-item { margin: 0; }

/* La carte du produit, reprise telle quelle : fond blanc, ombre, transformation
   au survol. Seul l'interieur change, comme pour `.rkt-carte--cycle`. */
.rkt-carte--vitrine {
  padding: var(--sp-3) var(--sp-2);
  gap: var(--sp-1);
  border-top: 3px solid transparent;
}

.rkt-carte--vitrine:hover { border-top-color: var(--c-accent); }

.rkt-carte--vitrine .rkt-carte-titre { font-size: 1.15rem; }

.rkt-carte-chevron {
  margin-top: auto;
  padding-top: var(--sp-1);
  color: var(--c-primary);
  font-size: 1.5rem;
  line-height: 1;
}

/* ══ 22. Instances de gouvernance (PROMPT-105, T1) ════════════════════════════
 *
 * Deux pieces : la liste de la page d'entree (`liste-instances.php`, rangees
 * cliquables) et le fil de retour de la fiche (`rkt_instance/standard.php`).
 * La grille des membres nommes ne recoit rien ici : elle reprend `.rkt-carte`
 * et `.rkt-grille--3` a l'identique, deja stylees.
 */

/* ── 22.1 La liste des organes ──────────────────────────────────────────── */

.rkt-instances {
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: 0;
}

.rkt-instance-rangee + .rkt-instance-rangee { margin-top: var(--sp-2); }

/*
 * LE FILET VERTICAL, dans la couleur principale : la hierarchie se voit,
 * parce qu'elle est vraie -- le mot du `PROMPT-105`. Meme epaisseur (4px) que
 * le rail de sous-navigation et l'etat courant du sommaire d'ancres, pour
 * rester dans le vocabulaire deja etabli du produit plutot que d'en inventer
 * un second.
 */
.rkt-instance-rangee a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  border-left: 4px solid var(--c-primary);
  background: var(--c-bg-alt);
  color: inherit;
  text-decoration: none;
  transition: background-color var(--transition);
}

.rkt-instance-rangee a:hover,
.rkt-instance-rangee a:focus-visible { background: var(--c-primary-voile); }

/* Le rang, en petites capitales AU-DESSUS du titre -- jamais de numero. */
.rkt-instance-rang {
  display: block;
  margin: 0 0 0.2rem;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt-instance-titre {
  display: block;
  font-family: var(--f-heading);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-instance-extrait {
  display: block;
  margin-top: 0.2rem;
  color: var(--c-text-doux);
  font-size: 1rem;
}

/* ── 22.2 Le fil de retour de la fiche ──────────────────────────────────── */

.rkt-fiche-retour {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-meta);
}

.rkt-fiche-retour a {
  color: var(--c-text-doux);
  text-decoration: none;
}

.rkt-fiche-retour a:hover,
.rkt-fiche-retour a:focus-visible { color: var(--c-primary); text-decoration: underline; }

/*
 * Le rang de la fiche reprend `.rkt-instance-rang` : meme classe que la
 * liste, aucune declaration de plus, seul le contexte (au-dessus du `h1`
 * plutot que dans une rangee) change.
 */
.rkt-fiche-entete .rkt-instance-rang { margin-bottom: var(--sp-1); }

/* ══ 23. Le contenu en accordéon (PROMPT-106, T1) ═════════════════════════════
 *
 * `templates/parts/contenu-accordeon.php` redecoupe le contenu par ses
 * titres de niveau 2 et rend chaque section dans un `details`/`summary`
 * natif. Le patron visuel reprend celui de la bande de questions (§19.2),
 * meme vocabulaire plutot qu'un second : filet vertical epais en tete de
 * bloc, signe plus/moins qui se retourne a l'ouverture.
 *
 * `.rkt-rubrique .rkt-prose h2` porte deja un `scroll-margin-top` et un
 * filet `:not(:first-of-type)` (§16) : le second ne s'applique jamais ici,
 * chaque `h2` etant seul dans son `summary`, donc toujours `:first-of-type`
 * de son parent. Seule la marge generale de `.rkt-prose h2` (§10) doit etre
 * neutralisee pour que le titre s'aligne avec le signe plus/moins.
 */

/*
 * ── LE SOCLE, ENFIN LIVRE (`PROMPT-159`, correctif du `PROMPT-149`, point 0) ─
 *
 * Le filet permanent `border-left: 4px solid var(--c-primary)` est retire :
 * carte contenue (bordure fine, coins arrondis), fond plein UNIQUEMENT sur
 * la section `[open]`, qui remplace la bordure par l'ombre du produit
 * plutot que de l'additionner. Espacement entre sections par `gap` du
 * conteneur, pas par une marge individuelle. Toute piece qui reutilise ces
 * classes de base (`etapes-accordeon.php`, `pieces-a-preparer.php`) herite
 * desormais ce comportement sans rien dupliquer.
 */

.rkt-accordeon {
  margin-top: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.rkt-accordeon-section {
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  overflow: hidden;
}

/* La section ouverte porte l'ombre du produit, jamais une nouvelle valeur --
   `--shadow-fort` existe deja, §7 et ailleurs. Elle REMPLACE la bordure,
   elle ne s'y ajoute pas. */
.rkt-accordeon-section[open] {
  border-color: transparent;
  box-shadow: var(--shadow-fort);
}

/* Le marqueur natif est retire des deux facons qui existent : voir §19.2. */
.rkt-accordeon-titre::-webkit-details-marker { display: none; }

.rkt-accordeon-titre {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  list-style: none;
  padding: var(--sp-2) var(--sp-3);
  background: transparent;
  color: var(--c-text);
  cursor: pointer;
}

.rkt-accordeon-titre:hover,
.rkt-accordeon-titre:focus-visible { background: var(--c-primary-pale); }

/*
 * SEULE LA SECTION `[open]` GARDE LE FOND PLEIN. Une fois ouverte, le survol
 * ne doit pas la faire revenir a l'aplat pale du repos.
 */
.rkt-accordeon-section[open] .rkt-accordeon-titre,
.rkt-accordeon-section[open] .rkt-accordeon-titre:hover,
.rkt-accordeon-section[open] .rkt-accordeon-titre:focus-visible {
  background: var(--c-primary);
  color: var(--c-sur-primary);
}

.rkt-rubrique .rkt-prose .rkt-accordeon-titre h2 {
  margin: 0;
  font-size: 1.15rem;
}

/* Le signe : deux traits qui font un plus, dont l'un disparait a l'ouverture.
   Encre douce au repos (le fond n'est plus fonce), blanc sur la section
   ouverte. */
.rkt-accordeon-signe {
  position: relative;
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
}

.rkt-accordeon-signe::before,
.rkt-accordeon-signe::after {
  content: "";
  position: absolute;
  background: var(--c-text-doux);
}

.rkt-accordeon-signe::before { inset: 6px 0 auto 0; height: 2px; }
.rkt-accordeon-signe::after { inset: 0 auto 0 6px; width: 2px; }

.rkt-accordeon-section[open] .rkt-accordeon-signe::before,
.rkt-accordeon-section[open] .rkt-accordeon-signe::after { background: var(--c-sur-primary); }

.rkt-accordeon-section[open] .rkt-accordeon-signe::after { display: none; }

.rkt-accordeon-corps { padding: 0 var(--sp-3) var(--sp-3); }

.rkt-accordeon-corps > *:first-child { margin-top: 0; }

@media (prefers-reduced-motion: no-preference) {
  .rkt-accordeon-titre { transition: background-color var(--transition); }
}

/*
 * ── L'IMPRESSION ────────────────────────────────────────────────────────
 *
 * Un `details` ferme ne s'imprime pas. Sur un texte reglementaire, c'est un
 * vrai defaut : l'apercu avant impression doit montrer TOUTES les sections,
 * ouvertes, quel que soit l'etat a l'ecran.
 *
 * PREMIERE REGLE `@media print` DE CETTE FEUILLE. Le selecteur porte sur
 * `.rkt details`, jamais sur `.rkt-accordeon-section` seule : la bande de
 * questions (§19.2) est batie sur le meme element natif, et en profite sans
 * qu'une seconde regle soit necessaire.
 *
 * CETTE REGLE SEULE NE SUFFIT PAS, et il faut le dire ici plutot que de
 * laisser croire le contraire : la mesure (export PDF reel) a montre que
 * Chrome ne masque plus le contenu d'un `details` ferme par un simple
 * `display: none` que CSS pourrait annuler -- c'est le meme mecanisme, hors
 * de portee de CSS, qui permet a `Ctrl+F` de retrouver ce contenu sans
 * l'ouvrir. Elle reste posee pour deux raisons : elle est correcte pour un
 * moteur qui masquerait bien par `display: none`, et elle ne coute rien la
 * ou elle ne suffit pas -- c'est `assets/js/rektora.js` (bloc sur
 * `beforeprint`/`afterprint`) qui fait le travail reel dans Chrome, en
 * posant et retirant l'attribut `open`.
 */
@media print {
  .rkt details:not([open]) > :not(summary) {
    display: block;
  }
}

/* ══ 24. L'accordéon des instances de gouvernance (PROMPT-110, T1 ; fond
 *        permanent corrige au PROMPT-164) ══════════════════════════════════
 *
 * `templates/parts/instances-accordeon.php` remplace `liste-instances.php`
 * (§22.1, retiree avec ce lot) : chaque organe n'est plus une rangee dans un
 * encadre, mais une barre depliable. Reprend LE PATRON de §23 -- meme classes
 * de base `.rkt-accordeon`, `.rkt-accordeon-section`, `.rkt-accordeon-titre`,
 * `.rkt-accordeon-signe`, `.rkt-accordeon-corps`.
 *
 * L'IMPRESSION ET L'OUVERTURE PAR ANCRE NE DEMANDENT RIEN ICI : la regle
 * `@media print` et le bloc JavaScript `beforeprint`/`afterprint` de §23
 * portent sur `.rkt details`, jamais sur une classe d'accordeon precise --
 * ces barres en profitent donc sans une ligne de plus.
 *
 * `PROMPT-164` : LE FOND `var(--c-primary)` PERMANENT (ouvert OU ferme) A ETE
 * RETIRE -- DERNIERE DES TROIS VARIANTES A LE PORTER, AUDIT EXHAUSTIF FAIT
 * AVANT CE LOT (recherche de toute regle `*-accordeon-titre` dans ce fichier :
 * le socle §23 corrige au `PROMPT-159`, `.rkt-etape-accordeon-titre`
 * corrige au `PROMPT-149`, et celle-ci -- aucune quatrieme variante trouvee).
 * Assume au `PROMPT-110` par un choix explicite (« la couleur ne change pas
 * avec l'etat, c'est elle qui identifie l'organe »), ce choix contredisait
 * la regle etablie depuis sur le reste du produit. Plus aucune couleur
 * propre sur `.rkt-instance-accordeon-titre` ni `.rkt-instance-accordeon-
 * signe` : les deux heritent entierement du socle (transparent au repos,
 * `var(--c-primary-pale)` au survol, `var(--c-primary)` plein uniquement sur
 * `[open]`).
 */

/*
 * LE RANG ET LE NOM. Le filet vertical assoupli : `--c-accent` (3px) etait
 * pense pour trancher sur un fond bleu plein permanent, DEVENU TROP APPUYE
 * sur un fond transparent/pale -- remplace par un filet fin neutre
 * (`--c-bordure`, 1px), meme idiome que les autres filets discrets du
 * produit. LA COULEUR DU TEXTE SUIT DESORMAIS L'ETAT, comme le reste de la
 * barre : encre douce au repos, blanc sur la section ouverte -- jamais fixe.
 * PAS DE JETON ROND ICI : a la difference du rang numerote des etapes
 * d'admission, ce surtitre categoriel est absent sur deux des cinq organes
 * (verifie en production) et n'est pas une sequence -- lui inventer un jeton
 * serait un mecanisme sans objet.
 */
.rkt-instance-accordeon-entete {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
  min-width: 0;
}

.rkt-instance-accordeon-rang {
  flex: 0 0 auto;
  padding-right: var(--sp-2);
  border-right: 1px solid var(--c-bordure);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt-instance-accordeon-nom {
  font-family: var(--f-heading);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--c-text);
}

.rkt-accordeon-section[open] .rkt-instance-accordeon-rang,
.rkt-accordeon-section[open] .rkt-instance-accordeon-nom {
  color: var(--c-sur-primary);
}

/*
 * LE CORPS DEPLIE. Pas de classe `.rkt-prose` ici -- a la difference de
 * `bande-questions.php` -- parce que cette piece est appelee depuis
 * `.rkt-colonne-lecture` d'une page `.rkt-rubrique--sous-page` : `.rkt-prose`
 * y porterait la regle du chapeau (`.rkt-rubrique--sous-page .rkt-colonne-
 * lecture .rkt-prose > p:first-child`, §16), qui grossirait a tort le premier
 * paragraphe des attributions de CHACUNE des cinq barres. Les titres internes
 * (composition, membres) recoivent donc leur propre espacement, plutot que
 * celui de `.rkt-prose h2`.
 */
.rkt-instance-accordeon-corps h2 {
  margin-top: var(--sp-4);
  font-size: 1.15rem;
}

.rkt-instance-accordeon-corps > *:first-child,
.rkt-instance-accordeon-corps h2:first-child { margin-top: 0; }

.rkt-instance-accordeon-corps .rkt-section { margin-top: var(--sp-4); }

.rkt-instance-accordeon-lien {
  margin-top: var(--sp-4);
  font-weight: 600;
}

.rkt-instance-accordeon-lien a { color: var(--c-primary); }
.rkt-instance-accordeon-lien a:hover,
.rkt-instance-accordeon-lien a:focus-visible { text-decoration: underline; }

/* ══ 25. La grille d'entree (PROMPT-108, T1) ═══════════════════════════════════
 *
 * `templates/parts/grille-entree.php`, sous la variante `grille.php`. Six
 * blocs possibles, deux colonnes, une gouttiere visible entre eux, AUCUN
 * ARRONDI NI OMBRE -- demande explicite du prompt, a l'oppose des cartes du
 * reste du produit.
 *
 * LE PALIER DE 900 PX EST PROPRE A CE COMPOSANT : aucune autre piece du
 * produit ne s'y accroche, la grille de deux blocs de largeurs inegales
 * (slogan/texte a gauche, domaines/action/petits a droite, empilement plus
 * grand a droite) respirait mal encore a 768px sur les quatre pages
 * verifiees. Meme logique deja acceptee au produit pour d'autres paliers
 * propres a un seul composant (`§19.2` a 600px, la vedette a 480px).
 *
 * LES COULEURS SONT TOUTES DES JETONS EXISTANTS -- voir le doc-bloc de
 * `grille-entree.php` pour le detail et les mesures de contraste.
 */

.rkt-grille-entree {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
  padding-top: var(--sp-4);
  padding-bottom: var(--sp-2);
}

@media (min-width: 900px) {
  .rkt-grille-entree:not(.rkt-grille-entree--pleine) {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}

.rkt-ge-col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  min-width: 0;
}

.rkt-ge-bloc { padding: var(--sp-4) var(--sp-3); }

/* ── Slogan : aplat --c-accent ────────────────────────────────────────────
 *
 * CONTRASTE MESURE, PAS SUPPOSE (charte reellement publiee, accent
 * #e9880d, fonctions `rkt_luminance()`/`rkt_contraste()` du produit) :
 *
 *   texte --c-text (#1d1d1d) sur --c-accent ............... 6,42:1
 *   phrase du slogan, TRES GRAND TEXTE (>= 24px gras ici) -- clause 3:1 :
 *     CONFORME, marge large ;
 *   ligne de chapeau, TEXTE COURANT -- clause 4,5:1 : CONFORME (6,42:1),
 *     sous AAA (7:1). Meme distinction que le `CR-91`.
 *
 * `--c-text` EST UN JETON FIXE, PAS DERIVE DE L'ACCENT DU CLIENT -- limite
 * assumee, signalee au compte-rendu, meme principe de precaution deja
 * accepte par `ouverture-affiche.php` pour son propre calcul fige.
 */
.rkt-ge-slogan {
  background: var(--c-accent);
  color: var(--c-text);
}

.rkt-ge-slogan-texte {
  margin: 0 0 var(--sp-1);
  font-family: var(--f-heading);
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.15;
}

@media (min-width: 768px) {
  .rkt-ge-slogan-texte { font-size: 2.25rem; }
}

.rkt-ge-slogan-chapeau {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

.rkt-ge-slogan .rkt-ge-slogan-texte:last-child,
.rkt-ge-slogan .rkt-ge-slogan-chapeau:last-child { margin-bottom: 0; }

/* ── Texte : fond de page, filet ──────────────────────────────────────────── */

.rkt-ge-texte {
  background: var(--c-bg);
  border: 1px solid var(--c-filet);
}

.rkt-ge-texte > *:last-child { margin-bottom: 0; }

/* ── Domaines : aplat --c-encre, ENTIEREMENT DEDUIT ───────────────────────
 *
 * Le prompt nomme `--c-ink`, absent du produit : `--c-encre` (#12263a) en
 * est l'equivalent exact, deja pose en aplat ailleurs (pied de page,
 * vedette d'archive, fil d'Ariane en bande). Blanc pur dessus : 15,40:1,
 * deja mesure et documente a la vedette d'archive (§T3).
 */
.rkt-ge-domaines {
  background: var(--c-encre);
  color: #ffffff;
}

.rkt-ge-domaines-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  column-gap: var(--sp-4);
}

@media (min-width: 480px) {
  .rkt-ge-domaines-liste { column-count: 2; }
}

.rkt-ge-domaines-liste li {
  position: relative;
  margin-bottom: var(--sp-1);
  padding-left: 1.1em;
  break-inside: avoid;
}

/* Puce carree a la couleur d'accent, reprise de la barre d'accent du produit (§16, §21). */
.rkt-ge-domaines-liste li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 0.55em;
  height: 0.55em;
  background: var(--c-accent);
}

.rkt-ge-domaines-liste a { color: #ffffff; text-decoration: none; }
.rkt-ge-domaines-liste a:hover,
.rkt-ge-domaines-liste a:focus-visible { text-decoration: underline; }

/* ── Action : aplat --c-primary-dark, + photographie si fournie ───────────
 *
 * Sans photographie : aplat uni, texte `--c-sur-primary` -- le jeton deja
 * calcule pour rester lisible sur `--c-primary-dark` (`enqueue.php`).
 *
 * Avec photographie : VOILE PORTE PAR LE BLOC DE TEXTE, pas par le bloc
 * entier -- voir la section suivante, et le `PROMPT-120` qui l'a impose.
 */
.rkt-ge-action {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--c-primary-dark);
  color: var(--c-sur-primary);
  text-decoration: none;
}

/*
 * CORRECTIF `PROMPT-120`, point 2 -- LE DEFAUT LE PLUS GRAVE DU LOT, ET CE
 * N'EST PAS LE VOILE.
 *
 * Le bloc d'action porte une adresse : il est rendu en `<a>`. La regle
 * generique `.rkt a { color: var(--c-primary-dark) }` est en specificite
 * (0,1,1) et ecrasait `.rkt-ge-action` ci-dessus, qui n'est qu'une classe
 * (0,1,0). Les deux lignes sortaient donc en `--c-primary-dark` -- LA MEME
 * COULEUR QUE L'APLAT ET QUE LE VOILE.
 *
 * MESURE, sur la charte reellement publiee (`--c-primary-dark` #004a8c) :
 *
 *   sans photographie, texte sur l'aplat plein ............. 1,00:1
 *     -- le texte n'etait pas seulement difficile a lire, il etait
 *        strictement invisible ;
 *   avec photographie, sur la zone la plus claire mesuree ... 2,95:1
 *     (la photographie eclaircit le fond et rend le bleu un peu
 *      distinguable : c'est ce que la capture de Michelot montre).
 *
 * Deux classes pour l'emporter -- MEME PIEGE, MEME PATRON que
 * `.rkt .rkt-ge-petit` trente lignes plus bas, corrige au meme endroit le
 * meme jour sur les deux petits blocs, et pas sur celui-ci. C'est la
 * sixieme fois que `.rkt a` mord dans ce fichier.
 */
.rkt .rkt-ge-action { color: var(--c-sur-primary); }

.rkt-ge-action-texte {
  position: relative;
  z-index: 2;
  padding: var(--sp-4) var(--sp-3);
}

.rkt-ge-action--photo {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 280px;
  /*
   * La marge interieure de `.rkt-ge-bloc` est annulee POUR LA SEULE
   * VARIANTE A PHOTOGRAPHIE. Sans cela, le voile pose sur le bloc de texte
   * (plus bas) s'arretait a 24 px des bords lateraux et a 32 px du bas :
   * il se lisait comme une etiquette posee sur la photographie, pas comme
   * un voile. Le texte ne perd rien, il porte deja sa propre marge
   * interieure (`.rkt-ge-action-texte`) -- les deux etaient cumulees.
   * Le bloc SANS photographie garde la marge du bloc, inchangee.
   */
  padding: 0;
}

.rkt-ge-action--photo .rkt-ge-action-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  line-height: 0;
}

.rkt-ge-action--photo .rkt-ge-action-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/*
 * LE VOILE, PORTE PAR LE BLOC DE TEXTE LUI-MEME (`PROMPT-120`, point 2).
 *
 * MEME MECANISME QUE LES CARTES DE CATALOGUE (`.rkt-carte--photo
 * .rkt-carte-corps`, §29) : un panneau quasi opaque derriere le texte, et
 * un fondu qui le ramene a la transparence au-dessus. Il n'est PAS
 * reinvente ici, il est transpose -- panneau bleu et texte blanc plutot
 * que panneau blanc et texte fonce.
 *
 * POURQUOI PAS LE DEGRADE PLEIN BLOC QUI ETAIT ECRIT ICI. Il partait de
 * 0,1 en haut pour finir a 0,92 en bas, sur la HAUTEUR DU BLOC. Le texte
 * n'occupe pas le bas du bloc : il commence a 44 % de sa hauteur et finit
 * a 71 %, la ou le degrade ne valait plus que 0,46 a 0,68. Mesure sur la
 * photographie reellement publiee, zone la plus claire du bandeau de
 * texte -- une fenetre brulee, un pixel a rgb(255,255,255) sous le voile :
 *
 *   texte blanc sur l'ancien degrade ......... 2,49:1  ECHEC (4,5 exige)
 *
 * Un degrade cale sur le bloc est donc juste par hasard : il depend de la
 * hauteur du texte. Le panneau porte par le texte suit le texte, quelle
 * que soit sa longueur -- c'est exactement la raison pour laquelle les
 * cartes de catalogue le font deja ainsi.
 *
 * CONTRASTES OBTENUS, meme pixel de reference (blanc pur sous le voile,
 * l'hypothese la plus defavorable qui existe) :
 *
 *   fond du panneau, 0,88 en haut ..... rgb(31, 96, 154)
 *   fond du panneau, 0,97 en bas ...... rgb(8, 79, 143)
 *   « Session d'automne » -- texte courant, 14 px, blanc a 85 %
 *     d'opacite -- clause 4,5:1 ......... 5,27:1  CONFORME
 *   « Admission ouverte » -- 22,4 px gras, donc TRES GRAND TEXTE au sens
 *     de WCAG 1.4.3 (>= 18,66 px gras) -- clause 3:1 ... 6,59:1 CONFORME
 *     (et conforme aussi a la clause 4,5:1 du texte courant, si on refuse
 *      de lui appliquer la clause du grand texte)
 *
 * SANS PHOTOGRAPHIE, le bloc garde l'aplat plein et aucun de ces deux
 * elements n'est pose : blanc sur `--c-primary-dark`, 8,91:1 pour le titre
 * et 6,89:1 pour la ligne a 85 % d'opacite. Verifie separement.
 */
.rkt-ge-action--photo .rkt-ge-action-texte {
  background: linear-gradient(
    to top,
    rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.97) 0%,
    rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.88) 100%
  );
}

/* Le fondu qui ramene le voile a la transparence au-dessus du texte. */
.rkt-ge-action--photo .rkt-ge-action-texte::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 5rem;
  background: linear-gradient(
    to top,
    rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.88) 0%,
    rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0) 100%
  );
}

.rkt-ge-action-sous {
  margin: 0 0 0.25em;
  font-size: var(--fs-meta);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.85;
}

.rkt-ge-action-titre {
  margin: 0;
  font-family: var(--f-heading);
  font-size: 1.4rem;
  font-weight: 700;
}

a.rkt-ge-action:hover .rkt-ge-action-titre,
a.rkt-ge-action:focus-visible .rkt-ge-action-titre { text-decoration: underline; }

/* ── Deux petits blocs : aplat --c-primary ────────────────────────────────── */

.rkt-ge-petits {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}

.rkt-ge-petits--un { grid-template-columns: 1fr; }

.rkt-ge-petit {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-3);
  background: var(--c-primary);
  text-decoration: none;
}

/*
 * CORRECTIF EN DIRECT (Michelot, 2026-07-30, sur capture) : `.rkt a` est en
 * specificite (0,1,1) et sortait le texte en bleu fonce sur l'aplat
 * `--c-primary`, illisible. Deux classes pour l'emporter -- meme piege,
 * meme patron que `.rkt .rkt-barre-entree a` plus haut dans ce fichier.
 */
.rkt .rkt-ge-petit { color: var(--c-sur-primary); }

.rkt-ge-petit:hover,
.rkt-ge-petit:focus-visible { background: var(--c-primary-dark); }

.rkt-ge-petit-icone { display: block; width: 28px; height: 28px; }
.rkt-ge-petit-icone svg { display: block; width: 100%; height: 100%; }

.rkt-ge-petit-titre {
  font-family: var(--f-heading);
  font-weight: 700;
}

.rkt-ge-petit-texte { font-size: var(--fs-meta); opacity: 0.9; }

/* ── Le contenu en accordeon sous la grille (piece du §23, inchangee) ────── */

.rkt-grille-accordeon { padding-top: var(--sp-6); }

/*
 * CORRECTIF EN DIRECT (Michelot, 2026-07-30, sur capture) : pleine largeur,
 * meme marge que la grille au-dessus (`.rkt-conteneur` standard,
 * `--w-content`) -- pas la largeur de lecture etroite de la regle generale
 * `.rkt-prose` (`--w-narrow`), qui encadrait l'accordeon au centre. Deux
 * classes pour depasser la specificite de `.rkt-prose` seule, meme patron
 * que documente au §16/§21 de ce fichier.
 */
.rkt-grille-accordeon.rkt-prose { max-width: var(--w-content); }

/*
 * `.rkt-grille-accordeon-titre` A ETE RETIREE (`PROMPT-120`, point 3). Le
 * titre qu'elle habillait reprenait mot pour mot le `h2` de la premiere
 * section repliee ; il est parti du gabarit, la regle partait avec lui --
 * une regle sans balise est une piste fausse pour qui lira ce fichier
 * ensuite. Aucun autre gabarit ne la posait (verifie sur tout le depot).
 */

/* ══ 26. Variante « Admission » (PROMPT-109, T1) ═══════════════════════════
 *
 * Trois pieces : le hero a photographie et voile (§26.1), la bande de trois
 * reperes (§26.2), les etapes en accordeon (§26.3, memes classes de base que
 * §23/§24, un modificateur de plus).
 */

/* ── 26.1 L'ouverture d'ACTION ─────────────────────────────────────────────
 *
 * Voir la documentation complete du dosage du voile dans
 * `templates/parts/ouverture-action.php` -- calcul reproduit ici pour que la
 * feuille et le gabarit racontent la meme chose.
 */

.rkt-action {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 420px;
  padding: var(--sp-6) 0;
  background: var(--c-primary);
  text-align: center;
}

.rkt-action-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  line-height: 0;
}

/* Deux classes, meme raison qu'a la §18.1 : `.rkt img` (0,1,1) ecraserait la
   hauteur en `object-fit: cover`. */
.rkt .rkt-action-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
}

/*
 * LE VOILE, DEGRADE DE LA CHARTE, `--c-primary-dark-rvb` -- meme jeton que
 * `.rkt-diapos-voile` (§9, hero du diaporama) et l'action a photographie de
 * `grille-entree.php` (§25), jamais recalcule.
 *
 * DOSE POUR DOMINER N'IMPORTE QUELLE PHOTOGRAPHIE, pas mesure sur un cliche
 * precis : aucune photographie definitive n'est encore posee sur
 * `/admission/` au moment de ce lot (le T2 du meme prompt la pose). Palier a
 * 0,76 de 15 % a 85 % de la largeur : meme contre un pixel BLANC PUR
 * (255,255,255), le pire cas mesurable pour un texte blanc, le fond composite
 * vaut #3d75a8 et le contraste du blanc dessus est de 4,87:1 -- au-dessus des
 * deux clauses (3:1 le titre, 4,5:1 le chapeau), mesure par `wp eval` /
 * `rkt_contraste()` sur la charte reelle d'IUAC. Une vraie photographie,
 * presque toujours moins claire qu'un blanc pur sur toute la zone de texte,
 * ne fera que mieux tenir ce seuil.
 *
 * Allege a 0,40 dans les 15 % extremes de chaque bord, pour laisser la
 * photographie se lire sur les cotes a partir de 768 px, la ou le bloc de
 * texte centre laisse de la place. Sous 768 px, le bloc de texte occupe la
 * quasi-totalite de la largeur : la zone allegee n'y porte aucun texte.
 */
/*
 * SOUS 768 PX, LE VOILE EST PLAT (pas de degrade horizontal) : mesure faite
 * sur la photographie reelle actuellement posee sur `/admission/` (media 483,
 * « Poste de travail, bureau lumineux ») a 375 px -- le chapeau (`max-width:
 * 42ch`) y occupe 4 % a 96 % de la largeur, DANS la zone allegee a 0,40 que
 * le premier jet de cette regle y posait, ce qui faisait tomber son contraste
 * mesure a 3,11:1, sous le seuil de 4,5:1. Corrige avant deploiement : sous
 * 768 px, le bloc de texte n'a pratiquement plus de marge de toute facon, la
 * photographie n'y gagnerait rien a se laisser voir sur des cotes qui
 * n'existent pas.
 */
.rkt-action--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.76);
}

@media (min-width: 768px) {
  .rkt-action--photo::before {
    background: linear-gradient(
      90deg,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.40) 0%,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.76) 15%,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.76) 85%,
      rgba(var(--c-primary-dark-rvb, 29, 29, 29), 0.40) 100%
    );
  }
}

.rkt-action-dedans {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  max-width: 46rem;
  margin-inline: auto;
}

/* Le fil d'Ariane est SUR la photographie voilee : memes teintes que
   `.rkt-fil-bande` (§7, fil sur `--c-encre`), jamais mesurees a part, meme
   principe que le reste de cette bande -- le voile domine, la teinte claire
   suffit. */
.rkt-action-fil .rkt-fil {
  background: transparent;
  border-bottom: 0;
}

.rkt-action-fil .rkt-fil .rkt-conteneur { max-width: none; margin: 0; padding: 0; }
.rkt-action-fil .rkt-fil ol { justify-content: center; padding: 0; }

.rkt-action-fil .rkt-fil a,
.rkt-action-fil .rkt-fil [aria-current="page"],
.rkt-action-fil .rkt-fil-sep { color: rgba(255, 255, 255, 0.85); }

.rkt-action-fil .rkt-fil a:hover { color: #ffffff; }

/* LE TITRE : TRES GRAND TEXTE au sens de WCAG 1.4.3 des 768 px (voir le
   calcul du voile ci-dessus) -- clause 3:1. */
.rkt .rkt-action-titre {
  margin: 0;
  font-family: var(--f-heading);
  font-size: calc(var(--fs-h1) * 1.15);
  font-weight: 700;
  line-height: 1.1;
  color: #ffffff;
  text-wrap: balance;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.5);
}

/* LE CHAPEAU : texte courant -- clause 4,5:1. */
.rkt-action-chapeau {
  margin: 0;
  max-width: 42ch;
  font-size: 1.1rem;
  line-height: var(--lh-body);
  color: #ffffff;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.45);
}

.rkt-action-bouton { margin-top: var(--sp-2); }

.rkt-action :focus-visible { outline-color: #ffffff; }

@media (min-width: 768px) {
  .rkt-action { min-height: 460px; }
  .rkt .rkt-action-titre { font-size: calc(var(--fs-h1) * 1.35); }
}

@media (min-width: 1024px) {
  .rkt-action { min-height: 520px; }
  .rkt .rkt-action-titre { font-size: calc(var(--fs-h1) * 1.5); }
}

/* ── 26.2 La bande de trois reperes ────────────────────────────────────────
 *
 * Contenant vide : la piece se retire entierement (`return`) tant que le
 * calendrier n'a rien a montrer -- aucune regle CSS ne sert alors, il n'y a
 * pas de `<section>` dans le DOM.
 */

.rkt-reperes {
  background: var(--c-primary-pale);
  border-bottom: 1px solid var(--c-filet);
}

.rkt-reperes-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
  padding: var(--sp-3) 0;
}

.rkt-repere {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  text-align: left;
}

.rkt-repere-icone {
  flex: 0 0 auto;
  display: flex;
  width: 28px;
  height: 28px;
  color: var(--c-primary-lisible, var(--c-primary));
}

.rkt-repere-icone svg { display: block; width: 100%; height: 100%; }

.rkt-repere-texte { display: flex; flex-direction: column; }

.rkt-repere-libelle {
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.rkt-repere-valeur {
  font-family: var(--f-heading);
  font-weight: 700;
  color: var(--c-heading);
}

@media (min-width: 768px) {
  .rkt-reperes-grille {
    grid-template-columns: repeat(3, auto);
    justify-content: center;
    gap: var(--sp-6);
  }
}

/* ── 26.3 Les quatre etapes en accordeon (`PROMPT-149`, point 1 ; nettoyee
 *        des doublons avec le socle au `PROMPT-159`) ──────────────────────
 *
 * Reprend LE PATRON de §23/§24 -- memes classes de base `.rkt-accordeon`,
 * `.rkt-accordeon-section`, `.rkt-accordeon-titre`, `.rkt-accordeon-signe`,
 * `.rkt-accordeon-corps`, meme mecanique `+/-`. Aucun balisage neuf dans
 * `etapes-accordeon.php`, seules les regles propres a `.rkt-etape-accordeon-*`
 * demeurent ci-dessous.
 *
 * AVANT LE `PROMPT-159` : le socle (§23) portait encore un filet permanent
 * `border-left`, jamais retire comme le `PROMPT-149` (point 0) le demandait.
 * Cette piece avait alors DUPLIQUE ICI le fond plein, l'ombre et la couleur
 * du signe -- l'inverse de la consigne du `PROMPT-149`
 * (« ne pas dupliquer dans `.rkt-etape-accordeon-*` ce que le socle fait
 * deja »). Le socle livre, ce qui suit est desormais HERITE et non repete :
 * seul reste ici ce qui est propre a cette piece -- le jeton de rang, le
 * filet vertical de l'entete, le lien d'action, et le seul veritable
 * pretend `padding` de son `summary` (`var(--sp-3)` uniforme, contre
 * `var(--sp-2) var(--sp-3)` au socle -- l'entete porte un jeton rond qui
 * demande une respiration egale sur les quatre cotes).
 */

.rkt-etapes-accordeon { margin-top: 0; }

.rkt-etape-accordeon-titre { padding: var(--sp-3); }

.rkt-etape-accordeon-entete {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}

/*
 * LE RANG DEVIENT UN JETON ROND, plus un chiffre coupe au trait vertical :
 * `border-right` disparait. Fond `--c-primary-voile` (le meme degre tres pale
 * deja construit pour ce genre de jeton), texte `--c-primary-dark`. La
 * section ouverte inverse le jeton -- fond blanc, anneau `--c-accent` --
 * SEUL emploi de l'accent dans cette piece, a dessein : il marque l'etat, pas
 * une decoration repetee.
 */
.rkt-etape-accordeon-rang {
  flex: 0 0 auto;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--f-heading);
  font-size: 1.15rem;
  font-weight: 800;
  line-height: 1;
  background: var(--c-primary-voile);
  color: var(--c-primary-dark);
}

.rkt-etape-accordeon-section[open] .rkt-etape-accordeon-rang {
  background: var(--c-sur-primary);
  color: var(--c-primary-dark);
  box-shadow: 0 0 0 2px var(--c-accent);
}

.rkt-etape-accordeon-libelle {
  font-family: var(--f-heading);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.3;
}

.rkt-etape-accordeon-lien {
  margin-top: var(--sp-3);
  font-weight: 600;
}

.rkt-etape-accordeon-lien a { color: var(--c-primary); }
.rkt-etape-accordeon-lien a:hover,
.rkt-etape-accordeon-lien a:focus-visible { text-decoration: underline; }

@media (min-width: 768px) {
  .rkt-etape-accordeon-rang { width: 2.6rem; height: 2.6rem; font-size: 1.3rem; }
}

/* ── « Pièces à préparer » en accordéon (`PROMPT-156`) ─────────────────────
 *
 * Classes de base `.rkt-accordeon-*` reprises telles quelles (aucune classe
 * de plus pour la carte, le signe ou le corps). Les deux classes ci-dessous
 * sont les SEULES neuves, necessaires uniquement parce que cette page porte
 * une icone a cote du titre -- absente du patron de base. `.rkt-pap-
 * accordeon-entete` groupe icone et titre en un seul enfant flex, pour que
 * `justify-content: space-between` de `.rkt-accordeon-titre` continue de
 * n'ecarter que DEUX blocs (entete, signe), pas trois elements disperses.
 */
.rkt-pap-accordeon-entete {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}

.rkt-pap-accordeon-icone {
  display: inline-flex;
  flex: 0 0 auto;
  width: 1.6rem;
  height: 1.6rem;
  color: var(--c-primary);
}

.rkt-pap-accordeon-icone svg { width: 100%; height: 100%; }

/* ══ 27. Variante « Recherche » (PROMPT-111, T1) ═══════════════════════════
 *
 * Composition neuve sur le modele UdeS, pas une nouvelle option de
 * l'archetype carrefour : ni rail, ni mosaique, ni bande de chiffres, ni
 * bande de cloture. Quatre pieces recoivent un style ici -- la surface et son
 * texte de page (§27.1), la grille des axes (§27.2), le fait marquant
 * (§27.3), les cartes de ressources (§27.4). La bande d'actualites
 * (`bande-actualites.php`) ne recoit rien de plus : elle est deja stylee a la
 * §14.4.
 */

/* ── 27.1 La surface : titre et texte de page, hors `.rkt-rubrique` ──────── */

/*
 * `.rkt-page-recherche`, et NON `.rkt-recherche` : cette derniere classe
 * existe deja, sur le panneau de recherche de l'en-tete (§4.3,
 * `.rkt-recherche { background: var(--c-bg-alt); border-top/bottom; ... }`,
 * `order: 2/3` en bureau). La reprendre sur ce `<main>` lui aurait fait
 * heriter un fond, des filets et un ordre flex qui ne le concernent pas --
 * collision de nom mesuree en verification live, corrigee avant ce lot.
 */

/*
 * LA BANDE D'OUVERTURE, REPETEE ICI : `.rkt-ouverture` (position, hauteur,
 * fond de repli) n'est stylee QUE sous `.rkt-rubrique` (§16). Ce gabarit ne
 * porte pas cette classe -- ce n'est pas une rubrique a rail et tuiles, une
 * composition neuve -- et sans ces regles, `.rkt-ouverture-media` (`position:
 * absolute; inset: 0`, §16) n'a plus de parent positionne ni borne en
 * hauteur : son bloc englobant remonte au conteneur initial, et la
 * photographie s'etirait sur la hauteur ENTIERE de la page, derriere axes,
 * actualites et ressources. BOGUE MESURE EN CAPTURE LIVE (premiere passe du
 * `PROMPT-111`), CORRIGE ICI par les memes trois paliers que `.rkt-rubrique`,
 * jamais une valeur inventee.
 */
.rkt-page-recherche .rkt-ouverture {
  position: relative;
  height: 280px;
  background: var(--c-primary);
}

.rkt-page-recherche .rkt-ouverture--photo { background: var(--c-primary-dark); }

.rkt-page-recherche .rkt-ouverture-titre { margin-bottom: var(--sp-4); }
.rkt-page-recherche .rkt-ouverture-titre h1 { margin: 0; }

.rkt-recherche-intro { margin-top: var(--sp-3); }

@media (min-width: 768px) {
  .rkt-page-recherche .rkt-ouverture { height: 360px; }
}

@media (min-width: 1024px) {
  .rkt-page-recherche .rkt-ouverture { height: 420px; }
  .rkt-page-recherche .rkt-ouverture-titre h1 { font-size: calc(var(--fs-h1) * 1.25); }
}

/* ── 27.2 La grille des axes ───────────────────────────────────────────────
 *
 * TROIS COLONNES DES 900 PX, UNE EN DESSOUS -- seuil propre a cette grille,
 * distinct des paliers 768/1024 du reste du produit : mesure demandee par le
 * `PROMPT-111`.
 */

.rkt-grille-axes {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
  align-items: stretch;
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: 0;
}

.rkt-grille-axes > li { margin: 0; }

@media (min-width: 900px) {
  .rkt-grille-axes { grid-template-columns: repeat(3, 1fr); }
}

/* Barre d'accent au survol, meme geste que `.rkt-carte--cycle` et
   `.rkt-carte--vitrine`. */
.rkt-carte--axe { border-top: 3px solid transparent; }
.rkt-carte--axe:hover,
.rkt-carte--axe:focus-visible { border-top-color: var(--c-accent); }
.rkt-carte--axe .rkt-carte-corps { gap: var(--sp-1); }

/* ── L'icone imposante de la carte d'axe (PROMPT-119) ─────────────────────
 *
 * Tranche par Michelot sur demonstration comparative : l'icone plutot que
 * l'image de fond, parce que la banque ne contient aucune photographie
 * disant un domaine de recherche abstrait -- une balance dit le droit, une
 * scene de bureau ne dit rien, et six scenes interchangeables rendraient
 * les six cartes semblables.
 *
 * ⚠ LE TRAIT EST AMINCI ICI, ET NULLE PART AILLEURS. Les six dessins de
 * `rkt_icone_domaine()` (`includes/helpers.php`) sont traces a
 * `stroke-width="1.7"` pour la bande de domaines de l'accueil, qui les rend
 * a 28 px (mesure : le prompt annonce 26, la page en rend 28). A 60 px, ce
 * trait devient epais et l'icone s'empate. La source
 * est PARTAGEE : la modifier alourdirait le probleme au lieu de le
 * resoudre, en changeant l'accueil pour corriger une page de recherche.
 * L'attribut de presentation `stroke-width` du SVG est de specificite nulle
 * face a une declaration CSS : une ligne suffit, et elle ne porte que sur
 * cette carte.
 *
 *   bande de domaines, accueil ... 28 px, trait 1,7 -> 1,98 px a l'ecran
 *   carte d'axe, recherche ....... 60 px, trait 1,4 -> 3,50 px a l'ecran
 *
 * La couleur est `--c-primary` et le dessin est en `currentColor` : le
 * gabarit n'ecrit aucune couleur. La carte etant un `<a>`, on pourrait
 * craindre `.rkt a` -- il ne s'applique pas ici, la regle vise le `span`,
 * pas le lien. Valeur calculee verifiee au navigateur, pas deduite.
 */
.rkt-axe-icone {
  display: block;
  width: 60px;
  height: 60px;
  margin-bottom: var(--sp-1);
  color: var(--c-primary);
}

.rkt-axe-icone svg {
  display: block;
  width: 100%;
  height: 100%;
  stroke-width: 1.4;
}

/*
 * ET LE JOUR OU L'INSTITUT AURA DES PHOTOGRAPHIES. Le gabarit bascule seul
 * sur l'image mise en avant (`grille-axes.php`) ; la vignette reprend alors
 * `.rkt-carte-media`, la piece deja posee pour les autres cartes
 * illustrees. Il ne reste ici qu'a retirer le filet du haut, que l'image
 * remplace : une carte illustree n'a pas besoin des deux.
 */
.rkt-carte--axe-photo { border-top-width: 0; }
.rkt-carte--axe-photo:hover,
.rkt-carte--axe-photo:focus-visible { border-top-width: 0; }

/*
 * LA CARTE COMPACTE, SANS IMAGE (`PROMPT-151`, point 2) : icone a gauche,
 * bloc badge + titre a droite, alignes verticalement au centre -- plus
 * d'empilement vertical, plus d'extrait. Le cas illustre
 * (`.rkt-carte--axe-photo`, ci-dessus) n'est pas touche.
 */
.rkt-carte--axe-compacte .rkt-carte-corps {
  flex-direction: row;
  align-items: center;
  gap: var(--sp-2);
}

.rkt-carte--axe-compacte .rkt-axe-icone { margin-bottom: 0; flex: 0 0 auto; }

.rkt-axe-texte {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}

.rkt-carte--axe-compacte .rkt-carte-titre { margin: 0; }

/* Le chevron rejoint le bord droit de la ligne : `margin-top: auto` (§7)
   n'a d'effet que dans une colonne, il faut `margin-left` dans une ligne. */
.rkt-carte--axe-compacte .rkt-carte-chevron {
  flex: 0 0 auto;
  margin-top: 0;
  margin-left: auto;
  padding-top: 0;
}

/* ── La fiche dediee d'un axe de recherche (`PROMPT-151`, point 3) ────────
 *
 * Le chapeau reprend le geste de `/reconnaissance-des-acquis/` (`PROMPT-147`) :
 * fond `var(--c-primary-pale)` sous le fil d'Ariane et le titre.
 */
.rkt-axe-fiche-chapeau {
  background: var(--c-primary-pale);
  padding-bottom: var(--sp-6);
}

.rkt-axe-fiche-chapeau .rkt-fil { background: transparent; border-bottom: 0; }

/*
 * L'ICONE, PLUS GRANDE QUE SUR LA CARTE (96px contre 60px), LE TRAIT
 * RE-AMINCI EN CONSEQUENCE : voir la mesure au doc-bloc du gabarit
 * (`templates/variantes/rkt_axe/standard.php`). Meme couleur que la carte,
 * `var(--c-primary)`, dessin en `currentColor`.
 */
.rkt-axe-fiche-icone {
  display: block;
  width: 96px;
  height: 96px;
  margin-top: var(--sp-3);
  color: var(--c-primary);
}

.rkt-axe-fiche-icone svg {
  display: block;
  width: 100%;
  height: 100%;
  stroke-width: 0.9;
}

.rkt-axe-fiche-chapeau .rkt-badge { margin-top: var(--sp-2); }

.rkt-axe-fiche-chapeau h1 { margin-top: var(--sp-2); }

/*
 * LA COLONNE « LES AUTRES AXES » : icone (28px, meme dimension que la bande
 * de domaines de l'accueil, meme trait 1,7 -- aucune icone n'a besoin d'etre
 * imposante ici, ce n'est qu'un lien de navigation) + titre, en ligne.
 */
.rkt-axe-fiche-autres {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.rkt-axe-fiche-autres a {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--c-text);
  text-decoration: none;
}

.rkt-axe-fiche-autres a:hover,
.rkt-axe-fiche-autres a:focus-visible {
  color: var(--c-primary-dark);
  text-decoration: underline;
}

.rkt-axe-fiche-autres-icone {
  display: block;
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  color: var(--c-primary);
}

.rkt-axe-fiche-autres-icone svg { display: block; width: 100%; height: 100%; }

.rkt-axe-fiche-autres-titre { font-weight: 600; }

/* ── 27.3 Le fait marquant, deux colonnes ──────────────────────────────────
 *
 * Contenant vide a deux niveaux : la section entiere (`return` dans la
 * piece) si les deux moities manquent, et la moitie seule qui prend la
 * largeur si l'autre manque (`--pleine`, meme forme que
 * `.rkt-grille-entree--pleine`, §25).
 */

.rkt-fait-marquant { background: var(--c-bg-alt); }

.rkt-fait-grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
}

.rkt-fait-grille--pleine { grid-template-columns: 1fr; }

@media (min-width: 900px) {
  .rkt-fait-grille:not(.rkt-fait-grille--pleine) {
    grid-template-columns: 3fr 2fr;
    align-items: start;
  }
}

.rkt-fait-gauche {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.rkt-fait-titre {
  margin: 0;
  font-family: var(--f-heading);
  font-size: var(--fs-h2);
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-fait-image {
  aspect-ratio: 1 / 1;
  max-width: 22rem;
  overflow: hidden;
  border-radius: var(--radius);
}

.rkt-fait-image img { display: block; width: 100%; height: 100%; object-fit: cover; }

.rkt-fait-texte { margin: 0; color: var(--c-text); }

/* Le panneau sombre, TROIS LIENS A PUCE RONDE deduits du sous-menu -- jamais
   saisis (voir `fait-marquant.php`). */
.rkt-fait-panneau {
  background: var(--c-primary-dark);
  border-radius: var(--radius);
  padding: var(--sp-3);
}

.rkt-fait-panneau-liste {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.rkt-fait-panneau-liste li {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
}

.rkt-fait-panneau-liste li::before {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c-sur-primary);
}

.rkt-fait-panneau-liste a {
  color: var(--c-sur-primary);
  font-weight: 600;
  text-decoration: none;
}

.rkt-fait-panneau-liste a:hover,
.rkt-fait-panneau-liste a:focus-visible { text-decoration: underline; }

/* La carte verticale : bandeau colore, deux lignes de titre PENSEES, jamais
   tronquees de force -- un titre plus court ou plus long reste lisible. */
.rkt-fait-carte {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--c-bg);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}

.rkt-fait-carte-bandeau {
  padding: var(--sp-4) var(--sp-3);
  background: var(--c-accent-dark);
  color: var(--c-sur-accent);
}

.rkt-fait-carte-sous {
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.92;
}

.rkt-fait-carte-titre {
  margin: 0;
  font-family: var(--f-heading);
  font-size: var(--fs-h3);
  font-weight: 700;
  line-height: 1.25;
}

.rkt-fait-carte-corps {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-3);
}

.rkt-fait-carte-texte { margin: 0; color: var(--c-text-doux); }

.rkt-fait-carte-bouton-conteneur { margin-top: auto; }

/* ── 27.4 Les cartes de ressources ─────────────────────────────────────────
 *
 * Reprend `.rkt-grille--3` et `.rkt-carte` du produit, deja stylees (§3, §7) :
 * seul l'espacement du bouton est propre a cette carte.
 */

.rkt-carte--ressource .rkt-carte-corps { gap: var(--sp-2); }
.rkt-carte-ressource-bouton { margin: var(--sp-1) 0 0; }

/* ══ 28. La page d'entree d'une rubrique de catalogue (PROMPT-112, T1) ════════
 *
 * Cinq pieces neuves, plus la bande de domaines de l'accueil reprise telle
 * quelle -- elle ne recoit RIEN ici : ses regles vivent au §12 depuis la
 * premiere vague, et l'extraction du lot 112 n'a pas touche une declaration.
 *
 * DEUX JETONS DU PROMPT N'EXISTENT PAS DANS LE PRODUIT, et leur equivalence est
 * posee ici une fois pour toutes :
 *
 *   `--c-ink`   ->  `--c-encre` (#12263a), deja en aplat au pied de page, a la
 *                   vedette d'archive et a la bande de domaines. Meme
 *                   equivalence que celle deja posee au §25 (grille d'entree).
 *                   Blanc pur dessus : 15,40:1, mesure et documente la-bas.
 *   `--c-fond`  ->  `--c-bg-alt` (gray-100), le fond clair du produit, celui de
 *                   `.rkt-section--alt` et du fil d'Ariane. L'ouverture centree
 *                   se pose donc sur le meme gris que le fil qu'elle contient,
 *                   ce qui les soude en une seule zone claire au lieu de deux.
 */

/* ── 28.1 L'ouverture claire et centree ────────────────────────────────────
 *
 * AUCUNE PHOTOGRAPHIE, et c'est le procede du modele : la bande de recherche
 * qui suit porte seule le contraste. Le fil d'Ariane garde son propre fond
 * (`--c-bg-alt`, §6), identique a celui de l'ouverture : la bordure basse du
 * fil est donc retiree ici, elle tracerait une ligne au milieu d'un aplat
 * continu.
 */

.rkt-ouverture-centree { background: var(--c-bg-alt); }

.rkt-ouverture-centree .rkt-fil { border-bottom: 0; }

.rkt-ouverture-centree-dedans {
  padding-top: var(--sp-4);
  padding-bottom: var(--sp-6);
  text-align: center;
}

.rkt .rkt-ouverture-centree-titre {
  margin: 0;
  font-size: var(--fs-h1);
  line-height: var(--lh-heading);
  color: var(--c-heading);
}

/* Le filet APRES le titre : memes mesures que `.rkt-section-titre::before`
   (48 x 4 px, `--c-accent`, rayon 2 px), seule la place change. */
.rkt-ouverture-centree-filet {
  display: block;
  width: 48px;
  height: 4px;
  margin: var(--sp-2) auto 0;
  border-radius: 2px;
  background: var(--c-accent);
}

/* La phrase d'ampleur : colonne de lecture etroite, centree, un cran au-dessus
   du corps de texte courant -- c'est une phrase, pas un paragraphe de page. */
.rkt-ouverture-centree-texte {
  max-width: var(--w-narrow);
  margin: var(--sp-3) auto 0;
  font-size: 1.1rem;
  color: var(--c-text-doux);
}

.rkt-ouverture-centree-texte p { margin: 0 0 var(--sp-2); }
.rkt-ouverture-centree-texte p:last-child { margin-bottom: 0; }

@media (min-width: 768px) {
  .rkt-ouverture-centree-dedans {
    padding-top: var(--sp-6);
    padding-bottom: var(--sp-8);
  }
  .rkt .rkt-ouverture-centree-titre { font-size: calc(var(--fs-h1) * 1.15); }
  .rkt-ouverture-centree-texte { font-size: 1.2rem; }
}

/* ── 28.2 La bande de recherche ────────────────────────────────────────────
 *
 * Aplat `--c-encre`, blanc dessus : 15,40:1, deja mesure. Le champ est blanc
 * sur ce fond, donc son texte reprend `--c-text` -- un champ de saisie sombre
 * se lit mal sur une connexion lente ou l'ecran est souvent bas de gamme, et
 * le blanc est ici la valeur sure.
 *
 * LE BOUTON DE SOUMISSION EST L'ACCENT (`--c-bouton--accent`, teinte assombrie
 * deja mesuree AA), les deux boutons de destination sont a FILET BLANC
 * (`.rkt-bouton--clair`, §5) : la hierarchie se lit sans lire les mots.
 * Aucune regle de bouton n'est ecrite ici, les deux existent.
 */

.rkt-bande-recherche {
  background: var(--c-encre);
  color: #ffffff;
  padding: var(--sp-6) 0;
}

.rkt-bande-recherche-dedans { text-align: center; }

.rkt .rkt-bande-recherche-titre {
  margin: 0 0 var(--sp-3);
  color: #ffffff;
  font-size: var(--fs-h2);
  line-height: var(--lh-heading);
}

.rkt-bande-recherche-formulaire {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  max-width: var(--w-narrow);
  margin: 0 auto;
}

.rkt-bande-recherche-champ {
  flex: 1;
  min-width: 0;
  padding: 0.75rem var(--sp-2);
  border: 2px solid transparent;
  border-radius: var(--radius-petit);
  background: #ffffff;
  color: var(--c-text);
  font-family: var(--f-body);
  font-size: 1rem;
  line-height: 1.3;
}

.rkt-bande-recherche-champ:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 2px;
}

/*
 * L'ESPACE SOUS LE CHAMP, ET POURQUOI IL MANQUAIT (`PROMPT-115`).
 *
 * La regle portait deja `margin: var(--sp-3) 0 0`, et elle ne s'appliquait
 * pas : la rangee de boutons est un `<p>`, et `.rkt p { margin: 0 0 var(--sp-2) }`
 * (§2) est de specificite (0,1,1) contre (0,1,0) ici. La marge haute etait donc
 * remise a zero par la regle generale, et les boutons TOUCHAIENT le formulaire.
 * Le selecteur est prefixe `.rkt` -- meme geste que `.rkt .rkt-bande-recherche-titre`
 * trois regles plus haut, qui avait deja rencontre le probleme.
 *
 * La marge passe a `--sp-4` : le titre est deja separe du formulaire par
 * `--sp-3`, et les boutons sont une autre PROPOSITION que la recherche, pas la
 * suite du meme geste. La gouttiere entre boutons reste `--sp-2`, elle tenait
 * deja -- `gap` n'est pas une marge, la regle generale ne l'atteignait pas.
 */
.rkt .rkt-bande-recherche-liens {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2);
  margin: var(--sp-4) 0 0;
}

.rkt-bande-recherche :focus-visible { outline-color: #ffffff; }

@media (min-width: 768px) {
  .rkt-bande-recherche { padding: var(--sp-8) 0; }
  .rkt-bande-recherche-formulaire { flex-direction: row; }
}

/* ── 28.3 Les cartes de catalogues, refondues (`PROMPT-145`) ────────────────
 *
 * Reprend `.rkt-grille` et `.rkt-carte` du produit (§3, §7). Trois rendus,
 * selon ce que l'entree porte : photo (avec ou sans compte), fond plein et
 * icone (ni photo ni compte), ou carte blanche ordinaire (compte sans photo,
 * deja correcte, pas touchee ici). La condition qui choisit entre eux est
 * dans `cartes-catalogues.php`, pas ici.
 *
 * REFUS DE LA VERSION PRECEDENTE, mesure avant ce lot : la photo portait un
 * voile clair pour que le compte reste lisible pose dessus, ce qui affaiblissait
 * les deux a la fois. Les deux se separent maintenant : la photo occupe le haut
 * de la carte EN PLEINE SATURATION, sans voile ; le compte descend sur fond
 * blanc, dans `rkt-carte-corps`, ou il n'a plus a lutter contre une image.
 */

.rkt-carte--catalogue .rkt-carte-corps { gap: var(--sp-1); }

/*
 * LA BARRE D'ACCENT AU-DESSUS DU COMPTE reprend, valeur pour valeur, celle des
 * chiffres cles de `/institut/` (`.rkt-chiffres-bande--barres .rkt-chiffres >
 * div::before`, §6bis) : 48px de large, 6px de haut, `var(--c-accent)`. Meme
 * signature, pas une variante choisie a l'oeil.
 *
 * DEUX NIVEAUX DE BALISAGE, ET C'EST DELIBERE : `.rkt-catalogue-compte` (le
 * `<p>`) porte la barre en flux normal, bloc au-dessus ; `.rkt-catalogue-valeur`
 * (un `<span>` a l'interieur) porte l'alignement en ligne du chiffre et de son
 * unite. Les fondre en un seul niveau flexible aurait fait de la barre un ITEM
 * du meme flux que le chiffre -- a cote de lui, jamais au-dessus.
 */
.rkt-catalogue-compte {
  margin: 0;
}

.rkt-catalogue-compte::before {
  content: '';
  display: block;
  width: 48px;
  height: 6px;
  margin-bottom: var(--sp-2);
  background: var(--c-accent);
}

.rkt-catalogue-valeur {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem;
}

.rkt-catalogue-nombre {
  font-family: var(--f-heading);
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--c-primary);
}

.rkt-catalogue-unite {
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

/* ── 28.3 bis La photo, en pleine saturation, en haut de la carte ──────────
 *
 * Elle suit le flux normal (plus de position absolue ni de voile) : un ratio
 * fixe la cadre, la carte peut donc suivre sa hauteur naturelle plutot qu'une
 * valeur imposee.
 */
.rkt .rkt-catalogue-photo {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

@media (prefers-reduced-motion: no-preference) {
  .rkt .rkt-catalogue-photo { transition: transform var(--transition); }
  .rkt .rkt-carte--photo:hover .rkt-catalogue-photo,
  .rkt .rkt-carte--photo:focus-within .rkt-catalogue-photo { transform: scale(1.04); }
}

/* ── 28.3 ter La carte sans photo ni compte : fond plein et icone ──────────
 *
 * `var(--c-primary-dark)`, jamais une couleur en dur : dans un produit
 * white-label la teinte suit le client. `var(--c-sur-primary)` porte le texte,
 * pour la meme raison -- c'est le jeton deja construit par `enqueue.php` pour
 * garantir un texte lisible sur ce degre precis (`rkt_couleur_lisible()`),
 * plutot qu'un blanc suppose qui echouerait sur une charte assez claire.
 *
 * LES ETATS DE SURVOL SONT REECRITS, ET CE N'EST PAS UNE PRECAUTION DE STYLE :
 * la regle generale du produit (§18.1bis, ligne ~4451) pose `background:
 * var(--c-primary-pale)` sur `.rkt-carte:hover`, a la specificite (0,1,1). Une
 * classe seule (0,1,0) perd contre elle -- c'est exactement le defaut deja
 * documente et corrige pour `.rkt-carte--pratique` (§28.4), rejoue ici a
 * l'identique plutot que redecouvert.
 */
.rkt-carte--catalogue-plein {
  background: var(--c-primary-dark);
  border-color: var(--c-primary-dark);
}

.rkt-carte--catalogue-plein:hover,
.rkt-carte--catalogue-plein:focus-within,
.rkt-carte--catalogue-plein:focus-visible {
  background: var(--c-primary-dark);
  border-color: var(--c-primary-dark);
}

/*
 * PREFIXEES `.rkt`, LES TROIS -- pas seulement le titre. `.rkt-carte-cta` recoit
 * plus bas (§28.3 quater) sa propre couleur de base, `.rkt-carte--catalogue
 * .rkt-carte-cta { color: var(--c-primary) }`, a la MEME specificite (deux
 * classes) que la regle ici si elle n'etait pas prefixee : l'issue dependrait
 * alors de laquelle des deux regles est ecrite en dernier dans le fichier,
 * exactement le piege que ce chantier a deja paye plusieurs fois. Le prefixe
 * porte la specificite a trois classes, elle gagne sans dependre de l'ordre.
 */
.rkt .rkt-carte--catalogue-plein .rkt-carte-corps,
.rkt .rkt-carte--catalogue-plein .rkt-carte-extrait,
.rkt .rkt-carte--catalogue-plein .rkt-carte-cta,
.rkt .rkt-carte--catalogue-plein .rkt-carte-titre,
.rkt .rkt-carte--catalogue-plein:hover .rkt-carte-titre {
  color: var(--c-sur-primary, #ffffff);
}

.rkt-catalogue-icone {
  display: inline-flex;
  width: 2.75rem;
  height: 2.75rem;
}

.rkt-catalogue-icone-svg { width: 100%; height: 100%; }

/* Le contour de focus doit se voir sur un aplat sombre comme sur une photo. */
.rkt-carte--catalogue-plein:focus-visible,
.rkt-carte--photo:focus-visible {
  outline: 3px solid var(--c-encre);
  outline-offset: -5px;
}

/* ── 28.3 quater L'appel a l'action, texte + chevron ────────────────────────
 *
 * Remplace le chevron seul : « Voir le catalogue » ou « En savoir plus »,
 * choisi par la piece selon que l'entree porte un compte. La fleche deja en
 * place s'agrandit d'un cran, elle ne change pas de role.
 */
.rkt-carte--catalogue .rkt-carte-cta {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: auto;
  padding-top: var(--sp-1);
  font-weight: 600;
  color: var(--c-primary);
}

.rkt-carte--catalogue .rkt-carte-cta .rkt-carte-chevron {
  margin-top: 0;
  padding-top: 0;
  font-size: 1.8rem;
}

/* ── 28.4 Les cartes pratiques, a aplat sombre (PROMPT-112, puis PROMPT-115) ─
 *
 * L'ancienne 28.4 (« Le service-conseil et le panneau d'acces ») A ETE
 * SUPPRIMEE avec la piece qu'elle habillait, `conseil-et-acces.php`
 * (`PROMPT-115`). Verifie avant la suppression, et pas suppose : les seize
 * regles `.rkt-conseil-*` n'etaient servies que par cette piece, elle-meme
 * appelee par la seule variante `page/etudes.php` ; releve sur quinze pages du
 * site en ligne, la classe `rkt-conseil` n'apparaissait que sur `/etudes/`.
 * C'est le controle que le `CR-104` avait paye pour ne pas l'avoir fait.
 *
 * LES CARTES PRATIQUES PASSENT A L'APLAT SOMBRE. Fond `--c-encre`, JAMAIS du
 * noir pur -- c'est le bleu-noir du produit, deja en service au pied de page et
 * a la bande de recherche de cette meme page. Titre et texte en blanc, et un
 * bouton a filet blanc en bas a la place du chevron.
 *
 * CLAUSES DE CONTRASTE, mesurees avec `rkt_contraste()` du produit :
 *
 *   titre, blanc pur sur --c-encre #12263a ......... 15,40:1   (clause 4,5:1)
 *   extrait, rgba(255,255,255,.92) = #eceeef ....... 13,23:1   (clause 4,5:1)
 *   filet du bouton, rgba(255,255,255,.7) = #b8bec4  8,21:1   (clause 3:1,
 *                                                    element d'interface)
 *
 * LE FOCUS CLAVIER EST OBLIGATOIRE ET IL EST DOUBLE : un contour blanc sur la
 * carte, et le filet du bouton qui passe au blanc plein. La carte entiere etant
 * l'ancre, le bouton n'est pas focalisable pour lui-meme ; sans ce second
 * signal, la personne au clavier verrait le contour sans comprendre que le
 * bouton en est la cible.
 */

.rkt-carte--pratique .rkt-carte-corps { gap: var(--sp-2); }

.rkt-carte--pratique {
  background: var(--c-encre);
  border-color: var(--c-encre);
  color: #ffffff;
}

/*
 * L'APLAT SOMBRE DOIT SURVIVRE AU SURVOL ET AU FOCUS, et c'est un defaut
 * MESURE, pas anticipe : la regle de survol du produit (§18) pose
 * `background: var(--c-primary-pale)` sur toute `.rkt-carte`, de specificite
 * (0,2,0) contre (0,1,0) ici. Au focus clavier, la carte virait donc au bleu
 * pale AVEC SON TEXTE RESTE BLANC -- releve au clavier par CDP pendant la
 * verification de ce lot : fond mesure rgb(230,239,248), texte #ffffff, soit
 * 1,16:1. Illisible, et precisement sur l'etat qui sert la navigation au
 * clavier.
 *
 * L'etat va donc vers le PLUS SOMBRE, `--c-encre-profond`, deja un jeton du
 * produit : le contraste du texte blanc y monte a 17,22:1 au lieu de 15,40:1.
 * Le survol reste lisible sans la couleur seule -- l'aplat fonce ET le filet du
 * bouton passe au blanc plein, ce qui est le principe pose au §18.
 */
.rkt-carte--pratique:hover,
.rkt-carte--pratique:focus-within,
.rkt-carte--pratique:focus-visible {
  background: var(--c-encre-profond);
  border-color: var(--c-encre-profond);
}

/* Le titre reste blanc au survol : la regle generale (§7) le passerait a la
   couleur principale, illisible sur cet aplat. */
.rkt .rkt-carte--pratique .rkt-carte-titre,
.rkt .rkt-carte--pratique:hover .rkt-carte-titre { color: #ffffff; }

.rkt-carte--pratique .rkt-carte-extrait { color: rgba(255, 255, 255, 0.92); }

/* Le bouton se pose au pied de la carte, quelle que soit la longueur du texte
   au-dessus : trois cartes cote a cote alignent donc leurs boutons. */
.rkt-carte--pratique .rkt-carte-action {
  margin-top: auto;
  align-self: flex-start;
}

.rkt-carte--pratique:focus-visible {
  outline: 3px solid #ffffff;
  outline-offset: -6px;
}

.rkt-carte--pratique:focus-visible .rkt-carte-action,
.rkt-carte--pratique:hover .rkt-carte-action {
  background: rgba(255, 255, 255, 0.12);
  border-color: #ffffff;
}

/*
 * A DEUX CARTES, LA GRILLE NE S'ETIRE PAS : elle garde la mesure qu'elle aurait
 * a trois colonnes et se centre. Deux cartes etirees sur les 1140 px du
 * conteneur seraient une autre section que la meme section a trois cartes ; la
 * largeur d'une carte est une constante de la page, pas une consequence du
 * nombre de pages qu'un client a enregistrees.
 *
 * La mesure est CALCULEE a partir des jetons, jamais saisie : deux colonnes de
 * la grille a trois, plus la gouttiere qui les separe.
 */
@media (min-width: 1024px) {
  .rkt-cartes-pratiques .rkt-grille--2 {
    max-width: calc((var(--w-content) - 2 * var(--sp-3)) / 3 * 2 + var(--sp-3));
    margin-left: auto;
    margin-right: auto;
  }
}

/* ══ 29. Les trois catalogues de la rubrique Études (PROMPT-113, T1) ══════════
 *
 * Rail de filtres en accordéon, tête de résultats, et les trois listes :
 * programmes (deux affichages), cours (liste dense), perfectionnement (cartes
 * à bandeau d'état). Une seule section pour les trois, parce que ce sont les
 * mêmes pièces paramétrées par le type -- c'est la décision de produit du
 * `PROMPT-113`, et la feuille la suit plutôt que de la contredire.
 *
 * CE QUI EST REPRIS, ET DONC ABSENT D'ICI :
 *  - le patron d'accordéon (§23) : `.rkt-accordeon-section` et
 *    `.rkt-accordeon-titre` sont posées par le balisage, seules les couleurs
 *    et le chevron sont ajoutés plus bas ;
 *  - la règle `@media print` de §23 (`.rkt details:not([open])`) et le bloc
 *    `beforeprint`/`afterprint` de `rektora.js` : ils portent sur `.rkt
 *    details`, les groupes de filtres en profitent SANS UNE LIGNE DE PLUS ;
 *  - le chevron `.rkt-carte-chevron` (§21.2), la pastille `.rkt-badge` et
 *    `.rkt-badge--partenaire` (§14), le bouton `.rkt-bouton` (§5).
 */

:root {
  /*
   * LE VERT, SEULE COULEUR SÉMANTIQUE DU SITE. Il ne sert qu'à l'état
   * « inscriptions ouvertes » d'une session de perfectionnement, et à rien
   * d'autre : ni succès de formulaire, ni disponibilité, ni case cochée.
   *
   * CONTRASTE MESURÉ, PAS SUPPOSÉ, avec les fonctions du produit
   * (`rkt_contraste()`, `rkt_luminance()`), sur la couleur réelle :
   *
   *   #146c43 sur #ffffff .......... 6,45:1   (clause 4,5:1 tenue)
   *   #ffffff sur #146c43 .......... 6,45:1   (clause 4,5:1 tenue)
   *
   * Le bandeau porte donc du blanc pur sur cet aplat, et la même couleur peut
   * servir de texte sur fond blanc sans être remesurée.
   *
   * Fixe au produit, JAMAIS à l'établissement : ce n'est pas une couleur de
   * charte, c'est un signal. Un client dont la marque est verte garde ce vert-
   * ci pour l'état, sinon le signal se confondrait avec la décoration.
   */
  --c-etat-ouverte: #146c43;
}

/* ── 28.5 « Reconnaissance des acquis », variante dediee (`PROMPT-147`) ─────
 *
 * Trois pieces : le chapeau clair, les cartes paralleles, le panneau d'action
 * sombre. Aucune n'est un composant partage ailleurs -- decoupage propre a
 * cette page, comme le prompt le demande.
 */

.rkt-reconnaissance-hero {
  background: var(--c-primary-pale);
  padding-bottom: var(--sp-6);
}

.rkt-reconnaissance-hero .rkt-fil { background: transparent; border-bottom: 0; }

.rkt-reconnaissance-hero h1 { margin-top: var(--sp-3); }

/*
 * LES CARTES : icone, barre d'accent, titre, corps. La barre reprend,
 * valeur pour valeur, celle deja validee sur les cartes « Les catalogues »
 * (`PROMPT-145`) -- 48px x 6px, `var(--c-accent)`. En flux normal (bloc,
 * pas pseudo-element), les trois pieces empilees dans `.rkt-carte-corps`
 * (deja `display:flex; flex-direction:column`, §7) n'ont besoin d'aucune
 * astuce de mise en page : chaque enfant prend sa propre ligne.
 */
.rkt-carte--reconnaissance .rkt-carte-corps { gap: var(--sp-1); }

.rkt-reconnaissance-icone {
  display: inline-flex;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--c-primary);
}

.rkt-reconnaissance-icone svg { width: 100%; height: 100%; }

.rkt-reconnaissance-barre {
  display: block;
  width: 48px;
  height: 6px;
  margin: var(--sp-1) 0 var(--sp-2);
  background: var(--c-accent);
}

/*
 * LE PANNEAU D'ACTION : `var(--c-primary-dark)`, jamais une couleur en dur
 * -- meme raison qu'au `PROMPT-145`, le produit est white-label. Le texte
 * porte `var(--c-sur-primary)`, prefixe `.rkt` pour battre la regle
 * generique `.rkt h1, .rkt h2, .rkt h3, .rkt h4 { color: var(--c-heading) }`
 * (specificite egale sans le prefixe -- le meme piege que celui deja pris
 * et corrige au `PROMPT-138`, evite ici plutot que redecouvert).
 */
.rkt-reconnaissance-panneau {
  background: var(--c-primary-dark);
  color: var(--c-sur-primary, #ffffff);
}

.rkt-reconnaissance-panneau-dedans {
  max-width: 54ch;
  margin: 0 auto;
  text-align: center;
}

.rkt .rkt-reconnaissance-panneau h2 { color: var(--c-sur-primary, #ffffff); }

.rkt-reconnaissance-panneau .rkt-prose { margin-left: auto; margin-right: auto; }

.rkt-reconnaissance-panneau .rkt-bouton { margin-top: var(--sp-3); }

/* ── 29.1 La grille d'un catalogue : rail à gauche, résultats à droite ──────
 *
 * Posée ici pour que les trois archives s'écrivent pareil. Sous 900 px le rail
 * repasse au-dessus des résultats : un rail en colonne étroite sur téléphone
 * n'aiderait personne, et les groupes sont repliés de toute façon.
 */

.rkt-catalogue {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  align-items: start;
}

@media (min-width: 900px) {
  .rkt-catalogue { grid-template-columns: 280px 1fr; }
}

.rkt-catalogue-corps { min-width: 0; }

/* ── 29.2 Le rail de filtres ────────────────────────────────────────────── */

.rkt-rail-filtres { min-width: 0; }

/*
 * LA BARRE D'UN GROUPE : aplat `--c-primary-dark`, texte blanc. Même geste que
 * les barres de gouvernance (§24), une nuance plus foncée : un rail de filtres
 * accompagne une liste, il ne doit pas lui disputer l'attention.
 */
.rkt-filtre-titre {
  background: var(--c-primary-dark);
  color: var(--c-sur-primary);
  font-family: var(--f-heading);
  font-weight: 600;
}

.rkt-filtre-titre:hover,
.rkt-filtre-titre:focus-visible { background: var(--c-primary); }

.rkt-filtre-groupe { border-left-color: var(--c-accent); }

.rkt-filtre-nom { min-width: 0; }

/*
 * LE CHEVRON QUI PIVOTE : même caractère et même quart de tour que
 * `.rkt-rail-chevron` (§17). La transition est déclarée sous
 * « no-preference », comme là-bas.
 */
.rkt-filtre-chevron {
  flex: 0 0 auto;
  font-size: 1.4rem;
  line-height: 1;
  transform: rotate(0deg);
}

.rkt-filtre-groupe[open] .rkt-filtre-chevron { transform: rotate(90deg); }

@media (prefers-reduced-motion: no-preference) {
  .rkt-filtre-chevron { transition: transform var(--transition); }
}

.rkt-filtre-valeurs {
  list-style: none;
  margin: 0;
  padding: var(--sp-1) 0;
}

.rkt .rkt-filtre-lien {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: 0.35rem var(--sp-3);
  color: var(--c-text);
  text-decoration: none;
  font-size: var(--fs-meta);
}

.rkt .rkt-filtre-lien:hover,
.rkt .rkt-filtre-lien:focus-visible {
  background: var(--c-primary-pale);
  color: var(--c-primary-dark);
}

/* La valeur active : un filet d'accent, et le libellé en gras. Cliquer dessus
   la retire -- c'est le seul retour arrière possible sans script. */
.rkt .rkt-filtre-lien--actif {
  background: var(--c-primary-voile);
  box-shadow: inset 3px 0 0 var(--c-accent);
  font-weight: 700;
}

.rkt-filtre-libelle { min-width: 0; }

/* Le compte : discret, tabulaire, et de largeur stable d'une ligne à l'autre. */
.rkt-filtre-compte {
  flex: 0 0 auto;
  color: var(--c-text-doux);
  font-variant-numeric: tabular-nums;
}

.rkt-filtre-lien--actif .rkt-filtre-compte { color: var(--c-primary-dark); }

.rkt-filtres-retirer {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-meta);
}

/* ── 29.3 L'interrupteur « Inscriptions ouvertes seulement » ────────────────
 *
 * Un lien porteur de `role="switch"` : il fonctionne sans JavaScript, au
 * clavier comme au doigt, et son état est annoncé par `aria-checked`.
 */

.rkt .rkt-interrupteur {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
  padding: var(--sp-2);
  background: var(--c-bg-alt);
  border: 1px solid var(--c-bordure);
  color: var(--c-text);
  text-decoration: none;
  font-size: var(--fs-meta);
  font-weight: 600;
}

.rkt .rkt-interrupteur:hover,
.rkt .rkt-interrupteur:focus-visible { background: var(--c-primary-pale); }

.rkt-interrupteur-piste {
  position: relative;
  flex: 0 0 auto;
  width: 36px;
  height: 20px;
  background: var(--gray-400);
  border-radius: 10px;
}

.rkt-interrupteur-bouton {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: #ffffff;
  border-radius: 50%;
}

/* Actif, la piste prend le vert de l'état qu'elle commande : c'est le même
   signal, il n'y en a pas deux. */
.rkt-interrupteur--actif .rkt-interrupteur-piste { background: var(--c-etat-ouverte); }
.rkt-interrupteur--actif .rkt-interrupteur-bouton { left: auto; right: 2px; }

@media (prefers-reduced-motion: no-preference) {
  .rkt-interrupteur-piste { transition: background-color var(--transition); }
}

/* ── 29.4 La tête de résultats ─────────────────────────────────────────────*/

.rkt-tete-resultats {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  padding-bottom: var(--sp-2);
  border-bottom: 2px solid var(--c-filet);
}

.rkt .rkt-resultats-compte { margin: 0; }

.rkt-resultats-nombre {
  font-family: var(--f-heading);
  font-size: var(--fs-h3);
  font-weight: 700;
  color: var(--c-heading);
}

.rkt-resultats-nom { color: var(--c-text-doux); }

.rkt-affichage-bascule {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-meta);
}

/* `display: flex` l'emporterait sur l'attribut natif : sans cette ligne, les
   deux boutons paraîtraient AVANT que le script puisse les servir. C'est tout
   le repli sans JavaScript qui tient ici. */
.rkt-affichage-bascule[hidden] { display: none; }

.rkt-affichage-nom { color: var(--c-text-doux); }

.rkt-affichage-boutons { display: inline-flex; }

.rkt .rkt-affichage-bouton {
  padding: 0.3rem 0.8rem;
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  color: var(--c-text);
  font-family: var(--f-body);
  font-size: var(--fs-meta);
  cursor: pointer;
}

.rkt .rkt-affichage-bouton + .rkt-affichage-bouton { border-left: 0; }

.rkt .rkt-affichage-bouton[aria-pressed="true"] {
  background: var(--c-primary-dark);
  border-color: var(--c-primary-dark);
  color: var(--c-sur-primary);
  font-weight: 700;
}

/* ── 29.5 Les programmes, deux affichages ──────────────────────────────────*/

.rkt-liste-programmes { margin-top: var(--sp-3); }

.rkt-prog-deploye {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rkt-prog-ligne {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--c-filet);
}

@media (min-width: 768px) {
  .rkt-prog-ligne { grid-template-columns: 1fr auto; align-items: start; }
}

.rkt-prog-texte { min-width: 0; }

.rkt .rkt-prog-pastilles {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin: 0;
}

.rkt .rkt-prog-surtitre {
  margin: var(--sp-1) 0 0;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt .rkt-prog-titre {
  margin: 0.2rem 0 0;
  font-size: var(--fs-h3);
}

.rkt .rkt-prog-titre a { text-decoration: none; }
.rkt .rkt-prog-titre a:hover,
.rkt .rkt-prog-titre a:focus-visible { text-decoration: underline; }

.rkt .rkt-prog-resume {
  margin: var(--sp-1) 0 0;
  color: var(--c-text-doux);
}

.rkt .rkt-prog-domaines {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-2);
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
}

.rkt-prog-domaines span { position: relative; }

.rkt-prog-domaines span + span { padding-left: var(--sp-2); }

.rkt-prog-domaines span + span::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 0.4em;
  height: 0.4em;
  background: var(--c-accent);
}

.rkt-prog-cote {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

@media (min-width: 768px) {
  .rkt-prog-cote { flex-direction: column; align-items: flex-end; }
}

.rkt-prog-encadres {
  display: flex;
  gap: var(--sp-1);
}

/*
 * L'ENCADRÉ D'UN CHIFFRE. Il ne paraît que si la fiche porte la valeur : un
 * cadre vide se lirait comme un défaut de gabarit. La règle vit dans
 * `liste-programmes.php`, la feuille ne fait que l'habiller.
 */
.rkt-prog-encadre {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 76px;
  padding: var(--sp-1) var(--sp-2);
  background: var(--c-bg-alt);
  border: 1px solid var(--c-bordure);
  text-align: center;
}

.rkt-prog-encadre-valeur {
  font-family: var(--f-heading);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--c-heading);
  line-height: 1.15;
}

.rkt-prog-encadre-nom {
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
}

.rkt .rkt-prog-bouton {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
}

.rkt-prog-bouton svg { width: 15px; height: 15px; }

/*
 * LA BASCULE : la vue déployée est l'état par défaut, la vue compacte n'existe
 * que sous une classe QUE SEUL `rektora.js` pose. Sans JavaScript, la première
 * s'affiche et la seconde reste repliée -- rien n'est cassé, rien ne manque.
 */
.rkt-prog-compact { display: none; }

.rkt-liste-programmes--compact .rkt-prog-deploye { display: none; }
.rkt-liste-programmes--compact .rkt-prog-compact { display: block; }

/* Un tableau large glisse sous le doigt plutôt que de pousser la page. */
.rkt-prog-compact { overflow-x: auto; }

.rkt-prog-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-meta);
}

.rkt-prog-table th,
.rkt-prog-table td {
  padding: 0.6rem var(--sp-1);
  text-align: left;
  border-bottom: 1px solid var(--c-filet);
  vertical-align: top;
}

.rkt-prog-table thead th {
  font-family: var(--f-heading);
  color: var(--c-heading);
  border-bottom: 2px solid var(--c-primary-dark);
  white-space: nowrap;
}

.rkt-prog-table .rkt-prog-nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rkt-prog-table .rkt-badge { margin-left: var(--sp-1); }

/* ── 29.6 Les cours, liste dense ───────────────────────────────────────────*/

.rkt-liste-cours { margin-top: var(--sp-3); }

.rkt-cours-groupe + .rkt-cours-groupe { margin-top: var(--sp-4); }

.rkt .rkt-cours-intertitre {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-1);
  padding-bottom: 0.3rem;
  border-bottom: 2px solid var(--c-accent);
  font-size: var(--fs-h3);
}

/*
 * LE GROUPE CODE + NOM, `PROMPT-146` : le code garde la chasse fixe (il
 * s'aligne sur les codes des lignes du groupe, en dessous), le nom qui le suit
 * s'ecrit dans la police courante -- ce n'est pas un code, c'est un intitule,
 * et le lire en chasse fixe l'aurait rendu illisible.
 */
.rkt-cours-intertitre-groupe {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 var(--sp-1);
}

.rkt-cours-intertitre-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.04em;
}

.rkt-cours-intertitre-libelle {
  font-family: var(--f-body);
  font-weight: 400;
}

.rkt-cours-intertitre-compte {
  font-family: var(--f-body);
  font-size: var(--fs-meta);
  font-weight: 400;
  color: var(--c-text-doux);
  font-variant-numeric: tabular-nums;
}

.rkt-cours-liste {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* QUATRE COLONNES POUR QUATRE CONTENUS : le code, le titre, les crédits, le
   chevron. En déclarer trois renvoyait le chevron à la ligne et doublait la
   hauteur de chacune des cent sept lignes -- mesuré sur capture, corrigé. */
.rkt .rkt-cours-lien {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: baseline;
  gap: var(--sp-1) var(--sp-2);
  padding: 0.5rem var(--sp-1);
  border-bottom: 1px solid var(--c-filet);
  color: var(--c-text);
  text-decoration: none;
}

.rkt .rkt-cours-lien:hover,
.rkt .rkt-cours-lien:focus-visible { background: var(--c-primary-pale); }

/*
 * LA CHASSE FIXE : un code se compare colonne par colonne. La pile est celle
 * du système, aucun fichier n'est chargé pour elle.
 */
.rkt-cours-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.95em;
  font-variant-numeric: tabular-nums;
  color: var(--c-primary-dark);
  white-space: nowrap;
}

.rkt-cours-titre { min-width: 0; }

.rkt-cours-credits {
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.rkt .rkt-cours-chevron {
  margin-top: 0;
  padding-top: 0;
  font-size: 1.3rem;
}

/* Sous 600 px, le code prend sa propre ligne plutôt que d'écraser le titre :
   même palier propre que la bande de questions (§19.2). */
@media (max-width: 600px) {
  .rkt .rkt-cours-lien { grid-template-columns: 1fr auto auto; }
  .rkt-cours-code { grid-column: 1 / -1; }
}

/* ── 29.7 Le perfectionnement, cartes à bandeau d'état ─────────────────────*/

.rkt-cartes-formations {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
}

.rkt-formation-carte {
  display: grid;
  grid-template-columns: 1fr;
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  box-shadow: var(--shadow);
  overflow: hidden;
}

/* Deux moitiés à partir de 600 px : sous ce seuil, une image de 45 % de
   largeur ne montre plus rien d'utile. */
@media (min-width: 600px) {
  .rkt-formation-carte { grid-template-columns: 45% 1fr; }
}

.rkt-formation-media {
  position: relative;
  min-height: 160px;
  background: var(--c-primary-dark);
}

.rkt-formation-media img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 160px;
  object-fit: cover;
}

/*
 * LE BANDEAU D'ÉTAT, EN BAS DE L'IMAGE. Il couvre toute la largeur : une
 * pastille flottante se serait posée sur un détail de la photo au hasard du
 * recadrage.
 */
.rkt .rkt-formation-bandeau {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  margin: 0;
  padding: 0.4rem var(--sp-2);
  background: var(--c-primary-dark);
  color: #ffffff;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
}

/* LE SEUL VERT DU SITE. Blanc dessus, 6,45:1, mesuré (§29 en-tête). */
.rkt .rkt-formation-bandeau--ouverte { background: var(--c-etat-ouverte); }

.rkt-formation-corps {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  padding: var(--sp-3);
}

.rkt .rkt-formation-titre {
  margin: 0;
  font-size: 1.15rem;
}

.rkt .rkt-formation-titre a { text-decoration: none; }
.rkt .rkt-formation-titre a:hover,
.rkt .rkt-formation-titre a:focus-visible { text-decoration: underline; }

.rkt .rkt-formation-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-2);
  margin: 0;
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
}

/* ── 29.8 La liste vide ────────────────────────────────────────────────────*/

.rkt .rkt-liste-vide {
  margin: var(--sp-4) 0;
  padding: var(--sp-3);
  background: var(--c-bg-alt);
  border-left: 4px solid var(--c-primary);
}

/* ══ 30. Les filtres en ligne du perfectionnement (PROMPT-117, T1) ════════════
 *
 * `templates/parts/filtres-en-ligne.php` remplace le rail vertical SUR CETTE
 * ARCHIVE SEULE. Le rail (§29.2) reste sur `/programmes/` et `/cours/`, où
 * vingt-sept programmes et cent-sept cours se filtrent sérieusement ; quinze
 * formations, elles, se parcourent d'un regard, et 280 px pris sur la largeur
 * n'y rendraient service à personne.
 *
 * TROIS PASTILLES ET UN INTERRUPTEUR, SUR UNE LIGNE :
 *
 *     Domaine ▾    Durée ▾    État de la session ▾    ( ) Inscriptions ouvertes seulement
 *
 * ── CE QUI N'EST PAS RÉÉCRIT ICI ──────────────────────────────────────────
 *
 * Les valeurs d'un menu reprennent `.rkt-filtre-valeur`, `.rkt-filtre-lien`,
 * `.rkt-filtre-libelle` et `.rkt-filtre-compte` du rail (§29.2), à l'identique :
 * même mise en page, même compte tabulaire, même marque de valeur active.
 * L'interrupteur reprend `.rkt-interrupteur` (§29.3) sans une déclaration de
 * plus, sauf ce qu'exige la mise en ligne (ci-dessous). DEUX APPARENCES, UNE
 * SEULE FEUILLE.
 */

.rkt-filtres-ligne {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-3) 0;
}

/* ── 30.1 La pastille, et son menu ─────────────────────────────────────────
 *
 * `details`/`summary` natif, comme le rail : pas une ligne de JavaScript, le
 * clavier d'office, l'état exposé à l'arbre d'accessibilité.
 */

.rkt-filtre-menu { position: relative; }

.rkt-filtre-pastille {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  max-width: 100%;
  padding: 0.4rem var(--sp-3);
  background: var(--c-bg-alt);
  border: 1px solid var(--c-bordure);
  border-radius: 999px;
  color: var(--c-text);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

/* Le marqueur natif : retiré des deux façons, comme §19.2 et §23. */
.rkt-filtre-pastille::-webkit-details-marker { display: none; }

.rkt-filtre-pastille:hover,
.rkt-filtre-pastille:focus-visible {
  background: var(--c-primary-pale);
  border-color: var(--c-primary);
  color: var(--c-primary-dark);
}

/* La pastille porte le choix fait : un menu refermé qui ne dirait que
   « Domaine » laisserait le visiteur sans moyen de savoir ce qui filtre sa
   liste. Le nom du groupe passe alors en second plan. */
.rkt-filtre-pastille--actif {
  background: var(--c-primary-voile);
  border-color: var(--c-accent);
  color: var(--c-primary-dark);
}

.rkt-filtre-pastille-nom { flex: 0 1 auto; }

.rkt-filtre-pastille--actif .rkt-filtre-pastille-nom {
  font-weight: 600;
  color: var(--c-text-doux);
}

.rkt-filtre-pastille-choix {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 700;
}

/*
 * LE CHEVRON EST CELUI DU PRODUIT -- le caractère `&rsaquo;` déjà en service
 * dans le rail (§29.2), `rail-rubrique.php` et `sommaire-ancres.php`. Fermé il
 * pointe vers le bas, ouvert vers le haut : c'est le geste d'une liste
 * déroulante, alors que le rail, lui, va de la droite vers le bas.
 */
.rkt-filtre-pastille-chevron {
  flex: 0 0 auto;
  font-size: 1.3rem;
  line-height: 1;
  transform: rotate(90deg);
}

.rkt-filtre-menu[open] .rkt-filtre-pastille-chevron { transform: rotate(-90deg); }

@media (prefers-reduced-motion: no-preference) {
  .rkt-filtre-pastille-chevron { transition: transform var(--transition); }
}

.rkt-filtre-menu-liste {
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  left: 0;
  min-width: 15rem;
  max-width: 22rem;
  max-height: 60vh;
  overflow-y: auto;
  margin: 0;
  padding: var(--sp-1) 0;
  list-style: none;
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  box-shadow: var(--shadow-fort);
}

/* ── 30.2 L'interrupteur, sur la même ligne ────────────────────────────────
 *
 * Le balisage est CELUI DU RAIL, au caractère près. Seules changent les trois
 * mesures qu'une ligne impose : pas de marge basse, la même hauteur que les
 * pastilles, et le même coin arrondi. Sélecteurs préfixés `.rkt` : `.rkt a`
 * est en (0,1,1) et écraserait une classe seule.
 */

.rkt .rkt-filtres-ligne .rkt-interrupteur {
  margin-bottom: 0;
  padding: 0.4rem var(--sp-3);
  border-radius: 999px;
}

.rkt .rkt-filtres-ligne-retirer {
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
}

/* ── 30.3 Sous 700 px : les filtres passent à la ligne ─────────────────────
 *
 * Chaque pastille prend la largeur, et son menu se déplie EN FLUX plutôt qu'en
 * surimpression : un panneau flottant de 15 rem posé sous la troisième pastille
 * sortirait de l'écran par la droite. L'interrupteur garde sa ligne entière, ce
 * qui est la seule façon de garder son libellé lisible d'un seul tenant.
 */

@media (max-width: 700px) {
  .rkt-filtres-ligne { gap: var(--sp-1); }

  .rkt-filtre-menu { width: 100%; }

  .rkt-filtre-pastille {
    justify-content: space-between;
    width: 100%;
    border-radius: var(--radius);
  }

  .rkt-filtre-menu-liste {
    position: static;
    min-width: 0;
    max-width: none;
    max-height: none;
    margin-top: 4px;
    box-shadow: none;
  }

  .rkt .rkt-filtres-ligne .rkt-interrupteur {
    justify-content: flex-start;
    width: 100%;
    border-radius: var(--radius);
  }
}

/* ── 30.4 L'impression ─────────────────────────────────────────────────────
 *
 * Le bloc `beforeprint` de `assets/js/rektora.js` (§23) ouvre TOUS les
 * `details` de la page avant impression -- règle juste pour un texte
 * réglementaire, désastreuse ici : les trois panneaux sont en surimpression et
 * se poseraient l'un sur l'autre par-dessus les premières cartes. Un filtre est
 * une commande, pas un contenu : la barre ne s'imprime pas.
 */

@media print {
  .rkt-filtres-ligne { display: none; }
}

/* ══ 31. Le catalogue sans rail, et ses deux colonnes (PROMPT-117, T1) ════════
 *
 * ── 31.1 LE BLOC DE CATALOGUE REND SES 280 PX QUAND IL N'Y A PLUS DE RAIL
 *
 * `.rkt-catalogue` réserve une colonne de 280 px au rail à partir de 900 px
 * (§29.1). Sur l'archive du perfectionnement, qui n'a plus de rail depuis le
 * `PROMPT-117`, cette colonne resterait vide et les cartes se logeraient dans
 * l'espace du corps au lieu de celui de la page -- l'avertissement du
 * `CR-117-T3`, repris tel quel.
 *
 * LA CONDITION EST LA STRUCTURE ELLE-MÊME, pas une classe de plus : quand
 * `.rkt-catalogue-corps` est le PREMIER enfant, c'est qu'aucun rail ne le
 * précède. Aucune classe nouvelle n'est donc demandée au gabarit de T3, dont le
 * seul geste reste de retirer l'appel au rail et le conteneur qui l'entoure.
 */

.rkt-catalogue > .rkt-catalogue-corps:first-child { grid-column: 1 / -1; }

/* ── 31.2 Deux colonnes de cartes à partir de 1024 px ──────────────────────
 *
 * `minmax(0, 1fr)` et non `1fr` : sans le minimum à zéro, un titre long tient
 * la colonne ouverte et la grille déborde. Le titre le plus long des quinze,
 * « Intelligence émotionnelle et leadership », est ce qui a imposé la mesure.
 *
 * UNE SEULE CARTE NE S'ÉTIRE PAS sur les deux colonnes : le placement
 * automatique la range en première colonne et la grille reste alignée à gauche.
 * C'est le cas le plus fréquent -- interrupteur actif, une formation sur quinze
 * accepte encore une inscription.
 *
 * LES DEUX COLONNES SONT LIÉES À LA PLEINE LARGEUR, et c'est délibéré : les
 * déclarer sur `.rkt-cartes-formations` seule les ferait apparaître aussi dans
 * la colonne étroite d'un catalogue à rail, où deux cartes de 400 px écraseraient
 * l'image contre le texte. La même condition qu'en 31.1 les commande donc.
 */

@media (min-width: 1024px) {
  .rkt-catalogue-corps:first-child .rkt-cartes-formations {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /*
   * L'IMAGE REND DE LA PLACE AU TEXTE. À deux colonnes, une carte fait la
   * moitié de la largeur : les 45 % d'image de §29.7, justes en pleine largeur,
   * laisseraient au titre une colonne de texte plus étroite que l'image
   * elle-même. Mesure faite sur la carte réelle avant de fixer la valeur.
   */
  .rkt-catalogue-corps:first-child .rkt-formation-carte {
    grid-template-columns: 38% 1fr;
  }
}

/* ══ 32. Les trois fiches individuelles (PROMPT-124, T1) ══════════════════════
 *
 * TROIS PIÈCES, PAS TROIS GABARITS : `ouverture-fiche.php`, `aside-fiche.php`
 * et `liste-cours-fiche.php`. Les trois variantes de T3 les assemblent.
 *
 * ── LA MESURE COMMANDE LA FORME ──────────────────────────────────────────
 *
 *     fiche de programme  4 900 à 6 900 signes
 *     fiche de formation  3 250 signes
 *     fiche de cours        188 signes
 *
 * Les trois ne reçoivent donc PAS un traitement comparable : le modificateur
 * `--compact` resserre l'ouverture d'une fiche courte. Une grande mise en page
 * pour deux lignes de texte fait paraître le contenu plus pauvre qu'il n'est.
 *
 * ── LE PIÈGE DE SPÉCIFICITÉ, PAYÉ SIX FOIS DANS CE CHANTIER ──────────────
 *
 * `.rkt p` et `.rkt a` valent (0,1,1) et écrasent une classe seule (0,1,0). Un
 * `.rkt-of-chapeau { color: … }` posé seul perdrait donc contre `.rkt p`, et
 * un lien de fil d'Ariane sur aplat bleu sortirait en `--c-primary-dark` sur
 * `--c-primary` — bleu sur bleu, illisible. TOUTES les règles de texte de cette
 * section sont donc préfixées `.rkt`, ce qui les porte à (0,2,0) ou au-delà.
 * Vérifié à la valeur calculée au navigateur, pas à la règle écrite.
 *
 * ── CONTRASTE, MESURÉ PAR `rkt_contraste()` SUR LA CHARTE RÉELLE ─────────
 *
 *     `--c-sur-primary` sur `--c-primary` (#0063ba) ......... 6,01:1
 *       clause 4,5:1 (texte courant) : fil, surtitre, chapeau, libellés  ✔
 *       clause 3:1 (très grand texte) : titre, grandes valeurs           ✔
 *
 * AUCUNE OPACITÉ SUR LE TEXTE : blanc à 80 % tombe à 4,44:1 et échoue la
 * clause 4,5:1. La hiérarchie se fait à la taille et à la graisse.
 */

.rkt-ouverture-fiche {
  background: var(--c-primary);
  color: var(--c-sur-primary);
  padding-bottom: var(--sp-6);
}

/* Le fil d'Ariane perd son fond et passe à l'encre de l'aplat. Trois classes :
   (0,3,1), très au-dessus de `.rkt a` (0,1,1). */
.rkt .rkt-ouverture-fiche .rkt-fil {
  background: transparent;
  border-bottom: 0;
}

.rkt .rkt-ouverture-fiche .rkt-fil a,
.rkt .rkt-ouverture-fiche .rkt-fil [aria-current="page"],
.rkt .rkt-ouverture-fiche .rkt-fil-sep {
  color: var(--c-sur-primary);
}

.rkt-of-dedans { max-width: var(--w-content); }

/* Le surtitre : le type et le cycle. Petites capitales, espacé — la hiérarchie
   vient de là, jamais d'un blanc affaibli. */
.rkt .rkt-of-surtitre {
  margin: var(--sp-2) 0 var(--sp-1);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--c-sur-primary);
}

/* Le code officiel, en chasse fixe : pile système, aucun fichier chargé. */
.rkt .rkt-of-code {
  margin: var(--sp-2) 0 var(--sp-1);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-h3);
  letter-spacing: 0.05em;
  font-variant-numeric: tabular-nums;
  color: var(--c-sur-primary);
}

/* TRÈS GRAND TEXTE au sens de WCAG 1.4.3 dès le palier mobile : 30 px en 700,
   au-delà des 18,66 px gras du seuil. La clause applicable est donc 3:1, et la
   mesure en donne 6,01. */
.rkt .rkt-of-titre {
  margin: 0 0 var(--sp-2);
  color: var(--c-sur-primary);
  font-size: clamp(1.75rem, 1.25rem + 2vw, 2.6rem);
  line-height: var(--lh-heading);
}

/* Texte courant : clause 4,5:1. Pleine encre, pas de transparence. */
.rkt .rkt-of-chapeau {
  max-width: 62ch;
  margin: 0 0 var(--sp-2);
  color: var(--c-sur-primary);
  font-size: 1.12rem;
  line-height: var(--lh-body);
}

/* La mention d'un contenu relayé. Encadrée d'un filet à gauche plutôt que
   colorée : une pastille de plus sur un aplat bleu ne se voit pas. */
.rkt .rkt-of-mention {
  max-width: 62ch;
  margin: 0 0 var(--sp-2);
  padding-left: var(--sp-2);
  border-left: 3px solid var(--c-accent);
  color: var(--c-sur-primary);
  font-size: var(--fs-meta);
}

/* ── Les faits en ligne ───────────────────────────────────────────────────
 *
 * LES FILETS SE RECALCULENT SEULS. Le filet vient de `+` — « un fait qui suit
 * un fait » — donc le premier fait RENDU n'en porte jamais, quel que soit le
 * nombre de faits absents avant lui. Aucun fait : la liste n'existe pas dans
 * le HTML, et rien ici ne s'applique.
 */

.rkt .rkt-of-faits {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--sp-1) 0;
  margin: var(--sp-3) 0 0;
  padding: 0;
}

.rkt .rkt-of-fait {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0 var(--sp-3);
}

.rkt .rkt-of-fait:first-child { padding-left: 0; }

/* Le filet vertical. DÉCORATIF : la liste porte la structure et chaque fait
   porte son libellé — la clause 3:1 des éléments d'interface (WCAG 1.4.11) vise
   ce qui est NÉCESSAIRE à la compréhension, et retirer ces filets ne retirerait
   aucune information. Mesuré tout de même, par `rkt_contraste()` sur la charte
   réelle : blanc à 45 % sur #0063ba donne #73a9d9, soit 2,41:1. La valeur est
   donnée plutôt que tue : si la clause devait un jour s'y appliquer, c'est
   l'opacité qu'il faudrait remonter, et c'est ici. */
.rkt .rkt-of-fait + .rkt-of-fait {
  border-left: 1px solid rgba(255, 255, 255, 0.45);
}

.rkt .rkt-of-fait-valeur {
  font-family: var(--f-heading);
  font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.1rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--c-sur-primary);
  font-variant-numeric: tabular-nums;
}

.rkt .rkt-of-fait-libelle {
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--c-sur-primary);
}

/* SOUS 768 PX, LES FAITS S'EMPILENT ET LE FILET BASCULE À L'HORIZONTALE.
 *
 * CORRECTIF APPORTÉ APRÈS MESURE, pas par précaution. À 375 px, deux faits du
 * programme 250 occupent 91 px et 264 px pour 343 px utiles : ils passent à la
 * ligne, et le second gardait alors un filet VERTICAL à sa gauche, orphelin,
 * plus un retrait de 1,5 rem. Mesuré au navigateur sur le rendu réel, corrigé
 * ici. Le premier fait rendu n'a toujours aucun filet : c'est le même `+`.
 */
@media (max-width: 767px) {
  .rkt .rkt-of-faits {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .rkt .rkt-of-fait { padding: var(--sp-1) 0; }

  .rkt .rkt-of-fait + .rkt-of-fait {
    border-left: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.45);
  }
}

/* ── L'ouverture resserrée d'une fiche courte ─────────────────────────────
 *
 * 188 signes ne remplissent pas une grande ouverture. Le titre redescend d'un
 * cran et la bande perd sa réserve basse ; rien d'autre ne change, pour que les
 * trois fiches restent de la même famille.
 */
.rkt-ouverture-fiche--compact { padding-bottom: var(--sp-4); }

.rkt .rkt-ouverture-fiche--compact .rkt-of-titre {
  font-size: clamp(1.5rem, 1.15rem + 1.4vw, 2rem);
}

.rkt .rkt-ouverture-fiche--compact .rkt-of-faits { margin-top: var(--sp-2); }

/* L'INTERTITRE D'UNE LISTE DE FICHE PORTE UNE PHRASE, PAS UN PRÉFIXE.
 *
 * `liste-cours-fiche.php` réemploie tout §29.6 — grille à quatre colonnes,
 * chevron, palier 600 px — SAUF ce point : l'intertitre de l'archive coiffe un
 * préfixe de code et le rend en chasse fixe. « Programmes qui incluent ce
 * cours » en chasse fixe était illisible, vu à la capture avant de le corriger.
 * C'est la seule règle que ce lot ajoute pour cette liste. */
.rkt-cours-intertitre-nom {
  font-family: var(--f-heading);
  letter-spacing: normal;
}

/* ── 32.2 Le corps de fiche, et la colonne qui peut ne pas être ───────────
 *
 * LE SENS DE LA CONDITION EST LE POINT DE CETTE RÈGLE. Deux colonnes SEULEMENT
 * quand la colonne existe. Écrite dans l'autre sens, un navigateur sans
 * `:has()` laisserait une colonne vide à droite du texte — le défaut même que
 * le `PROMPT-104` a fait retirer. Ici, le repli est la pleine largeur, qui est
 * toujours correcte.
 */

.rkt-fiche-corps { display: grid; gap: var(--sp-4); }

@media (min-width: 1024px) {
  .rkt-fiche-corps:has(.rkt-fiche-colonne) {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    align-items: start;
  }

  /* Collante au défilement. 96 px : la hauteur de l'en-tête replié, déjà la
     valeur de `.rkt-fiche-aside` du produit — aucune constante nouvelle. */
  .rkt-fiche-colonne { position: sticky; top: 96px; }
}

.rkt-fiche-colonne-encadre {
  padding: var(--sp-3);
  background: var(--c-primary-pale);
  border: 1px solid var(--c-filet);
  border-radius: 6px;
}

/* Deux encadres dans la meme colonne (`PROMPT-137`, « En bref » puis
   « Domaine ») : le second a besoin d'un ecart, le premier n'en porte pas. */
.rkt-fiche-colonne-encadre + .rkt-fiche-colonne-encadre { margin-top: var(--sp-3); }

.rkt .rkt-fiche-colonne-titre {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-h3);
  color: var(--c-heading);
}

/* Le badge d'état, AU-DESSUS des définitions. Le texte vient de
   `rkt_etat_session_bandeau()` (mécanisme du CR-97) : rien n'est déduit ici. */
.rkt .rkt-fiche-colonne-etat {
  margin: 0 0 var(--sp-2);
  padding: 0.45rem var(--sp-1);
  background: var(--c-bg);
  border-left: 3px solid var(--c-accent);
  font-size: var(--fs-meta);
  font-weight: 600;
  color: var(--c-text);
}

/* LES GROUPES SE SÉPARENT, PAS LES PAIRES (PROMPT-130, T1).
 *
 * Défaut relevé par Michelot : l'écart entre un libellé et sa valeur valait
 * celui qui sépare deux informations différentes, et l'œil ne pouvait plus
 * grouper. C'est la loi de proximité, et elle se règle en espacement, pas en
 * balisage — `dl > div > dt + dd` portait déjà les paires.
 *
 * LE LIBELLÉ COLLE À SA VALEUR :  interligne du libellé resserré à 1,25 et
 * marge haute de la valeur ramenée à zéro. UN FILET SÉPARE LES GROUPES : le
 * rembourrage passe de 0,5 à 0,85 rem, et le dernier groupe ne porte pas de
 * filet. Le rapport entre les deux écarts est mesuré au navigateur, pas
 * estimé : il figure au `CR-130-T1`.
 *
 * ÉTENDUE, PAS RÉÉCRITE, AU `PROMPT-132` : `.rkt-fiche-faits` est le nom que
 * portera le bloc « faits rapides » (Date, Lieu, Modalité) de la future fiche
 * Événement -- même balisage `dl > div > dt + dd`, même règle. Les deux
 * classes partagent donc les mêmes déclarations plutôt que d'en dupliquer une
 * seconde copie qui diverge à la première retouche.
 */
.rkt .rkt-fiche-colonne-liste,
.rkt .rkt-fiche-faits { margin: 0 0 var(--sp-3); }

.rkt .rkt-fiche-colonne-liste > div,
.rkt .rkt-fiche-faits > div {
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--c-filet);
}

.rkt .rkt-fiche-colonne-liste > div:first-child,
.rkt .rkt-fiche-faits > div:first-child { padding-top: 0; }

.rkt .rkt-fiche-colonne-liste > div:last-child,
.rkt .rkt-fiche-faits > div:last-child { border-bottom: 0; padding-bottom: 0; }

.rkt .rkt-fiche-colonne-liste dt,
.rkt .rkt-fiche-faits dt {
  font-size: var(--fs-meta);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt .rkt-fiche-colonne-liste dd,
.rkt .rkt-fiche-faits dd {
  margin: 0;
  line-height: 1.35;
  color: var(--c-text);
}

/* Sans définition ni état, le bouton reste seul : il ne doit pas hériter d'une
   marge basse de liste qui n'existe pas. */
.rkt .rkt-fiche-colonne-encadre .rkt-bouton { width: 100%; text-align: center; }

/* ══ 33. La fiche de programme (PROMPT-137, remplacement complet) ═════════════
 *
 * Remplace entierement l'habillage du `PROMPT-130` (panneau sombre
 * `--c-primary-dark`). Reference unique : artifact « Fiche de programme --
 * inspiree d'ULaval et de l'UQAM », 2026-07-31. Michelot : « Aucune
 * comparaison a faire. »
 *
 * FOND CLAIR PARTOUT : plus de panneau colore, plus de calcul de contraste
 * sur aplat client -- le texte reprend l'encre ordinaire du produit
 * (`--c-heading`, `--c-text-doux`), deja mesuree partout ailleurs sur fond
 * clair. Les deux boutons de l'en-tete reutilisent `.rkt-bouton` et
 * `.rkt-bouton--accent`, classes deja en service dans tout le produit --
 * aucune classe de bouton neuve.
 */

/* ── 33.1 L'ouverture, deux colonnes ─────────────────────────────────────── */

.rkt-ouverture-programme { background: var(--c-bg); border-bottom: 1px solid var(--c-bordure); padding-bottom: var(--sp-4); }

.rkt-op-grille {
  display: grid;
  gap: var(--sp-3);
  align-items: start;
  padding-top: var(--sp-3);
}

@media (min-width: 1024px) {
  .rkt-op-grille {
    grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
    gap: var(--sp-6);
  }
}

.rkt .rkt-op-type {
  margin: 0 0 0.2rem;
  font-family: var(--f-heading);
  font-size: clamp(1.05rem, 0.9rem + 0.6vw, 1.45rem);
  font-weight: 400;
  line-height: 1.2;
  color: var(--c-text-doux);
}

.rkt .rkt-op-titre {
  margin: 0 0 var(--sp-2);
  color: var(--c-heading);
  font-size: clamp(1.9rem, 1.4rem + 2vw, 2.6rem);
  line-height: var(--lh-heading);
}

.rkt .rkt-op-resume {
  max-width: 62ch;
  margin: 0;
  color: var(--c-text-doux);
  font-size: 1.1rem;
  line-height: var(--lh-body);
}

.rkt-op-panneau {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* CHAQUE ÉLÉMENT ABSENT DISPARAÎT ET LES SUIVANTS REMONTENT : le `gap` d'une
   colonne flexible n'existe qu'entre deux éléments présents. */
.rkt-op-panneau > * { margin: 0; }

/* Les deux boutons, côte à côte au palier bureau — c'est le geste que
   l'artifact désigne comme « le plus utile sur une page qui doit faire agir ». */
.rkt-op-boutons { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
.rkt .rkt-op-bouton { width: 100%; text-align: center; }

.rkt-op-faits {
  display: flex;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.rkt-op-fait {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
}

.rkt-op-fait-valeur {
  display: block;
  font-family: var(--f-heading);
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2.05rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--c-heading);
  font-variant-numeric: tabular-nums;
}

/* Une valeur qui n'est pas un nombre redescend d'un cran — même mesure qu'au
   `CR-130-T1` : « 2 ans à temps plein » sortait sur trois lignes en pleine
   taille et doublait la hauteur des deux cartes. */
.rkt-op-fait-valeur--long {
  font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.3rem);
  line-height: 1.25;
}

.rkt-op-fait-libelle {
  display: block;
  margin-top: 0.2rem;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

.rkt-op-fait-note {
  display: block;
  margin-top: 0.3rem;
  font-size: var(--fs-meta);
  font-weight: 400;
  color: var(--c-text-doux);
}

/* Le statut vient déjà rendu de T3 : cette feuille ne lui donne qu'une forme.
   La puce ne porte aucune information à elle seule — le texte la double
   toujours, donc aucune clause de contraste des éléments non textuels ne
   s'applique à sa seule couleur. */
.rkt .rkt-op-statut {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 0.6rem 0.9rem;
  background: var(--c-bg-alt);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 700;
  color: var(--c-heading);
}

/* LE SEUL VERT DU SITE (reprise exacte de `.rkt-formation-bandeau--ouverte`,
   deja mesure 6,45:1 blanc sur `--c-etat-ouverte`) : jamais une seconde
   teinte de vert posee ailleurs dans la feuille. */
.rkt .rkt-op-statut--ouvert {
  background: var(--c-etat-ouverte);
  color: #ffffff;
}

.rkt-op-statut-puce {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

.rkt-op-sess h2 { margin: 0 0 var(--sp-1); font-size: var(--fs-h3); color: var(--c-heading); }

.rkt-op-sessions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-1);
  padding: 0;
  list-style: none;
}

.rkt-op-session {
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--c-bordure);
  border-radius: 999px;
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  color: var(--c-text-doux);
}

/* Bouton plein-largeur, plus le lien souligné du `PROMPT-130` : la reference
   du `PROMPT-137` le montre encadre, comme les deux boutons d'action. */
.rkt .rkt-op-conditions { width: 100%; text-align: center; }

/* Les pastilles de domaine, second bloc de la colonne -- meme carte que
   `.rkt-fiche-colonne-encadre`, meme tenue que les pastilles de session. */
.rkt-op-domaines {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.rkt-op-domaines li {
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--c-bordure);
  font-size: var(--fs-meta);
  color: var(--c-text-doux);
}

/* ── 33.1bis L'ouverture de la fiche de cours, fond clair ─────────────────
 *
 * `PROMPT-129` partie 2, modèle ULaval : « en-tête, pleine largeur, fond
 * clair » — à l'opposé de l'aplat `--c-primary` de `.rkt-ouverture-fiche` et
 * du panneau sombre `--c-primary-dark` de `.rkt-op-panneau`. Même jeton que
 * `.rkt-ouverture-centree` (§29 de la feuille) pour le fond clair d'une
 * ouverture : `--c-bg-alt`.
 *
 * Le texte reprend donc l'encre ordinaire du produit (`--c-heading`,
 * `--c-text-doux`) au lieu de `--c-sur-primary` : aucun contraste calculé par
 * client à vérifier ici, ce sont les couleurs de texte courant du site,
 * déjà mesurées partout ailleurs sur fond clair.
 */
.rkt-ouverture-cours { background: var(--c-bg-alt); padding-bottom: var(--sp-4); }

.rkt-ouverture-cours .rkt-fil { border-bottom: 0; }

.rkt-oc-grille {
  display: grid;
  gap: var(--sp-3);
  align-items: start;
  padding-top: var(--sp-3);
}

@media (min-width: 1024px) {
  .rkt-oc-grille {
    grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
    gap: var(--sp-6);
  }
}

/* Le code en chasse fixe, au-dessus du titre — pas à côté. Même pile système
   que `.rkt-of-code`, sans sa couleur de fond sombre. */
.rkt .rkt-oc-code {
  margin: 0 0 var(--sp-1);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-h3);
  letter-spacing: 0.05em;
  font-variant-numeric: tabular-nums;
  color: var(--c-primary);
}

.rkt .rkt-oc-titre {
  margin: 0 0 var(--sp-2);
  color: var(--c-heading);
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.3rem);
  line-height: var(--lh-heading);
}

.rkt .rkt-oc-chapeau {
  max-width: 62ch;
  margin: 0;
  color: var(--c-text-doux);
  font-size: 1.05rem;
  line-height: var(--lh-body);
}

/* Les deux boutons, à droite au palier bureau — le même point de bascule que
   `.rkt-oc-grille`, pour que le panneau ne se sépare jamais du texte qui le
   justifie. */
.rkt-oc-boutons {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

@media (min-width: 1024px) {
  .rkt-oc-boutons { align-items: stretch; }
}

.rkt .rkt-oc-bouton { width: 100%; white-space: nowrap; }

/* Trois cartes de faits au plus, en ligne sous les boutons. `auto-fit` plutôt
   qu'un compte fixe de colonnes : une fiche qui n'aurait qu'un ou deux faits
   ne laisse pas de case vide. */
.rkt-oc-faits {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--sp-2);
  margin: var(--sp-4) 0 0;
  padding: 0;
  list-style: none;
}

.rkt-oc-fait {
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
}

.rkt-oc-fait-valeur {
  display: block;
  font-family: var(--f-heading);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--c-heading);
}

.rkt-oc-fait-libelle {
  display: block;
  margin-top: 0.2rem;
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

/* ── 33.2 Le semi-accordéon ──────────────────────────────────────────────
 *
 * PAS DE `details` / `summary` : replié, `details` masque TOUT sauf le
 * `summary`, donc le titre ET le début du texte. Il ne reste qu'un « Plus » sur
 * une carte vide. C'est structurellement incompatible avec un semi-accordéon,
 * et c'est un écueil déjà payé par le pilote.
 *
 * LA TRONCATURE N'EXISTE QUE SI LE JAVASCRIPT L'A POSÉE. `est-tronque` n'est
 * jamais écrite dans le gabarit ; sans script, aucune de ces règles ne
 * s'applique et tout le texte se lit d'un bloc. C'est la dégradation, et elle
 * est vérifiée au `CR-130-T1`.
 */

.rkt-sr { margin: 0 0 var(--sp-4); }

/*
 * ── LA FICHE DE PROGRAMME EN CARTES BLANCHES SUR FOND GRIS (`PROMPT-137`) ──
 *
 * Demande directe de Michelot sur la reference : chaque section devient une
 * carte, sur un fond `--c-bg-alt`. Scope a `.single-rkt_programme` : les
 * fiches de cours et de formation reutilisent aussi `.rkt-sr` sans en avoir
 * demande l'habillage, et cette regle ne doit rien leur imposer.
 */
.single-rkt_programme main#rkt-contenu.rkt-conteneur { background: var(--c-bg-alt); }

.single-rkt_programme .rkt-fiche-corps > div > .rkt-sr {
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-4);
}

/* Le titre est un `h2` ORDINAIRE, hors de tout conteneur repliable. */
.rkt .rkt-sr-titre {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-h2);
  color: var(--c-heading);
}

.rkt-sr-corps {
  position: relative;
  /* Borne du corps replié. Une seule valeur, et elle est en rem : une personne
     qui grossit le texte de son navigateur voit la même quantité de lignes,
     pas la même quantité de pixels. */
  --rkt-sr-borne: 14rem;
}

.rkt-sr-corps.est-tronque {
  max-height: var(--rkt-sr-borne);
  overflow: hidden;
}

/* Le dégradé fond la coupure. Décoratif et inerte : `pointer-events: none`,
   sans quoi il intercepterait le clic sur les derniers mots visibles. */
.rkt-sr-corps.est-tronque::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 4.5rem;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--c-bg) 88%);
  pointer-events: none;
}

/* Les deux classes coexistent une fois déplié : la règle porte donc les deux,
   sinon `est-tronque` seule l'emporterait par ordre d'écriture. */
.rkt-sr-corps.est-tronque.est-deplie {
  max-height: none;
  overflow: visible;
}

.rkt-sr-corps.est-tronque.est-deplie::after { content: none; }

.rkt .rkt-sr-plus {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: var(--sp-1);
  padding: 0.4rem 0;
  background: none;
  border: 0;
  font-family: var(--f-heading);
  font-size: 1rem;
  font-weight: 600;
  color: var(--c-primary-dark);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.rkt .rkt-sr-plus:hover { color: var(--c-accent-darker); }

.rkt-sr-chevron {
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-0.18em) rotate(45deg);
}

.rkt-sr-plus[aria-expanded="true"] .rkt-sr-chevron {
  transform: translateY(0.1em) rotate(-135deg);
}

/* `prefers-reduced-motion` COUPE LA TRANSITION DU CHEVRON. Elle est ajoutée
   sous `no-preference` plutôt que retirée sous `reduce`, comme partout dans
   cette feuille : elle n'est jamais déclarée pour qui la refuse.
   MESURÉ À LA VALEUR CALCULÉE, et le chiffre exact mérite d'être écrit :
     sans préférence ....... 0,15 s
     `reduce` .............. 0,00001 s  (0,01 ms)
   Ce n'est pas `0s` : la règle globale du §2 pose `transition-duration: 0.01ms`
   sur `.rkt *`, et c'est elle qui l'emporte. Le mouvement est donc bien
   supprimé à l'œil, mais par le garde-fou global, pas par l'absence de
   déclaration — dit ici plutôt que présumé. */
@media (prefers-reduced-motion: no-preference) {
  .rkt-sr-chevron { transition: transform var(--transition); }
}

/* ── 33.3 Le logo de l'établissement délivrant ───────────────────────────
 *
 * SON PROPRE FILET, comme un groupe de la colonne — c'est une signature, pas
 * un fait de plus. AUCUN LOGO, AUCUN BLOC : la pièce ne rend rien, donc ces
 * règles n'ont rien à cadrer et il n'y a ni cadre vide ni nom en repli.
 */

.rkt-ld {
  padding-top: var(--sp-2);
  border-top: 1px solid var(--c-filet);
}

.rkt .rkt-ld-libelle {
  margin: 0 0 var(--sp-1);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-text-doux);
}

/* (0,2,0) : `.rkt img` (0,1,1) impose `height: auto` et `display: block`, et
   écraserait une classe seule. */
.rkt .rkt-ld-image {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 72px;
  height: auto;
}

/* Dans la colonne « En bref », le logo se dégage du bouton qui le suit. */
.rkt .rkt-fiche-colonne-encadre .rkt-ld { margin-bottom: var(--sp-3); }

/* ══ 34. Carte d'annonce, et le partage en icônes rondes (PROMPT-132, T1) ═════
 *
 * Une seule carte pour deux archives : Actualités, qui remplace `.rkt-annonce`
 * (`PROMPT-114`, retiré par T3 dans ce même lot), et Événements, neuve.
 * Modèle CÉDÉ (Faculté de droit, Université Laval) — la forme seulement, les
 * couleurs et les polices restent celles du produit. Balisage :
 * `templates/parts/carte-annonce.php`.
 */

.rkt-carte-evt {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--c-bg);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  transition: transform var(--transition), box-shadow var(--transition);
}

.rkt-carte-evt:hover,
.rkt-carte-evt:focus-within {
  transform: translateY(-4px);
  box-shadow: var(--shadow-fort);
}

.rkt-carte-evt-media {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--c-bg-alt);
  overflow: hidden;
}

.rkt-carte-evt-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Fond plein, aucun dégradé : il n'apporte rien à la lisibilité d'un texte
   blanc sur une teinte unie. */
.rkt-carte-evt-bande {
  margin: 0;
  padding: 0.5rem var(--sp-2);
  font-family: var(--f-heading);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: 0.03em;
  color: #ffffff;
  background: var(--c-primary-dark);
}

/* Superposé au bas de l'image. */
.rkt-carte-evt-media .rkt-carte-evt-bande {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
}

/* Sans image, le bandeau descend en pleine largeur : c'est toute la carte qui
   commence par la date, teinte plus claire pour rester lisible sans la
   superposition sur image. Même règle que « la carte commence à la date »
   déjà tenue par l'archive actualités d'avant ce lot. */
.rkt-carte-evt-bande--pleine {
  background: var(--c-primary);
}

.rkt-carte-evt-corps {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-3) var(--sp-2);
}

.rkt-carte-evt-categorie { align-self: flex-start; }

.rkt-carte-evt-titre {
  margin: 0;
  font-family: var(--f-heading);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-heading);
}

.rkt-carte-evt-titre a {
  color: inherit;
  text-decoration: none;
}

/* Toute la carte est cliquable, même idiome que `.rkt-carte` et l'ancien
   `.rkt-annonce` : un seul arrêt dans l'ordre de tabulation. */
.rkt-carte-evt-titre a::after {
  content: '';
  position: absolute;
  inset: 0;
}

.rkt-carte-evt:hover .rkt-carte-evt-titre { color: var(--c-primary); }

.rkt .rkt-carte-evt-extrait {
  margin: 0;
  color: var(--c-text-doux);
}

/*
 * LES ICÔNES RONDES DE PARTAGE (`PROMPT-132`) SONT RETIRÉES DE LA FICHE
 * D'ARTICLE, remplacées par les boutons texte du `PROMPT-138` (§33.4,
 * `.rkt-art-partage-*`). Elles n'ont jamais eu d'autre appelant, mesuré avant
 * de retirer cette règle : `.rkt-partage` n'apparaît plus dans aucun
 * gabarit.
 */

/* ══ 35. La fiche Événement (PROMPT-132, T3, gabarit ; T1, feuille) ═══════════
 *
 * Dette signalée par `COMPTE-RENDU-132-T3` : quatre classes neuves du gabarit
 * `templates/variantes/rkt_evenement/standard.php` n'avaient encore aucune
 * règle. `.rkt-fiche-faits` était déjà couverte (§32.2, étendue au
 * `PROMPT-132`) ; les quatre qui suivent ne l'étaient pas.
 */

.rkt-evt-corps {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
}

@media (min-width: 1024px) {
  /* L'inverse de `.rkt-fiche-corps` (programme, PROMPT-130) : ici la colonne
     étroite -- image et faits -- vient EN PREMIER, dans le sens exact de la
     démonstration validée par Michelot. */
  .rkt-evt-corps { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); align-items: start; }
}

.rkt-evt-media-colonne { min-width: 0; }

/*
 * COLLISION DE NOM, RÉSOLUE SANS TOUCHER AU GABARIT. `.rkt-evt-media` existe
 * déjà (§9) pour la vignette d'un événement dans le widget « à la une » de la
 * page d'accueil -- 16/10, coins arrondis, fond `--c-primary-pale`. Le
 * gabarit de la fiche single réutilise le même nom sur un `<figure>`
 * différent, sans le savoir. La règle ci-dessous est SCOPÉE au parent neuf :
 * elle ne touche donc jamais la vignette de la page d'accueil.
 */
.rkt-evt-media-colonne .rkt-evt-media {
  display: block;
  aspect-ratio: auto;
  overflow: visible;
  border-radius: 0;
  background: none;
  margin: 0 0 var(--sp-2);
}

.rkt-evt-media-colonne .rkt-evt-media img {
  display: block;
  width: 100%;
  height: auto;
  max-width: none;
  border-radius: var(--radius);
}

.rkt-evt-contenu { min-width: 0; }

/*
 * LE MEDIA INTEGRE (`PROMPT-139`). Le champ `oembed` d'ACF rend un `<iframe>`
 * a largeur et hauteur fixes -- cette regle le rend fluide, en 16/9, sans
 * toucher au balisage produit par WordPress.
 */
.rkt-evt-media-integree {
  position: relative;
  aspect-ratio: 16 / 9;
  margin: 0 0 var(--sp-3);
  border-radius: var(--radius-petit);
  overflow: hidden;
  background: var(--c-bg-alt);
}

.rkt-evt-media-integree iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.rkt-evt-contenu-titre {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-h3);
  color: var(--c-heading);
}

.rkt-evt-liens {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}

/* ══ 36. La fiche de personne (PROMPT-154, remplacement complet) ══════════════
 *
 * Deux colonnes, 280 px / flexible -- valeurs PROPRES A CETTE FICHE, la
 * colonne laterale reprend le modele UQAM cite par Michelot, largeur FIXE,
 * pas proportionnelle. Rupture a 820 px : ni 768 ni 1024, aucune des deux
 * ruptures habituelles ne convenait a une colonne de cette largeur precise.
 * Voir la documentation complete dans le gabarit,
 * `templates/variantes/rkt_personne/standard.php`.
 */

.rkt-personne-corps { display: grid; gap: var(--sp-4); }

@media (min-width: 820px) {
  .rkt-personne-corps { grid-template-columns: 280px minmax(0, 1fr); align-items: start; }
  .rkt-personne-colonne { position: sticky; top: 96px; }
}

.rkt-personne-photo {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius);
  margin-bottom: var(--sp-2);
}

/* Icone + texte dans le meme badge : premier usage de cette combinaison,
   `.rkt-badge` seul ne prevoyait qu'un texte. */
.rkt-badge--institution {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: var(--sp-2);
}

.rkt-badge--institution svg { width: 14px; height: 14px; flex-shrink: 0; }

.rkt-personne-specialites {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-2);
  padding: 0;
  list-style: none;
}

/* Meme filet que celui deja pose entre les evenements (`.rkt-evt-ligne`) :
   valeur reprise, pas inventee. */
.rkt-personne-filet {
  border-top: 1px solid var(--c-filet);
  margin: var(--sp-2) 0;
}

.rkt-personne-contact {
  margin: 0 0 var(--sp-2);
  padding: 0;
  list-style: none;
}

.rkt-personne-contact li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0;
  font-size: var(--fs-meta);
}

.rkt-personne-contact a {
  color: var(--c-text);
  text-decoration: none;
  word-break: break-word;
}

.rkt .rkt-personne-contact a:hover { color: var(--c-primary-dark); text-decoration: underline; }

.rkt-personne-contact-icone {
  display: inline-flex;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  color: var(--c-text-doux);
}

.rkt-personne-contact-icone svg { width: 100%; height: 100%; }

.rkt-personne-profil-lien { margin-top: var(--sp-1); }

.rkt-personne-fonction {
  margin: 0.35rem 0 0;
  font-size: 1.1rem;
  color: var(--c-text-doux);
}

/* `PROMPT-166`. Meme traitement que la fonction, un cran plus discret --
   c'est un complement, pas une seconde ligne de titre. */
.rkt-personne-titre-pro {
  margin: 0.2rem 0 0;
  font-size: 1rem;
  color: var(--c-text-doux);
}

/* Le seul emprunt decoratif direct au modele UQAM -- valeur identique a
   `.rkt-evt-ligne`, reprise plutot qu'inventee. */
.rkt-personne-entete-filet {
  border-top: 1px dashed var(--c-bordure);
  margin: var(--sp-3) 0;
}

.rkt-personne-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
}

.rkt .rkt-personne-nav a {
  font-family: var(--f-heading);
  font-weight: 600;
  font-size: var(--fs-meta);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--c-primary-dark);
  text-decoration: none;
  padding-bottom: 0.3rem;
  border-bottom: 2px solid transparent;
}

.rkt .rkt-personne-nav a:hover,
.rkt .rkt-personne-nav a:focus-visible {
  border-bottom-color: var(--c-primary);
}

.rkt-personne-section { padding: var(--sp-3) 0; }
.rkt-personne-section:first-child { padding-top: 0; }

.rkt-personne-section--filet { border-top: 1px solid var(--c-filet); }

.rkt .rkt-personne-section h2 {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-h3);
  color: var(--c-heading);
}

.rkt-personne-enseignement {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rkt-personne-enseignement li {
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--c-filet);
}

.rkt-personne-enseignement li:last-child { border-bottom: 0; padding-bottom: 0; }

/* ══ 37. La fiche de partenaire (PROMPT-157, remplacement complet) ════════════
 *
 * Disposition reprise TELLE QUELLE de la fiche d'axe (`.rkt-fiche-corps` /
 * `.rkt-fiche-colonne`, § 32.2) : aucune declaration de plus pour la grille,
 * le contenant vide ou la rupture -- seules les pieces propres a cette
 * fiche (entete logo + titre, badges, liste « Les autres partenaires ») ont
 * besoin de regles neuves.
 */

.rkt-partenaire-fiche-entete {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}

/*
 * `.rkt img { max-width: 100% }` (§1) EST DE SPECIFICITE 0,1,1, PLUS FORTE
 * QUE UNE SEULE CLASSE (0,1,0) : sans le prefixe `.rkt`, le logo s'affichait
 * a sa largeur intrinseque (300px, mesure sur le logo CEIMH) au lieu des
 * 96px voulus, debordant le viewport a 375px. Meme piege documente ailleurs
 * dans cette feuille -- toujours prefixer par `.rkt` pour battre cette regle
 * generique, jamais `!important`.
 */
.rkt .rkt-partenaire-fiche-logo {
  flex: 0 0 auto;
  max-width: 96px;
  max-height: 96px;
  width: auto;
  height: auto;
  object-fit: contain;
}

.rkt-partenaire-fiche-nom-complet {
  margin: 0.25rem 0 0;
  color: var(--c-text-doux);
}

.rkt-partenaire-fiche-badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-3);
}

.rkt-partenaire-fiche-autres {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.rkt-partenaire-fiche-autres a {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--c-text);
  text-decoration: none;
}

.rkt-partenaire-fiche-autres a:hover,
.rkt-partenaire-fiche-autres a:focus-visible {
  color: var(--c-primary-dark);
  text-decoration: underline;
}

/* Aucun repli generique ici -- une entree sans logo ne montre qu'un titre,
   jamais un cadre gris a la place du logo manquant (voir doc du gabarit). */
.rkt-partenaire-fiche-autres-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
}

/*
 * Meme specificite que `.rkt img` (§1, une classe + un element) sans le
 * prefixe : un lien de source aurait fait dependre le gagnant de l'ordre du
 * fichier plutot que de la regle. Prefixe par `.rkt` pour ne plus en
 * dependre, meme raison qu'au-dessus pour `.rkt-partenaire-fiche-logo`.
 */
.rkt .rkt-partenaire-fiche-autres-logo img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.rkt-partenaire-fiche-autres-titre { font-weight: 600; }

/* ══ 38. La fiche pratique (PROMPT-160, remplacement complet) ═════════════════
 *
 * Disposition reprise TELLE QUELLE de la fiche d'axe et de partenaire
 * (`.rkt-fiche-corps` / `.rkt-fiche-colonne`, § 32.2) : aucune declaration
 * de plus pour la grille, le contenant vide ou la rupture.
 */

.rkt-outil-fiche-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3);
  margin: var(--sp-2) 0 var(--sp-3);
  color: var(--c-text-doux);
  font-size: var(--fs-meta);
}

.rkt-outil-fiche-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  margin-bottom: var(--sp-3);
}

.rkt-outil-fiche-autres {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.rkt-outil-fiche-autres a {
  color: var(--c-text);
  font-weight: 600;
  text-decoration: none;
}

.rkt-outil-fiche-autres a:hover,
.rkt-outil-fiche-autres a:focus-visible {
  color: var(--c-primary-dark);
  text-decoration: underline;
}

/*
 * ══ 39. La fiche d'organe : chapeau et colonne en cartes (PROMPT-162, en
 *        cartes au PROMPT-167) ═══════════════════════════════════════════
 * Exception assumee au retrait de la colonne d'appui du `PROMPT-104`, pour
 * la seule serie de gabarits dedies -- voir la documentation du gabarit.
 *
 * LE CHAPEAU reprend `.rkt-axe-fiche-chapeau` (§ fiche d'axe) a l'identique :
 * `var(--c-primary-pale)`, aucune valeur de couleur nouvelle.
 */
.rkt-instance-fiche-chapeau {
  background: var(--c-primary-pale);
  padding-top: var(--sp-4);
  padding-bottom: var(--sp-6);
}

.rkt-instance-fiche-surtitre {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: var(--sp-3) 0 0;
  font-family: var(--f-heading);
  font-weight: 600;
  font-size: var(--fs-meta);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-accent-dark);
}

.rkt-instance-fiche-surtitre-icone {
  display: flex;
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
}

.rkt-instance-fiche-surtitre-icone svg { width: 100%; height: 100%; }

.rkt-instance-fiche-chapeau h1 { margin-top: var(--sp-2); }

/*
 * LA COLONNE, EN CARTES : dans l'esprit de `.rkt-art-liee` (§ « A lire
 * aussi », post/standard.php), sans vignette photo -- un organe n'en a pas,
 * l'icone en tient lieu. Relief au survol repris tel quel de `.rkt-carte`
 * (§7) : memes valeurs, pas une nouvelle echelle inventee.
 */
.rkt-instance-fiche-autres {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.rkt-instance-fiche-autres a {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2);
  border: 1px solid var(--c-bordure);
  border-radius: var(--radius);
  color: var(--c-text);
  text-decoration: none;
}

@media (prefers-reduced-motion: no-preference) {
  .rkt-instance-fiche-autres a { transition: transform var(--transition), box-shadow var(--transition); }
}

.rkt-instance-fiche-autres a:hover,
.rkt-instance-fiche-autres a:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--shadow-fort);
  color: var(--c-text);
}

.rkt-instance-fiche-autres-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-petit);
  background: var(--c-primary-pale);
  color: var(--c-primary);
}

.rkt-instance-fiche-autres-icone svg { width: 22px; height: 22px; }

.rkt-instance-fiche-autres-titre { font-weight: 600; }
