/* =========================================================
   UI CHARTE — la couche d'identité, chargée EN DERNIER.

   Raison d'être : certaines valeurs d'une charte ne peuvent
   passer ni par un token, ni par une variable Bootstrap.

   · Bootstrap compile la graisse de ses titres en dur
     (h1…h6 { font-weight: 500 }) et n'expose aucune variable
     pour elle — contrairement à leur couleur.
   · Les composants du socle puisent dans --fw-* selon leur
     rôle. Cette identité veut des graisses différentes pour
     des composants qui partagent aujourd'hui le même token :
     le titre de hero et son accent lisent tous deux
     --fw-light, alors qu'elle les veut à 800 et 500.
     Changer la valeur du token ferait mentir son nom.

   RÈGLE : chaque déclaration ici doit dire pourquoi elle
   n'est ni un token ni une variable. Sans cette justification,
   elle a sa place ailleurs — et ce fichier doit rester court.

   Chargé après ui-organismes.css : c'est la seule position
   d'où une couche d'habillage peut corriger un composant.
   ========================================================= */

/* ---- Titres ----
   La charte est franchement grasse là où Bootstrap est medium.
   letter-spacing négatif : à 800 et à ces corps, l'approche par
   défaut aère trop les titres longs. */
h1, h2, h3, h4, h5, h6,
.ui-section-title {
  font-weight: 700;
}

/* 36px, contre les 32 de l'échelle Bootstrap. Posé sur le RÔLE — un titre de
   section — et non sur le token --fs-h2, qui gouverne tous les h2 du site :
   déplacer le token aurait grossi des titres qui n'ont rien demandé.
   Le sélecteur reprend la qualification par l'élément du socle, pour rester
   à la même spécificité et l'emporter par le seul ordre de chargement. */
h2.ui-section-title {
  font-size: var(--fs-h2);
}

/* ---- Chasse des titres ----
   Elle se resserre à mesure que le titre grandit — c'est très net dans la
   source, et c'est ce qui donne aux grands titres leur aspect compact.
   Une valeur unique aurait soit relâché les hero, soit écrasé les titres
   de carte. On l'échelonne donc, comme la source :

       hero            -0.055em   interlignage 0.98
       titre de section -0.045em             1.05
       titre de carte   -0.03em              (celui de Bootstrap)

   L'interlignage général reste --lh-heading (1.2) : à 1.05, un titre de
   carte sur deux lignes se toucherait. */
.ui-display-title {
  letter-spacing: -0.055em;
  line-height: 0.98;
}

.ui-section-title {
  letter-spacing: -0.045em;
  line-height: 1.05;
}

.ui-card-title {
  letter-spacing: -0.03em;
  font-family: var(--font-titre);
}

/* ---- Titre de hero ----
   Le mélange typographique vient du socle (phrase en --font-base,
   accent en --font-display) ; seules les graisses sont d'ici.
   Valeurs relevées sur la source : 800 pour la phrase, 500 pour
   l'accent serif — un serif à 800 s'empâterait. */
.ui-display-title { font-weight: 700; }

/* ---- L'accent du hero, seul endroit en serif ----
   Le socle prévoyait le mélange en opposant --font-display à --font-base,
   en supposant que la police d'accent est celle des titres. Ici elle ne
   l'est pas : la charte écrit TOUT en sans arrondi et ne réserve le serif
   qu'à ce fragment. Donner le serif à --font-display aurait fait basculer
   tous les h1…h6 du site — les tokens gardent donc leur rôle, et le serif
   se pose ici, au seul endroit qui le demande. */
.ui-display-title .ui-accent {
  font-family: Georgia, "Iowan Old Style", "Times New Roman", serif;
  /* Italique : le modèle écrit cet accent en « em », dont l'italique est le
     rendu par défaut. Notre marquage est un « span » — neutre — il faut donc
     poser explicitement ce que l'élément du modèle apportait sans le dire. */
  font-style: italic;
  font-weight: 500;
  color: var(--color-brand-pink);
}

/* Même poids que la règle structurelle du hero : le rose doit gagner par
   l'ordre de la couche charte, sans recourir à !important. */
.ui-hero .ui-display-title .ui-accent {
  color: var(--color-brand-pink);
}

/* ---- Boutons ----
   600, et non les 750 précédents. La source d'origine allait jusqu'à 850 ;
   Bootstrap n'a pas de variable de graisse pour .btn et le socle le laisse à
   --fw-normal (400), qui est la valeur de Bootstrap et non celle de la charte.

   750 mettait le libellé d'un bouton PLUS GRAS QUE LES TITRES de la page —
   .ui-display-title et .ui-section-title sont à 700. Une hiérarchie
   typographique où le mot « Créer mon profil » pèse plus lourd qu'un h1 se
   voit tout de suite, même sans savoir pourquoi : c'est ce que le bouton
   donnait à lire.
   600 le range avec .ui-nav-link, qui porte la même graisse : ce sont deux
   libellés d'interface, pas deux niveaux de titre. Le bouton garde sa présence
   par son aplat et son rayon, pas par l'épaisseur de ses lettres. */
.ui-btn,
.btn {
  font-weight: 600;
}

/* ---- Boutons ----
   La géométrie de la charte : plus arrondie et plus aérée que Bootstrap.
   Les hauteurs sont passées par les tokens --control-h* ; ce qui suit est
   ce qu'aucun token ne porte.

   Pourquoi pas les variables --bs-btn-* : elles existent (padding, radius,
   font-size) mais .ui-btn les court-circuite avec ses propres déclarations,
   le socle portant la hauteur en min-height pour aligner les boutons d'une
   même rangée quel que soit leur contenu. */
.ui-btn {
  gap: var(--space-3);                    /* 16px */
  padding-inline: var(--space-4);       /* 24px */
  border-radius: var(--radius-md); /* 18px */
}

.ui-btn.ui-btn-slim {
  /* Deux classes, à dessein : le socle écrit ses modificateurs de taille en
     « .ui-btn.ui-btn-slim ». Une règle à une seule classe perdrait, quel que
     soit l'ordre de chargement. Toute surcharge de taille doit s'aligner
     sur cette spécificité. */
  padding-inline: var(--space-3);        /* 16px */
  border-radius: var(--radius-md); /* un seul rayon de bouton (30 sept. 2026) */
  font-weight: 600;                /* le petit bouton suit le grand */
  box-shadow: none;                /* la source retire l'ombre à cette taille */
}

/* Les deux CTA d'acquisition reprennent exactement le rose du logo. Ils sont
   volontairement les seuls boutons roses : le pétrole reste la couleur des
   actions fonctionnelles.

   LIBELLÉ BLANC, sur décision explicite. À signaler pour qui reprendra ce
   fichier : sur l'ancien rose #ff214e, le blanc ne donnait que 3,76:1 et
   l'encre 4,06 — les deux sous les 4,5:1 du texte courant. Le rose de marque
   ne portait alors aucun libellé qui passe AA, et ces boutons devaient
   emprunter la variante assombrie #cf1a3f : ils sortaient donc dans un rose
   visiblement différent de celui des accents de titre.
   RÉGLÉ par le passage à #e20138, qui donne 4,89:1 en libellé blanc. Le CTA
   porte enfin exactement le rose de la marque, et la règle ci-dessous n'appelle
   plus qu'un jeton dont les deux noms valent la même couleur. */
.ui-header-actions .ui-btn-primary,
.ui-hero-load-actions .ui-btn-primary,
.ui-header-actions .ui-btn-primary:hover,
.ui-hero-load-actions .ui-btn-primary:hover {
  background: var(--color-brand-pink-ink);
  color: var(--white);
  box-shadow: var(--shadow-accent);
}

.ui-header-actions .ui-btn-primary:focus-visible,
.ui-hero-load-actions .ui-btn-primary:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--color-brand-pink-ink) 40%, transparent);
  outline-offset: 3px;
}

/* ---- Champs ----
   La source distingue le champ (49px) du bouton (56px) : ils ne partagent
   jamais une rangée, le bouton d'un formulaire s'y pose en pleine largeur
   sous les champs. --control-h vaut la hauteur du bouton ; les champs
   reprennent donc la leur ici. */
.ui-form-control,
.ui-form-select {
  min-height: 3.0625rem;           /* 49px */
  border-radius: var(--radius-sm); /* 13px */
}

/* ---- Cartes ----
   La charte leur donne une signature très reconnaissable, que le socle
   n'a pas : grand rayon, filet d'encre presque effacé, et surtout une
   ombre large et chaude — c'est elle qui fait « flotter » les cartes.

   Le filet n'est pas --border : la source emploie une transparence de
   l'encre (5 à 8 %), plus discrète qu'un filet plein, et qui se comporte
   mieux sur les fonds crème comme papier.

   La teinte de l'ombre n'est pas --shadow-color non plus. Les ombres des
   cartes de la source sont franchement brunes — rgb(69–92, 31–51, 22–39)
   selon les cas, soit très exactement --color-dark-soft. Une ombre grise
   sous une carte crème aurait l'air sale. */
.ui-carte,
.ui-article-card,
.ui-testimonial-card {
  border-radius: var(--radius);
  border-color: var(--border-soft);
  box-shadow: var(--shadow-md);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

/* Le rembourrage de Bootstrap (16px, $card-spacer) est trop serré pour cette
   charte, qui tient ses cartes de contenu entre 27 et 29px. On monte d'un cran
   sur l'échelle d'espacement plutôt que de poser 28px en dur : les fondations
   restent celles de Bootstrap, et --space-4 en est la valeur voisine. */
.ui-carte,
.ui-testimonial-card {
  padding: var(--space-4);
}

/* Le soulèvement au survol est plus franc que celui des boutons
   (-6px contre -2px) : une carte est une surface, pas une commande. */
.ui-carte:hover,
.ui-article-card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-photo);
}


/* ---- Rythme des sections ----
   La charte est très aérée : 110 à 130px de respiration verticale sur
   desktop, 80 à 90 sur mobile. --space-7 porte le cas desktop (120px).
   Le repli mobile du socle retombe sur --space-6, qui vaut 64px et sert
   aussi au hero — on ne le touche pas, on pose ici la valeur de la charte. */
@media (width <= 1100px) {
  .ui-section {
    padding-block: var(--space-6);         /* 64px */
  }
}

/* Entrée resserrée : la moitié du rembourrage haut, aux deux paliers du
   rythme — 60px au lieu de 120, 44 au lieu de 88. Posé ici, à côté des deux
   valeurs qu'il divise : les séparer, c'est prendre le risque qu'un palier
   bouge un jour sans l'autre. Le bas n'est pas touché — c'est l'entrée de la
   section qu'on resserre, pas la respiration qui la suit. */
.ui-content-section--haut-serre {
  padding-top: var(--space-6);
}

@media (width <= 1100px) {
  .ui-content-section--haut-serre {
    padding-top: var(--space-5);          /* 44px — la moitié des 5.5rem ci-dessus */
  }
}

/* ---- Fonds de section ----
   La charte alterne trois plans, et rien d'autre :

       crème   --white    le fond courant
       pêche   --surface-douce   les sections en retrait
       encre   --color-dark      les sections d'accent

   Le socle posait la FAQ sur --surface-appuyee, un pêche plus soutenu qui
   n'existe pas dans la charte, et la section de contenu sur du blanc pur
   au lieu du papier des cartes. Deux réaffectations de token, pas de
   nouvelle valeur. */
/* Le rose de --surface-douce a quitté les sections : sur toute une bande il
   pesait, et il est désormais réservé au pied du dégradé du hero d'accueil,
   où il n'occupe qu'une frange. Les sections reprennent le papier. */
/* Pas de fond : la FAQ prend le blanc de la page. Une section ne déclare
   une couleur que lorsqu'elle en a besoin. */

.ui-content-section {
  background: var(--surface-card);
}

/* ---- Hero ----
   La structure (deux colonnes centrées, sans image de fond) est portée par
   le composant : c'est un changement de nature, pas un habillage.
   Ne restent ici que les mesures propres à la charte. */
