/* ==========================================================================
   Fiche contributeur — cinq gabarits, un seul balisage.
   Ajoutee le 08/09/2026, refondue le 13/09/2026.

   ---------------------------------------------------------------------------
   CE QUI A CHANGE LE 13/09/2026, ET POURQUOI
   ---------------------------------------------------------------------------
   La version precedente ecrivait son texte secondaire en `rgba(255,255,255,…)`,
   c'est-a-dire qu'elle supposait un fond sombre. Or le fond vient du reglage du
   tenant : sur studio.diva-yoga.com il vaut #FAFAFA. Mesure sur la fiche de
   Maryse Lehoux le 13/09/2026 : resume et titres de section sortaient a
   **1,04:1** — du blanc sur blanc. Le seuil est 4,5:1.

   La lecon, et c'est elle qui gouverne tout ce fichier : **fixer une couleur de
   texte suppose qu'on connait le fond, et sur une plateforme multi-tenant on ne
   le connait pas.** Le texte attenue se derive donc de `currentColor` — la
   couleur de texte heritee — et jamais du blanc. Sur fond clair le texte est
   sombre, sa version attenuee reste sombre ; sur fond sombre, l'inverse. Mesure
   sur les deux extremes : 6,3:1 chez Diva Yoga, 9,2:1 sur le repli sombre.

   Corollaire : la branche `prefers-color-scheme` a disparu. Elle repondait a la
   preference du systeme d'exploitation du VISITEUR, alors que le theme est
   choisi par le CLIENT dans ses reglages — elle ne pouvait pas etre juste. Et
   elle se declenchait sur une classe `.cs-light` qu'aucune vue n'a jamais
   ecrite : c'etait du code mort qui donnait l'illusion que le cas etait traite.

   `currentColor` employe dans la propriete `color` elle-meme resout vers la
   valeur HERITEE (specification CSS Color). Il n'y a donc pas de circularite.
   Un navigateur sans `color-mix()` rend la declaration invalide au calcul, et
   la couleur retombe sur la valeur heritee : le texte est alors pleinement
   contraste au lieu d'etre attenue. La degradation est lisible.

   ---------------------------------------------------------------------------
   PORTEE
   ---------------------------------------------------------------------------
   Tout est prefixe par `.contributor-sheet` ou `.contributor-facts`. Aucune
   regle ne sort de ces deux enveloppes, et aucune ne redeclare `:root`.

   Le choix de gabarit pose `contributor-tpl-<cle>` sur les deux enveloppes ;
   ce qui suit ne fait que redistribuer les memes blocs. Aucun contenu n'est
   masque par un gabarit : passer de l'un a l'autre ne fait jamais disparaitre
   une information, ce qui est la promesse faite dans l'ecran d'edition.
   ========================================================================== */

