/* ==========================================================================
   activite.css - affinages des pages de DETAIL d'activité
   (bowling, simulateur-de-course, jumping-jack, billard, arcades,
   réalité-virtuelle, karaoké, zone-de-jeux, simulateur-de-golf, padel,
   tennis, squash, pickleball, badminton, five-club-fitness...).
   Chargé via is_page_template('template-activite.php').
   Objectif Phase B : reproduire fidèlement le visuel de la page "Arcades" du
   Raiffeisen Parc (hero diaporama sombre + H1 géant ajouré, barre d'actions
   qui chevauche le hero, intro fil d'Ariane + cartes vertes, galerie bandeau,
   étapes 2 colonnes, formules "em-card-border", tarifs sur fond accent,
   carrousel d'activités liées). Couleurs : tokens var(--fp-*) UNIQUEMENT
   (aucun #hex toléré par check-zones).
   Scope systématique : .fp-detail (posee sur le body des templates
   template-activite.php ET template-restaurant.php, cf. fp_body_class_detail
   dans functions.php - partage du kit visuel "detail" entre les 2 modeles).
   ========================================================================== */

/* Variable de motif décoratif "pattes" (fond des sections colorées). URL
   RELATIVE (mediatheque migree a l'identique -> resout en local) : le buffer
   de reecriture du theme (fp_localize_uploads) n'agit que sur le HTML rendu,
   pas sur ce CSS statique, donc pas d'URL distante en dur ici. */
.fp-detail {
  --fp-act-pattes: url('/wp-content/uploads/2025/04/Plan-de-travail-1.svg');
}

/* --------------------------------------------------------------------------
   HERO DETAIL : diaporama Ken Burns sombre, contenu ALIGNE A GAUCHE dans le
   conteneur de largeur globale (.fp-wrap : demarre au bord gauche du wrap,
   PAS plus a gauche que lui -> ne jamais toucher au centrage/margin:auto du
   .fp-wrap lui-meme, seul le texte a l'interieur passe en text-align:left).
   Metriques recopiees du CSS source (post-736.css, elements 6a5dabf/8a31a9b/
   4e4d42f) : H1 200px desktop / 155px tablette (<=1024px) / 112px mobile
   (<=767px), stroke 3.5px desktop+tablette / 2px mobile ; accroche 22px desktop
   (max-width 60%) / 18px mobile (max-width 100%) ; eyebrow a 100px du haut du
   hero (marge du icon-box d8f5503).
   -------------------------------------------------------------------------- */
/* ANCRAGE EN HAUT, et non centrage vertical (correctif 2026-08) : .fp-hero
   (main.css) est un flex avec align-items:center, donc TOUT le bloc de texte
   du héro était centré verticalement dans le cadre. Conséquence : la position
   du titre dépendait de la HAUTEUR DE CE QUI LE SUIT - une accroche sur 3
   lignes au lieu de 2, ou une icône d'activité présente sur une page et pas
   sur l'autre, faisait remonter ou descendre le titre de plusieurs dizaines
   de pixels. Deux pages du même modèle n'étaient donc jamais calées pareil,
   sans qu'aucune règle ne les distingue.
   En ancrant le bloc en HAUT, la position du titre ne dépend plus que de
   métriques fixes (padding du héro + espacement de tête + hauteur du
   sur-titre), identiques sur toutes les pages. C'est aussi la mesure du
   modèle source, dont le sur-titre est à 100px du haut du héro (cf. plus bas,
   espacement désormais porté par .fp-hero-inner). */
/* ANCRAGE EN BAS (Marino, 2026-09-07, remplace l'ancrage en haut) : avec
   flex-start, un titre tenant sur une seule ligne (cas devenu fréquent depuis
   la réduction du 2026-09-06, ex. Karaoké) laissait un grand vide en bas du
   héro. align-items: flex-end ancre désormais le bloc sur-titre/titre/
   accroche au bas du héro, avec un espace bas CONSTANT porté par le
   padding-bottom ci-dessous (90px) : cette valeur n'a JAMAIS changé dans
   l'historique du fichier (git log -p -S 'flex-start'), y compris au moment
   où flex-start avait été introduit - elle existait déjà, simplement
   neutralisée visuellement par l'ancrage haut. Hauteur du héro INCHANGÉE
   (min-height identique). Sur un titre de deux lignes ou plus, le bloc
   grandit donc naturellement VERS LE HAUT ; le garde-fou qui empêche le
   sur-titre de talonner la barre de navigation vit dans
   setupHeroTitreLignes() (assets/js/main.js, classe is-multiligne) : voir le
   bloc TITRE SUR DEUX LIGNES OU PLUS plus bas. */
/* RÉSERVE BASSE PORTÉE À 130px le 2026-09-09 (Marino) : « sur le Mac
   d'Evelyne je ne voyais pas assez du titre, il était vite coupé en bas ».
   Le bloc sur-titre / titre / accroche étant ancré au bas du héro, les 90px
   d'origine le collaient trop près du bord, et la moindre réduction de
   hauteur utile (fenêtre courte, zoom du navigateur, barre d'outils) le
   poussait hors de vue. 130px lui redonnent de l'air sans toucher à la
   hauteur du héro ni à son ancrage. */
.fp-detail .fp-hero-detail {
  min-height: min(93vh, 860px);
  padding: calc(var(--fp-nav-h) + 40px) 0 130px;
  border-radius: 0 0 60px 60px;
  overflow: hidden;
  align-items: flex-end;
}
/* Voile reproduit a l'identique du modele (::before du .em-hero source,
   mesure via getComputedStyle) : linear-gradient(var(--fp-primary) 0%,
   noir 72% d'alpha 34%) puis TOUT le calque a 48% d'opacite globale. Le vert
   fonce domine en haut du hero (comme le RP), s'assombrit vers un quasi-noir
   des le premier tiers, puis laisse la photo respirer en bas. --fp-ink est le
   token le plus proche d'un noir reel parmi les tokens sombres existants :
   compose avec color-mix pour rester en tokens (aucun hex/rgba brut, cf.
   contrainte activite.css). */
.fp-detail .fp-hero-detail .fp-hero-overlay {
  background: linear-gradient(
    180deg,
    var(--fp-primary) 0%,
    color-mix(in srgb, var(--fp-ink) 72%, transparent) 34%
  );
  opacity: .48;
}
/* .fp-hero-inner EST .fp-wrap : ne pas modifier son max-width/margin (ils
   viennent de .fp-wrap et le centrent dans la page) ; seul l'alignement du
   texte a l'interieur change. Le contenu demarre donc au bord gauche du
   conteneur de largeur globale, comme la source. */
/* L'espacement de tête (100px du modèle source) est porté par LE CONTENEUR,
   plus par le sur-titre : c'était une marge posée sur un élément OPTIONNEL
   (fp-hero-eyebrow n'est rendu que si la zone fournit un sur-titre, cf.
   fp_render_hero_detail, inc/sections.php). Une page sans sur-titre perdait
   donc d'un coup 100px d'espacement et son titre remontait d'autant. */
.fp-detail .fp-hero-detail .fp-hero-inner {
  /* width 100% : LA ligne qui manquait, et la cause de tout le probleme
     d'alignement signale page apres page.
     .fp-hero (main.css) est un conteneur FLEX en ligne. .fp-hero-inner en est
     donc un ELEMENT flex, dont la largeur se calcule sur son CONTENU et non sur
     le conteneur. Le margin: 0 auto herite de .fp-wrap centrait alors cette
     boite retrecie : son bord gauche dependait de la longueur du titre et de
     l'accroche, donc changeait d'une page a l'autre. Arcades tombait juste par
     hasard, bowling demarrait 50px plus a droite, Fitness 135px plus a droite.
     Avec width 100%, la boite fait exactement la largeur de contenu (bornee par
     le max-width de .fp-wrap) : bord gauche identique partout, aligne sur la
     barre d'actions et sur toutes les sections suivantes.
     Le hero standard, lui, avait toujours eu ce width 100% via .fp-hero-grid
     (main.css) : seul le hero de detail en etait prive. */
  width: 100%;
  text-align: left;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding-top: 100px;
}
/* Sur-titre du hero de detail : c'est le composant icon-box partage
   (fp_icon_box, main.css bloc ICON-BOX) qui dessine la pilule, avec l'icone de
   la page. La pastille sombre translucide + le pin en masque SVG qui vivaient
   ici SONT SUPPRIMES : c'etait une copie manuelle de la variante verre du
   composant, sur ce seul modele. Il ne reste que l'espacement du conteneur.
   L'espacement du haut du hero (100px) est porte par .fp-hero-inner ci-dessus :
   ce conteneur est optionnel, il ne doit porter aucune metrique de mise en page. */
.fp-detail .fp-hero-detail .fp-hero-eyebrow {
  margin-top: 0;
  margin-bottom: 22px;
  /* CE CONTENEUR EST LE H1 DE LA PAGE depuis le 2026-08-17 (demande du client :
     « Bowling à Rennaz » doit être le vrai titre de niveau 1, voir
     fp_render_hero_detail dans inc/sections.php). Il hérite donc de la règle
     générale des titres (h1..h4, main.css) une typographie qui ne le concerne
     pas : la pilule dessine son propre libellé dans .fp-ibox-title.
     Sans cette neutralisation, la taille de titre (jusqu'à 3.8rem) et sa
     hauteur de ligne fabriqueraient une ligne de texte VIDE bien plus haute
     que la pilule elle-même (elle est en inline-flex, donc posée dans une
     ligne de texte) : le sur-titre gagnerait une trentaine de pixels de haut
     sans que rien ne le montre. On revient donc à des valeurs de texte
     courant, strictement invisibles à l'écran. */
  font-size: 1rem;
  line-height: 1;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}
/* H1 : taille desktop recopiee du source (200px), rempli TEAL + contour BLANC
   fin, pose sur la photo (pas ajoure). Weight 400 (Thoge se suffit),
   letter-spacing normal, pas de text-shadow (absent du source).
   Le remplissage est repasse au teal --fp-primary (#2a7e74) : le vert le plus
   fonce des tokens (--fp-secondary-dark, #002f29) essaye entre-temps a la
   demande du client s'est revele trop sombre sur la photo. */
.fp-detail .fp-hero-detail .fp-hero-title {
  font-family: var(--fp-font-display);
  font-size: 200px;
  line-height: 1;
  text-transform: uppercase;
  text-align: left;
  font-weight: 400;
  letter-spacing: normal;
  color: var(--fp-primary);
  -webkit-text-stroke: 3.5px var(--fp-white);
  text-stroke: 3.5px var(--fp-white);
  margin: 0 0 18px;
  /* Filet de securite : le titre est saisi par la cliente et le héro est en
     overflow: hidden. Sans cela, un mot trop long pour sa ligne est tranché
     net, sans le moindre indice. Ne se déclenche que lorsqu'un mot ne tient
     pas seul sur une ligne : les titres actuels ne bougent pas. */
  overflow-wrap: break-word;
}
/* MOT D'ACCENT NEUTRALISE sur ce hero (retour client : « le H1 est en vert
   clair, je le veux en vert fonce comme le reste »). Le titre passe par
   fp_hero_accent_word (inc/sections.php), qui met le DERNIER mot en
   .fp-accent-word -> var(--fp-accent), le teal clair (main.css). Sur une
   page d'activite ou de restauration, le titre tient souvent en UN SEUL
   mot (« Arcades », « Bowling ») : c'est alors le titre ENTIER qui virait
   au vert clair. Ici, il herite donc simplement du vert fonce du titre
   (le contraste vient deja du contour blanc). Le hero de l'accueil, lui,
   garde son mot d'accent teal clair : cette regle est scopee au seul
   .fp-hero-detail. */
.fp-detail .fp-hero-detail .fp-hero-title .fp-accent-word {
  color: inherit;
}
/* ALIGNEMENT A GAUCHE GARANTI, quelle que soit la page (retour client : le
   titre est bien cale a gauche sur /activites/arcades/, mais parait « un peu
   plus centre » sur d'autres activites et sur la restauration).
   Le markup et la feuille de style sont pourtant identiques pour toutes ces
   pages : la divergence ne peut donc venir que du CONTENU du bloc titre
   enregistre en base, ou l'editeur a pu laisser une classe d'alignement
   (has-text-align-center) ou un centrage herite.
   On neutralise donc la cause a la racine plutot que de courir apres :
   - align-self stretch : le titre occupe toute la largeur du conteneur, au
     lieu de se retrecir a son texte, ce qui rend l'alignement sans ambiguite ;
   - text-align left force sur le titre ET sur tout ce qu'il contient, ce qui
     ecrase une eventuelle classe d'alignement venue de l'editeur.
   Sans effet sur la page arcades, qui est deja dans cet etat. */
.fp-detail .fp-hero-detail .fp-hero-title,
.fp-detail .fp-hero-detail .fp-hero-title > * {
  align-self: stretch;
  text-align: left;
}
.fp-detail .fp-hero-detail .fp-hero-lead {
  max-width: 60%;
  margin: 0;
  text-align: left;
  font-size: 22px;
  line-height: 26px;
  color: var(--fp-white);
}
/* Icône de l'activité, sous le titre, alignée à gauche. */
.fp-detail .fp-hero-icon {
  margin-top: 20px;
}
.fp-detail .fp-hero-icon img {
  width: 56px;
  height: 56px;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: .92;
}

/* --------------------------------------------------------------------------
   TITRE SUR DEUX LIGNES OU PLUS (2026-09-06, demande client) : certaines
   fiches ont un grand titre trop long pour tenir sur une ligne. AVEC
   L'ANCRAGE BAS (2026-09-07, voir .fp-hero-detail plus haut), un titre de
   deux lignes ou plus grandit naturellement VERS LE HAUT (le bas reste fixe,
   porté par le padding-bottom constant) : plus besoin de remonter le bloc à
   coups de padding-top, la seule chose qui reste à garantir est que ce bloc,
   en grandissant vers le haut, ne vienne pas talonner la barre de navigation.
   setupHeroTitreLignes() (assets/js/main.js) MESURE le rendu réel de
   .fp-hero-title (après le découpage animé de setupHeadingReveal) et pose
   is-multiligne sur .fp-hero-detail quand le titre occupe deux lignes ou
   plus : le titre rétrécit à 80% de sa taille normale, les espacements se
   resserrent. GARDE-FOU (2026-09-07, corrigé le même jour, relecture Opus) :
   la même fonction mesure ensuite, en coordonnées document (invariantes au
   défilement en cours), la distance réelle entre le haut du sur-titre (qui
   EST le h1 de la page, cf. CLAUDE.md) et la hauteur de la barre de
   navigation ; si elle passe sous 24px, is-multiligne est posée en filet (si
   le calcul par nombre de lignes ci-dessus ne l'avait pas déjà fait).
   PAS DE PALIER « SERRÉ » : avec les constantes actuelles (padding-top du
   héro + padding-top de .fp-hero-inner), cette distance ne peut
   mathématiquement jamais descendre sous ~140px, quel que soit le contenu
   (l'ancrage bas colle le bloc au bas du héro, mais le sur-titre - premier
   élément du bloc - reste toujours à ce plancher constant, cf. le
   commentaire de setupHeroTitreLignes()) : un seuil à 24px y est donc
   inatteignable par construction. is-multiligne (80%) est donc le SEUL filet
   réel pour un titre long. SANS JAVASCRIPT, rien ne change : aucune classe
   n'est jamais posée, le titre garde sa taille normale et un titre de deux
   lignes est accepté tel quel. */
.fp-detail .fp-hero-detail.is-multiligne .fp-hero-eyebrow {
  margin-bottom: 12px;
}
.fp-detail .fp-hero-detail.is-multiligne .fp-hero-title {
  font-size: 160px; /* 200px x 0.8 */
  margin-bottom: 10px;
}
@media (prefers-reduced-motion: no-preference) {
  /* Ken Burns un peu plus lent que le hero standard pour un rendu plus posé. */
  .fp-detail .fp-hero-detail .fp-hero-slide {
    animation-duration: 24s;
  }
}

/* --------------------------------------------------------------------------
   ENRICHISSEMENT HERO (retour client : "il manque 2-3 elements, on peut
   faire plus sympa, plus joli") : le hero garde EXACTEMENT sa structure et
   ses metriques (H1/eyebrow/lead/icone inchanges), on ajoute 3 couches
   purement decoratives / d'entree, sans toucher au diaporama ni a la barre
   d'actions :
    1. deux halos degrades flous (secondary-dark "etouffe" sous le voile,
       accent "net" au-dessus du voile) : z-index 1, exploitent le tie-break
       de peinture entre pseudo-elements et .fp-hero-overlay (egalement
       z-index 1) pour se placer respectivement dessous/dessus le voile sans
       jamais depasser le contenu texte (.fp-hero-inner, z-index 2 via la
       classe .fp-inner de main.css) ;
    2. une entree en cascade (eyebrow -> titre -> accroche -> icone), fondu +
       leger glissement, desactivee en reduced-motion (etat final fige,
       aucune classe fp-reveal necessaire : le hero est visible des le
       chargement, pas besoin de l'IntersectionObserver commun) ;
    3. un anneau pulse tres discret derriere l'icone de l'activite.
   Zone BASSE du hero volontairement laissee libre de toute decoration :
   c'est la que la barre .fp-actbar (position fixed) chevauche le hero (cf.
   section BARRE D'ACTIONS juste apres) ; les halos sont positionnes en haut
   du cadre pour ne jamais interferer visuellement avec elle.
   -------------------------------------------------------------------------- */
.fp-detail .fp-hero-detail::before,
.fp-detail .fp-hero-detail::after {
  content: '';
  position: absolute;
  z-index: 1;
  width: min(46vw, 620px);
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(60px);
}
.fp-detail .fp-hero-detail::before {
  top: -12%;
  left: -10%;
  background: radial-gradient(circle, color-mix(in srgb, var(--fp-secondary-dark) 70%, transparent) 0%, transparent 72%);
}
.fp-detail .fp-hero-detail::after {
  top: 4%;
  right: -14%;
  width: min(38vw, 480px);
  background: radial-gradient(circle, color-mix(in srgb, var(--fp-accent) 55%, transparent) 0%, transparent 70%);
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-hero-detail::before {
    animation: fp-hero-drift 14s ease-in-out infinite;
  }
  .fp-detail .fp-hero-detail::after {
    animation: fp-hero-drift 16s ease-in-out infinite reverse;
  }
}
@keyframes fp-hero-drift {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(3%, 4%) scale(1.08); }
}
/* Entree en cascade des elements du hero (fondu + glissement). Pas de classe
   fp-reveal ici : le hero est visible des le chargement, inutile de passer
   par l'IntersectionObserver commun (main.js). */
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-hero-detail .fp-hero-eyebrow,
  .fp-detail .fp-hero-detail .fp-hero-title,
  .fp-detail .fp-hero-detail .fp-hero-lead,
  .fp-detail .fp-hero-detail .fp-hero-icon {
    opacity: 0;
    animation: fp-hero-cascade .8s var(--fp-anim-ease) forwards;
  }
  .fp-detail .fp-hero-detail .fp-hero-eyebrow { animation-delay: .05s; }
  .fp-detail .fp-hero-detail .fp-hero-title { animation-delay: .16s; }
  .fp-detail .fp-hero-detail .fp-hero-lead { animation-delay: .32s; }
  .fp-detail .fp-hero-detail .fp-hero-icon { animation-delay: .46s; }
}
@keyframes fp-hero-cascade {
  from { opacity: 0; transform: translateY(22px); }
  to { opacity: 1; transform: translateY(0); }
}
/* Anneau pulse discret derriere l'icone de l'activite (repli statique en
   reduced-motion : le cercle reste visible, fixe, sans animation). */
.fp-detail .fp-hero-icon {
  position: relative;
}
.fp-detail .fp-hero-icon::before {
  content: '';
  position: absolute;
  inset: -14px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--fp-white) 45%, transparent);
  opacity: .7;
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-hero-icon::before {
    animation: fp-hero-ring 2.6s ease-out infinite;
  }
}
@keyframes fp-hero-ring {
  0% { transform: scale(.85); opacity: .55; }
  70%, 100% { transform: scale(1.25); opacity: 0; }
}
@media (max-width: 720px) {
  .fp-detail .fp-hero-detail::before,
  .fp-detail .fp-hero-detail::after {
    width: min(60vw, 360px);
  }
}

/* --------------------------------------------------------------------------
   BARRE D'ACTIONS : REFONTE LISIBILITÉ + CARACTÈRE (retour client : « la
   barre fixe de navigation n'est pas très jolie, fade, texte trop petit,
   et une fois qu'on scrolle le bouton Réserver devient illisible »).
   Parti pris (ajusté v2, retour client : « il me faut un truc qui fasse
   initialement la largeur du contenu, sinon c'est difforme ») : la barre
   fait AU REPOS la largeur du contenu du site (min(1300px, 90vw), pile la
   largeur du hero/.fp-wrap) et les 3 actions se PARTAGENT cette largeur ;
   capsule crème bordée teal 2px avec l'OMBRE DURE DÉCALÉE signature du
   site (registre em-card-border), libellés en Bebas nettement plus
   grands, action « Réserver » en dégradé teal plein avec reflet balayé au
   survol et petite pulsation périodique pour attirer l'oeil.
   AU CONDENSÉ (.is-condensed, posé par setupActbar main.js au défilement) :
   la typo NE DESCEND PLUS JAMAIS sous le seuil de lisibilité (1.05rem
   secondaires / 1.2rem Réserver, contre 0.7-0.82rem avant), seuls les
   paddings se resserrent en douceur. Entièrement au clavier (vrais <a>,
   focus-visible marqué), piste scrollable en filet de sécurité.
   POSITIONNEMENT INCHANGÉ (mécanique déjà fiable, ne pas y toucher) : la
   barre reste FIXED dès le chargement, ancrée une fois pour toutes en
   bas-centre de l'écran (left:50% + transform:translateX(-50%) + bottom
   fixe) - jamais de bascule relative -> fixed qui provoquerait un SAUT au
   défilement. Le JS gère aussi le fondu de fin de page (opacity/transform
   inline) au-delà de 90% de défilement, sans jamais toucher
   position/bottom non plus. */
/* Largeur = EXACTEMENT la largeur visible du contenu du site : .fp-wrap fait
   min(1300px, 90vw) MOINS ses gouttieres internes (padding 0 40px). Sans
   cette soustraction, la barre depassait des bords du contenu (retour
   client). */
.fp-detail .fp-actbar {
  position: fixed;
  left: 50%;
  right: auto;
  top: auto;
  bottom: 18px;
  transform: translateX(-50%);
  width: calc(min(1300px, 90vw) - var(--fp-gutter) * 2);
  z-index: 120;
  margin: 0;
  transition: width .4s ease, opacity .4s ease;
}
/* Le .fp-wrap interne (largeur globale + gouttières) est neutralisé : la
   largeur est portée par .fp-actbar lui-même, le dock remplit tout. */
.fp-detail .fp-actbar .fp-wrap {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
}
/* Entrée en scène unique au chargement (fondu + léger surgissement depuis le
   bas) : purement décorative, ne modifie JAMAIS l'état final (translateX(-50%)
   translateY(0)), identique à la position de repos statique -> aucun risque
   de saut au défilement ensuite, cf. commentaire ci-dessus. */
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-actbar {
    animation: fp-actbar-in .6s var(--fp-anim-ease) both;
  }
}
@keyframes fp-actbar-in {
  from { opacity: 0; transform: translateX(-50%) translateY(28px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
/* Condense au défilement : UNIQUEMENT la largeur change ici (position/
   bottom/transform identiques à l'état de repos, cf. bloc ci-dessus) ->
   zéro saut, juste un resserrement en douceur. La typo/padding des actions
   se resserrent en parallèle via .is-condensed plus bas, en restant
   pleinement lisibles (jamais sous 1.05rem / 1.2rem). */
.fp-detail .fp-actbar.is-condensed {
  width: min(720px, 60vw);
}
@media (max-width: 1024px) {
  .fp-detail .fp-actbar { width: 95vw; }
  .fp-detail .fp-actbar.is-condensed { width: 78vw; }
}
@media (max-width: 768px) {
  /* 100 % et non 100vw : la barre est en position fixe, sa boîte se mesure
     donc sur le bloc conteneur initial, qui EXCLUT la barre de défilement,
     alors que 100vw l'INCLUT. Avec 100vw, la barre pouvait dépasser la
     largeur réellement visible sur une fenêtre étroite munie d'une barre de
     défilement classique. Le centrage (left: 50%) se mesure sur le même
     conteneur : le rendu est identique, sans le risque de débordement. */
  .fp-detail .fp-actbar { width: calc(100% - 16px); }
  .fp-detail .fp-actbar.is-condensed { width: 92vw; }
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-actbar,
  .fp-detail .fp-actbar-item {
    transition: none;
    animation: none;
  }
}
/* Capsule unique et flottante : les 3 actions vivent DANS le meme conteneur.
   Surface creme degradee OPAQUE (demande client historique : pas de
   transparence), bordure teal franche 2px et ombre dure decalee signature
   (registre em-card-border du site) doublee d'une ombre ambiante douce.
   overflow-x:auto en filet de securite (jamais de contenu masque si des
   libelles longs etaient saisis dans la zone), barre de defilement masquee. */
.fp-detail .fp-actbar-dock {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  gap: 6px;
  padding: 9px;
  overflow-x: auto;
  scrollbar-width: none;
  border-radius: var(--fp-pill);
  background: linear-gradient(165deg, var(--fp-white) 0%, var(--fp-cream) 100%);
  border: 2px solid var(--fp-primary);
  box-shadow: 6px 6px 0 0 color-mix(in srgb, var(--fp-secondary-dark) 90%, transparent), 0 24px 44px -18px color-mix(in srgb, var(--fp-ink) 40%, transparent);
}
.fp-detail .fp-actbar-dock::-webkit-scrollbar { display: none; }
/* Chaque action : icône + libellé en Bebas, taille nettement relevée
   (retour client : texte trop petit). Les actions se PARTAGENT toute la
   largeur de la barre (flex:1) : avec trois entrées seulement, un
   dimensionnement au contenu laissait la barre difforme par rapport au
   contenu du site. Survol : teinte teal douce. */
/* Graisse 400 : c'est la SEULE vraie graisse de Bebas Neue - un font-weight
   600/700 declenchait un faux gras synthetise par le navigateur, pateux et
   peu lisible (cause du « pas tres lisible » remonte par le client). */
.fp-detail .fp-actbar-item {
  position: relative;
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 22px;
  border-radius: var(--fp-pill);
  color: var(--fp-secondary-dark);
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: 1.3rem;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: .05em;
  text-decoration: none;
  white-space: nowrap;
  transition: background .25s ease, color .25s ease, transform .25s ease, padding .3s ease, font-size .3s ease;
}
.fp-detail .fp-actbar-item:hover,
.fp-detail .fp-actbar-item:focus-visible {
  color: var(--fp-primary-dark);
  background: color-mix(in srgb, var(--fp-primary) 12%, transparent);
}
/* Separateur fin entre les actions SECONDAIRES (retour client : sans lui,
   on ne devine les elements cliquables qu'au survol). Pseudo-element sur
   chaque action secondaire sauf la premiere, centre dans le gap de 6px du
   dock ; jamais autour de « Reserver » (.is-main se detache deja seul, et
   son ::before porte le reflet). */
.fp-detail .fp-actbar-item:not(.is-main):not(:first-child)::before {
  content: '';
  position: absolute;
  left: -4px;
  top: 50%;
  transform: translateY(-50%);
  width: 1.5px;
  height: 22px;
  border-radius: 1px;
  background: color-mix(in srgb, var(--fp-primary) 32%, transparent);
  pointer-events: none;
}
.fp-detail .fp-actbar-item:focus-visible {
  outline: 2px solid var(--fp-primary);
  outline-offset: 2px;
}
/* Action PRINCIPALE « Réserver » : vrai bouton plein en dégradé teal, la plus
   grande de la barre, avec un fin liseré lumineux en haut. Reflet balayé au
   survol (::before) + micro pulsation périodique (propriété scale, ne touche
   pas au transform du survol) pour attirer l'oeil sans agresser. */
/* Vraie graisse Bebas (400, cf. commentaire ci-dessus) et taille encore un
   cran au-dessus des actions secondaires. Le survol NE CHANGE PLUS le
   background lui-meme (un degrade ne s'interpole pas -> bascule brutale
   constatee par le client) : un VOILE sombre (::after) fond en opacite
   par-dessus le degrade, transition douce garantie. */
/* LIBELLE COUPE SANS SIGNAL (banc d'essai, tools/bench-visuel/libelles.mjs) :
   le libellé de cette action est saisi par la cliente. Dès qu'il dépassait sa
   part de largeur, il était tranché en plein mot, sans points de suspension ni
   aucun indice, à TOUTES les largeurs, 1440 px compris.
   Cause : « overflow: hidden » (indispensable ici, il détoure le reflet ::before
   dans la pilule) change la taille minimale automatique du conteneur flexible.
   Par défaut « min-width: auto » vaut la taille du contenu et empêche un
   élément flexible de se réduire en dessous de son texte, MAIS cette règle ne
   s'applique que si overflow vaut visible. Avec overflow: hidden le minimum
   retombe à 0 : combiné à « flex: 1.25 1 0 » (base nulle) et à
   « white-space: nowrap » hérité, le libellé n'avait plus aucun plancher.
   Correctif : on repose explicitement le plancher que overflow: hidden a
   supprimé. Inerte pour les libellés courts actuels ; quand le texte s'allonge,
   c'est le dock qui défile (il est déjà en overflow-x: auto) au lieu de couper
   le texte. */
.fp-detail .fp-actbar-item.is-main {
  overflow: hidden;
  flex: 1.25 1 0;
  min-width: max-content;
  padding: 15px 30px;
  background: linear-gradient(135deg, var(--fp-primary) 0%, var(--fp-primary-dark) 100%);
  color: var(--fp-white);
  font-weight: 400;
  font-size: 1.45rem;
  letter-spacing: .06em;
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--fp-white) 30%, transparent), 0 10px 24px -10px color-mix(in srgb, var(--fp-primary) 85%, transparent);
}
/* Voile de survol : sous le reflet et sous le texte (z-index 0 / 1 / 2). */
.fp-detail .fp-actbar-item.is-main::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background: linear-gradient(135deg, var(--fp-secondary-dark) 0%, var(--fp-secondary) 100%);
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
}
.fp-detail .fp-actbar-item.is-main:hover::after,
.fp-detail .fp-actbar-item.is-main:focus-visible::after {
  opacity: 1;
}
.fp-detail .fp-actbar-item.is-main .fp-actbar-ic,
.fp-detail .fp-actbar-item.is-main .fp-actbar-label {
  position: relative;
  z-index: 2;
}
.fp-detail .fp-actbar-item.is-main::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  z-index: 1;
  width: 45%;
  background: linear-gradient(105deg, transparent, color-mix(in srgb, var(--fp-white) 45%, transparent), transparent);
  transform: skewX(-18deg);
  pointer-events: none;
}
.fp-detail .fp-actbar-item.is-main:hover::before,
.fp-detail .fp-actbar-item.is-main:focus-visible::before {
  animation: fp-actbar-shine .7s ease;
}
@keyframes fp-actbar-shine { to { left: 130%; } }
.fp-detail .fp-actbar-item.is-main:hover,
.fp-detail .fp-actbar-item.is-main:focus-visible {
  color: var(--fp-white);
  transform: translateY(-2px);
  box-shadow: 0 16px 30px -10px color-mix(in srgb, var(--fp-secondary-dark) 70%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-actbar-item.is-main::after { transition: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-actbar-item.is-main {
    animation: fp-actbar-cta-pulse 6s ease-in-out infinite;
  }
}
@keyframes fp-actbar-cta-pulse {
  0%, 86%, 100% { scale: 1; }
  91% { scale: 1.05; }
  96% { scale: .99; }
}
.fp-detail .fp-actbar-ic {
  display: inline-flex;
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
}
.fp-detail .fp-actbar-ic svg {
  width: 100%;
  height: 100%;
}
/* Suffixe réduit « (Magic Kids) » du bouton principal des activités de la
   zone (Marino, 2026-09-08/09 : « Réserver Magic Kids c'est un peu trop
   long, on peut simplement mettre Réserver, et Magic Kids entre parenthèses
   en beaucoup plus petit »). Le libellé plein reste au réglage Customizer
   (fp_zone_kids_access_label) : seul ce FRAGMENT est détaché au rendu
   (fp_actbar_kids_label_split, inc/sections.php) en taille nettement
   réduite, pour que la pastille ne s'allonge plus et ne force jamais de
   retour à la ligne sur la barre d'action COLLANTE en bas de l'écran
   mobile. Taille en em : suit automatiquement chaque palier de .is-main
   (repos, condensé, mobile), sans règle dédiée à ajouter ailleurs. Casse et
   graisse EN CAPITALES héritées de .fp-actbar-item (même traitement que les
   libellés secondaires écrits en police de corps sous 768px, juste
   au-dessous), l'opacité réduite suffit à le faire passer au second plan. */
.fp-detail .fp-actbar-label-sub {
  display: inline-block;
  margin-left: .35em;
  font-family: var(--fp-font-body);
  font-weight: 600;
  font-size: .5em;
  letter-spacing: .01em;
  opacity: .82;
}
@media (max-width: 768px) {
  /* RETOUR CLIENT (2026-08-17, choix validé) : sous cette largeur, les actions
     secondaires ne sont plus des pastilles muettes réduites à leur icône (on ne
     savait pas ce que l'on touchait). Elles passent en colonne, ICÔNE EN HAUT
     et LIBELLÉ ÉCRIT DESSOUS EN TOUT PETIT (11px, 10px sous 400px). Le libellé
     descend en police de CORPS : à cette taille, la police de titre condensée
     serait illisible (même règle que les libellés de lignes du tableau de
     tarifs, plus bas dans cette feuille).
     Cible tactile : 8 + 22 (icône) + 4 + 11 (libellé) + 8 = 53px de haut,
     au-dessus de la convention de 44px du projet.
     « Réserver » descend d'un cran (1.25rem -> 1.12rem, retraits 24px -> 20px)
     mais reste de très loin l'action la plus grosse de la barre. */
  .fp-detail .fp-actbar-item { padding: 13px 15px; }
  .fp-detail .fp-actbar-item:not(.is-main) {
    flex-direction: column;
    gap: 4px;
    padding: 8px 12px;
    min-height: 44px;
  }
  .fp-detail .fp-actbar-item:not(.is-main) .fp-actbar-label {
    display: block;
    font-family: var(--fp-font-body);
    font-weight: 600;
    font-size: 11px;
    line-height: 1;
    letter-spacing: .02em;
  }
  .fp-detail .fp-actbar-item.is-main { font-size: 1.12rem; padding: 14px 20px; }
}
/* Condense (défilement) : SEULS les paddings se resserrent un peu, la typo
   reste largement lisible (demande client explicite : ne plus jamais rendre
   « Réserver » illisible une fois la page défilée). */
.fp-detail .fp-actbar.is-condensed .fp-actbar-item {
  font-size: 1.05rem;
  /* 13px de padding vertical et non 10 : en condensé sous 768px, le libellé
     des boutons secondaires est masqué et il ne reste que l'icône de 18px ;
     à 10px la cible tactile tombait à ~38px, sous la convention de 44px du
     projet (relevé du chantier responsive du 2026-08-14). */
  padding: 13px 16px;
  gap: 8px;
}
.fp-detail .fp-actbar.is-condensed .fp-actbar-item.is-main {
  font-size: 1.2rem;
  /* 13px de vertical : à 12px la cible tombait à ~43px, juste sous la
     convention de 44px (relevé de la revue responsive du 2026-08-14). */
  padding: 13px 24px;
}
/* TELEPHONES TRES ETROITS : le libellé « Réserver » ne peut plus être tranché
   (cf. le min-width: max-content posé plus haut), mais à 320 px la barre
   entière réclamait 343 px pour 300 px disponibles et devait donc défiler,
   ce qui reléguait justement l'action principale hors du champ. On resserre
   les retraits juste ce qu'il faut pour que TOUT tienne sans défilement.
   Les deux états sont traités : au repos et une fois la page défilée
   (.is-condensed), dont les retraits sont plus spécifiques. Seuls les retraits
   et l'écart bougent : la taille du texte, elle, ne baisse pas (demande client
   explicite de ne jamais rendre « Réserver » illisible). */
@media (max-width: 400px) {
  .fp-detail .fp-actbar-dock { gap: 4px; padding: 7px; }
  .fp-detail .fp-actbar-item,
  .fp-detail .fp-actbar.is-condensed .fp-actbar-item { padding-left: 9px; padding-right: 9px; }
  .fp-detail .fp-actbar-item.is-main,
  .fp-detail .fp-actbar.is-condensed .fp-actbar-item.is-main { padding-left: 16px; padding-right: 16px; }
  /* 10px et non 11px : à 320px, les trois actions réclament alors 273px de
     contenu pour 278px disponibles dans la capsule, tout tient donc encore
     sans défilement, libellés écrits compris. */
  .fp-detail .fp-actbar-item:not(.is-main) .fp-actbar-label { font-size: 10px; }
}
.fp-detail .fp-actbar.is-condensed .fp-actbar-ic { width: 18px; height: 18px; }
/* Condensé SUR MOBILE : exactement la même grammaire qu'au repos, simplement
   resserrée (l'icône est déjà passée à 18px juste au-dessus). Le libellé reste
   écrit sous l'icône, la cible tactile reste au-dessus de la convention de
   44px (7 + 18 + 3 + 11 + 7 = 46px) et « Réserver » reste l'action la plus
   grosse (1.05rem contre 11px). Sans ce bloc, l'action principale condensée
   serait restée à 1.2rem, donc PLUS GROSSE qu'au repos (1.12rem) : les deux
   états doivent rester cohérents entre eux. */
@media (max-width: 768px) {
  .fp-detail .fp-actbar.is-condensed .fp-actbar-item:not(.is-main) {
    gap: 3px;
    padding-top: 7px;
    padding-bottom: 7px;
  }
  .fp-detail .fp-actbar.is-condensed .fp-actbar-item.is-main {
    font-size: 1.05rem;
    padding-top: 13px;
    padding-bottom: 13px;
  }
}

/* --------------------------------------------------------------------------
   INTRO DÉTAIL (.fp-intro-detail) : COMPOSITION v4 (nouveau refus client sur
   la v3 « colonne de texte + carte-sidebar » : rendu widget étriqué,
   « catastrophique »). Nouvelle scène en 2 colonnes CENTRÉES verticalement :
   texte à gauche (fil d'Ariane -> titre display Thoge + trait d'accent ->
   accroche avec chapeau -> bouton -> encart Magic Kids éventuel) ; à droite
   une ARCHE pleine couleur primary texturée ton sur ton par le plan du parc
   (assets/img/em-plan.svg, traits #7db8b4 sur aplat #2a7e74) sur laquelle la
   mascotte est posée en entier (contain, jamais recadrée) et dépasse du
   sommet. Les informations clés deviennent des BADGES pilules épinglés qui
   chevauchent le bas de l'arche (rotation alternée, redressés au survol).
   Mêmes informations, même image, contrat Gutenberg inchangé.
   -------------------------------------------------------------------------- */
/* Largeur : ALIGNEE sur la largeur globale du site (1300px) - la surcharge
   1400px heritee du source RParc creait un decalage visible avec le hero et
   la barre d'actions (retour client : « meme largeur partout »). */
.fp-detail .fp-intro-detail {
  background: var(--fp-paper);
  padding: calc(var(--fp-section-y) - 24px) 0 calc(var(--fp-section-y) - 16px);
}
.fp-detail .fp-breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
  font-size: .9rem;
  font-weight: 400;
}
/* Chevron decoratif en tete du fil (remplace l'ancienne petite image de
   zone, abandonnee). */
.fp-detail .fp-breadcrumb-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  color: var(--fp-primary);
}
.fp-detail .fp-breadcrumb-chevron svg {
  width: 100%;
  height: 100%;
}
.fp-detail .fp-breadcrumb-sep {
  opacity: .5;
}
.fp-detail .fp-breadcrumb-current {
  color: var(--fp-ink-soft);
}
/* Les liens du fil d'Ariane utilisent le soulignement anime GLOBAL des
   liens texte (main.css, bloc « Liens texte ») : plus de soulignement
   statique dedie ici. */
