/* @grammaire v2
   ══════════════════════════════════════════════════════════════
   Portraits — le mur (`/portraits`) et la fiche (`/portraits/{slug}`)

   Maquette « Portraits ANCESU » (projet Claude Design), rapatriée le
   2026-09-02 : elle existait depuis le début et n'avait jamais été ouverte.
   Les deux pages rendaient donc une grammaire de listing générique là où la
   maquette dessine deux écrans à part.

   CE QUE LA MAQUETTE CHANGE, et pourquoi ce n'est pas cosmétique :

   · LE PORTRAIT DEVIENT LE SUJET. Un avatar rond de 96 px dans une grille
     d'annuaire dit « entrée de répertoire ». Un cadre 3/4 plein, sous un voile
     qui porte le nom, dit « personne ». C'est la même donnée et ce n'est pas
     la même page.
   · LE MUR EST GROUPÉ PAR LETTRE, avec la bande alphabétique en ancres — la
     brique du glossaire (`components/alpha-band.css`), qui n'était employée
     qu'une fois.
   · LA FICHE PASSE SUR UN RAIL À GAUCHE : portrait, rattachement, comptes. Le
     texte respire à droite, et les interventions se lisent en FRISE par année
     plutôt qu'en liste plate.

   Ce qui reste emprunté à la grammaire commune, et n'a donc rien ici :
   l'en-tête (`_content_header`, surface `bare`), la barre d'outils
   (`_list_toolbar`), les en-têtes de groupe (`_group_header`), l'aplat des
   grandeurs (`components/figures-card.css`), le rebond
   (`article-single__related`).
   ══════════════════════════════════════════════════════════════ */

/* LA CARTE DU MUR ET SA GRILLE ONT ÉTÉ RETIRÉES le 2026-09-02, le jour même.

   Le mur de portraits 3/4 plein cadre, groupé par lettre, venait de la maquette
   « Portraits ANCESU » ; rendu, il était hors de la grammaire du site et il a
   été refusé. `/portraits` reprend le châssis de `/dossiers` — rail de filtres,
   `media-cards`, pagination — et la carte de personne délègue à `_media_card`
   avec l'avatar rond du composant 32.

   La leçon, puisqu'elle a coûté un aller-retour complet : une maquette dit une
   INTENTION, la charte dit ce que le site sait rendre. Quand les deux
   divergent, c'est la charte qui tranche, et une page qui ne ressemble à
   aucune autre du site est un défaut même quand elle est fidèle au dessin.

   Reste ici ce qui est PROPRE à la fiche, où le portrait est le sujet et non
   une vignette de liste. */

/* ══════════════════════════════════════════════════════════════
   LA GRILLE DE L'ANNUAIRE — quatre portraits par rangée
   ══════════════════════════════════════════════════════════════

   La grille du site (`media-cards`) pose une piste de 17 rem, sa variante
   `--dense` une de 14. Mesure du 2026-09-02 dans la colonne de droite de
   `/portraits`, qui fait 888 px à pleine largeur de conteneur :

     17 rem (272 px)   ->  3 pistes de 285 px   « ça fait très grand »
     14 rem (224 px)   ->  3 pistes encore : quatre en demanderaient
                           4 x 224 + 3 x 16 = 944 px, soit 56 de trop
     10.5 rem (168 px) ->  4 pistes de 210 px, et jamais cinq
                           (5 x 168 + 4 x 16 = 904 px, pour 888 offerts)

   D'où cette troisième piste, et elle est PROPRE aux portraits : un visage se
   reconnaît à 200 px, là où une carte à titre, chapô et étiquettes a besoin de
   ses 272. Ce n'est pas la même densité parce que ce n'est pas le même contenu.

   10,5 rem PLUTÔT QUE 12,5, et c'est le téléphone qui tranche : les deux
   rendent quatre pistes dans la colonne, mais à 390 px de fenêtre la piste de
   12,5 rem ne tient qu'UNE carte de 366 px — un visage pleine largeur, et 162
   rangées à faire défiler. À 10,5 elle en tient deux. C'est le défaut que
   l'ancienne grille du trombinoscope documentait déjà, retrouvé ici par la
   même arithmétique.

   `min(100%, …)` comme les deux autres : sans lui la piste réclame 168 px même
   quand la colonne n'en offre que 150, et pousse le conteneur sans qu'aucun
   ascenseur ne le signale — le parent la borne. */