.contributor-sheet,
.contributor-facts {
    /* --- Couleurs : toutes reprises au theme du tenant, aucune en dur. ----- */
    --cs-accent: var(--primary-color, #E05C70);
    --cs-accent-strong: var(--primary-enhanced-color, #ab2546);
    --cs-title: var(--couleur-titre, var(--primary-color, #E05C70));

    /* Deux crans d'attenuation, derives du texte herite (voir l'en-tete). */
    --cs-muted: color-mix(in srgb, currentColor 72%, transparent);
    --cs-faint: color-mix(in srgb, currentColor 66%, transparent);

    /* Filets et surfaces : le token du tenant quand il existe, sinon une
       teinte du texte courant — qui reste visible sur n'importe quel fond. */
    --cs-line: var(--card-border-color, var(--border-color, color-mix(in srgb, currentColor 22%, transparent)));
    --cs-surface: color-mix(in srgb, currentColor 4%, transparent);

    --cs-font-title: var(--font-titles, inherit);
    --cs-font-body: var(--font-paragraphs, inherit);

    /* --- Formes et rythme : des regles de composition, pas des choix de
       marque. Elles ne sont donc pas exposees au reglage du tenant. -------- */
    --cs-radius: 14px;
    --cs-gap: 28px;
}

.contributor-sheet {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: var(--cs-gap);
    padding: 8px 0 4px;
    font-family: var(--cs-font-body);
}

/* ------------------------------------------------------------------ En-tete */

.contributor-sheet .cs-head {
    display: grid;
    grid-template-columns: minmax(180px, 300px) minmax(0, 1fr);
    gap: var(--cs-gap);
    align-items: start;
}

.contributor-sheet .cs-portrait img {
    width: 100%;
    height: auto;
    max-width: 300px;
    border-radius: var(--cs-radius);
    display: block;
    object-fit: cover;
}

.contributor-sheet .cs-identity { min-width: 0; }

/* Le nom est passe de `h4` a `h1` le 08/09/2026 : la page n'avait aucun titre
   de niveau 1. La taille est fixee ici pour que le changement de niveau ne
   change pas l'apparence — c'est la hierarchie du document qui evolue. */
.contributor-sheet .cs-name {
    font-family: var(--cs-font-title);
    font-size: clamp(26px, 3.4vw, 38px);
    line-height: 1.12;
    margin: 0 0 6px;
    font-weight: 700;
}

/* LA COULEUR RENFORCEE, ET PAS LA PRIMAIRE. Decision de Sebastien du 16/09/2026.

   `--primary-color` a 16 px donne **3,39:1** sur le #FAFAFA de Diva Yoga, pour un seuil de
   4,5:1. Contrairement a la citation, cette ligne est trop petite pour beneficier de
   l'exception des grands textes : elle etait donc non conforme AA, en production, sur les
   quatre gabarits qui la peignent — et ce depuis l'origine du fichier, pas depuis un lot
   recent. `--cs-accent-strong` (#ab2546) la remonte a **6,52:1** sur ce fond, et a **6,25:1**
   mesure au pixel sur la surface tiede de « classique ». Elle reste un accent, elle devient
   lisible.

   DEUX FAMILLES DE GABARITS ECHAPPENT A CETTE REGLE, et toutes les deux pour la meme raison :
   leur metier n'est pas pose sur le fond de contenu.
     · « vitrine » et « profil » le ramenent a `color: inherit` pour prendre l'encre calculee
       de leur bandeau ;
     · « magazine » le garde en primaire, parce que son fond est un voile presque noir ou la
       renforcee tomberait a 2,90:1 — mesures dans le bloc de ce gabarit. */
.contributor-sheet .cs-job {
    color: var(--cs-accent-strong);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: .01em;
    margin: 0 0 12px;
}

.contributor-sheet .cs-summary {
    font-size: 17px;
    line-height: 1.6;
    color: var(--cs-muted);
    margin: 0 0 16px;
    max-width: 62ch;
}

/* LA CITATION EST UNE EXERGUE, et sa taille n'est pas une coquetterie.

   Sebastien a demande le 13/09/2026 qu'elle sorte en `--primary-color`. Mesure :
   `#E05C70` sur le fond `#FAFAFA` de Diva Yoga ne donne que **3,39:1**, donc sous
   le seuil de 4,5:1 d'un texte courant. Le meme accent sur le fond sombre de
   SymbioPlay donne 4,74:1, qui passe — mais on ne livre pas une regle qui n'est
   juste que sur un tenant.

   La sortie n'est pas de renoncer a la couleur : c'est d'en faire un GRAND texte.
   WCAG 1.4.3 abaisse le seuil a 3:1 des 24px en graisse normale, et 3,39:1 y
   satisfait sur les deux tenants. Une citation mise en avant a de toute facon
   vocation a etre grande : la contrainte d'accessibilite et l'intention
   typographique disent ici la meme chose.

   **Ne pas descendre `font-size` sous 24px** sans changer la couleur : en dessous,
   la regle redevient non conforme sur fond clair. */
/* Elle vit desormais DANS `.cs-lead` (voir la vue). `.cs-lead` est un bloc, pas le
   conteneur flex de la fiche : la gouttiere de 28 px qui la separait de l'en-tete
   n'est plus donnee par le `gap`, elle est rendue ici. Sans cette marge, la
   citation se collerait au portrait sur les quatre gabarits sans bandeau. */
.contributor-sheet .cs-quote {
    border-left: 3px solid var(--cs-accent);
    padding: 2px 0 2px 20px;
    margin: var(--cs-gap) 0 0;
    max-width: 72ch;
}

.contributor-sheet .cs-quote p {
    font-family: var(--cs-font-title);
    font-style: italic;
    font-size: clamp(24px, 2.2vw, 28px);
    line-height: 1.35;
    margin: 0;
    color: var(--cs-accent);
    text-wrap: balance;
}

.contributor-sheet .cs-updated {
    font-size: 13px;
    color: var(--cs-faint);
    margin: 0;
}

/* ------------------------------------------------- Titres de section commune */

/* Ils etaient peints en `--cs-faint` a 40 % de blanc : invisibles sur fond
   clair. Ils prennent maintenant la couleur de titre du tenant, qui est faite
   pour etre lue sur son fond. */
.contributor-sheet .cs-section-title,
.contributor-sheet .cs-bio h2,
.contributor-sheet .cs-embed-title,
.contributor-facts h2 {
    font-family: var(--cs-font-title);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--cs-title);
    margin: 0 0 14px;
}

/* ---------------------------------------------------------------- Biographie */

.contributor-sheet .cs-bio-body {
    font-size: 16px;
    line-height: 1.7;
    max-width: 72ch;
    color: var(--cs-muted);
}

.contributor-sheet .cs-bio-body p { margin: 0 0 14px; }
.contributor-sheet .cs-bio-body p:last-child { margin-bottom: 0; }
.contributor-sheet .cs-bio-body ul,
.contributor-sheet .cs-bio-body ol { margin: 0 0 14px; padding-left: 22px; }
.contributor-sheet .cs-bio-body li { margin-bottom: 6px; }
.contributor-sheet .cs-bio-body a { color: var(--cs-accent); }

/* Enveloppe inerte par defaut. Elle ne prend vie que pour « vitrine » avec video,
   plus bas : partout ailleurs, la biographie se rend comme si elle n'existait pas. */
.contributor-sheet .cs-bio-duo { display: block; }

/* Pleine largeur et justifiee sur « classique » et « vitrine » (demande de
   Sebastien du 13/09/2026). Les trois autres gardent leur alignement a gauche :
   « portrait » et « presentation » lisent en colonne etroite, ou le justifie
   creuse des rivieres, et « magazine » est deja en deux colonnes de texte.
   `hyphens: auto` attenue ces rivieres la ou le justifie s'applique. */
/* MESURE DU 13/09/2026, ET C'EST ELLE QUI A TRANCHE : sur une fenetre de 1024 px la
   ligne faisait **109 signes**, la ou l'oeil en suit 65 a 75 sans perdre le debut de
   la ligne suivante. Le `justify` y ajoutait des rivieres et `hyphens: auto` coupait
   les mots (« ex-ploite », « me-thodes »), particulierement visibles sur telephone.

   La colonne est donc bornee et le texte aligne a gauche. `max-width` en `ch` suit la
   taille de police du tenant : si le client grossit son texte, la colonne grossit avec
   lui et le compte de signes reste le meme. */
.contributor-tpl-classique .cs-bio-body,
.contributor-tpl-vitrine .cs-bio-body,
.contributor-tpl-profil .cs-bio-body {
    max-width: 68ch;
    text-align: left;
    hyphens: none;
}

/* « PROFIL COLLANT » SANS VIDEO : pleine largeur et justifie (demande de Sebastien du
   16/09/2026).

   Ce gabarit est le seul ou la borne de 68 signes se voyait comme un defaut plutot que
   comme un confort : la colonne de droite porte au-dessus d'elle des carrousels qui vont
   d'un bord a l'autre, et la biographie s'arretait au tiers de leur largeur en laissant un
   grand vide a sa droite. Le rail d'identite tient deja la colonne de gauche : le texte n'a
   pas la largeur d'une page entiere, il a celle d'une colonne.

   `:has()` fait le partage sans qu'aucune classe ne soit posee dans la vue : quand une
   video accompagne la biographie, `.cs-bio-duo` passe en deux colonnes plus bas et la
   regle ci-dessous ne s'applique pas. Un navigateur sans `:has()` ignore le selecteur
   entier et garde la colonne bornee, alignee a gauche — la mise en page d'avant, qui se
   lit tres bien.

   PAS DE `hyphens: auto` AVEC CE JUSTIFIE, et c'est un essai fait puis defait le 16/09/2026.
   La cesure est le remede habituel aux rivieres de blanc du justifie, mais elle ne se
   justifie que sur une colonne etroite, ou chaque ligne porte peu de mots. Ici la ligne en
   porte une vingtaine : les blancs se repartissent sur autant d'intervalles et ne creusent
   presque rien, tandis que la cesure, elle, se voyait a chaque paragraphe (« internatio-
   nale », « auto-guerison » a l'ecran du banc). Le 13/09/2026 avait deja tranche dans ce
   sens pour les autres gabarits. La colonne garde donc `hyphens: none`, herite de la regle
   du dessus.

   CE QUE CELA COUTE, ET C'EST ASSUME : sur une fenetre de 1600 px la ligne fait environ
   145 signes, la ou l'oeil en suit 65 a 75 sans perdre le debut de la suivante. C'est le
   prix de la pleine largeur, qui est ce qui a ete demande. Une borne intermediaire —
   `max-width: 100ch` par exemple — ramenerait la ligne a un confort de lecture sans rendre
   le grand vide de droite : c'est le seul reglage a toucher si le choix devait evoluer. */
.contributor-tpl-profil .cs-bio-duo:not(:has(.cs-bio-video)) .cs-bio-body {
    max-width: none;
    text-align: justify;
}

/* La video laterale de « vitrine ». Le `:has()` est ce qui evite d'avoir a poser
   une classe depuis la vue : sans video, aucun `.cs-bio-video` n'est ecrit, la
   regle ne s'applique pas, et la biographie reprend toute la largeur. */
.contributor-tpl-vitrine .cs-bio-duo:has(.cs-bio-video),
.contributor-tpl-profil .cs-bio-duo:has(.cs-bio-video) {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(260px, 1fr);
    gap: var(--cs-gap);
    align-items: start;
}

.contributor-sheet .cs-bio-video {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: var(--cs-radius);
    overflow: hidden;
    background: var(--cs-surface);
    border: 1px solid var(--cs-line);
}

.contributor-sheet .cs-bio-video iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* ------------------------------------------------------------- Section libre */

.contributor-sheet .cs-custom {
    border-top: 1px solid var(--cs-line);
    padding-top: var(--cs-gap);
}

/* Une section construite dans l'editeur visuel peut porter une image large.
   Sans ce garde-fou, elle deborderait de la page sur petit ecran. */
.contributor-sheet .cs-custom img,
.contributor-sheet .cs-custom video { max-width: 100%; height: auto; }
.contributor-sheet .cs-custom table { width: 100%; }

/* ------------------------------------------------------------- Integrations */

.contributor-sheet .cs-embeds {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--cs-gap);
}

.contributor-sheet .cs-embed {
    background: var(--cs-surface);
    border: 1px solid var(--cs-line);
    border-radius: var(--cs-radius);
    padding: 18px;
    min-width: 0;
}

/* Rapport 16/9 tenu par le conteneur : sans lui, l'`iframe` prend la hauteur
   par defaut de 150px et la video s'affiche dans un timbre-poste. */
.contributor-sheet .cs-embed-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 10px;
    overflow: hidden;
    background: var(--cs-surface);
}

/* Un agenda est haut, pas large : le 16/9 le tronquerait. */
.contributor-sheet .cs-embed-agenda .cs-embed-frame { aspect-ratio: 3 / 4; }

.contributor-sheet .cs-embed-frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

.contributor-sheet .cs-embed-link {
    margin: 12px 0 0;
    font-size: 14px;
}

.contributor-sheet .cs-embed-link a { color: var(--cs-accent); }

/* ------------------------------------------------- Catalogue : cours, series */

/* Les deux listes etaient un carrousel Owl au vieux balisage `.video-img`. Elles
   sont passees le 13/09/2026 a la carte `.px-card`, d'abord en grille, puis —
   meme jour, sur demande de Sebastien — au CARROUSEL de la page d'accueil, pour
   que la fiche ressemble au catalogue d'ou l'on vient.

   Il n'y a donc plus rien a styler ici : le rail `px-rail-wrap` et le carrousel
   `px-owl` sont habilles par `pages/home/sections/_styles.blade.php`, que
   `details.blade.php` inclut. Les reglages responsive vivent dans
   `partials/catalogue.blade.php`, recopies de l'accueil.

   Corollaire : les jetons `--cs-card-min` ont disparu du bloc de tete. La
   densite du catalogue ne differencie plus les gabarits — c'est voulu, puisque
   les cinq doivent ressembler a l'accueil. Ce sont l'en-tete et la biographie
   qui les distinguent. */
.contributor-sheet .cs-catalogue { min-width: 0; }

/* LE RAIL EST DANS UNE COLONNE, PAS DANS LA PAGE, et c'est toute la difference.

   `_styles.blade.php` habille le rail pour la PAGE D'ACCUEIL, ou il va d'un bord de la
   fenetre a l'autre : d'ou `padding: 8px 4vw 16px` et des fleches posees a `4vw - 22px`.
   Cette gouttiere est celle de la FENETRE. Recopiee telle quelle dans une fiche, elle
   decale les cartes par rapport a tout ce qui les entoure : mesure du 16/09/2026 sur une
   fenetre de 1600 px, `4vw` valait 64 px, le titre « Ses cours » et la barre de recherche
   commencaient a x=380 et la premiere carte a x=452 — 72 px d'ecart — pendant que la
   derniere sortait tronquee de l'autre cote.

   Dans la fiche, le rail EST la colonne : il n'a pas de gouttiere a se donner. Les cartes
   s'alignent donc sur le titre, sur la barre de recherche et sur la biographie, et les
   fleches se posent sur les bords du rail, comme le fait tout catalogue en rail.

   Le `!important` n'est pas un raccourci : la regle d'origine en porte un, et a poids egal
   c'est la specificite qui tranche — celle-ci est plus forte d'une classe. */
.contributor-sheet .cs-catalogue .px-owl.owl-carousel {
    padding-left: 0;
    padding-right: 0;
}

.contributor-sheet .cs-catalogue .px-owl .owl-nav button.owl-prev { left: 0 !important; }
.contributor-sheet .cs-catalogue .px-owl .owl-nav button.owl-next { right: 0 !important; }

/* Le degrade de bord fait fondre les cartes dans le fond de la PAGE, la ou le rail touche
   le bord de la fenetre. Dans une colonne il ne fond dans rien : il ne fait plus que
   delaver la premiere carte sur 80 px. */
.contributor-sheet .cs-catalogue .px-rail-wrap::before,
.contributor-sheet .cs-catalogue .px-rail-wrap::after { display: none; }

/* ============================================================= Les gabarits ==
   Chaque gabarit ne redefinit que ce qui le distingue. Ce qui n'est pas ecrit
   ici est volontairement commun.
   ========================================================================== */

/* --- Portrait : la photo commande, le texte se lit en colonne etroite. ----- */

.contributor-tpl-portrait .cs-head {
    grid-template-columns: minmax(240px, 420px) minmax(0, 1fr);
    align-items: center;
}

.contributor-tpl-portrait .cs-portrait img {
    max-width: 420px;
    aspect-ratio: 4 / 5;
}

.contributor-tpl-portrait .cs-name { font-size: clamp(30px, 4.2vw, 46px); }

/* La lecture passe a une colonne unique et centree ; les grilles de catalogue,
   elles, gardent la pleine largeur — une grille etranglee a 60ch n'aurait plus
   de raison d'etre une grille. */
.contributor-tpl-portrait .cs-bio,
.contributor-tpl-portrait .cs-custom,
.contributor-tpl-portrait .cs-embeds-group {
    max-width: 68ch;
    margin-left: auto;
    margin-right: auto;
    width: 100%;
}

.contributor-tpl-portrait .cs-bio-body { max-width: none; }

/* --- Magazine : bandeau large, identite SUPERPOSEE, deux colonnes. --------- */

/* Jusqu'au 13/09/2026 le commentaire annoncait une identite superposee, mais la
   posait dans un bloc SOUS l'image. Elle l'est reellement maintenant, avec un
   voile degrade qui garantit la lisibilite du nom quelle que soit la photo. */
.contributor-tpl-magazine .cs-head {
    grid-template-columns: 1fr;
    position: relative;
    border-radius: var(--cs-radius);
    overflow: hidden;
    background: var(--cs-surface);
    gap: 0;
}

.contributor-tpl-magazine .cs-portrait img {
    max-width: none;
    width: 100%;
    max-height: 380px;
    object-position: center 22%;
    border-radius: 0;
}

.contributor-tpl-magazine .cs-identity {
    position: absolute;
    inset: auto 0 0 0;
    padding: 64px 26px 22px;
    /* VOILE NOIR ET TEXTE BLANC, EN DUR, ET C'EST VOULU.
       Ce bloc n'est pas pose sur une surface du theme : il est pose sur une
       PHOTOGRAPHIE. Le fond n'est donc pas un token, c'est l'image du
       contributeur, et personne ne sait de quelle couleur elle est.

       J'avais d'abord bati ce voile sur `var(--detail-bg)` en me disant qu'un
       noir en dur trancherait sur un theme clair. Deux erreurs dans cette
       phrase. D'une part le voile tombait alors clair chez un tenant clair,
       donc illisible sur une photo claire. D'autre part le texte, lui,
       heritait de `--primary-text-color` : constate en preproduction le
       13/09/2026, un texte #1d2025 sur un voile #0d0620, soit du sombre sur
       du sombre — le nom du contributeur avait disparu.

       Un degrade sombre plus un texte clair est le seul couple qui tienne sur
       une image quelconque. La fonction garde `--cs-accent`, qui donne 5,6:1
       sur ce voile. */
    background: linear-gradient(
        to top,
        rgba(0, 0, 0, .92) 12%,
        rgba(0, 0, 0, .62) 52%,
        rgba(0, 0, 0, 0)
    );
    color: #fff;
}

.contributor-tpl-magazine .cs-name { color: #fff; }

/* LE METIER GARDE LA COULEUR PRIMAIRE ICI, ET SEULEMENT ICI.

   La regle commune l'a passe a `--cs-accent-strong` le 16/09/2026 : sur le fond de contenu
   la primaire ne donnait que 3,39:1, contre 6,52:1 a la renforcee. Sur CE bandeau, le calcul
   s'inverse — le fond est un voile presque noir, et une couleur plus sombre ne peut qu'y
   perdre. Mesures du 16/09/2026, sur le voile a .92 :

     photo sombre  -> primaire 5,88:1   renforcee 3,05:1
     photo moyenne -> primaire 5,59:1   renforcee 2,90:1
     photo claire  -> primaire 5,26:1   renforcee 2,73:1

   La renforcee tomberait donc SOUS le seuil de 4,5:1 sur les trois cas. C'est la meme lecon
   que l'en-tete de ce fichier : une couleur ne se juge jamais sans son fond, et ce bandeau
   n'a pas le meme fond que le reste de la fiche. */
.contributor-tpl-magazine .cs-job { color: var(--cs-accent); }

.contributor-tpl-magazine .cs-name { font-size: clamp(28px, 4vw, 44px); }

/* Seul le RESUME quitte le bandeau : sur une photo, au-dela de deux lignes, plus
   rien n'est lisible. Il ne se perd pas pour autant — `resume()` rend le debut de
   la biographie quand aucun resume n'est saisi, et la biographie est affichee
   juste dessous, en entier.

   La citation, elle, est sortie du bloc d'identite le 13/09/2026 : elle est
   devenue une exergue pleine largeur, commune aux cinq gabarits. Et la date de
   mise a jour reste visible ici, sur le bandeau (demande de Sebastien : elle doit
   figurer quelque part dans TOUS les gabarits, pas seulement quelques-uns). */
.contributor-tpl-magazine .cs-summary { display: none; }

.contributor-tpl-magazine .cs-bio-body {
    max-width: none;
    columns: 2;
    column-gap: 42px;
}

/* Une colonne coupee au milieu d'une liste est illisible : on l'en empeche. */
.contributor-tpl-magazine .cs-bio-body ul,
.contributor-tpl-magazine .cs-bio-body ol { break-inside: avoid; }

@media (max-width: 991.98px) {
    .contributor-tpl-magazine .cs-bio-body { columns: 1; }
}

/* --- Vitrine : le catalogue d'abord, la biographie ensuite. ---------------- */

/* L'ordre des blocs est pose dans la vue, pas ici : c'est un ordre de lecture
   et de document, il doit exister aussi pour qui ne recoit pas le CSS. */
/* LE BANDEAU. C'est `.cs-lead` qui le porte, et non `.cs-head` : la citation est a
   l'interieur de l'enveloppe, pas de l'en-tete, et une enveloppe ne se traverse pas
   en CSS.

   La couleur de fond est celle du client (`--primary-enhanced-color`), jamais une
   valeur ecrite ici. La couleur du TEXTE est calculee en PHP a partir de ce fond et
   servie dans `--band-text-color` : c'est la seule facon de garantir la lisibilite
   sans supposer que le client a choisi un fond sombre. Le repli blanc ne sert que si
   la variable manque. */
.contributor-tpl-vitrine .cs-lead,
.contributor-tpl-profil .cs-lead {
    background: var(--cs-accent-strong);
    color: var(--band-text-color, #fff);
    border-radius: var(--cs-radius);
    /* Nomme, parce que la photo de « vitrine » l'annule par une marge negative pour
       venir affleurer les bords du bandeau : les deux valeurs doivent rester egales
       et opposees, elles ne peuvent donc pas etre ecrites deux fois. */
    --cs-band-pad-y: 20px;
    --cs-band-pad-x: 24px;
    padding: var(--cs-band-pad-y) var(--cs-band-pad-x);
}

/* BANDEAU REFONDU LE 14/09/2026 : la photo tient toute la colonne de gauche, et la
   citation passe sous les pastilles (demande de Sebastien).

   L'en-tete passe en `display: contents`. Ses trois blocs — portrait, identite,
   bouton — deviennent alors des cases de la grille du BANDEAU, au meme titre que la
   citation, qui est leur soeur dans le document et non leur cousine. C'est le seul
   moyen de poser la citation sous les pastilles ET la photo a cote des deux sans
   toucher au balisage, qui reste commun aux six gabarits. Le `<header>` garde son
   role dans le document : seule sa boite disparait.

   La specificite monte d'un cran (`.contributor-sheet.contributor-tpl-vitrine`)
   parce que `.contributor-sheet .cs-lead { display: block }` est declare plus bas
   dans cette feuille : a specificite egale, c'est le dernier qui gagnerait. */
.contributor-sheet.contributor-tpl-vitrine .cs-lead {
    display: grid;
    grid-template-columns: clamp(140px, 16vw, 200px) minmax(0, 1fr) auto;
    /* Le bandeau rogne ce qui depasse : c'est SON arrondi qui decoupe la photo
       affleurante, laquelle n'a donc aucun rayon a elle. */
    overflow: hidden;
    /* Une seule rangee par defaut. La seconde n'est ouverte que s'il y a une
       citation : sinon la gouttiere de rangee creuserait un vide en pied de
       bandeau, sous une rangee qui ne contient rien. */
    grid-template-rows: auto;
    align-items: center;
    column-gap: 24px;
    row-gap: 12px;
}

.contributor-sheet.contributor-tpl-vitrine .cs-lead:has(.cs-quote) {
    grid-template-rows: auto auto;
}

.contributor-tpl-vitrine .cs-head { display: contents; }

.contributor-tpl-vitrine .cs-identity { grid-column: 2; grid-row: 1; }
.contributor-tpl-vitrine .cs-cta { grid-column: 3; grid-row: 1; }

/* LA CITATION SOUS LES PASTILLES, dans la colonne du texte, et non plus en pied de
   bandeau sur toute sa largeur : elle appartient a la personne dont on vient de lire
   le nom et les mesures, elle se lit dans la meme colonne qu'eux. */
.contributor-sheet.contributor-tpl-vitrine .cs-lead .cs-quote {
    grid-column: 2 / -1;
    grid-row: 2;
    position: relative;
    margin: 0;
    padding: 0 0 0 46px;
}

/* LES GUILLEMETS SONT UN ORNEMENT, PAS UNE PONCTUATION. Le signe ouvrant est pose
   en marge du texte, en serif et en grand ; le fermant suit le dernier mot.

   `/ ""` leur donne un texte de remplacement VIDE : le dessin reste, mais une
   synthese vocale ne l'annonce pas — « guillemet-virgule double culbute » au milieu
   d'une phrase n'apprend rien a personne, et la balise `blockquote` dit deja que
   c'est une citation. Un navigateur qui ignorerait cette syntaxe rend la declaration
   invalide et n'affiche aucun signe : la citation reste lisible, seul l'ornement
   manque. */
.contributor-sheet.contributor-tpl-vitrine .cs-lead .cs-quote::before {
    content: "\201C" / "";
    position: absolute;
    left: 0;
    top: -.28em;
    font-family: Georgia, "Times New Roman", "Noto Serif", serif;
    font-size: 64px;
    line-height: 1;
    /* Assez pale pour rester un ornement, assez dense pour se voir : le signe
       n'est pas une information, il annonce une voix.

       La valeur n'est pas choisie a l'oeil. L'exergue porte deja `opacity: .92`,
       les deux se multiplient, et le signe sort donc a 0,57 du blanc. Mesure au
       pixel sur le fond du tenant (#ab2546) le 15/09/2026 : **3,15:1**, soit le
       seuil des elements non textuels — atteint alors meme que ce signe est
       decoratif et muet pour un lecteur d'ecran. Le baisser le fait passer
       dessous : a .55 il tombait a 2,75:1. */
    opacity: .62;
}

.contributor-sheet.contributor-tpl-vitrine .cs-lead .cs-quote p::after {
    content: "\00A0\201D" / "";
    font-family: Georgia, "Times New Roman", "Noto Serif", serif;
    font-size: 34px;
    line-height: 0;
    vertical-align: -.3em;
    opacity: .62;
}

/* Dans le bandeau, tout le texte prend la couleur calculee : le nom et les titres ont
   sinon leur propre jeton, prevu pour le fond de contenu et non pour celui-ci. */
.contributor-tpl-vitrine .cs-name,
.contributor-tpl-profil .cs-name,
.contributor-tpl-vitrine .cs-job,
.contributor-tpl-profil .cs-job { color: inherit; }

.contributor-tpl-vitrine .cs-lead .cs-quote,
.contributor-tpl-profil .cs-lead .cs-quote {
    border-left: 0;
    padding: 0;
    margin: 14px 0 0;
    max-width: none;
    opacity: .92;
}

.contributor-tpl-vitrine .cs-lead .cs-quote p,
.contributor-tpl-profil .cs-lead .cs-quote p {
    color: inherit;
    font-size: clamp(16px, 1.5vw, 19px);
}

/* --- Les etiquettes de genre. ---------------------------------------------- */

/* CE QUE LA PERSONNE ENSEIGNE LE PLUS, compte a partir de son catalogue (voir
   `ContributorProfile::genresDominants`). Trois a cinq mots, sans titre et sans chiffre :
   la rangee se parcourt du regard, elle ne se lit pas.

   Elle emprunte la forme des etiquettes de specialite du pied de fiche — meme pastille,
   meme filet, meme encre attenuee — parce que c'est la meme nature d'information. Deux
   dessins differents pour deux listes de mots courts auraient fait croire a deux choses
   differentes. */
.contributor-sheet .cs-genres {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    margin: 16px 0 14px;
    padding: 0;
}

.contributor-sheet .cs-genre {
    border: 1px solid var(--cs-line);
    background: var(--cs-surface);
    border-radius: 999px;
    padding: 5px 13px;
    font-size: 13px;
    line-height: 1.3;
    color: var(--cs-muted);
}

/* Dans un bandeau, l'encre est celle que le calcul a choisie pour ce fond : les etiquettes
   la suivent, comme les pastilles de mesure juste en dessous. Un filet fixe y sortirait
   invisible sur un fond sombre et dur sur un fond clair. */
.contributor-tpl-vitrine .cs-genre,
.contributor-tpl-profil .cs-genre {
    color: inherit;
    background: color-mix(in srgb, currentColor 12%, transparent);
    border-color: color-mix(in srgb, currentColor 24%, transparent);
}

/* --- Les mesures, en pastilles. ------------------------------------------- */

.contributor-sheet .cs-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    margin: 10px 0 0;
    padding: 0;
}

.contributor-sheet .cs-stat {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-size: 13px;
    line-height: 1.2;
    padding: 5px 12px;
    border-radius: 999px;
    /* Teintes derivees du texte du bandeau : elles suivent la couleur calculee et
       tiennent donc sur un fond clair comme sur un fond sombre. */
    background: color-mix(in srgb, currentColor 14%, transparent);
    border: 1px solid color-mix(in srgb, currentColor 26%, transparent);
    white-space: nowrap;
}

.contributor-sheet .cs-stat b {
    font-family: var(--cs-font-title);
    font-size: 16px;
    font-weight: 800;
}

.contributor-sheet .cs-star { font-size: 12px; }
.contributor-sheet .cs-stat-sep { opacity: .6; }
.contributor-sheet .cs-stat-date { opacity: .85; }

/* LA PHOTO TIENT TOUTE LA COLONNE DE GAUCHE, citation comprise : c'est ce qui la
   fait passer d'une vignette ronde de 84 px a un vrai portrait.

   Elle est posee en absolu dans sa case pour SUIVRE la hauteur des autres blocs au
   lieu de l'imposer : une image en flux aurait fixe la hauteur du bandeau par sa
   propre proportion, et le bandeau aurait grandi avec chaque photo un peu haute.
   `min-height` n'est qu'un plancher, pour la fiche sans citation et sans bouton. */
.contributor-tpl-vitrine .cs-portrait {
    grid-column: 1;
    grid-row: 1 / -1;
    align-self: stretch;
    position: relative;
    /* La marge negative annule le rembourrage du bandeau sur ces trois bords : la
       photo touche le haut, le bas et la gauche. Elle est exactement opposee au
       rembourrage, d'ou la variable — une valeur recopiee finirait par diverger.

       Consequence utile : la marge etant retranchee, `min-height` fixe ici la
       hauteur TOTALE du bandeau quand le texte est court. 176 px donne un carre
       sur la fiche la plus depouillee, et un portrait des qu'il y a une citation. */
    margin: calc(-1 * var(--cs-band-pad-y)) 0 calc(-1 * var(--cs-band-pad-y)) calc(-1 * var(--cs-band-pad-x));
    min-height: 176px;
}

.contributor-tpl-vitrine .cs-portrait img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    border-radius: 0;
    object-fit: cover;
    /* Le sujet d'un portrait est en haut du cadre : recadrer par le centre lui
       coupe le front des que la photo est plus haute que sa case. */
    object-position: 50% 28%;
}

.contributor-tpl-vitrine .cs-name { font-size: clamp(21px, 2.4vw, 27px); margin-bottom: 2px; }
.contributor-tpl-vitrine .cs-job { margin-bottom: 0; }

/* Le bandeau doit rester un bandeau : seul le resume, qui peut faire trois lignes,
   en sort. La citation n'y est plus depuis qu'elle est devenue une exergue pleine
   largeur, et la date y reste — elle doit figurer dans tous les gabarits. */
.contributor-tpl-vitrine .cs-summary { display: none; }

.contributor-tpl-vitrine .cs-updated {
    margin-top: 4px;
}

/* --- Profil collant : l'identite reste a l'ecran pendant qu'on fouille. ----- */

/* Ce gabarit repond a un cas precis : un contributeur au catalogue long. Sur la
   fiche la plus fournie de Diva Yoga, atteindre le dernier cours demandait dix-huit
   clics de carrousel, sans jamais savoir ou l'on en etait. Le rail fige l'identite
   et le bouton d'entree pendant que la colonne de droite defile.

   L'enveloppe passe en grille : c'est la seule maniere d'obtenir une colonne qui
   s'etend sur toute la hauteur du contenu, condition pour que `position: sticky`
   ait de quoi coller. Tous les autres blocs vont en colonne 2, dans leur ordre de
   document — l'ordre de lecture reste celui de la vue. */
/* L'ENVELOPPE DE FLUX. Pour cinq gabarits sur six elle n'existe pas : `display: contents`
   fait disparaitre sa boite et ses enfants redeviennent enfants directs de la fiche. Voir
   le commentaire de `partials/identity.blade.php` pour ce qu'elle repare ici. */
.contributor-sheet .cs-flow { display: contents; }

.contributor-tpl-profil {
    display: grid;
    /* DEUX COLONNES, UNE SEULE RANGEE, et c'est la rangee unique qui compte : le rail et le
       flux sont les deux seuls enfants, donc la hauteur du rail ne peut plus ecarter les blocs
       de droite les uns des autres. Tant qu'il y avait une rangee par bloc, un rail plus haut
       que le premier d'entre eux creusait la difference en vide — 122 px mesures au banc le
       16/09/2026, 264 px sur la fenetre de Sebastien. */
    grid-template-columns: minmax(230px, 300px) minmax(0, 1fr);
    grid-template-rows: auto;
    align-items: start;
    gap: var(--cs-gap);

    /* OU LE RAIL S'ARRETE EN COLLANT. `24px` ne suffisait pas : l'en-tete du site est en
       `position: fixed` et mesure 68 px de haut sur Diva Yoga (mesure du 16/09/2026), si bien
       que le haut de la carte — le portrait et le nom — passait DESSOUS. 68 + 24 de respiration.
       La valeur est un jeton pour qu'un tenant a l'en-tete plus haut la reprenne d'un seul
       endroit, sans toucher aux trois regles qui s'en servent. */
    --cs-sticky-top: 92px;
}

.contributor-tpl-profil > .cs-flow {
    grid-column: 2;
    display: flex;
    flex-direction: column;
    gap: var(--cs-gap);
    min-width: 0;
}

.contributor-tpl-profil > .cs-lead {
    grid-column: 1;
    grid-row: 1;
    position: sticky;
    top: var(--cs-sticky-top);

    /* UN RAIL PLUS HAUT QUE LA FENETRE NE SE LIT PLUS. Colle par le haut, sa fin reste
       hors de l'ecran quoi qu'on fasse : le bouton « Commencer un cours » et la citation
       devenaient inatteignables sur un portable de 13 pouces des que la fiche portait les
       deux. Il defile alors sur lui-meme. `contain` evite qu'arrive en bout de course il
       relaie le geste a la page, ce qui ferait sauter la lecture. */
    max-height: calc(100vh - var(--cs-sticky-top) - 16px);
    overflow: hidden auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

/* Le rail est etroit : l'en-tete s'y empile au lieu de se poser en deux colonnes. */
.contributor-tpl-profil .cs-head {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
}

.contributor-tpl-profil .cs-portrait img {
    width: 100%;
    max-width: none;
    aspect-ratio: 1 / 1;
}

.contributor-tpl-profil .cs-name { font-size: clamp(22px, 2.2vw, 28px); }

/* Meme raison que pour « vitrine » : le resume repete les premieres lignes de la
   biographie, qui est juste a cote. Dans une colonne de 300 px il ferait dix lignes. */
.contributor-tpl-profil .cs-summary { display: none; }


/* --- Le bouton d'entree dans le catalogue. --------------------------------- */

/* Il est **en trait, pas en aplat**, et c'est un choix, pas un oubli. Un bouton
   plein impose une couleur de texte sur une couleur de fond ; les deux viennent du
   reglage du tenant, que rien n'oblige a s'accorder — c'est exactement la panne
   mesuree le 13/09/2026 sur cette meme fiche (1,21:1). Un bouton en trait herite du
   texte de la page : il est lisible sur n'importe quel fond, par construction. */
.contributor-sheet .cs-cta {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    min-width: 0;
}

.contributor-sheet .cs-cta-btn {
    display: inline-block;
    padding: 9px 18px;
    border: 1px solid currentColor;
    border-radius: 999px;
    font-family: var(--cs-font-title);
    font-weight: 700;
    font-size: 14px;
    line-height: 1.2;
    color: inherit;
    text-decoration: none;
    background: transparent;
    transition: background-color .18s ease;
}

.contributor-sheet .cs-cta-btn:hover,
.contributor-sheet .cs-cta-btn:focus-visible {
    /* 4 % du texte courant : une teinte qui se voit sur un fond clair comme sur un
       fond sombre, sans jamais supposer lequel. */
    background-color: var(--cs-surface);
    color: inherit;
    text-decoration: none;
}

.contributor-sheet .cs-cta-hint {
    margin: 0;
    font-size: 12px;
    line-height: 1.35;
    color: var(--cs-muted);
    max-width: 220px;
}

/* Dans le bandeau, le bouton est a droite, et il est PLEIN : l'aplat prend la couleur
   du texte calcule et le libelle reprend celle du fond. Les deux viennent du meme
   calcul, donc le contraste est le meme que celui du bandeau, quel que soit le client
   — c'est le seul bouton plein que cette feuille se permet. */
.contributor-tpl-vitrine .cs-cta { align-items: flex-end; text-align: right; }
.contributor-tpl-vitrine .cs-cta-hint {
    max-width: 200px;
    color: inherit;
    /* .88 et pas .8 : mesure au canvas sur le fond compose, le titre du cours tombait a
       4,85:1 a 12 px — au-dessus du seuil, mais sans marge. A .88 il remonte a 5,6. */
    opacity: .88;
}

.contributor-tpl-vitrine .cs-cta-btn,
.contributor-tpl-profil .cs-cta-btn {
    background: var(--band-text-color, #fff);
    color: var(--cs-accent-strong);
    border-color: transparent;
}

.contributor-tpl-vitrine .cs-cta-btn:hover,
.contributor-tpl-vitrine .cs-cta-btn:focus-visible,
.contributor-tpl-profil .cs-cta-btn:hover,
.contributor-tpl-profil .cs-cta-btn:focus-visible {
    background: color-mix(in srgb, var(--band-text-color, #fff) 88%, transparent);
    color: var(--cs-accent-strong);
}

.contributor-tpl-profil .cs-cta { align-items: stretch; }
.contributor-tpl-profil .cs-cta-btn { justify-content: center; text-align: center; }

/* Dans le rail, la borne de 200 px de « vitrine » n'a plus de sens : la colonne fait deja
   252 px de contenu, et brider le titre du cours a 200 le cassait en deux lignes courtes
   (« Body Fx · Express - La routine du / matin »). Il prend la largeur de la carte. */
.contributor-tpl-profil .cs-cta-hint {
    max-width: none;
    color: inherit;
    opacity: .88;
}

/* --- Recherche et tri du catalogue. ---------------------------------------- */

/* La barre reste `hidden` tant que le script ne l'a pas prise en charge : un champ
   de recherche qui ne cherche rien vaut moins que pas de champ. */
.cs-catalogue .cs-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin: 0 0 16px;
}

/* Le champ prend la place disponible, mais pas toute : sans plafond il ecrasait le tri,
   dont le libelle le plus long (« Les plus recents ») sortait coupe et sans sa fleche.
   Constate en preproduction le 14/09/2026 sur une fenetre de 1457 px. */
.cs-catalogue .cs-search {
    position: relative;
    flex: 1 1 220px;
    min-width: 170px;
    max-width: 420px;
}

.cs-catalogue .cs-search-input {
    width: 100%;
    padding: 8px 34px;
    border: 1px solid var(--cs-line);
    border-radius: 999px;
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 14px;
}

.cs-catalogue .cs-search-input::placeholder { color: var(--cs-faint); opacity: 1; }

.cs-catalogue .cs-search-icon {
    position: absolute;
    left: 13px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 13px;
    color: var(--cs-faint);
    pointer-events: none;
}

.cs-catalogue .cs-search-clear {
    position: absolute;
    right: 5px;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: transparent;
    color: var(--cs-muted);
    font-size: 14px;
    line-height: 1;
    padding: 6px 9px;
    border-radius: 50%;
    cursor: pointer;
}

.cs-catalogue .cs-search-clear:hover { background-color: var(--cs-surface); }

/* LE BOUTON DE CLASSEMENT.

   Premier fait, et il change tout : **le site remplace chaque `select` par le composant
   `nice-select`**. Au moment ou le visiteur voit la barre, le `<select>` est `display: none`
   et ce qui s'affiche est un `div.nice-select.cs-sort` — le composant recopie les classes du
   champ, si bien que les regles ecrites pour un `select` natif atterrissent sur lui sans
   qu'on l'ait voulu. Quatre defauts en decoulaient, tous mesures le 16/09/2026 :

     · `padding: 8px 12px` ecrasait la reserve de 30 px que `nice-select` garde a droite pour
       sa fleche : elle se posait SUR le dernier mot du libelle (« Les plus recent✦s ») ;
     · le composant sortait a 42 px de haut contre 39 pour le champ de recherche — deux
       pastilles voisines, de deux hauteurs ;
     · l'etiquette `<label for>` designait le `select` masque ; le `div` qui le remplace
       n'annoncait rien. Au clavier comme au lecteur d'ecran, la commande etait sans nom, et
       « Les plus recents » tout seul ne dit pas qu'il s'agit d'un classement ;
     · `:focus-visible` peignait le contour du `select` masque, jamais celui du composant :
       la barre se traversait au clavier sans que rien ne se voie.

   La forme est reprise du champ de recherche — meme filet, meme rayon, meme hauteur — parce
   que les deux commandes servent la meme liste et doivent se lire comme une paire. La liste
   deroulante garde les couleurs du composant, qui sont celles du theme du tenant.

   Les deux selecteurs sont ecrits cote a cote : le natif sert quand le composant n'est pas
   monte (script du site en echec), et rien ne doit changer d'aspect entre les deux etats. */
.cs-catalogue .cs-sort-field {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

/* « Trier » etait masque aux voyants. Le rendre visible coute deux mots et supprime la
   devinette : sans lui, la pastille ressemble a un filtre actif plutot qu'a un classement. */
.cs-catalogue .cs-sort-label {
    font-size: 13px;
    color: var(--cs-muted);
    white-space: nowrap;
    margin: 0;
    cursor: pointer;
}

.cs-catalogue .cs-sort,
.cs-catalogue .nice-select.cs-sort {
    /* Ni compression ni etirement : la commande se dimensionne sur son libelle le plus long. */
    flex: 0 0 auto;
    width: auto;
    height: auto;
    min-height: 39px;
    /* 34 px a droite : c'est la place de la fleche, et c'est ce qui manquait. */
    padding: 8px 34px 8px 15px;
    border: 1px solid var(--cs-line);
    border-radius: 999px;
    font: inherit;
    font-size: 14px;
    line-height: 21px;
    max-width: 100%;
}

/* La fleche du composant est peinte en gris fixe (#999). Reprise au texte courant, elle
   reste visible sur un fond clair comme sur un fond sombre — meme raison que partout
   ailleurs dans cette feuille. */
.cs-catalogue .nice-select.cs-sort::after {
    border-color: currentColor;
    right: 16px;
    opacity: .7;
}

/* La liste ouverte doit passer DEVANT le rail, dont les fleches montent a `z-index: 20`.
   Sans cela, les trois options s'ouvraient derriere la premiere carte. */
.cs-catalogue .nice-select.cs-sort.open { z-index: 40; }
.cs-catalogue .nice-select.cs-sort .list { z-index: 40; }

/* DEUX HABITUDES DU COMPOSANT QUI N'ONT PAS LEUR PLACE SUR TROIS OPTIONS.

   La version de `nice-select` employee par le site ouvre CHAQUE liste avec un champ
   « Recherche... » et masque l'option en cours par un `style="display: none"` pose sur la
   ligne. Sur une liste longue, les deux se defendent. Sur un classement a trois entrees :

     · le champ de recherche demande de lire, de comprendre puis d'ecarter une commande qui
       ne sert a rien — la liste entiere tient dans la hauteur du champ lui-meme ;
     · la liste change de contenu a chaque choix : on ouvre, on voit deux lignes, on choisit,
       on rouvre, ce ne sont plus les memes deux lignes. Le classement en cours, lui,
       n'apparait nulle part dans la liste. Une liste qui se reecrit se relit a chaque fois.

   Les trois options s'affichent donc toujours, celle en cours marquee. Le `!important` est
   ici obligatoire et non un raccourci : le composant ecrit `display: none` EN ATTRIBUT DE
   STYLE, qu'aucune specificite de feuille ne bat. La portee reste ce seul classement — le
   reste du site garde le composant tel qu'il est. */
.cs-catalogue .nice-select.cs-sort .nice-select-search { display: none !important; }

.cs-catalogue .nice-select.cs-sort .list .option.ns-default-hidden {
    display: list-item !important;
}

.cs-catalogue .nice-select.cs-sort .list .option.selected {
    font-weight: 700;
}

/* LE CONTOUR DE FOCUS N'APPARAISSAIT PAS, ET IL N'EST PAS DECORATIF : sans lui, la barre se
   traverse au clavier sans que rien ne se voie, et l'on ne sait plus ou l'on est.

   La regle existait depuis le 14/09/2026 et ne s'appliquait pas. Mesure du 16/09/2026 sur
   Diva Yoga, au clavier, `:focus-visible` verifie a `true` sur le champ comme sur le tri :
   `outline-style` sortait a `none` dans les deux cas. Une declaration `!important` du socle
   du site eteint le contour de toute commande ; a poids ordinaire, aucune specificite ne la
   bat. Le meme poids est donc pose ici — c'est la seule facon de rendre le focus visible,
   et la portee reste cette barre. Verifie apres coup : contour de 2 px present sur les deux
   commandes. */
/* La chaine est longue — quatre classes — et chaque cran a ete necessaire : a trois, le
   contour sortait en `solid 0px` sur le composant de tri, une declaration prioritaire du
   socle imposant encore sa largeur nulle. Mesure a chaque cran avant de s'arreter la.

   TROIS PROPRIETES SEPAREES, ET PAS LA FORME COURTE. Constate en preproduction le
   16/09/2026, apres que la forme courte eut suffi au banc : sur ce tenant, `megamenu.css`
   declare `* { outline: 0 !important }`, et le `outline: 2px solid currentColor !important`
   sortait a **`solid 0px`** sur le composant de tri — la couleur et le style tenaient, la
   largeur tombait. Le champ de recherche, lui, gardait ses 2 px. Ecrites une a une, les
   trois proprietes tiennent sur les deux commandes : mesure `solid 2px`, decalage 2 px.

   Ne pas « simplifier » en revenant a la forme courte : elle a deja echoue une fois, et
   l'echec ne se voit pas au banc. */
.contributor-sheet .cs-catalogue .cs-toolbar .cs-search-input:focus-visible,
.contributor-sheet .cs-catalogue .cs-toolbar .cs-search-clear:focus-visible,
.contributor-sheet .cs-catalogue .cs-toolbar .cs-sort:focus-visible,
.contributor-sheet .cs-catalogue .cs-toolbar .nice-select.cs-sort:focus-visible {
    outline-width: 2px !important;
    outline-style: solid !important;
    outline-color: currentColor !important;
    outline-offset: 2px;
}

.cs-catalogue .cs-results-count {
    /* Pousse au bout de la barre : les deux commandes se tiennent a gauche, le resultat de
       ce qu'elles font se lit a droite. Colle contre le tri, il se lisait comme sa legende. */
    margin: 0 0 0 auto;
    font-size: 13px;
    color: var(--cs-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.cs-catalogue .cs-no-result {
    margin: 18px 0 0;
    font-size: 14px;
    color: var(--cs-muted);
}

/* Etiquette reservee aux lecteurs d'ecran : le champ et le tri ont un `label`
   reel, il n'est simplement pas peint. */
.contributor-sheet .cs-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* --- La grille de resultats. ----------------------------------------------- */

/* Le carrousel est detruit des qu'un filtre ou un tri est actif (voir l'en-tete de
   `contributor-catalogue.js`) : le meme conteneur devient alors une grille. Masquer
   une carte a l'interieur d'Owl laisserait un trou de la largeur d'une carte. */
/* LA MEME CARTE AVANT ET APRES. Le rail et la grille montrent le meme catalogue : une carte
   qui retrecit d'un tiers des qu'on trie donne a croire qu'on a change de page. Mesure du
   16/09/2026 dans la colonne du gabarit « profil collant », large de 1168 px : le rail
   servait des cartes de 234 px, la grille en tirait sept de 155 px, et les titres y
   repassaient tronques (« Yoga Balles – Pour la ligne... »). Les bornes ci-dessous donnent
   cinq colonnes de 234 px pour les cours et trois de 389 px pour les series : exactement ce
   que montre le rail a cette largeur, et la grille suit ensuite la place disponible. */
.cs-catalogue .px-owl.cs-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 14px;
}

.cs-catalogue[data-cs-catalogue="series"] .px-owl.cs-grid {
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}

.cs-catalogue .px-owl.cs-grid > [data-cs-item] { width: auto; }

/* Une carte filtree est masquee par l'attribut `hidden`. Il ne suffit PAS : le socle des
   cartes declare `.single-video { display: block }`, une regle d'auteur qui bat la feuille
   du navigateur. Sans la ligne ci-dessous, la recherche reordonnerait les cartes sans
   jamais en cacher une seule — mesure faite au banc le 14/09/2026, avant tout push. La
   specificite suffit, aucun `!important` n'est necessaire. */
.cs-catalogue .px-owl.cs-grid > [data-cs-item][hidden] { display: none; }

/* --- Presentation : la video de presentation en tete de page. -------------- */

/* `.cs-lead` enveloppe TOUJOURS l'en-tete, quel que soit le gabarit : c'est ce qui
   evite d'ecrire deux fois le balisage de l'en-tete dans la vue, une fois avec la
   video et une fois sans. Par defaut elle ne fait rien de plus qu'un bloc — la
   fiche se rend exactement comme si l'en-tete etait la directement. */
.contributor-sheet .cs-lead { display: block; }

/* Elle ne devient la mise en page a deux colonnes que pour le gabarit
   `presentation`, ET seulement si une video a reellement ete rendue. */
.contributor-tpl-presentation .cs-lead:has(.cs-lead-frame) {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(260px, 1fr);
    gap: var(--cs-gap);
    align-items: stretch;
}

.contributor-sheet .cs-lead-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: var(--cs-radius);
    overflow: hidden;
    background: var(--cs-surface);
    border: 1px solid var(--cs-line);
}

.contributor-sheet .cs-lead-frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Quand la video mene, l'identite devient une carte de cote : portrait en
   medaillon, nom, fonction, resume. */
.contributor-tpl-presentation .cs-head {
    grid-template-columns: 1fr;
    gap: 14px;
    align-content: center;
    background: var(--cs-surface);
    border: 1px solid var(--cs-line);
    border-radius: var(--cs-radius);
    padding: 20px;
}

.contributor-tpl-presentation .cs-portrait img {
    width: 72px;
    height: 72px;
    max-width: none;
    border-radius: 50%;
    object-fit: cover;
}

.contributor-tpl-presentation .cs-name { font-size: clamp(21px, 2.4vw, 28px); }

.contributor-tpl-presentation .cs-bio,
.contributor-tpl-presentation .cs-custom {
    max-width: 68ch;
}

/* Le gabarit `presentation` sans video retombe sur la mise en page classique :
   la vue ne rend alors aucun `.cs-lead`, et ce selecteur remet le portrait a sa
   taille normale. Sans ce repli, la fiche s'ouvrirait sur une carte d'identite
   minuscule et vide de sens. */
.contributor-tpl-presentation:not(:has(.cs-lead-frame)) .cs-head {
    grid-template-columns: minmax(180px, 300px) minmax(0, 1fr);
    background: none;
    border: 0;
    padding: 0;
    gap: var(--cs-gap);
}

.contributor-tpl-presentation:not(:has(.cs-lead-frame)) .cs-portrait img {
    width: 100%;
    height: auto;
    max-width: 300px;
    border-radius: var(--cs-radius);
}

.contributor-tpl-presentation:not(:has(.cs-lead-frame)) .cs-name {
    font-size: clamp(26px, 3.4vw, 38px);
}

/* ========================================= Specialites et coordonnees ======= */

.contributor-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--cs-gap);
    margin-top: 36px;
    padding-top: 28px;
    border-top: 1px solid var(--cs-line);
    font-family: var(--cs-font-body);
}

.contributor-facts .cf-block { min-width: 0; }

.contributor-facts .cf-subtitle {
    font-family: var(--cs-font-title);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--cs-title);
    margin: 20px 0 10px;
}

/* Les specialites sont des etiquettes, pas des puces : ce sont des termes
   courts qu'on parcourt du regard, et une liste verticale les etirerait sur
   dix lignes. */
.contributor-facts .cf-tags {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.contributor-facts .cf-tag {
    border: 1px solid var(--cs-line);
    background: var(--cs-surface);
    border-radius: 999px;
    padding: 6px 14px;
    font-size: 14px;
    line-height: 1.3;
    color: var(--cs-muted);
}

.contributor-facts .cf-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.contributor-facts .cf-list li {
    display: flex;
    align-items: baseline;
    gap: 10px;
    font-size: 15px;
    overflow-wrap: anywhere;
    color: var(--cs-muted);
}

.contributor-facts .cf-list a { color: var(--cs-accent); }

.contributor-facts .cf-icon { color: var(--cs-accent); width: 18px; flex: none; }

.contributor-facts .cf-links {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.contributor-facts .cf-links a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border: 1px solid var(--cs-line);
    border-radius: 999px;
    padding: 7px 15px;
    font-size: 14px;
    color: var(--cs-muted);
    /* 40px de cible : une pastille de 30px se rate au doigt. Elle passe a 44px
       des qu'on est sur un pointeur grossier, plus bas. */
    min-height: 40px;
    transition: border-color .2s ease-out, background-color .2s ease-out, color .2s ease-out;
}

.contributor-facts .cf-links a:hover,
.contributor-facts .cf-links a:focus-visible {
    border-color: var(--cs-accent);
    color: var(--cs-accent);
    background: var(--cs-surface);
    text-decoration: none;
}

.contributor-facts .cf-empty {
    color: var(--cs-faint);
    font-style: italic;
    margin: 0;
}

/* Le gabarit portrait centre aussi ses deux colonnes de bas de page, pour ne
   pas rompre l'axe central qu'il vient d'installer. */
.contributor-tpl-portrait.contributor-facts { text-align: center; }
.contributor-tpl-portrait.contributor-facts .cf-tags,
.contributor-tpl-portrait.contributor-facts .cf-links { justify-content: center; }
.contributor-tpl-portrait.contributor-facts .cf-list li { justify-content: center; }

/* ================================================================ Ecrans ==== */

@media (pointer: coarse) {
    .contributor-facts .cf-links a { min-height: 44px; }

    /* Mesure au banc le 14/09/2026 : le bouton sortait a 37 px de haut, le champ et le
       tri a 36. Sous le doigt, le seuil est 44. `inline-flex` sert uniquement a centrer
       le libelle une fois la hauteur imposee. */
    .contributor-sheet .cs-cta-btn {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }

    .cs-catalogue .cs-search-input,
    .cs-catalogue .cs-sort { min-height: 44px; }

    .cs-catalogue .cs-search-clear { min-width: 36px; min-height: 36px; }
}

@media (max-width: 767.98px) {
    .contributor-sheet .cs-head,
    .contributor-tpl-portrait .cs-head,
    .contributor-tpl-presentation:not(:has(.cs-lead-frame)) .cs-head {
        grid-template-columns: 1fr;
    }

    .contributor-sheet .cs-portrait img,
    .contributor-tpl-portrait .cs-portrait img,
    .contributor-tpl-presentation:not(:has(.cs-lead-frame)) .cs-portrait img {
        max-width: 220px;
        aspect-ratio: 1 / 1;
    }

    /* Le bandeau vitrine se replie : la photo garde sa colonne mais redevient un
       carre a cote du seul nom ; le bouton et la citation passent dessous, pleine
       largeur. Trois colonnes sur 375 px ecraseraient le nom. */
    .contributor-sheet.contributor-tpl-vitrine .cs-lead,
    .contributor-sheet.contributor-tpl-vitrine .cs-lead:has(.cs-quote) {
        grid-template-columns: clamp(88px, 26vw, 116px) minmax(0, 1fr);
        grid-template-rows: auto;
        column-gap: 14px;
    }

    /* Plus d'affleurement sur telephone : la photo ne couvre qu'une rangee sur
       trois, un debord haut et bas mordrait sur le bouton et sur la citation.

       Pas d'`aspect-ratio` non plus : etirer une case ET lui imposer un rapport,
       c'est demander deux choses contradictoires, et Chrome resout en prenant la
       hauteur comme largeur — la photo debordait de sa colonne sur le nom (mesure
       le 14/09/2026 : 199 px de large dans une colonne de 97). La photo prend la
       hauteur de la rangee du nom, un portrait etroit, ce qui est le sujet. */
    .contributor-tpl-vitrine .cs-portrait {
        grid-row: 1;
        margin: 0;
        min-height: 0;
    }

    .contributor-tpl-vitrine .cs-portrait img {
        border-radius: calc(var(--cs-radius) - 4px);
    }

    /* Rangee automatique, et non la rangee 2 fixe : sans bouton, la citation doit
       remonter d'un cran au lieu de laisser une rangee vide au-dessus d'elle. */
    .contributor-sheet.contributor-tpl-vitrine .cs-lead .cs-quote {
        grid-column: 1 / -1;
        grid-row: auto;
        padding-left: 34px;
    }

    .contributor-tpl-presentation .cs-portrait img { aspect-ratio: 1 / 1; }

    /* LES PASTILLES DEBORDAIENT DE LA CARTE SUR TELEPHONE. Le rail replie garde deux
       colonnes — portrait a gauche, identite a droite — et la regle de 140 px du palier
       991 laissait 164 px a l'identite sur une fenetre de 390 px. Or « Mis a jour le
       15/09/2026 » mesure environ 170 px a 13 px de corps, et `white-space: nowrap`
       l'empeche de se couper : la pastille sortait du bandeau, tronquee par l'arrondi
       (mesure du 16/09/2026). Le portrait suit desormais la largeur de l'ecran, comme
       celui de « vitrine » au meme palier. */
    /* La specificite monte d'un cran, et ce n'est pas un ornement : le palier 991, qui pose
       le portrait a 140 px, est ecrit PLUS BAS dans cette feuille. A poids egal, c'est lui
       qui gagnerait — ces deux regles n'auraient alors servi a rien. */
    .contributor-sheet.contributor-tpl-profil .cs-head {
        grid-template-columns: clamp(88px, 24vw, 116px) minmax(0, 1fr);
    }

    .contributor-sheet.contributor-tpl-profil .cs-portrait img {
        max-width: none;
        width: 100%;
    }

    /* Le garde-fou qui va avec : une pastille plus longue que sa colonne se coupe en deux
       lignes au lieu de deborder. `nowrap` tient tant qu'il y a la place, et rien de plus. */
    .contributor-sheet .cs-stat { white-space: normal; }

    .contributor-sheet .cs-lead,
    .contributor-tpl-vitrine .cs-bio-duo:has(.cs-bio-video),
    .contributor-tpl-profil .cs-bio-duo:has(.cs-bio-video) { grid-template-columns: 1fr; }

    .contributor-sheet { --cs-gap: 20px; }

    /* Le bandeau vitrine descend le bouton sous le compteur plutot que d'ecraser
       le nom sur quatre colonnes. */
    .contributor-tpl-vitrine .cs-cta {
        grid-column: 1 / -1;
        grid-row: auto;
        align-items: flex-start;
        text-align: left;
    }
}

/* Le rail collant n'a plus de place a cote : il redevient un bloc ordinaire, en
   tete de page. Le seuil est celui du gabarit a deux colonnes, pas celui du
   telephone : a 900 px la colonne de droite ne ferait deja plus que 600 px. */
@media (max-width: 991.98px) {
    .contributor-tpl-profil {
        display: flex;
        flex-direction: column;

        /* `align-items: start` VENAIT DE LA GRILLE, ET NE DEVAIT PAS SUIVRE ICI.

           Sur la grille, il empeche le rail d'identite de s'etirer sur toute la hauteur.
           Repris tel quel par la colonne en `flex`, il change de sens : l'axe croise devient
           l'horizontale, et chaque bloc prend alors la largeur de SON CONTENU au lieu de
           celle du conteneur. Or le contenu d'un rail, ce sont ses cartes mises bout a bout.
           Mesure du 16/09/2026 sur une fenetre de 900 px : la section des cours sortait a
           **23 433 px** de large et la page entiere a **726 807 px** — un defilement
           horizontal de sept cent mille pixels sur telephone et sur tablette, present depuis
           la creation du gabarit.

           `stretch` est le comportement par defaut de `flex` ; il est ecrit ici parce que la
           regle de la grille, plus haut, l'a remplace. */
        align-items: stretch;
    }

    .contributor-tpl-profil > *,
    .contributor-tpl-profil > .cs-lead {
        grid-column: auto;
        grid-row: auto;
        position: static;
        /* Le rail redevenu bloc ordinaire n'a plus a se borner ni a defiler sur lui-meme :
           c'est la page qui defile. Sans cette remise a zero, une fiche fournie sortirait
           une barre de defilement a l'interieur du bandeau sur telephone. */
        max-height: none;
        overflow: visible;
    }

    .contributor-tpl-profil .cs-head {
        grid-template-columns: auto minmax(0, 1fr);
        align-items: center;
    }

    .contributor-tpl-profil .cs-portrait img { max-width: 140px; }

    /* Le bouton d'entree est le TROISIEME enfant de l'en-tete : replie sur deux colonnes, il
       tombait dans celle du portrait, large de 94 px sur telephone. Son libelle sortait en
       deux lignes et le titre du cours en trois (mesure du 16/09/2026). Il prend la largeur
       du bandeau, qui est ce qu'on attend d'un bouton d'appel. */
    .contributor-tpl-profil .cs-cta { grid-column: 1 / -1; }
}

/* --- Classique : l'en-tete se rechauffe, la biographie s'abrege. ----------- */

/* AJOUTE LE 16/09/2026. Tout ce qui suit est prefixe `.contributor-tpl-classique` :
   les cinq autres gabarits ne changent pas d'un pixel.

   Les gestes viennent d'une consultation de `EXTERNE_ui-ux-pro-max` (requete « wellness
   yoga instructor profile page warm editorial content-first »). La base proposait aussi
   une palette #EC4899 et un couple Lora / Raleway : ECARTES. Couleurs et polices
   appartiennent au reglage du tenant, et les imposer ici casserait toutes les instances
   qui ne sont pas Diva Yoga. Seul ce qui est structurel ou derive d'un token est retenu. */

/* P7 · La page respire. 40 px au lieu de 28 des qu'il y a la place ; en dessous de
   992 px la valeur commune reprend, sinon le telephone passe son temps a defiler. */
@media (min-width: 992px) {
    .contributor-tpl-classique { --cs-gap: 40px; }
}

/* P3 · LA SURFACE TIEDE. C'est le geste qui porte le « chaleureux » demande, et il ne
   coute aucune couleur en dur : 4 % de l'accent du tenant, pose en transparence sur le
   fond de page, quel qu'il soit.

   MESURE DU 16/09/2026, et c'est elle qui fixe les 4 % : sur le #FAFAFA de Diva Yoga,
   la surface calcule a rgb(249, 244, 244). La citation, qui sort en `--primary-color`
   #E05C70, y tombe de **3,39:1 a 3,24:1**. Le seuil applicable est 3:1 (WCAG 1.4.3,
   texte de 24 px ou plus) : la regle passe, avec 0,24 de marge. Le nom reste a 14,97:1
   et le texte attenue a 6,18:1.

   ==Ne pas monter au-dessus de 4 %== sans remesurer : a 8 % la citation tombe a 3,10:1
   et la marge disparait. Le levier, si un tenant a un accent plus clair encore, est de
   baisser ce pourcentage — pas de rapetisser la citation. */
.contributor-tpl-classique .cs-lead {
    background: color-mix(in srgb, var(--cs-accent) 4%, transparent);
    border-radius: 24px;
    padding: 32px;
}

@media (max-width: 575.98px) {
    .contributor-tpl-classique .cs-lead {
        border-radius: 18px;
        padding: 20px;
    }

    /* Sur 375 px, les 34 px de retrait du guillemet mangent 9 % de la largeur utile et
       decalent visiblement la citation par rapport au nom juste au-dessus. Le signe
       retrecit avec le retrait : la composition reste la meme, en plus serre. */
    .contributor-tpl-classique .cs-identity .cs-quote { padding-left: 26px; }
    .contributor-tpl-classique .cs-identity .cs-quote::before { font-size: 42px; }
}

/* P1 · Le portrait prend une ombre et un rayon plus genereux. L'ombre est derivee de
   `currentColor` comme tout le reste du fichier : elle se voit sur un fond clair comme
   sur un fond sombre, sans jamais supposer lequel. */
.contributor-tpl-classique .cs-portrait img {
    border-radius: 20px;
    box-shadow: 0 12px 32px color-mix(in srgb, currentColor 12%, transparent);
}

/* P2 · LA CITATION, sous le nom.

   Le guillemet ouvrant reprend exactement le traitement deja pose pour « vitrine » plus
   haut dans ce fichier : reutiliser plutot qu'inventer une deuxieme maniere de marquer
   une citation. Le filet de gauche de 3 px s'efface alors — le guillemet porte deja le
   signal, et les deux ensemble alourdissent un bloc d'identite qui est serre.

   La gouttiere de 28 px heritee de `.cs-quote` n'a plus de sens ici : la citation n'est
   plus une exergue pleine largeur separee de l'en-tete, elle est DANS l'en-tete. */
.contributor-tpl-classique .cs-identity .cs-quote {
    position: relative;
    border-left: 0;
    padding: 0 0 0 34px;
    margin: 14px 0 18px;
    max-width: 62ch;
}

/* LE GUILLEMET EST REPRIS MOT POUR MOT DU TRAITEMENT DE « VITRINE » (ligne 528), a la
   taille pres. Trois details de cette regle ne sont pas cosmetiques, et les redecouvrir
   par l'experience coute une demi-journee :

   · **La pile SERIF est obligatoire.** Rendu dans la police du tenant — Nunito chez Diva
     Yoga — le caractere \201C sort en deux traits droits qu'on prend pour un artefact.
     Mesure a l'ecran le 16/09/2026 : illisible comme guillemet. Georgia lui redonne la
     forme courbe qu'on reconnait.
   · **`/ ""` vide le texte de remplacement.** Sans lui, une synthese vocale annonce
     « guillemet-virgule double culbute » au milieu de la phrase. La balise `blockquote`
     dit deja que c'est une citation ; le signe n'est qu'un ornement.
   · **`top` en `em` et non en px.** La citation est en `clamp()` : une valeur fixe
     decalerait le signe des que la fenetre change de largeur.

   L'opacite de .62 est celle de « vitrine », et elle tient ici aussi — mais sur la
   couleur RENFORCEE, pas sur la primaire. Mesure au pixel sur la surface tiede du 16/09 :
   #ab2546 a .62 donne **3,05:1**, la primaire #E05C70 n'y arrive qu'a 2,06:1 et ne
   passerait meme pas a pleine opacite au-dela de 3,24:1. */
.contributor-tpl-classique .cs-identity .cs-quote::before {
    content: "\201C" / "";
    position: absolute;
    left: 0;
    top: -.28em;
    font-family: Georgia, "Times New Roman", "Noto Serif", serif;
    font-size: 52px;
    line-height: 1;
    color: var(--cs-accent-strong);
    opacity: .62;
    pointer-events: none;
}

/* Le guillemet fermant suit le dernier mot, comme sur « vitrine ». */
.contributor-tpl-classique .cs-identity .cs-quote p::after {
    content: "\00A0\201D" / "";
    font-family: Georgia, "Times New Roman", "Noto Serif", serif;
    font-size: 30px;
    line-height: 0;
    vertical-align: -.3em;
    color: var(--cs-accent-strong);
    opacity: .62;
}

/* P4 · LES TITRES DE SECTION SORTENT DU REGISTRE ADMINISTRATIF.

   Decision de Sebastien du 16/09/2026. Les capitales de 15 px a `.08em` d'interlettrage
   sont lisibles mais froides, et elles rendaient mal le compte demande au lot 3 : « SES
   12 COURS » se lit moins vite que « Ses 12 cours ».

   Les QUATRE selecteurs sont repris ensemble, parce qu'ils partagent une seule
   declaration plus haut dans ce fichier. En oublier un laisserait « Presentation video »
   ou « Ses specialites » seuls en capitales au milieu de titres en casse normale. */
.contributor-tpl-classique .cs-section-title,
.contributor-tpl-classique .cs-bio h2,
.contributor-tpl-classique .cs-embed-title,
.contributor-facts.contributor-tpl-classique h2 {
    font-size: 22px;
    letter-spacing: normal;
    text-transform: none;
    margin: 0 0 18px;
}

/* Le filet d'accent. `::after` en bloc plutot qu'une bordure basse : une bordure ferait
   toute la largeur du titre, alors qu'on veut une marque courte et fixe. */
.contributor-tpl-classique .cs-section-title::after,
.contributor-tpl-classique .cs-bio h2::after,
.contributor-facts.contributor-tpl-classique h2::after {
    content: "";
    display: block;
    width: 32px;
    height: 3px;
    border-radius: 999px;
    background: var(--cs-accent);
    margin-top: 10px;
}

/* Le titre d'une integration est un `h3` : il vit DANS une section qui a deja son filet.
   Un second filet a l'interieur ferait croire a un second niveau de decoupage. */
.contributor-tpl-classique .cs-embed-title { font-size: 18px; }

/* --- Classique : la biographie DANS le bandeau. ---------------------------- */

/* Elle occupe la colonne de droite de l'en-tete, sous l'identite (demande de Sebastien du
   16/09/2026). Le deplacement est fait par la vue — `.cs-bio` est une petite-fille de
   `.cs-lead` sur ce gabarit, une soeur sur les cinq autres — et ce qui suit ne fait que
   recoller les marges que ce changement de voisinage rend fausses.

   La gouttiere de la fiche (`--cs-gap`, 40 px sur ce gabarit) separait la biographie de
   l'en-tete quand elle etait une section a part. A l'interieur du meme bloc, elle creuse
   un trou : c'est le rythme de l'en-tete qui s'applique. */
.contributor-tpl-classique .cs-identity .cs-bio {
    margin-top: 26px;
}

/* LA MESURE PASSE DE 68 A 78 SIGNES ICI, ET PAS A « SANS BORNE ».

   Mesure du 16/09/2026 sur une fenetre de 1600 px : la colonne de droite du bandeau fait
   1092 px. Sans borne, la ligne y atteint **160 signes** — plus du double de ce que l'oeil
   suit sans perdre le debut de la suivante. A 68 signes, le texte s'arretait a 578 px et
   laissait un vide de 500 px dans un bandeau qu'on vient justement de remplir. A 78, il
   occupe 749 px et l'extrait sort en sept lignes, ce qui equilibre le portrait de 300 px
   pose en face.

   La borne est le SEUL reglage a toucher si la composition doit evoluer : `none` rend la
   pleine largeur, 68 rend la mesure commune aux autres gabarits. */
.contributor-tpl-classique .cs-identity .cs-bio-body {
    max-width: 78ch;
}

/* Le titre reste, avec son filet d'accent : c'est le seul reperage qui dit ou l'identite
   s'arrete et ou la biographie commence, une fois les deux dans la meme colonne. Il passe
   simplement d'un cran en dessous — un titre de section pleine largeur et un titre de
   sous-bloc ne se crient pas de la meme voix. */
.contributor-tpl-classique .cs-identity .cs-bio h2 {
    font-size: 17px;
    margin-bottom: 14px;
}

.contributor-tpl-classique .cs-identity .cs-bio h2::after {
    width: 24px;
    margin-top: 8px;
}

/* --- Classique : la biographie abregee et sa fenetre. ---------------------- */

/* L'EXTRAIT N'A AUCUNE REGLE A LUI, et c'est voulu. Il porte `.cs-bio-body` en plus de
   `.cs-bio-extrait` : largeur de colonne, taille et interligne lui viennent donc des memes
   declarations que la biographie complete. Redeclarer ici `max-width: 68ch` — la valeur
   posee pour « classique » ligne 220 — aurait mis le meme nombre a deux endroits, et le
   jour ou l'un bouge, l'extrait et la fenetre cessent de se ressembler.

   `.cs-bio-extrait` ne sert donc qu'au script et au repli `<noscript>`, qui ont besoin de
   savoir le designer. Mesure du 16/09/2026 sur une fenetre de 1024 px : colonne de 685 px,
   8 lignes, **81 signes par ligne en moyenne** (la borne `ch` compte la largeur du
   chiffre, plus large qu'une minuscule de Nunito). C'est au-dessus des 65 a 75 vises par
   la decision du 13/09/2026, mais tres en dessous des 109 signes qu'elle corrigeait ; la
   valeur vaut pour « classique », « vitrine » et « profil » a la fois et ne se change pas
   depuis ce lot. Signale au rapport. */

/* P5 · LE BOUTON EST PLEIN, PAS FANTOME.

   `.cs-cta-btn` est un bouton contour ; celui-ci ouvre le contenu principal de la fiche
   et merite d'etre vu.

   LE COUPLE DE COULEURS N'EST PAS CHOISI ICI, il est repris tel quel du bandeau de
   « vitrine » (ligne 458) : fond `--cs-accent-strong`, texte `--band-text-color`. Ce
   second token est calcule en PHP par `Contraste::texteLisible()` a partir du fond du
   client — c'est la SEULE facon d'ecrire sur la couleur d'un tenant sans supposer
   qu'elle est sombre ou claire. Ne pas y substituer `--cs-accent` : la couleur primaire
   nue est plus claire, et le texte calcule pour la primaire RENFORCEE n'y est plus
   garanti.

   `min-height` et `padding` portent la cible tactile a 44 px, le minimum qui se vise au
   pouce sans viser a cote. */
.contributor-tpl-classique .cs-bio-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    margin-top: 20px;
    padding: 11px 24px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-family: var(--cs-font-title);
    font-size: 15px;
    font-weight: 700;
    line-height: 1.2;
    cursor: pointer;
    color: var(--band-text-color, #fff);
    background: var(--cs-accent-strong);
    /* P6 · 200 ms, et une courbe qui part vite et s'arrete en douceur. */
    transition: box-shadow .2s cubic-bezier(.2, .8, .2, 1),
                transform .2s cubic-bezier(.2, .8, .2, 1);
}

/* LE SURVOL NE TOUCHE PAS AUX COULEURS, ET C'EST DELIBERE. Eclaircir ou assombrir le
   fond deplacerait le contraste avec un texte qui, lui, a ete calcule pour le fond de
   repos : le retour visuel se paierait en lisibilite, sur un bouton et dans un sens
   qu'on ne peut pas mesurer d'avance pour tous les tenants. Une ombre portee dans la
   teinte du bouton dit la meme chose sans rien changer au couple de couleurs. */
/* ⚠ SANS CETTE LIGNE, `bouton.hidden = true` NE FAIT RIEN. La feuille de l'agent
   utilisateur ecrit `[hidden] { display: none }` avec un poids de (0,1,0) ; la regle
   ci-dessus pese (0,2,0) et gagne. Le script qui replie la fiche sur un navigateur sans
   `<dialog>` masquait donc l'extrait mais laissait le bouton, inerte, sous la biographie
   complete. Constate a la mesure le 16/09/2026.

   La regle vaut pour tout usage futur de `hidden` sur ce bouton, pas seulement pour le
   repli : des qu'on pose `display` sur un element, on doit lui rendre son `hidden`. */
.contributor-tpl-classique .cs-bio-more[hidden] { display: none; }

.contributor-tpl-classique .cs-bio-more:hover {
    box-shadow: 0 6px 18px color-mix(in srgb, var(--cs-accent-strong) 38%, transparent);
}

/* L'anneau de focus n'est jamais retire : il est rendu VISIBLE sur les deux fonds
   possibles, par un decalage qui le detache du bouton plein. */
.contributor-tpl-classique .cs-bio-more:focus-visible {
    outline: 2px solid var(--cs-accent-strong);
    outline-offset: 2px;
}

/* Retour d'appui. Sans lui, un doigt ne sait pas si le bouton a pris le clic. */
.contributor-tpl-classique .cs-bio-more:active { transform: scale(.98); }

/* --- La fenetre. ----------------------------------------------------------- */

/* `<dialog>` natif : le fond inerte, le piege de focus, la fermeture par Echap et la
   couche `::backdrop` viennent du navigateur. Ce qui suit n'est que l'habillage.

   `color: inherit` est indispensable : un `<dialog>` est sorti du flux et repeint par
   l'agent utilisateur avec SES couleurs par defaut (noir sur blanc). Sans cette ligne,
   tout le fichier — qui derive ses gris de `currentColor` — mesurerait ses contrastes
   sur une couleur heritee qui n'est plus celle de la page.

   LE FOND EST `--couleur-fond-content`, ET SUREMENT PAS `--detail-bg`. Les deux sont des
   fonds, mais un seul va avec le texte qu'on pose dessus. `details.blade.php` refuse
   deliberement la classe `page-themed` pour cette raison exacte : sur studio.mentorplay,
   `--detail-bg` vaut #0d0620 (sombre) alors que `--primary-text-color` vaut #1d2025
   (sombre aussi). Mesure du 13/09/2026 : le nom du contributeur y passait de 15,65:1 a
   **1,21:1**. La fiche vit donc sur le fond de CONTENU, avec le texte fait pour lui —
   c'est ce couple-la, et pas un autre, que la fenetre doit reprendre. */
.contributor-sheet .cs-bio-dialog {
    width: min(720px, calc(100vw - 32px));
    max-height: min(80vh, 760px);
    padding: 0;
    border: 1px solid var(--cs-line);
    border-radius: var(--cs-radius);
    background: var(--couleur-fond-content, #fff);
    color: inherit;
    overflow: hidden;
}

/* VOILE NOIR EN DUR, ET C'EST LE MEME RAISONNEMENT QUE LE BANDEAU DE « MAGAZINE »
   (ligne 391) : le voile n'est pas pose sur une surface du theme, il est pose sur la PAGE
   — n'importe quel contenu, n'importe quelle image, n'importe quelle couleur de tenant.
   Un voile bati sur un token tomberait clair chez un tenant clair, et ne separerait alors
   plus rien : la fenetre flotterait sur une page qui reste lisible derriere elle.

   `::backdrop` ne porte aucun texte : la regle de contraste ne s'y applique pas, seule
   compte la separation visuelle. */
.contributor-sheet .cs-bio-dialog::backdrop {
    background: rgba(0, 0, 0, .55);
}

.contributor-sheet .cs-bio-dialog-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 20px 24px;
    border-bottom: 1px solid var(--cs-line);
}

/* Le nom de la personne titre la fenetre. Il ne reprend NI les capitales, NI le filet
   d'accent des titres de section : ce n'est pas une section de la page, c'est le nom
   d'une fenetre. */
.contributor-sheet .cs-bio-dialog-head h2 {
    font-family: var(--cs-font-title);
    font-size: 20px;
    font-weight: 700;
    letter-spacing: normal;
    text-transform: none;
    color: var(--cs-title);
    margin: 0;
}

.contributor-sheet .cs-bio-dialog-head h2::after { content: none; }

.contributor-sheet .cs-bio-dialog-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    cursor: pointer;
    color: inherit;
    background: transparent;
    transition: background-color .2s cubic-bezier(.2, .8, .2, 1);
}

.contributor-sheet .cs-bio-dialog-close:hover { background: var(--cs-surface); }

.contributor-sheet .cs-bio-dialog-close:focus-visible {
    outline: 2px solid var(--cs-accent);
    outline-offset: -2px;
}

/* Le corps defile SEUL : l'en-tete et sa croix restent a l'ecran quelle que soit la
   longueur de la biographie. Une croix qu'il faut aller rechercher en remontant est une
   croix qu'on ne trouve pas. */
.contributor-sheet .cs-bio-dialog-body {
    padding: 24px;
    max-width: none;
    overflow-y: auto;
    max-height: calc(min(80vh, 760px) - 85px);
    overscroll-behavior: contain;
}

/* LE REPLI DES NAVIGATEURS SANS `<dialog>` (Safari < 15.4). Le script pose cette classe
   et decouvre la fenetre dans le flux, exactement comme le fait `<noscript>` : une
   biographie en pleine page vaut mieux qu'un bouton qui ne repond pas. */
.contributor-sheet .cs-bio-dialog-inerte {
    display: block;
    position: static;
    width: auto;
    max-width: none;
    max-height: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    margin: 0;
    background: transparent;
    overflow: visible;
}

.contributor-sheet .cs-bio-dialog-inerte .cs-bio-dialog-head { display: none; }

.contributor-sheet .cs-bio-dialog-inerte .cs-bio-dialog-body {
    padding: 0;
    max-height: none;
    overflow: visible;
}

@media (prefers-reduced-motion: reduce) {
    .contributor-facts .cf-links a,
    .contributor-sheet .cs-cta-btn,
    .contributor-tpl-classique .cs-bio-more,
    .contributor-sheet .cs-bio-dialog-close { transition: none; }

    /* Le retour d'appui reste, mais sans deplacement : la couleur suffit a dire que le
       clic est pris, et c'est le mouvement que la preference systeme demande d'eviter. */
    .contributor-tpl-classique .cs-bio-more:active { transform: none; }
}