/* DÉFAUT CORRIGÉ (banc d'essai visuel, 2026-08-05) : mesurés à 45 x 25 px, les
   liens du fil d'Ariane sont sous la cible tactile minimale de 44 px, à TOUTES
   les largeurs (modèles activité, point de restauration et Magic Kids, tous
   porteurs de .fp-detail). On agrandit la zone de contact SANS toucher au
   dessin : un calque transparent centré sur le lien porte les 44 px. Le
   soulignement animé global passe par background-image, pas par un
   pseudo-élément : ::after est donc libre. */
.fp-detail .fp-breadcrumb-link { position: relative; }
.fp-detail .fp-breadcrumb-link::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 44px;
}
/* Deux colonnes a parts quasi egales (retour client 2026-09-03 : « plus que
   deux colonnes », scène agrandie). Les minimums evitent que l'une des deux
   s'ecrase avant le passage en 1 colonne (voir le breakpoint 980px). */
/* Colonnes calées EN HAUT (Marino, 2026-09-07 : « garder la galerie en face
   du titre ») : avec align-items: center, une colonne de texte longue
   (accroche, bouton, badges) faisait descendre la scène au milieu. */
.fp-detail .fp-intro-grid-detail {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(360px, 1fr);
  align-items: start;
  gap: clamp(40px, 5vw, 76px);
}
/* Colonne de texte : flux naturel (fil d'Ariane, titre, accroche, bouton,
   encart Magic Kids). Un peu d'air au-dessus du fil d'Ariane (retour
   client v4.3). */
.fp-detail .fp-intro-col {
  min-width: 0;
  padding-top: 18px;
}
/* Titre en Bebas (police de titres du site), grand mais raisonnable (retour
   client v4.2 : « un peu moins grand »). SANS .fp-reveal côté PHP : c'est
   l'apparition automatique des titres (setupHeadingReveal, cascade de
   caractères) qui le pilote seule, comme les autres h2 du site. Garde
   anti-coupure stricte conservée (règle dure du projet : jamais de mot
   coupé), largeur confortable pour 2 lignes pleines. */
.fp-detail .fp-intro-title {
  max-width: 20ch;
  text-align: left;
  margin: 0 0 18px;
  font-family: var(--fp-font-heading);
  font-weight: 700;
  font-size: clamp(38px, 4vw, 58px);
  line-height: .98;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: var(--fp-ink);
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
}
/* Trait d'accent sous le titre : dégradé primary -> accent, signature de la
   refonte (remplace la barre verticale noire de la v3, jugée sévère). */
.fp-detail .fp-intro-title::after {
  content: '';
  display: block;
  width: 76px;
  height: 5px;
  margin-top: 16px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--fp-primary), var(--fp-accent));
}
/* Accroche : premier paragraphe en chapeau (plus grand, encre pleine), la
   suite en gris doux. Plus de barre latérale. */
.fp-detail .fp-intro-col .fp-intro-body.fp-prose {
  max-width: 54ch;
  margin: 0 0 26px;
  color: var(--fp-ink-soft);
}
.fp-detail .fp-intro-col .fp-intro-body.fp-prose p:first-child {
  font-size: 1.14rem;
  line-height: 1.55;
  color: var(--fp-ink);
}
.fp-detail .fp-intro-actions {
  /* Le bouton ferme la colonne depuis le 2026-09-09 (fil d'Ariane, titre,
     pilules, bouton) : il lui faut son propre espace au-dessus, que portaient
     jusque-la les pilules qui le suivaient. */
  margin: 30px 0 0;
}
/* Scène décorative : arche + mascotte + badges. La figure entière porte le
   .fp-reveal (les badges internes n'en portent pas, cf. commentaire PHP). */
.fp-detail .fp-intro-figure {
  position: relative;
  min-width: 0;
  /* Décalage égal au fil d'Ariane et à son air : la scène commence à la
     hauteur du titre, pas de la miette de pain. */
  margin-top: 56px;
}
/* Scène : overflow hidden = c'est elle qui CLIPPE le bas de la mascotte
   (demande client v4.1 : « qu'elle dépasse en haut de la zone verte mais
   pas en bas, on cache le débordement pour un effet de profondeur »). Le
   bas de l'arche affleure le bas de la scène : la coupe se fait donc pile
   au bord de la zone verte, tandis que le haut reste libre (la mascotte
   dépasse du sommet de l'arche tout en restant dans la boîte de scène). */
.fp-detail .fp-intro-scene {
  position: relative;
  width: 100%;
  aspect-ratio: 10 / 11;
  overflow: hidden;
}
/* Anneau pointillé décoratif en haut à droite de la scène, rotation lente
   (même registre que la pastille tarifs), purement décoratif. Entièrement
   DANS la scène (overflow hidden ci-dessus, il serait rogné dehors). */
.fp-detail .fp-intro-scene::before {
  content: '';
  position: absolute;
  top: 4%;
  right: 2%;
  z-index: 0;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  /* Vert plein (retour client 2026-09-03) : sur la page galerie, l'anneau ne
     repose plus forcement sur l'aplat vert de l'arche, un trait mi-transparent
     s'y voyait mal. Un vert plein reste lisible sur n'importe quel fond. */
  border: 2px dashed var(--fp-primary);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-intro-scene::before {
    animation: fp-intro-ring-spin 36s linear infinite;
  }
}
@keyframes fp-intro-ring-spin { to { transform: rotate(360deg); } }
/* Arche : aplat primary + plan du parc en texture ton sur ton (les traits
   #7db8b4 du SVG ressortent doucement sur le #2a7e74), ombre interne en bas
   pour asseoir la mascotte. */
.fp-detail .fp-intro-stage {
  position: absolute;
  inset: 20% 0 0 0;
  border-radius: 999px 999px var(--fp-radius-lg) var(--fp-radius-lg);
  background-color: var(--fp-primary);
  background-image: url('../img/em-plan.svg');
  background-size: 150%;
  background-position: center 32%;
  box-shadow: inset 0 -40px 60px -36px color-mix(in srgb, var(--fp-secondary-dark) 80%, transparent), var(--fp-shadow-lg);
}
/* Mascotte : dépasse du sommet de l'arche ; ses pieds descendent SOUS le
   bord bas de la scène (bottom négatif) et sont coupés par l'overflow
   hidden -> elle semble sortir de la zone verte. Agrandie (v4.2, retour
   client : « un peu plus grande, que l'illusion soit meilleure en bas ») :
   hauteur au-delà de la scène + coupe plus franche des pieds. */
.fp-detail .fp-intro-mascotte {
  position: absolute;
  bottom: -8%;
  left: 50%;
  z-index: 1;
  height: 106%;
  max-width: 96%;
  object-fit: contain;
  object-position: bottom center;
  transform: translateX(-50%);
  filter: drop-shadow(0 22px 24px color-mix(in srgb, var(--fp-secondary-dark) 40%, transparent));
}
/* Apparition en FADE IN UP depuis l'intérieur de la zone verte (demande
   client) : cachée tant que la figure n'est pas révélée, puis elle monte en
   fondu quand main.js pose .is-in sur .fp-intro-figure (.fp-reveal). Le
   flottement continu prend le relais APRÈS l'entrée (2e animation de la
   liste, retardée : la cascade la fait gagner une fois active). Etat caché
   UNIQUEMENT sous no-preference : en mouvement réduit (ou sans l'entrée
   jouée), la mascotte reste simplement visible et immobile. */
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-intro-mascotte {
    opacity: 0;
    transform: translateX(-50%) translateY(48px);
  }
  .fp-detail .fp-intro-figure.is-in .fp-intro-mascotte {
    animation:
      fp-intro-mascotte-in .9s var(--fp-anim-ease) .25s both,
      fp-intro-mascotte-float 6s ease-in-out 1.4s infinite;
  }
}
@keyframes fp-intro-mascotte-in {
  from { opacity: 0; transform: translateX(-50%) translateY(48px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
@keyframes fp-intro-mascotte-float {
  0%, 100% { opacity: 1; transform: translateX(-50%) translateY(0); }
  50% { opacity: 1; transform: translateX(-50%) translateY(-8px); }
}

/* --------------------------------------------------------------------------
   CARROUSEL DE LA GALERIE DANS LA SCÈNE (pages d'activité, 2026-09-03).
   La galerie a quitté la section « Comment ça marche », retirée du rendu à la
   demande de la cliente, pour venir occuper la scène de l'intro.
   FORME REVUE LE MÊME JOUR (retour client) : l'arche de .fp-intro-stage,
   pensée pour une mascotte illustrée, coupait mal de vraies photos (angle
   « laid »). Le carrousel n'emprunte donc plus cette géométrie : coins
   uniformément arrondis, cadre souligné d'une bordure verte, ÉPAISSIE À 7px
   (retour client) pour mieux détacher le cadre du fond très blanc de la
   section. L'anneau pointillé décoratif commun (.fp-intro-scene::before) est
   désactivé sur cette variante, remplacé par un décor dédié, voir plus bas
   dans ce fichier (« DÉCOR ANIMÉ AUTOUR DE LA GALERIE »).
   .fp-intro-stage (l'arche) continue d'être rendue en dessous (span vide,
   voir fp_render_intro_detail) mais est désormais MASQUÉE en CSS : sa forme
   en arche ne correspondait plus au cadre rectangulaire du carrousel, et un
   reste de vert dépassait aux DEUX COINS BAS, sous le radius du carrousel
   (retour client). Le fond de chargement derrière les photos, avant qu'elles
   n'apparaissent, est donc porté par le carrousel lui-même, au même radius.
   Voir fp_activite_intro_galerie() (inc/sections.php) pour le périmètre et la
   sortie de secours, et setupCarousels() (main.js) pour le pilotage.
   -------------------------------------------------------------------------- */
.fp-detail .fp-intro-carousel {
  position: absolute;
  inset: 20% 0 0 0;
  z-index: 1;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  gap: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  border-radius: var(--fp-radius-lg);
  border: 7px solid var(--fp-primary);
  background-color: var(--fp-primary);
  box-shadow: inset 0 -40px 60px -36px color-mix(in srgb, var(--fp-secondary-dark) 80%, transparent);
}
.fp-detail .fp-intro-carousel::-webkit-scrollbar { display: none; }
/* Chaque photo est un LIEN vers son fichier (ouvre la visionneuse, cf.
   setupLightbox dans main.js ; sans JavaScript, la photo reste consultable,
   même patron que la galerie bandeau) : l'habillage natif est retiré pour
   retrouver la mise en forme d'un simple calque décoratif, et un focus visible
   est dessiné À L'INTÉRIEUR du cadre (outline-offset négatif) puisque le
   carrousel est en overflow-y: hidden et couperait un anneau qui déborderait
   vers l'extérieur. */
.fp-detail .fp-intro-carousel-slide {
  display: block;
  position: relative;
  overflow: hidden;
  scroll-snap-align: start;
  background-size: cover;
  background-position: center;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: transparent;
  font: inherit;
  color: inherit;
  text-decoration: none;
  cursor: zoom-in;
}
.fp-detail .fp-intro-carousel-slide:focus-visible {
  outline: 3px solid var(--fp-white);
  outline-offset: -6px;
}
/* Même respiration lente que le carrousel de la section étapes qu'il remplace
   (le fond hérité est ré-appliqué sur un calque pour pouvoir l'animer sans
   toucher au scroll-snap du parent). */
.fp-detail .fp-intro-carousel-slide::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: inherit;
  background-size: cover;
  background-position: center;
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-intro-carousel-slide::before {
    animation: fp-etapes-kenburns 16s ease-in-out infinite alternate;
  }
}
/* Voile bas : assied les photos dans le cadre et garde les flèches lisibles
   quelle que soit la photo. */
.fp-detail .fp-intro-carousel-slide::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 88px;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--fp-secondary-dark) 55%, transparent));
  pointer-events: none;
}
/* display:contents : chaque flèche se positionne directement par rapport à
   .fp-intro-scene (position:relative). Même idiome que .fp-etapes-carousel-nav,
   et l'ordre DOM (prev puis next) reste celui que lit le JS.
   Centrage vertical sur le CADRE du carrousel, pas sur la scène entière : le
   cadre commence à 20% du haut (même inset que .fp-intro-carousel), son
   milieu est donc à 60%. */
.fp-detail .fp-intro-carousel-nav {
  display: contents;
}
.fp-detail .fp-intro-carousel-nav .fp-carousel-arrow {
  position: absolute;
  top: 60%;
  transform: translateY(-50%);
  z-index: 2;
  background: var(--fp-white);
  color: var(--fp-primary);
}
.fp-detail .fp-intro-carousel-nav .fp-carousel-arrow:first-child { left: 10px; }
.fp-detail .fp-intro-carousel-nav .fp-carousel-arrow:last-child { right: 10px; }
/* Le centrage vertical doit survivre au survol : .fp-carousel-arrow applique
   scale(1.06) au hover (main.css) et les transform ne s'additionnent pas entre
   règles. Même précaution que sur le carrousel des étapes. */
.fp-detail .fp-intro-carousel-nav .fp-carousel-arrow:hover {
  background: var(--fp-dark);
  color: var(--fp-white);
  transform: translateY(-50%) scale(1.06);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-intro-carousel-nav .fp-carousel-arrow:hover {
    transform: translateY(-50%);
  }
}
/* Bouton « voir la galerie complète » : à cheval sur la bordure basse du
   cadre (retour client 2026-09-03). Reste dans le flux (pas de position
   absolute : .fp-intro-scene a un overflow hidden qui le rognerait), un
   simple margin-top negatif le remonte pour que la bordure du carrousel
   traverse son milieu vertical. -23px = moitie de la hauteur intrinseque du
   bouton (padding 14px haut/bas + bordure 1px + ligne de texte ~16px = 46px).
   Peint APRES la scene dans le DOM -> passe naturellement au-dessus d'elle
   sans z-index. */
.fp-detail .fp-intro-gallery-link {
  display: inline-flex;
  margin: -23px auto 0;
  position: relative;
  z-index: 2;
}
.fp-detail .fp-intro-figure-galerie {
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* La scène passe au premier plan de son propre contexte d'empilement (voir le
   bloc de décor juste en dessous) : z-index: 1 au-dessus des décors, sous le
   bouton .fp-intro-gallery-link (z-index: 2, déjà en place). .fp-intro-figure
   (règle commune, plus haut) porte déjà .fp-reveal, qui établit un contexte
   d'empilement à lui seul (will-change: transform) : ces z-index restent donc
   confinés à cette figure, sans effet sur le reste de la page. */
.fp-detail .fp-intro-figure-galerie .fp-intro-scene {
  width: 100%;
  position: relative;
  z-index: 1;
  /* Cadre aplati à 16:9 le 2026-09-09 (demande de Marino). Deux raisons qui
     vont dans le même sens : la colonne de gauche a perdu son texte
     d'introduction et se termine désormais sur le bouton, si bien qu'un cadre
     en 4/3 la dépassait nettement en hauteur ; et la plupart des photos
     déposées par la cliente sont justement en 16:9, elles ne sont donc plus
     recadrées du tout. Largeur inchangée, même grille deux colonnes. Les
     photos restent en background-size: cover
     (.fp-intro-carousel-slide), déjà l'équivalent d'un object-fit: cover
     pour un calque de fond. */
  aspect-ratio: 16 / 9;
}
/* CARROUSEL CALÉ EN HAUT DE LA SCÈNE (Marino, 2026-09-07 : « la galerie est
   centrée verticalement on dirait ») : la règle commune .fp-intro-carousel
   le fait démarrer à 20 % de la hauteur (inset: 20% 0 0 0, place réservée à
   la mascotte qui dépassait de l'arche sur la variante portrait). Sur la
   variante galerie, cette réserve n'a plus d'objet : le cadre commence au
   sommet de la scène, en face du titre. */
.fp-detail .fp-intro-figure-galerie .fp-intro-carousel {
  inset: 0;
}

/* Coins bas de la galerie (retour client) : l'arche de .fp-intro-stage ne
   correspond plus au cadre du carrousel et laissait voir du vert derrière son
   radius. Elle reste dans le contenu (span vide, voir fp_render_intro_detail)
   mais n'est plus affichée du tout sur cette variante. */
.fp-detail .fp-intro-figure-galerie .fp-intro-stage {
  display: none;
}
/* L'anneau pointillé commun à la scène (portrait ET galerie, cf. plus haut
   dans ce fichier) est confiné par l'overflow: hidden de .fp-intro-scene :
   sur la variante galerie, il est désactivé au profit du décor dédié
   ci-dessous, qui peut déborder du cadre. */
.fp-detail .fp-intro-figure-galerie .fp-intro-scene::before {
  display: none;
}

/* --------------------------------------------------------------------------
   DÉCOR ANIMÉ AUTOUR DE LA GALERIE (variante galerie uniquement, 2026-09-03).
   Le fond très blanc de la section autour du cadre de photos reste nu :
   deux pseudo-éléments décoratifs occupent cet espace, portés par la FIGURE
   entière (jamais par .fp-intro-scene, dont l'overflow: hidden couperait tout
   débordement) et placés DERRIÈRE la scène (z-index négatif ou nul, contre le
   z-index: 1 de .fp-intro-scene juste au-dessus) : jamais devant les photos
   ni le bouton. Purement décoratifs (pseudo-éléments, jamais lus par un
   lecteur d'écran), rotation et flottement lents, désactivés en mouvement
   réduit. Réduits sous 980px avec .fp-intro-figure (voir plus bas dans ce
   fichier), pour ne jamais dépasser la figure resserrée sur mobile. Le verrou
   de défilement latéral (main.css, overflow-x: clip sur html/body) protège de
   toute façon la page d'un défilement horizontal si l'un de ces décors
   dépassait légèrement du cadre du site.
   -------------------------------------------------------------------------- */
/* Grand anneau en haut à droite : descendu (retour client 2026-09-03, « descends-le
   en partie derrière la galerie ») pour qu'environ un tiers passe sous le coin
   haut droit du cadre, qui commence à 20 % de la hauteur de la scène. */
.fp-detail .fp-intro-figure-galerie::before {
  content: '';
  position: absolute;
  top: 6%;
  right: -12%;
  z-index: 0;
  width: 160px;
  height: 160px;
  border-radius: 50%;
  border: 2px dashed var(--fp-primary);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-intro-figure-galerie::before {
    animation: fp-intro-ring-spin 42s linear infinite;
  }
}
/* Second anneau, plus petit, en bas à gauche (retour client 2026-09-03 :
   « fais-en un deuxième ailleurs, en plus petit ») : remplace le disque flou
   du premier jet, même trait pointillé, tourne en sens inverse et plus
   lentement, lui aussi en partie sous le cadre. */
.fp-detail .fp-intro-figure-galerie::after {
  content: '';
  position: absolute;
  bottom: 5%;
  left: -9%;
  z-index: -1;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 2px dashed var(--fp-primary);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-intro-figure-galerie::after {
    animation: fp-intro-ring-spin 54s linear infinite reverse;
  }
}

/* L'ENCART « MAGIC KIDS - ACCÈS PAYANT » (.fp-kids-notice) A ÉTÉ RETIRÉ EN
   ENTIER le 2026-08-12 (mots du client : « faut l'enlever des pages Magic
   Kids, le tarif est déjà plus bas ») : la zone TARIFS de la page est la
   seule source du prix et de la mention d'accès. Plus aucun markup ne porte
   ces classes, voir fp_render_intro_detail, inc/sections.php. */

/* --------------------------------------------------------------------------
   INFORMATIONS CLÉS (.fp-intro-badges) : v5 (2026-09-03), les badges pilules
   (pastille d'icône primary + libellé) vivent SOUS le texte, dans la colonne
   de gauche, en rangée horizontale qui retombe à la ligne (même traitement
   que le repli mobile déjà en place, réutilisé ici pour le desktop). Avant
   la v5, ils formaient une colonne centrale verticale entre texte et scène.
   Contrat de données INCHANGÉ : fp_intro_stat_cards() (image optionnelle +
   légende obligatoire, group fp-zone-stats ou repli à plat). */
.fp-detail .fp-intro-badges {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: 14px 16px;
  /* Les pilules sont passées AU-DESSUS du bouton le 2026-09-09 : leur marge
     haute n'a plus à compenser la proximité du bouton, elle prend juste le
     relais du trait qui suit le titre. C'est desormais .fp-intro-actions qui
     porte l'espace, en dessous. */
  margin: 30px 0 0;
  padding: 0;
  max-width: none;
  list-style: none;
}
.fp-detail .fp-intro-badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 7px 18px 7px 8px;
  background: var(--fp-paper);
  border: 1.5px solid color-mix(in srgb, var(--fp-primary) 40%, transparent);
  border-radius: var(--fp-pill);
  box-shadow: 0 12px 24px -12px color-mix(in srgb, var(--fp-secondary-dark) 55%, transparent);
  transform: rotate(-1.8deg);
  transition: transform .3s ease, box-shadow .3s ease, border-color .3s ease;
}
.fp-detail .fp-intro-badge:nth-child(even) {
  transform: rotate(1.5deg);
}
.fp-detail .fp-intro-badge:hover {
  transform: rotate(0deg) translateY(-3px);
  border-color: var(--fp-primary);
  box-shadow: 0 16px 28px -12px color-mix(in srgb, var(--fp-secondary-dark) 65%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-intro-badge {
    transform: none;
    transition: none;
  }
  .fp-detail .fp-intro-badge:nth-child(even) { transform: none; }
  .fp-detail .fp-intro-badge:hover { transform: none; }
}
/* Pastille d'icône : ronde, fond primary uni, contient l'image éditable
   (fp-zone-stat) ou, à défaut, une icône décorative de repli. */
.fp-detail .fp-intro-badge-medal {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--fp-primary);
}
.fp-detail .fp-intro-badge-medal img {
  max-width: 60%;
  max-height: 60%;
  width: auto;
  object-fit: contain;
}
.fp-detail .fp-intro-badge-medal svg {
  width: 18px;
  height: 18px;
  color: var(--fp-white);
}
.fp-detail .fp-intro-badge-label {
  font-weight: 600;
  font-size: .95rem;
  line-height: 1.25;
  color: var(--fp-ink);
}

/* --------------------------------------------------------------------------
   GALERIE (.fp-galerie.fp-galerie-band) : bandeau pleine largeur fond primary
   + motif pattes discret, rangee titre + fleches (.fp-galerie-head), piste
   carrousel (.fp-galerie-track) avec un seul slide visible a la fois
   (.fp-galerie-slide, des <a> en background-image).
   -------------------------------------------------------------------------- */
.fp-detail .fp-galerie-band {
  position: relative;
  overflow: hidden;
  background: var(--fp-primary);
  color: var(--fp-white);
}
.fp-detail .fp-galerie-band::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: var(--fp-act-pattes);
  background-size: cover;
  background-position: center;
  opacity: .15;
  pointer-events: none;
}
.fp-detail .fp-galerie-band .fp-wrap {
  position: relative;
  z-index: 1;
}
.fp-detail .fp-galerie-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
}
.fp-detail .fp-galerie-band .fp-lead-light {
  margin: 0;
}
.fp-detail .fp-galerie-nav {
  display: flex;
  gap: 10px;
  flex: 0 0 auto;
}
.fp-detail .fp-galerie-band .fp-carousel-arrow {
  background: var(--fp-white);
  color: var(--fp-primary);
}
.fp-detail .fp-galerie-band .fp-carousel-arrow:hover {
  background: var(--fp-dark);
  color: var(--fp-white);
}
.fp-detail .fp-galerie-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  gap: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  border-radius: var(--fp-radius);
}
.fp-detail .fp-galerie-track::-webkit-scrollbar { display: none; }
.fp-detail .fp-galerie-slide {
  display: block;
  scroll-snap-align: start;
  height: clamp(320px, 42vw, 520px);
  background-size: cover;
  background-position: center;
  border-radius: var(--fp-radius);
}

/* --------------------------------------------------------------------------
   VIGNETTE VIDEO DE GALERIE (2026-09-10) : vidéo de médiathèque ou URL
   directe (YouTube, Vimeo, fichier .mp4/.webm) dans le carrousel de l'intro
   (.fp-intro-carousel-slide) et dans la bande galerie (.fp-galerie-slide),
   voir fp_galerie_item_render_kind() (inc/cpt.php) et les deux renderers
   d'inc/sections.php. Fond sombre de repli quand aucune vignette n'a pu être
   résolue (vidéo de médiathèque sans image mise en avant, Vimeo sans
   miniature directe) : jamais d'image cassée. Pictogramme « lecture » dessiné
   en CSS (aucune icône triangle au catalogue du thème, inc/icons.php).
   -------------------------------------------------------------------------- */
.fp-detail .fp-intro-carousel-slide.fp-galerie-video-fond,
.fp-detail .fp-galerie-slide.fp-galerie-video-fond {
  background-color: var(--fp-secondary-dark);
}
/* Vignette "premiere image" (2026-09-10) : videos de mediatheque SANS image
   mise en avant. La balise <video> ne lit que ses metadonnees (aucun
   telechargement complet, aucune lecture), elle remplit le meme cadre que
   l'image de fond des diapositives et ne capte jamais le clic (la visionneuse
   reste pilotee par le lien <a> qui l'entoure). Le fond sombre de repli
   ci-dessus reste dessous au cas ou le navigateur ne peindrait rien. */
.fp-detail .fp-intro-carousel-slide .fp-galerie-vignette,
.fp-detail .fp-galerie-slide .fp-galerie-vignette {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.fp-detail .fp-intro-carousel-slide .fp-galerie-play,
.fp-detail .fp-galerie-slide .fp-galerie-play {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: color-mix(in srgb, var(--fp-dark) 55%, transparent);
  border: 2px solid var(--fp-white);
  pointer-events: none;
}
.fp-detail .fp-intro-carousel-slide .fp-galerie-play::after,
.fp-detail .fp-galerie-slide .fp-galerie-play::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 54%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 9px 0 9px 15px;
  border-color: transparent transparent transparent var(--fp-white);
}
@media (max-width: 720px) {
  .fp-detail .fp-intro-carousel-slide .fp-galerie-play,
  .fp-detail .fp-galerie-slide .fp-galerie-play {
    width: 46px;
    height: 46px;
  }
  .fp-detail .fp-intro-carousel-slide .fp-galerie-play::after,
  .fp-detail .fp-galerie-slide .fp-galerie-play::after {
    border-width: 7px 0 7px 12px;
  }
}