.ui-hero-lead {
  /* 30px sous le titre. Le socle laisse le chapô coller au titre, ce qui allait
     tant qu'un sur-titre ouvrait le bloc ; sans lui, le titre et le chapô se
     touchent et le hero perd sa respiration. */
  margin-top: var(--space-4);
  /* 20px de plus sous le chapô, donc au-dessus des actions. Posé ICI et non
     sur les actions : entre deux frères en flux, les marges verticales
     fusionnent et c'est la plus grande qui l'emporte — une marge haute de
     20px sur les actions aurait été absorbée par les 32px du chapô, sans
     aucun effet visible. */
  margin-bottom: var(--space-5);
  max-width: 540px;
  line-height: 1.7;                /* la source aère ses chapôs, là où le
                                      corps courant reste à --lh-base (1.5) */
  color: var(--text-muted);
}

.ui-hero-load-actions {
  gap: var(--space-4);                  /* 24px */
}

/* ---- Pied de page ----
   La charte le tient serré : 72px de respiration en haut, 28 en bas — bien
   moins qu'une section (120), parce qu'il clôt la page au lieu de la scander.
   Le bloc d'appel en tête n'existe pas dans la charte ; il est désormais
   conditionné à sa donnée, et sans lui c'est ce rembourrage qui s'applique. */
.ui-footer {
  padding-block: var(--space-6) var(--space-4);   /* 64px / 24px */
}

@media (width <= 1100px) {
  .ui-footer {
    padding-block: var(--space-6) var(--space-4);  /* 64px / 24px */
  }
}

/* La baseline de marque est en italique serif — le seul autre endroit, avec
   l'accent du hero, où la charte emploie le serif. C'est ce qui lui donne son
   air de signature manuscrite au bas de la page. */
.ui-footer-brand > p {
  font: italic var(--fs-base)/1.5 Georgia, "Iowan Old Style", "Times New Roman", serif;
}

/* Les liens repassent à 14px (--fs-sm). Ils étaient à 12 par fidélité à la
   charte source, qui descendait même à 11 : c'est trop peu pour une colonne
   qu'on parcourt à la souris. Les TITRES de colonne, eux, restent à 12 et
   deviennent des sur-titres — capitales, interlettrage, filet rose. Un titre
   plus petit que ses liens ne pose pas de problème de hiérarchie dès lors
   qu'il change de registre : c'est la casse et l'ornement qui le classent,
   pas la taille. */
.ui-footer-grid a {
  font-size: var(--fs-sm);
}

/* Le pied de page suit la bande sombre : rose de marque, même réserve mesurée
   (2,46:1 sur --section-pied #043c48). Voir la note de .ui-showcase--dark. */
.ui-footer-cta .ui-section-title .ui-accent,
.ui-footer-signature .material-symbols-outlined {
  color: var(--color-brand-pink);
}

/* ---- Pied de page : mise en mouvement ----
   Le pied était un tableau : trois colonnes de liens alignées sous un logo,
   sans autre relief que ses filets. Sur l'encre pleine #043c48 il devenait
   franchement inerte. Quatre gestes le remettent en mouvement, tous repris
   du vocabulaire déjà en place ailleurs sur le site plutôt qu'inventés ici.

   1. DEUX HALOS en fond, l'un rose en haut à droite, l'autre menthe en bas à
      gauche, posés en diagonale — la même dissymétrie que les galets des
      sections claires, transposée en lumière parce qu'un aplat organique ne
      se lit pas sur un fond aussi dense. Ils sont très bas en opacité : leur
      rôle est de faire respirer la surface, pas de se remarquer.
   2. Des SUR-TITRES de colonne barrés d'un filet rose, qui donnent à la
      grille un rythme vertical qu'elle n'avait pas.
   3. Un survol qui AVANCE : une pastille rose se déplie à gauche du lien et
      le pousse de quatre pixels. La translation seule (l'état d'origine)
      bougeait sans rien montrer.
   4. Des pastilles sociales qui se remplissent et se soulèvent.

   Le rose n'est jamais du TEXTE ici : sur #043c48 il donne 3,19:1, sous les
   4,5 exigés d'un petit texte mais au-dessus des 3 d'un élément graphique.
   Filet, pastille et cœur sont des aplats ; les libellés restent blancs. */
.ui-footer::before,
.ui-footer::after {
  content: "";
  position: absolute;
  z-index: 0;
  /* Des ELLIPSES larges et basses, pas des disques. Le pied fait moins de
     400px de haut : un disque assez large pour animer la bande déborde de
     tous les côtés et cesse d'être un halo pour devenir un dégradé sur toute
     la surface — l'encre demandée n'existe alors plus nulle part. Aplaties et
     ancrées dans deux coins opposés, elles laissent le centre à #043c48. */
  width: min(46%, 560px);
  height: 300px;
  border-radius: 50%;
  pointer-events: none;
}

.ui-footer::before {
  inset-block-start: -150px;
  inset-inline-end: -6%;
  background: radial-gradient(closest-side,
              color-mix(in srgb, var(--color-brand-pink) 14%, transparent),
              transparent);
}

.ui-footer::after {
  inset-block-end: -160px;
  inset-inline-start: -8%;
  background: radial-gradient(closest-side,
              color-mix(in srgb, var(--accent-clair) 10%, transparent),
              transparent);
}

/* Le bloc d'appel et la rangée du bas ne passent pas par .ui-container : sans
   ce plan, les halos leur passeraient devant. */
.ui-footer-cta,
.ui-footer-bottom { position: relative; z-index: 1; }

/* Sur-titre de colonne : capitales espacées, et le filet rose en dessous. */
.ui-footer-grid h3 {
  position: relative;
  font-size: var(--fs-caption);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
}

.ui-footer-grid h3::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  width: 24px;
  height: 2px;
  border-radius: 2px;
  background: var(--color-brand-pink);
}

/* Une colonne VIDE entre la marque et les liens. La rangée valait 3 + 3+3+3
   sur douze, soit exactement la largeur du conteneur : les liens démarraient
   collés au logo. On décale la première colonne de liens d'un douzième et on
   reprend ce douzième sur les trois colonnes, qui passent de 3/12 (25 %) à
   8/12 partagés en trois (22,222 %). Le compte retombe juste — 25 + 8,333 +
   3 x 22,222 = 100 — et la grille reste donc à fleur de marge à droite.

   Écrit ici plutôt que dans les données : c'est un réglage de mise en page,
   il n'a pas à être recopié dans les huit fichiers de pages, ni à dépendre
   de la classe Bootstrap que chacun déclare. Les sélecteurs de voisinage
   (~ et +) passent devant .col-lg-3 en spécificité.

   Rien ne change sous 992px : les colonnes y sont empilées deux par deux,
   la marque occupe toute la largeur, et un décalage n'aurait pas de sens. */
@media (width >= 992px) {
  .ui-footer-grid > .ui-footer-brand ~ .ui-grid-item {
    flex: 0 0 auto;
    width: 22.2222%;
  }

  .ui-footer-grid > .ui-footer-brand + .ui-grid-item {
    margin-inline-start: 8.3333%;
  }
}

/* La pastille de survol. Elle est posée en dehors du lien (à −14px) pour ne
   pas décaler le texte au repos : c'est le lien entier qui glisse, la
   pastille se contentant d'apparaître dans la marge qu'il libère. */
.ui-footer-grid a {
  position: relative;
  width: fit-content;
  transition: color 0.2s ease, transform 0.2s ease;
}

.ui-footer-grid a::before {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: -14px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-brand-pink);
  opacity: 0;
  transform: translate(-4px, -50%);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.ui-footer-grid a:hover { transform: translateX(4px); }
.ui-footer-grid a:hover::before { opacity: 1; transform: translate(0, -50%); }

/* Les pastilles sociales se remplissent de rose — un aplat, donc les 3:1
   suffisent — et le pictogramme y passe en blanc. */
.ui-footer-social a:hover,
.ui-footer-social a:focus-visible {
  color: var(--on-dark);
  background: var(--color-brand-pink);
  border-color: var(--color-brand-pink);
  transform: translateY(-3px);
}

@media (prefers-reduced-motion: reduce) {
  .ui-footer-grid a,
  .ui-footer-grid a::before,
  .ui-footer-social a { transition: none; }
  .ui-footer-grid a:hover,
  .ui-footer-social a:hover { transform: none; }
}

/* ---- En-tête ----
   La charte le veut simple et large : navigation centrée, actions à
   droite, et une rangée de 96px là où le socle tenait en 79.

   Deux choses NE changent pas, à la demande : la barre utilitaire reste
   (la charte n'en a pas, mais le projet en a l'usage), et le logo reste
   vertical. Ce fichier ne porte donc que les mesures de la rangée de
   navigation.

   Le centrage est ABSOLU, sur la page — pas seulement dans l'espace
   restant. Les marges automatiques centraient la navigation entre le logo
   et les actions ; le logo étant plus étroit que les actions, elle
   penchait visiblement à gauche.

   Le centrage absolu suppose que le menu tienne entre ses voisins. Avec
   les quatre entrées de la charte, il reste 130px de dégagement de chaque
   côté à 1250px de large, la plus étroite où la barre horizontale existe.
   Un menu sensiblement plus long recouvrirait le logo : c'est la limite
   de ce parti pris, et elle est mesurable. */
/* Bootstrap ajoute 0.5rem de rembourrage vertical à .navbar, ce qui portait
   la rangée à 112px au lieu des 96 de --header-h.

   La variable doit être posée SUR .navbar, pas dans :root : Bootstrap la
   déclare sur l'élément lui-même, et une déclaration locale l'emporte
   toujours sur une valeur héritée. C'est le cas d'école que ui-theme.css
   décrit — la variable existe, mais le pont ne suffit pas à l'atteindre. */
.ui-site-header .navbar {
  --bs-navbar-padding-y: 0;
}

@media (width >= 1200px) {
  .ui-nav {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    margin-inline: 0;
  }
}

.ui-nav {
  gap: var(--space-4);                   /* 24px */
}

/* Le sélecteur de langue est un .btn : il héritait du 850 des boutons, plus
   lourd encore que les deux badges voisins. On l'aligne sur eux. */
.ui-utility-bar .ui-language-toggle,
.ui-utility-bar .ui-language-current {
  font-weight: var(--fw-semibold);
}

.ui-nav-link {
  font-weight: 600;
}

/* Le trait rose répond au logo ; le libellé reste encre/pétrole pour que la
   navigation ne redevienne pas une nappe de couleur. */
.ui-nav-link::after {
  background: var(--color-brand-pink-ink);
}

.ui-header-actions {
  gap: var(--space-4);                   /* 24px */
  font-size: var(--fs-sm);
  font-weight: 650;
}

/* Le lien de texte de l'en-tête — « Se connecter » dans le modèle. Il vit à
   côté d'un bouton et doit s'en distinguer sans crier : même corps et même
   graisse que les actions, aucune décoration, et le corail au survol comme
   les entrées de navigation. */
.ui-header-link {
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s ease;
}

.ui-header-link:hover,
.ui-header-link:focus-visible {
  color: var(--color-primary);
}

/* ---- Sections de contenu ----
   Le titre vit désormais DANS la colonne de texte, pas au-dessus des deux
   colonnes : c'est la structure de la charte, et elle est portée par le
   snippet. Ne restent ici que les mesures.

   Le liseré blanc autour de l'image est le trait le plus reconnaissable de
   ces sections — un cadre de 11px qui détache la photo du fond crème, avec
   un rayon plus large que le reste et une ombre profonde. */
.ui-content-media > img {
  border: 11px solid var(--white);
  border-radius: var(--radius);         /* 34px, un cran au-dessus des cartes */
  box-shadow: var(--shadow-photo);
  object-fit: cover;
}

/* Le texte courant de ces sections respire plus que le corps général :
   1.75 contre --lh-base (1.5). La largeur est bornée pour garder une
   longueur de ligne lisible même quand la colonne s'élargit. */
.ui-content-body {
  line-height: 1.75;
  max-width: 600px;
}

/* Le plafond de mesure saute quand le corps porte une mise en page et non un
   texte suivi : douze colonnes, une grille imbriquée, un encadré à côté. Les
   600px sont faits pour une longueur de LIGNE ; appliqués à une grille, ils
   la compriment tout entière, encadré compris.
   Posé ici, avec le plafond qu'il annule, et non dans ui-organismes.css :
   cette feuille est chargée en dernier, une règle écrite plus tôt aurait
   perdu l'arbitrage à spécificité égale. */