.media-cards--portraits {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 10.5rem), 1fr));
}

/* LA SILHOUETTE DES CARTES SANS PORTRAIT, À L'ÉCHELLE DE LA CARTE.

   La brique partagée pose son pictogramme de repli à 24 px : c'est la mesure
   d'une VIGNETTE de rangée, où il tient lieu de marque de type au coin d'une
   image de 104 px. Au centre d'un carré de 210 px il devient un point perdu,
   et la carte se lit comme un cadre vide plutôt que comme un portrait
   manquant.

   Le pictogramme est redimensionné ICI et non dans le paramètre `icon` du
   gabarit : celui-ci fixe la taille dans l'attribut du SVG, donc une seule
   valeur pour tous les appelants de la carte. La CSS, elle, ne vaut que sous
   cette grille.

   16 % de l'accent plutôt que les 30 % de la brique : à 24 px un trait pâle se
   perd, à 88 px le même trait devient un dessin qui réclame l'attention d'un
   contenu — or il dit précisément qu'il n'y a pas de contenu. Plus grand ET
   plus discret, c'est le même énoncé rendu à la bonne échelle. */
.media-cards--portraits .media-card__icon--on-hatch {
    color: color-mix(in srgb, var(--media-card-accent) 16%, transparent);
}

.media-cards--portraits .media-card__icon--on-hatch svg {
    width: 5.5rem;
    height: 5.5rem;
}

/* ══════════════════════════════════════════════════════════════
   LA FICHE — rail à gauche, texte à droite
   ══════════════════════════════════════════════════════════════ */

.portrait-fiche {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--spacing-lg);
    padding-block: var(--spacing-lg) var(--spacing-3xl);
}

/* `flex: 1 1 300px` contre `flex: 999 1 480px` : les deux colonnes tiennent
   côte à côte tant que 300 + 480 + l'écart entrent dans la largeur, et passent
   l'une sous l'autre sinon. Aucun point de rupture nommé — la bascule suit la
   place réellement disponible, pas une largeur d'écran devinée. */
.portrait-fiche__rail {
    flex: 1 1 18.75rem;
    min-width: 15rem;
    max-width: 22.5rem;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    position: sticky;
    /* Sous la barre collante, plus l'air de la maquette. */
    top: calc(var(--header-height) + var(--spacing-lg));
}

.portrait-fiche__main {
    flex: 999 1 30rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

/* Le rail ne colle plus dès qu'il passe AU-DESSUS du texte : collant, il
   resterait à l'écran pendant toute la lecture, en occupant la moitié d'un
   téléphone. */
@media (width < 60em) {
    .portrait-fiche__rail {
        position: static;
        max-width: none;
    }
}

.portrait-figure {
    position: relative;
    margin: 0;
    overflow: hidden;
    aspect-ratio: 3 / 4;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--surface-4);
    box-shadow: var(--shadow-card);
}

/* Le liseré de la maquette, en pied de portrait. C'est la SEULE bande de
   couleur de la fiche : elle signe le cadre sans rien encadrer. */
.portrait-figure::after {
    content: '';
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 0.375rem;
    background: var(--color-section-ancesu);
}

.portrait-figure__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 20%;
}

.portrait-figure__hatch {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
}

.portrait-figure__initials {
    font-family: var(--font-title);
    font-size: var(--font-size-4xl);
    font-weight: 700;
    color: var(--color-primary);
}

.portrait-figure__credit {
    position: absolute;
    inset-inline: 0;
    bottom: 0.375rem;
    padding: var(--spacing-xs) var(--spacing-sm);
    background: linear-gradient(
        180deg,
        transparent,
        color-mix(in srgb, var(--color-primary-dark) 72%, transparent)
    );
    font-size: var(--font-size-2xs);
    color: var(--color-on-navy-soft);
    text-align: end;
}

.portrait-facts {
    padding: var(--spacing-md);
}