/* --------------------------------------------------------------------------
   ETAPES FUSIONNEES (.fp-etapes-fusion) : section galerie + etapes en 2
   colonnes sur fond --fp-primary avec motif topographique (memes pattes,
   opacite ~0.15), texte blanc. Gauche : .fp-etapes-carousel-col (carrousel
   1 image visible ratio ~4/3, fleches rondes, bouton "voir la galerie
   complete" en surimpression bas-gauche, pilule claire). Droite :
   .fp-etapes-plan (titre + etapes a GROSSES pastilles numerotees blanches,
   texte primary, 72px).
   -------------------------------------------------------------------------- */
.fp-detail .fp-etapes-fusion {
  position: relative;
  overflow: hidden;
  background: var(--fp-primary);
  color: var(--fp-white);
}
.fp-detail .fp-etapes-fusion::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: var(--fp-act-pattes);
  background-size: cover;
  background-position: center;
  opacity: .15;
  pointer-events: none;
}
.fp-detail .fp-etapes-fusion .fp-wrap {
  position: relative;
  z-index: 1;
}
/* Gap elargi entre carrousel et etapes + carrousel PLAFONNE en largeur
   (retour client : « galerie un petit peu moins large, plus d'espace avec
   la zone de droite »). */
.fp-detail .fp-etapes-split {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(48px, 5vw, 80px);
  align-items: stretch;
}
.fp-detail .fp-etapes-carousel-col {
  max-width: 44%;
}
@media (max-width: 980px) {
  .fp-detail .fp-etapes-carousel-col { max-width: none; }
}
/* Titre de section agrandi (mesure sur le modele : 56px/line-height 56px,
   sur une seule ligne dans sa colonne) : le .fp-lead generique plafonne a
   2.6rem (41.6px), trop petit ici d'apres le retour client. */
.fp-detail .fp-etapes-fusion .fp-lead {
  color: var(--fp-white);
  position: relative;
  font-size: clamp(1.9rem, 3.4vw, 3.5rem);
  line-height: 1;
  max-width: none;
}
/* GHOST TITLE (titre fantome ajoure derriere le H2, facon RParc) : style PRET
   A L'EMPLOI, non actif tant que le markup ne pose pas l'attribut. Le CSS ne
   peut pas dupliquer le texte du H2 sans le connaitre (pas de contenu en dur
   generique ici) -> necessite cote PHP un attribut data-ghost sur le meme H2
   (inc/sections.php, fonction fp_render_etapes, la ligne du h2.fp-lead dans la
   branche fp-etapes-fusion) portant le MEME texte que le heading, ex. :
   <h2 class="fp-lead fp-reveal" data-ghost="<?php echo esc_attr( wp_strip_all_tags( $heading ) ); ?>">
   Une fois l'attribut present, ce ::before affiche un double du titre, tres
   agrandi, contour blanc fin, quasi transparent, en fond du H2 (purement
   decoratif, aria-hidden implicite car pas de contenu semantique ajoute :
   attr() ne cree pas de noeud accessible supplementaire). */
/* GHOST TITLE DESACTIVE : retour client explicite ("on voit ecrit... en
   fond, c'est tres laid, il faut l'enlever"). L'attribut data-ghost est
   retire cote markup (inc/sections.php), mais on neutralise aussi la regle
   ici par securite (belt and suspenders) : plus aucun ghost ne peut
   s'afficher, meme si l'attribut revenait un jour dans le DOM. */
.fp-detail .fp-etapes-fusion [data-ghost]::before {
  content: none;
}
/* Colonne carrousel : image compacte ratio 4/3, fleches rondes, bouton
   "voir la galerie complete" en surimpression bas-gauche (pilule claire). */
/* align-self:flex-start (correctif 2026-08) : .fp-etapes-split est un flex en
   align-items:stretch, donc cette colonne était ÉTIRÉE à la hauteur de la
   colonne de droite (les étapes). Or la photo, elle, garde son ratio 4/3 fixe,
   et les 2 repères posés en absolu le sont sur LA COLONNE : les flèches
   (top:50%) et le bouton « voir la galerie complète » (bottom:-22px) se
   calaient donc sur le bas de la COLONNE étirée, pas sur le bas de la PHOTO.
   Dès que la colonne des étapes était plus haute que la photo - une étape avec
   deux paragraphes au lieu d'un suffit - un vide apparaissait entre la galerie
   et son bouton, et les flèches descendaient sous le centre de la photo. Sur
   une page aux étapes plus courtes, le bouton restait collé : même code, même
   CSS, deux rendus. En ne s'étirant plus, la colonne fait exactement la
   hauteur de la photo et ces repères redeviennent indépendants du contenu de
   la colonne voisine. */
.fp-detail .fp-etapes-carousel-col {
  position: relative;
  flex: 1 1 320px;
  align-self: flex-start;
}
/* Cadre PHOTO (pimp v2, retour client : « visuellement ça roule bien, des
   effets ») : épais liseré blanc façon tirage papier, légère inclinaison qui
   se REDRESSE au survol de la colonne, ombre dure décalée signature en plus
   de l'ombre douce. Les flèches et le bouton galerie, positionnés sur la
   COLONNE, restent parfaitement droits. */
.fp-detail .fp-etapes-carousel {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  gap: 0;
  aspect-ratio: 4 / 3;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  border: 8px solid var(--fp-white);
  border-radius: var(--fp-radius);
  box-shadow: 10px 12px 0 0 color-mix(in srgb, var(--fp-secondary-dark) 40%, transparent), var(--fp-shadow-lg);
  transition: transform .45s cubic-bezier(.22, .85, .3, 1), box-shadow .35s ease;
}
/* Cadre DROIT (retour client : l'inclinaison ne passait pas), leger
   grossissement au survol seulement. */
.fp-detail .fp-etapes-carousel-col:hover .fp-etapes-carousel {
  transform: scale(1.012);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-etapes-carousel {
    transition: none;
  }
  .fp-detail .fp-etapes-carousel-col:hover .fp-etapes-carousel { transform: none; }
}
.fp-detail .fp-etapes-carousel::-webkit-scrollbar { display: none; }
/* Chaque photo : l'image est reportee sur un ::before (background-image:
   inherit reprend le style inline pose par le PHP) pour pouvoir lui appliquer
   un zoom lent « Ken Burns » SANS deborder sur les slides voisins (le span
   clippe via overflow:hidden). Un voile sombre (::after) monte du pied de
   chaque photo : le bouton galerie a cheval reste lisible sur toute image. */
.fp-detail .fp-etapes-carousel-slide {
  display: block;
  position: relative;
  overflow: hidden;
  scroll-snap-align: start;
  background-size: cover;
  background-position: center;
}
.fp-detail .fp-etapes-carousel-slide::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: inherit;
  background-size: cover;
  background-position: center;
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-etapes-carousel-slide::before {
    animation: fp-etapes-kenburns 16s ease-in-out infinite alternate;
  }
}
@keyframes fp-etapes-kenburns {
  from { transform: scale(1) translateX(0); }
  to { transform: scale(1.09) translateX(-1.5%); }
}
.fp-detail .fp-etapes-carousel-slide::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 88px;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--fp-secondary-dark) 55%, transparent));
  pointer-events: none;
}
/* Conteneur des 2 fleches SANS boite propre (retour client : une fleche a
   gauche, une a droite, chacune centree verticalement sur les bords de la
   galerie -> plus de groupe en haut a droite). display:contents fait
   participer chaque .fp-carousel-arrow directement au positionnement absolu
   par rapport a .fp-etapes-carousel-col (position:relative, deja en place).
   L'ordre DOM (prev = 1er enfant, next = 2e) est intact : le JS
   (data-fp-carousel) continue de fonctionner par ordre. */
.fp-detail .fp-etapes-carousel-nav {
  display: contents;
}
.fp-detail .fp-etapes-carousel-nav .fp-carousel-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  background: var(--fp-white);
  color: var(--fp-primary);
}
/* Prev = 1er enfant du conteneur -> a gauche de la galerie. */
.fp-detail .fp-etapes-carousel-nav .fp-carousel-arrow:first-child {
  left: 10px;
}
/* Next = dernier enfant du conteneur -> a droite de la galerie. */
.fp-detail .fp-etapes-carousel-nav .fp-carousel-arrow:last-child {
  right: 10px;
}
/* Le centrage vertical (translateY(-50%)) doit survivre au survol : le
   systeme .fp-carousel-arrow commun applique scale(1.06) au hover
   (main.css), ce qui ecraserait sinon le centrage (transform non additif
   entre regles, meme logique que le bouton galerie ci-dessous). */
.fp-detail .fp-etapes-carousel-nav .fp-carousel-arrow:hover {
  background: var(--fp-dark);
  color: var(--fp-white);
  transform: translateY(-50%) scale(1.06);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-etapes-carousel-nav .fp-carousel-arrow:hover {
    transform: translateY(-50%);
  }
}
/* Bouton « voir la galerie complète » en surimpression, CENTRÉ horizontalement,
   À CHEVAL sur le bas de la galerie (retour client : « tu peux le descendre
   un peu pour qu'il soit par-dessus la galerie, mais aussi qu'il dépasse un
   peu en dessous de la zone de galerie »). bottom NÉGATIF : le bouton
   chevauche la photo par le haut et déborde sous le cadre par le bas. La
   section .fp-etapes-fusion garde un padding vertical généreux (fp-s-cream),
   largement suffisant pour ce débord de quelques dizaines de pixels sans
   jamais être rogné par son overflow:hidden. */
.fp-detail .fp-etapes-gallery-link {
  position: absolute;
  left: 50%;
  right: auto;
  bottom: -22px;
  transform: translateX(-50%);
  z-index: 2;
  background: var(--fp-cream);
  color: var(--fp-primary);
  border-color: var(--fp-cream);
}
.fp-detail .fp-etapes-gallery-link::before {
  background: var(--fp-primary);
}
/* Le centrage horizontal (translateX(-50%)) doit survivre au survol : le
   systeme .fp-btn commun applique translateY(-2px) au hover (main.css), ce
   qui ecraserait sinon le centrage (transform non additif entre regles). */
.fp-detail .fp-etapes-gallery-link:hover {
  color: var(--fp-white);
  transform: translateX(-50%) translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-etapes-gallery-link:hover {
    transform: translateX(-50%);
  }
}
.fp-detail .fp-etapes-plan {
  flex: 1 1 45%;
  max-width: 45%;
}
/* Rythme vertical mesure sur le modele : gap 20px entre etapes (le gap flex
   column du bloc "plan" source), meme valeur que la marge H2 -> 1ere etape. */
.fp-detail .fp-etapes-grid {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin-top: 20px;
}
.fp-detail .fp-etape {
  display: flex;
  align-items: center;
  gap: 18px;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 0;
}
/* Branche fusion (page activite) : les icones SVG/webp d'etape remplacent
   desormais le numero (retour client : "doublon"), alignees EN HAUT au niveau
   du titre de l'etape (le modele RP n'a pas non plus de pastille numerotee ici,
   seulement l'icone d'illustration a gauche du texte). Pimp v2 : un FIL
   pointille blanc relie verticalement les icones d'etapes (parcours), et
   l'icone salue au survol de son etape. */
.fp-detail .fp-etapes-fusion .fp-etape {
  position: relative;
  align-items: flex-start;
}
.fp-detail .fp-etapes-fusion .fp-etape:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 29px;
  top: 67px;
  bottom: -22px;
  border-left: 2px dashed color-mix(in srgb, var(--fp-white) 40%, transparent);
  pointer-events: none;
}
/* Grosses pastilles numerotees : cercle 72px CONTOUR fin blanc, fond
   transparent (pas de fond plein, facon RParc), chiffre blanc gras. Reservees
   aux etapes HORS fusion (autres modeles) : masquees dans la fusion, cf.
   regle dediee juste apres. */
.fp-detail .fp-etape-num {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid var(--fp-white);
  color: var(--fp-white);
  font-family: var(--fp-font-heading);
  font-weight: 700;
  font-size: 1.6rem;
}
/* Numero masque dans la fusion (retour client : "ca fait doublon", les icones
   suffisent desormais). Prive en CSS plutot qu'en PHP pour rester minimal. */
.fp-detail .fp-etapes-fusion .fp-etape-num {
  display: none;
}
/* Icone illustrative de l'etape (branche fusion uniquement) : taille mesuree
   sur le modele (icon-box source, image_size 59px), alignee EN HAUT (au niveau
   du titre), jamais plus grande que l'ancienne pastille numero. */
.fp-detail .fp-etapes-fusion .fp-etape-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 59px;
  height: 59px;
  margin-top: 2px;
  transition: transform .3s ease;
}
.fp-detail .fp-etapes-fusion .fp-etape:hover .fp-etape-icon {
  transform: translateY(-3px) rotate(-6deg);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-etapes-fusion .fp-etape-icon { transition: none; }
  .fp-detail .fp-etapes-fusion .fp-etape:hover .fp-etape-icon { transform: none; }
}
.fp-detail .fp-etapes-fusion .fp-etape-icon img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Icones fournies en silhouette sombre : passees en blanc pour rester
     lisibles sur le fond --fp-primary de la section (meme traitement que
     l'icone du hero, fp-hero-icon). */
  filter: brightness(0) invert(1);
  opacity: .95;
}
/* Etapes HORS fusion (icone = repli du numero, pas d'illustration
   supplementaire) : taille generique inchangee. */
.fp-detail .fp-etapes.fp-s-cream:not(.fp-etapes-fusion) .fp-etape-icon img {
  width: 48px;
  height: 48px;
  object-fit: contain;
}
.fp-detail .fp-etape-body {
  flex: 1 1 auto;
}
.fp-detail .fp-etape-title {
  margin-bottom: 6px;
  color: var(--fp-white);
}
.fp-detail .fp-etape p {
  color: color-mix(in srgb, var(--fp-white) 88%, transparent);
  margin: 0;
}
/* Etapes HORS fusion (autres modeles) : fond clair standard, texte encre. */
.fp-detail .fp-etapes.fp-s-cream:not(.fp-etapes-fusion) .fp-etape-title,
.fp-detail .fp-etapes.fp-s-cream:not(.fp-etapes-fusion) .fp-lead {
  color: var(--fp-ink);
}
.fp-detail .fp-etapes.fp-s-cream:not(.fp-etapes-fusion) .fp-etape p {
  color: var(--fp-ink-soft);
}

/* --------------------------------------------------------------------------
   FORMULES (.fp-formules.is-centered) : REFONTE « BLUEPRINT DU PARC »
   (retour client : « trop basique et fade, vraiment lâche-toi, fais un truc
   sympa, tu peux utiliser em-plan / em-topo en fond »). La section devient
   une bande SOMBRE (dégradé secondary -> secondary-dark) sur laquelle le
   plan du parc (assets/img/em-plan.svg, traits #7db8b4 sans fond) se déploie
   en grand filigrane fondu haut/bas (.fp-formules-plan). Les cartes
   deviennent des « pass » clairs : bandeau topographique en tête
   (assets/img/em-topo.svg, aplat vert intégré au fichier), numéro Bebas
   géant posé dans le bandeau, médaillon d'icône blanc bordé teal à cheval
   sur le bandeau, corps kicker / titre display / description / liste à
   coches, bouton PLEIN pleine largeur toujours collé en bas. Survol : lift
   + léger pivot + ombre dure décalée accent (très lisible sur le fond
   sombre), le bandeau topo glisse doucement et le médaillon salue.
   -------------------------------------------------------------------------- */
/* Section CLAIRE (v3, retour client : « trop de blanc partout, le fond de
   la section devrait être blanc, ça peut te libérer pour les formules ») :
   l'inversion - fond de section blanc avec le plan du parc en filigrane
   clair, et les CARTES qui portent désormais la couleur (teal foncé). */
.fp-detail .fp-formules {
  position: relative;
  overflow: hidden;
  background: var(--fp-paper);
}
/* Plan du parc en filigrane : grand, centré, fondu en haut et en bas pour ne
   jamais buter contre les sections voisines (traits #7db8b4 sur blanc). */
.fp-detail .fp-formules-plan {
  position: absolute;
  inset: -4% -8%;
  z-index: 0;
  background-image: url('../img/em-plan.svg');
  background-size: min(1400px, 140%);
  background-position: center;
  background-repeat: no-repeat;
  opacity: .38;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 16%, #000 84%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 16%, #000 84%, transparent 100%);
}
.fp-detail .fp-formules .fp-wrap {
  position: relative;
  z-index: 1;
}
.fp-detail .fp-formules.is-centered .fp-lead {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
  color: var(--fp-ink);
}
/* Trait d'accent centré sous le titre, écho du trait de l'intro. */
.fp-detail .fp-formules .fp-lead::after {
  content: '';
  display: block;
  width: 56px;
  height: 4px;
  margin: 16px auto 0;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--fp-primary), var(--fp-accent));
}
/* Accroche courte centrée sous le titre (contenu de zone ou repli PHP). */
.fp-detail .fp-formules-sub {
  max-width: 58ch;
  margin: 14px auto 0;
  text-align: center;
  color: var(--fp-ink-soft);
  line-height: 1.55;
}
.fp-detail .fp-formules-body {
  display: flex;
  flex-direction: column;
  gap: 40px;
  margin-top: 48px;
}
.fp-detail .fp-formules-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 36px 34px;
  align-items: stretch;
}
/* Carte « pass » : design RETENU par le client (retour apres essai d'une
   variante pleine texture, jugee moins aboutie) - teal foncé en dégradé,
   texte blanc, bandeau topographique en tête terminé par un ARC assorti au
   haut de la carte, numéro ajouré dans le bandeau, médaillon d'icône à
   cheval sur le bandeau. */
.fp-detail .fp-formule {
  position: relative;
  display: flex;
  flex-direction: column;
  text-align: left;
  background: linear-gradient(180deg, var(--fp-secondary) 0%, var(--fp-secondary-dark) 100%);
  border: none;
  border-radius: var(--fp-radius-lg);
  overflow: hidden;
  box-shadow: 0 26px 52px -28px color-mix(in srgb, var(--fp-secondary-dark) 85%, transparent);
  transition: transform .4s cubic-bezier(.22, .85, .3, 1), box-shadow .35s ease;
}
.fp-detail .fp-formule:hover {
  transform: translateY(-10px) rotate(-1deg);
  box-shadow: 10px 12px 0 0 color-mix(in srgb, var(--fp-accent) 60%, transparent), 0 26px 52px -28px color-mix(in srgb, var(--fp-secondary-dark) 85%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-formule { transition: none; }
  .fp-detail .fp-formule:hover { transform: none; }
}
/* Bandeau topographique : le SVG em-topo porte son propre aplat vert, on le
   cadre simplement ; il glisse doucement au survol de la carte. L'::after
   dessine un arc assorti qui mord sur le bas du bandeau : la jonction n'est
   pas une simple ligne droite. */
.fp-detail .fp-formule-topo {
  position: relative;
  display: block;
  height: 110px;
  flex: 0 0 auto;
  background-image: url('../img/em-topo.svg');
  background-size: cover;
  background-position: center 38%;
  transition: background-position .6s ease;
}
.fp-detail .fp-formule:hover .fp-formule-topo {
  background-position: center 55%;
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-formule-topo { transition: none; }
  .fp-detail .fp-formule:hover .fp-formule-topo { background-position: center 38%; }
}
.fp-detail .fp-formule-topo::after {
  content: '';
  position: absolute;
  left: -8%;
  right: -8%;
  bottom: -1px;
  height: 26px;
  background: var(--fp-secondary);
  border-radius: 100% 100% 0 0;
}
/* Numéro Bebas géant AJOURÉ (contour blanc, fond transparent) dans le
   bandeau, au-dessus de l'arc. Purement décoratif (aria-hidden côté PHP). */
/* Chiffre de la formule : MEME traitement que le titre principal des pages
   activites et restauration, a la demande du client, simplement plus petit.
   Donc la police d'AFFICHAGE (--fp-font-display, Thoge avec Bebas en repli),
   celle de .fp-detail .fp-hero-detail .fp-hero-title, et un aplat plein au lieu
   du chiffre evide au contour qui etait ici : le contour se lisait comme une
   texture de fond, pas comme un numero.
   PIEGE : --fp-font-heading (Bebas seul) n'est PAS la meme chose. Les deux
   jetons existent et se ressemblent, mais les gros titres du site passent par
   --fp-font-display. Ne pas les intervertir.
   Le chiffre est ecrit nu (1, 2, 3) et non zero-complete : voir le rendu, dans
   inc/sections.php. */
.fp-detail .fp-formule-num {
  position: absolute;
  top: 42%;
  right: 20px;
  z-index: 1;
  transform: translateY(-50%);
  font-family: var(--fp-font-display);
  font-weight: 400;
  /* Cale sur l'echelle de .fp-hero-title (clamp 2.4rem / 6vw / 4.6rem), d'un
     cran en dessous puisque c'est un numero et non le titre de la page. */
  font-size: clamp(2.2rem, 4.6vw, 3.6rem);
  line-height: 1;
  color: var(--fp-white);
  text-shadow: 0 4px 16px rgba(0, 47, 41, .35);
}
/* Médaillon d'icône : blanc bordé teal + anneau doux, posé À CHEVAL sur le
   bas du bandeau topo (top = hauteur du bandeau moins la moitié du
   médaillon de 64px). */
.fp-detail .fp-formule-icon {
  position: absolute;
  top: 78px;
  left: 24px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--fp-paper);
  color: var(--fp-primary);
  border: 2px solid var(--fp-primary);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--fp-white) 18%, transparent), var(--fp-shadow);
  transition: transform .35s ease;
}
.fp-detail .fp-formule-icon svg {
  width: 30px;
  height: 30px;
}
.fp-detail .fp-formule:hover .fp-formule-icon {
  transform: translateY(-4px) rotate(-8deg);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-formule-icon { transition: none; }
  .fp-detail .fp-formule:hover .fp-formule-icon { transform: none; }
}
/* Corps de carte : padding haut généreux (le médaillon déborde dedans),
   bouton collé en bas via margin-top:auto. */
.fp-detail .fp-formule-inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  flex: 1 1 auto;
  padding: 46px 26px 26px;
}
/* Kicker en chip pilule blanche translucide sur la carte teal. */
.fp-detail .fp-formule-kicker {
  display: inline-flex;
  align-self: flex-start;
  margin: 0 0 10px;
  padding: 4px 12px;
  border-radius: var(--fp-pill);
  background: color-mix(in srgb, var(--fp-white) 14%, transparent);
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--fp-white);
}
/* Titre en Bebas (retour client : la police display Thoge est illisible a
   cette taille), graisse native 400, taille relevee, blanc sur teal. */
.fp-detail .fp-formule-title {
  margin: 0 0 12px;
  color: var(--fp-white);
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: clamp(1.6rem, 2.4vw, 2rem);
  line-height: 1.02;
  letter-spacing: .015em;
}
.fp-detail .fp-formule-desc {
  margin: 0 0 6px;
  color: color-mix(in srgb, var(--fp-white) 84%, transparent);
}
/* Liste à coches : chaque item porte une pastille check décorative
   (span posé côté PHP), texte blanc adouci. */
.fp-detail .fp-formule-list {
  margin: 12px 0 18px;
  padding: 0;
  list-style: none;
  color: color-mix(in srgb, var(--fp-white) 82%, transparent);
  font-size: .94rem;
  line-height: 1.4;
  text-align: left;
}
.fp-detail .fp-formule-list li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-bottom: 7px;
}
.fp-detail .fp-formule-li-ic {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fp-white) 16%, transparent);
  color: var(--fp-white);
}
.fp-detail .fp-formule-li-ic svg {
  width: 11px;
  height: 11px;
}
/* Bouton TOUJOURS collé en bas de carte, pleine largeur et centré. Sur la
   carte teal, le bouton passe en BLANC (surcharge du fp-btn-primary du
   markup) ; au survol le remplissage teal glisse (::before du fp-btn
   commun) et le TEXTE passe en blanc (sinon primary sur primary,
   illisible - meme correctif que le bouton des tarifs). */
.fp-detail .fp-formule-cta {
  margin-top: auto;
  align-self: stretch;
  justify-content: center;
}
.fp-detail .fp-formule-cta.fp-btn {
  background: var(--fp-white);
  color: var(--fp-primary-dark);
  border-color: var(--fp-white);
}
.fp-detail .fp-formule-cta.fp-btn::before {
  background: var(--fp-primary);
}
.fp-detail .fp-formule-cta.fp-btn:hover {
  color: var(--fp-white);
}
@media (max-width: 720px) {
  .fp-detail .fp-formule-topo { height: 92px; }
  .fp-detail .fp-formule-icon { width: 56px; height: 56px; top: 64px; left: 20px; }
  .fp-detail .fp-formule-icon svg { width: 26px; height: 26px; }
  .fp-detail .fp-formule-inner { padding: 40px 22px 22px; }
  /* Palier retire : la taille du chiffre est desormais fluide (clamp calee sur
     .fp-hero-title), elle se reduit deja d'elle-meme. Un palier fixe ici
     l'aurait au contraire fige a 3rem et casse la progression. */
}

/* --------------------------------------------------------------------------
   TARIFS : REFONTE COMPLÈTE (retour client : « il n'y a rien qui est
   centré, c'est du gauche-droite, ce n'est pas ça. Redesign complètement
   cette section. Tu gardes JUSTE la couleur de fond, c'est la seule
   contrainte. Et fais en sorte que si les éléments sont centrés, ils soient
   VRAIMENT tous centrés, pas des éléments à gauche, d'autres à droite »).
   SEULE chose conservée à l'identique : le fond de section (aplat --fp-accent
   + motif topographique ::before ci-dessous). Tout le reste est repensé avec
   un alignement RIGOUREUSEMENT centré, dans les 2 rendus gérés par le plugin
   fp-tarifs-manager (type "table" -> shortcode habillé plus bas, type
   "visual"/repli -> pastille juste après) : eyebrow/H2/accroche déjà centrés
   sont conservés, un petit trait d'accent centré est ajouté sous le titre
   pour souligner le nouveau parti pris « tout au centre ».
   Largeur : le source utilise --content-width:1500px sur cette section (au
   lieu de la valeur globale 1300px) -> on surcharge localement --fp-wrap.
   -------------------------------------------------------------------------- */
/* Padding vertical RESSERRE (retour client : trop d'espace haut et bas). */
.fp-detail .fp-tarifs {
  --fp-wrap: min(1500px, 90vw);
  position: relative;
  overflow: hidden;
  background: var(--fp-accent);
  padding: calc(var(--fp-section-y) - 16px) 0;
}
/* HAUTEUR MINIMALE AVEC UN MÉDIA DE FOND (Marino, 2026-09-10 : « pour Billard
   et Virtual Room on ne voit pas beaucoup [la vidéo de fond], petit tableau »).
   Une carte de deux lignes laissait une bande trop basse pour que la photo ou
   la vidéo de fond se lise. Flex en colonne pour que la carte reste centrée
   dans la hauteur gagnée ; les calques absolus (média, voile, note, curseur
   son) ne participent pas au flux et ne bougent pas. Le clamp garde une
   hauteur raisonnable sur téléphone, où le média n'est de toute façon chargé
   qu'à partir de 721 px. */