.ui-content-body--pleine {
  max-width: none;
}

.ui-content-heading {
  text-align: left;
  margin-bottom: 0;
}

.ui-content-body > p {
  margin: var(--space-4) 0 var(--space-4);        /* 25px / 32px, relevé sur la source */
}

/* Sur le gabarit sans image, le bloc se recentre — comme la source le fait
   sur mobile pour toutes ses sections de contenu. */
.ui-content-row--texte .ui-content-heading,
.ui-content-row--texte .ui-content-body {
  text-align: center;
  margin-inline: auto;
}

/* L'ALTERNATIVE de --texte, et non son complément : le bloc est placé par
   l'offset de la grille, pas par des marges automatiques, et sa composition
   se cale à gauche. Aucune règle de marge ici, et c'est le point : « margin-
   inline: 0 » aurait écrasé le « offset-lg-* » de Bootstrap, qui est lui
   aussi une marge gauche — le bloc serait retombé au ras du container au
   lieu de commencer sur sa colonne.
   Un descriptif de plusieurs paragraphes centré se lit mal : l'oeil perd le
   début de chaque ligne. */
.ui-content-row--gauche .ui-content-heading,
.ui-content-row--gauche .ui-content-body {
  text-align: left;
}

@media (width <= 991.98px) {
  .ui-content-heading,
  .ui-content-body {
    text-align: center;
    margin-inline: auto;
  }

  /* Le modificateur tient aussi sur mobile, et il est même plus utile qu'en
     desktop : c'est là que les lignes sont les plus courtes, donc que le
     centrage hache le plus la lecture. Les marges, elles, peuvent être
     remises à zéro sans risque : sous 992px, aucun offset de grille n'est
     appliqué — ils sont tous en « -lg- ». */
  .ui-content-row--gauche .ui-content-heading,
  .ui-content-row--gauche .ui-content-body {
    text-align: left;
    margin-inline: 0;
  }
}

/* ---- FAQ ----
   La source n'a pas de FAQ : il n'y a rien à recopier. On l'harmonise donc
   sur le vocabulaire déjà posé — des blocs arrondis, détachés, à filet
   presque effacé. Chaque question devient une petite carte, et non plus un
   maillon d'une liste continue.

   Bootstrap fond les bords entre items (il annule le border-top de tous
   sauf le premier) et n'arrondit que le premier et le dernier : c'est
   voulu pour un accordéon classique, et c'est exactement ce qu'il faut
   défaire ici. */
.ui-faq-list {
  --bs-accordion-border-color: var(--border-soft);
  --bs-accordion-border-radius: var(--radius);
  --bs-accordion-inner-border-radius: var(--radius);
  --bs-accordion-bg: var(--surface-card);
  --bs-accordion-btn-bg: var(--surface-card);
  --bs-accordion-active-bg: var(--surface-card);
  --bs-accordion-btn-padding-y: var(--space-4);
  --bs-accordion-btn-padding-x: var(--space-4);
  --bs-accordion-body-padding-x: var(--space-4);
}

.ui-faq-item {
  border-radius: var(--radius);
  margin-bottom: var(--space-3);
  box-shadow: var(--shadow-md);
}

/* Bootstrap retire le filet du haut à tous les items sauf le premier, pour
   qu'ils se touchent sans doubler la ligne. Détachés, il leur faut leurs
   quatre côtés. Le sélecteur reprend celui de Bootstrap
   (« .accordion-item:not(:first-of-type) ») et y ajoute la liste pour
   l'emporter — sans cela, le filet du haut restait à 0.

   Le RACCOURCI est nécessaire : Bootstrap écrit « border-top: 0 », ce qui
   met aussi le style à « none ». Ne redonner que la largeur ne rétablit
   rien — un bord sans style reste calculé à 0. */
.ui-faq-list .ui-faq-item:not(:first-of-type) {
  border-top: var(--bs-accordion-border-width) solid var(--bs-accordion-border-color);
}

.ui-faq-item:last-child {
  margin-bottom: 0;
}

/* Trois classes de sélecteur, à dessein : Bootstrap arrondit le bouton avec
   « .accordion-item:first-of-type > .accordion-header .accordion-button »,
   de même poids. Sans cette égalité, l'ordre de chargement ne suffirait pas.
   Pas d'overflow:hidden sur l'item pour y parvenir : l'anneau de focus du
   bouton déborde, et il serait rogné. */
.ui-faq-list .ui-faq-item > .accordion-header .accordion-button {
  border-radius: var(--radius);
}

.ui-faq-list .ui-faq-item > .accordion-header .accordion-button:not(.collapsed) {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* ---- Témoignages ----
   La charte donne à ses citations une voix éditoriale : Georgia en grand
   corps, graisse 500, chasse resserrée — et un guillemet ouvrant corail
   posé au-dessus, en très grand.

   C'est le troisième et dernier endroit où le serif apparaît, après
   l'accent du hero et la baseline du pied de page. Ces trois emplois ont
   un point commun : ce sont des voix, pas de l'interface. */
.ui-testimonial-mark {
  margin: 0 0 var(--space-1);
  font: 500 5rem/0.7 Georgia, "Iowan Old Style", "Times New Roman", serif;
  color: var(--color-brand-pink);
}

.ui-testimonial-quote p {
  font: 500 var(--fs-h4)/1.25 Georgia, "Iowan Old Style",
        "Times New Roman", serif;
  letter-spacing: -0.025em;
  color: var(--text);
}
@media (width <= 560px) { .ui-testimonial-quote p { font-size: var(--fs-lead); } }

/* L'attribution redescend en petit corps : elle situe, elle ne parle pas. */
.ui-testimonial-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-muted);
}

/* ---- Cartes d'engagement ----
   Elles vivent sur une section texturée. La charte ne les y pose pas en
   aplat opaque : elle les rend TRANSLUCIDES, avec un filet blanc, pour que
   la texture transparaisse et que la carte se pose sur le fond au lieu de
   le masquer. Relevé sur la source : blanc à 76 %, filet blanc à 90 %.

   Le filet n'est donc pas celui des cartes ordinaires (encre à 6 %) : sur
   un fond teinté, un filet sombre creuserait un trait là où la charte veut
   une arête lumineuse. */
.ui-cards-section .ui-carte {
  background: color-mix(in srgb, var(--white) 70%, transparent);
  border-color: color-mix(in srgb, var(--white) 90%, transparent);
}

/* Les cartes numérotées du showcase restent OPAQUES : elles sont sur fond
   encre, et une carte translucide y perdrait le contraste dont son texte
   sombre a besoin. Le procédé de la charte ne se transpose pas tel quel
   d'un fond clair à un fond sombre. */

/* ---- Showcase ----
   La bande sombre porte une SCÈNE sous un voile d'encre.

   Elle a d'abord été un aplat : le socle y posait images/fond.svg sous un
   dégradé à 74 %, et à cette opacité un motif abstrait ne se lit plus, il
   salit — d'où le retour à l'aplat qu'on lit encore dans l'historique de ce
   fichier. Ce qui change ici n'est pas l'avis sur le voile mais ce qu'il y a
   dessous : une texture sans sujet ne survit pas à 74 %, une photo de deux
   personnes attablées, si. C'est la même scène que la première carte
   communauté de l'accueil, et c'est voulu — la bande parle de la conversation
   qui s'engage, la carte du groupe où elle s'engage.

   Le masque est d'une SEULE teinte — --color-voile, #110000 — et seule son
   opacité varie. Deux teintes ont été essayées avant, et toutes deux
   coloraient la bande : --color-dark-soft — alors #49231a — en étape
   intermédiaire la faisait virer au brun, puis --color-dark seule — alors #31060a — au rouge.
   La cause est la même : ces encres sont saturées (88 % pour le rouge d'alors,
   49 % pour le violet qui lui a succédé), et la photo est
   quasi neutre — le voile fournissait donc seul la couleur de la bande.
   Mesuré à six hauteurs : teinte 354-358°, saturation 24 à 43 %.
   #110000 n'apporte que de l'ombre, la scène garde ses couleurs.

   L'aplat de fond, lui, reste --color-dark : il ne se voit que si l'image
   manque, et là c'est bien l'encre de la charte qu'on veut.

   Le voile est VERTICAL, et c'est le point : 68 % en haut de bande, 65 % au
   bas du bandeau de titre, 41 % au milieu, 57 % en bas. Un dégradé diagonal a
   été essayé d'abord, il ne tient pas — la parallaxe (--collection-bg-y,
   ±120px) fait passer derrière le titre des zones claires de la photo, et le
   sur-titre y tombait à 3,3:1. Le voile doit donc être dense LÀ OÙ LE TEXTE
   PASSE, c'est-à-dire sur le tiers haut : le bandeau de titre occupe 16 à
   32 % de la hauteur, la rangée de cartes commence à 38 %, et ces cartes sont
   opaques — sous elles, le voile s'ouvre à 41 % et c'est là que la scène se
   lit.

   LE PALIER À 34 % N'EST PAS DÉCORATIF : il tient le bas du bandeau de titre.
   Sans lui, l'interpolation vers l'étape du milieu ferait tomber le voile à
   61 % sous le titre, et le sur-titre avec — un dégradé se règle sur la
   géométrie de ce qu'il protège, pas sur des tiers ronds.

   Les valeurs sont mesurées sur le pixel le plus clair que la parallaxe
   puisse amener derrière le titre, pas estimées : sur-titre et accent à
   4,4:1, titre à 7,0:1. Le titre passe largement (3:1 exigé) ; le sur-titre
   est SOUS les 4,5:1 d'un petit texte, de 0,07 — un arbitrage assumé en
   faveur de la photo, sur le pire pixel d'une amplitude de parallaxe, pas sur
   le cas courant. Remonter les quatre étapes de trois points le repasserait.

   Le voile est resté à 94 % tant que l'accent était corail — une teinte
   moyenne qui n'atteignait pas 3:1 même là. Passé au sable
   (--accent-sur-sombre), il gagne du contraste quand le fond s'assombrit au lieu
   d'en perdre, et trente points de voile ont pu être rendus à la photo.

   L'aplat d'encre reste posé DERRIÈRE la photo (background-color) : il tient
   la bande si l'image tarde ou ne charge pas, et le texte reste lisible
   entre-temps.

   Le titre y perd toujours son ombre portée — un halo hérité qui n'existe
   nulle part dans cette charte. */
.ui-showcase {
  background-image:
    linear-gradient(180deg,
      color-mix(in srgb, var(--color-voile) 68%, transparent) 0%,
      color-mix(in srgb, var(--color-voile) 65%, transparent) 34%,
      color-mix(in srgb, var(--color-voile) 41%, transparent) 58%,
      color-mix(in srgb, var(--color-voile) 57%, transparent) 100%),
    url('../../images/photos/scene-1.jpg');
  background-color: var(--section-sombre);
  background-size: cover, cover;
  background-position: center, center calc(50% + var(--collection-bg-y, 0px));
  background-repeat: no-repeat;
}

.ui-showcase .ui-section-title {
  text-shadow: none;
}

.ui-showcase-lead {
  border-radius: var(--radius);
}

/* Le numéro d'une carte de série : un petit chiffre corail posé dans
   l'angle, en graisse 900 — pas un bloc au-dessus du titre. Il compte, il
   n'annonce pas. Portée limitée à la variante numérotée : le même atome
   .ui-kicker sert ailleurs de sur-titre en flux. */
.ui-carte--numerotee {
  position: relative;
}

.ui-carte--numerotee .ui-kicker {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: 600;               /* suit le sur-titre, dont il est la variante d'angle */
}

/* Le titre doit lui céder l'angle : sorti du flux, le numéro passerait
   sinon par-dessus la première ligne. La réserve tient deux chiffres et
   l'écart au bord. */
.ui-carte--numerotee .ui-card-title {
  padding-right: var(--space-5);
}

