{"id":850,"date":"2025-08-15T15:15:20","date_gmt":"2025-08-15T19:15:20","guid":{"rendered":"https:\/\/enpistedev.wpenginepowered.com\/reports\/"},"modified":"2026-03-09T13:41:44","modified_gmt":"2026-03-09T17:41:44","slug":"reports","status":"publish","type":"page","link":"https:\/\/enpiste.qc.ca\/en\/reports\/","title":{"rendered":"Reports &amp; publications"},"content":{"rendered":"<h2>Reports &amp; publications<\/h2>\n<p>A structured overview of our activities, performance, and impact in recent years.<\/p>\n<p>\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"800\" height=\"534\" src=\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg\" alt=\"\" srcset=\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg 1024w, https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-300x200.jpg 300w, https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-768x512.jpg 768w, https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1536x1024.jpg 1536w, https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-2048x1365.jpg 2048w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/p>\n<p>Christa Wilson, Erick Santos | N\u00f3s &#8211; A Romantic Circus Tale | Duo Erick &amp; Christa \u00a9 Chris Robert<\/p>\n<p>\t<div class=\"acf-a-la-une-app\" data-cpt=\"rapport\" data-lang=\"en\">\n\t\t\t\t\t<h2 class=\"acf-a-la-une-title\">Featured Reports and Publications<\/h2>\n\t\t\t\t<div class=\"acf-a-la-une-grid\"><\/div>\n\t\t<div class=\"acf-a-la-une-swiper swiper\" style=\"display:none;\">\n\t\t\t<div class=\"swiper-wrapper\"><\/div>\n\t\t\t<div class=\"swiper-pagination\"><\/div>\n\t\t<\/div>\n\t<\/div>\n\n\t<link rel=\"stylesheet\" href=\"https:\/\/cdn.jsdelivr.net\/npm\/swiper@11\/swiper-bundle.min.css\" \/>\n\t<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/swiper@11\/swiper-bundle.min.js\"><\/script>\n\n\t<style>\n\t.acf-a-la-une-title {\n\t  color: #D30C8C;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 32px !important;\n\t  font-style: normal;\n\t  font-weight: 600 !important;\n\t  line-height: 35px;\n\t  margin: 0;\n\t  flex: 0 0 30%;\n\t  min-width: 200px;\n\t  margin-bottom: 30px;\n\t}\n\t\n\t.acf-a-la-une-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-bottom: 30px; }\n\t@media screen and (min-width:1024px) {\n\t\t.acf-a-la-une-grid.one-card .acf-img-container { width:40%; height:100%; }\n\t}\n\t.acf-categories { display:flex; flex-wrap:wrap; gap:8px; }\n\t.acf-category { padding:4px 6px; color:#455A64; font-family:\"TikTok Sans\" !important; font-size:10px !important; font-weight:400 !important; line-height:12px; border-radius:100px; white-space:nowrap; background-color:#cfd8dc80; }\n\t.acf-a-la-une-grid.one-card { grid-template-columns:1fr; margin:0 auto 30px; }\n\t.acf-a-la-une-grid.two-cards { grid-template-columns:repeat(2, 1fr); }\n\t.acf-a-la-une-grid.three-cards { grid-template-columns:repeat(3, 1fr); }\n\t@media (max-width:1023px) {\n\t\t.acf-a-la-une-grid.two-cards { grid-template-columns:repeat(2, 1fr); }\n\t\t.acf-a-la-une-grid.one-card { grid-template-columns:1fr; max-width:none; margin:0 0 30px; }\n\t\t.acf-a-la-une-grid.three-cards { grid-template-columns:repeat(2, 1fr); }\n\t}\n\t@media (max-width:767px) {\n\t\t.acf-a-la-une-grid { grid-template-columns:1fr; }\n\t\t.acf-a-la-une-grid.one-card { max-width:none; margin:0 0 30px; }\n\t}\n\t.acf-card-wrapper { display:flex; flex-direction:column; }\n\t.acf-card { height:100%; display:flex; flex-direction:column; border-radius:12px; text-decoration:none; color:inherit; transition:box-shadow .3s; background:#F5F6F7; box-shadow:8px 8px 12px 0 rgba(231,231,233,.6)!important; min-height:200px; }\n\t.acf-card:hover { box-shadow:8px 8px 12px 0 rgba(160,160,167,.5)!important; }\n\t@media (min-width:1024px) {\n\t\t.acf-a-la-une-grid.one-card .acf-card { flex-direction:row; min-height:300px; max-height:350px; }\n\t\t.acf-a-la-une-grid.one-card .acf-img { width:100%!important; height:100%!important; border-radius:12px 0 0 12px!important; object-fit:cover; }\n\t\t.acf-a-la-une-grid.one-card .acf-body { width:50%; padding:24px; justify-content:flex-start; }\n\t\t.acf-a-la-une-grid.one-card .acf-date-title-excerpt { gap:12px; }\n\t\t.acf-a-la-une-grid.one-card .acf-title { font-size:28px!important; line-height:32px; }\n\t\t.acf-a-la-une-grid.one-card .acf-excerpt { font-size:16px!important; line-height:24px; }\n\t}\n\t.acf-img-container { position:relative; width:100%; height:170px; border-radius:12px 12px 0 0; overflow:hidden; }\n\t.acf-img { width:100%; height:100%; object-fit:cover; border-radius:12px 12px 0 0; }\n\t.acf-nom-prenom { position:absolute; bottom:0; left:0; color:#FFF; font-family:\"TikTok Sans\" !important; font-size:10px !important; font-weight:400 !important; line-height:12px; padding:0 0 6px 12px; }\n\t.acf-body { flex:1; display:flex; flex-direction:column; padding:16px; justify-content:space-between; }\n\t.acf-date-title-excerpt { display:flex; flex-direction:column; gap:8px; }\n\t.acf-date { color:#666; font-family:\"TikTok Sans\" !important; font-size:12px !important; font-weight:400 !important; line-height:16px; }\n\t.acf-title { color:#333; font-family:\"TikTok Sans\" !important; font-size:18px !important; font-weight:600 !important; line-height:24px; margin:0; }\n\t.acf-excerpt { color:#666; font-family:\"TikTok Sans\" !important; font-size:14px !important; font-weight:400 !important; line-height:20px; margin:0; }\n\t.acf-a-la-une-swiper { width:100%; overflow:hidden; }\n\t.acf-a-la-une-swiper .swiper-wrapper { display:flex; align-items:stretch; }\n\t.acf-a-la-une-swiper .swiper-slide { height:auto; display:flex; flex-direction:column; }\n\t.acf-a-la-une-swiper.tablet-3 .swiper-slide { width:calc(50% - 10px)!important; flex-shrink:0; }\n\t.acf-a-la-une-swiper.tablet-3 .acf-card-wrapper, .acf-a-la-une-swiper.mobile-2 .acf-card-wrapper, .acf-a-la-une-swiper.mobile-3 .acf-card-wrapper { height:100%; }\n\t.acf-a-la-une-swiper.mobile-2 .swiper-slide, .acf-a-la-une-swiper.mobile-3 .swiper-slide { width:100%!important; flex-shrink:0; }\n\t.acf-a-la-une-swiper .swiper-pagination { position:relative; margin-top:20px; text-align:center; }\n\t.acf-a-la-une-swiper .swiper-pagination-bullet { width:8px; height:8px; background:#CFD8DC; opacity:.5; margin:0 4px; border-radius:50%; cursor:pointer; }\n\t.acf-a-la-une-swiper .swiper-pagination-bullet-active { opacity:1; background:#455A64; }\n\t\n\t\/* Styles sp\u00e9cifiques UNIQUEMENT pour les pages de publications *\/\n\t\/* Ces styles ne s'appliquent que quand les classes .with-image ou .without-image sont pr\u00e9sentes *\/\n\t\n\t\/* Min-height sp\u00e9cifique pour les publications *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-card {\n\t\tmin-height: 200px !important;\n        transition: box-shadow .3s;\n        background: #F5F6F7;\n        box-shadow: 8px 8px 12px 0 rgba(231, 231, 233, .6) !important;\n\t}\n\t\n\t\/* Styles pour la structure des publications - plus sp\u00e9cifiques *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-header-group {\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t\tgap: 0 !important;\n\t\tpadding: 16px 16px 0 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-content-group {\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t\tgap: 8px !important;\n\t\tpadding: 0 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-card .acf-body {\n\t\tpadding: 0 !important;\n\t\tgap: 16px !important;\n\t\tjustify-content: flex-start !important;\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t}\n\n\t.acf-a-la-une-app.acf-publications-page .acf-card .acf-plus-holder {\n\t\tpadding: 0 16px 16px 16px !important;\n\t\tmargin-top: auto !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-img-container {\n\t\theight: 120px !important;\n\t\tborder-radius: 0 !important;\n\t\toverflow: hidden !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-img {\n\t\theight: 120px !important;\n\t\tborder-radius: 0 !important;\n\t\twidth: 100% !important;\n\t\tobject-fit: cover !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-title-publieur-group {\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t\tgap: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-img-container.acf-no-image {\n\t\tdisplay: none !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-ville-date {\n\t\tdisplay: flex !important;\n\t\tgap: 3px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-ville {\n\t\tfont-size: 12px !important;\n\t\tcolor: #666 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-ville::after {\n\t\tcontent: \", \" !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-title {\n\t\tfont-size: 18px !important;\n\t\tfont-weight: 600 !important;\n\t\tmargin: 0 !important;\n\t\tcolor: #333 !important;\n\t\tline-height: 1.3 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-date {\n\t\tfont-size: 12px !important;\n\t\tcolor: #666 !important;\n\t\tmargin: 0 !important;\n\t\talign-self: flex-end;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-excerpt {\n\t\tcolor: #666 !important;\n\t\tfont-size: 14px !important;\n\t\tline-height: 1.4 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t\/* Layouts adaptatifs pour les publications *\/\n\t\n\t\/* Styles de debug supprim\u00e9s - Design final propre *\/\n\t\n\t\/* 1 card avec image : layout horizontal sur desktop\/tablette *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-card {\n\t\tflex-direction: row !important;\n\t\tmin-height: 200px !important;\n\t\tmax-height: 350px !important;\n\t\tdisplay: flex !important;\n\t\talign-items: stretch !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-img-container {\n\t\tflex: 0 0 40% !important;\n\t\theight: 100% !important;\n\t\tborder-radius: 12px 0 0 12px !important;\n\t\toverflow: hidden !important;\n\t\tposition: relative !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-img {\n\t\twidth: 100% !important;\n\t\theight: 100% !important;\n\t\tborder-radius: 12px 0 0 12px !important;\n\t\tobject-fit: cover !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-body {\n\t\tflex: 1 !important;\n\t\tpadding: 24px !important;\n\t\tjustify-content: space-between !important;\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-date-title-excerpt {\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t\tgap: 12px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-title {\n\t\tfont-size: 28px !important;\n\t\tline-height: 32px !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-excerpt {\n\t\tfont-size: 16px !important;\n\t\tline-height: 24px !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t\/* 1 card sans image : layout vertical avec hauteur min *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.without-image .acf-card {\n\t\tmin-height: 200px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.without-image .acf-body {\n\t\tpadding: 20px !important;\n\t\theight: 100% !important;\n\t\tjustify-content: space-between !important;\n\t}\n\t\n\t\/* 2+ cards : layout grille standard avec structure comme \"ici\" *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards {\n\t\tgrid-template-columns: repeat(2, 1fr) !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards {\n\t\tgrid-template-columns: repeat(3, 1fr) !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards {\n\t\tgrid-template-columns: repeat(3, 1fr) !important;\n\t}\n\t\n\t\/* Styles pour les 2+ cards avec structure comme \"ici\" *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-card,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-card,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-card {\n\t\tflex-direction: column !important;\n\t\tmin-height: 200px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-img-container,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-img-container,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-img-container {\n\t\theight: 120px !important;\n\t\tborder-radius: 0 !important;\n\t\toverflow: hidden !important;\n\t\tposition: relative !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-img,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-img,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-img {\n\t\twidth: 100% !important;\n\t\theight: 120px !important;\n\t\tborder-radius: 0 !important;\n\t\tobject-fit: cover !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-body,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-body,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-body {\n\t\tflex: 1 !important;\n\t\tpadding: 0 !important;\n\t\tjustify-content: space-between !important;\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-header-group,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-header-group,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-header-group {\n\t\tpadding: 16px 16px 0 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-content-group,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-content-group,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-content-group {\n\t\tgap: 8px !important;\n\t\tpadding: 0 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-plus-holder,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-plus-holder,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-plus-holder {\n\t\tpadding: 0 16px 16px 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-title,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-title,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-title {\n\t\tfont-size: 22px !important;\n\t\tfont-weight: 600 !important;\n\t\tline-height: 24px !important;\n\t\tmargin: 0 !important;\n\t\tcolor: #333 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards .acf-excerpt,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards .acf-excerpt,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards .acf-excerpt {\n\t\tfont-size: 14px !important;\n\t\tfont-weight: 400 !important;\n\t\tline-height: 20px !important;\n\t\tmargin: 0 !important;\n\t\tcolor: #666 !important;\n\t}\n\t\n\t\/* Styles pour le carrousel (swiper) - copie exacte des styles 2+ cards *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .swiper-slide {\n\t\theight: auto !important;\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-card-wrapper {\n\t\theight: 100% !important;\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-card {\n\t\tflex-direction: column !important;\n\t\tmin-height: 200px !important;\n\t\tdisplay: flex !important;\n\t\tbackground: #F5F6F7 !important;\n\t\tborder-radius: 12px !important;\n\t\toverflow: hidden !important;\n\t\tbox-shadow: 8px 8px 12px 0 rgba(231, 231, 233, .6) !important;\n\t\theight: 100% !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-img-container {\n\t\theight: 120px !important;\n\t\tborder-radius: 0 !important;\n\t\toverflow: hidden !important;\n\t\tposition: relative !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-img {\n\t\twidth: 100% !important;\n\t\theight: 120px !important;\n\t\tborder-radius: 0 !important;\n\t\tobject-fit: cover !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-body {\n\t\tflex: 1 !important;\n\t\tpadding: 0 !important;\n\t\tjustify-content: space-between !important;\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-header-group {\n\t\tpadding: 16px 16px 0 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-content-group {\n\t\tgap: 8px !important;\n\t\tpadding: 0 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-plus-holder {\n\t\tpadding: 0 16px 16px 16px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-title {\n\t\tfont-size: 22px !important;\n\t\tfont-weight: 600 !important;\n\t\tline-height: 24px !important;\n\t\tmargin: 0 !important;\n\t\tcolor: #333 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-excerpt {\n\t\tfont-size: 14px !important;\n\t\tfont-weight: 400 !important;\n\t\tline-height: 20px !important;\n\t\tmargin: 0 !important;\n\t\tcolor: #666 !important;\n\t}\n\t\n\t\/* Styles suppl\u00e9mentaires pour le carrousel - copie des styles 2+ cards *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-date {\n\t\tfont-size: 12px !important;\n\t\tcolor: #666 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-name-publieur {\n\t\tfont-size: 14px !important;\n\t\tfont-weight: 600 !important;\n\t\tcolor: #333 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-entreprise-role {\n\t\tdisplay: flex !important;\n\t\tgap: 4px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-entreprise,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-role-publieur {\n\t\tfont-size: 12px !important;\n\t\tcolor: #666 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-ville-date {\n\t\tdisplay: flex !important;\n\t\tgap: 3px !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-ville {\n\t\tfont-size: 12px !important;\n\t\tcolor: #666 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-ville::after {\n\t\tcontent: \", \" !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-categories {\n\t\tdisplay: flex !important;\n\t\tgap: 8px !important;\n\t\tflex-wrap: wrap !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-category {\n\t\tfont-size: 12px !important;\n\t\tpadding: 4px 8px !important;\n\t\tbackground-color:#cfd8dc80 !important;\n\t\tborder-radius: 100px !important;\n\t\tcolor: #666 !important;\n\t}\n\t\n\t\/* Styles sp\u00e9cifiques pour forcer l'alignement parfait du carrousel avec la grid *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .swiper-wrapper {\n\t\talign-items: stretch !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .swiper-slide {\n\t\theight: auto !important;\n\t\tdisplay: flex !important;\n\t\tflex-direction: column !important;\n\t\talign-items: stretch !important;\n\t}\n\t\n\t\/* S'assurer que les cards du carrousel ont la m\u00eame hauteur *\/\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-card {\n\t\theight: 100% !important;\n\t\tmin-height: 200px !important;\n\t}\n\t\n\t\/* Forcer les m\u00eames styles que la grid pour tous les \u00e9l\u00e9ments *\/\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-name-publieur {\n\t\tfont-size: 14px !important;\n\t\tfont-weight: 600 !important;\n\t\tcolor: #333 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-entreprise-role {\n\t\tdisplay: flex !important;\n\t\tgap: 8px !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-entreprise,\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-role-publieur {\n\t\tfont-size: 12px !important;\n\t\tcolor: #666 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-ville-date {\n\t\tdisplay: flex !important;\n\t\tgap: 3px !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-ville {\n\t\tfont-size: 12px !important;\n\t\tcolor: #666 !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-ville::after {\n\t\tcontent: \", \" !important;\n\t}\n\t\n\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-swiper .acf-categories {\n\t\tdisplay: flex !important;\n\t\tgap: 8px !important;\n\t\tflex-wrap: wrap !important;\n\t\tmargin: 0 !important;\n\t}\n\t\n\t\n\t\/* Responsive pour les layouts des publications *\/\n\t@media (max-width: 1023px) {\n\t\t\/* 1 card avec image : layout vertical sur tablette *\/\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-card {\n\t\t\tflex-direction: column !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-img-container {\n\t\t\tflex: none !important;\n\t\t\theight: 120px !important;\n\t\t\tborder-radius: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-img {\n\t\t\theight: 120px !important;\n\t\t\tborder-radius: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.one-card.with-image .acf-body {\n\t\t\tpadding: 16px !important;\n\t\t}\n\t\t\n\t\t\/* 2+ cards sur tablette *\/\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.two-cards {\n\t\t\tgrid-template-columns: repeat(2, 1fr) !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.three-cards {\n\t\t\tgrid-template-columns: repeat(2, 1fr) !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid.multiple-cards {\n\t\t\tgrid-template-columns: repeat(2, 1fr) !important;\n\t\t}\n\t\t\n\t}\n\t\n\t@media (max-width: 767px) {\n\t\t\/* Tous les layouts sur mobile : 1 colonne *\/\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid {\n\t\t\tgrid-template-columns: 1fr !important;\n\t\t}\n\t\t\n\t\t\/* Force l'application des styles pour les pages de publications en mobile *\/\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-card-wrapper {\n\t\t\twidth: 100% !important;\n\t\t}\n\t\t\n\t\t\/* Styles unifi\u00e9s pour TOUTES les cards en mobile (1, 2, 3+) *\/\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-card {\n\t\t\tflex-direction: column !important;\n\t\t\tmin-height: 200px !important;\n\t\t\tdisplay: flex !important;\n\t\t\tbackground: white !important;\n\t\t\tborder-radius: 12px !important;\n\t\t\toverflow: hidden !important;\n\t\t\tbox-shadow: 0 2px 8px rgba(0,0,0,0.1) !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-img-container {\n\t\t\theight: 170px !important;\n\t\t\tborder-radius: 12px 12px 0 0 !important;\n\t\t\toverflow: hidden !important;\n\t\t\tposition: relative !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-img {\n\t\t\twidth: 100% !important;\n\t\t\theight: 100% !important;\n\t\t\tborder-radius: 12px 12px 0 0 !important;\n\t\t\tobject-fit: cover !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-body {\n\t\t\tflex: 1 !important;\n\t\t\tpadding: 0 !important;\n\t\t\tjustify-content: space-between !important;\n\t\t\tdisplay: flex !important;\n\t\t\tflex-direction: column !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-header-group {\n\t\t\tpadding: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-content-group {\n\t\t\tgap: 8px !important;\n\t\t\tpadding: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-plus-holder {\n\t\t\tpadding: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-title {\n\t\t\tfont-size: 22px !important;\n\t\t\tfont-weight: 600 !important;\n\t\t\tline-height: 24px !important;\n\t\t\tmargin: 0 !important;\n\t\t\tcolor: #333 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-excerpt {\n\t\t\tfont-size: 14px !important;\n\t\t\tfont-weight: 400 !important;\n\t\t\tline-height: 20px !important;\n\t\t\tmargin: 0 !important;\n\t\t\tcolor: #666 !important;\n\t\t}\n\t\t\n\t\t\/* Styles suppl\u00e9mentaires pour le mobile - pages de publications *\/\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-date {\n\t\t\tfont-size: 12px !important;\n\t\t\tcolor: #666 !important;\n\t\t\tmargin: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-name-publieur {\n\t\t\tfont-size: 14px !important;\n\t\t\tfont-weight: 600 !important;\n\t\t\tcolor: #333 !important;\n\t\t\tmargin: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-entreprise-role {\n\t\t\tdisplay: flex !important;\n\t\t\tgap: 4px !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-entreprise,\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-role-publieur {\n\t\t\tfont-size: 12px !important;\n\t\t\tcolor: #666 !important;\n\t\t\tmargin: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-ville-date {\n\t\t\tdisplay: flex !important;\n\t\t\tgap: 3px !important;\n\t\t\tmargin: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-ville {\n\t\t\tfont-size: 12px !important;\n\t\t\tcolor: #666 !important;\n\t\t\tmargin: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-ville::after {\n\t\t\tcontent: \", \" !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-categories {\n\t\t\tdisplay: flex !important;\n\t\t\tgap: 8px !important;\n\t\t\tflex-wrap: wrap !important;\n\t\t\tmargin: 0 !important;\n\t\t}\n\t\t\n\t\t.acf-a-la-une-app.acf-publications-page .acf-a-la-une-grid .acf-category {\n\t\t\tfont-size: 12px !important;\n\t\t\tpadding: 4px 8px !important;\n\t\t\tbackground-color: #f0f0f0 !important;\n\t\t\tborder-radius: 4px !important;\n\t\t\tcolor: #666 !important;\n\t\t}\n\t\t\n\t}\n\t<\/style>\n\n\t<script>\n\tdocument.addEventListener(\"DOMContentLoaded\", function () {\n\t\tdocument.querySelectorAll(\".acf-a-la-une-app\").forEach((app) => {\n\t\t\tconst cpt = app.dataset.cpt;\n\t\t\tconst lang = app.dataset.lang || (window.location.pathname.indexOf('\/en') !== -1 ? 'en' : 'fr');\n\t\t\tconst gridEl = app.querySelector(\".acf-a-la-une-grid\");\n\t\t\tconst swiperContainer = app.querySelector(\".acf-a-la-une-swiper\");\n\t\t\tconst swiperWrapper = swiperContainer.querySelector(\".swiper-wrapper\");\n\t\t\tlet swiper = null;\n\n\t\t\t\/\/ Fonction pour obtenir le message \"aucun r\u00e9sultat\" selon la page\n\t\t\tfunction getNoContentMessage() {\n\t\t\t\tconst path = window.location.pathname;\n\t\t\t\t\n\t\t\t\t\/\/ D\u00e9tection de la page selon l'URL\n\t\t\t\tif (path.includes('\/evenements') || path.includes('\/events')) {\n\t\t\t\t\treturn lang === 'en' ? 'No event found' : 'Aucun \u00e9v\u00e9nement trouv\u00e9';\n\t\t\t\t} else if (path.includes('\/nouvelles') || path.includes('\/news')) {\n\t\t\t\t\treturn lang === 'en' ? 'No news found' : 'Aucune nouvelle trouv\u00e9e';\n\t\t\t\t} else if (path.includes('\/communiques-de-presse') || path.includes('\/press-releases')) {\n\t\t\t\t\treturn lang === 'en' ? 'No press release found' : 'Aucun communiqu\u00e9 de presse trouv\u00e9';\n\t\t\t\t} else if (path.includes('\/rapports') || path.includes('\/reports')) {\n\t\t\t\t\treturn lang === 'en' ? 'No report found' : 'Aucun rapport trouv\u00e9';\n\t\t\t\t} else if (path.includes('\/valorisations') || path.includes('\/valuation')) {\n\t\t\t\t\treturn lang === 'en' ? 'No valuation found' : 'Aucune valorisation trouv\u00e9e';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\/\/ Pas de fallback voulu\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\t\/\/ Libell\u00e9s dynamiques\n\t\t\tconst LABELS = {\n\t\t\t\tlearnMore: lang === 'en' ? 'Learn more' : 'En savoir plus',\n\t\t\t\tnoImage:   lang === 'en' ? 'No image'   : 'Aucune image',\n\t\t\t\tnoContent: getNoContentMessage(),\n\t\t\t};\n\n\t\t\t\/\/ Utils\n\t\t\tfunction normalize(str) {\n\t\t\t\treturn (str || \"\").toString().normalize(\"NFD\").replace(\/[\\u0300-\\u036f]\/g, \"\").toLowerCase();\n\t\t\t}\n\n\t\t\t\/\/ Format date selon langue : \"16 avril 2026\" (FR) ou \"April 16 2026\" (EN). Si ville\/info avant : \", \"\n\t\t\tfunction formatDateFull(iso) {\n\t\t\t\tconst d = new Date(iso);\n\t\t\t\tif (lang === 'en') {\n\t\t\t\t\tconst m = d.toLocaleString('en-US', { month: 'long' });\n\t\t\t\t\treturn `${m} ${String(d.getDate()).padStart(2, '0')} ${d.getFullYear()}`;\n\t\t\t\t}\n\t\t\t\treturn d.toLocaleDateString(\"fr-FR\", { day: \"2-digit\", month: \"long\", year: \"numeric\" });\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e9rer cat\u00e9gories (exclut uncategorized id=1\/84)\n\t\t\tfunction getPostCategories(post) {\n\t\t\t\t\/\/ Si _embedded pr\u00e9sent\n\t\t\t\tif (post._embedded && post._embedded['wp:term']) {\n\t\t\t\t\tconst out = [];\n\t\t\t\t\tpost._embedded['wp:term'].forEach(group => {\n\t\t\t\t\t\tgroup.forEach(term => {\n\t\t\t\t\t\t\tif (term.taxonomy === 'category' && term.id !== 1 && term.id !== 84) {\n\t\t\t\t\t\t\t\tout.push(term.name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t\treturn Promise.resolve(out);\n\t\t\t\t}\n\t\t\t\t\/\/ Fallback: fetch single avec _embed\n\t\t\t\treturn fetch(`\/wp-json\/wp\/v2\/${cpt}\/${post.id}?lang=${lang}&acf_format=standard&_embed=wp:term`)\n\t\t\t\t\t.then(r => r.ok ? r.json() : null)\n\t\t\t\t\t.then(fp => {\n\t\t\t\t\t\tif (!fp || !fp._embedded || !fp._embedded['wp:term']) return [];\n\t\t\t\t\t\tconst out = [];\n\t\t\t\t\t\tfp._embedded['wp:term'].forEach(group => {\n\t\t\t\t\t\t\tgroup.forEach(term => {\n\t\t\t\t\t\t\t\tif (term.taxonomy === 'category' && term.id !== 1 && term.id !== 84) {\n\t\t\t\t\t\t\t\t\tout.push(term.name);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn out;\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => []);\n\t\t\t}\n\n\/\/ V\u00e9rifier si le post a le tag \"a-la-une\" (id=33) ou \"headlines\" (id=52)\nfunction hasALaUneTag(post) {\n\t\/\/ 1) Champ natif 'tags' si pr\u00e9sent (plus fiable et l\u00e9ger)\n\tif (Array.isArray(post.tags) && post.tags.length) {\n\t\treturn post.tags.includes(33) || post.tags.includes(52);\n\t}\n\t\/\/ 2) Fallback via _embedded wp:term\n\tif (post._embedded && post._embedded['wp:term']) {\n\t\tfor (const group of post._embedded['wp:term']) {\n\t\t\tfor (const term of group) {\n\t\t\t\tif (term.taxonomy === 'post_tag' && (term.id === 33 || term.id === 52)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n\t\t\tfunction getPostVille(post) {\n\t\t\t\tconst acf = post.acf || {};\n\t\t\t\tconst ville = acf.lieu_de_levenement || acf.ville_de_levenement || \"\";\n\t\t\t\tif (!ville) return \"\";\n\t\t\t\tconst clean = ville.endsWith(',') ? ville.slice(0,-1) : ville;\n\t\t\t\treturn clean.trim() ? (clean + (lang === 'en' ? ' ' : ' ')) : \"\";\n\t\t\t}\n\n\t\t\tfunction getPostDate(post) {\n\t\t\t\tif (post.acf && post.acf.date_devenement) {\n\t\t\t\t\tconst raw = post.acf.date_devenement;\n\t\t\t\t\tif (typeof raw === 'string' && raw.match(\/^\\\\d{8}$\/)) {\n\t\t\t\t\t\tconst y = raw.substring(0,4), m = raw.substring(4,6), d = raw.substring(6,8);\n\t\t\t\t\t\tconst dt = new Date(y, m-1, d);\n\t\t\t\t\t\treturn isNaN(dt.getTime()) ? formatDateFull(post.date) : formatDateFull(dt.toISOString());\n\t\t\t\t\t}\n\t\t\t\t\tconst dt = new Date(raw);\n\t\t\t\t\treturn isNaN(dt.getTime()) ? formatDateFull(post.date) : formatDateFull(dt.toISOString());\n\t\t\t\t}\n\t\t\t\treturn formatDateFull(post.date);\n\t\t\t}\n\n\t\t\tfunction getPostNomPrenom(post) {\n\t\t\t\treturn (post.acf && post.acf.nom_prenom) ? post.acf.nom_prenom : \"\";\n\t\t\t}\n\n\t\t\t\/\/ Fonctions pour r\u00e9cup\u00e9rer les champs ACF sp\u00e9cifiques aux publications\n\t\t\tfunction getPostACF(post, fieldName) {\n\t\t\t\treturn (post.acf && post.acf[fieldName]) ? post.acf[fieldName] : \"\";\n\t\t\t}\n\n\t\t\tasync function getPostACFTranslated(post, fieldName) {\n\t\t\t\tif (!post.acf || !post.acf[fieldName]) return \"\";\n\t\t\t\tconst field = post.acf[fieldName];\n\t\t\t\tif (typeof field === 'string') return field;\n\t\t\t\tif (typeof field === 'object' && field[lang]) return field[lang];\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\tfunction getLang() {\n\t\t\t\treturn lang;\n\t\t\t}\n\n\t\t\tfunction getPostImage(post) {\n\t\t\t\tif (post._embedded && post._embedded[\"wp:featuredmedia\"] && post._embedded[\"wp:featuredmedia\"][0]) {\n\t\t\t\t\tconst media = post._embedded[\"wp:featuredmedia\"][0];\n\t\t\t\t\treturn Promise.resolve(media.source_url || media.guid?.rendered || media.url || \"\");\n\t\t\t\t}\n\t\t\t\tif (post.featured_media) {\n\t\t\t\t\treturn fetch(`\/wp-json\/wp\/v2\/media\/${post.featured_media}?_cb=${Date.now()}`)\n\t\t\t\t\t\t.then(r => r.ok ? r.json() : null)\n\t\t\t\t\t\t.then(m => (m && (m.source_url || \"\")) || \"\")\n\t\t\t\t\t\t.catch(() => \"\");\n\t\t\t\t}\n\t\t\t\treturn Promise.resolve(\"\");\n\t\t\t}\n\n\t\t\tasync function makeCardHTML(p, totalCards = 1) {\n\t\t\t\tconst [img, categories] = await Promise.all([ getPostImage(p), getPostCategories(p) ]);\n\t\t\t\tconst ville = getPostVille(p);\n\t\t\t\tconst dateLabel = getPostDate(p);\n\t\t\t\tconst nomPrenom = getPostNomPrenom(p);\n\n\t\t\t\t\/\/ D\u00e9tecter si c'est une page de publications\n\t\t\t\tconst isPublications = window.location.pathname.includes('\/publications') || \n\t\t\t\t\twindow.location.pathname.includes('\/en\/publications');\n\t\t\t\t\n\t\t\t\t\/\/ R\u00e9cup\u00e9rer les champs ACF sp\u00e9cifiques aux publications\n\t\t\t\tlet namePublieur = '';\n\t\t\t\tlet entreprise = '';\n\t\t\t\tlet roleDuPublieur = '';\n\t\t\t\t\n\t\t\t\tif (isPublications) {\n\t\t\t\t\tconst currentLang = getLang();\n\t\t\t\t\t\n\t\t\t\t\t\/\/ R\u00e9cup\u00e9rer les champs ACF pour les publications (version synchrone)\n\t\t\t\t\tnamePublieur = currentLang === 'en' ? \n\t\t\t\t\t\t(getPostACF(p, 'name-publieur') || getPostACF(p, 'name_publieur') || getPostACF(p, 'nom-publieur') || getPostACF(p, 'nom_publieur')) : \n\t\t\t\t\t\t(getPostACF(p, 'name-publieur') || getPostACF(p, 'name_publieur') || getPostACF(p, 'nom-publieur') || getPostACF(p, 'nom_publieur'));\n\t\t\t\t\t\t\n\t\t\t\t\tentreprise = currentLang === 'en' ? \n\t\t\t\t\t\t(getPostACF(p, 'entreprise') || getPostACF(p, 'company') || getPostACF(p, 'societe')) : \n\t\t\t\t\t\t(getPostACF(p, 'entreprise') || getPostACF(p, 'company') || getPostACF(p, 'societe'));\n\t\t\t\t\t\t\n\t\t\t\t\troleDuPublieur = currentLang === 'en' ? \n\t\t\t\t\t\t(getPostACF(p, 'role-du-publieur') || getPostACF(p, 'role_du_publieur') || getPostACF(p, 'role-publieur') || getPostACF(p, 'role_publieur') || getPostACF(p, 'poste')) : \n\t\t\t\t\t\t(getPostACF(p, 'role-du-publieur') || getPostACF(p, 'role_du_publieur') || getPostACF(p, 'role-publieur') || getPostACF(p, 'role_publieur') || getPostACF(p, 'poste'));\n\t\t\t\t}\n\n\t\t\t\tconst cats = categories.filter(c => {\n\t\t\t\t\tconst t = (c||'').toLowerCase();\n\t\t\t\t\treturn !(t.includes('uncategorized') || t.includes('non cat\u00e9goris\u00e9') || t.includes('non categorise'));\n\t\t\t\t});\n\t\t\t\tconst categoriesHTML = cats.length\n\t\t\t\t\t? `<div style=\"display:flex; gap:8px; flex-wrap:wrap;\" class=\"acf-categories\">${cats.map(cat => `<span class=\"acf-category\">${cat}<\/span>`).join(\"\")}<\/div>`\n\t\t\t\t\t: \"\";\n\n\t\t\t\tconst nomPrenomHTML = nomPrenom ? `<div class=\"acf-nom-prenom\">${nomPrenom}<\/div>` : \"\";\n\t\t\t\t\n\t\t\t\t\/\/ HTML sp\u00e9cifique pour les publications\n\t\t\t\tif (isPublications) {\n\t\t\t\t\t\/\/ HTML des informations publieur\n\t\t\t\t\tconst publieurHTML = namePublieur ? `\n\t\t\t\t\t\t<div class=\"acf-publieur-info\">\n\t\t\t\t\t\t\t<div class=\"acf-name-publieur\">${namePublieur}<\/div>\n\t\t\t\t\t\t\t<div class=\"acf-entreprise-role\">\n\t\t\t\t\t\t\t\t${entreprise ? `<div class=\"acf-entreprise\">${entreprise}<\/div>` : ''}\n\t\t\t\t\t\t\t\t${roleDuPublieur ? `<div class=\"acf-role-publieur\">${roleDuPublieur}<\/div>` : ''}\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t` : '';\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Gestion de l'excerpt pour les publications\n\t\t\t\t\tlet excerptText = p.excerpt?.rendered || \"\";\n\t\t\t\t\tlet excerptHTML = '';\n\t\t\t\t\t\n\t\t\t\t\t\/\/ V\u00e9rifier si on a un excerpt valide\n\t\t\t\t\tconst tempDiv = document.createElement('div');\n\t\t\t\t\ttempDiv.innerHTML = excerptText;\n\t\t\t\t\tconst cleanText = tempDiv.textContent || tempDiv.innerText || '';\n\t\t\t\t\tconst hasValidExcerpt = cleanText.trim().length > 0;\n\t\t\t\t\t\n\t\t\t\t\tif (hasValidExcerpt) {\n\t\t\t\t\t\t\/\/ Limitation de l'excerpt UNIQUEMENT pour les pages de publications\n\t\t\t\t\t\tif (isPublications) {\n\t\t\t\t\t\t\t\/\/ D\u00e9terminer la limite selon le nombre de cards et la pr\u00e9sence d'image\n\t\t\t\t\t\t\tlet characterLimit = 0;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (img) {\n\t\t\t\t\t\t\t\t\/\/ Avec image : limiter selon le nombre de cards\n\t\t\t\t\t\t\t\tif (totalCards === 1) {\n\t\t\t\t\t\t\t\t\tcharacterLimit = 206;\n\t\t\t\t\t\t\t\t} else if (totalCards === 2) {\n\t\t\t\t\t\t\t\t\tcharacterLimit = 186;\n\t\t\t\t\t\t\t\t} else if (totalCards === 3) {\n\t\t\t\t\t\t\t\t\tcharacterLimit = 166;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcharacterLimit = 166; \/\/ Par d\u00e9faut pour 3+ cards\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\/\/ Sans image : afficher tout l'excerpt\n\t\t\t\t\t\t\t\tcharacterLimit = cleanText.length;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\/\/ Appliquer la limite\n\t\t\t\t\t\t\tif (cleanText.length > characterLimit) {\n\t\t\t\t\t\t\t\texcerptText = cleanText.substring(0, characterLimit) + '...';\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\texcerptText = cleanText;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\/\/ Pour les autres pages : excerpt complet\n\t\t\t\t\t\t\texcerptText = cleanText;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\texcerptHTML = `<div class=\"acf-excerpt\">${excerptText}<\/div>`;\n\t\t\t\t\t}\n\n\t\t\t\t\t\/\/ Si page publications et PAS d'excerpt, forcer la hauteur 100% sur l'image et son conteneur\n\t\t\t\t\tlet imageContainerStyle = '';\n\t\t\t\t\tlet imgStyle = '';\n\t\t\t\t\tif (isPublications && !hasValidExcerpt && img) {\n\t\t\t\t\t\timageContainerStyle = ' style=\"height:100% !important;\"';\n\t\t\t\t\t\timgStyle = ' style=\"height:100% !important;width:100%;object-fit:cover;\"';\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Classe pour masquer le conteneur d'image si pas d'image\n\t\t\t\t\tconst imageContainerClass = img ? 'acf-img-container' : 'acf-img-container acf-no-image';\n\t\t\t\t\t\n\t\t\t\t\tconst villeHTML = ville ? `<div class=\"acf-ville\">${ville}<\/div>` : '';\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Structure diff\u00e9rente selon le nombre de cards\n\t\t\t\t\tif (totalCards === 1) {\n\t\t\t\t\t\t\/\/ 1 card : structure sp\u00e9ciale avec titre et publieur group\u00e9s\n\t\t\t\t\t\t\tconst finalHTML = `\n\t\t\t\t\t\t\t<div class=\"acf-card-wrapper\">\n\t\t\t\t\t\t\t\t<div class=\"acf-card\" data-post-id=\"${p.id}\" onclick=\"window.location.href='${p.link}'\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"${imageContainerClass}\"${imageContainerStyle}>\n\t\t\t\t\t\t\t\t\t\t\t${img ? `<img class=\\\"acf-img\\\" src=\\\"${img}\\\" alt=\\\"${p.title?.rendered || ''}\\\"${imgStyle}>` : ''}\n\t\t\t\t\t\t\t\t\t\t${nomPrenomHTML}\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<div class=\"acf-body\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-date-title-excerpt\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"acf-date\">${ville ? ville.trim() + ', ' : ''}${dateLabel}<\/div>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"acf-title-publieur-group\">\n\t\t\t\t\t\t\t\t\t\t\t\t<h3 class=\"acf-title\">${p.title?.rendered || \"\"}<\/h3>\n\t\t\t\t\t\t\t\t\t\t\t\t${publieurHTML}\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t${categoriesHTML}\n\t\t\t\t\t\t\t\t\t\t\t${excerptHTML}\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-plus\" data-post-id=\"${p.id}\">...<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t`;\n\t\t\t\t\t\treturn finalHTML;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t\/\/ 2+ cards : structure standard comme dans \"ici\"\n\t\t\t\t\t\t\tconst finalHTML = `\n\t\t\t\t\t\t\t<div class=\"acf-card-wrapper\">\n\t\t\t\t\t\t\t\t<div class=\"acf-card\" data-post-id=\"${p.id}\" onclick=\"window.location.href='${p.link}'\">\n\t\t\t\t\t\t\t\t\t<div class=\"acf-body\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-header-group\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"acf-title\">${p.title?.rendered || \"\"}<\/div>\n\t\t\t\t\t\t\t\t\t\t\t${publieurHTML}\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"${imageContainerClass}\"${imageContainerStyle}>\n\t\t\t\t\t\t\t\t\t\t\t\t${img ? `<img class=\\\"acf-img\\\" src=\\\"${img}\\\" alt=\\\"${p.title?.rendered || ''}\\\"${imgStyle}>` : ''}\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-content-group\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"acf-ville-date\">\n\t\t\t\t\t\t\t\t\t\t\t\t${villeHTML}\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"acf-date\">${dateLabel}<\/div>\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t${categoriesHTML}\n\t\t\t\t\t\t\t\t\t\t\t${excerptHTML}\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-plus-holder\" data-post-id=\"${p.id}\">\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"acf-plus\" data-post-id=\"${p.id}\">...<\/div>\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t`;\n\t\t\t\t\t\treturn finalHTML;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t\/\/ HTML standard pour les autres types de contenu\n\t\t\t\tconst imageHTML = img\n\t\t\t\t\t? `<img decoding=\"async\" class=\"acf-img\" src=\"${img}\" alt=\"\">`\n\t\t\t\t\t: `<div class=\"acf-img-placeholder\" style=\"width: 100%; height: 170px; background: #E0E0E0; display: flex; align-items: center; justify-content: center; border-radius: 12px 12px 0 0; color: #999;\">${LABELS.noImage}<\/div>`;\n\n\t\t\t\treturn `\n\t\t\t\t\t<div class=\"acf-card-wrapper\">\n\t\t\t\t\t\t<a href=\"${p.link}\" class=\"acf-card\">\n\t\t\t\t\t\t\t<div class=\"acf-img-container\">\n\t\t\t\t\t\t\t\t${imageHTML}\n\t\t\t\t\t\t\t\t${nomPrenomHTML}\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"acf-body\">\n\t\t\t\t\t\t\t\t<div class=\"acf-date-title-excerpt\">\n\t\t\t\t\t\t\t\t\t<div class=\"acf-date\">${ville ? ville.trim() + ', ' : ''}${dateLabel}<\/div>\n\t\t\t\t\t\t\t\t\t${categoriesHTML}\n\t\t\t\t\t\t\t\t\t<h3 class=\"acf-title\">${p.title.rendered}<\/h3>\n\t\t\t\t\t\t\t\t\t<p class=\"acf-excerpt\">${p.excerpt.rendered}<\/p>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"acf-plus\" data-post-id=\"${p.id}\">...<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/a>\n\t\t\t\t\t<\/div>\n\t\t\t\t`;\n\t\t\t}\n\n\t\t\t\/\/ Fetch posts (bilingue, limite, embed, ACF standard) + filtre tag c\u00f4t\u00e9 API\nasync function fetchPosts() {\n\ttry {\n\t\tconst TAG_ID = (lang === 'en') ? 52 : 33; \/\/ EN=headlines(52) \/ FR=a-la-une(33)\n\t\tconst url =\n\t\t\t`\/wp-json\/wp\/v2\/${cpt}` +\n\t\t\t`?lang=${lang}` +\n\t\t\t`&per_page=100` +\n\t\t\t`&acf_format=standard` +\n\t\t\t`&_embed=wp:featuredmedia,wp:term` +\n\t\t\t`&tags=${TAG_ID}` + \/\/ filtre serveur \"\u00e0 la une\"\n\t\t\t`&_fields=id,title,excerpt,link,date,acf,featured_media,_embedded,tags` + \/\/ inclure 'tags'\n\t\t\t`&_cb=${Date.now()}`;\n\n\t\tconst response = await fetch(url, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } });\n\t\tif (!response.ok) return [];\n\n\t\tconst posts = await response.json();\n\n\t\t\/\/ Fallback s\u00e9curit\u00e9 au cas o\u00f9 le filtre serveur serait inop\u00e9rant\n\t\tconst aLaUneOnly = posts.filter(p => hasALaUneTag(p));\n\n\t\t\/\/ Exclure les posts dont toutes les cat\u00e9gories sont uncategorized\n\t\treturn aLaUneOnly.filter(p => {\n\t\t\tconst groups = (p._embedded && p._embedded['wp:term']) ? p._embedded['wp:term'] : [];\n\t\t\tlet hasValid = false;\n\t\t\tgroups.forEach(g => g.forEach(t => {\n\t\t\t\tif (t.taxonomy === 'category' && t.id !== 1 && t.id !== 84) hasValid = true;\n\t\t\t}));\n\t\t\treturn hasValid || !groups.length;\n\t\t});\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n\t\t\tfunction destroySwiper() { if (swiper) { swiper.destroy(true,true); swiper = null; } }\n\n\t\t\t\/\/ Version sp\u00e9ciale de hydrateDynamicButtons pour les publications\n\t\t\tasync function hydrateDynamicButtonsForPublications(container) {\n\t\t\t\tconst buttons = container.querySelectorAll('.acf-plus[data-post-id]');\n\t\t\t\t\n\t\t\t\tfor (const btn of buttons) {\n\t\t\t\t\tconst postId = btn.dataset.postId;\n\t\t\t\t\tif (!postId) continue;\n\t\t\t\t\t\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst fd = new FormData();\n\t\t\t\t\t\tfd.append('action', 'get_button_plus_dynamique');\n\t\t\t\t\t\tfd.append('post_id', postId);\n\t\t\t\t\t\tfd.append('text', '');\n\t\t\t\t\t\tfd.append('custom_class', 'acf-plus');\n\t\t\t\t\t\tfd.append('lang', getLang());\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst resp = await fetch('\/wp-admin\/admin-ajax.php', { \n\t\t\t\t\t\t\tmethod: 'POST', \n\t\t\t\t\t\t\tbody: fd, \n\t\t\t\t\t\t\tcredentials: 'same-origin', \n\t\t\t\t\t\t\tcache: 'no-store', \n\t\t\t\t\t\t\theaders: { 'Cache-Control': 'no-cache' } \n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (resp.ok) {\n\t\t\t\t\t\t\tconst plusHTML = await resp.text();\n\t\t\t\t\t\t\tif (plusHTML && plusHTML.trim() !== '' && plusHTML.includes('button-plus-dynamique')) {\n\t\t\t\t\t\t\t\tbtn.outerHTML = plusHTML;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\/\/ Fallback si pas de r\u00e9ponse valide\n\t\t\t\t\t\t\t\tconst buttonText = getLang() === 'en' ? 'Learn more' : 'En savoir plus';\n\t\t\t\t\t\t\t\tbtn.outerHTML = `\n\t\t\t\t\t\t\t\t\t<div class=\"button-plus-dynamique acf-plus\" data-post-id=\"${postId}\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"plus-icon\">\n\t\t\t\t\t\t\t\t\t\t\t<svg width=\"21\" height=\"22\" viewBox=\"0 0 21 22\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n\t\t\t\t\t\t\t\t\t\t\t\t<path d=\"M10.5 1.5V20.5M1 11H20\" stroke=\"#D30C8C\" stroke-width=\"1.56\" stroke-miterlimit=\"10\" stroke-linecap=\"round\"\/>\n\t\t\t\t\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t<div class=\"text-arrow\">\n\t\t\t\t\t\t\t\t\t\t\t<span>${buttonText}<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<svg width=\"14\" height=\"13\" viewBox=\"0 0 14 13\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n\t\t\t\t\t\t\t\t\t\t\t\t<path d=\"M13.6998 6.80031L8.49413 12.0059C8.41448 12.0856 8.30645 12.1303 8.19381 12.1303C8.08116 12.1303 7.97313 12.0856 7.89348 12.0059C7.81383 11.9263 7.76908 11.8183 7.76908 11.7056C7.76908 11.593 7.81383 11.4849 7.89348 11.4053L12.3743 6.92445L0.585584 6.92445C0.475604 6.92057 0.371424 6.87415 0.294992 6.79497C0.218561 6.71579 0.175845 6.61004 0.175845 6.49999C0.175845 6.38994 0.218561 6.28419 0.294992 6.20501C0.371424 6.12583 0.475605 6.07941 0.585586 6.07553L12.3743 6.07553L7.89348 1.59469C7.81383 1.51504 7.76908 1.40701 7.76908 1.29436C7.76908 1.18172 7.81383 1.07369 7.89348 0.99404C7.97313 0.914389 8.08116 0.869641 8.19381 0.869641C8.30645 0.869641 8.41448 0.914389 8.49413 0.99404L13.6998 6.19967C13.7794 6.27932 13.8242 6.38735 13.8242 6.49999C13.8242 6.61263 13.7794 6.72066 13.6998 6.80031Z\" fill=\"#D30C8C\"\/>\n\t\t\t\t\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tasync function renderGrid(posts) {\n\t\t\t\tswiperContainer.style.display = \"none\";\n\t\t\t\tgridEl.style.display = \"grid\";\n\t\t\t\t\n\t\t\t\tconst totalCards = posts.length;\n\t\t\t\tconst cardsHTML = await Promise.all(posts.map(p => makeCardHTML(p, totalCards)));\n\t\t\t\tconst finalHTML = cardsHTML.join(\"\");\n\t\t\t\t\n\t\t\t\tgridEl.innerHTML = finalHTML;\n\n\t\t\t\tgridEl.className = \"acf-a-la-une-grid\";\n\t\t\t\t\n\t\t\t\t\/\/ Logique sp\u00e9ciale UNIQUEMENT pour les pages de publications\n\t\t\t\tconst isPublications = window.location.pathname.includes('\/publications') || \n\t\t\t\t\twindow.location.pathname.includes('\/en\/publications');\n\t\t\t\t\n\t\t\t\tif (isPublications) {\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Debug du carrousel - essayer plusieurs fois\n\t\t\t\t\tconst debugSwiper = () => {\n\t\t\t\t\t\tconst swiperContainer = app.querySelector('.acf-a-la-une-swiper');\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (swiperContainer) {\n\t\t\t\t\t\t\tconst cards = swiperContainer.querySelectorAll('.acf-card');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (cards.length > 0) {\n\t\t\t\t\t\t\t\tconst firstCard = cards[0];\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tconst imgContainer = firstCard.querySelector('.acf-img-container');\n\t\t\t\t\t\t\t\tif (imgContainer) {\n\t\t\t\t\t\t\t\t\t\/\/ Image container exists\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tconst body = firstCard.querySelector('.acf-body');\n\t\t\t\t\t\t\t\tif (body) {\n\t\t\t\t\t\t\t\t\t\/\/ Body exists\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Essayer plusieurs fois avec des d\u00e9lais diff\u00e9rents\n\t\t\t\t\tsetTimeout(debugSwiper, 1000);\n\t\t\t\t\tsetTimeout(debugSwiper, 3000);\n\t\t\t\t\tsetTimeout(debugSwiper, 5000);\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Debug suppl\u00e9mentaire pour v\u00e9rifier si le carrousel existe\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tconst allElements = app.querySelectorAll('*');\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst swiperElements = app.querySelectorAll('[class*=\"swiper\"]');\n\t\t\t\t\t\tswiperElements.forEach((el, index) => {\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst cardElements = app.querySelectorAll('.acf-card');\n\t\t\t\t\t\tcardElements.forEach((el, index) => {\n\t\t\t\t\t\t});\n\t\t\t\t\t}, 2000);\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Debug final pour v\u00e9rifier l'\u00e9tat complet\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst grid = app.querySelector('.acf-a-la-une-grid');\n\t\t\t\t\t\tif (grid) {\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst swiper = app.querySelector('.acf-a-la-une-swiper');\n\t\t\t\t\t\tif (swiper) {\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 4000);\n\t\t\t\t\t\n\t\t\t\t\tconst totalCards = posts.length;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Debug: v\u00e9rifier les posts et leurs images\n\t\t\t\t\t\n\t\t\t\t\tconst cardsWithImages = posts.filter(p => p.featured_media && p.featured_media > 0).length;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Debug suppl\u00e9mentaire pour v\u00e9rifier la d\u00e9tection des images\n\t\t\t\t\tconst cardsWithoutImages = totalCards - cardsWithImages;\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Ajouter des classes CSS selon le nombre de cards et la pr\u00e9sence d'images\n\t\t\t\t\tif (totalCards === 1 && cardsWithImages === 1) {\n\t\t\t\t\t\t\/\/ 1 card avec image : layout horizontal sur desktop\/tablette, vertical sur mobile\n\t\t\t\t\t\tgridEl.classList.add(\"one-card\", \"with-image\");\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Les styles CSS s'appliquent automatiquement via les classes\n\t\t\t\t\t} else if (totalCards === 1 && cardsWithoutImages === 1) {\n\t\t\t\t\t\t\/\/ 1 card sans image : layout vertical avec hauteur min\n\t\t\t\t\t\tgridEl.classList.add(\"one-card\", \"without-image\");\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Appliquer les styles inline pour forcer l'application\n\t\t\t\t\t\tconst card = gridEl.querySelector('.acf-card');\n\t\t\t\t\t\tif (card) {\n\t\t\t\t\t\t\tcard.style.minHeight = '200px';\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (totalCards === 2) {\n\t\t\t\t\t\t\/\/ 2 cards : layout grille standard\n\t\t\t\t\t\tgridEl.classList.add(\"two-cards\");\n\t\t\t\t\t\tgridEl.style.gridTemplateColumns = 'repeat(2, 1fr)';\n\t\t\t\t\t} else if (totalCards === 3) {\n\t\t\t\t\t\t\/\/ 3 cards : layout grille standard\n\t\t\t\t\t\tgridEl.classList.add(\"three-cards\");\n\t\t\t\t\t\tgridEl.style.gridTemplateColumns = 'repeat(3, 1fr)';\n\t\t\t\t\t} else {\n\t\t\t\t\t\t\/\/ Plus de 3 cards : layout grille standard\n\t\t\t\t\t\tgridEl.classList.add(\"multiple-cards\");\n\t\t\t\t\t\tgridEl.style.gridTemplateColumns = 'repeat(3, 1fr)';\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t\/\/ Logique ORIGINALE pour toutes les autres pages (inchang\u00e9e)\n\t\t\t\t\tif (posts.length === 1) gridEl.classList.add(\"one-card\");\n\t\t\t\t\telse if (posts.length === 2) gridEl.classList.add(\"two-cards\");\n\t\t\t\t\telse if (posts.length === 3) gridEl.classList.add(\"three-cards\");\n\t\t\t\t}\n\n\t\t\t\t\/\/ Ex\u00e9cuter hydrateDynamicButtons pour toutes les pages\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (isPublications) {\n\t\t\t\t\t\t\/\/ Version sp\u00e9ciale pour les publications qui ne remplace pas le contenu\n\t\t\t\t\t\thydrateDynamicButtonsForPublications(gridEl);\n\t\t\t\t\t} else {\n\t\t\t\t\t\thydrateDynamicButtons(gridEl);\n\t\t\t\t\t}\n\t\t\t\t}, 50);\n\t\t\t}\n\n\t\t\tasync function renderSwiper(posts, variantClass) {\n\t\t\t\tgridEl.style.display = \"none\";\n\t\t\t\tgridEl.innerHTML = \"\";\n\t\t\t\tdestroySwiper();\n\t\t\t\tswiperContainer.style.display = \"block\";\n\t\t\t\tswiperContainer.className = \"acf-a-la-une-swiper swiper\";\n\t\t\t\tif (variantClass) swiperContainer.classList.add(variantClass);\n\t\t\t\t\n\t\t\t\t\/\/ V\u00e9rifier si c'est une page de publications\n\t\t\t\tconst isPublications = window.location.pathname.includes('\/publications') || \n\t\t\t\t\twindow.location.pathname.includes('\/en\/publications');\n\n\t\t\t\tconst totalCards = posts.length;\n\t\t\t\tconst cardsHTML = await Promise.all(posts.map(p => makeCardHTML(p, totalCards)));\n\t\t\t\tswiperWrapper.innerHTML = cardsHTML.map(html => `<div class=\"swiper-slide\">${html}<\/div>`).join(\"\");\n\n\t\t\t\tlet config = {\n\t\t\t\t\tloop:false, freeMode:false, slidesPerView:1, spaceBetween:20, speed:500,\n\t\t\t\t\tcenteredSlides:false, centeredSlidesBounds:false, observer:true, observeParents:true,\n\t\t\t\t\tpagination:{ el: swiperContainer.querySelector('.swiper-pagination'), clickable:true, type:'bullets' }\n\t\t\t\t};\n\t\t\t\tif (variantClass === 'tablet-3') { config.slidesPerView = 2; }\n\t\t\t\tif (variantClass === 'mobile-2' || variantClass === 'mobile-3') { config.slidesPerView = 1; }\n\n\t\t\t\tswiper = new Swiper(swiperContainer, config);\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (swiper) { swiper.update(); swiper.updateSlides(); }\n\t\t\t\t\tsetTimeout(() => hydrateDynamicButtons(swiperContainer), 50);\n\t\t\t\t}, 100);\n\t\t\t}\n\n\t\t\tfunction hydrateDynamicButtons(rootEl) {\n\t\t\t\trootEl.querySelectorAll(\"[data-post-id]\").forEach((container) => {\n\t\t\t\t\tif (container._loaded) return;\n\t\t\t\t\tcontainer._loaded = true;\n\t\t\t\t\tconst postId = container.dataset.postId;\n\t\t\t\t\tconst text = encodeURIComponent(LABELS.learnMore);\n\t\t\t\t\tfetch(\"\/wp-admin\/admin-ajax.php\", {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\theaders: { \"Content-Type\": \"application\/x-www-form-urlencoded\" },\n\t\t\t\t\t\tbody: `action=get_button_plus_dynamique&post_id=${postId}&text=${text}&custom_class=acf-button-plus&lang=${lang}`,\n\t\t\t\t\t})\n\t\t\t\t\t\t.then((r) => r.text())\n\t\t\t\t\t\t.then((html) => {\n\t\t\t\t\t\t\t\/\/ V\u00e9rifier si c'est une page de publications\n\t\t\t\t\t\t\tconst isPublications = window.location.pathname.includes('\/publications') || \n\t\t\t\t\t\t\t\twindow.location.pathname.includes('\/en\/publications');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (isPublications) {\n\t\t\t\t\t\t\t\t\/\/ Pour les publications, remplacer seulement le bouton, pas tout le contenu\n\t\t\t\t\t\t\t\tconst buttonContainer = container.querySelector('.acf-plus, .acf-plus-holder');\n\t\t\t\t\t\t\t\tif (buttonContainer) {\n\t\t\t\t\t\t\t\t\tbuttonContainer.innerHTML = html;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcontainer.innerHTML = html;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\/\/ Pour les autres pages, comportement original\n\t\t\t\t\t\t\t\tcontainer.innerHTML = html;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tconst card = container.closest(\".acf-card\");\n\t\t\t\t\t\t\tconst button = container.querySelector(\".button-plus-dynamique\");\n\t\t\t\t\t\t\tif (card && button) {\n\t\t\t\t\t\t\t\tcard.addEventListener(\"mouseenter\", () => button.classList.add(\"hover\"));\n\t\t\t\t\t\t\t\tcard.addEventListener(\"mouseleave\", () => button.classList.remove(\"hover\"));\n\t\t\t\t\t\t\t\tbutton.style.pointerEvents = \"none\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => { \n\t\t\t\t\t\t\tconst isPublications = window.location.pathname.includes('\/publications') || \n\t\t\t\t\t\t\t\twindow.location.pathname.includes('\/en\/publications');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (isPublications) {\n\t\t\t\t\t\t\t\tconst buttonContainer = container.querySelector('.acf-plus, .acf-plus-holder');\n\t\t\t\t\t\t\t\tif (buttonContainer) {\n\t\t\t\t\t\t\t\t\tbuttonContainer.innerHTML = `<button class=\"fallback-button\">${LABELS.learnMore}<\/button>`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcontainer.innerHTML = `<button class=\"fallback-button\">${LABELS.learnMore}<\/button>`;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcontainer.innerHTML = `<button class=\"fallback-button\">${LABELS.learnMore}<\/button>`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tasync function decideAndRender(posts) {\n\t\t\t\tconst w = window.innerWidth;\n\t\t\t\tif (w >= 1024) return await renderGrid(posts);\n\t\t\t\tif (w >= 768) return (posts.length <= 2) ? await renderGrid(posts) : await renderSwiper(posts, 'tablet-3');\n\t\t\t\treturn (posts.length === 1) ? await renderGrid(posts) : await renderSwiper(posts, posts.length === 2 ? 'mobile-2' : 'mobile-3');\n\t\t\t}\n\n\t\t\tasync function init() {\n\t\t\t\t\/\/ Ajouter la classe pour les styles sp\u00e9cifiques aux publications d\u00e8s le d\u00e9but\n\t\t\t\tconst isPublications = window.location.pathname.includes('\/publications') || \n\t\t\t\t\twindow.location.pathname.includes('\/en\/publications');\n\t\t\t\t\n\t\t\t\tif (isPublications) {\n\t\t\t\t\tapp.classList.add(\"acf-publications-page\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tconst posts = await fetchPosts();\n\t\t\t\tif (posts.length > 0) { await decideAndRender(posts); }\n\t\t\t\telse { gridEl.innerHTML = LABELS.noContent ? `<p>${LABELS.noContent}<\/p>` : ''; }\n\t\t\t}\n\n\t\t\tlet resizeTimeout;\n\t\t\twindow.addEventListener('resize', () => {\n\t\t\t\tclearTimeout(resizeTimeout);\n\t\t\t\tresizeTimeout = setTimeout(async () => {\n\t\t\t\t\tconst posts = await fetchPosts();\n\t\t\t\t\tif (posts.length > 0) { await decideAndRender(posts); }\n\t\t\t\t}, 250);\n\t\t\t});\n\n\t\t\tinit();\n\t\t});\n\t});\n\t<\/script>\n\t\t<div class=\"acf-archive-app\" data-cpt=\"rapport\" data-taxonomy=\"categories\" data-filter-text=\"Subject\" data-lang=\"en\">\n\t\t\n\t\t<!-- Header avec titre + filtres -->\n\t\t<div class=\"acf-archive-header\">\n\t\t\t\t\t\t\t<h2 class=\"acf-archive-title\">All reports and publications<\/h2>\n\t\t\t\t\t\t<div class=\"acf-archive-filters-recherche\">\n\t\t\t\t<div class=\"acf-archive-filters\">\n\t\t\t\t\t<input type=\"text\" class=\"acf-search\" placeholder=\"Search...\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-dropdown acf-region-dropdown\">\n\t\t\t\t\t\t<div class=\"acf-dropdown-trigger\">\n\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">Region<\/span>\n\t\t\t\t\t\t\t<svg class=\"acf-dropdown-arrow\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"11\" height=\"7\" viewBox=\"0 0 11 7\" fill=\"none\">\n\t\t\t\t\t\t\t\t<path d=\"M1 0.857143L5.33333 5.5L10 0.5\" stroke=\"#323332\"\/>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<div class=\"acf-dropdown-menu\">\n\t\t\t\t\t\t\t<div class=\"acf-region-list\">\n\t\t\t\t\t\t\t\t<!-- Les r\u00e9gions seront charg\u00e9es dynamiquement via JavaScript -->\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<div class=\"acf-dropdown acf-sujet-dropdown\">\n\t\t\t\t\t\t<div class=\"acf-dropdown-trigger\">\n\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">Subject<\/span>\n\t\t\t\t\t\t\t<svg class=\"acf-dropdown-arrow\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"11\" height=\"7\" viewBox=\"0 0 11 7\" fill=\"none\">\n\t\t\t\t\t\t\t\t<path d=\"M1 0.857143L5.33333 5.5L10 0.5\" stroke=\"#323332\"\/>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<div class=\"acf-dropdown-menu\">\n\t\t\t\t\t\t\t<div class=\"acf-dropdown-item\" data-value=\"\">\n\t\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">Reset<\/span>\n\t\t\t\t\t\t\t\t<svg class=\"acf-radio\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"15\" height=\"16\" viewBox=\"0 0 15 16\" fill=\"none\">\n\t\t\t\t\t\t\t\t\t<circle cx=\"7.5\" cy=\"8\" r=\"7\" stroke=\"#323332\"\/>\n\t\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<div class=\"acf-dropdown acf-date-dropdown\">\n\t\t\t\t\t\t<div class=\"acf-dropdown-trigger\">\n\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">Date<\/span>\n\t\t\t\t\t\t\t<svg class=\"acf-dropdown-arrow\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"11\" height=\"7\" viewBox=\"0 0 11 7\" fill=\"none\">\n\t\t\t\t\t\t\t\t<path d=\"M1 0.857143L5.33333 5.5L10 0.5\" stroke=\"#323332\"\/>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<div class=\"acf-dropdown-menu\">\n\t\t\t\t\t\t\t<!-- Filtres de dates personnalis\u00e9es -->\n\t\t\t\t\t\t\t<div class=\"acf-date-custom\">\n\t\t\t\t\t\t\t\t<div class=\"acf-date-inputs\">\n\t\t\t\t\t\t\t\t\t<div class=\"acf-date-field\">\n\t\t\t\t\t\t\t\t\t\t<label>From<\/label>\n\t\t\t\t\t\t\t\t\t\t<input type=\"date\" class=\"acf-date-from\" value=\"2026-04-02\">\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<span class=\"acf-date-separator\">-<\/span>\n\t\t\t\t\t\t\t\t\t<div class=\"acf-date-field\">\n\t\t\t\t\t\t\t\t\t\t<label>To<\/label>\n\t\t\t\t\t\t\t\t\t\t<input type=\"date\" class=\"acf-date-to\" value=\"2026-04-09\">\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- Filtres pr\u00e9d\u00e9finis -->\n\t\t\t\t\t\t\t<div class=\"acf-date-presets\">\n\t\t\t\t\t\t\t\t<div class=\"acf-dropdown-item-date\" data-value=\"7\" data-type=\"preset\">\n\t\t\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">New<\/span>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"acf-dropdown-item-date\" data-value=\"30\" data-type=\"preset\">\n\t\t\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">Last month<\/span>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"acf-dropdown-item-date\" data-value=\"364\" data-type=\"preset\">\n\t\t\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">Last year<\/span>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<!-- Boutons d'action -->\n\t\t\t\t\t\t\t<div class=\"acf-date-actions\">\n\t\t\t\t\t\t\t\t<button class=\"acf-date-apply\">Apply<\/button>\n\t\t\t\t\t\t\t\t<button class=\"acf-date-reset\">Reset<\/button>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<button class=\"acf-submit\">Search<\/button>\n\t\t\t<\/div>\n\t\t<\/div>\n\n\t\t<!-- R\u00e9sultats -->\n\t\t<div class=\"acf-archive-list\"><\/div>\n\t\t\n\t\t<!-- Bouton \"Voir plus\" -->\n\t\t<div class=\"acf-load-more-container\" style=\"display: none;\">\n\t\t\t<button class=\"acf-load-more\">See more Reports<\/button>\n\t\t<\/div>\n\t<\/div>\n\n\t<script>\n\t\tdocument.addEventListener(\"DOMContentLoaded\", function () {\n\t\tdocument.querySelectorAll(\".acf-archive-app\").forEach((app) => {\n            \/\/ Publications\/\u00e9v\u00e9nements: g\u00e9r\u00e9s par des composants d\u00e9di\u00e9s\n\t\t\tconst listEl = app.querySelector(\".acf-archive-list\");\n\t\t\t\n\t\t\t\/\/ Variable pour tracker si on est en mode append (d\u00e9clar\u00e9e t\u00f4t pour \u00eatre accessible)\n\t\t\tlet isAppendingMode = false;\n\t\t\t\n\t\t\t\/\/ Intercepter et corriger toute tentative d'\u00e9crire \"Aucun contenu trouv\u00e9\" dans listEl\n\t\t\t\/\/ ET emp\u00eacher le vidage en mode append\n\t\t\tif (listEl) {\n\t\t\t\tconst originalInnerHTML = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML') || \n\t\t\t\t                          Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'innerHTML');\n\t\t\t\t\n\t\t\t\t\/\/ Cr\u00e9er une propri\u00e9t\u00e9 personnalis\u00e9e pour listEl qui filtre le message incorrect\n\t\t\t\t\/\/ et prot\u00e8ge contre le vidage en mode append\n\t\t\t\tObject.defineProperty(listEl, 'innerHTML', {\n\t\t\t\t\tset: function(value) {\n\t\t\t\t\t\t\/\/ PROTECTION: Emp\u00eacher le vidage en mode append\n\t\t\t\t\t\tif (isAppendingMode) {\n\t\t\t\t\t\t\tconst isEmpty = value === '' || (typeof value === 'string' && value.trim() === '');\n\t\t\t\t\t\t\tconst hasChildren = this.children.length > 0;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (isEmpty && hasChildren) {\n\t\t\t\t\t\t\t\treturn; \/\/ Ne pas vider le contenu en mode append\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (typeof value === 'string') {\n\t\t\t\t\t\t\tconst lowerValue = value.toLowerCase();\n\t\t\t\t\t\t\t\/\/ Si le message incorrect est pr\u00e9sent, le remplacer\n\t\t\t\t\t\t\tif (lowerValue.includes('aucun contenu trouv\u00e9') || lowerValue.includes('no content found')) {\n\t\t\t\t\t\t\t\t\/\/ Utiliser getNoResultsMessage si disponible, sinon utiliser une valeur par d\u00e9faut\n\t\t\t\t\t\t\t\tlet correctMessage = '';\n\t\t\t\t\t\t\t\tif (typeof getNoResultsMessage === 'function') {\n\t\t\t\t\t\t\t\t\tcorrectMessage = getNoResultsMessage();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (correctMessage) {\n\t\t\t\t\t\t\t\t\tvalue = value.replace(\/Aucun contenu trouv\u00e9\/gi, correctMessage);\n\t\t\t\t\t\t\t\t\tvalue = value.replace(\/No content found\/gi, correctMessage);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvalue = '';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\/\/ Appliquer la valeur modifi\u00e9e\n\t\t\t\t\t\tlistEl.setHTML ? listEl.setHTML(value) : (originalInnerHTML ? originalInnerHTML.set.call(this, value) : (this.textContent = value));\n\t\t\t\t\t},\n\t\t\t\t\tget: function() {\n\t\t\t\t\t\treturn originalInnerHTML ? originalInnerHTML.get.call(this) : this.textContent;\n\t\t\t\t\t},\n\t\t\t\t\tconfigurable: true\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tconst searchInput = app.querySelector(\".acf-search\");\n\t\t\tconst regionDropdown = app.querySelector(\".acf-region-dropdown\");\n\t\t\tconst sujetDropdown = app.querySelector(\".acf-sujet-dropdown\");\n\t\t\tconst dateDropdown = app.querySelector(\".acf-date-dropdown\");\n\t\t\tconst submitBtn = app.querySelector(\".acf-submit\");\n\t\t\tconst loadMoreContainer = app.querySelector(\".acf-load-more-container\");\n\t\t\tconst loadMoreBtn = app.querySelector(\".acf-load-more\");\n\t\t\tconst cpt = app.dataset.cpt || 'posts';\n\t\t\tlet lang = app.dataset.lang || 'fr';\n\t\t\tconst enableACFFallback = lang !== 'en'; \/\/ \u00e9viter N requ\u00eates lentes en EN\n\t\t\tfunction getLang() {\n\t\t\t\tconst lang = app.dataset.lang || (window.location.pathname.indexOf('\/en') !== -1 ? 'en' : 'fr');\n\t\t\t\treturn lang;\n\t\t\t}\n\n\t\t\t\/\/ Formatage date unifi\u00e9 cards : FR \"16 avril 2026\", EN \"April 16 2026\". Si ville\/info avant : \", \"\n\t\t\tfunction formatPostDate(dateInput, lang = null) {\n\t\t\t\tif (!dateInput || dateInput === '' || dateInput === null) {\n\t\t\t\t\treturn '';\n\t\t\t\t}\n\t\t\t\tif (typeof dateInput === 'string' && dateInput.includes(' ') && !dateInput.includes('T')) {\n\t\t\t\t\treturn dateInput;\n\t\t\t\t}\n\t\t\t\tconst d = new Date(dateInput);\n\t\t\t\tif (isNaN(d.getTime())) {\n\t\t\t\t\treturn '';\n\t\t\t\t}\n\t\t\t\tconst currentLang = lang || getLang();\n\t\t\t\tif (currentLang === 'en') {\n\t\t\t\t\tconst month = d.toLocaleString('en-US', { month: 'long' });\n\t\t\t\t\treturn `${month} ${String(d.getDate()).padStart(2, '0')} ${d.getFullYear()}`;\n\t\t\t\t}\n\t\t\t\treturn d.toLocaleDateString('fr-FR', { day: '2-digit', month: 'long', year: 'numeric' });\n\t\t\t}\n\n            \/\/ Logiques de parsing sp\u00e9cifiques aux \u00e9v\u00e9nements retir\u00e9es\n\n            \/\/ Dates d'\u00e9v\u00e9nements retir\u00e9es: on utilise la date de publication\n            async function getEventDate(post) { return post.date; }\n\t\t\tlet postsFetchController = null;\n\t\t\t\/\/ Corriger le titre si n\u00e9cessaire (au cas o\u00f9 le PHP cache pose probl\u00e8me)\n\t\t\tconst titleEl = app.querySelector('.acf-archive-title');\n\t\t\tif (titleEl && getLang() === 'en') {\n\t\t\t\tconst currentTitle = titleEl.textContent.trim();\n\t\t\t\tconst titleTranslations = {\n\t\t\t\t\t'Toutes les valorisations': 'Every Valuation',\n\t\t\t\t\t'Communiqu\u00e9s de presse': 'Press Releases',\n\t\t\t\t\t'\u00c9v\u00e9nements': 'Events',\n\t\t\t\t\t'Publications': 'Publications',\n\t\t\t\t\t'Rapports': 'Reports'\n\t\t\t\t};\n\t\t\t\tif (titleTranslations[currentTitle]) {\n\t\t\t\t\ttitleEl.textContent = titleTranslations[currentTitle];\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tlet selectedRegion = \"\";\n\t\t\tlet selectedSujet = \"\";\n\t\t\tlet selectedDateFilter = null;\n\t\t\tlet selectedDateFrom = \"\";\n\t\t\tlet selectedDateTo = \"\";\n\t\t\tlet currentPage = 1;\n\t\t\tlet postsPerPage = 6;\n\t\t\tlet allPosts = [];\n\t\t\tlet filteredPosts = [];\n\t\t\tlet currentlyRenderedPosts = []; \/\/ Pour stocker les posts actuellement affich\u00e9s\n\t\t\tlet isAppending = false; \/\/ Flag pour tracker si on est en mode append\n\t\t\tlet shouldStopReapplying = false; \/\/ Flag pour arr\u00eater les reapplyDates d'anciennes instances\n\t\t\tlet cleanupTimeouts = []; \/\/ Pour stocker les timeouts de cleanup et pouvoir les annuler\n\t\t\tlet protectionObservers = []; \/\/ Pour stocker les MutationObservers de protection\n\n\t\t\t\/\/ Fonction pour obtenir le message \"aucun r\u00e9sultat\" selon la page\n\t\t\tfunction getNoResultsMessage() {\n\t\t\t\tconst currentLang = getLang();\n\t\t\t\tconst path = window.location.pathname.toLowerCase();\n\t\t\t\tconst currentCpt = (cpt || app.dataset.cpt || '').toLowerCase();\n\t\t\t\t\n                \/\/ D\u00e9tection de la page selon l'URL ou le CPT (insensible \u00e0 la casse)\n                if (path.includes('\/communiques-de-presse') || path.includes('\/press-releases') || currentCpt === 'communique-de-presse' || currentCpt === 'communiqu\u00e9s-de-presse') {\n\t\t\t\t\treturn currentLang === 'en' ? 'No press release found' : 'Aucun communiqu\u00e9 de presse trouv\u00e9';\n\t\t\t\t} else if (path.includes('\/rapports') || path.includes('\/reports')) {\n\t\t\t\t\treturn currentLang === 'en' ? 'No report found' : 'Aucun rapport trouv\u00e9';\n\t\t\t\t} else if (path.includes('\/valorisations') || path.includes('\/valuation')) {\n\t\t\t\t\treturn currentLang === 'en' ? 'No valuation found' : 'Aucune valorisation trouv\u00e9e';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\/\/ Pas de fallback voulu\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\t\n\t\t\t\/\/ Fonction pour nettoyer et remplacer le message \"Aucun contenu trouv\u00e9\"\n\t\t\tfunction cleanupNoContentMessage() {\n\t\t\t\tif (!listEl) return;\n\t\t\t\t\n\t\t\t\tconst existingText = listEl.textContent.trim().toLowerCase();\n\t\t\t\tconst existingHTML = listEl.innerHTML.trim().toLowerCase();\n\t\t\t\t\n\t\t\t\t\/\/ D\u00e9tection plus large : \"Aucun contenu trouv\u00e9\", \"No content found\", ou variantes\n\t\t\t\tconst hasWrongMessage = existingText.includes('aucun contenu trouv\u00e9') || \n\t\t\t\t                       existingText.includes('no content found') ||\n\t\t\t\t                       existingHTML.includes('aucun contenu trouv\u00e9') ||\n\t\t\t\t                       existingHTML.includes('no content found');\n\t\t\t\t\n\t\t\t\tif (hasWrongMessage) {\n\t\t\t\t\tconst correctMessage = getNoResultsMessage();\n\t\t\t\t\tif (correctMessage) {\n\t\t\t\t\t\t\/\/ V\u00e9rifier que le message correct n'est pas d\u00e9j\u00e0 pr\u00e9sent\n\t\t\t\t\t\tif (!existingText.includes(correctMessage.toLowerCase())) {\n\t\t\t\t\t\t\tlistEl.innerHTML = `<p>${correctMessage}<\/p>`;\n\t\t\t\t\t\t\t\/\/ Emp\u00eacher les scripts externes de le modifier imm\u00e9diatement apr\u00e8s\n\t\t\t\t\t\t\tif (listEl.lastChild && listEl.lastChild.tagName === 'P') {\n\t\t\t\t\t\t\t\tlistEl.lastChild.setAttribute('data-protected', 'true');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlistEl.innerHTML = '';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\/\/ Intercepter innerHTML et textContent AVANT le premier appel de cleanup pour bloquer imm\u00e9diatement\n\t\t\tif (listEl) {\n\t\t\t\ttry {\n\t\t\t\t\tconst listElProto = Object.getPrototypeOf(listEl);\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Intercepter innerHTML\n\t\t\t\t\tconst innerHTMLDescriptor = Object.getOwnPropertyDescriptor(listElProto, 'innerHTML') || \n\t\t\t\t\t                            Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'innerHTML');\n\t\t\t\t\t\n\t\t\t\t\tif (innerHTMLDescriptor && innerHTMLDescriptor.set) {\n\t\t\t\t\t\tconst originalSetInnerHTML = innerHTMLDescriptor.set;\n\t\t\t\t\t\t\n\t\t\t\t\t\tObject.defineProperty(listEl, 'innerHTML', {\n\t\t\t\t\t\t\tset: function(newValue) {\n\t\t\t\t\t\t\t\tif (typeof newValue === 'string') {\n\t\t\t\t\t\t\t\t\tconst lowerValue = newValue.toLowerCase();\n\t\t\t\t\t\t\t\t\tif (lowerValue.includes('aucun contenu trouv\u00e9') || lowerValue.includes('no content found')) {\n\t\t\t\t\t\t\t\t\t\tconst correctMsg = getNoResultsMessage();\n\t\t\t\t\t\t\t\t\t\tif (correctMsg) {\n\t\t\t\t\t\t\t\t\t\t\tnewValue = `<p>${correctMsg}<\/p>`;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tnewValue = '';\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\toriginalSetInnerHTML.call(this, newValue);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tget: function() {\n\t\t\t\t\t\t\t\treturn innerHTMLDescriptor.get ? innerHTMLDescriptor.get.call(this) : this.textContent;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Intercepter aussi textContent au cas o\u00f9\n\t\t\t\t\tconst textContentDescriptor = Object.getOwnPropertyDescriptor(listElProto, 'textContent') || \n\t\t\t\t\t                              Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'textContent');\n\t\t\t\t\t\n\t\t\t\t\tif (textContentDescriptor && textContentDescriptor.set) {\n\t\t\t\t\t\tconst originalSetTextContent = textContentDescriptor.set;\n\t\t\t\t\t\t\n\t\t\t\t\t\tObject.defineProperty(listEl, 'textContent', {\n\t\t\t\t\t\t\tset: function(newValue) {\n\t\t\t\t\t\t\t\tif (typeof newValue === 'string') {\n\t\t\t\t\t\t\t\t\tconst lowerValue = newValue.toLowerCase();\n\t\t\t\t\t\t\t\t\tif (lowerValue.includes('aucun contenu trouv\u00e9') || lowerValue.includes('no content found')) {\n\t\t\t\t\t\t\t\t\t\tconst correctMsg = getNoResultsMessage();\n\t\t\t\t\t\t\t\t\t\tif (correctMsg) {\n\t\t\t\t\t\t\t\t\t\t\t\/\/ Cr\u00e9er un paragraphe avec le bon message\n\t\t\t\t\t\t\t\t\t\t\tconst p = document.createElement('p');\n\t\t\t\t\t\t\t\t\t\t\tp.textContent = correctMsg;\n\t\t\t\t\t\t\t\t\t\t\tthis.innerHTML = '';\n\t\t\t\t\t\t\t\t\t\t\tthis.appendChild(p);\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tnewValue = '';\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\toriginalSetTextContent.call(this, newValue);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tget: function() {\n\t\t\t\t\t\t\t\treturn textContentDescriptor.get ? textContentDescriptor.get.call(this) : '';\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\t\/\/ Silent fail\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\/\/ Nettoyer tout message existant au d\u00e9marrage (pour \u00e9viter les messages de cache ou autres scripts)\n\t\t\tcleanupNoContentMessage();\n\t\t\t\n\t\t\t\/\/ Observer pour surveiller les changements et corriger automatiquement\n\t\t\tconst messageObserver = new MutationObserver((mutations) => {\n\t\t\t\tmutations.forEach((mutation) => {\n\t\t\t\t\tif (mutation.type === 'childList' || mutation.type === 'characterData') {\n\t\t\t\t\t\t\/\/ D\u00e9lai pour laisser le script externe finir avant de corriger\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tcleanupNoContentMessage();\n\t\t\t\t\t\t}, 10);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t\t\n\t\t\tif (listEl) {\n\t\t\t\tmessageObserver.observe(listEl, {\n\t\t\t\t\tchildList: true,\n\t\t\t\t\tsubtree: true,\n\t\t\t\t\tcharacterData: true\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t\/\/ V\u00e9rifier p\u00e9riodiquement (pour capturer les scripts qui se d\u00e9clenchent plus tard)\n\t\t\tconst cleanupInterval = setInterval(() => {\n\t\t\t\tcleanupNoContentMessage();\n\t\t\t}, 200);\n\n\t\t\t\/\/ Utils\n\t\t\tfunction normalize(str) {\n\t\t\t\treturn (str || \"\")\n\t\t\t\t\t.toString()\n\t\t\t\t\t.normalize(\"NFD\")\n\t\t\t\t\t.replace(\/[\\u0300-\\u036f]\/g, \"\")\n\t\t\t\t\t.toLowerCase();\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e9ration des donn\u00e9es ACF\n\t\t\tfunction getPostACF(post, fieldName) {\n\t\t\t\tif (!post.acf || !post.acf[fieldName]) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tconst value = post.acf[fieldName];\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\treturn value[0] || \"\";\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\t\/\/ Normalise une valeur ACF quelconque en cha\u00eene (prend le premier \u00e9l\u00e9ment pertinent)\n\t\t\tfunction toScalarString(value) {\n\t\t\t\tif (value == null) return \"\";\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\treturn toScalarString(value[0]);\n\t\t\t\t}\n\t\t\t\tif (typeof value === 'object') {\n\t\t\t\t\t\/\/ relationship \/ object field support\n\t\t\t\t\tconst candidate = value.post_title || value.title || value.name || value.label || value.value || value.rendered || \"\";\n\t\t\t\t\treturn String(candidate);\n\t\t\t\t}\n\t\t\t\treturn String(value);\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e8re la ville\/region : region (communiqu\u00e9s\/rapports\/valorisations), puis ville_de_levenement, lieu_de_levenement\n\t\t\tfunction getPostCity(post) {\n\t\t\t\tconst r = toScalarString(getPostACF(post, 'region')).trim();\n\t\t\t\tif (r) return r;\n\t\t\t\tconst v1 = toScalarString(getPostACF(post, 'ville_de_levenement')).trim();\n\t\t\t\tif (v1) return v1;\n\t\t\t\tconst v2 = toScalarString(getPostACF(post, 'lieu_de_levenement')).trim();\n\t\t\t\tif (v2) return v2;\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\tconst cityCache = new Map();\n\t\t\tasync function getPostCityCached(post, forceLang = null) {\n\t\t\t\tconst lang = forceLang || getLang();\n\t\t\t\tconst cacheKey = `${post.id}_${lang}`;\n\t\t\t\tif (cityCache.has(cacheKey)) return cityCache.get(cacheKey);\n\t\t\t\t\/\/ Essayer d'abord les donn\u00e9es d\u00e9j\u00e0 pr\u00e9sentes (admin peut avoir acf dans la liste)\n\t\t\t\tconst fromPost = getPostCity(post);\n\t\t\t\tif (fromPost) {\n\t\t\t\t\tcityCache.set(cacheKey, fromPost);\n\t\t\t\t\treturn fromPost;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst ts = Date.now();\n\t\t\t\t\tconst url = `\/wp-json\/wp\/v2\/${cpt}\/${post.id}?lang=${lang}&acf_format=standard&_cb=${ts}`;\n\t\t\t\t\tconst resp = await fetch(url, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' }, credentials: 'same-origin' });\n\t\t\t\t\tif (!resp.ok) {\n\t\t\t\t\t\tcityCache.set(cacheKey, \"\");\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\t\t\t\t\tconst data = await resp.json();\n\t\t\t\t\tconst r = toScalarString(data?.acf?.region ?? \"\").trim();\n\t\t\t\t\tconst v1 = r || toScalarString(data?.acf?.ville_de_levenement ?? \"\").trim();\n\t\t\t\t\tconst ville = v1 || toScalarString(data?.acf?.lieu_de_levenement ?? \"\").trim();\n\t\t\t\t\tcityCache.set(cacheKey, ville);\n\t\t\t\t\treturn ville;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tcityCache.set(cacheKey, \"\");\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e9ration des donn\u00e9es ACF traduites\n\t\t\tasync function getPostACFTranslated(post, fieldName) {\n\t\t\t\t\/\/ Essayer d'abord avec les donn\u00e9es ACF existantes\n\t\t\t\tif (post.acf && post.acf[fieldName]) {\n\t\t\t\t\tconst value = post.acf[fieldName];\n\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\treturn value[0] || \"\";\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tconst currentLang = getLang();\n\t\t\t\t\/\/ Si pas de donn\u00e9es ACF, essayer de r\u00e9cup\u00e9rer via une requ\u00eate s\u00e9par\u00e9e (FR ou EN)\n\t\t\t\ttry {\n\t\t\t\t\tconst ts = Date.now();\n\t\t\t\t\tconst url = `\/wp-json\/wp\/v2\/${cpt}\/${post.id}?lang=${currentLang}&acf_format=standard&_cb=${ts}`;\n\t\t\t\t\tconst response = await fetch(url, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' }, credentials: 'same-origin' });\n\t\t\t\t\tif (response.ok) {\n\t\t\t\t\t\tconst translatedPost = await response.json();\n\t\t\t\t\t\tif (translatedPost.acf && translatedPost.acf[fieldName]) {\n\t\t\t\t\t\t\tconst value = translatedPost.acf[fieldName];\n\t\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\t\treturn value[0] || \"\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e9ration stricte d'un champ ACF via l'endpoint single (utile en visiteur)\n\t\t\tasync function getPostACFStrict(post, fieldName) {\n\t\t\t\ttry {\n\t\t\t\t\tconst ts = Date.now();\n\t\t\t\t\tconst url = `\/wp-json\/wp\/v2\/${cpt}\/${post.id}?lang=${getLang()}&acf_format=standard&_cb=${ts}`;\n\t\t\t\t\tconst resp = await fetch(url, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' }, credentials: 'same-origin' });\n\t\t\t\t\tif (!resp.ok) return \"\";\n\t\t\t\t\tconst data = await resp.json();\n\t\t\t\t\treturn toScalarString(data?.acf?.[fieldName] ?? \"\").trim();\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e8re un champ ACF sous forme de tableau de libell\u00e9s (normalis\u00e9s), selon la langue\n\t\t\tasync function getPostACFValues(post, fieldName, mode = 'auto') {\n\t\t\t\ttry {\n\t\t\t\t\tlet raw = null;\n\t\t\t\t\tconst lang = getLang();\n\t\t\t\t\tif (mode === 'strict' || (mode === 'auto' && lang === 'en')) {\n\t\t\t\t\t\t\/\/ Forcer la langue courante via endpoint single\n\t\t\t\t\t\tconst ts = Date.now();\n\t\t\t\t\t\tconst url = `\/wp-json\/wp\/v2\/${cpt}\/${post.id}?lang=${lang}&acf_format=standard&_cb=${ts}`;\n\t\t\t\t\t\tconst resp = await fetch(url, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' }, credentials: 'same-origin' });\n\t\t\t\t\t\tif (!resp.ok) return [];\n\t\t\t\t\t\tconst data = await resp.json();\n\t\t\t\t\t\traw = data?.acf?.[fieldName] ?? null;\n\t\t\t\t\t} else if (mode === 'translated') {\n\t\t\t\t\t\traw = await getPostACFTranslated(post, fieldName);\n\t\t\t\t\t} else {\n\t\t\t\t\t\traw = getPostACF(post, fieldName);\n\t\t\t\t\t}\n\t\t\t\t\tif (raw == null || raw === '') return [];\n\t\t\t\t\tif (Array.isArray(raw)) {\n\t\t\t\t\t\treturn raw.map(v => toScalarString(v).trim()).filter(Boolean);\n\t\t\t\t\t}\n\t\t\t\t\t\/\/ ACF checkbox peut parfois \u00eatre objet unique\n\t\t\t\t\tif (typeof raw === 'object') {\n\t\t\t\t\t\tconst candidate = toScalarString(raw).trim();\n\t\t\t\t\t\treturn candidate ? [candidate] : [];\n\t\t\t\t\t}\n\t\t\t\t\treturn [toScalarString(raw).trim()].filter(Boolean);\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Traduction batch via admin-ajax + WPML (adapt\u00e9 de ici3)\n\t\t\tasync function translateChoices(fieldName, values) {\n\t\t\t\ttry {\n\t\t\t\t\tif (!Array.isArray(values) || values.length === 0) return [];\n\t\t\t\t\tconst currentLang = getLang();\n\t\t\t\t\tif (currentLang !== 'en') return values;\n\t\t\t\t\t\n\t\t\t\t\tconst fd = new FormData();\n\t\t\t\t\tfd.append('action', 'batch_translate_acf_choices_spectacle');\n\t\t\t\t\tif (fieldName) fd.append('field', fieldName);\n\t\t\t\t\tvalues.forEach(v => fd.append('choices[]', String(v)));\n\t\t\t\t\t\n\t\t\t\t\tconst controller = new AbortController();\n\t\t\t\t\tconst timeoutId = setTimeout(() => controller.abort(), 3000);\n\t\t\t\t\t\n\t\t\t\t\tconst resp = await fetch('\/wp-admin\/admin-ajax.php', { \n\t\t\t\t\t\tmethod: 'POST', \n\t\t\t\t\t\tbody: fd, \n\t\t\t\t\t\tcredentials: 'same-origin',\n\t\t\t\t\t\tsignal: controller.signal\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t\t\n\t\t\t\t\tif (!resp.ok) return values;\n\t\t\t\t\t\n\t\t\t\t\tconst data = await resp.json();\n\t\t\t\t\treturn Array.isArray(data?.translated) ? data.translated : values;\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn Array.isArray(values) ? values : [];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e9ration de l'image\n\t\t\tasync function getPostImage(post) {\n\t\t\t\tif (post.featured_media && !post._embedded) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst ts = Date.now();\n\t\t\t\t\t\tconst mediaUrl = `\/wp-json\/wp\/v2\/media\/${post.featured_media}?_cb=${ts}`;\n\t\t\t\t\t\tconst response = await fetch(mediaUrl, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' }, credentials: 'same-origin' });\n\t\t\t\t\t\tconst media = await response.json();\n\t\t\t\t\t\treturn media.source_url || \"\";\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (post._embedded && post._embedded[\"wp:featuredmedia\"] && post._embedded[\"wp:featuredmedia\"][0]) {\n\t\t\t\t\tconst media = post._embedded[\"wp:featuredmedia\"][0];\n\t\t\t\t\treturn media.source_url || media.guid?.rendered || media.url || \"\";\n\t\t\t\t}\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\t\/\/ R\u00e9cup\u00e9ration des cat\u00e9gories\n\t\t\tasync function getPostCategories(post) {\n\t\t\t\tif (!post.categories || post.categories.length === 0) return [];\n\t\t\t\ttry {\n\t\t\t\t\tconst categoryPromises = post.categories.map(async (catId) => {\n\t\t\t\t\t\t\/\/ Exclure les cat\u00e9gories \"Uncategorized\" (id=1) et \"Non cat\u00e9goris\u00e9\" (id=84)\n\t\t\t\t\t\tif (catId === 1 || catId === 84) return null;\n\t\t\t\t\t\tconst ts = Date.now();\n\t\t\t\t\t\tconst catUrl = `\/wp-json\/wp\/v2\/categories\/${catId}?lang=${getLang()}&_cb=${ts}`;\n\t\t\t\t\t\tconst response = await fetch(catUrl, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' }, credentials: 'same-origin' });\n\t\t\t\t\t\tif (response.ok) {\n\t\t\t\t\t\t\tconst category = await response.json();\n\t\t\t\t\t\t\treturn category.name;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t});\n\t\t\t\t\tconst categoryNames = await Promise.all(categoryPromises);\n\t\t\t\t\treturn categoryNames.filter(name => name !== null);\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Fonction pour v\u00e9rifier si un post a des cat\u00e9gories valides (pas seulement uncategorized)\n\t\t\tfunction hasValidCategories(post) {\n\t\t\t\tif (!post.categories || post.categories.length === 0) return false;\n\t\t\t\t\/\/ V\u00e9rifier s'il y a au moins une cat\u00e9gorie qui n'est pas uncategorized (id=1 ou id=84)\n\t\t\t\treturn post.categories.some(catId => catId !== 1 && catId !== 84);\n\t\t\t}\n\n\t\t\t\/\/ Filtrage des posts\n\t\t\tasync function filterPosts() {\n\t\t\t\tlet results = [...allPosts]; \/\/ allPosts contient d\u00e9j\u00e0 seulement les posts avec des cat\u00e9gories valides\n\t\t\t\tconst q = normalize(searchInput?.value?.trim() || \"\");\n\t\t\t\t\n\t\t\t\tif (q) {\n\t\t\t\t\tresults = results.filter((p) => {\n\t\t\t\t\t\tconst title = normalize(p.title?.rendered || \"\");\n\t\t\t\t\t\tconst excerpt = normalize(p.excerpt?.rendered || \"\");\n\t\t\t\t\t\treturn title.includes(q) || excerpt.includes(q);\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t\/\/ Filtres ACF - utiliser les donn\u00e9es traduites si en anglais\n\t\t\t\tconst currentLang = getLang();\n                const isReports = window.location.pathname.includes('\/reports') || window.location.pathname.includes('\/rapports');\n                const isPressReleases = window.location.pathname.includes('\/communiques-de-presse') || window.location.pathname.includes('\/press-releases') || (cpt === 'communique-de-presse');\n                const isValuations = window.location.pathname.includes('\/valorisations') || window.location.pathname.includes('\/valuation');\n\t\t\t\tif (selectedRegion) {\n\t\t\t\t\tconst filteredResults = [];\n\t\t\t\t\tfor (const p of results) {\n\t\t\t\t\t\t\/\/ R\u00e9cup\u00e9rer toutes les valeurs de r\u00e9gion (checkbox) dans la langue courante\n\t\t\t\t\t\tconst values = await getPostACFValues(p, 'region', 'auto');\n\t\t\t\t\t\tif (values.includes(selectedRegion)) {\n\t\t\t\t\t\t\tfilteredResults.push(p);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tresults = filteredResults;\n\t\t\t\t}\n\t\t\t\tif (selectedSujet) {\n\t\t\t\t\tconst filteredResults = [];\n\t\t\t\t\tfor (const p of results) {\n                        if (isReports) {\n\t\t\t\t\t\t\t\/\/ Sur la page rapports\/reports, utiliser les cat\u00e9gories comme \"Type\"\n\t\t\t\t\t\t\tconst cats = await getPostCategories(p);\n\t\t\t\t\t\t\tif (cats.includes(selectedSujet)) {\n\t\t\t\t\t\t\t\tfilteredResults.push(p);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (isPressReleases) {\n\t\t\t\t\t\t\t\/\/ Sur la page communiqu\u00e9s de presse\/press releases, utiliser les cat\u00e9gories comme \"Sujet\"\n\t\t\t\t\t\t\tconst cats = await getPostCategories(p);\n\t\t\t\t\t\t\tif (cats.includes(selectedSujet)) {\n\t\t\t\t\t\t\t\tfilteredResults.push(p);\n\t\t\t\t\t\t\t}\n                        } else if (isValuations) {\n\t\t\t\t\t\t\t\/\/ Sur la page valorisations\/valuation, utiliser les cat\u00e9gories comme \"Sujet\"\n\t\t\t\t\t\t\tconst cats = await getPostCategories(p);\n\t\t\t\t\t\t\tif (cats.includes(selectedSujet)) {\n\t\t\t\t\t\t\t\tfilteredResults.push(p);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst sujet = currentLang === 'en' ? await getPostACFTranslated(p, 'sujet') : getPostACF(p, 'sujet');\n\t\t\t\t\t\t\tif (sujet === selectedSujet) {\n\t\t\t\t\t\t\t\tfilteredResults.push(p);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tresults = filteredResults;\n\t\t\t\t}\n\n\t\t\t\t\/\/ Filtre de date\n\t\t\t\tif (selectedDateFilter === 'custom' && selectedDateFrom && selectedDateTo) {\n\t\t\t\t\tconst fromDate = new Date(selectedDateFrom);\n\t\t\t\t\tfromDate.setHours(0, 0, 0, 0);\n\t\t\t\t\tconst toDate = new Date(selectedDateTo);\n\t\t\t\t\ttoDate.setHours(23, 59, 59, 999);\n\t\t\t\t\t\n\t\t\t\t\tconst filteredResults = [];\n\t\t\t\t\tfor (const p of results) {\n\t\t\t\t\t\tconst eventDate = await getEventDate(p);\n\t\t\t\t\t\tconst postDate = new Date(eventDate);\n\t\t\t\t\t\tif (!isNaN(postDate.getTime()) && postDate >= fromDate && postDate <= toDate) {\n\t\t\t\t\t\t\tfilteredResults.push(p);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tresults = filteredResults;\n\t\t\t\t} else if (selectedDateFilter && selectedDateFilter !== 'custom') {\n\t\t\t\t\tconst days = parseInt(selectedDateFilter);\n\t\t\t\t\tconst cutoffDate = new Date();\n\t\t\t\t\tcutoffDate.setDate(cutoffDate.getDate() - days);\n\t\t\t\t\t\n\t\t\t\t\tconst filteredResults = [];\n\t\t\t\t\tfor (const p of results) {\n\t\t\t\t\t\tconst eventDate = await getEventDate(p);\n\t\t\t\t\t\tconst postDate = new Date(eventDate);\n\t\t\t\t\t\tif (!isNaN(postDate.getTime()) && postDate >= cutoffDate) {\n\t\t\t\t\t\t\tfilteredResults.push(p);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tresults = filteredResults;\n\t\t\t\t}\n\n\t\t\t\t\/\/ Tri par date (plus r\u00e9cent en premier)\n\t\t\t\t\/\/ V\u00e9rifier si les dates sont d\u00e9j\u00e0 format\u00e9es en fran\u00e7ais\n\t\t\t\tconst sortedResults = [];\n\t\t\t\tlet hasFormattedDates = false;\n\t\t\t\t\n\t\t\t\tfor (const p of results) {\n\t\t\t\t\tconst eventDate = await getEventDate(p);\n\t\t\t\t\t\/\/ V\u00e9rifier si la date est d\u00e9j\u00e0 format\u00e9e\n\t\t\t\t\tif (typeof eventDate === 'string' && eventDate.includes(' ') && !eventDate.includes('T')) {\n\t\t\t\t\t\thasFormattedDates = true;\n\t\t\t\t\t\tsortedResults.push({ post: p, date: eventDate });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst postDate = new Date(eventDate);\n\t\t\t\t\t\tif (!isNaN(postDate.getTime())) {\n\t\t\t\t\t\t\tsortedResults.push({ post: p, date: eventDate });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\/\/ Si les dates sont format\u00e9es, ne pas trier (les garder dans l'ordre d'origine)\n\t\t\t\tif (!hasFormattedDates) {\n\t\t\t\t\tsortedResults.sort((a, b) => new Date(b.date) - new Date(a.date));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tresults = sortedResults.map(item => item.post);\n\n\t\t\t\tfilteredPosts = results;\n\t\t\t\treturn results;\n\t\t\t}\n\n\t\t\t\/\/ Rendu des posts\n\t\t\tasync function renderPosts(posts, append = false) {\n\t\t\t\t\n\t\t\t\t\/\/ Variable pour stocker le nombre de cartes avant l'append (accessible dans les timeouts)\n\t\t\t\tlet existingCardsCountBeforeAppend = 0;\n\t\t\t\t\/\/ Variable pour stocker les IDs des cartes prot\u00e9g\u00e9es (accessible dans toute la fonction)\n\t\t\t\tlet protectedPostIds = new Set();\n\t\t\t\t\n\t\t\t\t\/\/ Si on est en mode append, PROT\u00c9GER IMM\u00c9DIATEMENT les cartes existantes\n\t\t\t\tif (append) {\n\t\t\t\t\tcleanupTimeouts.forEach(timeoutId => {\n\t\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t\t});\n\t\t\t\t\tcleanupTimeouts = []; \/\/ R\u00e9initialiser le tableau\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Sauvegarder le nombre de cartes AVANT toute op\u00e9ration\n\t\t\t\t\texistingCardsCountBeforeAppend = listEl.querySelectorAll('.acf-card-wrapper').length;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ PROTECTION IMM\u00c9DIATE: Marquer et prot\u00e9ger les cartes existantes AVANT toute autre op\u00e9ration\n\t\t\t\t\tconst existingCards = Array.from(listEl.querySelectorAll('.acf-card-wrapper'));\n\t\t\t\t\tprotectedPostIds = new Set(); \/\/ Utiliser la variable d\u00e9clar\u00e9e au niveau de la fonction\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Arr\u00eater les observers pr\u00e9c\u00e9dents\n\t\t\t\t\tprotectionObservers.forEach(observer => observer.disconnect());\n\t\t\t\t\tprotectionObservers = [];\n\t\t\t\t\t\n\t\t\t\t\texistingCards.forEach((wrapper) => {\n\t\t\t\t\t\tconst card = wrapper.querySelector('.acf-card');\n\t\t\t\t\t\tif (card) {\n\t\t\t\t\t\t\tconst postId = card.getAttribute('data-post-id');\n\t\t\t\t\t\t\tif (postId) {\n\t\t\t\t\t\t\t\tprotectedPostIds.add(postId);\n\t\t\t\t\t\t\t\t\/\/ Marquer la carte et tous ses \u00e9l\u00e9ments [data-post-id] comme prot\u00e9g\u00e9s\n\t\t\t\t\t\t\t\twrapper.setAttribute('data-protected-append', 'true');\n\t\t\t\t\t\t\t\tcard.setAttribute('data-protected-append', 'true');\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\/\/ Marquer tous les \u00e9l\u00e9ments [data-post-id] dans cette carte comme prot\u00e9g\u00e9s\n\t\t\t\t\t\t\t\twrapper.querySelectorAll('[data-post-id]').forEach(el => {\n\t\t\t\t\t\t\t\t\tel.setAttribute('data-protected-append', 'true');\n\t\t\t\t\t\t\t\t\tel.setAttribute('data-hydrated', 'true');\n\t\t\t\t\t\t\t\t\tif (el._loaded !== undefined) {\n\t\t\t\t\t\t\t\t\t\tel._loaded = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\/\/ PROTECTION: Intercepter innerHTML sur la carte elle-m\u00eame\n\t\t\t\t\t\t\t\tconst cardInnerHTMLDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(card), 'innerHTML');\n\t\t\t\t\t\t\t\tif (cardInnerHTMLDescriptor && cardInnerHTMLDescriptor.set) {\n\t\t\t\t\t\t\t\t\tconst originalCardSet = cardInnerHTMLDescriptor.set;\n\t\t\t\t\t\t\t\t\tconst savedCardHTML = card.innerHTML; \/\/ Sauvegarder le HTML AVANT toute modification\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tObject.defineProperty(card, 'innerHTML', {\n\t\t\t\t\t\t\t\t\t\tset: function(value) {\n\t\t\t\t\t\t\t\t\t\t\tif (this.hasAttribute('data-protected-append')) {\n\t\t\t\t\t\t\t\t\t\t\t\t\/\/ Restaurer le contenu original\n\t\t\t\t\t\t\t\t\t\t\t\toriginalCardSet.call(this, savedCardHTML);\n\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\toriginalCardSet.call(this, value);\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tget: cardInnerHTMLDescriptor.get,\n\t\t\t\t\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\/\/ PROTECTION: MutationObserver pour bloquer les suppressions\n\t\t\t\t\t\t\t\tconst protectionObserver = new MutationObserver((mutations) => {\n\t\t\t\t\t\t\t\t\tmutations.forEach((mutation) => {\n\t\t\t\t\t\t\t\t\t\tif (mutation.type === 'childList' && mutation.removedNodes.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\tmutation.removedNodes.forEach((node) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (node.nodeType === 1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst isImportant = node.matches && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnode.matches('.acf-img-container') ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnode.matches('.acf-body') ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnode.matches('.acf-title') ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnode.matches('.acf-excerpt') ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnode.matches('.acf-date')\n\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (isImportant && card.hasAttribute('data-protected-append')) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\/\/ R\u00e9ins\u00e9rer le n\u0153ud\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (mutation.target && mutation.nextSibling) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmutation.target.insertBefore(node, mutation.nextSibling);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else if (mutation.target) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmutation.target.appendChild(node);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tprotectionObserver.observe(card, {\n\t\t\t\t\t\t\t\t\tchildList: true,\n\t\t\t\t\t\t\t\t\tsubtree: true\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tprotectionObservers.push(protectionObserver);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\/\/ D\u00e9finir le flag pour \u00e9viter le cleanup pendant l'append\n\t\t\t\tisAppending = append;\n\t\t\t\tisAppendingMode = append; \/\/ Mettre \u00e0 jour le flag global pour l'interception innerHTML\n\t\t\t\t\n\t\t\t\t\/\/ Si on est en mode append, arr\u00eater les anciennes instances de reapplyDates\n\t\t\t\tif (append) {\n\t\t\t\t\tshouldStopReapplying = true;\n\t\t\t\t\twindow.__shouldStopReapplying = true; \/\/ Variable globale accessible par toutes les instances\n\t\t\t\t\t\/\/ PROTECTION: Emp\u00eacher tout vidage du contenu en mode append\n\t\t\t\t\t\/\/ Sauvegarder le contenu existant avant toute op\u00e9ration\n\t\t\t\t\tconst existingContent = listEl.innerHTML;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!append) {\n\t\t\t\t\tlistEl.innerHTML = \"\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\/\/ Filtrer une derni\u00e8re fois pour s'assurer qu'aucun post \"uncategorized\" ne passe\n\t\t\t\tconst validPosts = posts.filter(p => hasValidCategories(p));\n\t\t\t\t\n\t\t\t\tif (validPosts.length === 0) {\n\t\t\t\t\tconst noResultsText = getNoResultsMessage();\n\t\t\t\t\tif (noResultsText) {\n\t\t\t\t\t\tlistEl.innerHTML = `<p>${noResultsText}<\/p>`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlistEl.innerHTML = '';\n\t\t\t\t\t}\n\t\t\t\t\tif (loadMoreContainer) loadMoreContainer.style.display = \"none\";\n\t\t\t\t\t\/\/ V\u00e9rifier plusieurs fois pour contrer les scripts externes\n\t\t\t\t\tsetTimeout(() => cleanupNoContentMessage(), 10);\n\t\t\t\t\tsetTimeout(() => cleanupNoContentMessage(), 100);\n\t\t\t\t\tsetTimeout(() => cleanupNoContentMessage(), 300);\n\t\t\t\t\tsetTimeout(() => cleanupNoContentMessage(), 500);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst sliceStart = append ? (currentPage - 1) * postsPerPage : 0;\n\t\t\t\tconst sliceEnd = currentPage * postsPerPage;\n\t\t\t\tconst toRender = append ? validPosts.slice(sliceStart, sliceEnd) : validPosts.slice(0, sliceEnd);\n\n\t\t\t\t\/\/ Pr\u00e9-charger toutes les dates d'\u00e9v\u00e9nement pour \u00e9viter les probl\u00e8mes de timing\n\t\t\t\tconst postsWithEventDates = await Promise.all(toRender.map(async (p) => {\n\t\t\t\t\tconst eventDate = await getEventDate(p);\n\t\t\t\t\t\/\/ Cr\u00e9er un nouvel objet avec la date d'\u00e9v\u00e9nement\n\t\t\t\t\tconst postWithEventDate = Object.assign({}, p, { eventDate });\n\t\t\t\t\treturn postWithEventDate;\n\t\t\t\t}));\n\t\t\t\t\n\t\t\t\t\/\/ Stocker les posts actuellement rendus (avec eventDate) pour la r\u00e9application des dates\n\t\t\t\tif (append) {\n\t\t\t\t\tcurrentlyRenderedPosts = currentlyRenderedPosts.concat(postsWithEventDates);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentlyRenderedPosts = postsWithEventDates;\n\t\t\t\t}\n\n\t\t\t\tconst cardsHTML = await Promise.all(postsWithEventDates.map(async (p) => {\n\t\t\t\t\tconst img = await getPostImage(p);\n\t\t\t\t\tconst categories = await getPostCategories(p);\n\t\t\t\t\tconst region = toScalarString(getPostACF(p, 'region')).trim();\n\t\t\t\t\t\/\/ R\u00e9cup\u00e9rer la ville via fetch single-post (fonctionne pour visiteurs non connect\u00e9s)\n\t\t\t\t\tconst ville = await getPostCityCached(p);\n\t\t\t\t\tconst nomPrenom = getLang() === 'en' ? await getPostACFTranslated(p, 'nom_prenom') : getPostACF(p, 'nom_prenom');\n\t\t\t\t\t\n                    \/\/ Logiques publications retir\u00e9es\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Pr\u00e9parer le bouton + (NE PAS FAIRE D'APPEL AJAX CAR LE SERVEUR RENVOIE DU CSS)\n\t\t\t\t\t\/\/ Utiliser directement le fallback pour \u00e9viter toute injection malveillante\n\t\t\t\t\tlet plusHTML = '';\n\t\t\t\t\t\n\t\t\t\t\t\/\/ NE PAS APPELER LE SERVEUR - utiliser directement le fallback\n\t\t\t\t\t\/\/ const fd = new FormData();\n\t\t\t\t\t\/\/ const resp = await fetch('\/wp-admin\/admin-ajax.php', ...); \/\/ D\u00c9SACTIV\u00c9\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Utiliser le fallback directement\n\t\t\t\t\tconst buttonText = getLang() === 'en' ? 'Learn more' : 'En savoir plus';\n\t\t\t\t\tplusHTML = `\n\t\t\t\t\t\t<div class=\"button-plus-dynamique acf-plus\" data-post-id=\"${p.id}\">\n\t\t\t\t\t\t\t<div class=\"plus-icon\">\n\t\t\t\t\t\t\t\t<svg width=\"21\" height=\"22\" viewBox=\"0 0 21 22\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n\t\t\t\t\t\t\t\t\t<path d=\"M10.5 1.5V20.5M1 11H20\" stroke=\"#D30C8C\" stroke-width=\"1.56\" stroke-miterlimit=\"10\" stroke-linecap=\"round\"\/>\n\t\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"text-arrow\">\n\t\t\t\t\t\t\t\t<span>${buttonText}<\/span>\n\t\t\t\t\t\t\t\t<svg width=\"14\" height=\"13\" viewBox=\"0 0 14 13\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n\t\t\t\t\t\t\t\t\t<path d=\"M13.6998 6.80031L8.49413 12.0059C8.41448 12.0856 8.30645 12.1303 8.19381 12.1303C8.08116 12.1303 7.97313 12.0856 7.89348 12.0059C7.81383 11.9263 7.76908 11.8183 7.76908 11.7056C7.76908 11.593 7.81383 11.4849 7.89348 11.4053L12.3743 6.92445L0.585584 6.92445C0.475604 6.92057 0.371424 6.87415 0.294992 6.79497C0.218561 6.71579 0.175845 6.61004 0.175845 6.49999C0.175845 6.38994 0.218561 6.28419 0.294992 6.20501C0.371424 6.12583 0.475605 6.07941 0.585586 6.07553L12.3743 6.07553L7.89348 1.59469C7.81383 1.51504 7.76908 1.40701 7.76908 1.29436C7.76908 1.18172 7.81383 1.07369 7.89348 0.99404C7.97313 0.914389 8.08116 0.869641 8.19381 0.869641C8.30645 0.869641 8.41448 0.914389 8.49413 0.99404L13.6998 6.19967C13.7794 6.27932 13.8242 6.38735 13.8242 6.49999C13.8242 6.61263 13.7794 6.72066 13.6998 6.80031Z\" fill=\"#D30C8C\"\/>\n\t\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t`;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Formatage de la date\n\t\t\t\t\tconst currentLang = getLang();\n\t\t\t\t\tconst formattedDate = formatPostDate(p.eventDate, currentLang);\n\n\t\t\t\t\t\/\/ G\u00e9n\u00e9rer le HTML des cat\u00e9gories\n\t\t\t\t\tconst categoriesHTML = categories.length > 0 \n\t\t\t\t\t\t? `<div class=\"acf-tags\">${categories.map(cat => `<span class=\"acf-chip\">${cat}<\/span>`).join('')}<\/div>`\n\t\t\t\t\t\t: '';\n\n\t\t\t\t\t\/\/ Gestion de l'image\n\t\t\t\t\tlet imageHTML = '';\n\t\t\t\t\tif (img) {\n\t\t\t\t\t\timageHTML = `<img decoding=\"async\" class=\"acf-img\" src=\"${img}\" alt=\"${p.title?.rendered || ''}\">`;\n\t\t\t\t\t\tif (nomPrenom) {\n\t\t\t\t\t\t\timageHTML += `<div class=\"acf-nom-prenom\">\u00a9 ${nomPrenom}<\/div>`;\n\t\t\t\t\t\t}\n                        \/\/ Badge \u00e9v\u00e9nement retir\u00e9\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst noImageText = getLang() === 'en' ? 'No image' : 'Aucune image';\n\t\t\t\t\t\timageHTML = `<div class=\"acf-img-placeholder\" style=\"width: 100%; height: 170px; background: #E0E0E0; display: flex; align-items: center; justify-content: center; border-radius: 12px 12px 0 0; color: #999;\">${noImageText}<\/div>`;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst villeHTML = ville ? `<div class=\"acf-ville\">${ville}<\/div>` : '';\n\t\t\t\t\t\n                    \/\/ Carte publications retir\u00e9e\n\t\t\t\t\t\n\t\t\t\t\t\/\/ HTML standard pour les autres types de contenu\n\t\t\t\t\treturn `\n\t\t\t\t\t\t<div class=\"acf-card-wrapper\">\n\t\t\t\t\t\t\t<div class=\"acf-card\" data-post-id=\"${p.id}\" onclick=\"window.location.href='${p.link}'\">\n\t\t\t\t\t\t\t\t<div class=\"acf-img-container\">\n\t\t\t\t\t\t\t\t\t${imageHTML}\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"acf-body\">\n\t\t\t\t\t\t\t\t\t<div class=\"acf-date-title-excerpt\">\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-ville-date\">\n\t\t\t\t\t\t\t\t\t\t\t${villeHTML}\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"acf-date acf-date-original\" data-post-id=\"${p.id}\" data-original-date=\"${p.eventDate}\">${formattedDate}<\/div>\n\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-title\">${p.title?.rendered || \"\"}<\/div>\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-excerpt\">${p.excerpt?.rendered || \"\"}<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<div class=\"acf-plus-tags\">\n\t\t\t\t\t\t\t\t\t\t${categoriesHTML}\n\t\t\t\t\t\t\t\t\t\t<div class=\"acf-plus-holder\" data-post-id=\"${p.id}\">${plusHTML}<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t`;\n\t\t\t\t}));\n\n\t\t\t\tif (append) {\n\t\t\t\t\t\/\/ En mode append, utiliser insertAdjacentHTML pour \u00e9viter de recr\u00e9er tous les \u00e9l\u00e9ments\n\t\t\t\t\tconst htmlToAdd = cardsHTML.join(\"\");\n\t\t\t\t\t\/\/ PROTECTION: V\u00e9rifier que le nombre de cartes n'a pas chang\u00e9 depuis le d\u00e9but\n\t\t\t\t\t\/\/ (La protection a d\u00e9j\u00e0 \u00e9t\u00e9 mise en place au d\u00e9but de la fonction en mode append)\n\t\t\t\t\tconst currentCardsCount = listEl.querySelectorAll('.acf-card-wrapper').length;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ D\u00e9sactiver temporairement toutes les modifications du DOM en append\n\t\t\t\t\twindow.__shouldStopReapplying = true;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ V\u00e9rifier que le contenu existe toujours avant l'insertion\n\t\t\t\t\tconst cardsBeforeInsert = listEl.querySelectorAll('.acf-card-wrapper').length;\n\t\t\t\t\t\n\t\t\t\t\tif (existingCardsCountBeforeAppend > 0 && cardsBeforeInsert === 0) {\n\t\t\t\t\t\t\/\/ Si les cartes ont \u00e9t\u00e9 vid\u00e9es, on ne peut pas les restaurer facilement\n\t\t\t\t\t\t\/\/ Dans ce cas, on fait un rendu complet au lieu d'un append\n\t\t\t\t\t\tisAppending = false;\n\t\t\t\t\t\twindow.__shouldStopReapplying = false;\n\t\t\t\t\t\tawait renderPosts(posts, false);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tlistEl.insertAdjacentHTML('beforeend', htmlToAdd);\n\t\t\t\t\t\n\t\t\t\t\tconst cardsAfterInsert = listEl.querySelectorAll('.acf-card-wrapper').length;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ S'assurer que les nouvelles cartes ne sont PAS marqu\u00e9es comme prot\u00e9g\u00e9es\n\t\t\t\t\t\/\/ (elles doivent pouvoir \u00eatre trait\u00e9es par les scripts externes)\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tconst allNewCards = listEl.querySelectorAll('.acf-card-wrapper:not([data-protected-append])');\n\t\t\t\t\t\tallNewCards.forEach((wrapper) => {\n\t\t\t\t\t\t\tconst card = wrapper.querySelector('.acf-card');\n\t\t\t\t\t\t\tif (card && !protectedPostIds.has(card.getAttribute('data-post-id'))) {\n\t\t\t\t\t\t\t\t\/\/ C'est une nouvelle carte, la laisser \u00eatre trait\u00e9e normalement\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}, 10);\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Log IMM\u00c9DIATEMENT apr\u00e8s insertion pour voir le HTML\n\t\t\t\t\t\n\t\t\t\t\t\/\/ V\u00e9rifier si les posts existent toujours apr\u00e8s insertion\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Comparer IMM\u00c9DIATEMENT apr\u00e8s vs 100ms plus tard\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ V\u00e9rifier tous les wrappers\n\t\t\t\t\t\tlistEl.querySelectorAll('.acf-card-wrapper').forEach((wrapper, idx) => {\n\t\t\t\t\t\t\tconst card = wrapper.querySelector('.acf-card');\n\t\t\t\t\t\t\tconst title = card ? card.querySelector('.acf-title') : null;\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ V\u00e9rifier aussi toutes les cards directement (dans ou hors wrapper)\n\t\t\t\t\t\tlistEl.querySelectorAll('.acf-card').forEach((card, idx) => {\n\t\t\t\t\t\t\tconst title = card.querySelector('.acf-title');\n\t\t\t\t\t\t\tconst parentWrapper = card.parentElement && card.parentElement.classList.contains('acf-card-wrapper');\n\t\t\t\t\t\t\tif (!parentWrapper) {\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}, 100);\n\t\t\t\t\t\n\t\t\t\t\t\/\/ R\u00e9initialiser le flag APR\u00c8S l'insertion\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tconst cardsAfterTimeout = listEl.querySelectorAll('.acf-card-wrapper').length;\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ V\u00e9rifier que les cartes sont toujours l\u00e0 avant de r\u00e9initialiser les flags\n\t\t\t\t\t\t\/\/ On devrait avoir au moins le nombre de cartes qu'on avait avant l'append\n\t\t\t\t\t\tif (cardsAfterTimeout < existingCardsCountBeforeAppend) {\n\t\t\t\t\t\t\t\/\/ Erreur silencieuse\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ V\u00c9RIFICATION: V\u00e9rifier que les cartes prot\u00e9g\u00e9es sont toujours intactes\n\t\t\t\t\t\tconst protectedCards = listEl.querySelectorAll('[data-protected-append=\"true\"]');\n\t\t\t\t\t\tlet intactCount = 0;\n\t\t\t\t\t\tprotectedCards.forEach((el) => {\n\t\t\t\t\t\t\tconst card = el.closest('.acf-card');\n\t\t\t\t\t\t\tif (card) {\n\t\t\t\t\t\t\t\tconst hasTitle = card.querySelector('.acf-title');\n\t\t\t\t\t\t\t\tconst hasImage = card.querySelector('.acf-img-container');\n\t\t\t\t\t\t\t\tconst hasBody = card.querySelector('.acf-body');\n\t\t\t\t\t\t\t\tif (hasTitle && hasImage && hasBody) {\n\t\t\t\t\t\t\t\t\tintactCount++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Arr\u00eater les observers de protection\n\t\t\t\t\t\tprotectionObservers.forEach(observer => {\n\t\t\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t\t});\n\t\t\t\t\t\tprotectionObservers = [];\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Retirer les attributs de protection apr\u00e8s la r\u00e9initialisation\n\t\t\t\t\t\t\/\/ (les cartes peuvent maintenant \u00eatre modifi\u00e9es normalement)\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tlistEl.querySelectorAll('[data-protected-append]').forEach(el => {\n\t\t\t\t\t\t\t\tel.removeAttribute('data-protected-append');\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\n\t\t\t\t\t\twindow.__shouldStopReapplying = false;\n\t\t\t\t\t\tisAppendingMode = false;\n\t\t\t\t\t\tisAppending = false; \/\/ S'assurer que isAppending est aussi r\u00e9initialis\u00e9\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ V\u00e9rification finale apr\u00e8s r\u00e9initialisation\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tconst finalCardsCount = listEl.querySelectorAll('.acf-card-wrapper').length;\n\t\t\t\t\t\t\tif (finalCardsCount < cardsAfterTimeout) {\n\t\t\t\t\t\t\t\t\/\/ Erreur silencieuse\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 100);\n\t\t\t\t\t}, 1000);\n\t\t\t\t} else {\n\t\t\t\t\tlistEl.innerHTML = cardsHTML.join(\"\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\/\/ Forcer la r\u00e9application des dates apr\u00e8s un d\u00e9lai (pour contrer les scripts de traduction)\n\t\t\t\t\/\/ UNIQUEMENT en mode non-append pour \u00e9viter les conflits\n\t\t\t\tif (!append) {\n\t\t\t\t\t\/\/ R\u00e9initialiser le flag d'arr\u00eat\n\t\t\t\t\tshouldStopReapplying = false;\n\t\t\t\t\twindow.__shouldStopReapplying = false; \/\/ R\u00e9initialiser aussi la variable globale\n\t\t\t\t\t\n\t\t\t\t\tlet isReapplying = false;\n\t\t\t\t\tconst reapplyDates = async () => {\n\t\t\t\t\t\t\/\/ V\u00c9RIFICATION GLOBALE EN PREMIER - m\u00eame pour les anciennes instances\n\t\t\t\t\t\tif (window.__shouldStopReapplying) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (isReapplying) return;\n\t\t\t\t\t\tisReapplying = true;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Chercher seulement nos \u00e9l\u00e9ments de date originaux\n\t\t\t\t\tconst dateElements = listEl.querySelectorAll('.acf-date-original');\n\t\t\t\t\tconst currentLang = getLang();\n\t\t\t\t\t\n\t\t\t\t\tfor (const dateEl of dateElements) {\n\t\t\t\t\t\t\/\/ Essayer de r\u00e9cup\u00e9rer la date originale depuis l'attribut\n\t\t\t\t\t\tlet originalDate = dateEl.getAttribute('data-original-date');\n\t\t\t\t\t\tconst postId = dateEl.getAttribute('data-post-id');\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Si pas d'attribut, chercher dans les posts render\u00e9s et utiliser la date d'\u00e9v\u00e9nement pr\u00e9-charg\u00e9e\n\t\t\t\t\t\tif (!originalDate) {\n\t\t\t\t\t\t\tif (postId) {\n\t\t\t\t\t\t\t\tconst post = currentlyRenderedPosts.find(p => p.id.toString() === postId);\n\t\t\t\t\t\t\t\tif (post && post.eventDate) {\n\t\t\t\t\t\t\t\t\toriginalDate = post.eventDate;\n\t\t\t\t\t\t\t\t\t\/\/ Remettre l'attribut pour la prochaine fois\n\t\t\t\t\t\t\t\t\tdateEl.setAttribute('data-original-date', originalDate);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (originalDate) {\n\t\t\t\t\t\t\tconst formattedDate = formatPostDate(originalDate, currentLang);\n\t\t\t\t\t\t\tif (formattedDate) {\n\t\t\t\t\t\t\t\tdateEl.textContent = formattedDate;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tsetTimeout(() => { isReapplying = false; }, 100);\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\t\/\/ R\u00e9appliquer imm\u00e9diatement et apr\u00e8s plusieurs d\u00e9lais\n\t\t\t\tsetTimeout(() => reapplyDates(), 0);\n\t\t\t\tsetTimeout(() => reapplyDates(), 100);\n\t\t\t\tsetTimeout(() => reapplyDates(), 500);\n\t\t\t\tsetTimeout(() => reapplyDates(), 1000);\n\t\t\t\tsetTimeout(() => reapplyDates(), 2000);\n\t\t\t\t} \/\/ Fin du bloc if (!append)\n\n\n\t\t\t\t\/\/ Nettoyage: ne garder que les cartes rendues par ce shortcode dans cette instance\n\t\t\t\tfunction cleanupExtraneousCards() {\n\t\t\t\t\t\/\/ Ne pas faire le cleanup en mode append pour \u00e9viter de supprimer les posts d\u00e9j\u00e0 affich\u00e9s\n\t\t\t\t\tif (window.__shouldStopReapplying) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (isAppending) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tconst scope = app.parentElement || app;\n\t\t\t\t\tconst validIds = new Set(currentlyRenderedPosts.map(p => String(p.id)));\n\t\t\t\t\t\n\t\t\t\t\tconst allCards = scope.querySelectorAll('.acf-card');\n\t\t\t\t\t\n\t\t\t\t\t\/\/ 1) Supprimer toute carte dans le scope qui n'est pas dans notre liste rendue\n\t\t\t\t\tallCards.forEach((card) => {\n\t\t\t\t\t\tconst inOurList = listEl.contains(card);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ PROTECTION CRITIQUE: Si la carte est dans listEl, elle est VALIDE par d\u00e9finition\n\t\t\t\t\t\t\/\/ Ne jamais supprimer une carte qui est dans listEl\n\t\t\t\t\t\tif (inOurList) {\n\t\t\t\t\t\t\treturn; \/\/ Ne pas supprimer cette carte, elle est dans listEl\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Si la carte n'est PAS dans listEl, alors on peut la supprimer si elle n'est pas valide\n\t\t\t\t\t\t\/\/ Essayer de d\u00e9tecter un id depuis diff\u00e9rentes sources (comme dans cleanupRenderedCards)\n\t\t\t\t\t\tlet cardId = card.getAttribute('data-post-id');\n\t\t\t\t\t\tif (!cardId) {\n\t\t\t\t\t\t\tconst idFromDate = card.querySelector('.acf-date[data-post-id]')?.getAttribute('data-post-id');\n\t\t\t\t\t\t\tconst idFromPlus = card.querySelector('[data-post-id]')?.getAttribute('data-post-id');\n\t\t\t\t\t\t\tcardId = idFromDate || idFromPlus || '';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst isValid = cardId && validIds.has(cardId);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Supprimer seulement si la carte n'est pas dans listEl ET n'est pas valide\n\t\t\t\t\t\tif (!isValid) {\n\t\t\t\t\t\t\ttry { card.remove(); } catch(e) { card.style.setProperty('display','none','important'); }\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\t\/\/ 2) Dans nos cartes, retirer les tags \"uncategorized\" restants si inject\u00e9s par d'autres scripts\n\t\t\t\t\tlistEl.querySelectorAll('.acf-chip').forEach(tagEl => {\n\t\t\t\t\t\tconst txt = (tagEl.textContent || '').toLowerCase();\n\t\t\t\t\t\tif (txt.includes('uncategorized') || txt.includes('non cat\u00e9goris\u00e9') || txt.includes('non categorise')) {\n\t\t\t\t\t\t\ttagEl.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t\/\/ lancer le cleanup juste apr\u00e8s le rendu des cartes\n\t\t\t\t\/\/ NE PAS faire le cleanup imm\u00e9diat en mode append pour \u00e9viter de supprimer les posts d\u00e9j\u00e0 affich\u00e9s\n\t\t\t\tif (!append) {\n\t\t\t\t\tcleanupExtraneousCards();\n\t\t\t\t\tcleanupRenderedCards();\n\t\t\t\t\t\/\/ et re-clean quelques instants apr\u00e8s pour attraper toute injection tardive\n\t\t\t\t\t\/\/ Stocker les timeouts pour pouvoir les annuler si n\u00e9cessaire\n\t\t\t\t\tconst timeout1 = setTimeout(() => {\n\t\t\t\t\t\tif (!isAppending && !window.__shouldStopReapplying) {\n\t\t\t\t\t\t\tcleanupRenderedCards();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 150);\n\t\t\t\t\tconst timeout2 = setTimeout(() => {\n\t\t\t\t\t\tif (!isAppending && !window.__shouldStopReapplying) {\n\t\t\t\t\t\t\tcleanupRenderedCards();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 400);\n\t\t\t\t\tconst timeout3 = setTimeout(() => {\n\t\t\t\t\t\tif (!isAppending && !window.__shouldStopReapplying) {\n\t\t\t\t\t\t\tcleanupRenderedCards();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 800);\n\t\t\t\t\tcleanupTimeouts.push(timeout1, timeout2, timeout3);\n\t\t\t\t}\n\n\t\t\t\t\/\/ Bouton \"Voir plus\"\n\t\t\t\tif (loadMoreContainer) {\n\t\t\t\t\tif (validPosts.length > currentPage * postsPerPage) {\n\t\t\t\t\t\tloadMoreContainer.style.display = \"block\";\n\t\t\t\t\t\tif (loadMoreBtn) loadMoreBtn.disabled = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tloadMoreContainer.style.display = \"none\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\/\/ R\u00e9initialiser le flag isAppending apr\u00e8s le rendu\n\t\t\t\t\/\/ Note: window.__shouldStopReapplying est d\u00e9j\u00e0 r\u00e9initialis\u00e9 par setTimeout en mode append\n\t\t\t\tconst finalCardsCount = listEl.querySelectorAll('.acf-card-wrapper').length;\n\t\t\t\t\n\t\t\t\tif (append) {\n\t\t\t\t\t\/\/ Les flags seront r\u00e9initialis\u00e9s dans 1000ms\n\t\t\t\t} else {\n\t\t\t\t\tisAppending = false;\n\t\t\t\t\tisAppendingMode = false; \/\/ R\u00e9initialiser aussi le flag global\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Chargement des options de filtres\n\t\t\tasync function loadFilterOptions() {\n\t\t\t\t\/\/ Charger les r\u00e9gions\n\t\t\t\tconst regionList = app.querySelector(\".acf-region-list\");\n\t\t\t\tif (regionList) {\n\t\t\t\t\tconst regions = [];\n\t\t\t\t\tconst currentLang = getLang();\n\t\t\t\t\tfor (const p of allPosts) {\n\t\t\t\t\t\t\/\/ Toujours r\u00e9cup\u00e9rer via l'endpoint single pour garantir la traduction WPML\n\t\t\t\t\t\tconst region = await getPostACFStrict(p, 'region');\n\t\t\t\t\t\tif (region) regions.push(region);\n\t\t\t\t\t}\n\t\t\t\t\tlet uniqueRegions = [...new Set(regions.map(r => String(r)))];\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Traduire les r\u00e9gions si n\u00e9cessaire (comme dans ici3)\n\t\t\t\t\tif (currentLang === 'en' && uniqueRegions.length > 0) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst translatedRegions = await translateChoices('region', uniqueRegions);\n\t\t\t\t\t\t\tuniqueRegions = translatedRegions;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Ajouter une option de reset en t\u00eate\n\t\t\t\t\tconst resetLabel = currentLang === 'en' ? 'Region' : 'R\u00e9gion';\n\t\t\t\t\tregionList.innerHTML = `\n\t\t\t\t\t\t<div class=\"acf-region-item\" data-value=\"\">\n\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">${resetLabel}<\/span>\n\t\t\t\t\t\t\t<svg class=\"acf-radio\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"15\" height=\"16\" viewBox=\"0 0 15 16\" fill=\"none\">\n\t\t\t\t\t\t\t\t<circle cx=\"7.5\" cy=\"8\" r=\"7\" stroke=\"#323332\"\/>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>` + uniqueRegions.map(region => `\n\t\t\t\t\t\t<div class=\"acf-region-item\" data-value=\"${region}\">\n\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">${region}<\/span>\n\t\t\t\t\t\t\t<svg class=\"acf-radio\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"15\" height=\"16\" viewBox=\"0 0 15 16\" fill=\"none\">\n\t\t\t\t\t\t\t\t<circle cx=\"7.5\" cy=\"8\" r=\"7\" stroke=\"#323332\"\/>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t`).join('');\n\t\t\t\t}\n\n\t\t\t\t\/\/ Charger les sujets\n\t\t\t\tconst sujetList = app.querySelector(\".acf-sujet-dropdown .acf-dropdown-menu\");\n\t\t\t\tif (sujetList) {\n\t\t\t\t\tconst sujets = [];\n\t\t\t\t\tconst currentLang = getLang();\n                    const isReports = window.location.pathname.includes('\/reports') || window.location.pathname.includes('\/rapports');\n\t\t\t\t\tconst isPressReleases = window.location.pathname.includes('\/communiques-de-presse') || window.location.pathname.includes('\/press-releases') || (cpt === 'communique-de-presse');\n\t\t\t\t\tconst isValuations = window.location.pathname.includes('\/valorisations') || window.location.pathname.includes('\/valuation');\n                    \n\t\t\t\t\tfor (const p of allPosts) {\n                        if (isReports) {\n\t\t\t\t\t\t\tconst cats = await getPostCategories(p);\n\t\t\t\t\t\t\tcats.forEach(c => { if (c) sujets.push(c); });\n\t\t\t\t\t\t} else if (isPressReleases) {\n\t\t\t\t\t\t\t\/\/ Communiqu\u00e9s de presse: \"Sujet\" = cat\u00e9gories WordPress\n\t\t\t\t\t\t\tconst cats = await getPostCategories(p);\n\t\t\t\t\t\t\tcats.forEach(c => { \n\t\t\t\t\t\t\t\tif (c && !c.toLowerCase().includes('uncategorized') && !c.toLowerCase().includes('non cat\u00e9goris\u00e9') && !c.toLowerCase().includes('non categorise')) {\n\t\t\t\t\t\t\t\t\tsujets.push(c); \n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (isValuations) {\n\t\t\t\t\t\t\t\/\/ Valorisations: \"Sujet\" = cat\u00e9gories WordPress\n\t\t\t\t\t\t\tconst cats = await getPostCategories(p);\n\t\t\t\t\t\t\tcats.forEach(c => { \n\t\t\t\t\t\t\t\tif (c && !c.toLowerCase().includes('uncategorized') && !c.toLowerCase().includes('non cat\u00e9goris\u00e9') && !c.toLowerCase().includes('non categorise')) {\n\t\t\t\t\t\t\t\t\tsujets.push(c); \n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst sujet = currentLang === 'en' ? await getPostACFTranslated(p, 'sujet') : getPostACF(p, 'sujet');\n\t\t\t\t\t\t\tif (sujet) sujets.push(sujet);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlet uniqueSujets = [...new Set(sujets)];\n\t\t\t\t\t\/\/ Filtrer\/d\u00e9dupliquer pour la page EN afin d'\u00e9viter FR+EN m\u00e9lang\u00e9s\n\t\t\t\t\tif (currentLang === 'en') {\n\t\t\t\t\t\tconst frenchChars = \/[\u00e9\u00e8\u00ea\u00eb\u00e0\u00e2\u00ee\u00ef\u00f4\u00f6\u00f9\u00fb\u00fc\u00e7\u0153\u00c9\u00c8\u00ca\u00cb\u00c0\u00c2\u00ce\u00cf\u00d4\u00d6\u00d9\u00db\u00dc\u00c7\u0152]\/;\n\t\t\t\t\t\t\/\/ Pr\u00e9f\u00e9rer les versions ASCII si double\n\t\t\t\t\t\tconst asciiMap = new Map();\n\t\t\t\t\t\tuniqueSujets.forEach((s) => {\n\t\t\t\t\t\t\tconst ascii = (s || '').normalize('NFD').replace(\/[\\u0300-\\u036f]\/g, '');\n\t\t\t\t\t\t\tif (!asciiMap.has(ascii)) asciiMap.set(ascii, s);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tlet asciiPreferred = Array.from(asciiMap.values());\n\t\t\t\t\t\t\/\/ Retirer explicitement ceux qui contiennent des caract\u00e8res FR si une alternative ASCII existe\n\t\t\t\t\t\tasciiPreferred = asciiPreferred.filter((s) => !frenchChars.test(s) || !asciiMap.has(s));\n\t\t\t\t\t\t\/\/ Heuristique: garder uniquement les sujets \"propres\" ASCII\n\t\t\t\t\t\tuniqueSujets = asciiPreferred.filter((s) => \/^[A-Za-z0-9 ,&'()\\-]+$\/.test(s));\n\t\t\t\t\t}\n\t\t\t\t\t\/\/ Nettoyer d'abord les \u00e9l\u00e9ments existants (hors item par d\u00e9faut)\n\t\t\t\t\tsujetList.querySelectorAll('.acf-dropdown-item:not([data-value=\"\"])').forEach(el => el.remove());\n\t\t\t\t\tconst sujetItems = uniqueSujets.map(sujet => `\n\t\t\t\t\t\t<div class=\"acf-dropdown-item\" data-value=\"${sujet}\">\n\t\t\t\t\t\t\t<span class=\"acf-dropdown-text\">${sujet}<\/span>\n\t\t\t\t\t\t\t<svg class=\"acf-radio\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"15\" height=\"16\" viewBox=\"0 0 15 16\" fill=\"none\">\n\t\t\t\t\t\t\t\t<circle cx=\"7.5\" cy=\"8\" r=\"7\" stroke=\"#323332\"\/>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t`).join('');\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Ajouter apr\u00e8s l'\u00e9l\u00e9ment par d\u00e9faut\n\t\t\t\t\tconst defaultItem = sujetList.querySelector('.acf-dropdown-item[data-value=\"\"]');\n\t\t\t\t\tif (defaultItem) {\n\t\t\t\t\t\t\/\/ S'assurer que le texte de l'\u00e9l\u00e9ment par d\u00e9faut est \"R\u00e9initialiser\"\/\"Reset\"\n\t\t\t\t\t\tconst resetText = currentLang === 'en' ? 'Reset' : 'R\u00e9initialiser';\n\t\t\t\t\t\tconst defaultText = defaultItem.querySelector('.acf-dropdown-text');\n\t\t\t\t\t\tif (defaultText) {\n\t\t\t\t\t\t\tdefaultText.textContent = resetText;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefaultItem.insertAdjacentHTML('afterend', sujetItems);\n\t\t\t\t\t}\n\t\t\t\t\t\/\/ Synchroniser la s\u00e9lection apr\u00e8s le chargement\n\t\t\t\t\tsyncSujetSelection();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Fonction de synchronisation de la s\u00e9lection (comme dans evenements)\n\t\t\tfunction syncSujetSelection() {\n\t\t\t\tconst sujetList = app.querySelector(\".acf-sujet-dropdown .acf-dropdown-menu\");\n\t\t\t\tif (!sujetList) return;\n\t\t\t\tconst val = selectedSujet || '';\n\t\t\t\tsujetList.querySelectorAll('.acf-dropdown-item').forEach(item => {\n\t\t\t\t\tconst ev = item.getAttribute('data-value') || '';\n\t\t\t\t\titem.classList.toggle('selected', ev === val);\n\t\t\t\t});\n\t\t\t\t\/\/ Mettre \u00e0 jour le texte du trigger\n\t\t\t\t\/\/ Si selectedSujet est vide, afficher \"Sujet\"\/\"Subject\" ou \"Type\" selon la page\n\t\t\t\t\/\/ Sinon, afficher le nom de l'\u00e9l\u00e9ment s\u00e9lectionn\u00e9 (qui est la valeur de data-value)\n\t\t\t\tconst triggerText = sujetDropdown.querySelector('.acf-dropdown-text');\n\t\t\t\tif (triggerText) {\n\t\t\t\t\t\/\/ Forcer la mise \u00e0 jour avec la bonne valeur\n\t\t\t\t\tif (selectedSujet && selectedSujet !== '') {\n\t\t\t\t\t\t\/\/ Afficher le nom de l'\u00e9l\u00e9ment s\u00e9lectionn\u00e9 (la valeur de data-value)\n\t\t\t\t\t\ttriggerText.textContent = selectedSujet;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t\/\/ Afficher \"Sujet\"\/\"Subject\" ou \"Type\" selon la page\n\t\t\t\t\t\t\/\/ S'assurer qu'on utilise bien app.dataset.filterText et non le texte de l'\u00e9l\u00e9ment\n\t\t\t\t\t\tconst filterText = app.dataset.filterText || 'Sujet';\n\t\t\t\t\t\ttriggerText.textContent = filterText;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Initialisation des dropdowns\n\t\t\tfunction initDropdowns() {\n\t\t\t\tconst dropdowns = Array.from(app.querySelectorAll('.acf-dropdown'));\n\t\t\t\tif (!dropdowns.length) return;\n\t\t\t\tfunction closeAll() { dropdowns.forEach(d => d.classList.remove('active')); }\n\t\t\t\t\/\/ D\u00e9l\u00e9gu\u00e9: ouverture\/fermeture sur clic trigger\n\t\t\t\tapp.addEventListener('click', (e) => {\n\t\t\t\t\tconst trigger = e.target.closest('.acf-dropdown-trigger');\n\t\t\t\t\tif (trigger && app.contains(trigger)) {\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\tconst dd = trigger.closest('.acf-dropdown');\n\t\t\t\t\t\tif (!dd) return;\n\t\t\t\t\t\tconst wasActive = dd.classList.contains('active');\n\t\t\t\t\t\tcloseAll();\n\t\t\t\t\t\tif (!wasActive) {\n\t\t\t\t\t\t\tdd.classList.add('active');\n\t\t\t\t\t\t\t\/\/ Synchroniser la s\u00e9lection lors de l'ouverture (comme dans evenements)\n\t\t\t\t\t\t\tif (dd.classList.contains('acf-sujet-dropdown')) {\n\t\t\t\t\t\t\t\tsyncSujetSelection();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst menu = e.target.closest('.acf-dropdown-menu');\n\t\t\t\t\tif (menu && app.contains(menu)) {\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\/\/ clic ext\u00e9rieur\n\t\t\t\tdocument.addEventListener('click', closeAll);\n\t\t\t\t\/\/ touche Echap\n\t\t\t\tdocument.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeAll(); });\n\t\t\t}\n\n\t\t\t\/\/ Initialisation des filtres\n\t\t\tfunction initFilters() {\n\t\t\t\t\/\/ Filtre r\u00e9gion\n\t\t\t\tapp.addEventListener('click', async (e) => {\n\t\t\t\t\tconst regionItem = e.target.closest('.acf-region-item');\n\t\t\t\t\tif (regionItem) {\n\t\t\t\t\t\tconst value = regionItem.dataset.value;\n\t\t\t\t\t\tselectedRegion = selectedRegion === value ? \"\" : value;\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Mettre \u00e0 jour l'affichage\n\t\t\t\t\t\tapp.querySelectorAll('.acf-region-item').forEach(item => {\n\t\t\t\t\t\t\titem.classList.toggle('selected', item.dataset.value === selectedRegion);\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Mettre \u00e0 jour le texte du trigger\n\t\t\t\t\t\tconst triggerText = regionDropdown.querySelector('.acf-dropdown-text');\n\t\t\t\t\t\ttriggerText.textContent = selectedRegion || (getLang() === 'en' ? 'Region' : 'R\u00e9gion');\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Appliquer le filtre\n\t\t\t\t\t\tconst results = await filterPosts();\n\t\t\t\t\t\trenderPosts(results);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t\/\/ Filtre sujet\n\t\t\t\tapp.addEventListener('click', async (e) => {\n\t\t\t\t\tconst sujetItem = e.target.closest('.acf-dropdown-item');\n\t\t\t\t\tif (sujetItem) {\n\t\t\t\t\t\t\/\/ R\u00e9cup\u00e9rer la valeur depuis data-value (pas le texte)\n\t\t\t\t\t\tconst value = sujetItem.getAttribute('data-value') || '';\n\t\t\t\t\t\t\/\/ Assigner directement la valeur (comme dans evenements)\n\t\t\t\t\t\tselectedSujet = value;\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Synchroniser la s\u00e9lection (comme dans evenements)\n\t\t\t\t\t\tsyncSujetSelection();\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Forcer la mise \u00e0 jour du trigger apr\u00e8s syncSujetSelection pour \u00e9viter qu'il soit \u00e9cras\u00e9\n\t\t\t\t\t\t\/\/ (au cas o\u00f9 un autre gestionnaire d'\u00e9v\u00e9nements mettrait \u00e0 jour le trigger)\n\t\t\t\t\t\t\/\/ Utiliser requestAnimationFrame pour s'assurer que la mise \u00e0 jour se fait apr\u00e8s tous les autres gestionnaires\n\t\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\t\tconst triggerText = sujetDropdown.querySelector('.acf-dropdown-text');\n\t\t\t\t\t\t\tif (triggerText) {\n\t\t\t\t\t\t\t\tif (selectedSujet && selectedSujet !== '') {\n\t\t\t\t\t\t\t\t\ttriggerText.textContent = selectedSujet;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\/\/ S'assurer qu'on utilise bien app.dataset.filterText et non le texte de l'\u00e9l\u00e9ment\n\t\t\t\t\t\t\t\t\tconst filterText = app.dataset.filterText || 'Sujet';\n\t\t\t\t\t\t\t\t\ttriggerText.textContent = filterText;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Appliquer le filtre\n\t\t\t\t\t\tconst results = await filterPosts();\n\t\t\t\t\t\trenderPosts(results);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t\/\/ Filtre date\n\t\t\t\tapp.addEventListener('click', (e) => {\n\t\t\t\t\tconst dateItem = e.target.closest('.acf-dropdown-item-date');\n\t\t\t\t\tif (dateItem) {\n\t\t\t\t\t\tconst value = dateItem.dataset.value;\n\t\t\t\t\t\tconst type = dateItem.dataset.type;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (type === 'preset') {\n\t\t\t\t\t\t\tselectedDateFilter = value;\n\t\t\t\t\t\t\tselectedDateFrom = \"\";\n\t\t\t\t\t\t\tselectedDateTo = \"\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Mettre \u00e0 jour l'affichage\n\t\t\t\t\t\tapp.querySelectorAll('.acf-dropdown-item-date').forEach(item => {\n\t\t\t\t\t\t\titem.classList.toggle('selected', item.dataset.value === value);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t\/\/ Boutons d'action date\n\t\t\t\tconst applyBtn = app.querySelector('.acf-date-apply');\n\t\t\t\tconst resetBtn = app.querySelector('.acf-date-reset');\n\t\t\t\t\n\t\t\t\tif (applyBtn) {\n\t\t\t\t\tapplyBtn.addEventListener('click', () => {\n\t\t\t\t\t\tconst fromInput = app.querySelector('.acf-date-from');\n\t\t\t\t\t\tconst toInput = app.querySelector('.acf-date-to');\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (fromInput.value && toInput.value) {\n\t\t\t\t\t\t\tselectedDateFilter = 'custom';\n\t\t\t\t\t\t\tselectedDateFrom = fromInput.value;\n\t\t\t\t\t\t\tselectedDateTo = toInput.value;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tconst results = filterPosts();\n\t\t\t\t\t\t\trenderPosts(results);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (resetBtn) {\n\t\t\t\t\tresetBtn.addEventListener('click', () => {\n\t\t\t\t\t\tselectedDateFilter = null;\n\t\t\t\t\t\tselectedDateFrom = \"\";\n\t\t\t\t\t\tselectedDateTo = \"\";\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Reset les inputs\n\t\t\t\t\t\tconst fromInput = app.querySelector('.acf-date-from');\n\t\t\t\t\t\tconst toInput = app.querySelector('.acf-date-to');\n\t\t\t\t\t\tif (fromInput) fromInput.value = \"\";\n\t\t\t\t\t\tif (toInput) toInput.value = \"\";\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Reset l'affichage\n\t\t\t\t\t\tapp.querySelectorAll('.acf-dropdown-item-date').forEach(item => {\n\t\t\t\t\t\t\titem.classList.remove('selected');\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst results = filterPosts();\n\t\t\t\t\t\trenderPosts(results);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Recherche\n\t\t\tif (searchInput) {\n\t\t\t\tsearchInput.addEventListener('input', async () => {\n\t\t\t\t\tconst results = await filterPosts();\n\t\t\t\t\trenderPosts(results);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t\/\/ Bouton de recherche\n\t\t\tif (submitBtn) {\n\t\t\t\tsubmitBtn.addEventListener('click', async () => {\n\t\t\t\t\tconst results = await filterPosts();\n\t\t\t\t\trenderPosts(results);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t\/\/ Bouton \"Voir plus\"\n\t\t\tif (loadMoreBtn) {\n\t\t\t\tloadMoreBtn.addEventListener('click', () => {\n\t\t\t\t\tcurrentPage++;\n\t\t\t\t\trenderPosts(filteredPosts, true);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t\/\/ Chargement des posts\n\t\t\tasync function fetchPosts() {\n\t\t\t\ttry {\n\t\t\t\t\t\/\/ masquer la liste pendant le chargement pour \u00e9viter le flicker FR\u2192EN et garder la hauteur\n\t\t\t\t\tif (listEl) {\n\t\t\t\t\t\tlistEl.style.visibility = 'hidden';\n\t\t\t\t\t\tif (!listEl.style.minHeight) listEl.style.minHeight = '400px';\n\t\t\t\t\t\tlistEl.innerHTML = '';\n\t\t\t\t\t}\n\t\t\t\t\t\/\/ annuler toute requ\u00eate pr\u00e9c\u00e9dente\n\t\t\t\t\tif (postsFetchController) {\n\t\t\t\t\t\tpostsFetchController.abort();\n\t\t\t\t\t}\n\t\t\t\t\tpostsFetchController = new AbortController();\n\t\t\t\t\tconst { signal } = postsFetchController;\n\t\t\t\t\t\/\/ URL avec support WPML pour les traductions ACF + cache buster + champs limit\u00e9s pour rapidit\u00e9\n\t\t\t\t\tconst ts = Date.now();\n\t\t\t\t\tconst base = `\/wp-json\/wp\/v2\/${cpt}`;\n\t\t\t\t\tlang = getLang();\n\t\t\t\t\tconst apiUrl = lang === 'en' \n\t\t\t\t\t\t? `${base}?lang=en&per_page=100&acf_format=standard&_cb=${ts}`\n\t\t\t\t\t\t: `${base}?per_page=100&acf_format=standard&_cb=${ts}`;\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tconst response = await fetch(apiUrl, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache' }, credentials: 'same-origin', signal });\n\t\t\t\t\tif (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);\n\t\t\t\t\tconst posts = await response.json();\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Filtrer imm\u00e9diatement les posts avec seulement des cat\u00e9gories \"uncategorized\"\n\t\t\t\t\tconst validPosts = posts.filter(p => hasValidCategories(p));\n\t\t\t\t\tallPosts = validPosts;\n\t\t\t\t\tfilteredPosts = validPosts;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Pr\u00e9-charger toutes les villes en parall\u00e8le (visible en navigation priv\u00e9e via endpoint single)\n\t\t\t\t\tawait Promise.all(validPosts.map(post => getPostCityCached(post, lang)));\n\t\t\t\t\t\n\t\t\t\t\tawait loadFilterOptions();\n\t\t\t\t\t\/\/ Stabilize: run through the same render path used after filtering\n\t\t\t\t\tconst stable = await filterPosts();\n\t\t\t\t\t\/\/ Rendu final avec villes et dates stabilis\u00e9es\n\t\t\t\t\tawait renderPosts(stable);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error?.name === 'AbortError') {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst errorText = getLang() === 'en' ? 'Error loading content' : 'Erreur lors du chargement du contenu';\n\t\t\t\t\tlistEl.innerHTML = `<p>${errorText}<\/p>`;\n\t\t\t\t} finally {\n\t\t\t\t\t\/\/ r\u00e9v\u00e9ler la liste une fois pr\u00eat\n\t\t\t\t\tif (listEl) listEl.style.visibility = '';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ Fonction pour cacher les cartes statiques avec seulement des cat\u00e9gories \"uncategorized\" SEULEMENT dans ce container\n\t\t\tfunction hideStaticUncategorizedCards() {\n\t\t\t\t\/\/ Ne pas s'ex\u00e9cuter en mode append\n\t\t\t\tif (window.__shouldStopReapplying) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\/\/ Chercher SEULEMENT dans le container parent de ce shortcode, EXCLURE les cartes dynamiques dans listEl\n\t\t\t\tconst staticCards = app.parentElement ? \n\t\t\t\t\tArray.from(app.parentElement.querySelectorAll('.acf-card, .acf-card-wrapper, .acf-a-la-une-grid')).filter(card => {\n\t\t\t\t\t\t\/\/ Exclure toute carte qui est dans listEl (les cartes dynamiquement g\u00e9n\u00e9r\u00e9es)\n\t\t\t\t\t\t\/\/ Si c'est un wrapper, v\u00e9rifier si une de ses cartes enfants est dans listEl\n\t\t\t\t\t\tif (card.classList.contains('acf-card-wrapper')) {\n\t\t\t\t\t\t\tconst innerCard = card.querySelector('.acf-card');\n\t\t\t\t\t\t\treturn !listEl.contains(innerCard);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn !listEl.contains(card);\n\t\t\t\t\t}) :\n\t\t\t\t\t[];\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tstaticCards.forEach(card => {\n\t\t\t\t\t\/\/ V\u00e9rifier le contenu de la carte pour d\u00e9tecter \"uncategorized\"\n\t\t\t\t\tconst cardText = card.textContent.toLowerCase();\n\t\t\t\t\tconst titleEl = card.querySelector('.acf-title, [class*=\"title\"], h1, h2, h3, h4, h5, h6');\n\t\t\t\t\tconst titleText = titleEl ? titleEl.textContent.toLowerCase() : '';\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Chercher les cat\u00e9gories\/tags dans la carte\n\t\t\t\t\tconst tags = card.querySelectorAll('.acf-chip, .tag, [class*=\"tag\"], [class*=\"category\"]');\n\t\t\t\t\tconst tagTexts = Array.from(tags).map(tag => tag.textContent.toLowerCase().trim());\n\t\t\t\t\t\n\t\t\t\t\t\/\/ V\u00e9rifier si la carte contient \"uncategorized\" dans le texte\n\t\t\t\t\tconst containsUncategorized = cardText.includes('uncategorized') || \n\t\t\t\t\t\tcardText.includes('non cat\u00e9goris\u00e9') || \n\t\t\t\t\t\tcardText.includes('non categorise') ||\n\t\t\t\t\t\ttitleText.includes('uncategorized');\n\t\t\t\t\t\n\t\t\t\t\t\/\/ V\u00e9rifier si la carte n'a que des cat\u00e9gories \"uncategorized\"\n\t\t\t\t\tconst hasOnlyUncategorized = tagTexts.length > 0 && tagTexts.every(text => \n\t\t\t\t\t\ttext.includes('uncategorized') || \n\t\t\t\t\t\ttext.includes('non cat\u00e9goris\u00e9') || \n\t\t\t\t\t\ttext.includes('non categorise') ||\n\t\t\t\t\t\ttext === 'cat\u00e9gorie 3' || \n\t\t\t\t\t\ttext === 'category 3'\n\t\t\t\t\t);\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Ou si elle n'a aucune cat\u00e9gorie visible du tout mais semble \u00eatre \"uncategorized\"\n\t\t\t\t\tconst hasNoCategories = tagTexts.length === 0;\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Condition plus large : cacher si contient \"uncategorized\" OU pas de cat\u00e9gories OU que des cat\u00e9gories uncategorized\n\t\t\t\t\tif (containsUncategorized || hasOnlyUncategorized || hasNoCategories) {\n\t\t\t\t\t\t\n\t\t\t\t\t\t\/\/ Approche plus agressive : supprimer compl\u00e8tement du DOM\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcard.remove();\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\/\/ Fallback : cacher avec !important\n\t\t\t\t\t\t\tcard.style.setProperty('display', 'none', 'important');\n\t\t\t\t\t\t\tcard.style.setProperty('visibility', 'hidden', 'important');\n\t\t\t\t\t\t\tcard.style.setProperty('opacity', '0', 'important');\n\t\t\t\t\t\t\tcard.style.setProperty('height', '0', 'important');\n\t\t\t\t\t\t\tcard.style.setProperty('overflow', 'hidden', 'important');\n\t\t\t\t\t\t\tcard.style.setProperty('margin', '0', 'important');\n\t\t\t\t\t\t\tcard.style.setProperty('padding', '0', 'important');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t\/\/ Fonction pour ne garder QUE les cartes actuellement rendues par ce shortcode\n\t\t\tfunction cleanupRenderedCards() {\n\t\t\t\t\/\/ Ne pas faire le cleanup en mode append pour \u00e9viter de supprimer les posts d\u00e9j\u00e0 affich\u00e9s\n\t\t\t\tif (window.__shouldStopReapplying) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (isAppending) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tconst scope = app.parentElement || app;\n\t\t\t\tconst validIds = new Set(currentlyRenderedPosts.map(p => String(p.id)));\n\t\t\t\t\n\t\t\t\tconst allCards = scope.querySelectorAll('.acf-card');\n\t\t\t\t\n\t\t\t\t\/\/ Retirer toute carte du scope qui n'est pas DANS notre liste rendue visuelle\n\t\t\t\tallCards.forEach((card) => {\n\t\t\t\t\tconst inOurVisualList = listEl.contains(card); \/\/ doit \u00eatre dans notre grille\n\t\t\t\t\t\n\t\t\t\t\t\/\/ PROTECTION CRITIQUE: Si la carte est dans listEl, elle est VALIDE par d\u00e9finition\n\t\t\t\t\t\/\/ Ne jamais supprimer une carte qui est dans listEl, m\u00eame si elle n'est pas dans validIds\n\t\t\t\t\t\/\/ (car validIds peut ne pas \u00eatre \u00e0 jour au moment o\u00f9 le cleanup s'ex\u00e9cute)\n\t\t\t\t\tif (inOurVisualList) {\n\t\t\t\t\t\t\/\/ V\u00e9rifier seulement les tags uncategorized, mais ne pas supprimer la carte\n\t\t\t\t\t\tlet hasUncat = false;\n\t\t\t\t\t\tcard.querySelectorAll('.acf-chip').forEach(t => {\n\t\t\t\t\t\t\tconst tx = (t.textContent||'').toLowerCase();\n\t\t\t\t\t\t\tif (tx.includes('uncategorized') || tx.includes('non cat\u00e9goris\u00e9') || tx.includes('non categorise')) hasUncat = true;\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\/\/ Seulement supprimer les tags uncategorized, pas la carte elle-m\u00eame\n\t\t\t\t\t\tif (hasUncat) {\n\t\t\t\t\t\t\tcard.querySelectorAll('.acf-chip').forEach(t => {\n\t\t\t\t\t\t\t\tconst tx = (t.textContent||'').toLowerCase();\n\t\t\t\t\t\t\t\tif (tx.includes('uncategorized') || tx.includes('non cat\u00e9goris\u00e9') || tx.includes('non categorise')) {\n\t\t\t\t\t\t\t\t\tt.remove();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn; \/\/ Ne pas supprimer cette carte, elle est dans listEl\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Si la carte n'est PAS dans listEl, alors on peut la supprimer si elle n'est pas valide\n\t\t\t\t\t\/\/ Essayer de d\u00e9tecter un id depuis diff\u00e9rentes sources\n\t\t\t\t\tlet cardId = card.getAttribute('data-post-id');\n\t\t\t\t\tif (!cardId) {\n\t\t\t\t\t\tconst idFromDate = card.querySelector('.acf-date[data-post-id]')?.getAttribute('data-post-id');\n\t\t\t\t\t\tconst idFromPlus = card.querySelector('[data-post-id]')?.getAttribute('data-post-id');\n\t\t\t\t\t\tcardId = idFromDate || idFromPlus || '';\n\t\t\t\t\t}\n\t\t\t\t\tconst belongsToRender = cardId && validIds.has(String(cardId));\n\t\t\t\t\t\/\/ Si la carte contient un tag uncategorized, marque-la invalide\n\t\t\t\t\tlet hasUncat = false;\n\t\t\t\t\tcard.querySelectorAll('.acf-chip').forEach(t => {\n\t\t\t\t\t\tconst tx = (t.textContent||'').toLowerCase();\n\t\t\t\t\t\tif (tx.includes('uncategorized') || tx.includes('non cat\u00e9goris\u00e9') || tx.includes('non categorise')) hasUncat = true;\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\t\/\/ Supprimer seulement si la carte n'est pas dans listEl ET n'est pas valide\n\t\t\t\t\tif (!belongsToRender || hasUncat) {\n\t\t\t\t\t\ttry { card.remove(); } catch(e) { card.style.setProperty('display','none','important'); }\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\t\/\/ Retirer d'\u00e9ventuels tags uncategorized r\u00e9inject\u00e9s\n\t\t\t\tlistEl.querySelectorAll('.acf-chip').forEach(tagEl => {\n\t\t\t\t\tconst txt = (tagEl.textContent || '').toLowerCase();\n\t\t\t\t\tif (txt.includes('uncategorized') || txt.includes('non cat\u00e9goris\u00e9') || txt.includes('non categorise')) {\n\t\t\t\t\t\ttagEl.remove();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t\/\/ Observer pour surveiller l'ajout de nouvelles cartes SEULEMENT dans le container parent\n\t\t\tconst cardObserver = new MutationObserver((mutations) => {\n\t\t\t\tlet hasNewCards = false;\n\t\t\t\tlet hasRemovedNodes = false;\n\t\t\t\t\n\t\t\t\tmutations.forEach((mutation) => {\n\t\t\t\t\tif (mutation.type === 'childList') {\n\t\t\t\t\t\t\/\/ V\u00e9rifier les n\u0153uds supprim\u00e9s\n\t\t\t\t\t\tif (mutation.removedNodes.length > 0) {\n\t\t\t\t\t\t\thasRemovedNodes = true;\n\t\t\t\t\t\t\tmutation.removedNodes.forEach((node) => {\n\t\t\t\t\t\t\t\tif (node.nodeType === 1) {\n\t\t\t\t\t\t\t\t\tconst isCard = node.matches && (node.matches('.acf-card, .acf-card-wrapper') || node.querySelector('.acf-card, .acf-card-wrapper'));\n\t\t\t\t\t\t\t\t\tif (isCard) {\n\t\t\t\t\t\t\t\t\t\t\/\/ Carte supprim\u00e9e d\u00e9tect\u00e9e\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tmutation.addedNodes.forEach((node) => {\n\t\t\t\t\t\t\tif (node.nodeType === 1) { \/\/ Element node\n\t\t\t\t\t\t\t\t\/\/ V\u00e9rifier si le noeud ajout\u00e9 est une carte ou contient des cartes\n\t\t\t\t\t\t\t\tif (node.matches && (node.matches('.acf-card, .acf-card-wrapper, .acf-a-la-une-grid') || \n\t\t\t\t\t\t\t\t\tnode.querySelector('.acf-card, .acf-card-wrapper, .acf-a-la-une-grid'))) {\n\t\t\t\t\t\t\t\t\thasNewCards = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif (hasNewCards) {\n\t\t\t\t\t\/\/ NE PAS ex\u00e9cuter ces fonctions en mode append\n\t\t\t\t\tif (!window.__shouldStopReapplying) {\n\t\t\t\t\t\t\/\/ Attendre un peu que le contenu soit compl\u00e8tement ajout\u00e9\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\thideStaticUncategorizedCards();\n\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\/\/ NE PAS appeler cleanupRenderedCards si on est en mode append\n\t\t\t\t\t\tif (!isAppending) {\n\t\t\t\t\t\t\tsetTimeout(cleanupRenderedCards, 120);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t\/\/ Observer SEULEMENT le container parent de ce shortcode, pas toute la page\n\t\t\tconst observerTarget = app.parentElement || app;\n\t\t\tcardObserver.observe(observerTarget, {\n\t\t\t\tchildList: true,\n\t\t\t\tsubtree: true\n\t\t\t});\n\n\t\t\t\/\/ Initialisation\n\t\t\tinitDropdowns();\n\t\t\tinitFilters();\n\t\t\thideStaticUncategorizedCards(); \/\/ Cacher les cartes statiques d\u00e8s le d\u00e9but\n\t\t\t\n\t\t\t\/\/ R\u00e9ex\u00e9cuter apr\u00e8s un d\u00e9lai au cas o\u00f9 les cartes statiques sont ajout\u00e9es plus tard\n\t\t\tsetTimeout(hideStaticUncategorizedCards, 500);\n\t\t\tsetTimeout(hideStaticUncategorizedCards, 1000);\n\t\t\tsetTimeout(hideStaticUncategorizedCards, 2000);\n\t\t\t\n\t\t\tfetchPosts();\n\t\t});\n\t});\n\t<\/script>\n\n\t<style>\n\t.acf-archive-title {\n\t  color: #D30C8C;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 32px !important;\n\t  font-style: normal;\n\t  font-weight: 600 !important;\n\t  line-height: 35px;\n\t  margin: 0;\n\t  flex: 0 0 30%;\n\t  min-width: 200px;\n\t}\n\n\t.acf-archive-header {\n\t  display: flex;\n\t  align-items: center;\n\t  justify-content: space-between;\n\t  flex-wrap: wrap;\n\t  margin-bottom: 30px;\n\t  gap: 0;\n\t}\n\n\t.acf-archive-filters {\n\t  display: flex;\n\t  align-items: center;\n\t  background: #F5F6F7;\n\t  border-radius: 8px;\n\t  padding: 8px 12px;\n\t  gap: 20px;\n\t  width:100%;\n\t}\n\n\t\/* Barre de recherche *\/\n\t.acf-archive-filters input.acf-search {\n\t  flex: 1;\n\t  min-width: 200px;\n\t  padding: 0 0 0 40px;\n\t  border: none;\n\t  border-radius: 25px;\n\t  font-size: 14px;\n\t  background: transparent;\n\t  background-image: url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='20' height='20' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M18.9881 18.6236L14.1712 13.8067C15.5448 12.227 16.2514 10.1758 16.1421 8.08528C16.0328 5.9948 15.1161 4.02842 13.5852 2.60065C12.0544 1.17287 10.0289 0.395254 7.93592 0.431707C5.8429 0.46816 3.84579 1.31584 2.36557 2.79605C0.885357 4.27627 0.0376792 6.27338 0.00122609 8.3664C-0.035227 10.4594 0.742392 12.4848 2.17016 14.0157C3.59794 15.5466 5.56432 16.4633 7.6548 16.5726C9.74529 16.6819 11.7966 15.9753 13.3762 14.6017L18.1931 19.4186C18.2997 19.5179 18.4407 19.572 18.5865 19.5694C18.7322 19.5669 18.8712 19.5078 18.9743 19.4048C19.0774 19.3017 19.1364 19.1627 19.139 19.017C19.1415 18.8712 19.0874 18.7302 18.9881 18.6236ZM1.15308 8.52106C1.15308 7.14895 1.55996 5.80766 2.32226 4.66679C3.08456 3.52593 4.16805 2.63673 5.43571 2.11165C6.70338 1.58656 8.09828 1.44918 9.44402 1.71686C10.7898 1.98455 12.0259 2.64528 12.9961 3.61551C13.9664 4.58574 14.6271 5.82188 14.8948 7.16762C15.1625 8.51337 15.0251 9.90827 14.5 11.1759C13.9749 12.4436 13.0857 13.5271 11.9448 14.2894C10.804 15.0517 9.46269 15.4586 8.09058 15.4586C6.25133 15.4563 4.48804 14.7247 3.18749 13.4241C1.88694 12.1236 1.15531 10.3603 1.15308 8.52106Z' fill='black'\/%3E%3C\/svg%3E\");\n\t  background-repeat: no-repeat;\n\t  background-position: 12px center;\n\t  background-size: 16px;\n\t  margin-right: 0;\n\t}\n\t\t\t\n\t.acf-archive-filters-recherche {\n\t\tdisplay: flex;\n\t\tflex: 0 0 60%;\n\t\tmargin-left: auto;\n\t\tgap:16px;\n\t}\n\n\t\/* Dropdowns personnalis\u00e9s *\/\n\t.acf-dropdown {\n\t  position: relative;\n\t  flex: 0 0 auto;\n\t  cursor: pointer;\n\t}\n\n\t.acf-date-custom {\n\t  margin-bottom:16px;\n\t}\t\n\t\t\t\n\t.acf-dropdown-trigger {\n\t  display: flex;\n\t  align-items: center;\n\t  justify-content: space-between;\n\t  padding: 0 8px;\n\t  background: transparent;\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 14px !important;\n\t  font-style: normal;\n\t  font-weight: 400 !important;\n\t  line-height: 16px;\n\t  transition: all 0.2s;\n\t  gap: 8px;\n\t  position: relative;\n\t}\n\n\t.acf-dropdown-trigger:hover {\n\t  background-color: transparent;\n\t}\n\n\t.acf-dropdown-trigger:hover::after {\n\t  content: '';\n\t  position: absolute;\n\t  bottom: -4px;\n\t  left: 0;\n\t  right: 0;\n\t  height: 1px;\n\t  background-color: #333;\n\t  transform: scaleX(1);\n\t  transition: transform 0.2s ease;\n\t}\n\n\t.acf-date-from, .acf-date-to { cursor:pointer; }\n\t\t\t\n\t.acf-dropdown-trigger::after {\n\t  content: '';\n\t  position: absolute;\n\t  bottom: -4px;\n\t  left: 0;\n\t  right: 0;\n\t  height: 1px;\n\t  background-color: #333;\n\t  transform: scaleX(0);\n\t  transition: transform 0.2s ease;\n\t}\n\n\t.acf-dropdown.active .acf-dropdown-trigger::after { transform: scaleX(1); }\n\n\t.acf-dropdown-arrow {\n\t  transition: transform 0.3s ease;\n\t  color: #323332;\n\t  flex-shrink: 0;\n\t  display: flex;\n\t  align-items: center;\n\t  justify-content: center;\n\t}\n\n\t.acf-dropdown.active .acf-dropdown-arrow { transform: rotate(180deg); }\n\n\t.acf-dropdown-menu {\n\t  position: absolute;\n\t  top: 100%;\n\t  right: 0;\n\t  left: auto;\n\t  background: #ECEFF1;\n\t  border-radius: 12px;\n\t  opacity: 0;\n\t  visibility: hidden;\n\t  transform: translateY(-10px);\n\t  transition: all 0.2s;\n\t  z-index: 1000;\n\t  margin-top: 20px;\n\t  min-width: 250px;\n\t  padding:16px;\n\t}\n\n\t.acf-dropdown.active .acf-dropdown-menu {\n\t  opacity: 1;\n\t  visibility: visible;\n\t  transform: translateY(0);\n\t  cursor:pointer;\n\t}\n\n\t.acf-dropdown-item,\n\t.acf-dropdown-item-date {\n\t  display: flex;\n\t  align-items: center;\n\t  justify-content: space-between;\n\t  padding: 12px 16px;\n\t  cursor: pointer;\n\t  transition: background-color 0.2s;\n\t  border-radius: 8px;\n\t  gap: 12px;\n\t}\n\t\t\t\n\t.acf-dropdown-item-date {\n\t  background-color: rgba(211, 12, 140, 0.10);\n\t}\n\t.acf-dropdown-item-date:hover,\n\t.acf-dropdown-item-date.selected {\n\t  background-color: rgba(211, 12, 140, 0.30);\n\t}\n\n\t.acf-dropdown-item:hover { background-color: rgba(211, 12, 140, 0.10); }\n\t.acf-dropdown-item.selected { background-color: rgba(211, 12, 140, 0.10); }\n\n\t.acf-dropdown-item .acf-dropdown-text {\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 16px !important;\n\t  font-style: normal;\n\t  font-weight: 300 !important;\n\t  line-height: 20px;\n\t  flex: 1;\n\t}\n\t\t\t\n\t.acf-dropdown-item-date .acf-dropdown-text {\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 16px !important;\n\t  font-style: normal;\n\t  font-weight: 300 !important;\n\t  line-height: 20px;\n\t  flex: 1;\n\t  text-align:center;\t\t\n\t}\n\n\t.acf-radio { flex-shrink: 0; transition: all 0.2s ease; }\n\n\t\/* Styles pour le filtre R\u00e9gion (m\u00eame design que Format) *\/\n\t.acf-region-item {\n\t  display: flex;\n\t  align-items: center;\n\t  justify-content: space-between;\n\t  padding: 12px 16px;\n\t  cursor: pointer;\n\t  transition: background-color 0.2s;\n\t  border-radius: 8px;\n\t  gap: 12px;\n\t}\n\n\t.acf-region-item:hover {\n\t  background-color: rgba(211, 12, 140, 0.10);\n\t}\n\n\t.acf-region-item.selected {\n\t  background-color: rgba(211, 12, 140, 0.10);\n\t}\n\n\t.acf-region-item .acf-dropdown-text {\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 16px !important;\n\t  font-style: normal;\n\t  font-weight: 300 !important;\n\t  line-height: 20px;\n\t  flex: 1;\n\t}\n\n\t.acf-date-inputs {\n\t  display: flex;\n\t  align-items: center;\n\t  gap: 4px;\n\t  margin-bottom: 0;\n\t}\n\n\t.acf-date-field { display: flex; flex-direction: column; gap: 4px; }\n\n\t.acf-date-field label {\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 14px !important;\n\t  font-style: normal;\n\t  font-weight: 400 !important;\n\t  line-height: 16px;\n\t}\n\t\t\t\n\t.acf-date-presets {\n\t  margin-bottom:24px;\n\t  display:flex;\n\t  gap: 8px;\n\t  flex-direction:column;\n\t}\n\n\t.acf-date-field input[type=\"date\"] {\n\t  padding: 10px 12px;\n\t  border: 1px solid #B0BEC5;\n\t  border-radius: 4px;\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 12px !important;\n\t  font-style: normal;\n\t  font-weight: 400 !important;\n\t  line-height: 14px;\n\t  background: transparent;\n\t}\n\n\t.acf-date-separator {\n\t  color: #323332;\n\t  font-size: 18px;\n\t  font-weight: 500;\n\t  margin-top: 20px;\n\t}\n\t\t\t\n\t.acf-date-actions { display: flex; flex-direction: column; gap: 8px; }\n\n\t.acf-date-apply,\n\t.acf-date-reset {\n\t  padding: 12px 16px !important;\n\t  border: none;\n\t  border-radius: 8px !important;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 16px !important;\n\t  font-style: normal;\n\t  font-weight: 300 !important;\n\t  line-height: 20px;\n\t  cursor: pointer;\n\t  transition: all 0.2s;\n\t  width: 100%;\n\t}\n\n\t.acf-date-apply { background: rgba(211, 12, 140, 0.10); color: #D30C8C; }\n\t.acf-date-apply:hover { background: rgba(211, 12, 140, 0.30); color: #D30C8C; }\n\n\t.acf-date-reset { background: rgba(255, 255, 255, 0.55); color: #D30C8C; }\n\t.acf-date-reset:hover { color:#9B0C68; background-color: rgba(255, 255, 255, 0.95); }\n\n\t\/* Bouton s\u00e9par\u00e9 du bloc fusionn\u00e9 *\/\n\t.acf-archive-header .acf-submit {\n\t\talign-self: center;\n\t\tpadding: 10px 12px;\n\t\tborder: none;\n\t\tborder-radius: 8px;\n\t\tbackground: rgba(211, 12, 140, 0.10);\n\t\tcolor:#D30C8C;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 16px !important;\n\t  font-style: normal;\n\t  font-weight: 300 !important;\n\t  line-height: 20px;\n\t\tcursor: pointer;\n\t\ttransition: background 0.3s;\n\t\twhite-space: nowrap;\n\t\tflex: 0 0 auto;\n\t}\n\t.acf-archive-header .acf-submit:hover { background: rgba(211, 12, 140, 0.30); }\n\n\t\/* Focus states *\/\n\t.acf-archive-filters input:focus { outline: none; box-shadow: none; }\n\n\t\/* Cartes *\/\n\t.acf-archive-list {\n\t  display: grid;\n\t  grid-template-columns: repeat(3, 1fr);\n\t  gap: 20px;\n\t  margin-bottom: 30px;\n\t}\n\n\t.acf-card {\n\t  display: flex;\n\t  flex-direction: column;\n\t  border-radius: 12px;\n\t  text-decoration: none;\n\t  color: inherit;\n\t  transition: box-shadow 0.3s;\n\t  background: #F5F6F7;\n\t  box-shadow: 8px 8px 12px 0 rgba(231, 231, 233, 0.60) !important;\n\t  min-height: 415px;\n\t  cursor: pointer !important;\n\t}\n\t.acf-card:hover { box-shadow: 8px 8px 12px 0 rgba(160, 160, 167, 0.50) !important; }\n\n\t.acf-img-container {\n\t\tposition: relative;\n\t\twidth: 100%;\n\t}\n\t\t\n\t.acf-img {\n\t  width: 100%;\n\t  height: 170px !important;\n\t  object-fit: cover;\n\t  border-radius: 12px 12px 0 0 !important;\n\t}\n\t\t\n\t.acf-nom-prenom {\n    position: absolute;\n    bottom: 6px;\n    left: 12px;\n    color: #FFF;\n    font-family: \"TikTok Sans\" !important;\n    font-size: 10px !important;\n    font-style: normal;\n    font-weight: 400 !important;\n    line-height: 12px;\n    z-index: 2;\n\t\t}\n\t\t\n\t.acf-body {\n\t  flex: 1;\n\t  padding:16px;\n\t  justify-content: space-between;\n\t  display:flex;\n\t  flex-direction: column;\n\t}\n\t.acf-date-title-excerpt { display:flex; flex-direction:column; gap:8px; }\n\n\t\/* Styles pour la ville de l'\u00e9v\u00e9nement *\/\n\t.acf-ville-date {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tgap: 3px;\n\t\tflex-wrap: wrap;\n\t}\n\t.acf-ville {\n\t\tcolor: #323332;\n\t\tfont-family: \"TikTok Sans\" !important;\n\t\tfont-size: 10px !important;\n\t\tfont-style: normal;\n\t\tfont-weight: 400 !important;\n\t\tline-height: 12px;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t}\n\n\t.acf-ville::after {\n\t\tcontent: \", \"; \/* Format unifi\u00e9 : ville, 16 avril 2026 *\/\n\t}\n\n    \/* Styles publications retir\u00e9s *\/\n\n\t.acf-date {\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 10px !important;\n\t  font-style: normal;\n\t  font-weight: 400 !important;\n\t  line-height: 12px;\n\t}\n\t.acf-title {\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 22px !important;\n\t  font-style: normal;\n\t  font-weight: 600 !important;\n\t  line-height: 24px;\n\t}\n\t.acf-excerpt {\n\t  color: #607D8B;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 14px !important;\n\t  font-style: normal;\n\t  font-weight: 300 !important;\n\t  line-height: 16px;\n\t}\n\t.acf-plus { margin-top: auto; }\n\n\t.acf-plus-tags {\n\t\tdisplay: flex;\n\t\tflex-wrap:nowrap;\n\t\tjustify-content:space-between;\n\t\talign-items: center;\n\t}\n\t\t\t\t\t\t   \n\t\/* Styles pour le bouton plus dynamique dans les cartes *\/\n\t.button-plus-dynamique {\n\t\tdisplay: inline-block !important;\n\t\tcursor: pointer !important;\n\t\tposition: relative !important;\n\t\tpointer-events: auto !important;\n\t\tz-index: 10 !important;\n\t}\n\t\n\t.button-plus-dynamique .plus-icon {\n\t\tdisplay: inline-flex !important;\n\t\talign-items: center !important;\n\t\tjustify-content: center !important;\n\t\twidth: 37px !important;\n\t\theight: 37px !important;\n\t\tbackground-color: #FAE6F3 !important;\n\t\tborder-radius: 8px !important;\n\t\ttransition: all 0.3s ease !important;\n\t}\n\t\n\t.button-plus-dynamique .text-arrow {\n\t\tdisplay: none !important;\n\t\talign-items: center !important;\n\t\tgap: 8px !important;\n\t\tpadding: 8px 12px !important;\n\t\tbackground-color: rgba(211, 12, 140, 0.10) !important;\n\t\tborder-radius: 8px !important;\n\t\tcolor: #D30C8C !important;\n\t\tfont-family: \"TikTok Sans\", sans-serif !important;\n\t\tfont-size: 14px !important;\n\t\tfont-weight: 400 !important;\n\t\twhite-space: nowrap !important;\n\t}\n\t\n\t\/* Hover direct du bouton *\/\n\t.button-plus-dynamique:hover .plus-icon {\n\t\tdisplay: none !important;\n\t}\n\t.button-plus-dynamique:hover .text-arrow {\n\t\tdisplay: inline-flex !important;\n\t\tbackground-color: rgba(211, 12, 140, 0.30) !important;\n\t}\n\t\n\t\/* HOVER SUR LA CARTE PARENT *\/\n\t.acf-card:hover .button-plus-dynamique .plus-icon {\n\t\tdisplay: none !important;\n\t}\n\t.acf-card:hover .button-plus-dynamique .text-arrow {\n\t\tdisplay: inline-flex !important;\n\t\tbackground-color: rgba(211, 12, 140, 0.30) !important;\n\t}\n\t\n\t\/* Forcer le masquage SEULEMENT des cartes statiques uncategorized dans le contexte de ce shortcode *\/\n\t.acf-archive-app ~ .acf-card:not([data-post-id]),\n\t.acf-archive-app ~ .acf-card-wrapper:not([data-post-id]),\n\t.acf-archive-app ~ .acf-a-la-une-grid:not([data-post-id]),\n\t.acf-archive-app + .acf-card:not([data-post-id]),\n\t.acf-archive-app + .acf-card-wrapper:not([data-post-id]),\n\t.acf-archive-app + .acf-a-la-une-grid:not([data-post-id]) {\n\t\tdisplay: none !important;\n\t\tvisibility: hidden !important;\n\t\topacity: 0 !important;\n\t\theight: 0 !important;\n\t\toverflow: hidden !important;\n\t\tmargin: 0 !important;\n\t\tpadding: 0 !important;\n\t}\n\n\t\/* Voir plus *\/\n\t.acf-load-more-container { text-align: center; margin-top: 30px; }\n\t.acf-load-more {\n\t  padding: 10px 12px !important;\n\t  border-top: none;\n\t  border-left: none;\n\t  border-right: none;\n\t  border-bottom: 1px solid #323332;\n\t  border-radius: 0 !important;\n\t  color: #323332;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 14px !important;\n\t  font-style: normal;\n\t  font-weight: 400 !important;\n\t  line-height: 16px;\n\t  cursor: pointer;\n\t  transition: all 0.3s;\n\t  background-color: transparent;\n\t}\n\t.acf-load-more:hover { border-color:#D30C8C; color:#D30C8C; background-color:transparent;  }\n\t\t\n\t\/* Styles pour les cat\u00e9gories (m\u00eame design que les tags) *\/\n\t.acf-tags { display: flex; gap: 8px; flex-wrap: wrap; }\n\t.acf-chip {\n\t  padding: 4px 6px;\n\t  color: #455A64;\n\t  font-family: \"TikTok Sans\" !important;\n\t  font-size: 10px !important;\n\t  font-style: normal;\n\t  font-weight: 400 !important;\n\t  line-height: 12px;\n\t  border-radius: 100px;\n\t  white-space: nowrap;\n\t  background-color: #CFD8DC;\n\t}\n\n\t@media (max-width: 992px) {\n\t\t.acf-archive-filters-recherche {\n\t\t\tmargin-left:0;\n\t\t}\n\t  .acf-archive-list { grid-template-columns: repeat(2, 1fr); }\n\t  .acf-archive-header { flex-direction: column; align-items: stretch; gap: 20px; }\n\t  .acf-archive-title { flex: none; }\n\t  .acf-archive-filters {width: 85%; }\n\t  .acf-archive-filters input.acf-search { min-width: 150px; }\n\t  .acf-dropdown { width: 100px; }\n\t}\n\n\t@media (max-width: 768px) {\n\t  .acf-archive-list { grid-template-columns: 1fr; }\n\t  .acf-archive-filters { flex-direction: column; gap: 10px; }\n\t  .acf-archive-filters input.acf-search { min-width: 100%; margin-right: 0; margin-bottom: 5px; }\n\t  .acf-dropdown { width: 100%; }\n\t  .acf-archive-header .acf-submit { margin-left: 0; margin-top: 10px; }\n\t  .acf-date-inputs { gap: 8px; }\n\t  .acf-date-separator { margin: 0; }\n\t  .acf-dropdown-menu { right: auto; left: 0; }\n\t}\n\t<\/style>\n\n\t\t<style><\/style>\n\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Reports &amp; publications A structured overview of our activities, performance, and impact in recent years. Christa Wilson, Erick Santos | N\u00f3s &#8211; A Romantic Circus Tale | Duo Erick &amp; Christa \u00a9 Chris Robert<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-850","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Reports &amp; publications - En Piste<\/title>\n<meta name=\"description\" content=\"Reports: En Piste&#039;s studies, assessments and analyses on the circus arts sector. An overview of our publications and reflections.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/enpiste.qc.ca\/en\/reports\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Reports &amp; publications - En Piste\" \/>\n<meta property=\"og:description\" content=\"Reports: En Piste&#039;s studies, assessments and analyses on the circus arts sector. An overview of our publications and reflections.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/enpiste.qc.ca\/en\/reports\/\" \/>\n<meta property=\"og:site_name\" content=\"En Piste\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/EnPiste1\/\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-09T17:41:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1707\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/enpiste.qc.ca\/en\/reports\/\",\"url\":\"https:\/\/enpiste.qc.ca\/en\/reports\/\",\"name\":\"Reports &amp; publications - En Piste\",\"isPartOf\":{\"@id\":\"https:\/\/enpiste.qc.ca\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/enpiste.qc.ca\/en\/reports\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/enpiste.qc.ca\/en\/reports\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg\",\"datePublished\":\"2025-08-15T19:15:20+00:00\",\"dateModified\":\"2026-03-09T17:41:44+00:00\",\"description\":\"Reports: En Piste's studies, assessments and analyses on the circus arts sector. An overview of our publications and reflections.\",\"breadcrumb\":{\"@id\":\"https:\/\/enpiste.qc.ca\/en\/reports\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/enpiste.qc.ca\/en\/reports\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/enpiste.qc.ca\/en\/reports\/#primaryimage\",\"url\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg\",\"contentUrl\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/enpiste.qc.ca\/en\/reports\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/enpiste.qc.ca\/en\/homepage\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Reports &amp; publications\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/enpiste.qc.ca\/#website\",\"url\":\"https:\/\/enpiste.qc.ca\/\",\"name\":\"En piste\",\"description\":\"un art vivant, une communaut\u00e9 engag\u00e9e\",\"publisher\":{\"@id\":\"https:\/\/enpiste.qc.ca\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/enpiste.qc.ca\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/enpiste.qc.ca\/#organization\",\"name\":\"En piste\",\"url\":\"https:\/\/enpiste.qc.ca\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/enpiste.qc.ca\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/10\/Vector.png\",\"contentUrl\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/10\/Vector.png\",\"width\":337,\"height\":93,\"caption\":\"En piste\"},\"image\":{\"@id\":\"https:\/\/enpiste.qc.ca\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/EnPiste1\/\",\"https:\/\/www.linkedin.com\/in\/en-piste-regroupement-national-des-arts-du-cirque-821171144\/\",\"https:\/\/www.instagram.com\/enpistecirque\/?hl=fr-ca\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Reports &amp; publications - En Piste","description":"Reports: En Piste's studies, assessments and analyses on the circus arts sector. An overview of our publications and reflections.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/enpiste.qc.ca\/en\/reports\/","og_locale":"en_US","og_type":"article","og_title":"Reports &amp; publications - En Piste","og_description":"Reports: En Piste's studies, assessments and analyses on the circus arts sector. An overview of our publications and reflections.","og_url":"https:\/\/enpiste.qc.ca\/en\/reports\/","og_site_name":"En Piste","article_publisher":"https:\/\/www.facebook.com\/EnPiste1\/","article_modified_time":"2026-03-09T17:41:44+00:00","og_image":[{"width":2560,"height":1707,"url":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-scaled.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/enpiste.qc.ca\/en\/reports\/","url":"https:\/\/enpiste.qc.ca\/en\/reports\/","name":"Reports &amp; publications - En Piste","isPartOf":{"@id":"https:\/\/enpiste.qc.ca\/#website"},"primaryImageOfPage":{"@id":"https:\/\/enpiste.qc.ca\/en\/reports\/#primaryimage"},"image":{"@id":"https:\/\/enpiste.qc.ca\/en\/reports\/#primaryimage"},"thumbnailUrl":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg","datePublished":"2025-08-15T19:15:20+00:00","dateModified":"2026-03-09T17:41:44+00:00","description":"Reports: En Piste's studies, assessments and analyses on the circus arts sector. An overview of our publications and reflections.","breadcrumb":{"@id":"https:\/\/enpiste.qc.ca\/en\/reports\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/enpiste.qc.ca\/en\/reports\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/enpiste.qc.ca\/en\/reports\/#primaryimage","url":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg","contentUrl":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_DuoErickChrista_01-1024x683.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/enpiste.qc.ca\/en\/reports\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/enpiste.qc.ca\/en\/homepage\/"},{"@type":"ListItem","position":2,"name":"Reports &amp; publications"}]},{"@type":"WebSite","@id":"https:\/\/enpiste.qc.ca\/#website","url":"https:\/\/enpiste.qc.ca\/","name":"En piste","description":"un art vivant, une communaut\u00e9 engag\u00e9e","publisher":{"@id":"https:\/\/enpiste.qc.ca\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/enpiste.qc.ca\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/enpiste.qc.ca\/#organization","name":"En piste","url":"https:\/\/enpiste.qc.ca\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/enpiste.qc.ca\/#\/schema\/logo\/image\/","url":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/10\/Vector.png","contentUrl":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/10\/Vector.png","width":337,"height":93,"caption":"En piste"},"image":{"@id":"https:\/\/enpiste.qc.ca\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/EnPiste1\/","https:\/\/www.linkedin.com\/in\/en-piste-regroupement-national-des-arts-du-cirque-821171144\/","https:\/\/www.instagram.com\/enpistecirque\/?hl=fr-ca"]}]}},"_links":{"self":[{"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/pages\/850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/comments?post=850"}],"version-history":[{"count":0,"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/pages\/850\/revisions"}],"wp:attachment":[{"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/media?parent=850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}