.fp-detail .fp-tarifs.has-fond-media {
  min-height: clamp(520px, 72vh, 760px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* MOTIF ANIMÉ (Marino, 09.09.2026) : « les zones tarifs qui n'auraient pas
   encore de photo ou vidéo de fond, il faudrait que le plan en place bouge
   aussi ». MÊME RECETTE que .fp-ip-horaires-motif (informations.css),
   .fp-footer::before (main.css) et le listing des activités de l'accueil
   (home.css) : inset négatif pour que le zoom et le va-et-vient ne découvrent
   jamais un bord (la section est déjà en overflow: hidden juste au-dessus),
   transform SEUL, jamais background-position qui repeint tout le calque à
   chaque image, dérive lente en alternance, coupée sous prefers-reduced-motion.

   La dérive n'est PAS conditionnée à l'absence de média, et c'est volontaire :
   sur une fiche qui porte une photo ou une vidéo, le conteneur .fp-tarifs-fond
   recouvre entièrement ce calque, on ne le voit donc pas, et l'y couper par un
   :not(.has-fond-media) ferait bloquer le motif d'un coup au moment précis où
   la vidéo apparait en fondu, la classe étant posée par le script au démarrage
   de la lecture. Un transform de plus sur un calque masqué ne coûte rien ; une
   saccade au bon milieu du fondu se verrait. */
.fp-detail .fp-tarifs::before {
  content: '';
  position: absolute;
  inset: -14%;
  z-index: 0;
  background-image: var(--fp-act-pattes);
  background-size: cover;
  background-position: center;
  opacity: .2;
  pointer-events: none;
  transform: scale(1.12);
}
/* DÉRIVE PLUS MARQUÉE (Marino, 10.09.2026 : « anime aussi un peu plus le fond
   des tarifs vides »). Mêmes valeurs que le fond de l'accueil (home.css) pour
   que les deux respirent au même rythme : course portée de 3 à 6 % de la
   largeur du calque, composante verticale ajoutée pour ne plus lire comme un
   simple glissement latéral, cycle ramené de 26 à 20 secondes. Le débordement
   (inset -14 % puis zoom 1,12, soit près de 22 % de marge de chaque côté) reste
   très supérieur à la course : aucun bord ne peut se découvrir. */
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-tarifs::before {
    animation: fp-tarifs-motif-derive 20s ease-in-out infinite alternate;
    will-change: transform;
  }
}
@keyframes fp-tarifs-motif-derive {
  from { transform: scale(1.12) translate(-6%, -1.5%); }
  to   { transform: scale(1.12) translate(6%, 1.5%); }
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-tarifs::before { animation: none; will-change: auto; }
}
.fp-detail .fp-tarifs .fp-wrap {
  position: relative;
  z-index: 1;
  text-align: center;
}
/* Un peu plus d'air entre l'icon-box (sur-titre à icône) et le titre en
   dessous (retour client). Règle d'architecture du composant icon-box
   (main.css) : on ne touche qu'à l'espacement de son CONTENEUR, jamais à la
   pilule elle-même. Le conteneur de cette zone précise est le <div
   class="fp-reveal"> qui l'enveloppe directement dans fp_render_tarifs
   (inc/sections.php) : il n'est pas marqué .fp-section-eyebrow comme
   ailleurs sur le site, donc la marge globale de cette classe ne s'y
   applique pas ; :first-child + sélecteur de balise le distingue sans risque
   de la carte de tarifs (.fp-tarifs-body), elle aussi un div.fp-reveal mais
   jamais en premier enfant de .fp-wrap. */
.fp-detail .fp-tarifs .fp-wrap > div.fp-reveal:first-child {
  margin-bottom: clamp(16px, 2.4vw, 24px);
}
.fp-detail .fp-tarifs .fp-lead {
  text-align: center;
  color: var(--fp-white);
  margin-left: auto;
  margin-right: auto;
}
/* Petit trait d'accent CENTRÉ sous le titre : signature visuelle du parti
   pris « tout au centre » de cette refonte. */
.fp-detail .fp-tarifs .fp-lead::after {
  content: '';
  display: block;
  width: 56px;
  height: 3px;
  margin: 18px auto 0;
  border-radius: 2px;
  background: var(--fp-white);
  opacity: .75;
}
/* Accroche de section (paragraphe n1 de la zone Gutenberg « tarifs », donc
   editable dans l'editeur, et non un champ du plugin). Declaration UNIQUE :
   tout ce qui concerne .fp-tarifs-lead est ici, y compris le centrage.
   ELARGIE de 60ch a 78ch (retour client : « trop comprime, il passe sur
   plusieurs lignes inutilement ») : la section dispose de min(1500px, 90vw),
   l'accroche s'y tenait sur ~565px. A 78ch elle occupe ~735px et retombe sur
   deux lignes, sans depasser la mesure lisible. text-wrap:pretty evite en plus
   qu'un mot isole reste seul sur la derniere ligne (progressif : ignore par
   les navigateurs qui ne le connaissent pas). */
.fp-detail .fp-tarifs-lead {
  max-width: 78ch;
  margin: 12px auto 0;
  text-align: center;
  color: var(--fp-white);
  font-size: clamp(1rem, 1.5vw, 1.18rem);
  line-height: 1.6;
  text-wrap: pretty;
}
/* « Découvrez nos formules » ET « Découvrez nos autres activités » (.fp-related,
   carrousel en bas de fiche) : environ +15% (Marino, 2026-09-07), valeurs de
   .fp-lead (main.css, clamp 1.7rem / 3vw / 2.6rem) x1.15. Scope étroit : ne
   touche JAMAIS .fp-tarifs .fp-lead (branches pastille/repli-ultime, dont le
   palier mobile propre reste inchangé, voir plus bas dans ce fichier), ni
   aucun autre h2.fp-lead du site. S'applique à tous les paliers (le palier
   mobile de .fp-formules, historiquement écrit à part, est recalculé x1.15 au
   même endroit, voir plus bas). */
.fp-detail .fp-formules .fp-lead,
.fp-detail .fp-related .fp-lead {
  font-size: clamp(1.955rem, 3.45vw, 2.99rem);
}
/* .fp-tarifs-body est la racine de l'encart, utilisee dans les 3 branches du
   renderer : tableau plugin (.fp-tarifs-body-table), prix unique en fronton
   (.fp-tarif-solo, plugin "visual" ou repli zone), ou table de repli ultime.
   Le fronton vit DIRECTEMENT sur le fond de section (pas de carte blanche) :
   on neutralise donc la carte UNIQUEMENT quand l'encart contient un
   .fp-tarif-solo, en laissant le fond blanc/radius/ombre intacts pour les 2
   autres branches (un tableau brut sur fond accent serait moins lisible). */
.fp-detail .fp-tarifs-body {
  background: var(--fp-paper);
  border-radius: var(--fp-radius-lg);
  padding: 48px clamp(24px, 5vw, 64px);
  max-width: 900px;
  margin: 40px auto 0;
  text-align: center;
  box-shadow: var(--fp-shadow-lg);
  overflow-x: auto;
}
.fp-detail .fp-tarifs-body:has(.fp-tarif-solo) {
  background: transparent;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
  overflow: visible;
}
/* Encart tableau (plugin, type "table") : CARTE VERT FONCE (retour client :
   « je veux le meme que pour le Raiffeisen Parc, titres plus grands, fond vert
   fonce ») posee sur le meme fond teal texture, tout le texte en blanc. Plus
   large que l'encart pastille pour laisser respirer une matrice a plusieurs
   colonnes, et le defilement horizontal est confie a .fp-tarifs-matrix-wrap
   (overflow visible ici : sinon la carte elle-meme scrollerait et la colonne
   de libelles collante perdrait son ancrage). */
.fp-detail .fp-tarifs-body-table {
  max-width: 1080px;
  background: var(--fp-secondary);
  border-radius: var(--fp-radius-lg);
  color: var(--fp-white);
  box-shadow: 0 26px 60px -30px color-mix(in srgb, var(--fp-secondary-dark) 85%, transparent);
  overflow: visible;
  /* Transition du fond (relecture Opus, 2026-09-07) : has-fond-media (règle
     plus bas) peut arriver APRÈS le premier rendu, posée par setupVideosFond()
     (main.js) quand une vidéo seule s'active (aucune image) - sans cette
     transition, la carte sautait sèchement au verre dépoli pendant que le
     média, lui, apparaît en fondu (1.2s). Naturellement sans effet pour les
     visiteurs en mouvement réduit : chez eux, has-fond-media n'est jamais
     ajoutée après coup (image déjà présente au premier rendu, ou vidéo
     jamais activée), la transition ne se joue donc jamais. */
  transition: background .6s ease;
}

/* --------------------------------------------------------------------------
   TARIFS, TYPE « TABLE » SEULEMENT, UNIQUEMENT SUR UNE FICHE D'ACTIVITÉ
   (2026-09-06, demande client) : la puce et le titre migrent DANS la carte
   vert foncé, alignés à gauche, le titre nettement agrandi. En dehors de la
   carte il ne reste plus rien pour ce rendu (voir fp_render_tarifs(),
   inc/sections.php, gardé par `$is_activite`) : la pastille et le repli
   ultime gardent leur eyebrow/h2 EXTERNES inchangés (règles .fp-tarifs
   .fp-lead et .fp-tarifs-lead plus haut dans ce fichier), tout comme la
   branche « table » du gabarit Tarifs hors fiche d'activité (rendu
   historique, sans ces classes-ci).
   -------------------------------------------------------------------------- */
/* La carte devient le PREMIER (et seul) enfant direct de .fp-wrap pour ce
   type : elle ne doit pas hériter du margin-bottom posé plus haut sur
   « .fp-wrap > div.fp-reveal:first-child » (qui ne visait que l'eyebrow
   EXTERNE des deux autres branches). Sélecteur plus spécifique (une classe de
   plus qu'elle) pour l'emporter sans toucher à la règle générale. */
.fp-detail .fp-tarifs .fp-wrap > div.fp-tarifs-body-table.fp-reveal:first-child {
  margin-bottom: 0;
}
/* Puce (fp_eyebrow) : même composant que partout ailleurs sur le site (voir
   RÈGLE D'ARCHITECTURE, main.css), on ne touche donc qu'à son CONTENEUR
   (alignement, espacement). Elle est posée sur un fond sombre (la carte vert
   foncé) alors que la section elle-même reste claire (fp-s-cream) : la classe
   fp-fond-sombre, posée côté PHP, bascule le composant en variante « verre »
   (pilule sombre translucide, texte blanc), exactement le mécanisme documenté
   pour une carte qui contredit le fond de sa section. */
.fp-detail .fp-tarifs-body-eyebrow {
  text-align: left;
  margin-bottom: clamp(14px, 2vw, 20px);
}
/* Titre : par rapport à l'ancien h2.fp-lead partagé par les autres branches
   (clamp 1.7rem / 3vw / 2.6rem juste au-dessus dans ce fichier), facteur 1,5x
   (2.55rem, 4.5vw, 3.9rem). RAMENÉ de 3x à 2x le 2026-09-07 (retour Marino :
   le titre en 3x était trop grand), puis de 2x à 1,5x le 2026-09-10 (même
   retour, encore trop grand : « on réduit un peu le texte "Tarifs" ») : mêmes
   proportions de calcul, facteur revu, sans le rendre timide pour autant.
   SOUS 720px, un palier dédié (plus bas dans ce fichier) prend le relais et
   reste soumis à la même ré-assertion « aucun mot coupé » (harnais
   Playwright, titre de 22 caractères). Bebas Neue n'existe qu'en graisse 400
   (voir .fp-ibox-title plus bas dans ce fichier) : jamais de font-weight
   supérieur, ce serait un faux gras synthétisé par le navigateur. */
.fp-detail .fp-tarifs-body-title {
  margin: 0;
  text-align: left;
  font-family: var(--fp-font-heading);
  font-weight: 400;
  text-transform: uppercase;
  line-height: .95;
  letter-spacing: .01em;
  color: var(--fp-white);
  overflow-wrap: break-word;
  font-size: clamp(2.55rem, 4.5vw, 3.9rem);
}
/* EN-TÊTE DE CARTE (Marino, 2026-09-07) : puce + titre à gauche, bouton de la
   zone à droite, aligné sur le bas du bloc titre (flex-end : le bouton est
   une pilule courte, la puce+le titre une colonne bien plus haute, flex-end
   rapproche le bouton de la ligne de base du titre sans les artefacts de
   `align-items: baseline` entre éléments de tailles très différentes). Sous
   720px (plus bas dans ce fichier), le bouton repasse SOUS le titre, pleine
   largeur : plus aucun bouton en bas de carte dans cette branche (il vivait
   avant dans .fp-tarifs-actions, voir inc/sections.php).
   JAMAIS de flex-wrap ICI (piège rencontré) : avec un titre géant, un
   flex-wrap: wrap ferait passer le BOUTON à la ligne suivante plutôt que de
   rétrécir le titre (l'algorithme de repli à la ligne compare les tailles
   HYPOTHÉTIQUES avant tout rétrécissement, et un h2 sans largeur explicite y
   vaut sa largeur sur une seule ligne, presque toujours plus large que
   l'espace restant à côté du bouton). Sans flex-wrap, min-width: 0 sur
   .fp-tarifs-body-head-text force au contraire le TITRE à rétrécir (donc à
   passer sur plusieurs lignes lui-même) pour laisser la place au bouton sur
   LA MÊME ligne, ce qui est le résultat voulu. Le palier mobile plus bas
   bascule en `flex-direction: column` : pas besoin de wrap pour empiler. */
.fp-detail .fp-tarifs-body-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
}
.fp-detail .fp-tarifs-body-head-text {
  min-width: 0;
  flex: 1 1 auto;
}
.fp-detail .fp-tarifs-body-head-action {
  flex: 0 0 auto;
}
.fp-detail .fp-tarifs-body-lead {
  margin: 16px 0 0;
  max-width: 70ch;
  text-align: left;
  color: var(--fp-white);
  font-size: clamp(1rem, 1.5vw, 1.18rem);
  line-height: 1.6;
  text-wrap: pretty;
}
/* LARGEUR DE LA CARTE ADAPTÉE AU NOMBRE DE COLONNES (Marino, 2026-09-07) :
   classe posée côté PHP (fp_tarifs_table_colonnes(), inc/sections.php) selon
   le nombre RÉEL de colonnes de la première ligne du tableau rendu par le
   plugin (cellules ET colspan additionnés, une matrice jours/tranches
   compte donc bien plus que ses seules balises <th>). 2 colonnes (liste
   simple libellé + prix) : carte nettement plus étroite ; 3 : intermédiaire ;
   4 et plus (matrice à plusieurs jours/tranches) : classe has-cols-4plus,
   ajoutée le 2026-09-10. Le centrage (margin: auto) vient de .fp-tarifs-body,
   hérité sans le redéclarer ici.
   TOUS LES PALIERS RESSERRÉS D'UN CRAN le 2026-09-10 (Marino : « idem pour
   les tableaux, on réduit un peu... la largeur »), y compris la largeur par
   défaut (.fp-tarifs-body-table, plus haut) qui servait jusqu'ici de repli
   pour 4 colonnes et plus, ramenée de 1080px à 1000px via cette classe
   dédiée. */
.fp-detail .fp-tarifs-body-table.has-cols-2 {
  max-width: 660px;
}
/* TITRE RÉDUIT SUR CARTE ÉTROITE, DESKTOP SEULEMENT (relecture Opus,
   2026-09-07) : à largeur de carte réduite, la colonne du titre (bouton
   "Réserver mon jeu !" + gap déduits) laisse moins de place, et le clamp
   général (plus haut) risquerait alors de couper un mot en plein milieu.
   Palier dédié, plus petit, réservé à cette seule largeur de carte (jamais
   flex-wrap sur l'en-tête, cf. plus haut : c'est la taille de police qui
   cède, pas la mise en page). SCOPÉ à 721px et plus (jamais 720px, cf. la
   note sur ce seuil plus bas dans ce fichier) : ce sélecteur porte une
   classe de plus que la règle générale du palier mobile (has-cols-2 en plus
   de fp-tarifs-body-title), il l'emporterait donc PAR SPÉCIFICITÉ même sous
   720px si on ne le limitait pas ici, écrasant le plancher mobile dédié
   (voir plus bas dans ce fichier) alors qu'il n'a jamais été pensé pour
   cette largeur de carte. RESSERRÉ le 2026-09-10 dans les mêmes proportions
   que le titre général (facteur 1,5x au lieu de 2x, cf. plus haut) :
   1.95rem/3.3vw/2.7rem (repris de l'ancien 2.6rem/4.4vw/3.6rem × 0.75). */
@media (min-width: 721px) {
  .fp-detail .fp-tarifs-body-table.has-cols-2 .fp-tarifs-body-title {
    font-size: clamp(1.95rem, 3.3vw, 2.7rem);
  }
}
/* Élargie de 860 à 920px le 2026-09-11 (Marino : « si c'est 3 colonnes tu peux
   aussi élargir un peu le bloc en glassmorphisme »). Trois colonnes de tarifs
   respirent mal dans la largeur pensée pour deux, et ces 60px suffisent à
   desserrer les libellés sans que la carte ne rattrape celle à quatre colonnes,
   qui reste plus large. */
.fp-detail .fp-tarifs-body-table.has-cols-3 {
  max-width: 920px;
}
.fp-detail .fp-tarifs-body-table.has-cols-4plus {
  max-width: 1000px;
}
/* Indication « faites glisser » : MASQUÉE PAR DÉFAUT. Le défilement horizontal
   du tableau n'existe que sous 720px (voir le bloc mobile plus bas) : sur
   ordinateur, le tableau tient dans sa carte et annoncer un geste impossible
   ne ferait qu'égarer. La règle qui la révèle vit donc dans la requête de
   média, jamais ici. */
.fp-detail .fp-tarifs-glisser,
.fp-detail .fp-tarifs-piste {
  display: none;
}
/* Fond média FACULTATIF de la SECTION (pas de la carte) : image et/ou vidéo,
   toutes deux seedées vides dans la zone Gutenberg (fp_blk_section 'tarifs',
   inc/block-patterns.php), et lues UNIQUEMENT sur une fiche d'activité (voir
   inc/sections.php). Les deux (et le voile ci-dessous) sont réunis dans UN
   SEUL conteneur .fp-tarifs-fond (span, inc/sections.php), absolument
   positionné derrière .fp-wrap (z-index 1 plus haut dans ce fichier), sur la
   section déjà position:relative + overflow:hidden : c'est CE conteneur qui
   porte le fondu d'apparition (règle juste en dessous), image/vidéo/voile
   apparaissant ensemble d'un seul geste. Quand les deux médias sont présents,
   la vidéo (déclarée après dans le markup PHP) peint PAR-DESSUS l'image : le
   filet de secours « prefers-reduced-motion » ci-dessous, PLUS le palier
   mobile plus bas dans ce fichier, la masquent alors et révèlent l'image. */