/* ---- Bandeau d'appel ----
   Deux ornements hérités ont été retirés du composant : une filigrane
   « B2B » de 288px écrite en dur dans le CSS — du vocabulaire de secteur
   qui avait survécu à la neutralisation parce qu'il n'était pas dans le
   HTML — et un filet vertical dégradé à halo. La charte n'a ni l'un ni
   l'autre : elle appelle à l'action par le texte et le bouton.

   Le titre y est le plus grand de tout le site, et le plus resserré :
   64px (display-3), puis 48 et 40 par paliers, interlignage 1.03, chasse -0.055em. C'est le seul
   endroit, avec le hero, qui va aussi loin. */
.ui-cta-band-copy h2 {
  font-size: var(--fs-display-3);
  line-height: 1.03;
  letter-spacing: -0.055em;
  padding-left: 0;
}
/* Paliers de l'échelle du DS plutôt qu'une taille fluide (30 sept. 2026). */
@media (width <= 820px) { .ui-cta-band-copy h2 { font-size: var(--fs-display-5); } }
@media (width <= 560px) { .ui-cta-band-copy h2 { font-size: var(--fs-h1); } }

.ui-cta-band-copy {
  padding-left: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
}

.ui-cta-band-copy > p:last-child {
  max-width: 620px;
  font-size: var(--fs-lead);
  line-height: 1.65;
}

.ui-steps-panel {
  border-radius: var(--radius);
}

/* ---- Icône de carte, et sa progression ----
   La charte pose en tête de certaines cartes un carré arrondi portant un
   glyphe. Sur une série, sa teinte PROGRESSE du plus doux au plus soutenu :
   c'est ce qui donne à la suite son sens de lecture.

   La source obtient cette progression par nth-child. Ici elle est portée
   par la donnée (iconTone) : dans un design system, une carte ne doit pas
   changer d'aspect parce qu'on l'a déplacée dans la grille. */
.ui-carte-icone {
  display: grid;
  place-items: center;
  /* Dimensions du modèle : 82px, rayon 28. La pastille de numéro déborde du
     carré, d'où la position relative — sans elle, elle se placerait par
     rapport à la carte et non par rapport au carré. */
  position: relative;
  width: 82px;
  height: 82px;
  margin-bottom: var(--space-4);        /* 24px */
  border-radius: var(--radius);          /* 28px */
  background: var(--surface-appuyee);
  color: var(--color-dark);
  /* Le carre est LEGEREMENT INCLINE, et le glyphe avec lui puisque la
     rotation porte sur le conteneur. C'est ce qui donne a la serie son air
     dessine a la main plutot que pose a la regle. Releve sur la source. */
  transform: rotate(-4deg);
}

.ui-carte-icone .material-symbols-outlined {
  font-size: var(--icon-xl);
}

/* Pastille de numéro posée sur l'angle du carré. Son liseré n'est pas un
   trait : c'est le fond de la section qui passe entre elle et le carré, et
   qui la détache quand les deux couleurs sont proches. La valeur suit donc
   le fond de la bande claire, seul endroit où cette composition sert. */
.ui-carte-icone-num {
  position: absolute;
  top: -8px;
  right: -8px;
  display: grid;
  place-items: center;
  /* 20 % de plus que les 28px d'origine, liseré et chiffre compris — une
     pastille agrandie sans son trait ni son chiffre changerait de dessin. */
  width: 34px;
  height: 34px;
  border: 3.6px solid var(--surface-douce);
  border-radius: 50%;
  background: var(--color-brand-pink-ink);
  /* Chiffre BLANC. La réserve qui figurait ici — 3,77:1, sous les 4,5 d'un
     petit texte — est LEVÉE : elle tenait à l'ancien rose #ff204e, sur lequel
     aucun libellé ne passait AA. Sur #e20138, le blanc donne 4,89:1. */
  color: var(--white);
  font-size: var(--fs-caption);
  /* 600 et non 800. La pastille chiffrée était l'élément le plus gras de la
     page — plus que les titres (700), plus que les boutons. Un numéro d'étape
     n'a pas à peser plus lourd que le titre qu'il numérote : il se signale par
     son aplat rond et sa couleur, pas par l'épaisseur du chiffre.
     Même graisse que la pastille de notifications et les libellés de bouton. */
  font-weight: 600;
}

/* Les carrés forment une PROGRESSION dans la seule famille du pétrole des
   titres. Ils portaient auparavant des teintes sans rapport — une pêche, un
   corail éclairci, une encre — héritées d'une charte antérieure ; sur une
   page devenue pétrole et rose, elles se lisaient comme des accidents
   plutôt que comme des marches.

   QUATRE marches depuis que la série « Simple comme un premier sourire » a
   gagné une étape : 18 %, 40 %, 62 %, plein — des paliers de 22 points, donc
   régulièrement espacés. La deuxième descend de 45 à 40 pour que l'écart soit
   le même partout : une progression dont les marches sont inégales se lit
   comme une erreur de teinte, pas comme une gradation.

   Le ton « soft » de la molécule reste en dehors de cette série : il vaut
   --surface-appuyee, qui n'est pas du pétrole. C'est le défaut d'une carte
   isolée, non le premier degré d'une suite.

   Le glyphe bascule au blanc sur la DERNIÈRE marche seulement, là où l'encre
   ne tient plus : 11,43 · 7,67 · 4,88 en encre sur les trois premières,
   7,64 en blanc sur la quatrième. Chaque marche garde ainsi le contraste le
   plus élevé que son fond permet, et les quatre passent AA. */
.ui-carte-icone--accent {
  background: color-mix(in srgb, var(--color-titre) 12%, var(--white));
  color: var(--color-dark);
}

.ui-carte-icone--primary {
  background: color-mix(in srgb, var(--color-titre) 40%, var(--white));
  color: var(--color-dark);
}

/* Troisième marche. 62 % et non 70 : au-delà, le fond entre dans une zone où
   NI l'encre NI le blanc n'atteignent 4,5 sur le numéro (3,74 et 4,03 à
   70 %). 62 est le dernier palier où l'encre passe encore. */
.ui-carte-icone--profond {
  background: color-mix(in srgb, var(--color-titre) 55%, var(--white));
  color: var(--color-dark);
}

.ui-carte-icone--dark {
  background: var(--color-titre);
  color: var(--white);
}

/* Toutes les cartes d'une rangee ont la meme hauteur. Les colonnes de
   Bootstrap s'etirent deja ; c'est la carte qui ne remplissait pas la
   sienne — mesure 256, 306, 313 et 306 px pour des colonnes toutes a 313.
   Le texte le plus long commande donc la hauteur de la rangee entiere. */
.ui-grid-item > .ui-carte {
  height: 100%;
}

/* En-tete centre : quand la bande n'a pas de chapo lateral, le titre et son
   sur-titre se centrent, bornes a une longueur de ligne lisible. */
.ui-section-heading--centre {
  max-width: 760px;
  margin-inline: auto;
  margin-bottom: var(--space-5);        /* 48px */
  text-align: center;
}

/* ---- Showcase clair ----
   Le pendant clair de la bande sombre : même structure, fond pêche, et une
   série de cartes translucides posées dessus. C'est la section « du premier
   regard à la conversation » du modèle. */
/* Deux anneaux en fond, débordant de part et d'autre : ils meublent les marges
   sans jamais passer derrière le texte, et le débordement est contenu par
   « overflow: hidden ». Ce sont des ANNEAUX, non des disques — la bordure
   épaisse laisse voir le fond au centre, ce qui les rend beaucoup plus
   discrets qu'un aplat de la même taille. */
/* ---- Fonds de section, posés par la DONNÉE ----
   Un modificateur par couleur de la famille --section-*. Il se pose via la clé
   « modifier » de l'organisme, jamais dans le CSS d'un composant : c'est la
   PAGE qui décide de son rythme, pas la section qui décide pour elle. La même
   section d'aperçu est blanche sur l'accueil et menthe ailleurs, sans qu'une
   ligne de son organisme change.

   LA RÈGLE : d'une section à l'autre, fond coloré, fond blanc, fond coloré.
   Une section sur deux seulement porte une couleur — c'est l'alternance qui
   découpe la page, pas la couleur elle-même, et deux bandes colorées
   consécutives annulent l'effet qu'on cherchait.

   Et on change de teinte à chaque fois plutôt que de répéter le rosé : la
   palette en compte cinq, toutes à 10 %, toutes au-dessus de 15:1 en texte
   Nuit. S'en tenir à une seule donnait une page monochrome — c'est
   précisément ce qu'on corrige ici. */
.ui-fond-teinte-1   { background: var(--section-teinte-1); }
.ui-fond-teinte-2  { background: var(--section-teinte-2); }
.ui-fond-teinte-3  { background: var(--section-teinte-3); }
.ui-fond-teinte-4   { background: var(--section-teinte-4); }
.ui-fond-teinte-5   { background: var(--section-teinte-5); }
.ui-fond-teinte-6 { background: var(--section-teinte-6); }
.ui-fond-teinte-7 { background: var(--section-teinte-7); }

/* Le DÉGRADÉ du hero, réemployé en fond de section : même départ au blanc,
   même arrivée sur la teinte 7. La bande reprend donc la respiration de
   l'ouverture de page au lieu d'un aplat, et les deux se répondent.

   Écrit ici et non repris de .ui-hero-scroll-zone--degrade : celle-là porte
   en plus un background-size calculé sur --search-bar-h, propre à la carte de
   recherche qui la traverse. Une section n'a pas de carte à couper. */
.ui-fond-degrade { background: linear-gradient(to bottom, var(--white), var(--section-teinte-7)); }

/* LE FOND TEXTURÉ DES ÉCRANS D'APP du téléphone (1er oct. 2026) : le jeton
   --fond-app — dégradé pâle et formes floues pétrole et vertes. Mon compte le
   porte ; la recherche en swipe le pose sur toute la page. */
.ui-fond-app { background: var(--fond-app); }

/* Rembourrage haut réduit de 30 % sur la section qui porte le décor de
   galets : le galet remonte déjà de 165px au-dessus de la limite et occupe
   l'espace que cette marge ménageait. La garder pleine laissait un vide entre
   la fin des cartes du dessus et le sur-titre. */
.ui-decor-galets { padding-top: var(--space-6); }

/* ---- Décor de galets ----
   Le même aplat organique que le hero (.ui-hero-visual--detoure::before) :
   rayons dissymétriques, rotation de −6°, 40 % de --surface-appuyee. Les
   valeurs sont recopiées à l'identique — c'est le même ornement, il doit se
   RECONNAÎTRE d'une section à l'autre plutôt que se ressembler à peu près.

   Deux galets et non un, posés en MIROIR : l'un sort par le haut à gauche,
   l'autre par le bas à droite, tournés de 180° l'un par rapport à l'autre.
   La diagonale équilibre la bande sans que le regard s'arrête sur une forme
   isolée, et les deux sortent du cadre — un ornement qui tient entier dans la
   section se lit comme un objet, pas comme un fond.

   Ils remplacent les anneaux de .ui-bande-peche, qui venaient de la vitrine
   claire et n'avaient pas de parenté avec le hero. */
/* overflow-x: clip et non hidden — les galets doivent DÉBORDER vers le haut
   pour couvrir les deux sections d'un seul tenant, mais pas sur les côtés, où
   ils feraient scroller la page. « clip » sur un seul axe laisse l'autre en
   « visible », ce que « hidden » ne permet pas : hidden sur un axe force
   l'autre en auto, et le débordement vertical serait rogné.

   z-index 0 avec position:relative : la section forme un plan qui passe SOUS
   celui de la section du dessus (voir la règle :has ci-dessous). Le galet peut
   donc empiéter sur elle sans jamais recouvrir son contenu. */
.ui-decor-galets {
  position: relative;
  z-index: 0;
  overflow-x: clip;
}

/* La section qui PRÉCÈDE un décor de galets se met au-dessus. Sélecteur de
   voisinage plutôt qu'une classe posée à la main : le jour où le décor change
   de section, la règle suit sans qu'on ait à y penser. */
.ui-section:has(+ .ui-decor-galets) {
  position: relative;
  z-index: 1;
}