.portrait-social {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.portrait-social__title {
    margin: 0;
    font-size: var(--font-size-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-light);
}

/* ══════════════════════════════════════════════════════════════
   LES SECTIONS DE LA FICHE
   ══════════════════════════════════════════════════════════════ */

.bio-section {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    margin-top: var(--spacing-lg);
}

.bio-section:first-child {
    margin-top: 0;
}

.bio-section[id] {
    scroll-margin-top: var(--spacing-4xl);
}

/* La biographie vit dans une carte, comme le « Parcours » de la maquette : le
   texte y est la seule chose posée sur du blanc, et sa colonne est bornée —
   66 caractères, la mesure de la maquette. Sans borne, une biographie longue
   court sur toute la largeur et l'œil perd sa ligne de retour. */
.bio-section--prose {
    padding: var(--spacing-lg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--surface-2);
}

.bio-section--prose .prose-content {
    max-width: 66ch;
}

/* ══════════════════════════════════════════════════════════════
   LA FRISE DES INTERVENTIONS
   ══════════════════════════════════════════════════════════════ */

.portrait-timeline {
    display: flex;
    flex-direction: column;
}

.portrait-timeline__row {
    display: flex;
    align-items: stretch;
    gap: var(--spacing-lg);
}

.portrait-timeline__year {
    flex: 0 0 auto;
    width: 4rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-sm);
    padding-top: var(--spacing-md);
}

.portrait-timeline__an {
    font-family: var(--font-title);
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--color-primary);
    font-variant-numeric: tabular-nums;
}

.portrait-timeline__line {
    flex: 1;
    width: 2px;
    border-radius: var(--radius-pill);
    background: var(--color-border);
}

.portrait-timeline__items {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    padding-block: var(--spacing-ms) var(--spacing-md);
}

.portrait-talk {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--spacing-md);
    padding: var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--surface-2);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--motion-1) var(--easing-standard),
                box-shadow var(--motion-1) var(--easing-standard);
}

.portrait-talk:hover,
.portrait-talk:focus-visible {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-md);
    text-decoration: none;
    outline: none;
}

.portrait-talk__body {
    flex: 1 1 15rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.portrait-talk__title {
    font-family: var(--font-title);
    font-size: var(--font-size-base);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.portrait-talk__event {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

/* La date en chasse fixe : c'est une VALEUR, pas de la prose. Même distinction
   que la colonne droite de `_facts_list`. */
.portrait-talk__date {
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.portrait-talk__pieces {
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-xs);
}

/* Les pastilles disent ce qu'on TROUVERA derrière le titre. Elles ne sont pas
   cliquables : en pilule sur fond gris elles ressemblaient à des boutons, une
   fausse promesse d'action pire qu'une absence d'affordance. */
.portrait-piece {
    display: flex;
    align-items: center;
    height: 1.5rem;
    padding-inline: var(--spacing-sm);
    border-radius: var(--radius-pill);
    background: var(--color-neutral-soft);
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text);
}

.portrait-piece--replay {
    background: color-mix(in srgb, var(--color-accent) 22%, transparent);
    color: var(--color-primary-dark);
}

/* ══════════════════════════════════════════════════════════════
   LES REDIFFUSIONS

   Section absente de la maquette, et la donnée existe : un replay peut exister
   sans intervention rattachée, et rien ne permet de les rapprocher. Elle garde
   donc sa forme de rangées, sous la frise.
   ══════════════════════════════════════════════════════════════ */

.bio-replays {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.bio-replay {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--surface-2);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--motion-1) var(--easing-standard),
                box-shadow var(--motion-1) var(--easing-standard);
}

.bio-replay:hover,
.bio-replay:focus-visible {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-md);
    outline: none;
}

.bio-replay__icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--color-primary) 10%, transparent);
    color: var(--color-primary);
}

.bio-replay__body {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
    min-width: 0;
    flex: 1 1 auto;
}

.bio-replay__title {
    font-weight: 600;
    color: var(--color-primary-dark);
}

.bio-replay__meta {
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.bio-replay__arrow {
    flex: 0 0 auto;
    color: var(--color-text-light);
}

/* ── Téléphone ────────────────────────────────────────────────────
   Syntaxe de PLAGE, complément exact du palier tablette (48em). */
@media (width < 48em) {
    .portrait-timeline__row {
        gap: var(--spacing-md);
    }

    .portrait-timeline__year {
        width: 2.75rem;
    }

    .portrait-timeline__an {
        font-size: var(--font-size-base);
    }

    .bio-section--prose {
        padding: var(--spacing-md);
    }
}