.fp-detail .fp-tarifs-fond {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.fp-detail .fp-tarifs-fond-image,
.fp-detail .fp-tarifs-fond-video,
.fp-detail .fp-tarifs-fond-voile {
  position: absolute;
  inset: 0;
}
.fp-detail .fp-tarifs-fond-image {
  display: block;
  background-image: var(--fp-tarifs-fond);
  background-size: cover;
  background-position: center;
}
.fp-detail .fp-tarifs-fond-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* VOILE (Marino, 2026-09-07) : bande vert foncé translucide légère, posée
   au-dessus du média (dernier enfant du conteneur .fp-tarifs-fond) et sous la
   carte, pour harmoniser le média avec les sections blanches et vertes du
   reste de la page. Assombrit systématiquement le média : le contraste du
   verre dépoli de la carte (règle plus bas) ne peut donc que s'améliorer par
   rapport à un média nu, valeurs recalculées et notées plus bas.
   VISIBILITÉ SCOPÉE SUR .has-fond-media (Marino, 2026-09-08, annule la
   relecture de la veille qui limitait l'ÉMISSION du voile à la seule image) :
   le balisage (inc/sections.php) émet désormais ce voile dès qu'une image OU
   une vidéo existe, mais il reste invisible (opacity 0) tant que la section
   ne porte pas has-fond-media - posée côté PHP dès qu'une image existe
   (immédiat, sans JavaScript), ou côté JS par setupVideosFond() au moment
   précis où une vidéo seule s'active réellement. Une vidéo seule jamais
   activée (mobile, mouvement réduit, économie de données, sans JavaScript)
   ne voile donc jamais un aplat de fond vide. Transition propre (voir plus
   bas) : has-fond-media arrive TOUJOURS dans le même geste synchrone que
   .is-visible (reveler(), assets/js/main.js), le voile fond donc EXACTEMENT
   avec le média, jamais avant ni après. */
.fp-detail .fp-tarifs-fond-voile {
  /* VOILE ALLEGE DE 35 A 20 % le 2026-09-09 (Marino : « comme on a de belles
     videos, on peut reduire le vert fonce pour les voir un peu mieux
     derriere ? »), puis DE 20 A 12 % le 2026-09-10 matin (meme retour, un
     cran de plus : « on voit pas assez les videos de fond derriere les zones
     tarif »), puis REMONTE DE 12 A 16 % le 2026-09-10 soir (meme jour, retour
     inverse : a 12 % le voile avait totalement disparu, or c'est lui qui
     raccorde le media aux sections claires voisines - Marino le veut leger
     mais visible). Valeur choisie ENTRE les deux derniers paliers essayes
     (20 %, encore juge trop present, et 12 %, invisible), plus proche du bas
     de cette fourchette. Le contraste du texte n'en souffre pas : la carte
     porte son PROPRE fond (voir plus bas, ALLEGE le meme jour, de 50 a 35 %
     de --fp-dark) plus un flou de 14 px (regle du verre depoli, plus bas), et
     c'est lui qui tient la lisibilite, pas ce voile. */
  /* VOILE VERT, PAS NOIR (Marino, 10.09.2026, troisième retour : « les voiles
     verts légers ne sont plus là »). À 16 % de --fp-dark, un vert presque noir,
     le voile ne se percevait pas comme du vert : il grisait à peine. On passe
     sur --fp-secondary, le vert du parc, à 22 % : visible, franchement vert,
     et léger, la vidéo reste le sujet maintenant que le verre est à 35 %. */
  background: color-mix(in srgb, var(--fp-secondary) 22%, transparent);
  opacity: 0;
  transition: opacity 2.4s ease-out;
}
/* TEXTURE EM-TOPO SUR LE VOILE (Marino, 2026-09-10 : « le glassmorphisme est
   allégé, il ne reste qu'un aplat de couleur sur les vidéos, sans matière »).
   Le motif « plan du parc » de .fp-tarifs::before (--fp-act-pattes) vit SOUS
   .fp-tarifs-fond : un média (image ou vidéo) le recouvre entièrement dès
   qu'il est actif, il ne reste donc invisible derrière une vidéo. On pose
   la texture ICI, sur le voile lui-même (dernier calque, déjà au-dessus du
   média et sous la carte), plutôt que d'ajouter un quatrième élément dans le
   balisage (inc/sections.php, hors de ce correctif) : un ::after HÉRITE de
   l'opacité 0/1 du voile parent, il apparaît donc dans EXACTEMENT le même
   fondu, sans transition propre à écrire.
   FICHIER RETENU : assets/img/em-topo-traits.svg (celui du pied de page,
   .fp-footer::before, main.css), traits seuls sans aplat de fond (fill:
   none, trait du même teal clair que le motif « plan » ci-dessus).
   L'autre variante, assets/img/em-topo.svg, embarque un rectangle plein d'un
   vert profond en plus des traits : posée ici, elle repeindrait la vidéo
   d'un aplat opaque au lieu d'une simple texture, exactement le défaut
   qu'on corrige.
   OPACITÉ TRÈS BASSE (.12, sous le .2 du plan derrière le média et sous le
   .16 même du voile) : une texture, pas un décor, la vidéo reste le sujet.
   La teinte du voile (color-mix ci-dessus) n'est pas touchée. Aucune
   animation posée ici (contrairement au motif "plan" plus haut) : un motif
   supplémentaire en mouvement sur un média déjà animé aurait plus de chances
   de créer un effet de moiré que d'ajouter de la matière. */
.fp-detail .fp-tarifs-fond-voile::after {
  content: '';
  position: absolute;
  inset: 0;
  background: url('../img/em-topo-traits.svg') center center / cover no-repeat;
  opacity: .12;
  pointer-events: none;
}
.fp-detail .fp-tarifs.has-fond-media .fp-tarifs-fond-voile {
  opacity: 1;
}
/* APPARITION EN FONDU (Marino, 2026-09-07, durée portée à 2.4s le
   2026-09-08) : SANS JavaScript, .fp-tarifs-fond n'a aucune classe cachée et
   reste à son état par défaut ci-dessus (aucune règle d'opacité) : DONC
   visible d'emblée, jamais invisible (le voile, lui, suit sa propre règle
   has-fond-media juste au-dessus, indépendante de .fp-fond-attente). AVEC
   JavaScript, setupVideosFond() (assets/js/main.js) ajoute .fp-fond-attente
   dès l'initialisation (ce qui bascule l'opacité à 0), puis .is-visible dès
   que la section entre dans l'écran (IntersectionObserver, seuil ~15%, une
   seule fois) : c'est ce même instant qui déclenche le chargement (src) et la
   lecture de la vidéo, voir inc/sections.php. Mouvement réduit : aucune
   classe .fp-fond-attente n'est posée par le script dans ce cas (apparition
   immédiate, sans transition, même esprit que .fp-reveal ailleurs sur le
   site), la vidéo restant de toute façon exclue par les conditions
   favorables. */
.fp-detail .fp-tarifs-fond.fp-fond-attente {
  opacity: 0;
  transition: opacity 2.4s ease-out;
}
.fp-detail .fp-tarifs-fond.fp-fond-attente.is-visible {
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-tarifs-fond-video {
    display: none;
  }
  .fp-detail .fp-tarifs-fond.fp-fond-attente {
    opacity: 1;
    transition: none;
  }
  .fp-detail .fp-tarifs-fond-voile {
    transition: none;
  }
}
/* Verre dépoli vert foncé translucide : SEULEMENT quand un média de fond est
   présent (section .has-fond-media). Sans média, la carte garde EXACTEMENT
   son fond plein actuel (règle .fp-tarifs-body-table ci-dessus, non
   retouchée) et la section son fond actuel. Opacité du fond ALLÉGÉE DE 65 À
   50 % le 2026-09-10 matin (Marino : « on voit pas assez les vidéos de fond
   derrière les zones tarif, possible de réduire le vert foncé du
   glassmorphisme ? »), puis DE 50 À 35 % le 2026-09-10 soir (même journée, un
   cran franc de plus : « c'est l'opacité sombre du verre qu'il faut un peu
   réduire encore »). Ce n'est PAS l'opacité qui tient la lisibilité mais le
   flou : vérifié au pire cas, texte blanc sur média entièrement blanc, le
   contraste reste lisible grâce au flou de 14px ET au voile posé sur le média
   (règle ci-dessus, assombrit systématiquement ce qu'il y a derrière la
   carte, ne peut donc qu'améliorer ce contraste). Le filet de repli sans
   backdrop-filter (voir la table des contextes fp-ibox, main.css) n'est pas
   nécessaire ici. */
.fp-detail .fp-tarifs.has-fond-media .fp-tarifs-body-table {
  background: color-mix(in srgb, var(--fp-dark) 35%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid color-mix(in srgb, var(--fp-white) 18%, transparent);
}
/* --------------------------------------------------------------------------
   SUPPORT DE LISIBILITÉ SANS CARTE DE TARIFS (2026-09-09, Marino : « pour la
   vidéo à mettre sous les tarifs arcades, je sais qu'actuellement c'est pas
   prévu mais il faudrait pouvoir le faire »). Une fiche sans grille de tarifs
   de type "table" (Arcades et consœurs) peut désormais porter, elle aussi, un
   média de fond (inc/sections.php, $fp_tarifs_fond_nu) : la puce, le titre
   "Tarifs" et l'accroche, normalement posés à même le fond de la section,
   migrent alors DANS la carte "pastille" ou "repli ultime" réellement rendue
   (jamais les deux à la fois : un seul de ces deux rendus s'exécute). Cette
   carte porte la classe fp-tarifs-body-nu UNIQUEMENT quand elle n'a pas déjà
   d'habillage propre : une carte "-table" à lignes saisies à la main garde le
   sien, déjà traité en verre dépoli par la règle .has-fond-media ci-dessus.
   Par défaut TRANSPARENTE (même esprit que .fp-tarifs-body:has(.fp-tarif-solo)
   plus haut) : tant que le média n'est pas réellement visible (has-fond-media
   absent : vidéo seule pas encore activée, mobile, mouvement réduit, sans
   JavaScript), le texte reste posé directement sur le fond de la section,
   EXACTEMENT comme le rendu historique qu'il remplace.

   VARIANTE RESSERRÉE (2026-09-10, Marino : « une plus petite zone
   glassmorphisme, par exemple derrière le texte principal, la puce reste
   dehors comme le bouton, et la mention de délai peut juste avoir de l'ombre
   derrière »). Seuls le titre, le prix et la ligne de crédit restent DANS la
   carte : la puce (.fp-tarifs-nu-puce) et le pied (.fp-tarifs-nu-outro,
   mention de délai + bouton) en sont sortis côté PHP (fp_render_tarifs,
   $fp_tarifs_fond_nu_puce_html / $fp_tarifs_fond_nu_outro_html), posés
   directement sur le média. La carte se resserre donc à son contenu au lieu
   d'occuper toute la largeur de la section (voir max-width plus bas).

   CARTE RÉTRÉCIE, ÉPOUSANT SON CONTENU (2026-09-10 soir, Marino : « réduire
   la largeur de l'élément, faut qu'il s'adapte un peu mieux, quitte à avoir
   moins de padding sur les bords »). Sans largeur explicite, un bloc reprend
   par défaut toute la largeur disponible (bornée par max-width) : une carte
   pour un prix court restait donc aussi large qu'une carte pour un prix
   long. width: fit-content force la carte à se limiter à la largeur réelle
   de son contenu (titre, prix, ligne de crédit), max-width ne servant plus
   que de PLAFOND pour un contenu très long, qui repasse alors à la ligne.
   Plafond abaissé de 640px à 460px pour le même motif. Padding également
   réduit (bords moins généreux) : le padding propre au bloc prix
   (.fp-tarif-solo-price plus bas) reste, lui, inchangé, il porte le débord
   de l'ellipse.

   PLAFOND REMONTÉ À 620px (2026-09-10, nouvelle retouche Marino : « le
   titre passe très vite sur deux lignes et le texte en dessous aussi »).
   460px était trop juste pour le prix en Bebas et la phrase de crédit :
   remontée mesurée, encore loin des 640px d'avant le resserrement du soir,
   qui laisse plus de champ au texte sans redonner à la carte toute sa
   largeur d'origine. Sous 92% de la largeur de l'écran (mobile compris),
   c'est toujours ce pourcentage qui l'emporte : ce plafond ne joue que sur
   tablette et poste de travail. MARGE HAUTE RETIRÉE (0 au lieu des 40px
   hérités de .fp-tarifs-body ci-dessus, jamais annulés jusqu'ici) : la puce
   (.fp-tarifs-nu-puce plus bas) porte déjà son propre espacement de 8px
   avant la carte, ces deux marges s'additionnaient et creusaient un vide
   trop grand entre la puce et le verre dépoli. Le auto horizontal reste
   nécessaire au centrage d'une carte en largeur fit-content. --------- */
.fp-detail .fp-tarifs .fp-tarifs-body.fp-tarifs-body-nu {
  width: fit-content;
  /* 760px depuis le 2026-09-10 (deuxième passe, Marino : « encore un peu plus
     de largeur de contenu ») : à 620px, « 1.50 la partie ! » passait encore
     sur deux lignes avec le point d'exclamation seul en bas. */
  max-width: min(760px, 92%);
  margin: 0 auto;
  background: transparent;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
  overflow: visible;
}
/* Air entre la puce et le titre (repris de la règle générale
   .fp-wrap > div.fp-reveal:first-child, plus haut dans ce fichier, qui ne
   s'applique plus ici : l'en-tête injecté n'est plus l'enfant direct de
   .fp-wrap, mais de cette carte). Même valeur, sans y toucher. */
.fp-detail .fp-tarifs-body-nu > div.fp-reveal:first-child {
  margin-bottom: clamp(16px, 2.4vw, 24px);
}
/* Verre dépoli DÈS que le média est réellement visible : mêmes valeurs que la
   carte "-table" en fond média juste au-dessus (opacité allégée de 65 à 50 %
   le 2026-09-10 matin, puis de 50 à 35 % le 2026-09-10 soir, même motif),
   pour rester cohérente avec le reste de la fiche. Padding horizontal et
   vertical resserrés le même soir (voir le bloc de commentaire au-dessus de
   la règle de largeur). Largeur resserrée par la règle .fp-tarifs-body-nu
   ci-dessus (le centrage vient toujours de .fp-tarifs-body de base, non
   modifiée ici). */
.fp-detail .fp-tarifs.has-fond-media .fp-tarifs-body.fp-tarifs-body-nu {
  background: color-mix(in srgb, var(--fp-dark) 35%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid color-mix(in srgb, var(--fp-white) 18%, transparent);
  border-radius: var(--fp-radius-lg);
  padding: 30px clamp(18px, 3.5vw, 32px);
  box-shadow: var(--fp-shadow-lg);
}
/* PUCE HORS CARTE (2026-09-10) : posée directement sur le média, pilule
   sombre translucide via la classe fp-fond-sombre posée côté PHP (jetons
   --fp-ibox-*, main.css), même mécanique que la puce de la carte vert foncé
   plus haut dans ce fichier. L'espacement avant la carte qui suit vient de
   la règle générale .fp-wrap > div.fp-reveal:first-child (plus haut dans ce
   fichier) : cette puce en est le premier enfant direct dès qu'elle existe. */
.fp-detail .fp-tarifs-nu-puce {
  display: inline-block;
}
/* AIR RÉDUIT AVANT LA CARTE (2026-09-10 soir, Marino : « la puce reste juste
   au-dessus de la zone en verre, à quelques pixels d'écart ») : règle PROPRE
   à cette puce plutôt qu'une retouche de la règle générale
   .fp-wrap > div.fp-reveal:first-child (juste plus haut dans ce fichier),
   qui sert aussi ailleurs sur cette même fiche. Même sélecteur (div, classe,
   :first-child) que la règle générale pour égaler sa spécificité : cette
   règle, déclarée plus bas dans le fichier, l'emporte donc à l'octet près
   pour ce seul élément, sans toucher à la règle générale. */
.fp-detail .fp-tarifs .fp-wrap > div.fp-tarifs-nu-puce:first-child {
  margin-bottom: 8px;
}
/* PIED HORS CARTE (2026-09-10) : mention de délai et bouton, posés eux aussi
   directement sur le média, dans le prolongement de la carte resserrée
   juste au-dessus. */
.fp-detail .fp-tarifs-nu-outro {
  margin-top: clamp(18px, 2.4vw, 26px);
}
/* Mention de délai SANS carte pour la porter : plus d'aplat/flou, une simple
   ombre sur les lettres suffit à la garder lisible sur le média (même
   recette que .fp-tarifs-credit plus haut dans ce fichier). */
.fp-detail .fp-tarifs-nu-outro .fp-tarifs-delai {
  color: var(--fp-white);
  text-shadow:
    0 1px 2px color-mix(in srgb, var(--fp-secondary-dark) 70%, transparent),
    0 2px 10px color-mix(in srgb, var(--fp-secondary-dark) 45%, transparent);
}
/* Hauteur de la SECTION (pas de la carte) : le repli, court par nature (puce
   et titre, parfois une accroche), ne suffirait pas à laisser voir la vidéo
   ou l'image de fond. Padding vertical propre à ce cas, plus généreux que le
   rythme habituel de la section (règle .fp-tarifs de base, plus haut) : le
   contenu reste centré par .fp-wrap, inchangé. */
.fp-detail .fp-tarifs.fp-tarifs-nu {
  padding-top: clamp(140px, 18vw, 220px);
  padding-bottom: clamp(140px, 18vw, 220px);
}
/* Mention de bas de carte ET note de ligne (relecture Opus du 2026-09-06) :
   ailleurs dans cette feuille, ces deux classes sont à 80% de blanc
   (color-mix), pensé pour un contraste sur le fond plein --fp-secondary
   (~5.9:1). Sur le verre 65% posé au-dessus d'un média clair, ce même 80%
   retombe sous le seuil AA (~3,75:1 mesuré sur média blanc) : blanc PLEIN
   uniquement dans ce cas, sans toucher au reste du site. */
.fp-detail .fp-tarifs.has-fond-media .fp-tarifs-note,
.fp-detail .fp-tarifs.has-fond-media .fp-tarifs-rownote {
  color: var(--fp-white);
}

.fp-detail .fp-tarifs-widget {
  display: block;
}
/* Titre de grille : plus rendu sur les pages activite (show_title="0", la
   section a deja son h2). Regle conservee, en graisse NATIVE 400, pour les
   contextes ou le shortcode est appele avec son titre. */
.fp-detail .fp-tarifs-title {
  margin: 0 0 26px;
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--fp-white);
  text-align: center;
}

/* --------------------------------------------------------------------------
   VERSION « PRIX UNIQUE » (.fp-tarif-solo, grille "visual" du plugin ou
   repli zone) : REFONTE « FRONTON » (retour client : « section dégueulasse,
   propose un autre design »). Abandon complet du médaillon sombre et du
   texte en arc : le tarif est écrit EN TRÈS GRAND (Thoge blanc) directement
   sur le fond de section, entouré d'une ellipse « coup de marqueur » (SVG
   légèrement inclinée) qui SE DESSINE à l'apparition (stroke-dashoffset
   déclenché par .fp-reveal.is-in posé par main.js sur .fp-tarifs-body).
   Plus aucune vignette : le fronton est du texte pur. Le sous-texte est TIRÉ
   À L'INTÉRIEUR de l'ellipse, encerclé avec le prix (dernier retour client) ;
   deux étincelles décoratives scintillent en périphérie. Sous l'ellipse, la
   mention complémentaire et le bouton forment un second groupe resserré. Tout
   est rigoureusement centré (exigence client conservée).
   -------------------------------------------------------------------------- */
.fp-detail .fp-tarif-solo {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 900px;
  margin: 28px auto 0;
  text-align: center;
}
/* (Plus de vignette au-dessus du prix : retour client, le fronton est du
   texte pur.) Le prix, SON SOUS-TEXTE et l'ellipse partagent le meme
   conteneur : l'ellipse epouse la boite entiere (preserveAspectRatio:none),
   elle encercle donc les deux d'un seul trait.
   Le padding bas est un peu plus genereux que le haut : l'ellipse est centree
   sur la boite, ce decalage remonte le bloc de texte et laisse le sous-texte,
   qui est la ligne la plus basse, franchement a l'interieur de l'arc. */
.fp-detail .fp-tarif-solo-price {
  position: relative;
  display: inline-block;
  max-width: 100%;
  /* Marges latérales réduites le 2026-09-10 (même retouche que le plafond de
     la carte) : c'est de la largeur rendue au texte, l'ellipse suit la boîte. */
  padding: clamp(26px, 3.6vw, 46px) clamp(26px, 4.5vw, 56px) clamp(30px, 4vw, 52px);
}
/* Ellipse AGRANDIE (le client l'autorise explicitement : « quitte a rendre
   l'element anime un peu plus grand ») : rayons portes de 262x86 a 270x96
   dans le meme viewBox 560x210, et SVG deborde de 1.5 % en largeur / 2.5 % en
   hauteur hors de la boite. Elle reste un encerclement serre, pas un ovale
   demesure. Aucune incidence sur l'animation : pathLength="100" normalise la
   longueur du trace, stroke-dasharray/offset restent en 100 -> 0.
   GÉOMÉTRIE EXPLICITE (retour client du 2026-08-20 : sur téléphone, « le rond
   est calé tout à gauche au lieu de s'étendre de gauche à droite derrière le
   contenu »). La version précédente posait « inset » sur les quatre côtés en
   laissant width et height sur « auto ». Or un SVG est un élément REMPLACÉ :
   quand sa largeur est « auto », les règles de dimensionnement lui donnent sa
   taille intrinsèque (300px de repli pour un SVG qui n'a qu'un viewBox) et le
   côté droit est simplement ignoré, ce qui plaque l'ellipse à gauche de la
   boîte. Certains moteurs étirent quand même la largeur, d'autres non : le
   rendu dépendait donc du navigateur, et le téléphone de la cliente tombait du
   mauvais côté. On donne désormais une largeur EXPLICITE en pourcentage, seule
   écriture qui se comporte pareil partout : 103 % de la boîte avec un décalage
   de -1.5 % à gauche, soit exactement le même débord des deux côtés qu'avant.

   HAUTEUR ELLE AUSSI EXPLICITE, PAS DÉDUITE DU VIEWBOX (2026-09-10, Marino,
   capture de la fiche Arcades à l'appui : « adapter la dimension du rond en
   arrière-plan à la taille du texte, dans ce cas ça dépasse »). La hauteur
   déduite du rapport du viewBox (aspect-ratio: 560/210) dépend de la LARGEUR
   de la boîte, pas de sa hauteur réelle : tant que le prix tenait sur une
   ligne, la coïncidence faisait à peu près illusion, mais dès que le prix
   passe à deux lignes (cas réel : « 1.50 LES 15 CRÉDITS ! »), la boîte
   grandit en hauteur alors que l'ellipse, elle, garde la hauteur calculée
   sur la largeur : le texte déborde de l'encerclement. On applique donc au
   pourcentage de hauteur EXACTEMENT le même principe que celui déjà validé
   pour la largeur ci-dessus (et déjà utilisé, avant ce chantier, uniquement
   sur le palier téléphone plus bas dans ce fichier) : height: 105% avec un
   débord de 2.5 % en haut ET en bas, résolu contre la hauteur RÉELLE de
   .fp-tarif-solo-price (position: relative, conteneur direct), donc toujours
   fidèle au nombre de lignes du prix, une comme deux. Ni « auto » ni
   aspect-ratio : deux dimensions désormais explicites, comme le veut la
   garde ci-dessus. L'animation n'est pas affectée : pathLength="100" normalise
   la longueur du tracé indépendamment de la géométrie, stroke-dasharray/
   offset restent en 100 -> 0 (voir la règle juste en dessous). */
.fp-detail .fp-tarif-solo-ring {
  position: absolute;
  top: -2.5%;
  left: -1.5%;
  right: auto;
  bottom: auto;
  width: 103%;
  height: 105%;
  overflow: visible;
  transform: rotate(-2.5deg);
  pointer-events: none;
}
.fp-detail .fp-tarif-solo-ring ellipse {
  fill: none;
  stroke: var(--fp-white);
  stroke-width: 4.5;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  opacity: .92;
}
/* Trace du « coup de marqueur » : declenche par la revelation de l'encart
   (.fp-tarifs-body porte .fp-reveal, main.js lui pose .is-in). */
.fp-detail .fp-tarifs-body.is-in .fp-tarif-solo-ring ellipse {
  transition: stroke-dashoffset 1.1s var(--fp-anim-ease) .35s;
  stroke-dashoffset: 0;
}
/* Garde mouvement reduit : le trace est deja termine, aucune transition. La
   regle .is-in est reprise ici pour qu'elle ne reintroduise pas la transition
   par specificite superieure. */
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-tarif-solo-ring ellipse,
  .fp-detail .fp-tarifs-body.is-in .fp-tarif-solo-ring ellipse {
    stroke-dashoffset: 0;
    transition: none;
  }
}
/* Prix en THOGE (retour client : Thoge etait mieux) mais en graisse NATIVE
   400 : l'illisibilite venait du font-weight 700 herite des h3 globaux, qui
   synthetisait un faux gras pateux sur cette police deja ronde.
   AGRANDI (retour client : le tarif etait trop petit) : le fronton doit se
   lire de loin, l'agrandissement passe uniquement par la taille. */
.fp-detail .fp-tarif-solo-title {
  margin: 0;
  font-family: var(--fp-font-display);
  font-weight: 400;
  font-size: clamp(3.1rem, 8.6vw, 7.5rem);
  line-height: .95;
  letter-spacing: .01em;
  color: var(--fp-white);
  text-shadow: 0 8px 22px color-mix(in srgb, var(--fp-secondary-dark) 30%, transparent);
}
/* Sous-texte (champ « Texte / Body » du gestionnaire de tarifs) : PLUS AUCUNE
   pastille blanche (retour client : « un element sur fond blanc qui ressemble
   a un bouton mais qui n'en est pas »). C'est une simple ligne de texte
   blanche, sans aplat ni bordure ni ombre portee, DESORMAIS TIREE A
   L'INTERIEUR de l'ellipse : elle est encerclee avec le prix, un seul bloc.
   Elle se revele juste apres le trace du marqueur, comme la fin du meme geste.
   BORNAGE (c'est ce qui garantit qu'un body long ne sort jamais de l'arc) :
   min(30ch, 68%). 30ch plafonne la mesure sur grand ecran (l'ellipse y est
   large, c'est la lisibilite qui commande) ; 68 % de la boite prend le relais
   sur petit ecran, ou l'ellipse se resserre - la ligne reste alors dans la
   partie centrale de l'arc, la ou il est le plus large. Au-dela, le texte
   passe simplement a la ligne suivante et la boite grandit : l'ellipse,
   dimensionnee sur la boite, grandit avec lui. Marge haute élargie le
   2026-09-07 (retour de Marino sur Arcades : le sous-texte collait au prix),
   puis RESSERRÉE le 2026-09-10 soir (retour inverse, même Marino : « trop
   d'air entre le prix et le texte du dessous »). Taille de police également
   réduite le même soir (« c'est une précision, pas un argument, elle ne doit
   pas concurrencer le prix ») : environ -20% sur les trois termes du clamp.
   BORNES ÉLARGIES (2026-09-10, même retouche que le plafond de la carte
   juste au-dessus, .fp-tarifs-body-nu passé de 460 à 620px) : la ligne
   passait sur trois lignes dans le cadre resserré du soir, plus que ce que
   l'ellipse rendait lisible. 30ch/68% devient 36ch/78%, dans les mêmes
   proportions que la largeur de carte gagnée, pour que le texte occupe la
   part élargie de l'arc sans en déborder. */
.fp-detail .fp-tarif-solo-sub {
  max-width: min(44ch, 84%);
  margin: clamp(6px, 1vw, 12px) auto 0;
  font-family: var(--fp-font-body);
  font-weight: 500;
  font-size: clamp(.85rem, 1.5vw, 1.08rem);
  line-height: 1.45;
  color: var(--fp-white);
  text-shadow: 0 2px 14px color-mix(in srgb, var(--fp-secondary-dark) 45%, transparent);
  opacity: 0;
  transform: translateY(10px);
}
.fp-detail .fp-tarif-solo-sub :where(p) {
  margin: 0;
}
.fp-detail .fp-tarifs-body.is-in .fp-tarif-solo-sub {
  transition: opacity .6s var(--fp-anim-ease) 1.05s, transform .6s var(--fp-anim-ease) 1.05s;
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-tarif-solo-sub,
  .fp-detail .fp-tarifs-body.is-in .fp-tarif-solo-sub {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
/* Etincelles decoratives en peripherie du bloc prix, scintillement alterne. */
.fp-detail .fp-tarif-spark {
  position: absolute;
  z-index: 1;
  color: var(--fp-white);
  opacity: .85;
  pointer-events: none;
}
.fp-detail .fp-tarif-spark svg {
  width: 100%;
  height: 100%;
}
.fp-detail .fp-tarif-spark.is-a {
  top: 6%;
  left: 3%;
  width: 34px;
  height: 34px;
}
.fp-detail .fp-tarif-spark.is-b {
  bottom: 14%;
  right: 4%;
  width: 26px;
  height: 26px;
}
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-tarif-spark {
    animation: fp-tarif-spark-twinkle 3.6s ease-in-out infinite;
  }
  .fp-detail .fp-tarif-spark.is-b {
    animation-delay: 1.6s;
  }
}
@keyframes fp-tarif-spark-twinkle {
  0%, 100% { opacity: .35; transform: scale(.85) rotate(0deg); }
  50% { opacity: 1; transform: scale(1.08) rotate(12deg); }
}
/* Mention complementaire (champ « Info complementaire » du gestionnaire de
   tarifs). Elle reste DELIEE du prix par la taille et la graisse, mais elle
   repasse en BLANC et descend se coller au bouton (retour client). Elle n'est
   donc plus separee du reste par la couleur : c'est la proximite avec le
   bouton, en bas du bloc, qui la designe comme mention de pied.
   CONTRASTE : blanc sur l'aplat --fp-accent de la section ne donne que
   2.17:1, sous le seuil pour du petit texte. On ne renonce pas au blanc : on
   pose derriere le texte un VOILE sombre (::before ci-dessous) qui ramene le
   fond local a 6.75:1. Le voile est floute, donc sans arete : c'est une brume,
   pas une boite - aucun risque qu'il soit relu comme un second bouton. */
.fp-detail .fp-tarifs-credit {
  position: relative;
  isolation: isolate;
  max-width: 52ch;
  margin: clamp(18px, 2.4vw, 26px) auto 0;
  padding: 2px 4px;
  text-align: center;
  font-family: var(--fp-font-body);
  font-weight: 400;
  font-size: .82rem;
  line-height: 1.6;
  letter-spacing: .045em;
  color: var(--fp-white);
  /* Ombre PORTEE SUR LES LETTRES, et non plus un voile derriere elles : elle
     detache les caracteres sans dessiner la moindre surface. C'est ce qui
     remplace le voile supprime juste en dessous. */
  text-shadow:
    0 1px 2px color-mix(in srgb, var(--fp-secondary-dark) 70%, transparent),
    0 2px 10px color-mix(in srgb, var(--fp-secondary-dark) 45%, transparent);
}
/* VOILE SUPPRIME, troisieme et dernier retour du client sur ce meme element :
   « enleve cette zone d'ombre moche ». Il avait deja ete resserre une premiere
   fois (« il y a une big ombre, elle m'a l'air immense ») : le resserrer ne
   suffisait pas, c'est la surface elle-meme qui genait. Sur une mention d'une
   seule ligne, un aplat flou centre se lit toujours comme une tache, quelle que
   soit sa taille.
   NE PAS LE REINTRODUIRE. Si la lisibilite doit etre renforcee, passer par
   l'ombre portee sur les lettres ci-dessus, qui ne cree aucune surface.
   Contrepartie assumee et connue du client, qui a demande de ne pas m'arreter
   aux contrastes : sans voile, le blanc sur --fp-accent tombe sous le seuil de
   lisibilite recommande pour du petit texte. L'ombre portee compense a l'oeil,
   pas au calcul. */
/* Le lien reprend le systeme de soulignement PARTAGE du site (main.css, barre
   currentColor qui se deplie) : on ne redefinit pas un second soulignement
   local, on se contente de la couleur et d'un etat de repos visible. */
.fp-detail .fp-tarifs-credit a {
  color: var(--fp-white);
  background-size: 100% 1.5px;
}
/* Bouton pill BLANC (au lieu du bouton primary herite), facon RP, en GRAND
   format (c'est l'action principale de la section). Reutilise pour les 2
   versions (fronton et tableau).
   REMONTE vers le texte (retour client) : 26px -> 16px. Et quand la mention
   complementaire le precede, le bouton lui est carrement colle (regle de
   voisinage juste apres) : sous-texte, mention et bouton forment alors un
   ensemble resserre au lieu de trois blocs espaces. */
.fp-detail .fp-tarifs-actions {
  margin-top: 16px;
  display: flex;
  justify-content: center;
}
.fp-detail .fp-tarifs-actions .fp-btn {
  background: var(--fp-white);
  color: var(--fp-primary);
  border-color: var(--fp-white);
  font-size: 1.1rem;
  padding: 16px 34px;
  box-shadow: 0 16px 30px -14px color-mix(in srgb, var(--fp-secondary-dark) 55%, transparent);
}
/* Au survol, le remplissage teal du fp-btn commun (::before) glisse sur le
   bouton : le TEXTE doit passer en blanc (retour client : il restait teal,
   bouton « full vert » illisible). */
.fp-detail .fp-tarifs-actions .fp-btn::before {
  background: var(--fp-primary);
}
.fp-detail .fp-tarifs-actions .fp-btn:hover {
  color: var(--fp-white);
}
/* Mention suivie du bouton : on les colle (retour client, « vraiment
   relativement colle aux boutons »). Le voile de la mention deborde de 12px
   vers le bas, cet ecart le laisse se fondre juste au-dessus de la pilule. */
.fp-detail .fp-tarifs-credit + .fp-tarifs-actions {
  margin-top: 10px;
}
/* Dans la carte du tableau, le bouton blanc porte du VERT FONCE (et non le
   teal par defaut) : c'est la pilule du modele, et le contraste sur blanc y
   est bien meilleur. */
.fp-detail .fp-tarifs-body-table .fp-tarifs-actions {
  margin-top: 28px;
}
.fp-detail .fp-tarifs-body-table .fp-tarifs-actions .fp-btn {
  color: var(--fp-secondary);
  box-shadow: 0 18px 34px -16px color-mix(in srgb, var(--fp-secondary-dark) 80%, transparent);
}
.fp-detail .fp-tarifs-body-table .fp-tarifs-actions .fp-btn::before {
  background: var(--fp-secondary);
}
.fp-detail .fp-tarifs-body-table .fp-tarifs-actions .fp-btn:hover {
  color: var(--fp-white);
}

/* --------------------------------------------------------------------------
   VERSION « TABLEAU » (plugin fp-tarifs-manager, shortcode [fp_tarifs]) :
   REFONTE « CARTE VERT FONCÉ », copie du modèle Raiffeisen Parc (retour
   client, captures à l'appui : « je veux le même que pour le Raiffeisen Parc,
   titres plus grands, fond vert foncé, etc., vraiment copy paste »). La carte
   blanche à prix teal disparaît : la carte est en --fp-secondary, TOUT le
   texte est blanc, les noms de jours sont beaucoup plus grands, la bande des
   créneaux est un aplat légèrement plus clair, la mention de bas de carte est
   en italique atténué et le bouton blanc est REMONTÉ DANS la carte.
   Toutes les polices de titre restent en graisse NATIVE 400 (Bebas/Thoge
   n'existent qu'en 400 : l'agrandissement passe par la taille, jamais par un
   font-weight qui produirait un faux gras).
   Le markup reste un <table> natif et les en-têtes portent scope=colgroup/col/
   row : la lecture par un lecteur d'écran est intacte. Le défilement
   horizontal reste confiné à .fp-tarifs-matrix-wrap, jamais sur la page.
   Mode simple (3 colonnes) et mode matrix (jours x tranches), tout centré
   (exigence client conservée), colonne des libellés collante en matrix.
   -------------------------------------------------------------------------- */
/* border-radius/box-shadow neutralises : c'est la CARTE qui les porte
   desormais, pas le tableau (la feuille du plugin, fp-tarifs.css, en pose par
   defaut pour un usage hors theme). */
.fp-detail .fp-tarifs-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  color: var(--fp-white);
}
/* (La liste simple a sa propre mise en page, plus bas : largeur des colonnes
   au contenu, libellés à gauche, prix à droite.) */
.fp-detail .fp-tarifs-table th,
.fp-detail .fp-tarifs-table td {
  /* Hauteur des cases resserrée le 2026-09-10 (Marino : « idem pour les
     tableaux, on réduit... la hauteur des cases ») : seul le rembourrage
     vertical baisse, l'horizontal reste identique pour ne pas resserrer la
     largeur utile des colonnes. */
  padding: 12px 14px;
  text-align: center;
  border-bottom: 1px solid color-mix(in srgb, var(--fp-white) 14%, transparent);
}
/* En-tetes BLANCS et nettement plus GRANDS (c'est le « titres plus grands »
   demande) ; graisse native 400. */
.fp-detail .fp-tarifs-table thead th {
  background: transparent;
  border-bottom: 1px solid color-mix(in srgb, var(--fp-white) 26%, transparent);
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: clamp(1.05rem, 1.9vw, 1.6rem);
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fp-white);
}
/* Plus de zebrage : la cible ne separe les lignes que par un filet tres
   discret (et un zebrage translucide trahirait la colonne collante, dont le
   fond doit rester strictement opaque). */
.fp-detail .fp-tarifs-table tbody tr:last-child td,
.fp-detail .fp-tarifs-table tbody tr:last-child th {
  border-bottom: none;
}
.fp-detail .fp-tarifs-table tbody tr {
  transition: background .2s ease;
}
/* th inclus : la premiere cellule d'une ligne est un th scope="row" (matrice
   depuis toujours, liste simple depuis le 2026-09-03), sans quoi le survol
   ne teintait que la fin de la ligne. */
.fp-detail .fp-tarifs-table tbody tr:hover th,
.fp-detail .fp-tarifs-table tbody tr:hover td {
  background: color-mix(in srgb, var(--fp-white) 7%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-tarifs-table tbody tr { transition: none; }
}
/* Libelles de ligne : police de CORPS (petit texte -> jamais la police de
   titre), blancs. */
.fp-detail .fp-tarifs-label {
  font-family: var(--fp-font-body);
  font-weight: 600;
  font-size: .98rem;
  color: var(--fp-white);
}
.fp-detail .fp-tarifs-rownote {
  display: block;
  margin-top: 2px;
  font-family: var(--fp-font-body);
  font-weight: 400;
  font-size: .8rem;
  color: color-mix(in srgb, var(--fp-white) 80%, transparent);
}
/* Prix CENTRÉ (exigence client conservée), blanc et grand : c'est
   l'information que le visiteur vient chercher. */
.fp-detail .fp-tarifs-price-col,
.fp-detail .fp-tarifs-price {
  text-align: center;
  white-space: nowrap;
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: clamp(1.2rem, 1.8vw, 1.55rem);
  letter-spacing: .02em;
  color: var(--fp-white);
}
/* Mention de bas de carte (note de grille du plugin, ou mention par defaut) :
   petite, italique, blanc attenue a 80 % -> environ 5.9:1 sur --fp-secondary,
   largement au-dessus du seuil, jamais un gris pale. */
.fp-detail .fp-tarifs-note {
  max-width: 62ch;
  margin: 20px auto 0;
  text-align: center;
  font-family: var(--fp-font-body);
  font-style: italic;
  font-size: .82rem;
  line-height: 1.6;
  color: color-mix(in srgb, var(--fp-white) 80%, transparent);
}

/* RÈGLE DES 10 MINUTES (Marino, 2026-09-08/09) : mention de service sobre
   posée dans la zone Tarifs des fiches d'activité (branches « offres »,
   « table » côté fiche et pastille de fp_render_tarifs, inc/sections.php),
   jamais en pilule ni en FAQ. Même gabarit typographique discret que la
   mention « tarifs indicatifs » déjà en place sur chaque carte
   (.fp-tarifs-note / .fp-tarifs-credit juste au-dessus et plus bas dans ce
   fichier) : petite, jamais en concurrence visuelle avec le prix. La couleur
   varie selon la carte qui l'accueille (règles ci-dessous), le gabarit
   commun reste ici. */
.fp-detail .fp-tarifs-delai {
  max-width: 62ch;
  margin: 10px auto 0;
  text-align: center;
  font-family: var(--fp-font-body);
  font-style: italic;
  font-size: .82rem;
  line-height: 1.6;
}
/* Carte vert foncé (branche « table » côté fiche d'activité) : même
   traitement que la mention de bas de carte ci-dessus, blanc atténué à
   80 % (environ 5.9:1 sur --fp-secondary). */
.fp-detail .fp-tarifs-body-table .fp-tarifs-delai {
  color: color-mix(in srgb, var(--fp-white) 80%, transparent);
}
/* Fond accent (branche pastille) ou carte teal de la section « offres »
   (.fp-tarifs-body-tk) : même traitement que .fp-tarifs-credit, ombre
   portée sur les lettres pour garder le contraste sans poser de voile
   derrière le texte. */
.fp-detail .fp-tarifs-body:not(.fp-tarifs-body-table) .fp-tarifs-delai {
  color: var(--fp-white);
  text-shadow:
    0 1px 2px color-mix(in srgb, var(--fp-secondary-dark) 70%, transparent),
    0 2px 10px color-mix(in srgb, var(--fp-secondary-dark) 45%, transparent);
}
/* Mention collée au bouton qui suit, même esprit que .fp-tarifs-credit +
   .fp-tarifs-actions plus bas dans ce fichier (branches « offres » et
   pastille, qui gardent leur bouton juste après la mention). */
.fp-detail .fp-tarifs-delai + .fp-tarifs-actions {
  margin-top: 10px;
}

/* LISTE SIMPLE, lecture « carte des prix » (2026-09-03, retour client : « plus
   joli, texte du créneau plus grand, une ligne qui sépare »). Le plugin ne
   rend plus d'en-tête sur cette liste par défaut (un seul intitulé facultatif
   peut réapparaître, réglé dans l'admin) : le poids visuel qu'avaient les
   titres de colonnes passe sur le libellé de chaque ligne : police de titre en
   majuscules, à GAUCHE, prix à DROITE, plus grand lui aussi, filets nettement
   visibles (30 % de blanc, contre 14 % hérités de la matrice) et lignes plus
   aérées. Largeur des colonnes au contenu (plus de 50/50 figé : un libellé
   long et un prix court n'ont pas la même place à prendre). Le centrage
   « tout centré » reste la règle de la MATRICE, pas de cette liste. Les
   règles de cellule visent le CORPS du tableau (tbody) : l'en-tête
   facultatif garde l'habillage commun de « thead th » ci-dessus. */
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) {
  table-layout: auto;
}
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) tbody th,
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) tbody td {
  /* Hauteur resserrée le 2026-09-10 (Marino), même logique que la règle
     générale plus haut : rembourrage vertical seul en baisse. */
  padding: 15px 18px;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid color-mix(in srgb, var(--fp-white) 30%, transparent);
}
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-label {
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: clamp(1.3rem, 2vw, 1.7rem);
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: .04em;
}
/* Cellule « Créneau » quand Prestation est aussi affichée (3 colonnes) : elle
   n'est plus l'en-tête de ligne, texte de corps lisible. */
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) td:not(.fp-tarifs-price) {
  font-family: var(--fp-font-body);
  font-size: 1.05rem;
}
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-price-col,
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-price {
  text-align: right;
  font-size: clamp(1.4rem, 2vw, 1.85rem);
}
/* La note de ligne vit dans la cellule du prix (nowrap) : elle doit pouvoir
   passer à la ligne, en petit, sous le prix. */
.fp-detail .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-price .fp-tarifs-rownote {
  white-space: normal;
  margin-top: 4px;
  letter-spacing: 0;
}
/* Matrice jour x tranche : noms de jours blancs et tres grands, filets
   verticaux clairs entre colonnes, colonne des libelles collante au scroll
   horizontal (reste lisible sur mobile). Le scroll vit ICI et nulle part
   ailleurs : la page ne deborde jamais lateralement. */
.fp-detail .fp-tarifs-matrix-wrap {
  overflow-x: auto;
  border-radius: 0;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--fp-white) 45%, transparent) transparent;
}
.fp-detail .fp-tarifs-matrix {
  min-width: 560px;
}
.fp-detail .fp-tarifs-matrix th,
.fp-detail .fp-tarifs-matrix td {
  text-align: center;
  /* Hauteur resserrée le 2026-09-10 (Marino) : rembourrage vertical seul en
     baisse, l'horizontal reste à 14px pour ne pas resserrer les colonnes. */
  padding: 11px 14px;
}
/* Angle et libelles collants : fond OPAQUE obligatoire (ils masquent le
   contenu qui defile dessous). L'angle de la 2e ligne d'en-tete prend la
   teinte de la bande des creneaux pour que la bande traverse toute la carte. */
.fp-detail .fp-tarifs-matrix .fp-tarifs-corner {
  position: sticky;
  left: 0;
  z-index: 3;
  background: var(--fp-secondary);
}
.fp-detail .fp-tarifs-matrix thead tr:nth-child(2) .fp-tarifs-corner {
  background: color-mix(in srgb, var(--fp-white) 10%, var(--fp-secondary));
}
/* Noms de jours : le « titres plus grands » demande. Graisse NATIVE 400. */
.fp-detail .fp-tarifs-matrix .fp-tarifs-day {
  background: transparent;
  color: var(--fp-white);
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: clamp(1.15rem, 2.1vw, 1.85rem);
  line-height: 1.05;
  letter-spacing: .04em;
  text-transform: uppercase;
  vertical-align: top;
  padding-top: 14px;
  padding-bottom: 11px;
}
/* Seconde ligne d'un jour (ex. « + jours feries (veille comprise) et vacances
   scolaires ») : police de CORPS, casse normale, blanc attenue a 80 %
   (~6.7:1 sur --fp-secondary). vertical-align:top sur les <th> ci-dessus :
   les autres en-tetes restent calees en haut, la rangee s'ajuste sans que
   leur libelle ne se recentre bizarrement. */
.fp-detail .fp-tarifs-matrix .fp-tarifs-day-subtitle {
  display: block;
  max-width: 26ch;
  margin: 6px auto 0;
  font-family: var(--fp-font-body);
  font-size: .72rem;
  font-weight: 400;
  line-height: 1.35;
  text-transform: none;
  letter-spacing: normal;
  color: color-mix(in srgb, var(--fp-white) 80%, transparent);
}
/* Bande des creneaux : aplat legerement plus clair que la carte, petit texte
   blanc en police de corps. */
.fp-detail .fp-tarifs-matrix .fp-tarifs-period {
  background: color-mix(in srgb, var(--fp-white) 10%, var(--fp-secondary));
  color: var(--fp-white);
  font-family: var(--fp-font-body);
  font-weight: 500;
  font-size: .8rem;
  line-height: 1.3;
  text-transform: none;
  letter-spacing: .03em;
  padding-top: 8px;
  padding-bottom: 8px;
}
/* Fins filets verticaux entre colonnes. */
.fp-detail .fp-tarifs-matrix .fp-tarifs-day,
.fp-detail .fp-tarifs-matrix .fp-tarifs-period,
.fp-detail .fp-tarifs-matrix .fp-tarifs-price {
  border-left: 1px solid color-mix(in srgb, var(--fp-white) 18%, transparent);
}
/* Colonne des libellés de ligne : CENTRÉE elle aussi (était alignée à
   gauche -> seul point vraiment « gauche-droite » restant du mode matrice,
   puisque le reste de la matrice était déjà centré). */
.fp-detail .fp-tarifs-matrix .fp-tarifs-rowlabel {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--fp-secondary);
  text-align: center;
  font-family: var(--fp-font-body);
  font-weight: 600;
  font-size: .98rem;
  color: var(--fp-white);
  box-shadow: 2px 0 0 0 color-mix(in srgb, var(--fp-white) 18%, transparent);
}
.fp-detail .fp-tarifs-matrix .fp-tarifs-rownote {
  display: block;
  text-align: center;
  font-family: var(--fp-font-body);
  font-weight: 400;
  font-size: .78rem;
  color: color-mix(in srgb, var(--fp-white) 80%, transparent);
}
.fp-detail .fp-tarifs-matrix .fp-tarifs-price {
  font-family: var(--fp-font-heading);
  font-weight: 400;
  color: var(--fp-white);
}

/* --------------------------------------------------------------------------
   TARIFS SUR PETIT ÉCRAN : UNE PILE DE TABLEAUX PAR JOUR(S) (retour client
   2026-08-17 : « sur mobile, plus aucun tableau à faire défiler
   horizontalement »).
   Le plugin fp-tarifs-manager rend, depuis la MÊME boucle de données, le
   tableau complet ET une pile de petits tableaux, un par groupe de jours
   réellement déclaré dans la grille de l'activité (deux groupes donnent deux
   tableaux, trois en donnent trois : jamais un découpage figé). Ici, on ne
   fait que choisir lequel des deux s'affiche.
   SEUIL 820px : c'est la largeur en dessous de laquelle la matrice complète
   (largeur minimale 560px) commence réellement à défiler dans sa carte
   (90vw moins 2 x 40px de gouttière moins 2 x clamp(24px, 5vw, 64px) de
   retrait de carte). Au-dessus, RIEN NE CHANGE : le poste de travail garde le
   tableau complet actuel, au pixel près.
   La bascule est écrite ici EN PLUS de la feuille du plugin : activite.css est
   chargée dans le <head> des pages de détail, alors que la feuille du plugin
   n'est mise en file qu'au moment où le shortcode est rendu (donc en pied de
   page). Sans cette copie, la pile pourrait apparaître une fraction de seconde
   sous le tableau complet au chargement.
   ÉCRITURE MOBILE D'ABORD (retour client du 2026-08-20, « je ne vois toujours
   pas les mini-tableaux sur mon téléphone ») : la pile est désormais l'état PAR
   DÉFAUT de la feuille, et c'est la matrice complète qui est rendue par une
   requête de grand écran. Le résultat visible est le même qu'avant à toutes les
   largeurs, mais l'ordre des priorités change : si une couche quelconque
   (optimiseur de CSS, feuille tronquée, moteur ancien) perdait la requête de
   média, le téléphone garderait la pile au lieu de retomber sur la matrice à
   faire défiler. C'est la demande du client : la pile n'est pas un mode que
   l'on active, c'est l'affichage normal du téléphone.
   Le garde-fou reste la classe .fp-tarifs-has-daystack, posée par le plugin
   UNIQUEMENT quand une pile existe réellement en dessous : sans elle, la
   matrice complète reste visible partout, jamais de section vide.
   -------------------------------------------------------------------------- */
.fp-detail .fp-tarifs-has-daystack .fp-tarifs-matrix-wrap {
  display: none;
}
/* Une seule colonne EXPLICITE : chaque sous-tableau occupe donc toute la
   largeur utile de la carte, jamais la largeur naturelle de son contenu
   (retour client du 2026-08-17 : « les mini-tableaux en pleine largeur de la
   carte, empilés et respirants »). L'écart entre deux groupes de jours est de
   22px, pour qu'ils se lisent bien comme des blocs distincts. */
.fp-detail .fp-tarifs-daystack {
  display: grid;
  grid-template-columns: 1fr;
  gap: 22px;
}
@media (min-width: 821px) {
  .fp-detail .fp-tarifs-has-daystack .fp-tarifs-matrix-wrap {
    display: block;
  }
  .fp-detail .fp-tarifs-has-daystack .fp-tarifs-daystack {
    display: none;
  }
}
/* Chaque sous-tableau porte aussi .fp-tarifs-matrix : il hérite donc de tout
   l'habillage ci-dessus (jours en grand, bande des créneaux, filets, prix
   blancs). On lui retire ce qui n'a plus de sens sans défilement : la largeur
   minimale de 560px et la colonne collante. Sélecteurs COMPOSÉS
   (.fp-tarifs-matrix.fp-tarifs-daytable) pour l'emporter sans dépendre de
   l'ordre du fichier, les réglages mobiles de la matrice complète vivant plus
   bas dans cette feuille. */
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable {
  min-width: 0;
  width: 100%;
}
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable .fp-tarifs-corner,
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable .fp-tarifs-rowlabel {
  position: static;
  box-shadow: none;
}
/* Cellules resserrées et prix un cran plus sobre : c'est ce qui permet à un
   groupe de jours à deux créneaux (le cas courant) de tenir sans défiler dès
   320px de large (libellé 60px + 2 prix de 68px = 196px pour 208px utiles
   dans la carte). Le prix reste l'information la plus grosse de la ligne.
   Retrait vertical remonté à 13px (retour client du 2026-08-17, « respirants ») :
   la carte élargie plus bas dans cette feuille rend assez de place pour que
   chaque prestation ait sa propre bande bien détachée de la suivante, et la
   ligne atteint alors 44px de haut, la cible tactile de référence. */
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable th,
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable td {
  padding: 13px 8px;
}
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable .fp-tarifs-price {
  font-size: clamp(1rem, 4.4vw, 1.35rem);
}
/* Libellé de prestation : une ligne de tableau par prestation, le libellé à
   gauche et un prix par créneau. Coupure autorisée dans un mot très long
   (« Anniversaire », « Accompagnant ») : sans elle, un seul libellé pourrait
   imposer sa largeur minimale au tableau et redéclencher un défilement
   horizontal, ce que le client ne veut plus voir sur téléphone. */
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable .fp-tarifs-rowlabel {
  font-size: .92rem;
  overflow-wrap: break-word;
}
.fp-detail .fp-tarifs-matrix.fp-tarifs-daytable .fp-tarifs-day {
  padding-top: 14px;
  padding-bottom: 10px;
}
/* Chaque tableau est une petite carte à part entière : un filet clair et des
   angles arrondis suffisent à séparer les groupes de jours empilés.
   overflow-x en FILET DE SÉCURITÉ seulement : il ne se déclenche que dans une
   configuration extrême (un même groupe de jours portant trois créneaux ou
   plus sur un écran de 320px). Dans toutes les configurations réelles, rien ne
   défile, ce qui est bien la demande du client. */
.fp-detail .fp-tarifs-dayblock {
  overflow-x: auto;
  border: 1px solid color-mix(in srgb, var(--fp-white) 18%, transparent);
  border-radius: var(--fp-radius);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--fp-white) 45%, transparent) transparent;
}