.ui-decor-galets::before,
.ui-decor-galets::after {
  content: "";
  position: absolute;
  z-index: 0;
  width: min(46%, 520px);
  aspect-ratio: 620 / 580;
  border-radius: 46% 54% 58% 42% / 47% 43% 57% 53%;
  background: color-mix(in srgb, var(--surface-appuyee) 40%, transparent);
}

/* -34% : le galet remonte d'un bon tiers de sa hauteur AU-DESSUS de la
   section, de sorte que la limite entre les deux bandes le traverse au lieu
   de le couper. C'est tout l'objet du débordement. */
.ui-decor-galets::before {
  inset-block-start: -34%;
  inset-inline-start: -12%;
  transform: rotate(-6deg);
}

/* 174° et non −6° : la même rotation, à un demi-tour près. Le galet du bas
   est donc exactement celui du haut retourné, et non une seconde forme. */
.ui-decor-galets::after {
  inset-block-end: -16%;
  inset-inline-end: -12%;
  transform: rotate(174deg);
}

/* Le contenu repasse devant. */
.ui-decor-galets > .ui-container {
  position: relative;
  z-index: 1;
}

/* ---- Décor de rond ----
   Le pendant SOBRE des galets : un disque unique, franc, à peine teinté, que
   le bord de la section recoupe. Là où les galets donnent une forme dessinée
   à la main, celui-ci ne donne qu'une masse — c'est ce qu'il faut sous une
   section qui porte déjà un objet dessiné (la carte d'évènement) ou une pile
   de blocs (l'accordéon de la FAQ), où une seconde forme organique ferait
   concurrence au contenu.

   7 % du pétrole des titres, une seule valeur pour les deux fonds : sur le
   blanc il donne #eef4f5, sur la teinte froide de la FAQ #d2e2e4. Dans les
   deux cas l'écart au fond est du même ordre, le rond se voit autant sans
   qu'on ait à le régler par section.

   overflow: hidden et non « clip » sur un axe : ici le disque doit être
   RECOUPÉ par la section, pas la déborder. C'est la coupe qui le fait lire
   comme un fond et non comme un objet posé sur la page. */
.ui-decor-rond {
  position: relative;
  z-index: 0;
  overflow: hidden;
}

.ui-decor-rond::before {
  content: "";
  position: absolute;
  z-index: 0;
  width: min(52%, 560px);
  /* PLUS UN CERCLE. Un « border-radius » à huit valeurs donne le galbe
     irrégulier des galets ; celui-ci est un tirage différent du leur, pour que
     les deux familles ne soient pas la même forme à deux échelles. La
     proportion aussi est brisée — 1,12 au lieu de 1 — sans quoi un galbe posé
     sur un carré se relit comme un cercle bosselé. */
  aspect-ratio: 1.12;
  border-radius: 58% 42% 47% 53% / 44% 56% 44% 56%;
  background: color-mix(in srgb, var(--color-titre) 6%, transparent);
  inset-block-start: -16%;
  inset-inline-end: -10%;
  pointer-events: none;
}

/* Variante en miroir, pour alterner d'une section à l'autre. Le disque passe
   en bas à gauche : deux sections qui se suivent avec le rond au même endroit
   se liraient comme une seule bande mal cadrée. */
.ui-decor-rond--gauche::before {
  inset-block-start: auto;
  inset-inline-end: auto;
  inset-block-end: -20%;
  inset-inline-start: -12%;
}

/* Variante qui DÉBORDE sur la section suivante au lieu d'être recoupée par la
   sienne. Le disque cesse alors d'appartenir à une bande pour enjamber la
   limite entre deux — c'est ce qui relie visuellement une section d'appel à
   la consultation qui la suit.

   Deux réglages le permettent, et il faut les deux :

   · overflow-y VISIBLE, overflow-x CLIP. Le débordement doit se faire vers le
     bas, jamais sur les côtés où il ferait défiler la page. « clip » sur un
     seul axe laisse l'autre en « visible », ce que « hidden » interdit — un
     axe caché force l'autre en « auto ».

   · z-index 1 sur la section. Sans lui, le fond OPAQUE de la section suivante,
     posée après dans le document, repeindrait par-dessus la part du disque qui
     la recouvre : le débordement existerait sans se voir. Le disque n'est
     qu'un voile à 7 %, il teinte ce qu'il recouvre sans le masquer, et il ne
     capte pas le pointeur.

   La section qui reçoit le débordement n'a rien à déclarer : c'est celle qui
   porte le disque qui décide de le laisser sortir. */
.ui-decor-rond--deborde {
  overflow-y: visible;
  overflow-x: clip;
  z-index: 1;
}

/* Le disque remonte de 150px. Écrit en calc sur la valeur d'origine plutôt
   qu'en valeur absolue : le -20 % reste lisible comme le réglage de la
   variante « gauche », et les 150px comme la correction propre à CETTE
   composition. Les deux classes dans le sélecteur — le décalage n'a de sens
   que pour le disque de gauche qui déborde, celui d'en haut à droite n'a pas
   d'inset-block-end à corriger. */
.ui-decor-rond--gauche.ui-decor-rond--deborde::before {
  inset-block-end: calc(-20% + 150px);
}

.ui-decor-rond > .ui-container {
  position: relative;
  z-index: 1;
}
.ui-fond-base   { background: var(--section-base); }

/* .ui-bande-peche porte le fond et les anneaux, .ui-showcase--light s'y joint.
   Le décor a été DÉTACHÉ de la vitrine claire le jour où l'aperçu des
   évènements de l'accueil a dû le porter aussi : un fond n'appartient pas à
   l'organisme qui l'a employé le premier. Le modificateur se pose par la
   donnée (« modifier ») sur n'importe quelle section, sans que son organisme
   ait à le connaître.

   Les deux sélecteurs plutôt qu'une classe ajoutée au balisage de la vitrine :
   .ui-showcase--light est déjà écrit dans les données de concept.html et du
   design system ; le renommer ferait un chantier là où une virgule suffit. */
.ui-bande-peche,
.ui-showcase--light {
  position: relative;
  overflow: hidden;
  /* AUCUN aplat : ce sont les ANNEAUX qui font le décor de cette bande, pas
     son fond. Ils suffisent à la détacher de ses voisines, et le blanc de la
     page les laisse mieux voir qu'un rosé. */
}

.ui-bande-peche::before,
.ui-bande-peche::after,
.ui-showcase--light::before,
.ui-showcase--light::after {
  content: "";
  position: absolute;
  z-index: 0;
  width: 180px;
  height: 180px;
  border: 35px solid color-mix(in srgb, var(--color-secondary) 25%, transparent);
  border-radius: 50%;
}

.ui-bande-peche::before,
.ui-showcase--light::before {
  left: -85px;
  top: 120px;
}

.ui-bande-peche::after,
.ui-showcase--light::after {
  right: -110px;
  bottom: 20px;
}

/* Le contenu repasse devant les anneaux. */
.ui-bande-peche > .ui-container,
.ui-showcase--light > .ui-container {
  position: relative;
  z-index: 1;
}

/* Propre à la vitrine CLAIRE : elle doit défaire le fond en dégradé et les
   couleurs de texte que .ui-showcase pose pour sa variante sombre. Une section
   qui n'est pas une vitrine n'a rien à défaire, d'où ces trois lignes hors du
   décor partagé. */
/* background-COLOR autant que background-image. Le retrait de l'aplat, quand
   le blanc est devenu le fond par défaut, n'avait laissé que « background-image:
   none » : la variante claire héritait donc du background-color sombre de
   .ui-showcase et rendait un titre encre sur pétrole — 1,27:1, illisible.
   La couleur du texte suppose un fond clair, le fond doit donc être déclaré. */
.ui-showcase--light {
  background-image: none;
  background-color: var(--section-base);
  color: var(--text);
}

.ui-showcase--light .ui-section-title,
.ui-showcase--light .ui-card-title {
  color: var(--text);
}

.ui-showcase--light .ui-eyebrow {
  color: var(--color-brand-pink-ink);
}

.ui-showcase--light .ui-showcase-lead {
  color: var(--text-muted);
  border-color: var(--border-soft);
}

.ui-showcase--light .ui-carte {
  background: color-mix(in srgb, var(--white) 90%, transparent);
  border-color: var(--white);
}

/* ---- Titre et texte de carte ----
   Relevé sur les cartes du modèle : 20 à 22px selon la section, en gras,
   chasse resserrée — et un texte à 16px avec un interlignage généreux.

   Le socle les posait à --fs-h4 (24px) en graisse 500 : une échelle de
   titre de niveau 4, cohérente avec Bootstrap mais trop haute et trop
   légère pour cette charte, où une carte se lit d'un coup d'œil.
   On descend d'un cran sur l'échelle — --fs-h5 vaut 20px, à un pixel du
   modèle — et on remonte la graisse. */
.ui-card-title {
  font-size: var(--fs-h5);
  font-weight: 600;
}

/* Le texte de carte passe de --fs-sm (14px) à --fs-base (16px) : dans le
   modèle une carte n'écrit pas en petit, elle écrit court. */
.ui-carte p {
  font-size: var(--fs-base);
  line-height: 1.65;
}

/* Sur les surfaces claires, le rose signe les fragments éditoriaux tandis que
   les commandes et repères fonctionnels restent pétrole. */
.ui-showcase .ui-section-title .ui-accent {
  color: var(--color-brand-pink);
}

/* L'accent de la bande sombre porte le ROSE DE MARQUE, comme tous les autres
   accents de titre du site. Un seul rose, sans exception de contexte.

   RÉSERVE MESURÉE, à connaître : #e20138 sur --section-sombre donne 2,46:1,
   sous les 3:1 qu'un accent de titre de 36px devrait tenir. Le rose d'avant,
   #ff204e, y arrivait à 3,18 — une marge de 0,18 qui tenait au couple exact
   #ff204e / #053c49 et que le changement de rose a effacée.
   Un rose éclairci (#ec5a7e, 3,62) a été essayé et retiré : il rétablissait la
   lecture mais introduisait un TROISIÈME rose, alors que l'objet de la
   manœuvre était de n'en garder qu'un.
   La sortie propre, le jour où on la voudra, est d'assombrir la bande et non
   d'éclaircir le rose : à 10 % de clarté au lieu de 15 (#032730), le rose
   plein repasse à 3,21 et le blanc du texte courant y gagne aussi. */
.ui-showcase--dark .ui-section-title .ui-accent {
  color: var(--color-brand-pink);
}

/* Le sur-titre de la bande sombre suit la règle « tous les sur-titres au
   rose » et quitte l'abricot. Il y perd du contraste — 4,05:1 contre 9,75 —
   mais reste au-dessus des 3:1 d'un élément graphique. L'accent du TITRE, lui,
   garde l'abricot : c'est un accent, pas un sur-titre. */
/* BLANC sur la bande sombre, et non le rose des autres sur-titres : sur le
   pétrole, le rose ne donne que 3,18:1 pour du 12px. Le blanc monte à 12,01 —
   et le sur-titre garde son pictogramme, qui suffit à le signer. */
.ui-showcase--dark .ui-eyebrow--accent {
  color: var(--white);
}


/* ---- Hero « réciprocité » (concept.html) : calage vertical ----
   Les deux colonnes remontent, de valeurs différentes — le texte de 80px, le
   visuel de 40. Elles ne bougent donc pas ensemble et le décalage est voulu :
   le titre monte plus haut que la fiche qu'il commente.

   Sélecteur :has(.ui-hero-board) plutôt qu'une classe posée à la main. Ce hero
   est le seul du site à porter la fiche de critères ; le viser par ce qu'il
   CONTIENT évite d'inventer un modificateur pour une page unique, et la fiche
   du design system, qui rend le même organisme, suit sans rien déclarer.

   Conséquence assumée : la section garde sa hauteur, l'air remonté se retrouve
   donc en bas. C'est ce qu'on veut ici — le hero se termine plus tôt et la
   section suivante paraît plus proche. */
.ui-hero:has(.ui-hero-board) .ui-hero-copy-primary {
  position: relative;
  top: -80px;
}

.ui-hero:has(.ui-hero-board) .ui-hero-visual {
  position: relative;
  top: -40px;
}

