.elementor-98 .elementor-element.elementor-element-894fd96f{--display:flex;--min-height:66vh;--justify-content:center;--padding-top:190px;--padding-bottom:132px;--padding-left:24px;--padding-right:24px;}.elementor-98 .elementor-element.elementor-element-894fd96f:not(.elementor-motion-effects-element-type-background), .elementor-98 .elementor-element.elementor-element-894fd96f > .elementor-motion-effects-container > .elementor-motion-effects-layer{background-color:var( --e-global-color-pspnav9 );}.elementor-98 .elementor-element.elementor-element-c48a0619{--display:flex;--gap:0px 0px;--row-gap:0px;--column-gap:0px;}.elementor-widget-text-editor{font-family:var( --e-global-typography-text-font-family ), Sans-serif;font-size:var( --e-global-typography-text-font-size );font-weight:var( --e-global-typography-text-font-weight );line-height:var( --e-global-typography-text-line-height );color:var( --e-global-color-text );}.elementor-widget-text-editor.elementor-drop-cap-view-stacked .elementor-drop-cap{background-color:var( --e-global-color-primary );}.elementor-widget-text-editor.elementor-drop-cap-view-framed .elementor-drop-cap, .elementor-widget-text-editor.elementor-drop-cap-view-default .elementor-drop-cap{color:var( --e-global-color-primary );border-color:var( --e-global-color-primary );}.elementor-98 .elementor-element.elementor-element-641892cc{font-family:var( --e-global-typography-pspsurt-font-family ), Sans-serif;font-size:var( --e-global-typography-pspsurt-font-size );font-weight:var( --e-global-typography-pspsurt-font-weight );text-transform:var( --e-global-typography-pspsurt-text-transform );line-height:var( --e-global-typography-pspsurt-line-height );letter-spacing:var( --e-global-typography-pspsurt-letter-spacing );color:var( --e-global-color-pspsag3 );}.elementor-widget-heading .elementor-heading-title{font-family:var( --e-global-typography-primary-font-family ), Sans-serif;font-size:var( --e-global-typography-primary-font-size );font-weight:var( --e-global-typography-primary-font-weight );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );color:var( --e-global-color-primary );}.elementor-98 .elementor-element.elementor-element-38902363 .elementor-heading-title{font-family:var( --e-global-typography-primary-font-family ), Sans-serif;font-size:var( --e-global-typography-primary-font-size );font-weight:var( --e-global-typography-primary-font-weight );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );color:var( --e-global-color-pspcrem );}.elementor-98 .elementor-element.elementor-element-44c72d05{font-family:var( --e-global-typography-text-font-family ), Sans-serif;font-size:var( --e-global-typography-text-font-size );font-weight:var( --e-global-typography-text-font-weight );line-height:var( --e-global-typography-text-line-height );color:var( --e-global-color-pspsag1 );}.elementor-98 .elementor-element.elementor-element-940feb0d{--display:flex;--padding-top:96px;--padding-bottom:108px;--padding-left:24px;--padding-right:24px;}.elementor-98 .elementor-element.elementor-element-940feb0d:not(.elementor-motion-effects-element-type-background), .elementor-98 .elementor-element.elementor-element-940feb0d > .elementor-motion-effects-container > .elementor-motion-effects-layer{background-color:var( --e-global-color-pspcrem );}.elementor-98 .elementor-element.elementor-element-d2e25d64{--display:flex;--gap:0px 0px;--row-gap:0px;--column-gap:0px;}.elementor-widget-loop-grid .elementor-button{background-color:var( --e-global-color-accent );font-family:var( --e-global-typography-accent-font-family ), Sans-serif;font-size:var( --e-global-typography-accent-font-size );font-weight:var( --e-global-typography-accent-font-weight );text-transform:var( --e-global-typography-accent-text-transform );line-height:var( --e-global-typography-accent-line-height );letter-spacing:var( --e-global-typography-accent-letter-spacing );}.elementor-widget-loop-grid .elementor-pagination{font-family:var( --e-global-typography-secondary-font-family ), Sans-serif;font-size:var( --e-global-typography-secondary-font-size );font-weight:var( --e-global-typography-secondary-font-weight );line-height:var( --e-global-typography-secondary-line-height );letter-spacing:var( --e-global-typography-secondary-letter-spacing );}.elementor-widget-loop-grid .e-load-more-message{font-family:var( --e-global-typography-secondary-font-family ), Sans-serif;font-size:var( --e-global-typography-secondary-font-size );font-weight:var( --e-global-typography-secondary-font-weight );line-height:var( --e-global-typography-secondary-line-height );letter-spacing:var( --e-global-typography-secondary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-8aacf793{--grid-columns:3;}.elementor-98 .elementor-element.elementor-element-8aacf793 .elementor-loop-container{grid-auto-rows:1fr;}.elementor-98 .elementor-element.elementor-element-8aacf793 .e-loop-item > .elementor-section, .elementor-98 .elementor-element.elementor-element-8aacf793 .e-loop-item > .elementor-section > .elementor-container, .elementor-98 .elementor-element.elementor-element-8aacf793 .e-loop-item > .e-con, .elementor-98 .elementor-element.elementor-element-8aacf793 .e-loop-item .elementor-section-wrap  > .e-con{height:100%;}.elementor-98 .elementor-element.elementor-element-8aacf793 .elementor-pagination{text-align:center;}body:not(.rtl) .elementor-98 .elementor-element.elementor-element-8aacf793 .elementor-pagination .page-numbers:not(:first-child){margin-left:calc( 10px/2 );}body:not(.rtl) .elementor-98 .elementor-element.elementor-element-8aacf793 .elementor-pagination .page-numbers:not(:last-child){margin-right:calc( 10px/2 );}body.rtl .elementor-98 .elementor-element.elementor-element-8aacf793 .elementor-pagination .page-numbers:not(:first-child){margin-right:calc( 10px/2 );}body.rtl .elementor-98 .elementor-element.elementor-element-8aacf793 .elementor-pagination .page-numbers:not(:last-child){margin-left:calc( 10px/2 );}.elementor-98 .elementor-element.elementor-element-ba89ed61{--display:flex;--gap:0px 0px;--row-gap:0px;--column-gap:0px;}.elementor-98 .elementor-element.elementor-element-476e4cac{--display:flex;--gap:0px 0px;--row-gap:0px;--column-gap:0px;}.elementor-98 .elementor-element.elementor-element-91581fc0{text-align:center;}.elementor-98 .elementor-element.elementor-element-91581fc0 .elementor-heading-title{font-family:var( --e-global-typography-primary-font-family ), Sans-serif;font-size:var( --e-global-typography-primary-font-size );font-weight:var( --e-global-typography-primary-font-weight );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );color:var( --e-global-color-pspnav9 );}.elementor-98 .elementor-element.elementor-element-2ac505b1{text-align:center;font-family:var( --e-global-typography-text-font-family ), Sans-serif;font-size:var( --e-global-typography-text-font-size );font-weight:var( --e-global-typography-text-font-weight );line-height:var( --e-global-typography-text-line-height );color:var( --e-global-color-pspmute );}.elementor-98 .elementor-element.elementor-element-7e60b431{--display:flex;--padding-top:112px;--padding-bottom:112px;--padding-left:24px;--padding-right:24px;}.elementor-98 .elementor-element.elementor-element-7e60b431:not(.elementor-motion-effects-element-type-background), .elementor-98 .elementor-element.elementor-element-7e60b431 > .elementor-motion-effects-container > .elementor-motion-effects-layer{background-color:var( --e-global-color-primary );}.elementor-98 .elementor-element.elementor-element-a0a7dea9{--display:flex;--gap:0px 0px;--row-gap:0px;--column-gap:0px;}.elementor-98 .elementor-element.elementor-element-f12975cc{text-align:center;font-family:var( --e-global-typography-pspsurt-font-family ), Sans-serif;font-size:var( --e-global-typography-pspsurt-font-size );font-weight:var( --e-global-typography-pspsurt-font-weight );text-transform:var( --e-global-typography-pspsurt-text-transform );line-height:var( --e-global-typography-pspsurt-line-height );letter-spacing:var( --e-global-typography-pspsurt-letter-spacing );color:var( --e-global-color-pspsag3 );}.elementor-98 .elementor-element.elementor-element-eb8bd2a6{text-align:center;}.elementor-98 .elementor-element.elementor-element-eb8bd2a6 .elementor-heading-title{font-family:var( --e-global-typography-primary-font-family ), Sans-serif;font-size:var( --e-global-typography-primary-font-size );font-weight:var( --e-global-typography-primary-font-weight );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );color:var( --e-global-color-pspcrem );}.elementor-98 .elementor-element.elementor-element-eabb730d{text-align:center;font-family:var( --e-global-typography-text-font-family ), Sans-serif;font-size:var( --e-global-typography-text-font-size );font-weight:var( --e-global-typography-text-font-weight );line-height:var( --e-global-typography-text-line-height );color:var( --e-global-color-pspsag1 );}.elementor-widget-button .elementor-button{background-color:var( --e-global-color-accent );font-family:var( --e-global-typography-accent-font-family ), Sans-serif;font-size:var( --e-global-typography-accent-font-size );font-weight:var( --e-global-typography-accent-font-weight );text-transform:var( --e-global-typography-accent-text-transform );line-height:var( --e-global-typography-accent-line-height );letter-spacing:var( --e-global-typography-accent-letter-spacing );}.elementor-98 .elementor-element.elementor-element-ae6a34d7 .elementor-button-content-wrapper{flex-direction:row-reverse;}.elementor-98 .elementor-element.elementor-element-ae6a34d7 .elementor-button .elementor-button-content-wrapper{gap:8px;}@media(max-width:1024px){.elementor-98 .elementor-element.elementor-element-894fd96f{--min-height:62vh;}.elementor-widget-text-editor{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-98 .elementor-element.elementor-element-641892cc{font-size:var( --e-global-typography-pspsurt-font-size );line-height:var( --e-global-typography-pspsurt-line-height );letter-spacing:var( --e-global-typography-pspsurt-letter-spacing );}.elementor-widget-heading .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-38902363 .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-44c72d05{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-widget-loop-grid .elementor-pagination{font-size:var( --e-global-typography-secondary-font-size );line-height:var( --e-global-typography-secondary-line-height );letter-spacing:var( --e-global-typography-secondary-letter-spacing );}.elementor-widget-loop-grid .elementor-button{font-size:var( --e-global-typography-accent-font-size );line-height:var( --e-global-typography-accent-line-height );letter-spacing:var( --e-global-typography-accent-letter-spacing );}.elementor-widget-loop-grid .e-load-more-message{font-size:var( --e-global-typography-secondary-font-size );line-height:var( --e-global-typography-secondary-line-height );letter-spacing:var( --e-global-typography-secondary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-8aacf793{--grid-columns:2;}.elementor-98 .elementor-element.elementor-element-91581fc0 .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-2ac505b1{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-98 .elementor-element.elementor-element-f12975cc{font-size:var( --e-global-typography-pspsurt-font-size );line-height:var( --e-global-typography-pspsurt-line-height );letter-spacing:var( --e-global-typography-pspsurt-letter-spacing );}.elementor-98 .elementor-element.elementor-element-eb8bd2a6 .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-eabb730d{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-widget-button .elementor-button{font-size:var( --e-global-typography-accent-font-size );line-height:var( --e-global-typography-accent-line-height );letter-spacing:var( --e-global-typography-accent-letter-spacing );}}@media(max-width:767px){.elementor-98 .elementor-element.elementor-element-894fd96f{--min-height:62vh;--padding-top:146px;--padding-bottom:100px;--padding-left:20px;--padding-right:20px;}.elementor-widget-text-editor{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-98 .elementor-element.elementor-element-641892cc{font-size:var( --e-global-typography-pspsurt-font-size );line-height:var( --e-global-typography-pspsurt-line-height );letter-spacing:var( --e-global-typography-pspsurt-letter-spacing );}.elementor-widget-heading .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-38902363 .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-44c72d05{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-98 .elementor-element.elementor-element-940feb0d{--padding-top:68px;--padding-bottom:76px;--padding-left:20px;--padding-right:20px;}.elementor-widget-loop-grid .elementor-pagination{font-size:var( --e-global-typography-secondary-font-size );line-height:var( --e-global-typography-secondary-line-height );letter-spacing:var( --e-global-typography-secondary-letter-spacing );}.elementor-widget-loop-grid .elementor-button{font-size:var( --e-global-typography-accent-font-size );line-height:var( --e-global-typography-accent-line-height );letter-spacing:var( --e-global-typography-accent-letter-spacing );}.elementor-widget-loop-grid .e-load-more-message{font-size:var( --e-global-typography-secondary-font-size );line-height:var( --e-global-typography-secondary-line-height );letter-spacing:var( --e-global-typography-secondary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-8aacf793{--grid-columns:1;}.elementor-98 .elementor-element.elementor-element-91581fc0 .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-2ac505b1{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-98 .elementor-element.elementor-element-7e60b431{--padding-top:84px;--padding-bottom:84px;--padding-left:20px;--padding-right:20px;}.elementor-98 .elementor-element.elementor-element-f12975cc{font-size:var( --e-global-typography-pspsurt-font-size );line-height:var( --e-global-typography-pspsurt-line-height );letter-spacing:var( --e-global-typography-pspsurt-letter-spacing );}.elementor-98 .elementor-element.elementor-element-eb8bd2a6 .elementor-heading-title{font-size:var( --e-global-typography-primary-font-size );line-height:var( --e-global-typography-primary-line-height );letter-spacing:var( --e-global-typography-primary-letter-spacing );}.elementor-98 .elementor-element.elementor-element-eabb730d{font-size:var( --e-global-typography-text-font-size );line-height:var( --e-global-typography-text-line-height );}.elementor-widget-button .elementor-button{font-size:var( --e-global-typography-accent-font-size );line-height:var( --e-global-typography-accent-line-height );letter-spacing:var( --e-global-typography-accent-letter-spacing );}}/* Start custom CSS *//* =========================================================================
   PÔLE SANTÉ PSY · SOCLE DE FORMES ET D'ANIMATIONS
   Créé le 6 août 2026, à partir de la page Consultations (page 85).

   À QUOI SERT CE FICHIER
   C'est la couche d'ambiance du site, extraite de la page où elle a été mise
   au point, pour que les pages suivantes ne la réinventent pas. Il se colle
   TEL QUEL en tête du CSS de page, avant les règles propres à la page.
   Rien ici n'est spécifique à Consultations : aucune URL, aucun identifiant de
   page, aucun contenu. Seuls les DÉCALAGES de halos section par section sont à
   écrire dans le CSS de la page, et le §4 ci-dessous dit comment.

   TROIS COUCHES, PAS UNE DE PLUS. C'est la règle du §5 de CLAUDE.md, et c'est
   ce qui distingue un site vivant d'un sapin de Noël :
     1. APPARITIONS     fadeInUp 24px, 0,6s, décalage 80ms, déclenchement unique
     2. SURVOL          une micro-interaction par famille d'objet
     3. AMBIANCE        halos organiques, courbes, motif de pluie
   N'ajoute pas de quatrième couche. Si une page semble en avoir besoin, c'est
   qu'il lui manque une image ou une respiration, pas une animation.

   CINQ RÈGLES D'ÉCRITURE, toutes payées au moins une fois
   ---------------------------------------------------------------------------
   1. RÉPÉTITION DE CLASSE, jamais de préfixe d'identifiant de page.
      `.psp-x.psp-x.psp-x` vaut 0-3-0 et survit à une copie de page.
      `.elementor-page-85 .psp-x` fait le même travail et MEURT à la copie :
      c'est la cause des 42 sélecteurs morts du §19 étape 3.
   2. TOUTE RÈGLE QUI HABILLE UN TITRE RÉPÈTE SA CLASSE (0-4-0).
      Elementor émet ses contrôles de widget APRÈS le CSS personnalisé, et
      `.elementor-element-XXXX .elementor-heading-title` vaut 0-2-0 comme
      `.psp-x-titre .elementor-heading-title`. À spécificité égale, la sienne
      gagne : sans répétition, TOUS les titres sortent à la typographie globale.
      Constaté le 6 août 2026 sur les quatre pages du site.
   3. LES BORNES DE MESURE DE LECTURE S'ÉCRIVENT EN `em`, JAMAIS EN px.
      590px donne 72 caractères à 18px et 92 à 14px : une borne en pixels
      suppose une taille de police et ment dès qu'elle change. 33em ≈ 72
      caractères quelle que soit la taille.
   4. `var(--psp-titre, "Fraunces"), sans-serif` TOUJOURS avec son repli.
      La variable n'est définie nulle part sur le site : sans repli, la règle
      retombe silencieusement sur Source Sans 3.
   5. UNE RANGÉE ORPHELINE SE CORRIGE EN IMPOSANT LA GRILLE, jamais en
      ajustant le `flex-basis`. Voir §5 de ce fichier.
   ========================================================================= */


/* ==========================================================================
   1. GARDE-FOUS. À coller en premier, avant toute autre règle.
   ========================================================================== */

/* §18 pièges 2 et 3 : une animation d'entrée portée par un container masque
   son contenu POUR DE BON, parce que le container reçoit `elementor-invisible`
   mais que son `data-settings` sort vide et que le JS ne le révèle jamais.
   Règle : aucune animation sur un container, elles descendent sur les widgets.
   Cette ligne est la ceinture : l'apparition devient une amélioration
   progressive, jamais une condition d'affichage. */
.elementor-invisible { visibility: visible !important; }

/* §18 piège 4 : Elementor insère une cale sous un en-tête sticky, qui pousse
   le hero de 128px au lieu de l'y superposer. Le §8 veut la superposition. */
.elementor-sticky__spacer { display: none !important; }

/* Le §5 exige un anneau de mise au point visible, qu'Elementor supprime. */
:focus-visible {
  outline: 3px solid var(--psp-navy-700);
  outline-offset: 2px;
  border-radius: 2px;
}


/* ==========================================================================
   2. LES DEUX ANIMATIONS DE FOND. Aucune autre keyframe sur le site.
   ========================================================================== */

/* Déformation lente d'une forme organique. C'est le moteur de toute
   l'ambiance : halos de section, pastille du collage, formes libres. */
@keyframes psp-morph {
  0%   { border-radius: 62% 38% 47% 53% / 55% 44% 56% 45%; transform: translate3d(0,0,0) rotate(0deg); }
  33%  { border-radius: 38% 62% 63% 37% / 41% 58% 42% 59%; transform: translate3d(0,-14px,0) rotate(3deg); }
  66%  { border-radius: 55% 45% 34% 66% / 62% 36% 64% 38%; transform: translate3d(0,8px,0) rotate(-2deg); }
  100% { border-radius: 62% 38% 47% 53% / 55% 44% 56% 45%; transform: translate3d(0,0,0) rotate(0deg); }
}

/* Motif de pluie, fil rouge visuel arrêté au §2. Ne s'emploie que sur les
   fonds sombres : hero et bande de respiration. */
@keyframes psp-pluie {
  from { transform: translate3d(0, -10px, 0); }
  to   { transform: translate3d(0, 0, 0); }
}


/* ==========================================================================
   3. HALOS DE SECTION · classe `psp-forme`
   Deux halos par section, portés par les pseudo-éléments du container.
   Se pose sur n'importe quelle section. `--rose` inverse les deux couleurs.
   ========================================================================== */

.psp-forme { position: relative; overflow: hidden; isolation: isolate; }

.psp-forme::before,
.psp-forme::after {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  animation: psp-morph 26s ease-in-out infinite;
}

.psp-forme::before {
  inset-inline-end: -10%;
  inset-block-start: -14%;
  inline-size: 44vw; block-size: 44vw;
  max-inline-size: 560px; max-block-size: 560px;
  background: radial-gradient(closest-side, var(--psp-sage-100), transparent 74%);
}

.psp-forme::after {
  inset-inline-start: -12%;
  inset-block-end: -18%;
  inline-size: 34vw; block-size: 34vw;
  max-inline-size: 430px; max-block-size: 430px;
  background: radial-gradient(closest-side, var(--psp-rose-100), transparent 74%);
  animation-duration: 34s;
  animation-direction: reverse;
}

.psp-forme--rose::before { background: radial-gradient(closest-side, var(--psp-rose-100), transparent 74%); }
.psp-forme--rose::after  { background: radial-gradient(closest-side, var(--psp-sage-100), transparent 74%); }

/* ATTENTION. `overflow: hidden` crée un conteneur de défilement, ce qui
   NEUTRALISE silencieusement le `position: sticky` de tout descendant : le
   `position` calculé sort bien à `sticky` et rien ne bouge. Sur une section qui
   contient une colonne collante, écrire `overflow: clip`, qui confine
   exactement pareil sans créer ce conteneur. */
/* .ma-section.ma-section.ma-section { overflow: clip; } */

/* Sur fond marine, les halos en teintes pleines éclaircissent le fond en
   plaques. Version translucide, à poser sur toute section sombre. */
.psp-sombre.psp-forme::before {
  background: radial-gradient(closest-side, rgba(79, 107, 87, .42), transparent 72%);
  inset-block-start: -16%; inset-inline-end: -12%;
}
.psp-sombre.psp-forme::after {
  background: radial-gradient(closest-side, rgba(142, 78, 86, .38), transparent 72%);
  inset-block-end: -20%; inset-inline-start: -10%;
}


/* ==========================================================================
   4. TROISIÈME HALO · classe `psp-halo`, sur le container INTÉRIEUR
   Un `psp-forme` n'a que deux pseudo-éléments donc deux halos, et deux halos
   aux angles laissent tout le centre plat. Sur une section qui porte une
   grille de quatre ou cinq blocs, ce troisième halo empêche le fond d'être uni.
   Il tourne en 52s contre 26 et 34 : trois durées premières entre elles, donc
   le motif ne se rejoue jamais à l'identique.
   À RÉSERVER aux sections les plus denses. Deux ou trois par page, pas plus.
   ========================================================================== */

.psp-halo { position: relative; }

.psp-halo::before {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  inset-block-start: 18%;
  inset-inline-start: 22%;
  inline-size: 56vw;
  block-size: 56vw;
  max-inline-size: 760px;
  max-block-size: 760px;
  transform: translate(-50%, -20%);
  background: radial-gradient(closest-side, rgba(168, 191, 168, .30), transparent 72%);
  animation: psp-morph 52s ease-in-out infinite;
}

/* DÉCALAGES SECTION PAR SECTION, à écrire dans le CSS DE LA PAGE et pas ici.
   Si le halo revient au même endroit d'une section à l'autre, le motif devient
   un gabarit. Chaque page redéfinit ses positions, et elles doivent différer
   de celles des pages voisines. Gabarit à recopier :

   .ma-section::before { inset-block-start: -20%; inset-inline-end: -18%; inline-size: 42vw; block-size: 42vw; }
   .ma-section::after  { inset-block-end: -22%; inset-inline-start: -10%; inline-size: 28vw; block-size: 28vw; }

   Pour pousser un halo à gauche, penser à remettre `inset-inline-end: auto`,
   sinon les deux insets se battent. */


/* ==========================================================================
   5. SÉPARATIONS COURBES · classe `psp-courbe`
   La section remonte de 68px sur la précédente et lui présente un bord
   elliptique : la couleur du dessus déborde dans les angles et la transition
   devient un mouvement au lieu d'une ligne.

   QUATRE PAR PAGE, réparties. Sur treize sections ce serait un tic ; sur
   quatre c'est un rythme.
   Aucune image, aucun JavaScript, aucun pseudo-élément consommé : la courbe est
   un rayon de bordure sur la section elle-même, donc elle cohabite avec les
   halos de `psp-forme`.
   NE PAS la poser sur une section qui porte déjà une marge négative, comme le
   panneau de repères à cheval.
   ========================================================================== */

.psp-courbe {
  border-start-start-radius: 50% 68px;
  border-start-end-radius: 50% 68px;
  margin-block-start: -68px !important;
  padding-block-start: 180px !important;
  position: relative;
  z-index: 2;
}

@media (max-width: 767px) {
  .psp-courbe {
    border-start-start-radius: 50% 40px;
    border-start-end-radius: 50% 40px;
    margin-block-start: -40px !important;
    padding-block-start: 120px !important;
  }
}


/* ==========================================================================
   6. HERO · photographie sous voile marine, plus motif de pluie
   Composant du §17, identique sur les quatre pages. C'est ce voile qui rend
   lisibles le logo clair et la navigation blanche exigés au §8.
   ========================================================================== */

.psp-hero { position: relative; overflow: hidden; isolation: isolate; }

.psp-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(100deg,
      rgba(15, 37, 64, .96) 0%,
      rgba(15, 37, 64, .90) 34%,
      rgba(15, 37, 64, .66) 62%,
      rgba(22, 50, 79, .48) 100%),
    radial-gradient(70% 90% at 88% 18%, rgba(79, 107, 87, .40), transparent 70%);
}

.psp-hero::after {
  content: "";
  position: absolute;
  inset: -40% -25%;
  z-index: -1;
  background-image: repeating-linear-gradient(
    15deg,
    rgba(221, 231, 218, .14) 0 1px,
    transparent 1px 10px);
  mask-image: radial-gradient(ellipse 80% 75% at 76% 12%, #000 5%, transparent 74%);
  -webkit-mask-image: radial-gradient(ellipse 80% 75% at 76% 12%, #000 5%, transparent 74%);
  animation: psp-pluie 6.5s linear infinite;
  pointer-events: none;
}

/* En mobile, le voile passe en vertical : le dégradé oblique laisse le bas du
   texte sur la partie claire de l'image. */
@media (max-width: 767px) {
  .psp-hero::before {
    background:
      linear-gradient(180deg,
        rgba(15, 37, 64, .90) 0%,
        rgba(15, 37, 64, .93) 55%,
        rgba(15, 37, 64, .96) 100%);
  }
}

/* RYTHME VERTICAL DU HERO. Un hero se juge à CINQ écarts, jamais à sa hauteur
   totale. Valeurs mesurées et validées (§21, §22) :
     sous l'en-tête            96 à 190   (64 à 190 en mobile)
     surtitre vers titre       10 à 24
     titre vers bloc suivant   18 à 40
     dernier texte vers boutons 28 à 60
     BOUTONS VERS CE QUI SUIT  88 à 150   <- celui qu'on oublie
   Le cinquième décide de la sensation d'étouffement, parce que le panneau à
   cheval remonte de 84px DANS le hero et mange cet espace sans que ça
   apparaisse dans les réglages Elementor.
   Piège de compensation : aérer le haut d'un hero à hauteur fixe et contenu
   centré PREND l'espace en bas. Toujours re-mesurer le bas après avoir aéré. */
.psp-surtitre--clair { margin-block-end: 14px !important; }
.psp-hero-titre { margin-block-end: 26px !important; }
.psp-hero-titre .elementor-heading-title { text-wrap: balance; }
.psp-hero-chapo { max-inline-size: 33em; }
.psp-hero-chapo p { max-inline-size: 33em; margin: 0; }
.psp-hero-inner > .e-con-inner { margin-inline: auto; }
.psp-hero-actions { padding-block-start: 38px !important; }
.psp-hero-actions > .e-con-inner,
.psp-hero-actions { align-items: center; }

@media (max-width: 767px) {
  .psp-hero-inner > .e-con-inner { max-inline-size: 100%; }
  .psp-hero-actions { padding-block-start: 32px !important; }
}


/* ==========================================================================
   7. BANDE DE RESPIRATION · classe `psp-respire`
   Une pause dans le parcours, sur une page longue. Photographie pleine largeur
   sous voile marine, motif de pluie plus large et plus lent que celui du hero,
   une seule ligne en Fraunces.

   UNE SEULE PAR PAGE, et pas dans le même registre que celle des voisines :
   l'Accueil porte une citation sur fond sauge clair, Consultations une
   affirmation de méthode sur fond sombre. Deux pauses, deux registres.
   La photographie est décorative : le sens est porté par la ligne de texte,
   il n'y a donc pas de texte alternatif à inventer.
   ========================================================================== */

.psp-respire { position: relative; overflow: hidden; isolation: isolate; }

.psp-respire::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg,
      rgba(15, 37, 64, .93) 0%,
      rgba(22, 50, 79, .86) 50%,
      rgba(15, 37, 64, .93) 100%),
    radial-gradient(60% 120% at 20% 50%, rgba(79, 107, 87, .34), transparent 72%);
}

.psp-respire::after {
  content: "";
  position: absolute;
  inset: -50% -30%;
  z-index: -1;
  background-image: repeating-linear-gradient(
    12deg,
    rgba(221, 231, 218, .13) 0 1px,
    transparent 1px 13px);
  mask-image: radial-gradient(ellipse 90% 90% at 50% 50%, #000 10%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 90% 90% at 50% 50%, #000 10%, transparent 78%);
  animation: psp-pluie 9s linear infinite;
  pointer-events: none;
}

.psp-respire-inner > .e-con-inner {
  max-inline-size: 820px;
  margin-inline: auto;
  text-align: center;
}

/* Widget de TEXTE et non de titre : une grande phrase décorative ne doit pas
   entrer dans la hiérarchie des titres de la page. */
.psp-respire-ligne p {
  margin: 0;
  font-family: var(--psp-titre, "Fraunces"), sans-serif;
  font-size: clamp(27px, 3.4vw, 44px);
  font-weight: 400;
  line-height: 1.28;
  letter-spacing: -.005em;
  text-wrap: balance;
}


/* ==========================================================================
   8. COLLAGE PHOTO · classes `psp-collage`, `psp-collage-a`, `psp-collage-b`
   Grande image à contour organique, vignette en chevauchement, pastille sauge
   qui se déforme derrière. C'est le composant qui casse un mur de texte quand
   une section n'a qu'une colonne.

   Les deux emplacements sont des containers VIDES : leurs URL vivent dans le
   bloc d'emplacements photo généré en fin de CSS de page, jamais ici.
   ========================================================================== */

.psp-collage {
  position: relative;
  padding-block-end: 76px !important;
  padding-inline-end: 62px !important;
}

.psp-collage-a,
.psp-collage-b {
  background-repeat: no-repeat !important;
  background-size: cover !important;
  background-position: center center !important;
  transition: border-radius .5s var(--psp-ease), box-shadow .35s var(--psp-ease);
}

.psp-collage-a {
  min-block-size: 380px;
  border-radius: 46% 54% 40% 60% / 12% 12% 88% 88%;
  box-shadow: var(--psp-ombre);
  width: 100%;
  max-width: 100%;
}

.psp-collage:hover .psp-collage-a { border-radius: 40% 60% 46% 54% / 16% 16% 84% 84%; }

.psp-collage-b {
  position: absolute;
  inset-block-end: 0;
  inset-inline-end: 0;
  inline-size: 58%;
  min-block-size: 200px;
  border-radius: 18px;
  border: 8px solid var(--psp-cream);
  box-shadow: var(--psp-ombre-fo);
}

.psp-collage:hover .psp-collage-b {
  box-shadow: 0 4px 8px rgba(15, 37, 64, .10), 0 22px 50px rgba(15, 37, 64, .20);
}

.psp-collage::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block-start: -30px;
  inset-inline-start: -36px;
  inline-size: 172px;
  block-size: 172px;
  background: var(--psp-sage-100);
  border-radius: 62% 38% 47% 53% / 55% 44% 56% 45%;
  animation: psp-morph 24s ease-in-out infinite;
}

@media (max-width: 900px) {
  .psp-collage { padding-inline-end: 44px !important; padding-block-end: 58px !important; }
  .psp-collage-a { min-block-size: 300px; }
}


/* ==========================================================================
   9. EMPLACEMENT PHOTO EN TÊTE DE CARTE · classe `psp-carte-photo`
   Zoom doux au survol, coins bas qui s'arrondissent un peu plus.

   UN EMPLACEMENT PHOTO EST UN CONTAINER VIDE, ET UN CONTAINER VIDE NE PREND
   AUCUNE HAUTEUR. Sans `min-block-size`, le fond est bien posé et l'image est
   INVISIBLE, et un contrôle qui teste `backgroundImage !== none` ne le voit
   pas. Trois garde-fous cumulés, dans cet ordre : le parent étire, l'emplacement
   fait 100%, et `no-repeat` plus `cover` empêchent toute tuile.
   ========================================================================== */

.psp-carte-photo {
  background-repeat: no-repeat !important;
  background-size: cover !important;
  background-position: center center !important;
  min-block-size: 210px;
  border-radius: 0 0 28px 28px;
  transition: border-radius .45s var(--psp-ease), transform .55s var(--psp-ease);
  transform-origin: center;
}

/* Le zoom passe par `transform` et non par `background-size` : la carte porte
   `overflow: hidden`, donc le débordement est masqué proprement, et on ne
   dépend plus d'une valeur qui déformait l'image. */
.psp-carte:hover .psp-carte-photo,
.psp-carte:focus-within .psp-carte-photo {
  transform: scale(1.05);
  border-radius: 0 0 42px 42px;
}


/* ==========================================================================
   10. MICRO-INTERACTIONS · une par famille d'objet, jamais deux
   Toute carte, tout panneau, tout bloc cliquable ou survolable du site prend
   `psp-leve`. Le filet de couleur qui s'allonge prend `psp-filet`.
   ========================================================================== */

.psp-leve {
  transition: transform .3s var(--psp-ease), box-shadow .3s var(--psp-ease);
}

.psp-leve:hover,
.psp-leve:focus-within {
  transform: translateY(-6px);
  box-shadow: var(--psp-ombre-fo);
}

/* Variante douce, pour les blocs de texte sans ombre au repos. */
.psp-leve--doux:hover { transform: translateY(-4px); box-shadow: var(--psp-ombre); }

/* Filet de couleur en tête de bloc, qui s'allonge au survol. */
.psp-filet { position: relative; }

.psp-filet::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 30px;
  inline-size: 44px;
  block-size: 3px;
  border-radius: 0 0 3px 3px;
  background: var(--psp-sage-600);
  transition: inline-size .3s var(--psp-ease);
}

.psp-filet:hover::before { inline-size: 76px; }

.psp-filet--marine::before { background: var(--psp-navy-600); }
.psp-filet--rose::before   { background: var(--psp-rose-700); }
.psp-filet--sauge::before  { background: var(--psp-sage-500); }

/* Barre pleine largeur en tête de panneau, variante sans survol. */
.psp-barre { position: relative; overflow: hidden; }

.psp-barre::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 4px;
  z-index: 3;
  background: var(--psp-sage-600);
}

.psp-barre--marine::before { background: var(--psp-navy-600); }
.psp-barre--rose::before   { background: var(--psp-rose-700); }


/* ==========================================================================
   11. SIGNES GRAPHIQUES RÉCURRENTS
   Filet avant le surtitre, trait dégradé sous le titre de section centré,
   puces en goutte. C'est ce qui fait qu'une page nouvelle appartient au site.
   ========================================================================== */

.psp-surtitre p { margin: 0; }
.psp-surtitre--centre { margin-block-end: 12px; }
.psp-surtitre--clair p { color: var(--psp-sage-300); }

.psp-surtitre p::before {
  content: "";
  display: inline-block;
  inline-size: 28px;
  block-size: 2px;
  margin-inline-end: 12px;
  vertical-align: middle;
  background: currentColor;
  opacity: .6;
}

.psp-surtitre--centre p::after {
  content: "";
  display: inline-block;
  inline-size: 28px;
  block-size: 2px;
  margin-inline-start: 12px;
  vertical-align: middle;
  background: currentColor;
  opacity: .6;
}

/* AIR SOUS UN TITRE DE SECTION. Corrigé dans le socle le 6 août 2026, dette
   annoncée au §27.8 point 9. La règle d'origine était
   `.psp-section-titre { margin-block-end: 4px }`, et le §27.3 l'expliquait par
   un calibrage sur le titre CENTRÉ, qui reçoit ensuite le trait dégradé de
   22 px.

   MESURE FAITE AVANT DE CORRIGER, sur les cinq pages en ligne : ce n'était pas
   ça. LA RÈGLE NE S'APPLIQUAIT PAS DU TOUT. `margin-block-end` calculé = 0px
   sur les quatre pages publiées, alors que le socle écrit 4px. À 0-1-0 elle
   perd contre la marge de widget qu'Elementor émet dans le CSS du document
   APRÈS le CSS personnalisé : c'est le mécanisme du §26.4bis sur les titres et
   du §18 sur les boutons, ici appliqué à une marge. Les deux rustines de la
   page 87 ne fonctionnaient que parce qu'elles portaient `!important`.

   Écarts titre / bloc suivant relevés à 1440 px avant correction :
     Consultations  « Pourquoi consulter »       -2 px
     Consultations  « Quelles approches »        -2 px
     Qui suis-je    « Formations et diplômes »   14 px
     Prendre RDV    « Où me trouver »            16 px
     Accueil        « Un pôle spécialisé »       30 px
   Norme retenue, celle du §21 pour « titre vers bloc suivant » : 18 à 40 px.

   DEUX RÈGLES, PAS UNE. La marge seule ne suffit pas : l'écart dépendait aussi
   de la marge haute du bloc suivant, qui vaut 18 px sur `psp-texte`, 6 sur un
   `psp-liste` et 0 ailleurs. Même intention, trois résultats. La seconde règle
   la neutralise, pour que l'air vienne d'un seul endroit. */
.psp-section-titre.psp-section-titre.psp-section-titre { margin-block-end: 20px; }

/* Un titre CENTRÉ tire son air du trait dégradé ci-dessous (le `margin: 22px
   auto 0` du ::after). Il ne prend donc pas la marge. Même spécificité, écrite
   après, donc elle gagne. */
.psp-section-titre--centre.psp-section-titre--centre.psp-section-titre--centre { margin-block-end: 0; }

/* Elementor 7 ne pose PAS de `.elementor-widget-container` : le paragraphe est
   enfant DIRECT du widget. Vérifié dans le DOM le 6 août 2026, ne pas le
   supposer. 0-3-1, ce qui bat les 0-1-1 de `.psp-texte p` et `.psp-liste ul`. */
.psp-section-titre.psp-section-titre:not(.psp-section-titre--centre) + .elementor-element > p:first-child,
.psp-section-titre.psp-section-titre:not(.psp-section-titre--centre) + .elementor-element > ul:first-child {
  margin-block-start: 0;
}

.psp-section-titre--centre .elementor-heading-title::after {
  content: "";
  display: block;
  inline-size: 64px;
  block-size: 3px;
  margin: 22px auto 0;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--psp-sage-300), var(--psp-rose-300));
}

/* Puce en goutte, pas un rond : rappel du fil rouge de la pluie. */
.psp-liste ul { margin: 6px 0 0; padding: 0; list-style: none; }

.psp-liste li {
  position: relative;
  padding-inline-start: 28px;
  margin-block-end: 9px;
  font-size: 16px;
  line-height: 1.6;
  max-inline-size: 33em;
}

.psp-liste li:last-child { margin-block-end: 0; }

.psp-liste li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: .58em;
  inline-size: 11px;
  block-size: 11px;
  background: var(--psp-sage-300);
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
}

.psp-liste--marine li::before { background: var(--psp-navy-600); }
.psp-liste--rose li::before   { background: var(--psp-rose-300); }

/* Amorce de citation : filet vertical, Fraunces italique. À distinguer de la
   bande de respiration, qui est pleine largeur. Deux formes, deux usages. */
.psp-citation-amorce p {
  margin: 0;
  padding-inline-start: 26px;
  border-inline-start: 3px solid var(--psp-sage-500);
  font-family: var(--psp-titre, "Fraunces"), sans-serif;
  font-size: clamp(21px, 2.1vw, 27px);
  font-weight: 400;
  font-style: italic;
  line-height: 1.42;
  color: var(--psp-navy-900);
  max-inline-size: 26em;
  text-wrap: balance;
}

/* Fraunces rend le & en esperluette ornementale, illisible dans un titre. Le
   §19 tranche : écrire « et ». Cette règle est une ceinture, à étendre à toute
   nouvelle classe de titre de la page. */
.psp-section-titre .elementor-heading-title { font-variant-ligatures: none; font-feature-settings: "dlig" 0; }

/* CEINTURE DE COUPURE DES TITRES. Trouvée le 6 août 2026 en construisant
   /entreprises/, par le contrôle de débordement de titre du §26.4bis.

   Le §26.4bis pose `overflow-wrap: break-word` sur les titres de CARTE, jamais
   sur le H1 ni sur les titres de SECTION, qui sont pourtant les plus gros de la
   page : à 35px en mobile, un mot de quatorze lettres sort de sa boîte. Mesuré
   à 375px : « Accompagnement » débordait de 10px, « fonctionnement » de 23.

   `hyphens: auto` et PAS `overflow-wrap` seul. La page est servie en
   `lang="fr-FR"`, donc le navigateur coupe aux vraies césures françaises et
   pose le trait d'union ; `overflow-wrap` couperait n'importe où, au milieu
   d'un mot, dans un H1 en Fraunces. Le second reste en dernier recours, pour un
   mot qu'aucun motif de césure ne sait couper (une URL, un sigle long).
   Vérifié au banc d'essai à 375px : zéro débordement avec `hyphens` seul. */
.psp-hero-titre.psp-hero-titre.psp-hero-titre .elementor-heading-title,
.psp-section-titre.psp-section-titre.psp-section-titre .elementor-heading-title {
  hyphens: auto;
  overflow-wrap: break-word;
}

/* Marqueur de chantier (§14) : une donnée manque, on l'affiche au lieu de
   l'inventer. À retirer dès que la cliente a répondu. */
.psp-attente-texte p {
  margin: 14px 0 0;
  font-size: 13px;
  font-style: italic;
  color: var(--psp-muted);
  max-inline-size: 33em;
}

.psp-attente-bloc {
  margin-block-start: 14px;
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px dashed var(--psp-sage-500);
  background: var(--psp-sage-50);
}

.psp-attente-bloc p { margin: 0; font-size: 14px; line-height: 1.6; font-style: italic; max-inline-size: 33em; }


/* ==========================================================================
   12. MESURE DE LECTURE. En `em`, toujours.
   ========================================================================== */

.psp-mesure p { max-inline-size: 33em; }
.psp-mesure--centre p { max-inline-size: 33em; margin-inline: auto; }


/* ==========================================================================
   13. MOUVEMENT RÉDUIT. Non négociable, critère WCAG 2.3.3.
   Le kit coupe déjà animations et transitions. On neutralise en plus tout ce
   qui est porté par `transform` et par les pseudo-éléments de forme.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .psp-forme::before,
  .psp-forme::after,
  .psp-halo::before,
  .psp-collage::before,
  .psp-hero::after,
  .psp-respire::after { animation: none; }

  .psp-leve:hover,
  .psp-leve--doux:hover,
  .psp-carte:hover .psp-carte-photo { transform: none; }

  html { scroll-behavior: auto; }
}


/* ==========================================================================
   14. GABARITS DE GRILLE. À recopier, jamais à improviser.

   UNE RANGÉE ORPHELINE NE SE CORRIGE PAS EN AJUSTANT LE `flex-basis`, ELLE SE
   CORRIGE EN IMPOSANT LA GRILLE. Avec une base souple, quatre blocs sortent en
   3 + 1 à 1440 et cinq blocs en 3 + 2 avec la seconde rangée ÉTIRÉE. Mesuré
   deux fois, sur Qui suis-je puis sur Consultations.

   Et il faut TOUJOURS les deux formes de sélecteur : un container boxed
   intercale un `.e-con-inner` et ses enfants sont petits-enfants, un container
   full n'en a aucun et ses enfants sont directs. Une règle qui ne vise qu'une
   des deux formes ne matche rien, EN SILENCE. Test de détection : lire le
   `flex` calculé de l'enfant, `0 1 auto` signale le piège. Et vérifier aussi le
   `flex-wrap` du PARENT : aucun `flex-basis` d'enfant ne provoque un repli si
   le parent refuse le retour à la ligne.

   DEUX BLOCS
     .P > .E, .P > .e-con-inner > .E { flex: 1 1 330px !important; width: auto !important; min-inline-size: 0 !important; }
     @media (max-width: 780px) { ... flex: 1 1 100% !important; }

   TROIS BLOCS · 3 colonnes ou 1, JAMAIS 2 + 1
     .P > .E, .P > .e-con-inner > .E { flex: 1 1 260px !important; width: auto !important; min-inline-size: 0 !important; }
     @media (max-width: 1000px) { ... flex: 0 0 100% !important; }

   QUATRE BLOCS · 2 x 2 imposé, ou 4 colonnes puis 2 x 2
     .P > .E, .P > .e-con-inner > .E { flex: 0 0 calc((100% - 24px) / 2) !important; width: auto !important; min-inline-size: 0 !important; }
     @media (max-width: 760px) { ... flex: 0 0 100% !important; }
     (variante 4 colonnes : calc((100% - 72px) / 4) au-dessus de 1200px)

   CINQ BLOCS · largeur imposée au tiers, `flex-grow: 0`, rangée incomplète
     .P > .E, .P > .e-con-inner > .E { flex: 0 0 calc((100% - 44px) / 3) !important; width: auto !important; min-inline-size: 0 !important; }
     @media (max-width: 1000px) { ... flex: 0 0 calc((100% - 22px) / 2) !important; }
     @media (max-width: 700px)  { ... flex: 0 0 100% !important; }

   Le `calc` soustrait les gouttières : (nombre de colonnes - 1) x écart.
   ========================================================================== */


/* =========================================================================
   ACTUALITÉS · RÈGLES COMMUNES AUX DEUX GABARITS
   7 août 2026. Collé après le socle dans le CSS de l'ARTICLE et dans celui de
   l'INDEX.

   POURQUOI CE FICHIER EXISTE, ET POURQUOI IL EST DUPLIQUÉ
   Un gabarit de Theme Builder n'est pas une page : trois documents Elementor
   cohabitent sur une même URL. Sur `/actualites/` le navigateur charge le CSS
   de l'INDEX plus celui du LOOP ITEM ; sur un article, celui de l'ARTICLE plus
   celui du LOOP ITEM. Le Loop Item n'a donc AUCUN CSS propre : ses règles
   vivent dans les deux documents qui l'hébergent. C'est un choix, et voici
   pourquoi : autrement il faudrait connaître l'ordre de chargement de trois
   feuilles pour savoir laquelle gagne, et cet ordre n'est garanti nulle part.
   Le coût est quatre kilo-octets écrits deux fois, le bénéfice est qu'aucune
   règle ne dépend d'un ordre qu'on ne contrôle pas.

   LES CINQ RÈGLES D'ÉCRITURE DU SOCLE S'APPLIQUENT SANS EXCEPTION.
   ========================================================================= */

/* ---------------------------------------------------------- 0. Fondations */

.psp-section { position: relative; }

/* ---------------------------------------------------------- 1. Boutons
   Vocabulaire arrêté au §17 et stabilisé au §28.5. Recopié tel quel depuis
   `entreprises.css` : ces variantes ne sont pas dans le socle, elles vivent
   dans le CSS de chaque document. */

.psp-bouton.psp-bouton.psp-bouton .elementor-button {
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: .01em;
}

.psp-bouton--clair.psp-bouton--clair.psp-bouton--clair .elementor-button,
.psp-bouton--clair.psp-bouton--clair.psp-bouton--clair .elementor-button svg {
  fill: var(--psp-navy-900);
}
.psp-bouton--clair.psp-bouton--clair.psp-bouton--clair .elementor-button {
  background-color: var(--psp-cream) !important;
  color: var(--psp-navy-900);
  border: 2px solid var(--psp-cream);
  white-space: nowrap;
  padding: 15px 30px;
}
.psp-bouton--clair.psp-bouton--clair.psp-bouton--clair .elementor-button:hover,
.psp-bouton--clair.psp-bouton--clair.psp-bouton--clair .elementor-button:focus-visible {
  background-color: #FFFFFF;
  border-color: #FFFFFF;
  color: var(--psp-navy-900);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .22);
}

.psp-bouton--secondaire.psp-bouton--secondaire.psp-bouton--secondaire .elementor-button {
  background-color: var(--psp-navy-800) !important;
  color: #FFFFFF;
  border: 2px solid var(--psp-navy-800);
  padding: 15px 30px;
}
.psp-bouton--secondaire.psp-bouton--secondaire.psp-bouton--secondaire .elementor-button:hover,
.psp-bouton--secondaire.psp-bouton--secondaire.psp-bouton--secondaire .elementor-button:focus-visible {
  background-color: var(--psp-navy-700);
  border-color: var(--psp-navy-700);
  color: #FFFFFF;
}
.psp-bouton--secondaire.psp-bouton--secondaire.psp-bouton--secondaire { align-self: flex-start; }

/* §28.5 : LA FLÈCHE SORTAIT EN BLANC SUR FOND BLANC sur trois pages publiées.
   Elementor colore le texte du bouton mais pose le `fill` du SVG dans le CSS
   du document, APRÈS le CSS personnalisé. `currentColor` raccroche la flèche à
   la couleur du texte quelle qu'elle soit, fond sombre compris. */
.psp-bouton--lien.psp-bouton--lien.psp-bouton--lien .elementor-button {
  background-color: transparent !important;
  color: var(--psp-navy-700);
  padding: 0;
  border-radius: 0;
  justify-content: flex-start;
  text-align: start;
  text-transform: none;
  font-weight: 500;
  font-size: 15px;
  letter-spacing: 0;
}
.psp-bouton--lien.psp-bouton--lien.psp-bouton--lien .elementor-button svg {
  fill: currentColor !important;
}
.psp-bouton--lien.psp-bouton--lien.psp-bouton--lien .elementor-button-text {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0 1px;
  padding-block-end: 2px;
  transition: background-size .25s var(--psp-ease);
}
.psp-bouton--lien.psp-bouton--lien.psp-bouton--lien .elementor-button:hover .elementor-button-text,
.psp-bouton--lien.psp-bouton--lien.psp-bouton--lien .elementor-button:focus-visible .elementor-button-text {
  background-size: 100% 1px;
}

/* §27.3 point 4 : `align-self` du WIDGET bat `align-items` de son container.
   Un centrage se reprend sur le widget, jamais sur le parent seul. */
.psp-bouton--centre.psp-bouton--centre.psp-bouton--centre .elementor-button { margin-inline: auto; }
.psp-bouton--centre.psp-bouton--centre.psp-bouton--centre {
  text-align: center;
  align-self: center;
  align-items: center;
}

@media (max-width: 767px) {
  .psp-bouton--clair.psp-bouton--clair.psp-bouton--clair,
  .psp-bouton--clair.psp-bouton--clair.psp-bouton--clair .elementor-button,
  .psp-bouton--secondaire.psp-bouton--secondaire.psp-bouton--secondaire,
  .psp-bouton--secondaire.psp-bouton--secondaire.psp-bouton--secondaire .elementor-button { width: 100%; }
  .psp-bouton--clair.psp-bouton--clair.psp-bouton--clair .elementor-button,
  .psp-bouton--secondaire.psp-bouton--secondaire.psp-bouton--secondaire .elementor-button { justify-content: center; }
}


/* ---------------------------------------------------------- 2. Appel à l'action
   Même bloc que sur les six pages : surtitre, H2, un paragraphe, un bouton. */

.psp-cta-inner > .e-con-inner { max-inline-size: 820px; margin-inline: auto; }

.psp-cta-titre.psp-cta-titre.psp-cta-titre .elementor-heading-title {
  font-size: clamp(28px, 3.2vw, 41px);
  line-height: 1.22;
}

.psp-cta-texte p { margin: 0 0 30px; max-inline-size: 33em; margin-inline: auto; }


/* ---------------------------------------------------------- 3. Ligne de méta
   Catégorie, date, et temps de lecture ajouté par script sur l'article.
   Le widget `post-info` d'Elementor rend une `<ul class="elementor-icon-list-items">`
   et NON un `<p>` : le filet du surtitre du socle, écrit `.psp-surtitre p::before`,
   ne s'y applique pas. D'où ces règles dédiées plutôt qu'un détournement de
   `psp-surtitre`, qui aurait donné une classe qui ne fait rien.

   ICÔNES COUPÉES. Le §2 arbitre que l'iconographie ne porte aucun registre
   médical et que les sections se distinguent par la couleur et la forme : le
   site n'a pas une seule icône hors des flèches de bouton. Le réglage
   `show_icon: none` est posé sur chaque élément du répéteur, cette règle est la
   ceinture. */

.psp-meta .elementor-icon-list-items {
  margin: 0;
  padding: 0;
  list-style: none;
}

.psp-meta .elementor-icon-list-icon { display: none !important; }

.psp-meta .elementor-icon-list-item,
.psp-meta .elementor-icon-list-item a {
  font-family: "Source Sans 3", system-ui, sans-serif;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .04em;
  line-height: 1.5;
}

/* Séparateur en point médian entre deux éléments, comme sur tout le site. */
.psp-meta .elementor-inline-item:not(:last-child)::after {
  content: "·";
  margin-inline: 10px;
  opacity: .55;
}


/* ---------------------------------------------------------- 4. Mouvement réduit
   Le socle neutralise halos, pluie, collage et micro-interactions. On ajoute
   ici les seules classes propres aux Actualités qui bougent. */

@media (prefers-reduced-motion: reduce) {
  .psp-art-carte:hover { transform: none; }
  .psp-filtre { transition: none; }
}


/* =========================================================================
   ACTUALITÉS · LA CARTE D'ARTICLE (gabarit Loop Item)
   7 août 2026. Collé dans le CSS de l'INDEX et dans celui de l'ARTICLE, jamais
   dans le gabarit Loop Item lui-même (voir l'en-tête de `actualites-commun.css`).

   LA CARTE RÉUTILISE LE SOCLE, ELLE NE LE RÉÉCRIT PAS :
     `psp-carte`        pour que le zoom de photo du socle se déclenche au survol
     `psp-leve`         translation -6px et ombre au survol
     `psp-barre--marine` barre pleine largeur en tête
     `psp-carte-photo`  cadrage, `no-repeat`, `cover`, zoom, coins bas arrondis

   L'IMAGE MISE EN AVANT EST FACULTATIVE, ET C'EST LE POINT DÉLICAT.
   Le verbatim demande une vignette sur chaque carte. Mais la cliente écrit
   elle-même et nous ne relirons pas ses articles : un jour elle publiera sans
   image mise en avant. Trois réponses possibles, et une seule tient :
     · imposer une image de repli identique pour tous → une grille de neuf
       cartes portant la MÊME photographie, ce qui est pire que rien ;
     · laisser l'emplacement vide → le socle lui donne `min-block-size: 210px`,
       donc un rectangle gris de 210px en tête de carte ;
     · FAIRE DISPARAÎTRE l'emplacement quand il n'y a pas d'image.
   C'est la troisième.

   PREMIÈRE TENTATIVE, ET POURQUOI ELLE A ÉCHOUÉ. La vignette était un container
   VIDE portant l'image mise en avant en FOND dynamique, comme les cinq
   emplacements photo des pages. Le repli devait être un sélecteur d'attribut
   `[style*="background-image"]`, en pariant sur le fait qu'Elementor pose un
   fond dynamique en style EN LIGNE puisqu'il diffère d'un élément de boucle à
   l'autre. MESURÉ À L'ÉCRAN LE 7 AOÛT 2026 : il ne le fait pas. Il émet une
   règle `.elementor-96 .elementor-element-XXXX { background-image: url(…) }`
   dans une feuille EN LIGNE de la page. Aucun attribut `style`, donc la règle
   de hauteur ne se déclenchait sur AUCUNE des deux cartes : l'une avec image et
   l'autre sans sortaient toutes les deux à `photo_h = 0`. C'est le piège 6 du
   §18 dans sa forme la plus pure, le fond posé et l'image invisible, et il a
   fallu MESURER les deux cartes pour le voir, la page n'ayant l'air de rien.

   CORRECTIF RETENU : le widget `theme-post-featured-image`, donc une vraie
   balise `<img>` et non un fond. Trois gains, et aucune perte :
     · quand l'article n'a pas d'image, le widget ne rend PAS de `<img>`, donc
       `:not(:has(img))` fait disparaître le bloc, ce qui est exprimable en CSS
       alors qu'un fond absent ne l'est pas ;
     · l'image porte le texte alternatif de la médiathèque, le chargement
       différé natif et le `srcset` de WordPress ;
     · les deux raisons qui faisaient écarter le widget Image au §17 ne
       s'appliquent pas ici : « Elementor efface les références média à
       l'import » vise un identifiant média ÉCRIT DANS LE JSON, et il n'y en a
       pas, l'image vient du marqueur dynamique ; « un widget Image sans pièce
       jointe n'a aucun texte alternatif exploitable » vise justement le cas où
       il n'y a pas de pièce jointe, et ici il y en a une.
   ========================================================================= */

/* ---------------------------------------------------------- 1. La carte */

.psp-art-carte.psp-art-carte.psp-art-carte {
  background: #FFFFFF;
  border-radius: 20px;
  overflow: hidden;
  block-size: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 0 !important;
  box-shadow: 0 1px 2px rgba(15, 37, 64, .05), 0 12px 30px rgba(15, 37, 64, .08);
}

/* La barre du socle est en `z-index: 3` et `position: absolute` sur le parent :
   elle passe donc PAR-DESSUS la photographie, ce qui est voulu, la carte se lit
   comme un objet unique et non comme deux blocs empilés. */

/* ---------------------------------------------------------- 2. L'emplacement photo
   `min-block-size: 0` annule le 210px du socle, qui suppose un container vide
   portant un fond : ici c'est une `<img>` qui donne la hauteur. 0-3-0 contre le
   0-1-0 du socle. */

.psp-art-photo.psp-art-photo.psp-art-photo {
  min-block-size: 0;
  border-radius: 0;
  inline-size: 100%;
  overflow: hidden;
  line-height: 0;               /* pas d'espace fantôme sous une image en ligne */
}

/* PAS D'IMAGE MISE EN AVANT : LE WIDGET N'EXISTE MÊME PAS DANS LE DOM.
   Vérifié : la carte n'a plus qu'UN enfant, son corps. La règle ci-dessous ne
   sert donc que de ceinture, pour le cas où une version d'Elementor rendrait
   une enveloppe vide. Le vrai traitement est le bandeau de repli ci-dessous. */
.psp-art-photo.psp-art-photo.psp-art-photo:not(:has(img)) { display: none !important; }

/* ---------------------------------------------------------- 2bis. BANDEAU DE REPLI
   LE DÉFAUT QUE LA CAPTURE A MONTRÉ, ET QUE TROIS MESURES AVAIENT MANQUÉ.
   Deux cartes côte à côte, l'une avec image et l'autre sans : elles avaient la
   même largeur, la même hauteur et le même alignement de lien, donc TOUTES les
   mesures passaient. À l'écran, la seconde portait 210 PIXELS DE VIDE entre son
   titre et son lien, parce que `equal_height` aligne les hauteurs et que le
   corps de la carte sans image n'a rien pour occuper la place de la photo.
   C'est littéralement la règle du §27.3 : une photographie sur l'une de deux
   cartes jumelles n'est jamais un choix, c'est un oubli.

   TROIS RÉPONSES POSSIBLES, ET LA TROISIÈME EST LA BONNE :
     · exiger l'image mise en avant → on ne relira pas les articles de la
       cliente, donc c'est un vœu, pas une garantie ;
     · une photographie de repli identique pour toutes → une grille de neuf
       cartes portant la même image, ce qui est pire que le vide ;
     · UN BANDEAU DESSINÉ, qui n'imite pas une photographie. Il tient la même
       place, il appartient au vocabulaire du site (sauge vers rose, la goutte
       du fil rouge de la pluie), et il ne prétend rien. Une carte sans image
       reste régulière au lieu d'être trouée.

   MISE EN ŒUVRE. Le bandeau est un `::after` du container de carte, remis en
   tête par `order: -1` puisque la carte est un flex en colonne. Il ne peut pas
   être un `::before` : celui-là porte déjà la barre de couleur du socle
   (`psp-barre`), et un élément n'a que deux pseudo-éléments. C'est la même
   collision que celle qui a fait disparaître le voile du hero, évitée cette
   fois parce qu'on la connaissait. */
.psp-art-carte:not(:has(.psp-art-photo))::after {
  content: "";
  order: -1;
  display: block;
  inline-size: 100%;
  block-size: 200px;
  background:
    radial-gradient(38% 52% at 74% 32%, rgba(251, 249, 245, .55), transparent 70%),
    radial-gradient(46% 60% at 22% 78%, rgba(255, 255, 255, .40), transparent 72%),
    linear-gradient(138deg, var(--psp-sage-100, #DDE7DA) 0%, var(--psp-rose-100, #F5E4E4) 100%);
}

@media (max-width: 767px) {
  .psp-art-carte:not(:has(.psp-art-photo))::after { block-size: 180px; }
}

.psp-art-photo.psp-art-photo.psp-art-photo img {
  display: block;
  inline-size: 100%;
  block-size: 200px;
  object-fit: cover;
  object-position: center center;
  border-radius: 0;
  box-shadow: none;
}

@media (max-width: 767px) {
  .psp-art-photo.psp-art-photo.psp-art-photo img { block-size: 180px; }
}

/* Le zoom du socle se fait par `transform` sur un élément à `overflow: hidden`
   côté carte. Rien à réécrire, sauf le sens du rayon : ici la photo est EN
   TÊTE de carte, donc ce sont les coins hauts qui suivent l'arrondi de la
   carte, et les coins bas restent droits. */
.psp-carte:hover .psp-art-photo.psp-art-photo.psp-art-photo,
.psp-carte:focus-within .psp-art-photo.psp-art-photo.psp-art-photo {
  border-radius: 0;
}


/* ---------------------------------------------------------- 3. Le corps
   `flex: 1` sur le corps et `margin-block-start: auto` sur le lien : sans ces
   deux lignes, le lien de chaque carte se cale sous son propre texte et les
   trois liens d'une rangée ne sont jamais alignés. C'est le défaut 3 du §20
   (204px de vide sous le lien d'un panneau), et son correctif. */

.psp-art-corps.psp-art-corps.psp-art-corps {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  flex: 1 1 auto;
  padding: 26px 26px 24px !important;
  gap: 0 !important;
}

.psp-art-meta.psp-art-meta { margin-block-end: 10px !important; }

.psp-art-meta .elementor-icon-list-item,
.psp-art-meta .elementor-icon-list-item a {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--psp-sage-600, #4F6B57);
}

/* §26.4bis et §27.1 : toute règle qui habille un titre RÉPÈTE SA CLASSE.
   Sans les quatre répétitions le titre sort à 33px, la typographie globale
   « Sous-titres », et un titre d'article long déborde de sa carte. Quatorze
   classes étaient en défaut sur les quatre premières pages du site. */
.psp-art-titre.psp-art-titre.psp-art-titre.psp-art-titre .elementor-heading-title {
  font-family: var(--psp-titre, "Fraunces"), sans-serif;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.26;
  letter-spacing: -.005em;
  color: var(--psp-navy-900, #0F2540);
  overflow-wrap: break-word;
  -webkit-hyphens: auto;
  hyphens: auto;
  font-variant-ligatures: none;
  font-feature-settings: "dlig" 0;
}

.psp-art-titre.psp-art-titre { margin-block-end: 10px !important; }

/* Le titre est le lien principal de la carte. Il n'est PAS souligné au repos :
   le critère WCAG 1.4.1 vise les liens noyés dans un bloc de texte, pas un
   titre de carte, dont la nature de lien ne fait aucun doute. `recette-page.js`
   exclut d'ailleurs les liens de liste et de titre de ce contrôle depuis la
   session « Pied de page ». */
.psp-art-titre .elementor-heading-title a {
  color: inherit;
  text-decoration: none;
}
.psp-carte:hover .psp-art-titre .elementor-heading-title a,
.psp-art-titre .elementor-heading-title a:focus-visible { color: var(--psp-navy-700, #1E4463); }

/* PAS DE RÈGLE D'EXTRAIT, PARCE QU'IL N'Y A PAS D'EXTRAIT SUR LA CARTE.
   Il y en avait un, construit puis retiré le 7 août 2026 : le marqueur
   `post-excerpt` rend l'extrait SAISI À LA MAIN et rien quand il n'y en a pas,
   or la cliente écrit elle-même et le champ « Résumé » de Gutenberg est dans
   un panneau replié. Une grille où quatre cartes sur neuf portent un résumé
   n'est pas une variation, c'est la règle du §27.3 sur la photographie posée
   sur l'une de deux cartes jumelles. Le raisonnement complet est dans
   `build-actualites.py`, à l'endroit où le widget aurait dû être. */

/* §27.3 point 5 : l'écart « dernier texte vers bouton » du §21 vaut pour tout
   bloc qui se termine par une action, pas seulement pour le hero. Norme 28 à
   60. `margin-block-start: auto` pousse le lien en bas de la carte, la marge
   fixe garantit le plancher quand la carte est courte. */
.psp-art-lien.psp-art-lien {
  margin-block-start: auto !important;
  padding-block-start: 22px !important;
}


/* ---------------------------------------------------------- 4. La grille
   §26.4 : UNE RANGÉE ORPHELINE NE SE CORRIGE PAS EN AJUSTANT LE `flex-basis`,
   ELLE SE CORRIGE EN IMPOSANT LA GRILLE. La grille d'Elementor est ici une
   vraie grille CSS (`.elementor-grid`), pas un flex de containers : le piège
   6bis du §18 ne s'y applique pas, mais le principe si. Trois colonnes, puis
   deux, puis une. Jamais 2 + 1 sur une rangée de trois. */

.psp-index-grille .elementor-grid,
.psp-lire-grille .elementor-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
}

/* `flex-grow: 0`, largeur imposée au tiers : c'est la parade du §26.4, et elle
   est écrite ici plutôt que laissée à une base souple. Avec `flex-grow: 1`, une
   rangée incomplète étire ses cartes et une carte seule prend toute la largeur. */
.psp-index-grille .elementor-grid > *,
.psp-lire-grille .elementor-grid > * {
  flex: 0 0 calc((100% - 56px) / 3);
  min-inline-size: 0;
}

/* LA GRILLE « À LIRE AUSSI » EST CENTRÉE, CELLE DE L'INDEX NE L'EST PAS, et la
   différence est réfléchie.
   L'index est paginé : une rangée incomplète en fin de liste se lit comme la
   suite d'une grille, alignée à gauche comme les précédentes. « À lire aussi »
   n'affiche JAMAIS plus de trois cartes et en affichera souvent une ou deux :
   une carte seule calée à gauche sous un titre centré se lit comme un défaut.
   Vu à la CAPTURE, avec un seul article voisin. Aucune mesure ne pouvait le
   dire : la carte avait la bonne largeur et la bonne hauteur. */
.psp-lire-grille .elementor-grid { justify-content: center; }

@media (max-width: 1000px) {
  .psp-index-grille .elementor-grid,
  .psp-lire-grille .elementor-grid { gap: 24px; }
  .psp-index-grille .elementor-grid > *,
  .psp-lire-grille .elementor-grid > * { flex: 0 0 calc((100% - 24px) / 2); }
}

@media (max-width: 680px) {
  .psp-index-grille .elementor-grid,
  .psp-lire-grille .elementor-grid { gap: 22px; }
  .psp-index-grille .elementor-grid > *,
  .psp-lire-grille .elementor-grid > * { flex: 0 0 100%; }
}


/* ---------------------------------------------------------- 5. Pagination
   Elementor rend `.elementor-pagination` avec des `<a>` et un `<span class="current">`.
   Cibles tactiles à 44px, critère WCAG 2.5.8, le même plancher que les options
   du formulaire (§25.7). */

.psp-index-grille .elementor-pagination {
  margin-block-start: 44px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 8px;
}

.psp-index-grille .elementor-pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 44px;
  min-block-size: 44px;
  padding-inline: 12px;
  border-radius: 999px;
  border: 1px solid var(--psp-sage-300, #A8BFA8);
  font-family: "Source Sans 3", system-ui, sans-serif;
  font-size: 16px;
  font-weight: 500;
  color: var(--psp-navy-700, #1E4463);
  text-decoration: none;
  background: #FFFFFF;
  transition: background-color .2s var(--psp-ease), color .2s var(--psp-ease),
              border-color .2s var(--psp-ease);
}

.psp-index-grille .elementor-pagination .page-numbers:hover,
.psp-index-grille .elementor-pagination .page-numbers:focus-visible {
  background: var(--psp-sage-50, #EEF3EC);
  border-color: var(--psp-sage-600, #4F6B57);
  color: var(--psp-navy-900, #0F2540);
}

.psp-index-grille .elementor-pagination .page-numbers.current {
  background: var(--psp-navy-800, #16324F);
  border-color: var(--psp-navy-800, #16324F);
  color: #FFFFFF;
}


/* =========================================================================
   ACTUALITÉS · GABARIT ARCHIVE, l'index
   7 août 2026. Socle + commun + carte collés en tête à la génération.

   CE GABARIT SERT TROIS URL, PAS UNE : `/actualites/`, qui est la page des
   articles (`page_for_posts` = 17), et les archives de catégorie
   `/actualites/category/articles/` et `/actualites/category/groupes/`. La
   condition « toutes les archives » couvre les trois, vérifié en requête
   anonyme.

   LE H1 EST STATIQUE, ET C'EST UN CHOIX.
   Le marqueur dynamique `archive-title` rendrait « Actualités » sur l'index et
   « Articles » sur une archive de catégorie. Mais sur la page des articles,
   qui est `is_home()` et non `is_archive()`, ce qu'il rend dépend du thème et
   n'est pas garanti. Le filtre juste dessous dit déjà quelle rubrique est
   active, avec `aria-current`. Un H1 constant est prévisible, et sur ce site
   personne ne relira le rendu de chaque archive de catégorie.

   LE HERO NE PORTE AUCUNE PHOTOGRAPHIE, ET C'EST UN CHOIX AUSSI.
   Les six pages du site en ont une. Ici, deux raisons de s'en passer :
   l'index présente jusqu'à neuf vignettes juste en dessous, et une septième
   image en tête ferait concurrence à celles qui portent le contenu ; et les
   cinq photographies vérifiées du site sont toutes déjà attribuées à une page,
   or le §20 interdit d'introduire une URL neuve sans l'avoir REGARDÉE, et le
   §26.3 rappelle qu'une URL qui répond 200 ne dit rien de ce qu'elle montre.
   Le voile du socle sur fond marine 900, le motif de pluie et les halos
   suffisent à faire un hero du site.
   ========================================================================= */

/* ---------------------------------------------------------- 1. Décalages de halos
   Positions propres à ce gabarit, différentes de celles d'Entreprises et du
   Coin des Pros : si le halo revient au même endroit d'une section à l'autre
   ou d'une page à l'autre, le motif devient un gabarit (socle §4). */

.psp-index.psp-index::before { inset-block-start: -22%; inset-inline-end: -14%; inline-size: 36vw; block-size: 36vw; }
.psp-index.psp-index::after  { inset-block-end: -18%; inset-inline-start: -12%; inline-size: 30vw; block-size: 30vw; }

.psp-cta.psp-cta::before { inset-block-start: -16%; inset-inline-end: auto; inset-inline-start: -18%; inline-size: 32vw; block-size: 32vw; }
.psp-cta.psp-cta::after  { inset-block-end: -24%; inset-inline-start: auto; inset-inline-end: -8%; inline-size: 28vw; block-size: 28vw; }

/* Troisième halo, un seul : l'index n'a que trois sections, deux en
   porteraient trop (socle §3, deux ou trois sur une page longue). */
.psp-index-inner.psp-index-inner::before { inset-block-start: 24%; inset-inline-start: 74%; }


/* ---------------------------------------------------------- 2. Hero
   Le voile, la pluie et les cinq écarts du rythme vertical viennent du socle.
   Le hero n'a AUCUN bouton : sur un index, l'action est de choisir un article,
   et il n'y en a pas d'autre à proposer en tête. `recette-page.js` mesure alors
   `texte_vers_suite` au lieu de `boutons_vers_suite`, même norme de 88 à 150
   (§24). */

.psp-hero-titre { max-inline-size: 900px; }


/* ---------------------------------------------------------- 3. Filtres par rubrique
   Le verbatim demande « Filtres par catégorie ». Trois pastilles : Tout,
   Articles, Groupes, c'est-à-dire les deux catégories arrêtées au §2.

   ELLES RESTENT VISIBLES MÊME QUAND IL N'Y A AUCUN ARTICLE. On pourrait les
   masquer avec le même `:has()` que l'état vide. Ce serait une erreur : sur une
   archive de catégorie vide, masquer le filtre enfermerait le visiteur dans une
   page sans issue. Et le jour de la livraison, trois pastilles au-dessus de
   « Les premiers articles arrivent bientôt » annoncent la structure au lieu de
   la cacher.

   L'ÉTAT ACTIF EST POSÉ PAR SCRIPT EN LIGNE, six lignes, aucun appel réseau,
   aucun cookie : il ne rouvre donc pas le bandeau de consentement écarté au §2.
   Même parti qu'au §16 pour l'aria du burger et qu'au §25.7 pour les libellés
   du formulaire. Sans JavaScript, les trois pastilles restent des liens
   utilisables : l'état actif est un confort, jamais une condition de
   fonctionnement. */

.psp-filtres { margin-block-end: 34px !important; }

.psp-filtres-liste {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.psp-filtre {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding: 0 20px;
  border-radius: 999px;
  border: 1px solid var(--psp-sage-300, #A8BFA8);
  background: #FFFFFF;
  font-family: "Source Sans 3", system-ui, sans-serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--psp-navy-700, #1E4463);
  text-decoration: none;
  transition: background-color .2s var(--psp-ease), color .2s var(--psp-ease),
              border-color .2s var(--psp-ease);
}

.psp-filtre:hover,
.psp-filtre:focus-visible {
  background: var(--psp-sage-50, #EEF3EC);
  border-color: var(--psp-sage-600, #4F6B57);
  color: var(--psp-navy-900, #0F2540);
}

/* Contraste vérifié : blanc sur marine 800 = 13,10 (AAA). L'état actif ne se
   distingue pas QUE par la couleur, il porte aussi `aria-current="page"`, lu
   par les lecteurs d'écran (WCAG 1.4.1 et 4.1.2). */
.psp-filtre[aria-current="page"] {
  background: var(--psp-navy-800, #16324F);
  border-color: var(--psp-navy-800, #16324F);
  color: #FFFFFF;
}


/* ---------------------------------------------------------- 4. État vide
   L'ÉTAT VIDE EST UN LIVRABLE, PAS UN DÉTAIL. Aucun article n'existe, la
   cliente écrit elle-même : le jour de la livraison, c'est CE bloc que le
   visiteur verra, et pas la grille.

   Le texte est celui du verbatim, mot pour mot : « Les premiers articles
   arrivent bientôt. » Rien n'est inventé.

   IL EST TOUJOURS DANS LE DOM, ET MASQUÉ QUAND LA GRILLE A DES ENFANTS.
   `:has()` est déjà employé sur ce site (§25.14, les cartes de profil du
   formulaire), donc l'appui navigateur est acquis. Le sens est le bon : par
   défaut on montre l'état vide, et c'est la PRÉSENCE d'articles qui le masque.
   Si `:has()` échouait, le visiteur verrait un message honnête sous une grille
   pleine, ce qui est laid ; l'inverse, une page blanche, serait un défaut. */

.psp-vide {
  border: 1px dashed var(--psp-sage-300, #A8BFA8);
  border-radius: 22px;
  background: #FFFFFF;
  padding: 54px 34px !important;
  text-align: center;
}

.psp-vide-titre.psp-vide-titre.psp-vide-titre.psp-vide-titre .elementor-heading-title {
  font-family: var(--psp-titre, "Fraunces"), sans-serif;
  font-size: clamp(23px, 2.4vw, 30px);
  font-weight: 600;
  line-height: 1.28;
  color: var(--psp-navy-900, #0F2540);
}

.psp-vide-titre.psp-vide-titre { margin-block-end: 14px !important; }

.psp-vide-texte p {
  margin: 0;
  max-inline-size: 33em;
  margin-inline: auto;
  color: var(--psp-muted, #5A6673);
}

/* LES DEUX LIENS DE L'ÉTAT VIDE SONT SOULIGNÉS, ET C'EST UN CORRECTIF.
   Ils sortaient sans soulignement, signalés par `recette-page.js` aux quatre
   largeurs : ce sont des liens NOYÉS DANS UN BLOC DE TEXTE, donc exactement le
   cas d'école du critère WCAG 1.4.1, celui où rien d'autre que la couleur ne
   dit que c'en est un. Même famille que le lien « Politique de confidentialité »
   du §24, qui sortait à 1,29 de contraste sur le fond marine.
   Le jour de la livraison, ce bloc est le SEUL contenu de l'index : ses deux
   liens sont donc les seuls chemins offerts au visiteur.

   TROIS RÉPÉTITIONS, ET VOICI CONTRE QUOI. Écrite `.psp-vide-texte p a`, soit
   0-1-2, la règle perdait. Relevé dans la feuille du KIT (`post-45.css`) :

       .psp-texte a:not(.elementor-button),
       .elementor-widget-text-editor a:not(.elementor-button) { text-decoration: none }

   c'est-à-dire 0-2-1, puisque l'argument d'un `:not()` compte dans le calcul.
   CE N'EST PAS UN PROBLÈME D'ORDRE MAIS DE SPÉCIFICITÉ : la feuille du kit
   charge AVANT celle du document, et perdrait à égalité.

   PORTÉE GÉNÉRALE, à retenir pour tout le site : le kit RETIRE le soulignement
   de TOUT lien placé dans un widget de texte. Sur les six pages, chaque lien
   dans du texte courant a donc besoin de sa propre règle à 0-3-2 au moins,
   sinon il échoue au critère 1.4.1 sans que rien ne le signale à l'écran. */
.psp-vide-texte.psp-vide-texte.psp-vide-texte p a {
  color: var(--psp-navy-700, #1E4463);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--psp-sage-500, #6E8A72);
  transition: color .2s var(--psp-ease), text-decoration-color .2s var(--psp-ease);
}

.psp-vide-texte.psp-vide-texte.psp-vide-texte p a:hover,
.psp-vide-texte.psp-vide-texte.psp-vide-texte p a:focus-visible {
  color: var(--psp-navy-900, #0F2540);
  text-decoration-color: var(--psp-navy-700, #1E4463);
}

/* IL Y AVAIT UNE PASTILLE EN GOUTTE ICI, ET ELLE A ÉTÉ RETIRÉE.
   Elle devait rappeler le fil rouge de la pluie (§2) et empêcher le bloc de
   n'être qu'un cadre en pointillé. À la CAPTURE, elle sortait dans l'angle
   supérieur GAUCHE, à cheval sur la bordure, alors que tout le contenu du bloc
   est centré : `margin-inline: auto` sur un pseudo-élément d'un container
   Elementor ne le centre pas comme on l'attend.
   On aurait pu chercher la bonne combinaison de `align-self`. On l'a retirée :
   c'est la leçon du pointillé de liaison du §28.5, « un signe qu'on doit
   expliquer est un signe de trop ». Le cadre en pointillé, le titre en Fraunces
   et les deux liens suffisent à faire un bloc, et le §5 veut un site vivant,
   pas un sapin de Noël. */
.psp-vide-inner > .e-con-inner { align-items: center; }

.psp-index-inner:has(.elementor-loop-container > *) .psp-vide { display: none !important; }

@media (max-width: 767px) {
  .psp-vide { padding: 40px 22px !important; }
}


/* ---------------------------------------------------------- 5. Corps de l'index */

.psp-index-inner > .e-con-inner { max-inline-size: 1240px; margin-inline: auto; }/* End custom CSS */