/* Rendu generique "visual" du plugin (fp-tarifs-visual) : garde defensive,
   utilisee seulement si le shortcode est un jour rendu hors du cas pastille
   dedie ci-dessus (cf. rapport de livraison). */
.fp-detail .fp-tarifs-visual .fp-tarifs-pastille {
  background: var(--fp-paper);
  border-radius: var(--fp-radius-lg);
  box-shadow: var(--fp-shadow-lg);
  padding: 30px;
}
.fp-detail .fp-tarifs-pastille-title {
  color: var(--fp-primary);
  font-family: var(--fp-font-heading);
}
.fp-detail .fp-tarifs-pastille-body {
  color: var(--fp-ink);
}
.fp-detail .fp-tarifs-pastille-info {
  margin-top: 14px;
  color: var(--fp-ink-soft);
}

/* --------------------------------------------------------------------------
   VERSION « OFFRES » EN CONTEXTE ACTIVITÉ : RETIRÉE le 2026-09-05. La grille
   "offres" (tarifs Magic Kids) affichée sur une fiche d'activité n'emprunte
   plus la carte vert foncé (.fp-tarifs-body-table + .fp-tarifs-offres* +
   .fp-tarifs-jetons* + widget .fp-tk--activite en variante sombre) : elle
   rend désormais sa PROPRE section teal à part (.fp-kids-tarifs), identique
   à celle de la vitrine Magic Kids, rendue par fp_render_tarifs()
   (inc/sections.php) qui SORT de la fonction avant d'atteindre la carte vert
   foncé. Habillage dans assets/css/tarifs-kids.css, chargée sur les pages
   concernées (voir fun_planet_enqueue_per_template, functions.php). Plus
   aucun markup n'émet .fp-tarifs-offres* ni .fp-tarifs-jetons* (vérifié sur
   inc/, assets/js/ et le plugin, 2026-09-05) ; le plugin émet encore
   .fp-tk--activite sur la racine du widget, mais comme simple MARQUEUR du
   contexte (avec data-tk-activite), plus aucune règle ne la cible : les
   ~500 lignes de règles CSS qui habillaient tout cela ici ont été retirées.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   RELATED « Découvrez nos autres activités » : REFONTE CARTES IMMERSIVES
   (nouveau retour client : « le listing d'activités est immonde aussi,
   envisage d'autres cards bien animées », avec un modèle fourni : carte
   voyage image pleine, voile sombre en bas, titre + description + bouton).
   Carrousel horizontal conservé (flèches accessibles + comportement clavier
   inchangé, cf. tabindex sur la piste). Chaque carte devient une image
   PLEIN CADRE en couleurs (fini le cadre crème et le duotone) : voile teal
   foncé qui monte du bas, pastille numérotée et chip flèche en verre en
   haut, titre display blanc, courte description, bouton « Découvrir »
   blanc pleine largeur toujours visible. Apparition des cartes A L'ENTREE
   dans la fenêtre du carrousel (système has-inview / is-in-view piloté par
   main.js, cf. bloc dédié plus bas). Le fond de section troque les pattes
   pour le PLAN DU PARC en filigrane clair (assets/img/em-plan.svg), écho
   du fond des formules.
   -------------------------------------------------------------------------- */
.fp-detail .fp-related {
  padding: calc(var(--fp-section-y) + 54px) 0 calc(var(--fp-section-y) + 84px);
  position: relative;
  overflow: hidden;
}
/* Plan du parc en filigrane sur la moitié basse de la section (traits
   #7db8b4 clairs), fondu vers le haut : texture douce sous les cartes. */
.fp-detail .fp-related::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: url('../img/em-plan.svg');
  background-size: min(1200px, 140vw);
  background-position: center 115%;
  background-repeat: no-repeat;
  opacity: .32;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg, transparent 6%, #000 46%);
  mask-image: linear-gradient(180deg, transparent 6%, #000 46%);
}
/* Le modele n'a AUCUNE gouttiere laterale supplementaire sur cette section
   (--content-width 1300px resout a la meme largeur que .fp-wrap, mesure
   confirmee) : on neutralise le padding herite de .fp-wrap (main.css,
   var(--fp-gutter) = 40px de chaque cote) pour que le carrousel retrouve sa
   pleine largeur de contenu (3 cartes desktop bien cadrees au lieu de 2). */
.fp-detail .fp-related .fp-wrap {
  position: relative;
  z-index: 1;
  padding-left: 0;
  padding-right: 0;
}
/* Titre/intro/badge CENTRES (.fp-related-head-center). */
.fp-detail .fp-related-head-center {
  text-align: center;
  max-width: 720px;
  margin: 0 auto;
}
/* Le H2 herite un max-width en ch trop etroit (.fp-lead generique,
   main.css) : sur cette tete centree, le conteneur fait deja 720px, le
   titre doit pouvoir l'occuper en entier (mesure sur le modele : tient sur
   une seule ligne a cette largeur). */
.fp-detail .fp-related-head-center .fp-lead {
  max-width: none;
}
.fp-detail .fp-related-head-center .fp-section-sub {
  margin: 10px auto 0;
}
/* Piste + fleches sur les cotes (position absolute, milieu vertical). */
.fp-detail .fp-related-carousel {
  position: relative;
  margin-top: 40px;
}
.fp-detail .fp-related-arrow {
  position: absolute;
  top: 50%;
  z-index: 3;
  transform: translateY(-50%);
}
.fp-detail .fp-related-arrow.is-prev { left: -22px; }
.fp-detail .fp-related-arrow.is-next { right: -22px; }
/* Fleches rondes BLANCHES avec ombre (facon RP), chevron primary, hover qui
   bascule sur le fond primary (au lieu du vert fonce herite de
   .fp-carousel-arrow global). */
.fp-detail .fp-related-arrow .fp-carousel-arrow {
  background: var(--fp-white);
  color: var(--fp-primary);
  box-shadow: var(--fp-shadow-lg);
}
.fp-detail .fp-related-arrow .fp-carousel-arrow:hover {
  background: var(--fp-primary);
  color: var(--fp-white);
}
/* Gap genereux (retour client : « utilise du gap ») : 36px, formules de
   largeur de colonne calees dessus. PADDING VERTICAL sur la piste (bug
   remonte par le client : la piste est un conteneur de scroll, elle CLIPPE
   verticalement - le lift au survol et l'etat d'attente translateY des
   cartes se faisaient couper net, radius mange).
   RETOUR CLIENT (2026-09-06) : deux cartes pleines au centre (une seule sous
   720px, cf. les deux media queries plus bas), deux cartes de bord qui
   s'estompent vers le blanc du fond de section (mask-image ci-dessous),
   jamais coupees net au bord du conteneur. Le magnetisme carte par carte du
   defilement manuel est assure par main.js (pas par scroll-snap CSS, cf.
   scroll-snap-type ci-dessous) : glissement en douceur vers la position bien
   alignee une fois le geste termine, avec la MEME animation pilotee que les
   boutons. */
.fp-detail .fp-related-track {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  /* PLANCHER DE COLONNE (2026-09-10). La carte porte aspect-ratio 4 / 3.6 ET
     min-height 300px (plus bas dans cette feuille) : elle ne peut donc pas
     être plus étroite que 300 x 4 / 3.6, soit 333 px. Quand la piste lui
     calculait une colonne plus étroite, la carte débordait de sa colonne et
     MORDAIT sur la suivante : à 768 px de fenêtre la colonne tombait à 239 px
     et les deux cartes de tête se chevauchaient de 59 px, l'une par-dessus
     l'autre, avec les cartes de bord écrasées dessous. Le défaut n'était pas
     propre à la tablette, il commençait sous 1140 px environ, mais il ne
     devenait franchement visible qu'en dessous de 1024 px.

     max() rend ce chevauchement structurellement impossible : la colonne
     suit le calcul d'origine tant qu'il est plus large que la carte, et
     s'arrête à la largeur de la carte sinon. La piste montre alors moins de
     cartes à la fois, ce qui est le comportement attendu d'un carrousel, au
     lieu de les empiler. main.js compte les cartes pleines sur cette même
     géométrie (setupCarousels, activeCount) : les deux restent d'accord sans
     palier écrit en double. */
  --fp-related-carte-min: 333.34px;
  grid-auto-columns: max(var(--fp-related-carte-min), calc((100% - 108px) / 2.85));
  gap: 36px;
  padding: 18px 0 36px;
  overflow-x: auto;
  /* JAMAIS "smooth" : main.js pilote lui-meme chaque frame de scrollLeft
     (courbe cubique maison) - le mode natif "smooth" du navigateur, qui
     interprete CHAQUE ecriture comme une nouvelle demande de defilement
     anime sur sa propre duree, entrait en collision avec ces ecritures
     rapprochees (16ms) et empechait la piste d'avancer reellement. */
  scroll-behavior: auto;
  /* scroll-snap-type reste VOLONTAIREMENT desactive (jamais "x mandatory") :
     un essai a montre que le magnetisme natif du navigateur "corrige" toute
     position posee par script des qu'elle ne correspond pas exactement au
     centrage d'UNE SEULE carte - y compris sans aucun geste utilisateur -
     ce qui est incompatible avec une piste qui centre une PAIRE de cartes
     (desktop/tablette). Le magnetisme manuel est donc assure par main.js. */
  scroll-snap-type: none;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  text-align: left;
  /* Fondu TOTALEMENT transparent aux deux extremites (14% a 86%), pour que
     les cartes de bord se dissolvent dans le blanc de la section plutot que
     d'etre coupees net au bord du conteneur. var(--fp-ink) sert ici de
     couleur opaque du masque, jamais une couleur hexadecimale en dur. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, var(--fp-ink) 14%, var(--fp-ink) 86%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, var(--fp-ink) 14%, var(--fp-ink) 86%, transparent 100%);
}
.fp-detail .fp-related-track::-webkit-scrollbar { display: none; }
/* Carte immersive plein cadre : l'image est le fond, le contenu vit dessus,
   CENTRE verticalement (retour client), format moins haut. Fond
   secondary-dark de secours (le temps du chargement de l'image), coins
   arrondis larges, lift au survol. Plus de pastille numerotee : avec le
   defilement en boucle infinie (cartes clonees), un compteur mentirait. */
.fp-detail .fp-related .fp-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: 4 / 3.6;
  min-height: 300px;
  background: var(--fp-secondary-dark);
  border: none;
  border-radius: var(--fp-radius-lg);
  overflow: hidden;
  padding: 0;
  box-shadow: 0 18px 40px -22px color-mix(in srgb, var(--fp-secondary-dark) 80%, transparent);
  transition: transform .45s cubic-bezier(.22, .85, .3, 1), box-shadow .35s ease;
}
.fp-detail .fp-related .fp-card:hover {
  transform: translateY(-10px);
  box-shadow: 0 30px 54px -24px color-mix(in srgb, var(--fp-secondary-dark) 90%, transparent);
}
/* Cadre interieur lisere (blanc translucide) qui encadre la photo a
   quelques pixels du bord : la touche « soignee » de la carte ; il se
   resserre legerement au survol. */
.fp-detail .fp-related .fp-card::before {
  content: '';
  position: absolute;
  inset: 10px;
  z-index: 2;
  border: 1px solid color-mix(in srgb, var(--fp-white) 30%, transparent);
  border-radius: calc(var(--fp-radius-lg) - 8px);
  pointer-events: none;
  transition: inset .35s ease;
}
.fp-detail .fp-related .fp-card:hover::before {
  inset: 7px;
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-related .fp-card::before { transition: none; }
  .fp-detail .fp-related .fp-card:hover::before { inset: 10px; }
}
/* (La chip d'accroche en verre est abandonnee : l'accroche s'affiche
   desormais en petit texte sous le titre, cf. .fp-card-sub plus bas.) */
/* Chip fleche « ouvrir » en haut a droite : fleche droite pivotee vers le
   haut-droite, s'inverse en blanc plein au survol de la carte. */
.fp-detail .fp-related .fp-card-open {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fp-white) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--fp-white) 40%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: var(--fp-white);
  transform: rotate(-45deg);
  transition: background .3s ease, color .3s ease, transform .35s ease;
}
.fp-detail .fp-related .fp-card-open svg {
  width: 16px;
  height: 16px;
}
.fp-detail .fp-related .fp-card:hover .fp-card-open {
  background: var(--fp-white);
  color: var(--fp-secondary-dark);
  transform: rotate(-45deg) scale(1.12);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-related .fp-card-open { transition: none; }
  .fp-detail .fp-related .fp-card:hover .fp-card-open { transform: rotate(-45deg); }
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-related .fp-card { transition: none; }
  .fp-detail .fp-related .fp-card:hover { transform: none; }
}
/* CARTES ACTIVES SANS FLASH (retour client 2026-09-06) : plus
   d'IntersectionObserver (source du flash au rebouclage et de la 3e carte
   qui pouvait apparaitre en pleine opacite). main.js pose .has-inview sur la
   piste quand le systeme est actif, puis calcule GEOMETRIQUEMENT, a chaque
   frame d'un mouvement pilote comme au repos, quelles cartes tombent le plus
   pres du centre de la piste (is-in-view, pleines, toujours exactement 2, 1
   sous 720px) et lesquelles sont juste a cote (is-side, plus basses,
   reduites, attenuees, en train de se fondre dans le degrade blanc de la
   piste, cf. mask-image plus haut). Ce classement garantit qu'au plus N
   cartes sont jamais pleinement visibles en meme temps, y compris pendant un
   mouvement. Sans JS ou en mouvement reduit, la piste n'a pas .has-inview :
   toutes les cartes restent simplement visibles. */
.fp-detail .fp-related-track.has-inview .fp-card {
  opacity: .15;
  transform: translateY(26px) scale(.95);
}
.fp-detail .fp-related-track.has-inview .fp-card.is-in-view {
  opacity: 1;
  transform: none;
}
/* Cartes de bord : plus basses, legerement reduites, attenuees. */
.fp-detail .fp-related-track.has-inview .fp-card.is-side {
  opacity: .55;
  transform: translateY(28px) scale(.92);
}
/* Le lift au survol doit survivre a la regle is-in-view (plus specifique
   que le :hover generique de la carte). */
.fp-detail .fp-related-track.has-inview .fp-card.is-in-view:hover {
  transform: translateY(-10px);
}
/* Pendant un mouvement pilote (main.js), l'opacite/la position ci-dessus
   sont ecrites en ligne, image par image, a partir de la position REELLE de
   defilement. L'OPACITE reste INSTANTANEE (aucune transition sur cette
   propriete) : c'est ce qui garantit qu'au plus N cartes sont pleinement
   visibles en meme temps meme pendant le mouvement (une transition lissee
   ferait se chevaucher le fondu de la carte qui sort avec celui de la carte
   qui entre, recreant le flash d'origine). Seule la POSITION (translateY,
   scale) beneficie d'une courte transition, pour eviter un saut sec visible
   quand une carte change de palier (pleine/de bord/lointaine) : cela ne
   change rien a la garantie ci-dessus, qui ne porte que sur l'opacite. Au
   repos (classe retiree), les regles ci-dessus et le lift au survol
   reprennent normalement la main. */
.fp-detail .fp-related-track.is-animating .fp-card {
  transition: transform .12s linear;
}
/* Image PLEIN CADRE en couleurs (fini le duotone) : elle remplit toute la
   carte, zoom doux au survol (l'overflow hidden de la carte contient tout). */
.fp-detail .fp-related .fp-card-media {
  position: absolute;
  inset: 0;
  aspect-ratio: auto;
  border-radius: 0;
  overflow: hidden;
}
.fp-detail .fp-related .fp-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s ease;
}
.fp-detail .fp-related .fp-card:hover .fp-card-media img {
  transform: scale(1.07);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-related .fp-card-media img { transition: none; }
  .fp-detail .fp-related .fp-card:hover .fp-card-media img { transform: none; }
}
/* Voile teal fonce qui monte du bas : le contenu est aligne en bas de
   carte (retour client), le haut de la photo reste bien lisible. */
.fp-detail .fp-related .fp-card-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--fp-secondary-dark) 24%, transparent) 0%,
    transparent 26%,
    transparent 40%,
    color-mix(in srgb, var(--fp-secondary-dark) 70%, transparent) 72%,
    color-mix(in srgb, #001411 90%, transparent) 100%);
  pointer-events: none;
  transition: opacity .4s ease;
}
/* Placeholder "Bientot disponible !" : fond vert, illustration lynx chantier
   AVEC le texte "Bientot disponible ! / Ce contenu est en cours de creation."
   deja peint dans l'image (bientot-dispo.webp). QA : le markup (inc/sections.php)
   redessine ce meme texte en HTML par-dessus (fp-card-placeholder-title/-desc),
   ce qui cree un double texte superpose (image + calque HTML, tailles/polices
   differentes -> effet de contour dedouble). Le conteneur parent porte deja
   aria-hidden="true" (rien a l'accessibilite), donc on masque les 2 calques
   HTML : l'image reste seule source du texte, un seul rendu lisible. */
.fp-detail .fp-related .fp-card-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 20px;
  text-align: center;
  color: var(--fp-white);
  background-color: var(--fp-primary);
}
/* Fond em-topo (motif topographique en leger overlay), MEME fichier que le
   reste du theme (--fp-act-pattes, chemin RELATIF qui resout en local) : plus
   d'URL distante RParc en dur (corrige au passage, cf. rapport). */
.fp-detail .fp-related .fp-card-placeholder::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: var(--fp-act-pattes);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: .2;
  pointer-events: none;
}
.fp-detail .fp-related .fp-card-placeholder-title,
.fp-detail .fp-related .fp-card-placeholder-desc {
  display: none;
}
/* Corps : posé SUR l'image, au-dessus du voile, CENTRÉ verticalement.
   flex:0 0 auto obligatoire : le flex:1 hérité de la base .fp-card-body
   (main.css) étirait le corps sur toute la hauteur de carte et neutralisait
   le justify-content:center posé sur la carte. Padding latéral et vertical
   généreux (retour client : les flèches du carrousel passaient par-dessus
   le texte des cartes en bord de piste). */
.fp-detail .fp-related .fp-card-body {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 30px 34px;
}
/* Titre en BEBAS graisse native (retour client : plus de Thoge ici), grand
   et blanc sur le voile, ombré pour rester lisible sur toute photo. */
.fp-detail .fp-related .fp-card-title {
  display: block;
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: 2.2rem;
  line-height: .96;
  color: var(--fp-white);
  letter-spacing: .02em;
  /* Ombre PRONONCÉE (Marino, 2026-09-10, deuxième passage : « il se peut que
     le fond soit clair, il me faut une ombre un peu plus prononcée sur les
     titres et textes ») : trait net sous les lettres + halo large. Cette
     règle gagne sur celle de main.css (même ombre, moins spécifique). */
  text-shadow: 0 2px 4px color-mix(in srgb, var(--fp-dark) 85%, transparent), 0 6px 22px color-mix(in srgb, var(--fp-dark) 70%, transparent);
}
/* Petit texte descriptif sous le titre (meta fp_carte_accroche, repli
   extrait) : blanc adouci, 2 lignes maxi. */
.fp-detail .fp-related .fp-card-sub {
  color: color-mix(in srgb, var(--fp-white) 86%, transparent);
  font-size: .95rem;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Bouton « Découvrir » : DESIGN STANDARD des boutons du site (classes
   fp-btn fp-btn-light posées côté PHP : blanc, remplissage teal qui glisse,
   flèche qui se déplie), largeur AU CONTENU et format FIN (retour client :
   padding et texte réduits). Les propriétés typographiques de la BASE
   .fp-card-go (main.css : gras 700, .92rem, gap 6px) sont explicitement
   neutralisées ici - elles arrivaient APRES .fp-btn dans la cascade et
   rendaient le bouton différent des autres. Le lien étant la carte
   entière, tous les effets :hover du fp-btn commun sont répliqués sur le
   survol de la CARTE. */
.fp-detail .fp-related .fp-card-go {
  align-self: flex-start;
  margin-top: 12px;
  gap: 0;
  font-weight: 400;
  font-size: 1rem;
  padding: 12px 26px;
  color: var(--fp-primary);
}
.fp-detail .fp-related .fp-card:hover .fp-card-go {
  transform: translateY(-2px);
  box-shadow: var(--fp-shadow-lg);
  color: var(--fp-white);
}
.fp-detail .fp-related .fp-card:hover .fp-card-go::before {
  width: 100%;
}
.fp-detail .fp-related .fp-card:hover .fp-card-go.fp-btn:has(.fp-arr) {
  padding-right: 46px;
}
.fp-detail .fp-related .fp-card:hover .fp-card-go .fp-arr {
  width: 15px;
  opacity: 1;
  transform: translateX(0);
  margin-left: 9px;
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-related .fp-card:hover .fp-card-go { transform: none; }
}

/* --------------------------------------------------------------------------
   ATOUTS A ICONES : le RParc aligne 3 atouts sobres (icone + titre + courte
   description), fond blanc, cartes a peine marquees. On adoucit la carte par
   defaut du theme : moins de bordure, plus d'air, pastille d'icone douce.
   -------------------------------------------------------------------------- */
.fp-detail .fp-features {
  background: var(--fp-paper);
}
.fp-detail .fp-features-grid {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}
.fp-detail .fp-feature {
  border-color: color-mix(in srgb, var(--fp-line) 70%, transparent);
  border-radius: var(--fp-radius-sm);
  box-shadow: 0 8px 22px -18px color-mix(in srgb, var(--fp-ink) 50%, transparent);
}
.fp-detail .fp-feature-icon {
  width: 64px;
  height: 64px;
  background: color-mix(in srgb, var(--fp-primary) 10%, var(--fp-paper));
}

/* --------------------------------------------------------------------------
   FAQ : accordeon sobre du RParc, filets fins, question en gras, icone +/-.
   Le markup du theme (filet haut/bas, icone en croix) colle deja ; on affine
   l'espacement, la pastille d'icone et le survol.
   -------------------------------------------------------------------------- */
.fp-detail .fp-faq {
  background: var(--fp-paper);
}
.fp-detail .fp-faq-list {
  max-width: 860px;
}
.fp-detail .fp-faq-q {
  font-size: 1.1rem;
  padding: 20px 6px;
}
.fp-detail .fp-faq-q:hover {
  color: var(--fp-primary);
}
.fp-detail .fp-faq-icon {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fp-primary) 10%, var(--fp-paper));
}
.fp-detail .fp-faq-q[aria-expanded="true"] .fp-faq-icon {
  background: color-mix(in srgb, var(--fp-primary) 18%, var(--fp-paper));
}

/* --------------------------------------------------------------------------
   CTA FINAL (bloc de cloture « Prêt à jouer ? ») : bandeau image avec overlay
   sombre, renforce par rapport au socle (main.css) pour rester lisible sur
   les photos d'activite. Recette « detail » : reprise A L'IDENTIQUE par
   restaurant.css et zone-kids.css via la classe de corps commune .fp-detail
   (aucune declaration propre necessaire dans ces deux feuilles). Le padding
   supplementaire (+8px) est le meme que celui d'activites.css et
   restauration.css : une seule valeur de « respiration finale » pour tous
   les bandeaux de cloture un cran plus genereux que la section courante.
   -------------------------------------------------------------------------- */
.fp-detail .fp-cta-section {
  padding: calc(var(--fp-section-y) + 8px) 0;
}
.fp-detail .fp-cta-photo {
  opacity: 0.42;
}
.fp-detail .fp-cta-overlay {
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--fp-primary) 78%, transparent),
    color-mix(in srgb, var(--fp-primary-dark) 90%, transparent)
  );
}

/* --------------------------------------------------------------------------
   POPUP HORAIRES (.fp-horaires-popup, rendu par fp_horaires_popup, hook
   wp_footer, inc/template-tags.php) : REFONTE COMPLÈTE (retour client :
   « tu peux le modifier, j'aimerais un truc beaucoup plus compact et
   beaucoup plus sexy »). Le style par défaut vit dans main.css (hors
   périmètre de cet agent) : cette section le SURCHARGE entièrement, scopée
   au template activité - le popup n'est de toute façon jamais injecté
   ailleurs (garde PHP dans fp_horaires_popup). Boîte bien plus compacte
   (440px au lieu de 720px), bandeau dégradé teal en tête (icône + titre +
   badge de statut regroupés), onglets en pilules pleines au lieu du
   soulignement plat, entrée en scène (fondu + léger zoom) à chaque
   ouverture. Contrat JS
   INTACT : [data-fp-popup-open]/[data-fp-popup-close], .fp-popup-tab
   [data-tab]/.fp-popup-panel[data-panel], aria-modal, hidden, piège à focus
   sur .fp-horaires-popup-panel (main.js, hors périmètre, non modifié).

   RETOUCHES 2026-08 (quatre demandes du client, la fenêtre elle-même est
   gardée telle quelle) :
    1. la pastille « ouvert / fermé » reprend le visuel validé ailleurs. Elle
       n'est plus habillée ici : c'est le composant partagé .fp-horaires-status
       de main.css qui s'en charge, pour l'accueil, les points de restauration
       et cette fenêtre, en un seul endroit ;
    2. titre un peu plus grand, et sur deux lignes (ce que la fenêtre montre,
       puis de quelle activité il s'agit) ;
    3. les deux onglets se lisent comme un vrai sélecteur à deux positions :
       piste teintée VISIBLE (l'ancienne piste était en --fp-cream, un blanc
       à peine cassé, donc invisible sur un panneau blanc : rien ne disait que
       le second onglet était cliquable) et position choisie posée en relief
       sur une surface blanche ;
    4. libellés des onglets plus grands et surtout en graisse 400. Ils étaient
       en Bebas Neue 600 à 12,16 px : Bebas Neue n'est chargée qu'en 400, le
       navigateur fabriquait donc un faux gras qui épaissit les traits et ferme
       les contreformes. C'était bien la cause de l'illisibilité signalée.

   RETRAIT DE LA MASCOTTE (2026-09-03) : demande du client, plus aucune image
   à cet endroit, ni mascotte ni image d'attente (inc/mascottes-attente.php).
   La mascotte miniature qui pointait au-dessus du bandeau n'existe plus dans
   le DOM (inc/template-tags.php, fp_horaires_popup) : les règles qui la
   positionnaient sont retirées ci-dessous. Elle était en position absolue,
   purement décorative, sans participer à la mise en page du bandeau ni du
   corps : son retrait ne laisse donc aucune colonne ni aucun espace à
   récupérer, le titre, la pastille d'état, les onglets et les tableaux
   restent sur une seule colonne pleine largeur comme avant.
   -------------------------------------------------------------------------- */
.fp-detail .fp-horaires-popup-panel {
  width: min(440px, 92vw);
  max-height: 86vh;
  padding: 0;
  border-radius: var(--fp-radius-lg);
  overflow: hidden;
  box-shadow: var(--fp-shadow-strong);
  /* Colonne : le bandeau garde sa hauteur naturelle, le corps prend le reste
     et défile. Remplace une hauteur maximale calculée sur une hauteur de
     bandeau écrite en dur, qui devenait fausse dès que le titre changeait. */
  display: flex;
  flex-direction: column;
}
.fp-detail .fp-horaires-popup-overlay {
  backdrop-filter: blur(3px);
}
.fp-detail .fp-horaires-popup-close {
  top: 14px;
  right: 14px;
  z-index: 3;
  background: color-mix(in srgb, var(--fp-white) 90%, transparent);
}
/* Bandeau dégradé compact : icône + titre + badge de statut. L'icône se cale
   en haut, sur la ligne de titre : depuis que le bloc de texte compte trois
   lignes (titre, activité, pastille), un centrage vertical la laissait flotter
   toute seule au milieu du bandeau. */
.fp-detail .fp-horaires-popup-head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 26px 54px 22px 22px;
  background: linear-gradient(135deg, var(--fp-primary) 0%, var(--fp-secondary-dark) 100%);
  overflow: hidden;
}
.fp-detail .fp-horaires-popup-head::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--fp-act-pattes);
  background-size: cover;
  background-position: center;
  opacity: .14;
  pointer-events: none;
}
.fp-detail .fp-horaires-popup-head-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fp-white) 18%, transparent);
  color: var(--fp-white);
}
.fp-detail .fp-horaires-popup-head-icon svg {
  width: 22px;
  height: 22px;
}
.fp-detail .fp-horaires-popup-head-text {
  min-width: 0;
}
/* TITRE sur deux lignes dans un seul h2 (inc/template-tags.php) : « Horaires
   d'ouverture » dit ce que la fenêtre montre, la seconde ligne dit de quelle
   activité. Le nom accessible du dialogue (aria-labelledby) reste porté par
   ce h2 et vaut donc « Horaires d'ouverture <activité> ».
   Graisse 400 : Bebas Neue n'est chargée qu'en 400, la règle générale h1-h4
   de main.css demande 700 et faisait fabriquer un faux gras au navigateur. */
.fp-detail .fp-horaires-popup-title {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 0 0 10px;
  font-weight: 400;
  line-height: 1;
  color: var(--fp-white);
}
.fp-detail .fp-horaires-popup-title-quoi {
  font-size: clamp(1.2rem, 4.2vw, 1.7rem);
  letter-spacing: .01em;
}
/* Nom de l'activité : police de corps de texte, en capitales espacées, pour
   se distinguer de la ligne de titre sans jouer sur un gris. Blanc plein sur
   le bandeau teal : 4,85:1 au point le plus clair du dégradé (--fp-primary),
   au-dessus des 4,5:1 demandés à un texte courant. */
.fp-detail .fp-horaires-popup-title-ou {
  font-family: var(--fp-font-body);
  font-weight: 500;
  font-size: clamp(.8rem, 2.6vw, .9rem);
  letter-spacing: .08em;
  line-height: 1.2;
  text-transform: uppercase;
}
/* La pastille « ouvert / fermé » n'est plus habillée ici : composant partagé
   .fp-horaires-status / .fp-horaires-popup-status (main.css), identique à
   celui de l'accueil et des pages de restauration. Rien à surcharger, la
   pilule blanche ombrée se pose telle quelle sur le bandeau teal. */
/* Corps sous le bandeau : padding indépendant, défile si besoin. */
.fp-detail .fp-horaires-popup-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 18px 22px 22px;
  overflow-y: auto;
}
/* DEUX RÉGIMES (2026-09-05, Mur de grimpe et Mini-golf fluo) : bandeau
   d'explication pleine largeur, puis légende alignée à droite (retouche du
   même jour, au-dessus des pilules qui sont elles aussi à droite), puis des
   pilules Magic Kids / Activité seule à la place du simple horaire, sur les
   pages concernées seulement (fp_horaires_regimes_for). */
.fp-detail .fp-horaires-popup-regime {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 12px;
  padding: 10px 12px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--fp-accent) 16%, var(--fp-white));
  border: 1px solid color-mix(in srgb, var(--fp-accent) 55%, transparent);
  font-size: .84rem;
  line-height: 1.35;
  color: var(--fp-ink);
}
.fp-detail .fp-horaires-popup-regime-icon {
  flex: 0 0 auto;
  display: inline-flex;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  color: var(--fp-secondary);
}
.fp-detail .fp-horaires-popup-regime-icon svg {
  width: 18px;
  height: 18px;
}
.fp-detail .fp-horaires-popup-regime-texte {
  margin: 0;
}
.fp-detail .fp-horaires-popup-regime-texte a {
  color: var(--fp-secondary);
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* Légende à droite, au-dessus des pilules (elles aussi alignées à droite,
   décision Marino du 2026-09-05) : justify-content: flex-end. */
.fp-detail .fp-horaires-popup-legende {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px 14px;
  margin: 0 0 8px;
  font-size: .78rem;
  color: var(--fp-ink-soft);
}
.fp-detail .fp-horaires-popup-legende-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
/* Le libellé « Magic Kids » ressort en police de titre (retouche Marino du
   2026-09-05, une fois la pilule kids privée de son mot « Kids » visible : la
   légende reste le seul endroit où le régime est nommé en clair). Bebas Neue
   n'existe qu'en 400 : jamais de 700 ici, ce serait un faux gras. L'item
   « Activité seule » garde le style commun ci-dessus, rien à ajouter. */
.fp-detail .fp-horaires-popup-legende-item.is-kids {
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: .9rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--fp-secondary);
}
.fp-detail .fp-horaires-swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  background: var(--fp-primary);
}
.fp-detail .fp-horaires-swatch.is-seule {
  background: var(--fp-white);
  border: 2px solid var(--fp-primary);
  box-sizing: border-box;
}
/* Conteneur des deux pilules, à droite de la ligne (jour ou date). */
.fp-detail .fp-horaires-pills {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}
.fp-detail .fp-horaires-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--fp-pill);
  font-size: .8rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fp-detail .fp-horaires-pill.is-kids {
  background: var(--fp-primary);
  color: var(--fp-white);
}
.fp-detail .fp-horaires-pill.is-seule {
  background: var(--fp-white);
  color: var(--fp-secondary);
  border: 1.5px solid var(--fp-primary);
}
/* Sous 480px, .fp-horaires-pills passe déjà les pilules l'une sous l'autre
   (flex-wrap hérité ci-dessus) plutôt que de forcer une largeur trop étroite :
   la ligne garde align-items: center, déjà posé par .fp-horaires-popup-ligne
   (main.css), rien à surcharger ici. */
/* Sous 360px, une pilule « activité seule » à DEUX créneaux (par exemple
   « 09:00 - 10:00, 18:00 - 22:00 »), en white-space: nowrap, débordait de
   5px et se faisait rogner. Elle passe alors en pleine largeur de ligne
   (alignée à droite comme le reste), et l'espace entre pilules se resserre
   pour laisser toute la place au texte. */