/* ---- Sur-titres ----
   Texte ET pictogramme au rose --color-brand-pink.
   La réserve qui figurait ici — 3,77:1 sur blanc pour du 12px, sous les 4,5
   du texte courant, « choix assumé » — est LEVÉE : elle tenait à l'ancien rose
   #ff204e. Sur #e20138, le sur-titre donne 4,89:1 et passe AA. */
.ui-eyebrow {
  /* inline-flex, non block : le sur-titre ne doit pas s'étendre au-delà de son
     texte, sans quoi le « gap » du pictogramme n'aurait rien à espacer. */
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-brand-pink-ink);
  font-size: var(--fs-caption);
  /* 600 et non 800. À 12px, capitales et 0,13em d'interlettrage, le sur-titre
     se signale déjà par sa forme : il est le seul texte de la page en petites
     capitales espacées. Y ajouter la graisse maximale le faisait rivaliser
     avec le titre qu'il annonce — et un sur-titre qui pèse plus que son titre
     inverse la hiérarchie qu'il est censé poser.
     600 : la graisse commune des libellés d'interface du site. */
  font-weight: 600;
  letter-spacing: 0.13em;
}

/* Réaffirmé APRÈS la règle ci-dessus : à spécificité égale, c'est l'ordre qui
   tranche, et la variante claire doit rester maîtresse sur fond sombre. */
.ui-eyebrow--light {
  color: var(--on-dark-subtle);
}

/* Le pictogramme du sur-titre est légèrement plus grand que la capitale qui
   le suit — 14px contre 12px, comme dans le modèle. */
.ui-eyebrow {
  margin-bottom: var(--space-4);         /* 22px dans le modèle */
}

.ui-eyebrow .material-symbols-outlined {
  font-size: var(--icon-sm);
  color: var(--color-brand-pink-ink);
  /* Plein, comme le caractère ♥ du modèle. Les autres axes sont repris du
     socle : la propriété est unique, n'écrire que « FILL » les effacerait. */
  font-variation-settings: 'FILL' 1, 'wght' 300, 'GRAD' 0, 'opsz' 20;
}

/* ---- Hero « sélection » ----
   Le grand anneau du modèle : une bordure de 75px, non un disque plein, ce
   qui laisse voir le fond au centre. Débordant à droite et en haut, il est
   contenu par l'« overflow: hidden » que le hero porte déjà. */
.ui-hero:has(.ui-hero-selection)::before {
  content: "";
  position: absolute;
  z-index: 0;
  top: -130px;
  right: -190px;
  width: 620px;
  height: 620px;
  border: 75px solid color-mix(in srgb, var(--color-secondary) 6%, transparent);
  border-radius: 50%;
}

/* L'accent passe à la ligne, comme le « em » du modèle, et le titre garde sa
   largeur de composition. Portée à ce hero seul : ailleurs, l'accent reste
   dans le fil du texte. */
.ui-hero:has(.ui-hero-selection) .ui-display-title {
  max-width: 640px;
}

.ui-hero:has(.ui-hero-selection) .ui-display-title .ui-accent {
  display: block;
}

/* Le modèle aligne les deux colonnes du hero de sélection sur leur BAS, non
   sur leur milieu : la scène descend jusqu'au pied du hero et le texte se
   pose à la même ligne. C'est ce qui donne son assise à la composition. */
.ui-hero:has(.ui-hero-selection) .ui-hero-copy,
.ui-hero:has(.ui-hero-selection) .ui-hero-visual {
  align-self: end;
}

/* Chapô plus large ici que sur le hero d'accueil : 585px contre 540. */
.ui-hero:has(.ui-hero-selection) .ui-hero-lead {
  max-width: 585px;
}

/* ---- Lien-texte ----
   Le socle le peint entièrement en corail, à 600 : c'était une décision prise
   avant la charte. Le modèle veut le libellé à l'encre, graisse 800, et
   réserve le corail à la seule flèche — c'est elle qui porte le mouvement.
   Le soulignement au survol du socle est conservé : le modèle s'en passe,
   mais retirer cette affordance d'un lien coûterait plus qu'elle ne rapporte. */
.ui-text-link {
  color: var(--text);
  font-weight: 700;
}

.ui-text-link span {
  margin-left: var(--space-2);
  color: var(--color-brand-pink-ink);
}

/* La bulle est un geste expressif, pas une commande : elle reprend la couleur
   du logo alors que le bouton voisin conserve le pétrole fonctionnel. */
/* Le bord de la bulle prend la couleur des TITRES et non le rose : la bulle
   est posée à côté du titre de hero, les deux traits se répondent. C'est la
   règle qui l'emporte — le socle la donne en pétrole d'action. */
.ui-hero-bulle,
.ui-hero-bulle::before,
.ui-hero-bulle::after {
  border-color: var(--color-titre);
}

/* La pastille de date garde ses CHIFFRES au rose, mais plus son filet haut :
   sur une carte qui porte déjà une pastille de lieu rose et une heure rose, le
   trait faisait une troisième marque de la même couleur dans le même angle.
   La couleur du texte suffit à rattacher la date à l'identité. */
.ui-evenement-date {
  color: var(--color-brand-pink-ink);
}

/* La section ÉVÉNEMENTS de l'accueil remonte de 60px. Visée par la PAIRE de
   classes : « .ui-evenements-section » seul attrape aussi la liste complète
   de evenements.html, qui n'a rien demandé — c'est le dégradé qui distingue
   le bloc de trois cartes de l'accueil.

   Marge NÉGATIVE et non rembourrage réduit : c'est la bande entière — son dégradé et ses galets —
   qui doit monter, alors qu'un padding raboté n'aurait fait remonter que le
   contenu à l'intérieur d'un fond resté en place.

   La section qui précède (les communautés) n'a pas de fond : le dégradé passe
   dessous sans être masqué, et seul son blanc de respiration se superpose. */
.ui-evenements-section.ui-fond-degrade {
  margin-block-start: calc(var(--space-6) * -1);
}

/* Même geste sur concept.html : ses deux sections en dégradé — « Comment ça
   marche » et « Communautés » — remontent de 50px. Elles ont d'abord été
   posées à 80, puis chacune a repris 30px d'air : à 80 la section suivante
   paraissait coller au bord de celle du dessus, et le rapprochement se lisait
   comme un défaut de gouttière plutôt que comme un resserrement voulu.

   Elles sont visées par la PAIRE de classes et non par leur identifiant :
   aucune feuille du projet ne style par id, et « .ui-fond-degrade » seul
   attraperait aussi la section événements de l'accueil, qui a son propre
   décalage. La combinaison ne se rencontre que sur concept.

   Ce qui les précède ne les masque pas : le mur de profils est transparent,
   et le hero, lui, est blanc — or le dégradé PART du blanc. Les 80px qu'il
   recouvre sont donc de la même couleur que ce qu'ils cachent, et ce n'est
   que du rembourrage : le contenu commence 120px plus bas. */
.ui-content-section.ui-fond-degrade,
.ui-communaute-section.ui-fond-degrade {
  margin-block-start: calc(var(--space-5) * -1);
}

/* 20px de plus entre la grille et son bouton — 64 devient 84. L'écart avait
   d'abord été porté à 114 (+50), puis le bouton est remonté de 30 : le +50 et
   le -30 sont écrits comme un seul +20, une pile de corrections successives
   ne disant plus rien de l'intention.

   Posé par un MODIFICATEUR et non sur .ui-groupes-action : la classe sert
   aussi à la section « communautés voisines » de communaute.html, qui n'a pas
   demandé cet écart. Le réglage appartient à la page qui l'emploie, pas à
   l'organisme, exactement comme les fonds et les décors. */
.ui-section--action-detachee .ui-groupes-action {
  margin-top: var(--space-6);
}

/* Les CTA des sections COMMUNAUTÉS et ÉVÈNEMENTS passent au rose de marque,
   là où les autres boutons gardent le pétrole. Ce sont les deux boutons qui
   ferment un bloc identitaire de l'accueil, et le rose les y rattache — les
   commandes fonctionnelles (recherche, filtres) restent au pétrole.
   Libellé blanc à 3,77:1 — même arbitrage que les CTA du hero et de l'en-tête,
   dont il rejoint la famille.

   Repos ET survol dans la même déclaration : le rose ne bouge pas au survol,
   c'est l'ombre qui répond.

   .ui-liste-action rejoint la liste : c'est le même geste — « Créer un
   évènement » sur la page des évènements de l'espace membre. Le « Liker » du
   profil aussi : c'est LE geste de la marque, celui que le rose signe partout
   ailleurs — le cœur du fil, la pastille de match, le CTA d'inscription.
   Il est déclaré en « outline » dans les données pour rester le SECOND bouton
   de la rangée, après « Suivre » ; la charte lui rend l'aplat rose, sans quoi
   liker aurait été plus discret que suivre. Les trois sont
   des CTA de CRÉATION, et c'est ce qui leur vaut le rose : le pétrole est la
   couleur des commandes ordinaires, le rose celle des gestes qui ouvrent
   quelque chose. Une seule règle pour tous, donc aucune divergence possible le
   jour où le rose bouge — et il a bougé deux fois.

   « JE PARTICIPE » EST LE DERNIER ENTRÉ, par le même critère : s'inscrire à
   une sortie met quelque chose au monde — une place réservée, et un nom de
   plus dans la liste que les autres liront. C'est aussi le seul geste de la
   fiche, tout le reste s'y lit.
   IL N'EST ROSE QUE CONNECTÉ, d'où « .ui-page-membre » en tête du sélecteur :
   la fiche PUBLIQUE porte le même bouton au même endroit, mais il y dit
   « Créer mon profil pour participer », et le rose des pages de vitrine est
   réservé à l'appel de l'accueil. Deux états d'une même page, deux gestes
   différents.

   « ENVOYER » REJOINT LA LISTE À SON TOUR, par le même critère : envoyer un
   message met quelque chose au monde, exactement comme publier un billet ou
   créer une communauté. C'est d'ailleurs le seul geste de la page de
   discussions qui produise quoi que ce soit — tout le reste s'y lit.

   « PUBLIER » EST ENTRÉ AVANT LUI, et c'était la première fois que le rose
   entrait dans le fil. Le critère est le même que pour « Créer une communauté » et
   « Créer un évènement » : un geste qui met quelque chose au monde. Publier en
   est un — d'ailleurs les trois se disent avec le même verbe dans la tête du
   membre.
   Le composeur n'avait AUCUN bouton : on pouvait joindre une photo, une humeur
   ou un évènement, tout cela en gris, et rien ne disait comment conclure. Ce
   n'était pas seulement une couleur qui manquait, c'était le geste.
   IL EST LE SEUL APLAT ROSE DE LA PAGE, et ce n'est pas une économie de moyens
   mais la règle de l'accueil : un bouton plein par zone, celui qui conclut ; le
   reste en accent. Les trois liens de pied d'encart — « Voir les 12 », « Tous
   mes évènements », « Toutes les communautés » — sont passés au rose en ENCRE
   pour cette raison : trois capsules pleines empilées dans une colonne de 300px
   auraient disputé l'attention au fil, qui est ce qu'on est venu lire. */
.ui-groupes-action .ui-btn-primary,
.ui-evenements-action .ui-btn-primary,
.ui-liste-action,
.ui-messagerie-envoi,
.ui-page-membre .ui-hero-evenement-actions .ui-btn-primary,
.ui-sortie-actions .ui-btn-primary,
.ui-groupes-action .ui-btn-primary:hover,
.ui-evenements-action .ui-btn-primary:hover,
.ui-liste-action:hover,
.ui-page-membre .ui-hero-evenement-actions .ui-btn-primary:hover,
.ui-sortie-actions .ui-btn-primary:hover,
.ui-messagerie-envoi:hover,
.ui-monprofil-actions .ui-btn-outline:hover {
  background: var(--color-brand-pink-ink);
  color: var(--white);
  box-shadow: var(--shadow-accent);
}