@media (max-width: 360px) {
  .fp-detail .fp-horaires-pills { gap: 4px; }
  .fp-detail .fp-horaires-pill { flex: 1 1 100%; justify-content: flex-end; }
}
/* SÉLECTEUR À DEUX POSITIONS (retour client : « qu'on voie un peu plus que
   c'est un basculement, avec un fond défini, comme ça on voit qu'on peut
   cliquer sur Vacances et jours fériés aussi »).
   Seule la PISTE change vraiment : elle porte une teinte et un filet VISIBLES
   sur le panneau blanc, si bien que la position non choisie se lit comme un
   emplacement vide où l'on peut aller, et non comme un simple mot posé là.
   La position choisie garde le remplissage teal qu'elle avait, avec en plus un
   léger relief : l'état ne se lit donc pas que par la teinte, c'est aussi une
   surface pleine et détachée contre un emplacement plat et transparent.
   Pour les lecteurs d'écran, aria-selected reste posé par main.js, inchangé.
   CONTRASTES : position choisie (--fp-primary) contre la piste, 4,05:1, et
   libellé blanc dessus, 4,85:1 ; libellé de la position libre (--fp-secondary)
   sur la piste, 8,28:1. */
.fp-detail .fp-popup-tabs {
  gap: 4px;
  border-bottom: 0;
  margin-bottom: 14px;
  padding: 4px;
  background: color-mix(in srgb, var(--fp-primary) 14%, var(--fp-white));
  border: 1px solid color-mix(in srgb, var(--fp-primary) 38%, transparent);
  border-radius: var(--fp-pill);
}
/* 44 px de haut minimum : cible tactile confortable, y compris quand le
   libellé tient sur une seule ligne. */
.fp-detail .fp-popup-tab {
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  text-align: center;
  border-bottom: 0;
  border-radius: var(--fp-pill);
  padding: 8px 12px;
  /* Graisse 400 et non 600 : Bebas Neue n'existe qu'en 400, un 600 faisait
     fabriquer un faux gras. Taille remontée de .76rem à ~1rem, ce qui rend
     les libellés lisibles sans les épaissir. */
  font-weight: 400;
  font-size: clamp(.9rem, 3.2vw, 1.02rem);
  line-height: 1.15;
  letter-spacing: .02em;
  color: var(--fp-secondary);
  transition: background .25s ease, color .25s ease, box-shadow .25s ease;
}
/* Survol de la position libre : son emplacement s'éclaircit, signe qu'elle est
   cliquable. */
.fp-detail .fp-popup-tab:hover {
  background: color-mix(in srgb, var(--fp-white) 70%, transparent);
}
.fp-detail .fp-popup-tab.is-active {
  background: var(--fp-primary);
  color: var(--fp-white);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--fp-secondary-dark) 25%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-popup-tab { transition: none; }
}
.fp-detail .fp-horaires-popup-ligne {
  padding: 8px 2px;
  font-size: .92rem;
}
/* GROUPES PAR CAMPAGNE (Marino, 2026-09-10 : « affiche aussi le nom, avec un
   slider en 2 par 2 pour une période prolongée »). Le libellé de l'exception
   est désormais le nom de la campagne (fixup 145) : fp_horaires_popup()
   regroupe ses dates par campagne (fp_horaires_grouper_exceptions(),
   inc/template-tags.php, branche « régime unique » seulement) et enveloppe
   chaque groupe dans .fp-horaires-popup-groupe. .fp-horaires-popup-liste
   étant déjà display:flex/column (main.css), le groupe s'y empile sans
   réglage particulier ; seules l'entête, la liste imbriquée et la navigation
   ont besoin d'un habillage. */
.fp-detail .fp-horaires-popup-groupe:not([hidden]) ~ .fp-horaires-popup-groupe:not([hidden]) {
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--fp-line);
}
/* JOURS EN GRAISSE NORMALE ET TÊTE RESSERRÉE (Marino, 10.09.2026 : « que les
   jours ne soient plus en gras si le titre l'est, et moins d'espace entre un
   titre et ses jours liés »). Le nom de la campagne porte déjà le gras : deux
   niveaux en gras se disputaient l'oeil. Les dates redescendent à la graisse
   courante, et l'air entre la tête du groupe et sa première date se réduit. */
.fp-detail .fp-horaires-popup-groupe-tete {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 2px 4px 0;
}
.fp-detail .fp-horaires-popup-groupe .fp-horaires-popup-jour {
  font-weight: 400;
}
.fp-detail .fp-horaires-popup-groupe-tete + .fp-horaires-popup-ligne,
.fp-detail .fp-horaires-popup-groupe-dates > .fp-horaires-popup-ligne:first-child {
  padding-top: 4px;
}
.fp-detail .fp-horaires-popup-groupe-nom {
  font-weight: 700;
  color: var(--fp-ink);
}
.fp-detail .fp-horaires-popup-groupe-periode {
  color: var(--fp-ink-soft);
  font-size: .85rem;
}
/* Les dates du groupe reprennent .fp-horaires-popup-ligne telles quelles
   (main.css) : rien à redéfinir ici, seule la dernière ligne DE CHAQUE
   GROUPE perd son filet bas (:last-child, déjà porté par main.css, se
   résout maintenant par groupe imbriqué plutôt que sur la liste entière). */
.fp-detail .fp-horaires-popup-groupe-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 6px 4px 2px;
}
.fp-detail .fp-horaires-popup-groupe-nav[hidden] { display: none; }
.fp-detail .fp-horaires-popup-groupe-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--fp-primary) 40%, transparent);
  background: var(--fp-white);
  color: var(--fp-primary);
  font-size: .95rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color .2s ease, color .2s ease;
}
.fp-detail .fp-horaires-popup-groupe-arrow:hover:not(:disabled) {
  background: var(--fp-primary);
  color: var(--fp-white);
}
.fp-detail .fp-horaires-popup-groupe-arrow:disabled {
  opacity: .35;
  cursor: default;
}
.fp-detail .fp-horaires-popup-groupe-statut {
  min-width: 4.5em;
  text-align: center;
  color: var(--fp-ink-soft);
  font-size: .78rem;
  font-variant-numeric: tabular-nums;
}
/* Pas de défilement animé : la pagination bascule par [hidden], un
   changement instantané à toutes les préférences de mouvement. Seule la
   micro-transition de survol des flèches est coupée ici. */
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-horaires-popup-groupe-arrow { transition: none; }
}
/* Téléphone étroit : marges resserrées pour que le titre et les deux
   libellés d'onglets respirent (règles conservées telles quelles depuis le
   retrait de la mascotte du 2026-09-03 : elle était en position absolue et
   ne participait pas à ce calcul de marges). */
@media (max-width: 480px) {
  .fp-detail .fp-horaires-popup-head {
    gap: 12px;
    padding: 22px 52px 18px 16px;
  }
  .fp-detail .fp-horaires-popup-body {
    padding: 16px 16px 18px;
  }
  .fp-detail .fp-popup-tab {
    padding: 8px 8px;
  }
}
/* Entrée en scène à chaque ouverture : la boîte part de [hidden] (display:
   none), donc l'animation est rejouée à chaque fois que l'attribut est
   retiré (main.js, setupHorairesPopup, hors périmètre). */
@media (prefers-reduced-motion: no-preference) {
  .fp-detail .fp-horaires-popup-panel {
    animation: fp-popup-in .32s var(--fp-anim-ease) both;
  }
}
@keyframes fp-popup-in {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-horaires-popup-panel {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   Mobile <= 980px : colonnes qui s'empilent (intro, étapes), cartes stats et
   formules en 1 colonne, tarifs plus compacts. Breakpoint theme (980px) au
   lieu du 1024px source, mais valeurs H1 recopiees a l'identique (155px,
   stroke inchange 3.5px sur ce palier source).
   -------------------------------------------------------------------------- */
@media (max-width: 980px) {
  .fp-detail .fp-hero-detail .fp-hero-title {
    font-size: 155px;
  }
  /* Titre sur deux lignes ou plus (voir le bloc TITRE SUR DEUX LIGNES OU
     PLUS plus haut dans ce fichier) : même réduction à 80% sur ce palier. */
  .fp-detail .fp-hero-detail.is-multiligne .fp-hero-title {
    font-size: 124px; /* 155px x 0.8 */
  }
  /* Empile texte (badges compris) / scène (une seule colonne, ordre du DOM). */
  .fp-detail .fp-intro-grid-detail {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  /* Empilés, les badges repassent en rangée horizontale centrée, avec un peu
     moins d'air au-dessus qu'en desktop (44px). */
  .fp-detail .fp-intro-badges {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    max-width: none;
    gap: 10px 12px;
    margin-top: 32px;
  }
  /* La scène (arche + mascotte, ou galerie) reste raisonnablement étroite et
     centrée plutôt que de s'étirer d'un bord à l'autre du conteneur. */
  .fp-detail .fp-intro-figure {
    max-width: 440px;
    margin: 0 auto;
    width: 100%;
  }
  /* Décor de la galerie réduit : la figure est resserrée à 440px max, les
     tailles desktop (160px/96px) déborderaient trop largement. */
  .fp-detail .fp-intro-figure-galerie::before {
    width: 100px;
    height: 100px;
  }
  .fp-detail .fp-intro-figure-galerie::after {
    width: 64px;
    height: 64px;
  }
  .fp-detail .fp-etapes-plan {
    max-width: 100%;
  }
  /* RÈGLE RETIRÉE LE 2026-09-10. Elle resserrait la colonne à
     calc((100% - 108px) / 2.44) en visant « toujours deux cartes pleines au
     centre, avec des bords plus étroits qu'en desktop ». C'est précisément ce
     qui cassait : à 768 px la colonne tombait à 239 px alors que la carte ne
     peut pas mesurer moins de 333 px de large (aspect-ratio 4 / 3.6 plus
     min-height 300px), si bien que les deux cartes annoncées comme pleines se
     chevauchaient de 59 px. Le plancher de colonne posé sur la règle de base
     s'applique désormais ici aussi, et la piste montre une seule carte pleine
     tant que deux ne tiennent pas côte à côte. */
}

/* --------------------------------------------------------------------------
   PASSE TABLETTE (2026-09-10) : ALIGNEMENT DE L'INTRO UNE FOIS EMPILÉE.

   Le bloc ci-dessus empile l'intro sur une seule colonne dès 980 px, puis
   CENTRE les badges et la scène pendant que le sur-titre, le titre, le texte
   et le bouton restent alignés à gauche. Sur un téléphone, où la scène occupe
   presque toute la largeur, l'écart ne se voit pas. Sur une tablette il saute
   aux yeux : à 768 px la colonne fait 611 px et la scène 440 px, si bien que
   le regard descend en escalier, gauche, centre, gauche, centre.

   Badges et scène reprennent donc l'alignement du reste, et la scène toute la
   largeur de la colonne, comme la photo de la section Présentation de
   l'accueil traitée le même jour. Mesuré sans aucun débordement de page à
   768, 900 et 980 px : les deux décors de la galerie (anneau et disque flou,
   posés hors de la scène) tiennent dans la gouttière du conteneur.

   BORNÉ À 721 PX PAR LE BAS : le mobile est validé par la cliente et sera
   reprise dans une passe dédiée, rien de ce qui est écrit ici ne l'atteint.
   -------------------------------------------------------------------------- */
@media (min-width: 721px) and (max-width: 980px) {
  .fp-detail .fp-intro-badges { justify-content: flex-start; }
  .fp-detail .fp-intro-figure {
    max-width: none;
    margin-inline: 0;
  }
}

/* --------------------------------------------------------------------------
   Mobile <= 720px : hero plus compact, actions pleine largeur, galerie plus
   dense, étapes et formules en 1 colonne. Breakpoint theme (720px) au lieu
   du 767px source, valeurs H1 recopiees a l'identique (112px, stroke 2px).
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .fp-detail .fp-hero-detail {
    min-height: min(95vh, 640px);
    padding-top: calc(var(--fp-nav-h) + 24px);
    /* Espace bas CONSTANT (ancrage bas, voir la règle générale plus haut dans
       ce fichier) : aucune valeur mobile distincte n'existe dans l'historique
       git (le 90px desktop n'a jamais eu de contrepartie mobile explicite,
       seulement hérité en silence). CORRIGÉ à 110px (relecture Opus,
       2026-09-07) : la première valeur de repli (36px) plaçait l'accroche
       SOUS la barre d'actions flottante .fp-actbar (position fixe, bottom
       18px, cf. plus haut dans ce fichier) - recouvrement mesuré de 20 à
       40px sur iOS quand la barre d'adresse mobile est déployée. 110px
       laisse une marge au-dessus de .fp-actbar dans ce cas. */
    /* Portée de 110 à 150px le 2026-09-09, même motif que sur grand écran :
       le bloc titre était trop bas, et sur mobile la barre d'adresse mange
       déjà une partie de la hauteur annoncée. */
    padding-bottom: 150px;
    border-radius: 0 0 30px 30px;
  }
  /* TITRE COUPE SUR TELEPHONE ETROIT (banc d'essai, mesure a 320 px) :
     l'echelle du H1 s'arretait ici, 112 px etant appliques a TOUTES les
     largeurs sous 720 px. A 320 px la colonne de titre ne fait que 248 px,
     alors qu'a 112 px un mot comme « Spéléologie » (310 px) ou « Restaurant »
     (304 px) est plus large : le héro étant en overflow: hidden, la fin du mot
     disparaissait purement et simplement. Ce sont deux titres reels du
     catalogue, pas des cas d'ecole.
     La taille devient donc fluide sous 431 px (26vw), ou 112 px est atteint :
     au-dessus de ce seuil et jusqu'a 720 px, RIEN NE CHANGE par rapport a
     avant. A 320 px le titre tombe a 83 px et « Spéléologie » tient en 230 px,
     dans les 248 px disponibles. */
  .fp-detail .fp-hero-detail .fp-hero-title {
    font-size: clamp(64px, 26vw, 112px);
    -webkit-text-stroke: 2px var(--fp-white);
    text-stroke: 2px var(--fp-white);
  }
  /* Titre sur deux lignes ou plus, palier mobile : même réduction à 80% du
     clamp fluide ci-dessus (voir le bloc TITRE SUR DEUX LIGNES OU PLUS plus
     haut dans ce fichier). Sans cette règle, la valeur du palier 980px
     (124px) l'aurait emportée ici par simple ordre de cascade, plus grande
     que le clamp mobile normal : le titre aurait grossi au lieu de rétrécir. */
  .fp-detail .fp-hero-detail.is-multiligne .fp-hero-title {
    font-size: clamp(51px, 20.8vw, 90px);
  }
  /* Espacement de tête du héro : porté par le conteneur, comme en desktop
     (jamais par le sur-titre, qui est optionnel).
     RETOUR CLIENT (2026-08-17) : sur téléphone, l'ensemble sur-titre + titre +
     accroche descend UN PEU, pour respirer davantage sous la barre de
     navigation. 40px deviennent 64px, soit 88px d'air réellement visible sous
     la barre (24px de retrait du héro plus ces 64px) au lieu de 64px. DEPUIS
     l'ancrage bas (2026-09-07, voir la règle générale plus haut dans ce
     fichier), ce padding-top n'est plus la source visible de l'espacement du
     bloc (poussé par le bas, il ne remonte jusqu'ici que si le titre grandit
     sur plusieurs lignes) : il reste néanmoins comme garde haute, sans effet
     sur un titre d'une ligne. */
  .fp-detail .fp-hero-detail .fp-hero-inner {
    padding-top: 64px;
  }
  .fp-detail .fp-hero-detail .fp-hero-lead {
    max-width: 100%;
    font-size: 18px;
    line-height: 1.4;
  }
  /* Mobile : meme logique que desktop/tablette (largeur/typo des pilules
     geree par les breakpoints dedies 1024px/768px ci-dessus, alignes sur les
     seuils du JS source) ; les pilules restent cote a cote et utilisables,
     resserrees en douceur au condense, jamais de rupture de layout. */
  .fp-detail .fp-etapes-split,
  .fp-detail .fp-formules-grid {
    gap: 24px;
  }
  .fp-detail .fp-etapes-carousel {
    aspect-ratio: 16 / 11;
  }
  /* RETOUR CLIENT (2026-08-17) : sur téléphone, le carrousel de la section
     galerie + étapes est UN PEU PLUS HAUT. Largeur strictement inchangée (il
     occupe toujours toute la colonne) : seul le rapport change, 16/11 (0.69 x
     la largeur) devient 5/4 (0.80 x la largeur), soit environ 16 % de hauteur
     en plus. Réglage scopé à la section fusionnée des pages d'activité : le
     modèle restaurant réutilise le même composant photo (.fp-carte-galerie)
     et garde, lui, son rapport actuel. */
  .fp-detail .fp-etapes-fusion .fp-etapes-carousel {
    aspect-ratio: 5 / 4;
  }
  /* Le bouton « Voir la galerie complète » est posé en absolu à bottom:-22px :
     il déborde donc de 22px SOUS la colonne du carrousel. Une fois les colonnes
     empilées, il ne restait plus que 2px d'air entre ce bouton et le titre de
     la colonne suivante (« Comment lancer ta partie ») : 24px d'écart entre
     colonnes moins les 22px de débord. On rend ces 22px à la colonne, ce qui
     porte l'air réellement visible sous le bouton à 28px (24 + 26 - 22), donc
     au-dessus des 24px minimum demandés. */
  .fp-detail .fp-etapes-fusion .fp-etapes-carousel-col {
    margin-bottom: 26px;
  }
  .fp-detail .fp-galerie-slide {
    height: clamp(240px, 60vw, 360px);
  }
  /* Mobile (<=720px) : UNE seule carte pleine au centre, deux bords qui se
     fondent dans le blanc de chaque cote (mask-image, cf. base).

     MÊME PLANCHER QU'EN TABLETTE (2026-09-10). Le calcul seul donnait 174 px
     de colonne sur un téléphone de 390 px, pour une carte qui ne peut pas
     descendre sous 333 px (aspect-ratio 4 / 3.6 plus min-height 300px) : la
     carte débordait de sa colonne et les voisines se chevauchaient de 110 px,
     plus encore que sur tablette. La carte occupe désormais environ 85 pour
     cent de la largeur, proportion habituelle d'un carrousel sur téléphone,
     et les deux bords restent devinables sur les côtés. */
  .fp-detail .fp-related-track {
    grid-auto-columns: max(var(--fp-related-carte-min), calc((100% - 72px) / 1.6));
  }
  .fp-detail .fp-related-arrow.is-prev { left: 4px; }
  .fp-detail .fp-related-arrow.is-next { right: 4px; }
  /* TÊTES DE SECTION UN PEU PLUS GRANDES SUR TÉLÉPHONE (retour client du
     2026-08-17), pour « Découvrez nos formules » et « Tarif · <activité> ».
     Les deux sont un h2.fp-lead, dont l'échelle générale (main.css, clamp
     1.7rem / 3vw / 2.6rem) reste bloquée sur son plancher de 27px jusqu'à
     ~907px de large : sur téléphone, elle ne grandit donc jamais. On la
     relance ici entre 31px et 34px pour .fp-tarifs (inchangé, cette section
     est hors périmètre du +15% ci-dessous), et à une valeur propre pour
     .fp-formules (voir juste en dessous : +15% s'applique à TOUS les
     paliers, mobile compris, donc cette valeur historique est elle-même
     recalculée x1.15 plutôt que laissée telle quelle). */
  .fp-detail .fp-formules .fp-lead {
    font-size: clamp(2.2425rem, 9.2vw, 2.4725rem);
  }
  .fp-detail .fp-tarifs .fp-lead {
    font-size: clamp(1.95rem, 8vw, 2.15rem);
  }
  /* TITRE DE LA CARTE VERT FONCÉ (type « table »), PALIER MOBILE : le clamp
     desktop (plus haut dans ce fichier, ramené de 3x à 2x le 2026-09-07, puis
     à 1,5x le 2026-09-10) reste figé sur son plancher sous ~907px, alors que
     la largeur utile de la carte n'est plus que 322px à 390px (padding
     mobile de .fp-tarifs-body ci-dessous). Un titre de 22 caractères type
     « TARIFS DU SHUFFLEBOARD » coupait un mot en plein milieu avec le seul
     clamp desktop à 2x. Palier dédié, RESSERRÉ le 2026-09-10 dans les mêmes
     proportions que le titre général (facteur × 0.75 : 1.95rem/12vw/3.225rem,
     repris de l'ancien 2.6rem/16vw/4.3rem) : une réduction uniforme ne peut
     que réduire encore la largeur nécessaire, jamais la faire remonter au
     seuil de coupure déjà validé (harnais Playwright, mot le plus long). */
  .fp-detail .fp-tarifs-body-title {
    font-size: clamp(1.95rem, 12vw, 3.225rem);
  }
  /* EN-TÊTE DE CARTE, PALIER MOBILE (Marino, 2026-09-07) : le bouton quitte la
     ligne du titre et repasse EN DESSOUS, pleine largeur (le fp-btn commun
     est en inline-flex, cf. main.css : width 100% + justify-content:center
     l'étire sans changer sa forme). */
  .fp-detail .fp-tarifs-body-head {
    flex-direction: column;
    align-items: stretch;
  }
  .fp-detail .fp-tarifs-body-head-action {
    width: 100%;
  }
  .fp-detail .fp-tarifs-body-head-action .fp-btn {
    width: 100%;
    justify-content: center;
  }
  /* LA VIDÉO DE FOND S'AFFICHE SUR TÉLÉPHONE (2026-09-10 au soir).
     CAUSE RÉELLE du défaut « je ne vois toujours pas les vidéos sur mobile »,
     signalé plusieurs fois par Marino : une règle posée ici masquait
     .fp-tarifs-fond-video sous 720px au nom de WCAG 2.2.2 (une vidéo qui
     démarre seule et dure plus de cinq secondes doit offrir un moyen de
     l'arrêter). Le 2026-09-09, le JS a été autorisé à lancer la vidéo sur
     téléphone, mais cette règle n'a jamais été levée : la vidéo se
     téléchargeait et jouait bel et bien, invisible. Le format n'y était pour
     rien, et le bouton « Voir en grand » ne pouvait pas marcher non plus,
     le plein écran étant refusé à un élément non affiché.
     Le motif d'accessibilité, lui, reste traité, et mieux qu'en masquant :
     un bouton pause/reprise accompagne désormais la vidéo (voir
     .fp-tarifs-pause plus bas et brancherPause() dans main.js), en plus du
     masquage sous prefers-reduced-motion qui, lui, est conservé. */
  /* CARTE DES TARIFS ÉLARGIE SUR TÉLÉPHONE (retour client du 2026-08-17 : la
     carte est trop étroite, ses marges latérales mangent la place).
     Trois retraits se cumulaient avant d'arriver au tableau : la gouttière du
     conteneur (5vw de chaque côté), son retrait interne (20px) et le retrait
     de la carte (20px), soit une quarantaine de pixels perdus de chaque côté
     sur un écran de 390px. On ramène le bord de la carte à une vingtaine de
     pixels du bord de l'écran, ce qui rend environ 50px de largeur utile aux
     tableaux, soit un cinquième de plus.
     Section SEULE concernée : les autres gardent le rythme habituel du site. */
  .fp-detail .fp-tarifs {
    --fp-wrap: min(1500px, 96vw);
    padding: var(--fp-section-y-sm) 0;
  }
  /* Support de lisibilité sans carte de tarifs (voir plus haut) : padding
     vertical propre ramené à une valeur plus sobre sur téléphone. */
  .fp-detail .fp-tarifs.fp-tarifs-nu {
    padding-top: 80px;
    padding-bottom: 80px;
  }
  .fp-detail .fp-tarifs .fp-wrap {
    padding: 0 12px;
  }
  /* La carte (fond/padding) ne s'applique qu'au fallback tableau : le cas
     pastille est deja transparent (regle :has() desktop, pas de carte a
     compacter). La pastille elle-meme est fluide (min(280px, 70vw)),
     aucune valeur fixe mobile requise. */
  .fp-detail .fp-tarifs-body {
    padding: 30px 14px;
  }
  /* Bleed du scroll horizontal de la matrice jusqu'aux bords de la carte
     (memes 14px que le padding mobile de .fp-tarifs-body juste au-dessus) :
     evite une double marge qui grignoterait la largeur utile du scroll. */
  .fp-detail .fp-tarifs-matrix-wrap {
    margin: 0 -14px;
    padding: 0 14px;
  }
  /* Matrice a beaucoup de colonnes : on resserre les cellules pour reduire la
     course de defilement, sans jamais rogner la taille des noms de jours (le
     clamp les tient a 1.15rem minimum) ni la colonne collante des libelles.
     Hauteur resserree d'un cran de plus le 2026-09-10 (Marino), meme logique
     que le palier desktop plus haut. */
  .fp-detail .fp-tarifs-matrix th,
  .fp-detail .fp-tarifs-matrix td {
    padding: 10px 10px;
  }
  .fp-detail .fp-tarifs-matrix .fp-tarifs-day {
    padding-top: 11px;
    padding-bottom: 10px;
  }
  /* TARIF UNIQUE SUR TÉLÉPHONE : l'ellipse doit envelopper TOUT le bloc, prix
     et sous-texte compris. La hauteur en pourcentage (105 %, même débord de
     2.5 % en haut et en bas) est DEPUIS le 2026-09-10 la règle de base,
     partagée avec le poste de travail (voir le long commentaire au-dessus de
     .fp-tarif-solo-ring, plus haut dans ce fichier) : elle n'a donc plus
     besoin d'être répétée ici. Seul reste propre au téléphone le petit
     ajustement suivant.
     TIRÉ DE 7 PX VERS LE HAUT EN PLUS (retour client du 2026-08-20) : l'arc
     supérieur coupait encore le prix, alors que la description gardait de la
     marge en dessous ; l'anneau remonte donc de « six à huit pixels »
     demandés, EN PLUS du débord de base de 2.5 %. Réservé au téléphone : le
     poste de travail garde le débord de base tel quel. */
  .fp-detail .fp-tarif-solo-ring {
    top: calc(-2.5% - 7px);
  }
}

/* ==========================================================================
   PASSE TABLETTE (2026-08-24) : bande 721 px à 1024 px, et rien d'autre.

   Toute règle de ce bloc est bornée DES DEUX CÔTÉS. Sous 721 px, c'est à dire
   sur toute la plage validée par la cliente, aucune de ces déclarations n'est
   évaluée ; au-dessus de 1024 px non plus, l'ordinateur reste tel quel. Ce
   bloc n'existe que pour l'entre-deux, là où les blocs mobiles ont cessé de
   s'appliquer et où la mise en page d'ordinateur n'est pas encore à l'aise.
   ========================================================================== */

/* CARTES DE FORMULE : DEUX COLONNES DÈS 721 px.

   Défaut mesuré au banc : .fp-formules-grid est en
   repeat(auto-fit, minmax(290px, 1fr)) avec 34 px de gouttière. Sur une
   tablette de 768 px de large (l'iPad en portrait, la largeur de tablette la
   plus répandue), la colonne utile mesure 611 px : deux pistes y feraient
   288,5 px, soit UN PIXEL ET DEMI de moins que le plancher de 290 px. La
   grille retombe donc à une seule colonne et chaque carte de formule s'étire
   sur 611 px, alors qu'elle n'en fait que 335 sur un poste de travail : une
   carte de formule plus large sur tablette que sur ordinateur, c'est le
   symptôme, pas une intention.

   À 810 px la même grille passe d'elle-même à deux colonnes : la mise en page
   à deux cartes de front est donc DÉJÀ celle du site dans cette bande, elle
   ne fait que rater les quelques dizaines de pixels du bas de la plage. On
   pose les deux colonnes explicitement de 721 à 1024 px, ce qui ne change
   rien à partir de 810 px (la grille y était déjà à deux) et rétablit la
   cohérence en dessous. À 721 px chaque carte mesure environ 268 px, soit à
   peine moins que les 311 px qu'elle occupe sur un téléphone de 390 px. */
@media (min-width: 721px) and (max-width: 1024px) {
  .fp-detail .fp-formules-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --------------------------------------------------------------------------
   PASSE TABLETTE (2026-09-10) : MARGES INTERNES DES CARTES DE FORMULE.

   Les deux colonnes posées juste au-dessus donnent des cartes de 289 px à
   768 px de fenêtre. Or la carte porte 28 px de marge interne et son corps
   .fp-formule-inner 26 px de plus, soit 108 px mangés des deux côtés, 37 pour
   cent de la carte : la description tombe à 181 px, environ vingt-cinq signes
   par ligne, et s'étire sur quatre à cinq lignes. Le défaut est sur les
   VINGT ET UNE fiches d'activité à la fois, c'est le plus répandu de la
   passe.

   Les deux marges sont resserrées et la gouttière de la grille avec elles :
   la description repasse à 226 px sur trois lignes, la carte perd 79 px de
   hauteur. Le dessin ne change pas, l'image de tête et la pastille d'icône
   gardent leur place à cheval sur le bord.

   Borné à 980 px par le haut (au-delà, les colonnes dépassent 380 px et le
   texte respire de lui-même) et à 721 px par le bas (sur téléphone la grille
   est sur une seule colonne, le texte y a déjà toute la largeur).
   -------------------------------------------------------------------------- */
@media (min-width: 721px) and (max-width: 980px) {
  .fp-detail .fp-formules-grid { gap: 28px 24px; }
  .fp-detail .fp-formule { padding: 22px 16px; }
  .fp-detail .fp-formule-inner { padding: 40px 18px 22px; }
}

/* NOTE, pour la prochaine passe : les liens du fil d'Ariane mesurent bien
   25 px de haut au banc, mais leur cible tactile est DÉJÀ portée à 44 px par
   un calque transparent (.fp-detail .fp-breadcrumb-link::after, plus haut dans
   ce fichier), à toutes les largeurs. Rien à corriger ici : c'est la mesure de
   la boîte du lien qui est trompeuse, pas la zone réellement atteignable. */

/* --------------------------------------------------------------------------
   NOTE DE CHANTIER « À DISCUTER EN ENTRETIEN MARDI » (Marino, 2026-09-07) :
   posée par fp_render_intro_detail() sur les fiches d'activité, tant que le
   site est fermé au public seulement. Un cadre ORANGE en traitillés entoure le
   titre ET le texte de l'intro (le bloc que la cliente barre), l'étiquette à
   cheval sur son bord haut. Volontairement HORS charte (--fp-chantier, seul
   usage autorisé de l'orange) : ce n'est pas un élément de design, c'est une
   note destinée à la direction du parc.
   -------------------------------------------------------------------------- */
.fp-detail .fp-intro-note-zone {
  position: relative;
  display: inline-block;
  max-width: 100%;
  margin: 12px 0 18px -16px;
  padding: 22px 16px 4px;
  border: 2px dashed var(--fp-chantier);
  border-radius: 16px;
}
.fp-detail .fp-intro-note-zone .fp-intro-title {
  margin-bottom: 18px;
}
.fp-detail .fp-intro-note-entretien {
  position: absolute;
  top: 0;
  left: 14px;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--fp-chantier);
  color: var(--fp-white);
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: .95rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
}
.fp-detail .fp-intro-note-entretien::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--fp-white);
}

/* NOTE DE CHANTIER DE LA SECTION TARIFS, fiche Bowling seulement (Marino,
   2026-09-07) : MÊME pilule que l'étiquette de l'intro (fond orange plein,
   texte blanc, point), en haut à gauche de la section, assez large pour
   tenir sur deux lignes, trois au plus. Même registre hors charte
   (--fp-chantier), posée par fp_render_tarifs() tant que le site est fermé au
   public. Au-dessus du média de fond et de son voile (z-index). */
.fp-detail .fp-tarifs-note-entretien {
  position: absolute;
  top: 18px;
  left: 18px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: min(44ch, calc(100% - 36px));
  margin: 0;
  padding: 7px 14px;
  border-radius: 18px;
  background: var(--fp-chantier);
  color: var(--fp-white);
  font-family: var(--fp-font-heading);
  font-weight: 400;
  font-size: .95rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1.2;
}
.fp-detail .fp-tarifs-note-entretien::before {
  content: '';
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--fp-white);
}

/* --------------------------------------------------------------------------
   BOUTON DE SON DE LA VIDÉO DE FOND (2026-09-09, Marino)
   --------------------------------------------------------------------------
   La vidéo démarre muette, c'est la seule façon qu'un navigateur la laisse se
   lancer seule. Ce bouton permet de l'allumer si on le souhaite.

   Il arrive avec l'attribut hidden et n'est révélé que par setupVideosFond()
   quand la vidéo est réellement lancée : sans JavaScript, sur mobile, en
   mouvement réduit ou en économie de données, aucune vidéo ne démarre et le
   bouton n'apparaît donc jamais.

   Verre dépoli : voile blanc très léger plus flou d'arrière-plan, sur le même
   registre que la carte des tarifs. Les navigateurs sans backdrop-filter
   retombent sur le seul voile, qui suffit à détacher le bouton du média.
   -------------------------------------------------------------------------- */
/* CURSEUR ROND « SON » (setupVideosFond > brancherCurseurSon, main.js) : un
   disque qui suit le pointeur sur le fond de la section quand une vidéo joue.
   Posé par le script, positionné par transform depuis le coin haut-gauche de
   la section puis recentré par la marge négative, jamais de pointer-events :
   c'est la section qui reçoit le clic. Le curseur système s'efface sur le
   fond pendant qu'il est visible (has-curseur-son) et revient sur le
   contenu. Sous mouvement réduit, il apparait sans transition. */