/* LE CŒUR ALLUMÉ EST ROSE, et il rejoint donc la famille des gestes de marque
   — le CTA d'inscription, le bouton « Liker », le cœur du fil. Un match est
   très exactement ce que ce rose signale ailleurs : le moment où quelque chose
   s'ouvre. Il était en pétrole, la couleur des commandes ordinaires, et rien
   ne distinguait alors « j'ai mis en favori » de « nous nous sommes trouvés ».
   L'étoile, elle, RESTE en gris : mettre de côté n'engage rien, et deux
   interrupteurs allumés de la même couleur sur une même carte ne se
   distingueraient plus — or ils peuvent l'être ensemble, un follower pouvant
   aussi être un match.
   Blanc sur #e20138 : 4,57:1, au-dessus des 3:1 exigés d'un objet graphique
   (WCAG 1.4.11), et même au-dessus du seuil des textes. */
.ui-profil-like[aria-pressed="true"] {
  background: var(--color-brand-pink-ink);
  border-color: var(--color-brand-pink-ink);
}

/* LE BOUTON « MESSAGE » : fond blanc, filet et glyphe BLEUS. Il n'a pas
   d'état — il n'apparaît que sur un match et y est toujours disponible —, donc
   le filet plutôt que l'aplat, comme tout ce qui n'est pas allumé sur cette
   carte. L'aplat rose lui a été donné puis repris : posé juste après le cœur
   allumé, il formait avec lui deux disques roses jumeaux qu'on ne distinguait
   que par le glyphe.
   À SAVOIR : « --genre-lui » est le SEUL bleu de la palette, et il sert par
   ailleurs à signer un taux qui concerne un homme. La couleur porte donc deux
   sens sur la même carte. Le glyphe les sépare — une bulle n'est pas un
   pictogramme de personne —, mais le jour où l'on voudra lever l'ambiguïté,
   c'est ici qu'il faudra revenir.
   #157d8f sur blanc : 4,58:1, au-dessus des 3:1 d'un objet graphique. */
.ui-profil-message {
  border-color: var(--genre-lui);
  color: var(--genre-lui);
}

.ui-profil-message:hover,
.ui-profil-message:focus-visible {
  background: var(--genre-lui);
  border-color: var(--genre-lui);
  color: var(--white);
}

/* L'ÉTOILE ALLUMÉE PASSE AU PÉTROLE PLEIN — la teinte du logo, celle des
   commandes du produit. Elle sortait du gris de texte, qui ne disait rien :
   « mis de côté » est un état, pas une absence de couleur.
   Les deux interrupteurs disent donc les deux couleurs de la marque, et la
   distinction est nette même allumés ensemble — un follower peut aussi être un
   match : pétrole pour ce qu'on a rangé, rose pour ce qui s'est ouvert.
   Le glyphe reste blanc, comme le veut la règle commune : 7,84:1 sur le
   pétrole, très au-dessus des 3:1 qu'exige WCAG 1.4.11 d'un objet graphique.
   Essais écartés en chemin : la terracotta --color-secondary (blanc à 2,06:1,
   sous le seuil) et la surface appuyée à 15 % (blanc à 1,29, invisible ; elle
   aurait imposé un glyphe sombre et deux règles de couleur au lieu d'une). */
.ui-profil-favori[aria-pressed="true"] {
  background: var(--color-bouton);
  border-color: var(--color-bouton);
}

/* AU REPOS, CHAQUE BOUTON PORTE DÉJÀ SA COULEUR : pétrole pour l'étoile, qui
   fait un follower ; rose pour le cœur, qui fait un match ; gris pour la
   croix, qui ne fait qu'écarter. On voit ce qu'on obtiendra avant de cliquer,
   et une carte où l'un des deux est allumé se lit d'un coup — le plein dit ce
   qui est fait, le filet ce qui reste possible.
   Cette règle valait d'abord pour les seules listes d'ATTENTE, sur un
   modificateur « --attente ». Elle a été généralisée : sur la page des
   followers, le cœur éteint est tout aussi actionnable, et rien ne justifiait
   qu'il y soit gris et rose ailleurs. Le modificateur a donc été supprimé
   plutôt que laissé sans emploi.
   Le FILET seul : l'aplat est réservé à l'état ALLUMÉ. Un bouton plein qui n'a
   pas été actionné mentirait sur son état, et les trois boutons de la carte
   diraient tous « c'est fait ».
   Pétrole sur blanc 7,84:1, rose sur blanc 4,89 — l'un et l'autre au-dessus
   des 3:1 exigés d'un objet graphique (WCAG 1.4.11). */
.ui-profil-favori {
  border: 1px solid var(--color-bouton);
  color: var(--color-bouton);
}

.ui-profil-like {
  border: 1px solid var(--color-brand-pink-ink);
  color: var(--color-brand-pink-ink);
}

/* LA CROIX GARDE SON GRIS, et prend le filet que ses deux voisines ont pris :
   les trois boutons se ressemblent, seule la couleur les distingue. Le rouge y
   a été essayé — filet et glyphe en --color-danger — et écarté : trois ronds
   cerclés de trois couleurs vives faisaient une carte qui crie, là où retirer
   quelqu'un reste un geste ordinaire qu'on ne cherche pas à provoquer.
   Le ROUGE reste donc réservé à ce qui détruit vraiment — « Supprimer » dans
   le menu d'un billet. Écarter, c'est ranger, pas détruire.
   Gris de texte secondaire sur blanc : 4,63:1, au-dessus des 3:1 exigés d'un
   objet graphique (WCAG 1.4.11). */
.ui-profil-passe {
  border: 1px solid var(--text-muted);
}

/* LES BOUTONS D'UNE CARTE PROFIL, PLEINS PAR DÉFAUT (1er oct. 2026) : les
   ronds blancs cerclés étaient trop fades. Comme sur la page swipe, chacun
   porte sa couleur en aplat, picto blanc — encre pour « Masquer », pétrole
   pour « Contact » et « Message », rose du logo pour le like. Activé, le
   bouton garde son aplat et son picto se remplit (FILL, ui-molecules). */
.ui-profil-passe,
.ui-profil-favori,
.ui-profil-like,
.ui-profil-message {
  color: var(--white);
}
.ui-profil-passe { border-color: var(--color-dark); background: var(--color-dark); }
.ui-profil-favori,
.ui-profil-favori[aria-pressed="true"],
.ui-profil-message,
.ui-profil-message:hover,
.ui-profil-message:focus-visible { border-color: var(--color-titre); background: var(--color-titre); color: var(--white); }
.ui-profil-like,
.ui-profil-like[aria-pressed="true"] { border-color: var(--color-brand-pink); background: var(--color-brand-pink); }
/* Le cœur toujours PLEIN, pas seulement une fois liké. */
.ui-profil-like .material-symbols-outlined { font-variation-settings: 'FILL' 1, 'wght' 300, 'GRAD' 0, 'opsz' 20; }

/* LES TAUX EN COULEURS VIVES (1er oct. 2026), comme les boutons : pleins,
   texte blanc — rose du logo pour elle, pétrole pour lui. (D'abord réservés
   à la page swipe, puis étendus à toutes les cartes.) */
.ui-profil-score--elle,
.ui-profil-score--lui { color: var(--white); }
.ui-profil-score--elle { border-color: var(--color-brand-pink); background: var(--color-brand-pink); }
.ui-profil-score--lui { border-color: var(--color-titre); background: var(--color-titre); }
:is(.ui-profil-score--elle, .ui-profil-score--lui) .material-symbols-outlined { color: inherit; }

/* LES GESTES DE LA FICHE PROFIL EN COULEURS VIVES (1er oct. 2026), comme
   les ronds des cartes : encre pour Masquer, pétrole pour le contact, rose
   du logo pour le like ; texte et picto blancs. Ils l'emportent sur le fond
   blanc des boutons de la bannière (règle ci-dessous) par leur classe de
   rôle, posée d'après « rond ». */
.ui-monprofil-actions .ui-btn.ui-monprofil-action--passe,
.ui-monprofil-actions .ui-btn.ui-monprofil-action--favori,
.ui-monprofil-actions .ui-btn.ui-monprofil-action--like { color: var(--white); }
.ui-monprofil-actions .ui-btn.ui-monprofil-action--passe { border-color: var(--color-dark); background: var(--color-dark); }
.ui-monprofil-actions .ui-btn.ui-monprofil-action--favori { border-color: var(--color-titre); background: var(--color-titre); }
.ui-monprofil-actions .ui-btn.ui-monprofil-action--like { border-color: var(--color-brand-pink); background: var(--color-brand-pink); }
.ui-monprofil-actions .ui-btn.ui-monprofil-action--like .material-symbols-outlined { font-variation-settings: 'FILL' 1, 'wght' 300, 'GRAD' 0, 'opsz' 20; }

/* SUR LA BANNIÈRE, le second bouton passe au FOND BLANC. L'aplat rose lui
   allait tant qu'il était posé sur la page ; sur une photographie, deux aplats
   pleins côte à côte se disputent l'image, et le blanc est la seule teinte qui
   tienne au-dessus de n'importe quel cliché. Il garde le rose en encre et en
   filet — le geste reste signé, il n'est plus crié. Au survol, il retrouve
   l'aplat : la règle ci-dessus le tient toujours par « :hover ». */
.ui-monprofil-actions .ui-btn-outline {
  border-color: var(--color-brand-pink-ink);
  background: var(--white);
  color: var(--color-brand-pink-ink);
  box-shadow: var(--shadow-md);
}

/* LES DEUX CTA D'ÉTAT de la bannière d'un profil : PLEINS, exactement comme
   les interrupteurs allumés d'une carte — pétrole pour « Followers », rose
   pour « C'est un Match ! ». Le blanc est réservé à ce qui reste à faire ; le
   plein dit ce qui est fait, et la page se lit d'un coup d'œil.
   Ils l'emportent sur les règles blanches ci-dessous par leur classe propre,
   et non par un ordre d'écriture : les deux autres pages du même organisme —
   « Modifier la couverture », « Aperçu public » — gardent leur fond blanc,
   parce qu'elles proposent des commandes, pas des états.
   Blanc sur pétrole 7,84:1, blanc sur rose 4,89:1. */
.ui-monprofil-actions .ui-btn.ui-monprofil-action--follower {
  border-color: var(--color-bouton);
  background: var(--color-bouton);
  color: var(--white);
}

.ui-monprofil-actions .ui-btn.ui-monprofil-action--match {
  border-color: var(--color-brand-pink-ink);
  background: var(--color-brand-pink-ink);
  color: var(--white);
}

/* LE TROISIÈME BOUTON DE LA BANNIÈRE — « Masquer » — est le seul qui refuse.
   Fond blanc comme ses deux voisins, mais encre GRISE : la hiérarchie passe
   par l'encre, et celle-ci le range au dernier rang sans le cacher. Le rouge
   lui a été refusé pour la même raison qu'à la croix des cartes — masquer,
   c'est ranger, pas détruire.
   Gris de texte secondaire sur blanc : 5,85:1. */
.ui-monprofil-actions .ui-btn-ghost {
  /* 20px demandés, puis 10 de plus, en sus de la gouttière de la rangée : le
     refus est en tête mais séparé des deux gestes qui engagent. Sans cet
     écart, on le clique en visant « Suivre ». La marge est portée par le
     bouton et non par la rangée — c'est LUI qui doit se tenir à distance, où
     qu'on le place. La somme est écrite, pas le total. */
  margin-inline-end: var(--space-4);
  border: 1px solid var(--border);
  background: var(--white);
  color: var(--text-muted);
  box-shadow: var(--shadow-md);
}

.ui-monprofil-actions .ui-btn-ghost:hover,
.ui-monprofil-actions .ui-btn-ghost:focus-visible {
  border-color: var(--text-muted);
  background: var(--text-muted);
  color: var(--white);
  box-shadow: var(--shadow-md);
}

/* Le PREMIER bouton passe au blanc pour la même raison, avec le pétrole pour
   encre : sur une photographie, deux boutons blancs se lisent comme une paire,
   là où un aplat sombre et un aplat rose se disputaient l'image. La hiérarchie
   n'est plus portée par l'aplat mais par la couleur de l'encre — pétrole pour
   la commande ordinaire, rose pour le geste qui engage. */
.ui-monprofil-actions .ui-btn-primary {
  border: 1px solid var(--border);
  background: var(--white);
  color: var(--color-titre);
  box-shadow: var(--shadow-md);
}