.fp-detail .fp-tarifs-curseur {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  width: 96px;
  height: 96px;
  margin: -48px 0 0 -48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 10px;
  background: color-mix(in srgb, var(--fp-secondary) 88%, transparent);
  color: var(--fp-white);
  font-family: var(--fp-font-body);
  font-size: .68rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: .06em;
  text-transform: uppercase;
  box-shadow: var(--fp-shadow-lg);
  opacity: 0;
  scale: .6;
  pointer-events: none;
  will-change: transform;
  transition: opacity .18s ease, scale .18s ease;
}
.fp-detail .fp-tarifs-curseur.is-visible { opacity: 1; scale: 1; }
.fp-detail .fp-tarifs-curseur.is-actif { background: color-mix(in srgb, var(--fp-primary) 92%, transparent); }
.fp-detail .fp-tarifs.has-curseur-son { cursor: none; }
.fp-detail .fp-tarifs.has-curseur-son .fp-tarifs-body,
.fp-detail .fp-tarifs.has-curseur-son a,
.fp-detail .fp-tarifs.has-curseur-son button { cursor: auto; }
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-tarifs-curseur { transition: none; }
}
.fp-detail .fp-tarifs-son {
  position: absolute;
  right: 22px;
  bottom: 22px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--fp-white) 38%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--fp-white) 16%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  color: var(--fp-white);
  cursor: pointer;
  box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--fp-dark) 90%, transparent);
  transition: background .25s ease, transform .25s var(--fp-anim-ease), border-color .25s ease;
}
.fp-detail .fp-tarifs-son:hover,
.fp-detail .fp-tarifs-son:focus-visible {
  background: color-mix(in srgb, var(--fp-white) 30%, transparent);
  border-color: color-mix(in srgb, var(--fp-white) 60%, transparent);
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-tarifs-son { transition: none; }
  .fp-detail .fp-tarifs-son:hover,
  .fp-detail .fp-tarifs-son:focus-visible { transform: none; }
}
.fp-detail .fp-tarifs-son svg {
  width: 20px;
  height: 20px;
  display: block;
}
/* Une seule des deux icônes à la fois : haut-parleur barré au repos,
   haut-parleur et ondes quand le son est allumé. */
/* BOUTON PAUSE / REPRISE DE LA VIDÉO DE FOND (2026-09-10 au soir). Il remplace
   le masquage de la vidéo sous 720px comme réponse à WCAG 2.2.2 : le visiteur
   dispose d'un vrai moyen d'arrêter le mouvement, sur tous les écrans. Même
   dessin que le bouton de son, posé à GAUCHE pour ne jamais se disputer le coin
   avec lui ni avec « Voir en grand ». Révélé par le script en même temps que le
   son, donc seulement quand la vidéo joue réellement. */
.fp-detail .fp-tarifs-pause {
  position: absolute;
  left: 22px;
  bottom: 22px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--fp-white) 38%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--fp-white) 16%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  color: var(--fp-white);
  cursor: pointer;
  box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--fp-dark) 90%, transparent);
}
.fp-detail .fp-tarifs-pause:hover,
.fp-detail .fp-tarifs-pause:focus-visible {
  background: color-mix(in srgb, var(--fp-white) 26%, transparent);
}
/* Deux barres (en lecture) qui deviennent un triangle (en pause) : dessiné en
   CSS, aucun glyphe, aucune icône à charger. */
.fp-detail .fp-tarifs-pause-ic {
  display: block;
  width: 14px;
  height: 14px;
  border-left: 4px solid currentColor;
  border-right: 4px solid currentColor;
}
.fp-detail .fp-tarifs-pause.is-en-pause .fp-tarifs-pause-ic {
  width: 0;
  height: 0;
  border-left: 13px solid currentColor;
  border-right: 0;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  margin-left: 4px;
}
.fp-detail .fp-tarifs-son-ic { display: inline-flex; }
.fp-detail .fp-tarifs-son .fp-tarifs-son-ic--actif { display: none; }
.fp-detail .fp-tarifs-son.is-actif .fp-tarifs-son-ic--coupe { display: none; }
.fp-detail .fp-tarifs-son.is-actif .fp-tarifs-son-ic--actif { display: inline-flex; }
/* Le son allumé se signale aussi par la couleur, pas seulement par le glyphe :
   deux haut-parleurs se ressemblent trop au premier coup d'oeil. */
.fp-detail .fp-tarifs-son.is-actif {
  background: color-mix(in srgb, var(--fp-primary) 72%, transparent);
  border-color: color-mix(in srgb, var(--fp-white) 55%, transparent);
}
/* La vidéo se lance aussi sur mobile depuis le 2026-09-09 : le bouton reste
   donc présent, simplement un peu plus compact et un peu moins écarté du
   bord, l'espace y étant compté. */
@media (max-width: 720px) {
  .fp-detail .fp-tarifs-son {
    right: 14px;
    bottom: 14px;
    width: 40px;
    height: 40px;
  }
  .fp-detail .fp-tarifs-son svg { width: 18px; height: 18px; }
}

/* ==========================================================================
   PASSE MOBILE DES FICHES D'ACTIVITÉ (Marino, 2026-09-10, dictée fiche par
   fiche). Tout est borné sous 720px, sauf mention. Le bureau et la tablette
   ne bougent pas.
   ========================================================================== */
@media (max-width: 720px) {
  /* 1. HÉRO : les textes ajoutés par la cliente sont un peu longs et, en
     blanc sur une photo claire, passent mal. Corps réduit de 18 à 16px, une
     ombre portée sous le texte, et le voile de la bannière s'assombrit vers
     le bas (là où le texte vit) : « soit une ombre, soit l'overlay en bas,
     soit un peu des deux ». Le titre et la pilule ne changent pas. */
  .fp-detail .fp-hero-detail .fp-hero-lead {
    font-size: 16px;
    line-height: 1.45;
    text-shadow: 0 1px 3px color-mix(in srgb, var(--fp-dark) 70%, transparent), 0 4px 18px color-mix(in srgb, var(--fp-dark) 55%, transparent);
  }
  .fp-detail .fp-hero-detail .fp-hero-overlay {
    background: linear-gradient(
      180deg,
      var(--fp-primary) 0%,
      color-mix(in srgb, var(--fp-ink) 72%, transparent) 34%,
      color-mix(in srgb, var(--fp-ink) 72%, transparent) 62%,
      color-mix(in srgb, var(--fp-dark) 92%, transparent) 100%
    );
    opacity: .58;
  }

  /* 2. SECTION APRÈS LE HÉRO TOUT CENTRÉE : fil d'Ariane, titre, séparateur,
     puces. Le texte du paragraphe garde son alignement, seule la puce est
     centrée comme demandé. */
  .fp-detail .fp-breadcrumb { justify-content: center; text-align: center; }
  .fp-detail .fp-intro-title { text-align: center; margin-left: auto; margin-right: auto; }
  .fp-detail .fp-intro-title::after { margin-left: auto; margin-right: auto; }
  .fp-detail .fp-intro-badges { justify-content: center; }
  .fp-detail .fp-intro-actions,
  .fp-detail .fp-intro-col > .fp-btn { justify-content: center; }
  .fp-detail .fp-intro-col { align-items: center; text-align: center; }

  /* Les puces flottent doucement (« sur PC elles ne bougent qu'au survol, là
     on peut se permettre de les faire flotter »), en décalé l'une de l'autre.
     Coupé sous prefers-reduced-motion en fin de bloc. */
  .fp-detail .fp-intro-badge {
    animation: fp-intro-badge-flotte 5.2s ease-in-out infinite;
  }
  .fp-detail .fp-intro-badge:nth-child(2) { animation-delay: -1.7s; }
  .fp-detail .fp-intro-badge:nth-child(3) { animation-delay: -3.4s; }

  /* 3. GALERIE PLUS GRANDE (« un peu plus haute, un peu plus large, on a du
     mal à voir les images ») : elle passe de 440px plafonnés à toute la
     largeur de la colonne, cadre 4/3. Les deux cercles décoratifs suivent :
     l'anneau remonte et se cale sur le coin haut droit, le disque descend
     sur le coin bas gauche, pour rester visibles à côté d'une scène qui
     occupe désormais toute la largeur. */
  .fp-detail .fp-intro-figure { max-width: none; width: 100%; margin: 0; }
  .fp-detail .fp-intro-figure-galerie::before { top: -9%; right: -6%; width: 110px; height: 110px; }
  .fp-detail .fp-intro-figure-galerie::after { bottom: -7%; left: -5%; width: 72px; height: 72px; }

  /* 4. CARROUSEL « AUTRES ACTIVITÉS » : plus de fondu blanc sur les bords
     (« sur mobile tu peux complètement l'enlever »), et les flèches tirées
     aux extrémités pour dégager le texte de la carte centrale. */
  .fp-detail .fp-related-track {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .fp-detail .fp-related-arrow.is-prev { left: -6px; }
  .fp-detail .fp-related-arrow.is-next { right: -6px; }
  /* Piste EN PLEINE LARGEUR D'ÉCRAN (Marino, soir du 2026-09-10 : « le
     conteneur vient tout couper à gauche et à droite ; on devrait avoir un
     conteneur qui fait toute la largeur, comme ça les cartes sortent de
     l'écran au lieu d'être coupées par une bordure »). Même technique que le
     slider des formules ci-dessous, et la même raison. */
  .fp-detail .fp-related-track {
    width: 100vw;
    max-width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding-inline: var(--fp-gutter-mobile, 18px);
  }

  /* 6. GALERIE DE L'INTRO : plus grande, et chevrons aux extrémités de l'écran
     (Marino, soir du 2026-09-10 : « autorise quelque chose d'un peu plus large
     et un peu plus haut qu'on puisse vraiment plus facilement interagir ; les
     petits chevrons, décale-les un peu plus vers les extrémités »). Le cadre
     passe de 16/9 à 4/3 : sur téléphone la scène occupe toute la largeur, un
     format plus haut donne une vraie surface de toucher sans rien décaler
     autour. La figure, déjà en pleine largeur de la gouttière, s'étend jusqu'aux
     bords de l'écran. */
  .fp-detail .fp-intro-figure-galerie .fp-intro-scene {
    aspect-ratio: 4 / 3;
    width: 100vw;
    max-width: 100vw;
    margin-inline: calc(50% - 50vw);
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }
  .fp-detail .fp-intro-carousel-nav .fp-carousel-arrow:first-child { left: 6px; }
  .fp-detail .fp-intro-carousel-nav .fp-carousel-arrow:last-child { right: 6px; }

  /* 5. TARIFS À DEUX RÉGIMES : la phrase explicative « accessible en activité
     seule en dehors des horaires Magic Kids » prend trop de place sur
     téléphone et force à faire défiler ; l'interrupteur et sa légende
     suffisent. Les libellés courts des segments viennent du markup
     (inc/sections.php, span.fp-tarifs-regime-court). */
  /* CORRECTIF DU 2026-09-11 (Marino : « le toggle pour switch les tarifs sur
     mur de grimpe est cassé sur mobile »). La règle masquait la phrase dans
     TOUS les panneaux. Sur Mini-golf fluo, sans conséquence : le panneau porte
     aussi un tableau de tarifs. Sur Mur de grimpe, cette phrase est le SEUL
     contenu du panneau « en dehors des horaires » : la masquer laissait un
     panneau entièrement vide, et l'onglet paraissait ne rien faire. Mesuré au
     banc : hauteur 0 sur Mur de grimpe, 292px sur Mini-golf.

     La phrase n'est donc masquée que lorsque le panneau porte AUSSI un corps de
     tarifs, c'est à dire quand il reste quelque chose à lire. Formulé sans
     nommer aucune activité : toute fiche à venir sera traitée juste.

     SEULE dans sa liste de sélecteurs (piège 5f du CLAUDE.md : un :has()
     invalide emporterait toute la liste). Un navigateur qui ignore :has()
     affiche la phrase partout : c'est le comportement d'avant ce masquage,
     un peu long à faire défiler mais jamais un panneau vide. */
  .fp-detail .fp-tarifs-regime > .fp-tab-panel:has(.fp-tarifs-body) .fp-tarifs-regime-note { display: none; }
  /* Le libellé long reste LU (lecteurs d'écran), seulement masqué à l'œil :
     le court est aria-hidden, sans quoi le bouton n'aurait plus de nom. */
  .fp-detail .fp-tarifs-regime-tab .fp-tarifs-regime-long {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
  .fp-detail .fp-tarifs-regime-tab .fp-tarifs-regime-court { display: inline; }
  .fp-detail .fp-tarifs-regime-tabs { flex-wrap: nowrap; }
  .fp-detail .fp-tarifs-regime-tab { padding: 9px 14px; font-size: .88rem; white-space: nowrap; }

  /* 6. TABLEAU DE TARIFS EN SLIDER HORIZONTAL (Marino, 2026-09-10 au soir,
     fiche Pixel Jump : « j'ai des tarifs qui dépassent quand trop de colonnes,
     propose un slide horizontal »).
     Première tentative, écartée : comprimer la table pour la faire tenir. Elle
     tenait, mais au prix de textes rapetissés et d'un libellé coupé en plein
     mot (« PERSONNE(S) SUPPLÉMENTAI RE(S) »), verdict de Marino : « trop
     petit ». Le tableau garde donc sa taille de lecture normale, prend la
     largeur qu'il lui faut, et c'est LUI qui glisse.
     Le défilement vit sur .fp-tarifs-widget, le conteneur que le plugin pose
     autour de la table (FP_Tarifs_Shortcode::render_simple), JAMAIS sur la
     carte .fp-tarifs-body-table : sinon la puce et le titre « Tarifs »
     partiraient de côté avec le tableau. Même principe que la matrice jour par
     tranche, qui a depuis toujours son propre .fp-tarifs-matrix-wrap : le
     défilement est confiné, la page ne déborde jamais latéralement.
     min-width: max-content sur la table : sans lui, la table se comprimerait
     pour tenir dans le conteneur et il n'y aurait tout simplement rien à faire
     glisser.
     SEULEMENT À PARTIR DE TROIS COLONNES (Marino : « scroll horizontal que si
     3 colonnes de tarifs, si deux on change pas »). Une grille à deux colonnes
     tient sans peine sur un téléphone : elle garde exactement le rendu qu'elle
     avait, pleine largeur, sans rien à faire glisser. Les classes has-cols-*
     sont posées par fp_tarifs_table_colonnes() (inc/sections.php), qui
     additionne les colspan de la première ligne. */
  .fp-detail .fp-tarifs-body-table.has-cols-3 .fp-tarifs-widget,
  .fp-detail .fp-tarifs-body-table.has-cols-4plus .fp-tarifs-widget {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--fp-white) 40%, transparent) transparent;
  }
  .fp-detail .has-cols-3 .fp-tarifs-table:not(.fp-tarifs-matrix),
  .fp-detail .has-cols-4plus .fp-tarifs-table:not(.fp-tarifs-matrix) {
    min-width: max-content;
  }

  /* TENTATIVE DE FAIRE TENIR TROIS COLONNES SANS DÉFILEMENT : ABANDONNÉE
     (2026-09-11). Recette essayée le même jour à la demande de Marino :
     réserve latérale rendue au tableau, colonne du milieu resserrée, cellules
     autorisées à passer à la ligne. Verdict sur la fiche Pixel Jump :
     « toujours pas ». Pire, sans défilement le tableau ne glissait plus mais
     DÉBORDAIT, et la colonne des prix se retrouvait coupée net au bord de la
     carte : un contenu inaccessible là où il était seulement à faire glisser.

     Ce qui manquait : la place. Trois colonnes dont un prix qui ne se coupe pas
     ne tiennent pas sous 400px, quoi qu'on resserre, sans rapetisser les textes,
     ce que Marino avait déjà refusé (« trop petit »).

     Le défilement est donc rétabli tel qu'il était, et c'est SON AFFORDANCE
     qu'on améliore : une indication explicite sous le tableau
     (.fp-tarifs-glisser, posée par fp_tarifs_glisser_indication() dans
     inc/sections.php) dit désormais qu'il y a quelque chose à faire glisser.
     Voir cette indication plus bas dans ce fichier. */

  /* OMBRE INTERNE DU CÔTÉ QUI GLISSE (Marino, 2026-09-11). Posée sur le
     conteneur de défilement, donc fixe par rapport à la carte : elle ne part
     pas avec le tableau. Elle dit qu'il reste du contenu à droite, et elle
     s'efface en fin de course (classe est-au-bout, posée par
     assets/js/tarifs-glisser.js) : une ombre qui resterait alors qu'il n'y a
     plus rien à voir serait un mensonge visuel.
     a-glisser et non un affichage permanent : rien n'apparaît si le tableau
     tient dans sa carte. */
  .fp-detail .fp-tarifs-widget.a-glisser {
    box-shadow: inset -18px 0 18px -18px color-mix(in srgb, var(--fp-dark) 85%, transparent);
    transition: box-shadow .25s ease;
  }
  .fp-detail .fp-tarifs-widget.a-glisser.est-au-bout {
    box-shadow: none;
  }

  /* BARRE DE PROGRESSION, « un truc blanc » (Marino, 2026-09-11). Dessinée par
     le script et non par la barre de défilement native : sur iOS, celle-ci est
     en surimpression et reste invisible au repos, elle n'aurait donc rien
     annoncé. Le pouce suit la position réelle du tableau, sa largeur dit quelle
     part on voit. */
  .fp-detail .fp-tarifs-piste {
    /* display INDISPENSABLE ici : la règle par défaut, hors requête de média,
       met .fp-tarifs-piste à display:none, et rien ne le défaisait. La barre
       existait dans la page, mesurée à 0 par 0. */
    display: block;
    position: relative;
    height: 4px;
    margin: 12px auto 0;
    max-width: 180px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--fp-white) 22%, transparent);
    overflow: hidden;
  }
  /* Le display:block ci-dessus bat la feuille du navigateur : sans cette
     ligne, l'attribut hidden que pose le script quand le tableau tient dans sa
     carte n'aurait plus aucun effet, et la barre s'afficherait vide. */
  .fp-detail .fp-tarifs-piste[hidden] {
    display: none;
  }
  .fp-detail .fp-tarifs-piste-pouce {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    border-radius: inherit;
    background: var(--fp-white);
    transition: left .12s linear, width .2s ease;
  }
  @media (prefers-reduced-motion: reduce) {
    .fp-detail .fp-tarifs-piste-pouce { transition: none; }
    .fp-detail .fp-tarifs-widget.a-glisser { transition: none; }
  }

  /* Indication « faites glisser », sous le tableau et seulement sur téléphone,
     là où le défilement existe. Discrète, centrée, jamais en travers du
     tableau : elle informe sans encombrer. */
  .fp-detail .fp-tarifs-glisser {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 10px 0 0;
    font-size: .78rem;
    letter-spacing: .02em;
    color: color-mix(in srgb, var(--fp-white) 72%, transparent);
  }
  .fp-detail .fp-tarifs-glisser-fleche {
    font-size: 1rem;
    line-height: 1;
  }
  /* Chaque cellule tient sur une ligne : c'est ce qui donne au tableau sa
     largeur naturelle, et ce qui évite les coupures en plein mot. */
  .fp-detail .has-cols-3 .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-label,
  .fp-detail .has-cols-3 .fp-tarifs-table:not(.fp-tarifs-matrix) td:not(.fp-tarifs-price),
  .fp-detail .has-cols-4plus .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-label,
  .fp-detail .has-cols-4plus .fp-tarifs-table:not(.fp-tarifs-matrix) td:not(.fp-tarifs-price) {
    white-space: nowrap;
  }
  /* Seule exception : la note sous le prix, qui serait interminable sur une
     ligne (« Par personne. Maximum 12 personnes »). Elle passe à la ligne dans
     une colonne de largeur raisonnable, alignée à droite sous son prix. */
  .fp-detail .has-cols-3 .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-rownote,
  .fp-detail .has-cols-4plus .fp-tarifs-table:not(.fp-tarifs-matrix) .fp-tarifs-rownote {
    display: block;
    max-width: 22ch;
    margin-left: auto;
    white-space: normal;
  }
}
@keyframes fp-intro-badge-flotte {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-5px); }
}
@media (prefers-reduced-motion: reduce) {
  .fp-detail .fp-intro-badge { animation: none; }
}
/* Hors téléphone, seul le libellé long des segments existe.

   BORNÉE À 721px ET PLUS le 2026-09-11 (Marino : « le toggle pour switch les
   tarifs sur mur de grimpe est cassé sur mobile, idem pour mini golf »).

   Sans cette borne, la règle s'appliquait AUSSI sur téléphone. Elle porte
   exactement les mêmes trois classes que celle du bloc mobile plus haut
   (.fp-detail .fp-tarifs-regime-tab .fp-tarifs-regime-court { display: inline })
   et vient APRÈS elle dans la feuille : à spécificité égale, c'est l'ordre qui
   tranche, et une requête de média n'ajoute aucun poids. Le libellé court était
   donc masqué partout.

   Conséquence mesurée au banc sur les deux fiches, en 390px : le libellé long
   étant masqué visuellement pour les lecteurs d'écran (position absolue, 1px),
   et le court en display:none, les deux boutons ne contenaient plus RIEN de
   visible et tombaient à 28px de large pour 44 de haut. Le bascule paraissait
   cassé alors qu'il fonctionnait : il n'avait simplement plus de texte. */
@media (min-width: 721px) {
  .fp-detail .fp-tarifs-regime-tab .fp-tarifs-regime-court { display: none; }
}

/* FORMULES EN SLIDER SUR TÉLÉPHONE (Marino, 2026-09-10) : voir
   setupFormulesSlider() (main.js) pour le pourquoi. Le défilement est natif
   (overflow + magnétisme), le script n'ajoute que points et flèches. Une
   carte centrée à 88 % de la largeur, la suivante se devine sur la droite,
   même hauteur pour toutes (align-items: stretch, cartes en colonne flex).
   Les marges internes de la passe tablette ne s'appliquent pas ici (elles
   sont bornées à 721px). */
@media (max-width: 720px) {
  /* PLEINE LARGEUR D'ÉCRAN (Marino, soir du 2026-09-10 : « je vois la deuxième
     formule coupée sur le côté droit par un carré blanc, il faut que la section
     soit vraiment en pleine largeur, comme ça elle n'est jamais coupée que par
     les bords de l'écran »). La piste sortait de la gouttière de .fp-wrap par
     une marge négative égale à --fp-gutter-mobile, ce qui la calait sur la
     gouttière et non sur l'écran : le moindre écart (padding hérité, barre de
     défilement) laissait une bande blanche à droite. `margin-inline: calc(50%
     - 50vw)` la recentre sur la fenêtre entière quel que soit son conteneur ;
     le retrait interne redevient une vraie gouttière. `scroll-snap-stop:
     always` (sur la carte) interdit d'en sauter plusieurs d'un geste : on
     avance d'une carte, on recule d'une carte, jamais de course libre. */
  .fp-detail .fp-formules-grid {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    /* overflow-y EXPLICITE (Marino, 2026-09-11 : « que le slide soit
       qu'horizontal, là je peux slide en diagonal vertical »). Déclarer un seul
       axe ne suffit pas : quand overflow-x vaut auto, la spécification force
       l'autre axe de visible à auto. La piste devenait donc scrollable
       verticalement elle aussi, et le doigt la faisait partir en diagonale.
       hidden ne coupe rien ici, la hauteur de la piste étant déjà celle de sa
       carte la plus haute.
       Pas de touch-action: pan-x, volontairement : cela aurait empêché de
       faire défiler LA PAGE quand le geste commence sur le carrousel. */
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding: 0 var(--fp-gutter-mobile, 18px);
    width: 100vw;
    max-width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding: 6px var(--fp-gutter-mobile, 18px) 10px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .fp-detail .fp-formules-grid::-webkit-scrollbar { display: none; }
  .fp-detail .fp-formules-grid .fp-formule {
    flex: 0 0 86%;
    max-width: 86%;
    scroll-snap-align: center;
    scroll-snap-stop: always;
  }
  /* AUCUNE OMBRE SUR LA PISTE (Marino, 2026-09-11 : « sur mobile enlève les
     ombres des formules, ça se coupe »).

     La carte porte au repos une ombre large et douce, 52px de flou décalés de
     26px vers le bas. Sur ordinateur elle se déploie librement ; ici la grille
     est devenue un carrousel à défilement horizontal, et tout ce qui dépasse
     de la piste est tranché net. L'ombre se voyait donc coupée au ras de la
     carte, en un trait franc, exactement l'inverse de l'effet recherché.

     Neutralisée, jamais supprimée : la règle de base reste intacte et
     l'ordinateur garde son ombre. Le relief vient de toute façon du dégradé de
     la carte, qui suffit à la détacher du fond. */
  .fp-detail .fp-formules-grid .fp-formule {
    box-shadow: none;
  }
  /* AUCUN EFFET DE SURVOL SUR LA PISTE (Marino, 2026-09-10 au soir : « enlève
     le hover sur mobile, le hover casse l'effet car quand on slide il se
     déclenche »). Un écran tactile n'a pas de survol, mais le navigateur en
     simule un au toucher : la carte se soulevait et pivotait en plein
     glissement, et l'état restait collé après le geste. Les trois règles de
     survol de la carte sont neutralisées ici, jamais supprimées : le bureau
     les garde intactes. */
  .fp-detail .fp-formules-grid .fp-formule:hover {
    transform: none;
    /* none et non plus l'ombre de repos : depuis le 2026-09-11 la piste n'en
       porte plus du tout (voir plus haut), la restaurer ici au moindre toucher
       aurait fait réapparaître le trait coupé que l'on vient d'enlever. */
    box-shadow: none;
  }
  .fp-detail .fp-formules-grid .fp-formule:hover .fp-formule-topo {
    background-position: center 38%;
  }
  .fp-detail .fp-formules-grid .fp-formule:hover .fp-formule-icon {
    transform: none;
  }
  /* Moins de marges internes dans la carte (Marino : « il faut moins de padding
     sur la zone de contenu, le texte formule et le texte en dessous sont tout
     petits parce qu'on a beaucoup de padding en haut et sur les côtés »). Le
     retrait haut reste plus grand que les autres : le médaillon d'icône est à
     cheval sur le bandeau et mord dessus. */
  .fp-detail .fp-formules-grid .fp-formule-inner { padding: 30px 16px 18px; }
  /* Une seule formule : bloc simple, pas de piste à faire défiler. Règle
     avec :has SEULE dans sa liste (piège 5f). */
  .fp-detail .fp-formules-grid:has(> .fp-formule:only-child) { display: block; width: auto; max-width: none; padding: 0; margin: 0; }
  .fp-detail .fp-formules-grid:has(> .fp-formule:only-child) .fp-formule { max-width: none; }

  /* Points et flèches COLLÉS à la piste (Marino : « tu peux monter les points
     et la navigation beaucoup plus proches, il y a trop d'espace blanc entre
     les deux »). Le conteneur .fp-formules-body porte un gap de 40px hérité du
     bureau : il est ramené à zéro sous 720px, l'écart utile étant porté par la
     seule marge de la rangée. */
  .fp-detail .fp-formules-body { gap: 0; margin-top: 30px; }
  .fp-formules-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin-top: 2px;
  }
  .fp-formules-points { display: flex; gap: 8px; }
  .fp-formules-point {
    width: 10px; height: 10px; padding: 0; margin: 0;
    border: 0; border-radius: 50%;
    background: color-mix(in srgb, var(--fp-secondary) 28%, transparent);
    cursor: pointer;
    transition: background .2s ease, transform .2s ease;
  }
  .fp-formules-point.is-active { background: var(--fp-primary); transform: scale(1.25); }
  .fp-formules-fleche {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; padding: 0; margin: 0;
    border: 1.5px solid var(--fp-primary); border-radius: 50%;
    background: var(--fp-white); color: var(--fp-primary);
    cursor: pointer;
    transition: opacity .2s ease;
  }
  .fp-formules-fleche::before {
    content: ''; width: 9px; height: 9px;
    border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
    transform: rotate(-45deg) translate(-1px, 1px);
  }
  .fp-formules-fleche.is-prev::before { transform: rotate(135deg) translate(-1px, 1px); }
  .fp-formules-fleche[disabled] { opacity: .32; cursor: default; }
  .fp-formules-point:focus-visible, .fp-formules-fleche:focus-visible { outline: 2px solid var(--fp-primary); outline-offset: 3px; }
}

/* BOUTON DE SECOURS DE LA VIDÉO DE FOND (voir setupVideosFond, main.js) :
   « Lancer la vidéo » n'apparaît que si la lecture automatique a été refusée
   (économie d'énergie sur iOS). Il reprend le dessin du bouton de son. Le
   bouton « Voir en grand » qui l'accompagnait a été retiré le 2026-09-10 au
   soir, la vidéo s'affichant désormais vraiment sur téléphone. */
.fp-detail .fp-tarifs-lancer {
  position: absolute;
  left: 50%;
  bottom: 22px;
  z-index: 3;
  transform: translateX(-50%);
  padding: 10px 18px;
  border: 1.5px solid var(--fp-white);
  border-radius: 999px;
  background: color-mix(in srgb, var(--fp-dark) 55%, transparent);
  color: var(--fp-white);
  font-weight: 600;
  font-size: .9rem;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  cursor: pointer;
}
.fp-detail .fp-tarifs-lancer:focus-visible,
.fp-detail .fp-tarifs-pause:focus-visible { outline: 2px solid var(--fp-white); outline-offset: 3px; }

/* Sur téléphone, les deux commandes se partagent le bas du média (pause à
   gauche, son à droite) : un cran plus petites et plus près des bords, elles
   restent au-dessus des 44px de cible tactile recommandés. */
@media (max-width: 720px) {
  .fp-detail .fp-tarifs-son,
  .fp-detail .fp-tarifs-pause { width: 44px; height: 44px; bottom: 16px; }
  .fp-detail .fp-tarifs-son { right: 16px; }
  .fp-detail .fp-tarifs-pause { left: 16px; }
}

/* ==========================================================================
   TÉLÉPHONE : ON RETIRE LES EFFETS QUI COÛTENT LE PLUS AU GPU
   (Marino, 2026-09-11 : « on va opti la vitesse maintenant, surtout les pages
   activités ». Validé : « sous 720 px, retirer les halos floutés du hero et
   remplacer les flous d'arrière-plan des pastilles par un fond opaque ».)

   CE QUI CHAUFFAIT. Une fiche empilait, dans le même écran ou presque, un
   diaporama plein écran en zoom permanent, deux halos floutés à 60 px animés
   en boucle par-dessus, des pastilles à flou d'arrière-plan posées sur ce
   diaporama, puis plus bas une vidéo de fond sous un tableau lui aussi flouté.
   Aucun de ces effets n'était désactivé sur téléphone. Flouter en direct une
   surface qui bouge est l'opération la plus chère qu'on puisse demander à un
   navigateur mobile : le flou se recalcule à chaque image, sur toute la zone.

   CE BLOC VIT EN FIN DE FICHIER, ET C'EST NÉCESSAIRE : une requête de média
   n'ajoute aucune spécificité, seule la position dans le fichier départage
   deux règles de même poids. Le déplacer plus haut le rendrait inopérant.

   LE DESSIN NE CHANGE PAS, seule la matière : chaque surface qui perd son flou
   gagne en opacité de quoi garder exactement le même contraste de texte. C'est
   le traitement que le thème applique déjà aux navigateurs sans
   backdrop-filter (voir le bloc @supports de main.css).
   ========================================================================== */
@media (max-width: 720px) {
  /* 1. LES DEUX HALOS DU HÉRO. Deux disques de 46vw floutés à 60 px et animés
        en boucle, superposés au diaporama qui zoome : la surface à recalculer
        couvrait la moitié de l'écran, en continu, dès l'arrivée sur la page.
        Sur grand écran ils restent, la dépense y est sans conséquence. */
  .fp-detail .fp-hero-detail::before,
  .fp-detail .fp-hero-detail::after {
    display: none;
  }

  /* 2. LA CARTE DES TARIFS, posée sur une vidéo en boucle. C'est le pire cas
        de la page : une surface floutée par-dessus des images qui défilent. */
  .fp-detail .fp-tarifs.has-fond-media .fp-tarifs-body-table,
  .fp-detail .fp-tarifs.has-fond-media .fp-tarifs-body.fp-tarifs-body-nu {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: color-mix(in srgb, var(--fp-dark) 88%, transparent);
  }

  /* 3. LES TROIS BOUTONS DE LA VIDÉO (son, pause, lancer), eux aussi flottant
        au-dessus d'elle. */
  .fp-detail .fp-tarifs-son,
  .fp-detail .fp-tarifs-pause,
  .fp-detail .fp-tarifs-lancer {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: color-mix(in srgb, var(--fp-dark) 78%, transparent);
  }

  /* 4. LA PASTILLE « VOIR » DES CARTES DU CARROUSEL et le voile du pop-up des
        horaires : flous plus légers, mais posés sur des surfaces en mouvement
        (carrousel qui défile, pop-up qui s'ouvre). */
  .fp-detail .fp-related .fp-card-open {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: color-mix(in srgb, var(--fp-dark) 72%, transparent);
  }
  .fp-detail .fp-horaires-popup-overlay {
    backdrop-filter: none;
    background-color: color-mix(in srgb, var(--fp-dark) 72%, transparent);
  }
}