.ui-monprofil-actions .ui-btn-primary:hover,
.ui-monprofil-actions .ui-btn-primary:focus-visible {
  border-color: var(--color-bouton);
  background: var(--color-bouton);
  color: var(--white);
}

.ui-groupes-action .ui-btn-primary:focus-visible,
.ui-evenements-action .ui-btn-primary:focus-visible,
.ui-liste-action:focus-visible,
.ui-monprofil-actions .ui-btn-outline:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--color-brand-pink-ink) 40%, transparent);
  outline-offset: 3px;
}

/* Toute l'heure au rose, pictogramme compris — c'est la règle qui l'emporte
   sur celle des molécules. Le texte y était en pétrole et seuls la flèche et
   le pictogramme en rose : la ligne parlait deux couleurs. */
.ui-evenement-heure {
  color: var(--color-brand-pink-ink);
}

/* La flèche et le pictogramme suivent le texte de l'heure, qui est passé à
   l'encre : ils restaient au rose plein et faisaient les deux derniers
   caractères de la page sous le seuil, à 3,77 pour du 14px. */
.ui-evenement-heure .material-symbols-outlined,
.ui-evenement-heure > span:not(.visually-hidden) {
  color: var(--color-brand-pink-ink);
}

/* Sous 1100px, le socle pousse le texte du hero de 190px : c'est la place que
   réclame l'image pleine largeur du hero d'accueil, qui passe alors DERRIÈRE
   le texte. La variante « sélection » n'a pas d'image à dégager — sa scène
   occupe sa propre colonne — et cette marge n'y créait qu'un vide. */
@media (width <= 1100px) {
  .ui-hero:has(.ui-hero-selection) .ui-hero-copy-primary {
    margin-top: 0;
  }
}

/* ---- Fond du hero et de l'en-tête ----
   Le modèle pose #fffdfb sur ces deux surfaces : son « papier ». L'en-tête
   n'est donc pas blanc pur, et le hero ne repose pas sur le crème des
   sections. Depuis que --white PORTE ce papier, le hero n'a plus rien
   à déclarer : il en hérite. Seul l'en-tête a besoin d'une règle, le socle y
   ayant posé du blanc pur.
   Posée ici et non dans les organismes : elle corrige un choix du socle, ce
   qui est la fonction de cette couche.
   L'emporte sur le blanc du socle, y compris celui de la requête média : à
   spécificité égale, c'est l'ordre de chargement qui tranche, et cette
   feuille est la dernière. */
/* BLANC pur et non le papier : le hero d'accueil ouvre désormais sur du blanc
   en haut de son dégradé, et l'en-tête doit s'y raccorder sans couture. Sur le
   papier rosé, la limite entre les deux se voyait. */
.ui-site-header {
  background: var(--white);
}

/* Déclaré et non laissé à l'héritage : le hero porte la même couleur que la
   page, mais il la porte — si une section venait un jour peindre son fond,
   le hero ne suivrait pas par accident. */
.ui-hero {
  background: var(--white);
}

/* ---- Logo ----
   Déplacé de 15px vers la gauche. Le socle positionne la marque en absolu, et
   son décalage n'est pas le même à toutes les tailles — 27px sous 1400, 64px
   au-delà. Une marge négative s'ajoute à ce que « left » calcule, quel qu'il
   soit : une seule règle suffit là où il aurait fallu corriger deux calculs
   et les tenir accordés à chaque changement du socle. */
.ui-brand {
  margin-left: calc(var(--space-3) * -1);
}

/* LE SUR-TITRE DE LA FAQ QUITTE LE ROSE — la seule exception du système, et
   elle est arithmétique, pas esthétique.

   Le rose unifié #e20138 tient 4,89:1 sur blanc : 0,39 de marge au-dessus des
   4,5 du petit texte. N'importe quel fond teinté mange cette marge. La FAQ est
   la seule section dont le fond est posé sur le COMPOSANT (--section-teinte-7,
   #e1eced) et non par la page ; son sur-titre de 12px y tombe à 4,06.

   Éclaircir la teinte ne sauve rien : mesuré, même à 6 % de pétrole au lieu de
   12, le rose plafonne à 4,45 — il faudrait aller au blanc pur. Et rendre à ce
   seul sur-titre un rose plus sombre ramènerait deux roses sur la même page,
   ce que l'unification vient précisément de supprimer.
   Reste à le sortir du rose : sur ce fond, le pétrole des titres donne 6,50:1.
   Une place où le rose ne se lit pas est une place où le rose n'a rien à faire. */
.ui-faq .ui-eyebrow--accent {
  color: var(--color-titre);
}

/* ---- Décor de fond de l'espace membre ----
   Les pages connectées n'avaient aucun décor, là où le site public pose des
   galets et des disques sous ses sections : passé la connexion, on changeait
   d'application. Deux disques suffisent à recoudre — c'est la même forme, la
   même teinte et le même retrait que le « ui-decor-rond » du public, 7 % du
   pétrole des titres.

   POURQUOI PAS « ui-decor-rond » DIRECTEMENT. Cette classe pose
   « overflow: hidden » sur sa section pour se faire recouper. En zone membre,
   les DEUX RAILS et l'en-tête sont « position: sticky », et un ancêtre en
   « overflow: hidden » devient leur conteneur de défilement : le rail cesse
   de coller à la fenêtre. « clip » fait la même coupe sans créer de conteneur
   de défilement, d'où le choix ici — et d'où le fait que le disque soit posé
   sur la PAGE et non sur une section.

   z-index -1, et la page en « position: relative ». Un enfant en z-index
   négatif se peint au-dessus du fond de son parent et sous le contenu en
   flux : les disques passent donc derrière tout, cartes comprises, sans qu'on
   ait à donner un z-index à quoi que ce soit d'autre. Le faire à l'endroit —
   un disque en z-index 0 — aurait obligé à remonter chaque section, ce qui
   aurait créé autant de contextes d'empilement et enfermé les modales de
   confirmation sous l'en-tête, qui est à 1030.

   Ils ne bougent pas avec le contenu : ancrés en haut de page, ils occupent la
   zone que TOUTES les pages membre remplissent. Un disque calé sur un
   pourcentage de la hauteur se serait posé sur le vide des pages courtes — la
   file des likes tient en quatre cartes, le fil descend sur dix écrans. */
/* PORTÉ PAR « main » ET NON PAR LE BODY. Un « overflow » déclaré sur le body ne
   coupe pas le body : il SE PROPAGE à la fenêtre. Mesuré du temps où il y était :
   1530px de large pour une fenêtre de 1400, soit une barre horizontale sur
   toutes les pages membre. Sur « main », qui est un élément comme un autre, la
   coupe a lieu — et elle sert la forme d'ancrage ci-dessous comme les GALETS,
   qui débordent tous des deux côtés.
   Sur x SEULEMENT, et « clip » plutôt que « hidden » : en zone membre l'en-tête
   et les deux rails sont « position: sticky », et un ancêtre en « hidden »
   devient leur conteneur de défilement — le rail cesserait de coller. « clip »
   coupe sans créer de conteneur de défilement.
   Et sur « main » plutôt que sur le body : un « overflow » déclaré sur le body
   ne coupe pas le body, il SE PROPAGE à la fenêtre. Mesuré du temps où il y
   était : 1530px de large pour une fenêtre de 1400, soit une barre horizontale
   sur toutes les pages membre. */
.ui-page-membre > main {
  position: relative;
  overflow-x: clip;
}

/* LA FORME D'ANCRAGE, en haut à droite de chaque page membre. Un ÉLÉMENT et non
   une couche de fond, parce qu'elle seule porte le vrai galbe : un
   « border-radius » à huit valeurs, que la grille d'un dégradé ne sait pas
   faire. C'est un tirage différent de celui des galets, pour que les deux
   familles ne soient pas la même forme à deux échelles, et la proportion est
   brisée à 1,12 — un galbe posé sur un carré se relit comme un cercle bosselé.
   Elle glisse sous l'en-tête, qui est opaque : elle n'apparaît qu'à partir de
   la barre.
   z-index -1, et « main » en position relative : un enfant en z-index négatif
   se peint au-dessus du fond de son parent et sous le contenu en flux. Elle
   passe donc derrière tout, cartes comprises, sans qu'on ait à donner un
   z-index à quoi que ce soit d'autre — ce qui aurait créé autant de contextes
   d'empilement et enfermé les modales de confirmation sous l'en-tête, à 1030.
   Une SECONDE la doublait en haut à gauche ; retirée à la demande. Le premier
   écran en portait alors trois avec la première couche répétée, là où le reste
   de la page en montre une à la fois. */
.ui-page-membre > main::before {
  content: "";
  position: absolute;
  z-index: -1;
  /* 546px : 780 moins 30 %, comme les trois couches répétées. Les retraits
     suivent, sans quoi une forme rétrécie se recentrerait dans la page au lieu
     de rester coupée par le bord. */
  width: min(45%, 546px);
  aspect-ratio: 1.12;
  border-radius: 58% 42% 47% 53% / 44% 56% 44% 56%;
  background: var(--decor-disque);
  inset-block-start: -120px;
  inset-inline-end: -147px;
  pointer-events: none;
}

/* ---- Galets de l'espace membre ----
   Le pendant du décor de rond, et le même partage qu'au public : le disque ne
   donne qu'une MASSE, le galet une forme dessinée. Une section qui porte déjà
   des objets dessinés — un fil de photographies, une bannière, une grille
   pleine de cartes — n'en supporte qu'une ; là où le contenu respire, la forme
   a la place d'exister.
   D'où le choix des DEUX PAGES DE « MON ACTIVITÉ » qui se vident, la file des
   likes et le registre des matchs : quatre cartes d'un côté, deux groupes de
   l'autre, et beaucoup de fond entre les deux. Elles y gagnent en plus un air
   de famille, ce qui ne nuit pas à deux pages que le rail donne pour paires.
   Le fil, les profils, les communautés et les évènements gardent les seuls
   disques : leurs grilles sont pleines.

   LA FORME EST RECOPIÉE À L'IDENTIQUE de « .ui-decor-galets » — rayons
   dissymétriques, proportion 620/580, rotation de −6° et son demi-tour à 174°.
   C'est le même ornement, il doit se RECONNAÎTRE d'un espace à l'autre plutôt
   que se ressembler à peu près.
   Ce qui change est le PORTEUR : au public, la section elle-même, qui se
   déclare « overflow-x: clip » pour ne pas faire défiler la page. Ici, c'est
   « main » qui coupe déjà pour les disques, et la section n'a donc qu'à se
   poser en « position: relative » sans z-index — pas de contexte
   d'empilement créé, donc rien qui enferme les modales sous l'en-tête. */
.ui-page-membre--galets > main > .ui-liste-section { position: relative; }

.ui-page-membre--galets > main > .ui-liste-section::before,
.ui-page-membre--galets > main > .ui-liste-section::after {
  content: "";
  position: absolute;
  z-index: -1;
  width: min(46%, 520px);
  aspect-ratio: 620 / 580;
  border-radius: 46% 54% 58% 42% / 47% 43% 57% 53%;
  /* 22 % là où le public met 40 : même raison que les disques, le fond membre
     est déjà teinté. Mesuré côte à côte, 40 % y donnait un aplat franc qui
     passait devant les cartes à l'œil bien qu'il fût derrière. */
  background: color-mix(in srgb, var(--surface-appuyee) 25%, transparent);
  pointer-events: none;
}

/* En bas à gauche, sous la grille : c'est là que ces deux pages ont du vide,
   et un galet posé dans le vide est un galet qu'on ne dispute à personne. */
.ui-page-membre--galets > main > .ui-liste-section::before {
  inset-block-end: -6%;
  inset-inline-start: -14%;
  transform: rotate(-6deg);
}

/* 174° et non −6° : la même rotation à un demi-tour près. Le second galet est
   exactement le premier retourné, et non une seconde forme. Il part à droite,
   à mi-hauteur, pour croiser la diagonale du disque qui vient d'en haut. */
.ui-page-membre--galets > main > .ui-liste-section::after {
  inset-block-start: 38%;
  inset-inline-end: -16%;
  transform: rotate(174deg);
}
