{"id":826,"date":"2025-08-28T17:01:39","date_gmt":"2025-08-28T17:01:39","guid":{"rendered":"https:\/\/enpistedev.wpenginepowered.com\/festival-directory\/"},"modified":"2025-11-17T21:38:17","modified_gmt":"2025-11-17T21:38:17","slug":"festival-directory","status":"publish","type":"page","link":"https:\/\/enpiste.qc.ca\/en\/festival-directory\/","title":{"rendered":"Festival Directory"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"826\" class=\"elementor elementor-826 elementor-717\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dc3eff5 e-flex e-con-boxed e-con e-parent\" data-id=\"dc3eff5\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3faf91c e-flex e-con-boxed e-con e-parent\" data-id=\"3faf91c\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-4329def e-con-full e-flex e-con e-child\" data-id=\"4329def\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-ae86c1a e-con-full e-flex e-con e-child\" data-id=\"ae86c1a\" data-element_type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-f103c23 e-con-full e-flex e-con e-child\" data-id=\"f103c23\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9456179 elementor-widget elementor-widget-heading\" data-id=\"9456179\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Festival Directory<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-99207df elementor-widget__width-initial elementor-widget elementor-widget-text-editor\" data-id=\"99207df\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>An overview of the festivals that showcase the circus across the country<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7b68bee e-con-full e-flex e-con e-child\" data-id=\"7b68bee\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b2eae6a elementor-widget elementor-widget-image\" data-id=\"b2eae6a\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"750\" height=\"937\" src=\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg\" class=\"attachment-large size-large wp-image-4188\" alt=\"\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4e163bc elementor-absolute elementor-widget elementor-widget-text-editor\" data-id=\"4e163bc\" data-element_type=\"widget\" data-settings=\"{&quot;_position&quot;:&quot;absolute&quot;}\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p><span data-sheets-root=\"1\">Patrice Ducharme-Castonguay, H\u00e9lo\u00efse Binette, Louve Bergeron and Mark Breton | Folies Potag\u00e8res | LP Lemay \u00a9 S\u00e9bastien Chion<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-4abe6cb e-flex e-con-boxed e-con e-parent\" data-id=\"4abe6cb\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3db877a elementor-widget elementor-widget-shortcode\" data-id=\"3db877a\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">    <div class=\"acf-archive-festival-app\" \n         data-cpt=\"festival\"\n         data-search-button=\"Search\"\n         data-search-results=\"Search (0 results)\"\n         data-date-location=\"Date\"\n         data-duration=\"Duration\"\n         data-location=\"Location\"\n         data-reset=\"Reset\"\n         data-close=\"Close\"\n         data-filters=\"Province\"\n         data-origin=\"Origin\"\n         data-from=\"From\"\n         data-to=\"To\"\n           data-passed=\"Passed\"\n           data-coming-soon=\"Coming soon\"\n           data-all=\"All\"\n           data-mediation-label=\"Mediation Activity\"\n           data-diversity-label=\"Diversity\"\n           data-speech-label=\"Speech\">\n        \n        <!-- Header avec titre + filtres -->\n        <div class=\"acf-archive-header\">\n                            <h2 class=\"acf-archive-title\">Every Festivals<\/h2>\n                        <div class=\"acf-archive-filters-recherche\">\n                <div class=\"acf-archive-filters\">\n                    <input type=\"text\" class=\"acf-search\" placeholder=\"Search...\">\n                    \n                    <!-- Filtre Date & Lieu -->\n                    <div class=\"acf-dropdown acf-date-lieu-dropdown\">\n                        <div class=\"acf-dropdown-trigger\">\n                            <span class=\"acf-dropdown-text\">Date<\/span>\n                            <svg class=\"acf-dropdown-arrow\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"11\" height=\"7\" viewBox=\"0 0 11 7\" fill=\"none\">\n                                <path d=\"M1 0.857143L5.33333 5.5L10 0.5\" stroke=\"#323332\"\/>\n                            <\/svg>\n                        <\/div>\n                        <div class=\"acf-dropdown-menu\">\n                            <!-- Accord\u00e9on Date -->\n                            <div class=\"acf-accordion\">\n                                <div class=\"acf-accordion-header\">\n                                    <span>Date<\/span>\n                                    <svg class=\"acf-accordion-arrow\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"14\" height=\"16\" viewBox=\"0 0 14 16\" fill=\"none\">\n                                        <path d=\"M6.65669 15.6569L0.707413 9.70758C0.616383 9.61655 0.565243 9.49308 0.565243 9.36435C0.565243 9.23561 0.616383 9.11215 0.707413 9.02112C0.798442 8.93009 0.921906 8.87895 1.05064 8.87895C1.17938 8.87895 1.30284 8.93009 1.39387 9.02112L6.51482 14.1421L6.51482 0.66925C6.51926 0.543558 6.57231 0.424496 6.6628 0.337146C6.75329 0.249795 6.87415 0.200977 6.99992 0.200977C7.12569 0.200977 7.24655 0.249795 7.33704 0.337146C7.42753 0.424496 7.48058 0.543559 7.48501 0.669251L7.48501 14.1421L12.606 9.02112C12.697 8.93009 12.8205 8.87895 12.9492 8.87895C13.0779 8.87895 13.2014 8.93009 13.2924 9.02112C13.3835 9.11215 13.4346 9.23561 13.4346 9.36435C13.4346 9.49308 13.3835 9.61655 13.2924 9.70758L7.34315 15.6569C7.25212 15.7479 7.12865 15.799 6.99992 15.799C6.87118 15.799 6.74772 15.7479 6.65669 15.6569Z\" fill=\"currentColor\"\/>\n                                    <\/svg>\n                                <\/div>\n                                <div class=\"acf-accordion-content\">\n                                    <div class=\"acf-date-range\">\n                                        <div class=\"acf-date-field\">\n                                            <label>From<\/label>\n                                            <input type=\"date\" class=\"acf-date-from\">\n                                        <\/div>\n                                        <span class=\"acf-date-separator\">-<\/span>\n                                        <div class=\"acf-date-field\">\n                                            <label>To<\/label>\n                                            <input type=\"date\" class=\"acf-date-to\">\n                                        <\/div>\n                                    <\/div>\n                                    <div class=\"acf-date-presets\">\n                                        <div class=\"acf-dropdown-item-date\" data-value=\"past\">\n                                            <span class=\"acf-dropdown-text\">Passed<\/span>\n                                        <\/div>\n                                        <div class=\"acf-dropdown-item-date\" data-value=\"upcoming\">\n                                            <span class=\"acf-dropdown-text\">Coming soon<\/span>\n                                        <\/div>\n                                        <div class=\"acf-dropdown-item-date\" data-value=\"all\">\n                                            <span class=\"acf-dropdown-text\">All<\/span>\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n                            <\/div>\n\n                            <!-- Boutons d'action -->\n                            <div class=\"acf-filter-actions\">\n                                <div class=\"acf-filter-buttons\">\n                                    <button class=\"acf-filter-reset\">Reset<\/button>\n                                    <button class=\"acf-filter-close\">Close<\/button>\n                                <\/div>\n                                <button class=\"acf-filter-search\">Search (0 results)<\/button>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n\n                    <!-- Filtre Province -->\n                    <div class=\"acf-dropdown acf-filtres-dropdown\">\n                        <div class=\"acf-dropdown-trigger\">\n                            <span class=\"acf-dropdown-text\">Province<\/span>\n                            <svg class=\"acf-dropdown-arrow\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"11\" height=\"7\" viewBox=\"0 0 11 7\" fill=\"none\">\n                                <path d=\"M1 0.857143L5.33333 5.5L10 0.5\" stroke=\"#323332\"\/>\n                            <\/svg>\n                        <\/div>\n                        <div class=\"acf-dropdown-menu\">\n                            <!-- Liste Provenance (sans accord\u00e9on) -->\n                            <div class=\"acf-provenance-list\">\n                                <!-- Les provenances seront charg\u00e9es dynamiquement -->\n                            <\/div>\n\n                            <!-- Boutons d'action -->\n                            <div class=\"acf-filter-actions\">\n                                <div class=\"acf-filter-buttons\">\n                                    <button class=\"acf-filter-reset\">Reset<\/button>\n                                    <button class=\"acf-filter-close\">Close<\/button>\n                                <\/div>\n                                <button class=\"acf-filter-search\">Search (0 results)<\/button>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                <\/div>\n                <button class=\"acf-submit\">Search<\/button>\n            <\/div>\n        <\/div>\n\n        <!-- R\u00e9sultats -->\n        <div class=\"acf-archive-list\"><\/div>\n        \n        <!-- Bouton \"Voir plus\" -->\n        <div class=\"acf-load-more-container\" style=\"display: none;\">\n            <button class=\"acf-load-more\">See more Festivals<\/button>\n        <\/div>\n    <\/div>\n\n\t    <style>\n   .acf-archive-title {\n  color: #D30C8C;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 32px !important;\n  font-style: normal;\n  font-weight: 600 !important;\n  line-height: 35px;\n  margin: 0;\n  flex: 0 0 30%;\n  min-width: 200px;\n}\n\n.acf-archive-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  flex-wrap: wrap;\n  margin-bottom: 30px;\n  gap: 0;\n}\n\n.acf-archive-filters {\n  display: flex;\n  align-items: center;\n  background: #F5F6F7;\n  border-radius: 8px;\n  padding: 8px 12px;\n  gap: 20px;\n  width:100%;\n}\n\n\/* Barre de recherche *\/\n.acf-archive-filters input.acf-search {\n  flex: 1;\n  min-width: 200px;\n  padding: 0 0 0 40px;\n  border: none;\n  border-radius: 25px;\n  font-size: 14px !important;\n  background: transparent;\n  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  background-repeat: no-repeat;\n  background-position: 12px center;\n  background-size: 16px;\n  margin-right: 0;\n}\n            \n.acf-archive-filters-recherche {\n  display: flex;\n  flex: 0 0 60%;\n  margin-left: auto;\n  gap:16px;\n}\n\n\/* Dropdowns personnalis\u00e9s *\/\n.acf-dropdown {\n  position: relative;\n  flex: 0 0 auto;\n  cursor: pointer;\n}\n            \n.acf-dropdown-trigger {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 0 8px;\n  background: transparent;\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-style: normal;\n  font-weight: 400 !important;\n  line-height: 16px;\n  transition: all 0.2s;\n  gap: 8px;\n  position: relative;\n}\n\n.acf-dropdown-trigger:hover {\n  background-color: transparent;\n}\n\n.acf-dropdown-trigger:hover::after {\n  content: '';\n  position: absolute;\n  bottom: -4px;\n  left: 0;\n  right: 0;\n  height: 1px;\n  background-color: #333;\n  transform: scaleX(1);\n  transition: transform 0.2s ease;\n}\n            \n.acf-dropdown-trigger::after {\n  content: '';\n  position: absolute;\n  bottom: -4px;\n  left: 0;\n  right: 0;\n  height: 1px;\n  background-color: #333;\n  transform: scaleX(0);\n  transition: transform 0.2s ease;\n}\n\n.acf-dropdown.active .acf-dropdown-trigger::after { transform: scaleX(1); }\n\n\/* Fl\u00e8che des filtres (trigger) \u2014 inchang\u00e9e, garde l\u2019ic\u00f4ne et la rotation *\/\n.acf-dropdown-arrow {\n  transition: transform 0.3s ease;\n  color: #323332;\n  flex-shrink: 0;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.acf-dropdown.active .acf-dropdown-arrow { transform: rotate(180deg); }\n\n.acf-dropdown-menu {\n  position: absolute;\n  top: 100%;\n  right: 0;\n  left: auto;\n  background: #ECEFF1;\n  border-radius: 12px;\n  opacity: 0;\n  visibility: hidden;\n  transform: translateY(-10px);\n  transition: all 0.2s;\n  z-index: 1000;\n  margin-top: 20px;\n  min-width: 360px;\n  padding: 16px;\n}\n\n.acf-dropdown.active .acf-dropdown-menu {\n  opacity: 1;\n  visibility: visible;\n  transform: translateY(0);\n  cursor: pointer;\n}\n\n\/* Styles pour les accord\u00e9ons *\/\n.acf-accordion {\n  border-top: 0.8px solid #B0BEC5;\n  overflow: hidden;\n}\n\n.acf-accordion-header {\n  padding: 16px 0;\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  transition: all 0.3s ease;\n  color:#00000B;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 16px !important;\n  font-style: normal;\n  font-weight: 700 !important;\n  line-height: 20px;\n}\n\n.acf-accordion-title {\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-weight: 400 !important;\n  line-height: 18px;\n  transition: color 0.3s ease;\n}\n\n.acf-accordion-arrow {\n  width: 14px;\n  height: 16px;\n  transition: transform 0.3s ease, color 0.3s ease;\n  flex-shrink: 0;\n}\n\n\/* REMPLACEMENT UNIQUEMENT \u00c0 L\u2019INT\u00c9RIEUR DES DROPDOWNS: fl\u00e8che -> tiret 8x1 *\/\n.acf-archive-festival-app .acf-dropdown-menu .acf-accordion-header .acf-accordion-arrow path { display: none; }\n.acf-archive-festival-app .acf-dropdown-menu .acf-accordion-header .acf-accordion-arrow {\n  width: 8px;\n  height: 1px;\n  background: #323332;\n  border-radius: 1px;\n  transform: none !important; \/* pas de rotation pour le tiret *\/\n}\n\n\/* Hover: header + tiret en #D30C8C (dans dropdowns uniquement) *\/\n.acf-archive-festival-app .acf-dropdown-menu .acf-accordion-header:hover {\n  color: #D30C8C;\n}\n.acf-archive-festival-app .acf-dropdown-menu .acf-accordion-header:hover .acf-accordion-arrow {\n  background: #D30C8C;\n}\n\n\/* Actif: header + tiret en #D30C8C (et pas de rotation) *\/\n.acf-archive-festival-app .acf-dropdown-menu .acf-accordion.active .acf-accordion-header {\n  color: #D30C8C;\n}\n.acf-archive-festival-app .acf-dropdown-menu .acf-accordion.active .acf-accordion-header .acf-accordion-arrow {\n  background: #D30C8C;\n  transform: none !important;\n}\n\n.acf-accordion-content {\n  max-height: 0;\n  overflow: hidden;\n  transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), \n              padding 0.4s cubic-bezier(0.4, 0, 0.2, 1),\n              opacity 0.3s ease;\n  opacity: 0;\n  padding: 0 0;\n}\n\n.acf-accordion.active .acf-accordion-content {\n  max-height: 500px;\n  padding: 0 0 16px 0;\n  opacity: 1;\n}\n\n\/* Dernier accord\u00e9on sans bordure *\/\n.acf-accordion:last-child {\n  border-bottom: none;\n}\n\n\/* Filtres de date *\/\n.acf-date-range {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  margin-bottom: 16px;\n}\n\n.acf-date-field {\n  display: flex;\n  flex-direction: column;\n  gap: 4px;\n}\n\n.acf-date-field label {\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 12px !important;\n  font-weight: 400 !important;\n}\n\n.acf-date-field input[type=\"date\"] {\n  padding: 8px 12px;\n  border: 1px solid #B0BEC5;\n  border-radius: 4px;\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 12px !important;\n  background: transparent;\n}\n\n.acf-date-separator {\ncolor: #ECEFF1;\nfont-family: \"TikTok Sans\" !important;\nfont-size: 14px !important;\nfont-style: normal;\nfont-weight: 400 !important;\nline-height: 16px;\n}\n\n.acf-date-presets {\n  display: flex;\n  gap: 8px;\n  margin-bottom: 16px;\n}\n\n.acf-dropdown-item-date {\n  display: flex;\n  align-items: center;\n  padding: 4px 6px;\n  cursor: pointer;\n  transition: background-color 0.2s;\n  border-radius: 100px;\n  background-color: rgba(176, 190, 197, 0.50);\n  flex: 1;\n  justify-content: center;\n}\n\n.acf-dropdown-item-date:hover,\n.acf-dropdown-item-date.selected {\n  background-color: rgba(211, 12, 140, 0.10);\n}\n\n.acf-dropdown-item-date .acf-dropdown-text {\n  color: #546E7A;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 10px !important;\n  font-weight: 400 !important;\n  text-align: center;\n}\n\n\/* Options de filtres *\/\n.acf-filter-item {\n  margin-bottom: 16px;\n}\n\n.acf-filter-label {\n  display: block;\n  color: #00000B;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 16px !important;\n  font-weight: 400 !important;\n  line-height:20px;\n}\n\n.acf-filter-option {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  padding: 6px 0;\n  cursor: pointer;\n  justify-content:space-between;\n}\n\t\t\n\t\t.acf-filter-option:hover label {\n\t\t\tcolor:#D30C8C;\n\t\t}\n\t\t\n.acf-filter-option.selected label { color: #D30C8C; }\n\n.acf-filter-option input[type=\"checkbox\"] {\n  width: 16px;\n  height: 16px;\n  accent-color: #D30C8C;\n}\n\n.acf-filter-option label {\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 16px !important;\n  font-weight: 300 !important;\n  line-height:20px;\n  cursor: pointer;\n}\n\t\t\n\t\t.acf-mediation-list {\n\t\t\tdisplay:flex;\n\t\t\tflex-direction:column;\n\t\t\tgap:8px;\n\t\t}\n\t\t\n\t\t.acf-mediation-list .acf-filter-item {\n\t\t\tdisplay:flex;\n\t\t\tflex-direction:row;\n\t\t\tmargin-bottom:0 !important;\n\t\t\tjustify-content:space-between;\n\t\t\talign-items:center;\n\t\t}\n\t\t\n\t\t.acf-mediation-list .acf-filter-item .acf-mediation-options, .acf-mediation-list .acf-diversite-options, .acf-mediation-list .acf-paroles-options {\n\t\t\tdisplay:flex;\n\t\t\twhite-space:nowrap;\n\t\t\tgap:16px;\n\t\t}\n\t\t\n\t\t.acf-mediation-options .acf-filter-option, .acf-diversite-options .acf-filter-option, .acf-paroles-options .acf-filter-option {\n\t\t\tpadding:0 !important;\n}\n\n\/* Boutons d'action *\/\n.acf-filter-actions {\n  margin-top: 20px;\n  padding-top: 16px;\n}\n\n.acf-filter-buttons {\n  display: flex;\n  gap: 8px;\n  margin-bottom: 8px;\n}\n\n.acf-filter-reset,\n.acf-filter-close {\n  flex: 1;\n  padding: 4px 6px !important;\n  border: 0.5px solid #D30C8C;\n  border-radius: 8px;\n  background: transparent;\n  color: #D30C8C;\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  cursor: pointer;\n  transition: all 0.2s;\n}\n\n.acf-filter-reset:hover,\n.acf-filter-close:hover {\n  background: rgba(211, 12, 140, 0.10);\n  color: #D30C8C;\n  border-color: rgba(211, 12, 140, 0.10);\n}\n\n.acf-filter-search {\n  width: 100%;\n  padding: 10px 12px;\n  border: none;\n  border-radius: 8px;\n  background: rgba(211, 12, 140, 0.10);\n  color: #D30C8C;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-weight: 500 !important;\n  cursor: pointer;\n  transition: background 0.2s;\n\tdisplay:flex;\n\tgap:10px;\n\talign-items:center;\n\tjustify-content:center;\n}\n\n.acf-filter-search svg { flex-shrink:0; }\n\n.acf-filter-search:hover {\n  background: rgba(211, 12, 140, 0.30);\n  color: #D30C8C;\n}\n\n\/* Bouton s\u00e9par\u00e9 du bloc fusionn\u00e9 *\/\n.acf-archive-header .acf-submit {\n  align-self: center;\n  padding: 10px 12px;\n  border: none;\n  border-radius: 8px;\n  background: rgba(211, 12, 140, 0.10);\n  color:#D30C8C;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-style: normal;\n  font-weight: 400 !important;\n  line-height: 20px;\n  cursor: pointer;\n  transition: background 0.3s;\n  white-space: nowrap;\n  flex: 0 0 auto;\n}\n.acf-archive-header .acf-submit:hover { background: rgba(211, 12, 140, 0.30); }\n\n\/* Focus states *\/\n.acf-archive-filters input:focus { outline: none; box-shadow: none; }\n\n\/* Cartes *\/\n.acf-archive-list {\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n  gap: 20px;\n  margin-bottom: 30px;\n}\n\n.acf-card {\n  display: flex;\n  flex-direction: column;\n  border-radius: 12px;\n  text-decoration: none;\n  color: inherit;\n  transition: box-shadow 0.3s;\n  background: #F5F6F7;\n  box-shadow: 8px 8px 12px 0 rgba(231, 231, 233, 0.60) !important;\n  min-height: 415px;\n  cursor: pointer;\n}\n    \n.acf-card:hover { \n  box-shadow: 8px 8px 12px 0 rgba(160, 160, 167, 0.50) !important; \n}\n\n.acf-img-container {\n  position: relative;\n  width: 100%; \n  display:flex;\n}\n        \n.acf-img {\n  width: 100%;\n  height: 200px !important;\n  object-fit: cover;\n  object-position:center center;\n  border-radius: 12px 12px 0 0 !important;\n}\n\n\/* Badge de date avec le nouveau design *\/\n.acf-date-badge {\n  position: absolute;\n  top: 16px;\n  right: 16px;\n  background: white;\n  border-radius: 8px;\n  overflow: hidden;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n  min-width: 80px;\n}\n\n.acf-date-header {\n  background: #D30C8C;\n  color: #ECEFF1;\n  padding: 6px;\n  text-align: center;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-weight: 400 !important;\n  line-height: 16px;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n}\n\n.acf-date-header-centered {\n  justify-content: center;\n}\n\n.acf-date-body {\n  padding: 6px;\n  text-align: center;\n}\n\n.acf-date-debut,\n.acf-date-fin {\n  color: #D30C8C;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 16px !important;\n  font-weight: 400 !important;\n  line-height: 16px;\n  margin: 0;\n}\n\n.acf-date-debut {\n  margin-bottom: 4px;\n}\n\n.acf-date-fin {\n  margin-top: 4px;\n}\n\t\t\n.acf-body {\n  flex: 1;\n  padding: 16px;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.acf-content {\n  display: flex;\n  flex-direction: column;\n  gap: 8px;\n}\n\n\/* Producteur du festival *\/\n.acf-producteur {\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-weight: 400 !important;\n  line-height: 16px;\n}\n\n\/* Titre du festival *\/\n.acf-title {\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 22px !important;\n  font-weight: 600 !important;\n  line-height: 24px;\n}\n\n\/* Ville du festival *\/\n.acf-ville-festival {\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-weight: 400 !important;\n  line-height: 16px;\n}\n\n\/* Extrait *\/\n.acf-excerpt {\n  color: #607D8B;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-weight: 300 !important;\n  line-height: 16px;\n  overflow: hidden;\n}\n\n\/* Tags et cat\u00e9gories en bas \u00e0 gauche *\/\n.acf-tags {\n  display: flex;\n  gap: 6px;\n  flex-wrap: wrap;\n  max-width: 50%;\n  flex: 1;\n}\n\n.acf-chip {\n  padding: 3px 6px;\n  color: #455A64;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 9px !important;\n  font-weight: 400 !important;\n  line-height: 10px;\n  border-radius: 100px;\n  white-space: nowrap;\n  background-color: #CFD8DC;\n  flex-shrink: 1;\n}\n\n\/* Bouton \"+\" en bas \u00e0 droite *\/\n.acf-plus {\n  align-self: flex-end;\n  margin-top: auto;\n  margin-left: auto;\n}\n\n.acf-archive-festival-app .button-plus-dynamique {\n  flex-direction:row-reverse;\n}\n.acf-archive-festival-app .hover-wrapper-dynamique {\n  display:none !important;\n  height:38px !important;\n}\n.acf-archive-festival-app .acf-card:hover .hover-wrapper-dynamique {\n  display:flex !important;\n}\n\n\/* Conteneur pour aligner tags et bouton sur la m\u00eame ligne *\/\n.acf-bottom-row {\n  display: flex;\n  align-items: flex-end;\n  justify-content: space-between;\n}\n\n\/* Voir plus *\/\n.acf-load-more-container { \n  text-align: center; \n  margin-top: 30px; \n}\n    \n.acf-load-more {\n  padding: 10px 12px !important;\n  border-top: none;\n  border-left: none;\n  border-right: none;\n  border-bottom: 1px solid #323332;\n  border-radius: 0 !important;\n  color: #323332;\n  font-family: \"TikTok Sans\" !important;\n  font-size: 14px !important;\n  font-style: normal;\n  font-weight: 400 !important;\n  line-height: 16px;\n  cursor: pointer;\n  transition: all 0.3s;\n  background-color: transparent;\n}\n    \n.acf-load-more:hover { \n  border-color: #D30C8C; \n  color: #D30C8C; \n  background-color: transparent;  \n}\n\n\/* Responsive *\/\n@media (max-width: 992px) {\n  .acf-archive-filters-recherche {\n    margin-left: 0;\n  }\n  .acf-archive-list { \n    grid-template-columns: repeat(2, 1fr); \n  }\n  .acf-archive-header { \n    flex-direction: column; \n    align-items: stretch; \n    gap: 20px; \n  }\n  .acf-archive-title { \n    flex: none; \n  }\n  .acf-archive-filters {\n    width: 85%; \n  }\n  .acf-archive-filters input.acf-search { \n    min-width: 150px; \n  }\n  .acf-dropdown { \n    width: 100px; \n  }\n}\n\n@media (max-width: 768px) {\n  .acf-archive-list { \n    grid-template-columns: 1fr; \n  }\n  .acf-archive-filters { \n    flex-direction: column; \n    gap: 10px; \n  }\n  .acf-archive-filters input.acf-search { \n    min-width: 100%; \n    margin-right: 0; \n    margin-bottom: 5px; \n  }\n  .acf-dropdown { \n    width: 100%; \n  }\n  .acf-archive-header .acf-submit { \n    margin-left: 0; \n    margin-top: 10px; \n  }\n  .acf-dropdown-menu { \n    right: auto; \n    left: 0; \n    min-width: 280px;\n  }\n}\n    <\/style>\n\n\t\t    <script>\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n  document.querySelectorAll(\".acf-archive-festival-app\").forEach((app) => {\n    const listEl = app.querySelector(\".acf-archive-list\");\n    const searchInput = app.querySelector(\".acf-search\");\n    const dateLieuDropdown = app.querySelector(\".acf-date-lieu-dropdown\");\n    const filtresDropdown = app.querySelector(\".acf-filtres-dropdown\");\n    const submitBtn = app.querySelector(\".acf-submit\");\n    const loadMoreContainer = app.querySelector(\".acf-load-more-container\");\n    const loadMoreBtn = app.querySelector(\".acf-load-more\");\n    const cpt = app.dataset.cpt || 'festival';\n    const searchButtonText = app.dataset.searchButton || 'Rechercher';\n    const searchResultsText = app.dataset.searchResults || 'Rechercher (0 r\u00e9sultats)';\n    \n    \/\/ Textes traduits des filtres\n    const dateLocationText = app.dataset.dateLocation || 'Date';\n    const durationText = app.dataset.duration || 'Dur\u00e9e';\n    const locationText = app.dataset.location || 'Lieu';\n    const resetText = app.dataset.reset || 'R\u00e9initialiser';\n    const closeText = app.dataset.close || 'Fermer';\n    const filtersText = app.dataset.filters || 'Province';\n    const originText = app.dataset.origin || 'Provenance';\n    const fromText = app.dataset.from || 'Du';\n    const toText = app.dataset.to || 'Au';\n    const passedText = app.dataset.passed || 'Pass\u00e9';\n    const comingSoonText = app.dataset.comingSoon || '\u00c0 venir';\n    const allText = app.dataset.all || 'Tous';\n    const mediationLabelText = app.dataset.mediationLabel || 'Activit\u00e9 de m\u00e9diation';\n    const diversityLabelText = app.dataset.diversityLabel || 'Diversit\u00e9';\n    const speechLabelText = app.dataset.speechLabel || 'Paroles';\n    \n    \/\/ D\u00e9tection de la langue pour la traduction des tags\n    const isEnglish = document.documentElement.lang === 'en' || \n                     document.documentElement.lang.startsWith('en-') ||\n                     window.location.pathname.includes('\/en\/');\n    \n    console.log('D\u00e9tection de langue:', {\n      lang: document.documentElement.lang,\n      pathname: window.location.pathname,\n      isEnglish: isEnglish\n    });\n\t  \n\t  \/\/ Cacher le badge de date sur les pages r\u00e9pertoire FR\/EN\n\t  (function(){\n\t    try {\n\t      var p = window.location && window.location.pathname ? window.location.pathname.replace(\/\\\/$\/, '') : '';\n\t      var shouldHide = p === '\/repertoire-des-oeuvres-circassiennes' || p === '\/en\/directory-of-circus-works';\n\t      if (shouldHide) {\n\t        var st = document.createElement('style');\n\t        st.type = 'text\/css';\n\t        st.appendChild(document.createTextNode('.acf-date-badge{display:none !important;}'));\n\t        document.head && document.head.appendChild(st);\n\t      }\n\t    } catch(e) {}\n\t  })();\n\t  \n    \/\/ \u00c9tat des filtres\n    let selectedDateFilter = null; \/\/ 'custom', 'past', 'upcoming', 'all'\n    let selectedDateFrom = \"\";\n    let selectedDateTo = \"\";\n    let selectedProvenance = \"\";\n    let selectedMediation = \"\";\n    let selectedDiversite = \"\";\n    let selectedParoles = \"\";\n\n    let currentPage = 1;\n    let postsPerPage = 6;\n    let allPosts = [];\n    let filteredPosts = [];\n\n    \/\/ Utils\n    function normalize(str) {\n      return (str || \"\")\n        .toString()\n        .normalize(\"NFD\")\n        .replace(\/[\\u0300-\\u036f]\/g, \"\")\n        .toLowerCase();\n    }\n\n    \/\/ Cache pour les traductions\n    const translationCache = new Map();\n    \n    \/\/ Fonction pour traduire le contenu des posts (titre, producteur, etc.)\n    \/\/ Note: Si l'API retourne d\u00e9j\u00e0 les contenus traduits avec lang=en, cette fonction peut \u00eatre simplifi\u00e9e\n    async function translatePostContent(post) {\n      \/\/ Si l'API retourne d\u00e9j\u00e0 les contenus traduits, on peut retourner le post tel quel\n      \/\/ Sinon, on peut garder la logique de traduction pour les champs ACF sp\u00e9cifiques\n      if (!isEnglish) return post;\n      \n      try {\n        const translatedPost = { ...post };\n        \n        \/\/ Traduire seulement les champs ACF qui ne sont pas traduits par l'API\n        if (post.acf?.producteur_du_spectacle) {\n          const translatedProducteur = await translateChoices('producteur_du_spectacle', [post.acf.producteur_du_spectacle]);\n          if (translatedProducteur && translatedProducteur[0]) {\n            translatedPost.acf.producteur_du_spectacle = translatedProducteur[0];\n          }\n        }\n        \n        return translatedPost;\n      } catch (error) {\n        console.log('Erreur de traduction du contenu:', error);\n        return post;\n      }\n    }\n    \n    \/\/ Traduction batch via admin-ajax + WPML\n    async function translateChoices(fieldName, values) {\n      console.log('translateChoices appel\u00e9e:', { fieldName, values, isEnglish });\n      try {\n        if (!Array.isArray(values) || values.length === 0) return [];\n        if (!isEnglish) {\n          console.log('Pas de traduction n\u00e9cessaire (isEnglish = false)');\n          return values;\n        }\n        \n        \/\/ Cr\u00e9er une cl\u00e9 de cache\n        const cacheKey = `${fieldName || 'general'}:${values.sort().join('|')}`;\n        \n        \/\/ V\u00e9rifier le cache\n        if (translationCache.has(cacheKey)) {\n          return translationCache.get(cacheKey);\n        }\n        \n        const fd = new FormData();\n        fd.append('action', 'batch_translate_acf_choices_festival');\n        if (fieldName) fd.append('field', fieldName);\n        values.forEach(v => fd.append('choices[]', String(v)));\n        \n        const controller = new AbortController();\n        const timeoutId = setTimeout(() => controller.abort(), 3000); \/\/ 3s timeout\n        \n        const resp = await fetch('\/wp-admin\/admin-ajax.php', { \n          method: 'POST', \n          body: fd, \n          credentials: 'same-origin',\n          signal: controller.signal\n        });\n        \n        clearTimeout(timeoutId);\n        \n        if (!resp.ok) {\n          return values;\n        }\n        \n        const data = await resp.json();\n        console.log('R\u00e9ponse AJAX:', data);\n        \n        let result = values;\n        if (Array.isArray(data?.translated)) {\n          result = data.translated;\n          console.log('Traduction r\u00e9ussie:', result);\n        } else {\n          console.log('Pas de traduction dans la r\u00e9ponse, utilisation des valeurs originales');\n        }\n        \n        \/\/ Mettre en cache\n        translationCache.set(cacheKey, result);\n        return result;\n      } catch (error) {\n        return Array.isArray(values) ? values : [];\n      }\n    }\n\n\/\/ R\u00e9cup\u00e9ration des donn\u00e9es ACF\n    function getPostACF(post, fieldName) {\n  if (!post.acf || !post.acf[fieldName]) {\n    return \"\";\n  }\n  \n  const value = post.acf[fieldName];\n  \n  if (Array.isArray(value)) {\n    return value[0] || \"\";\n  }\n  return value;\n}\n\n   \/\/ Fonction sp\u00e9cifique pour r\u00e9cup\u00e9rer les dates ACF\n    function getPostDateACF(post, fieldName) {\n  const dateValue = getPostACF(post, fieldName);\n  \n      if (!dateValue) return null;\n  \n  \/\/ Essayer diff\u00e9rents formats de date\n      let parsedDate = null;\n  \n  \/\/ Format YYYY-MM-DD (standard)\n  if (typeof dateValue === 'string' && dateValue.match(\/^\\d{4}-\\d{2}-\\d{2}$\/)) {\n        parsedDate = new Date(dateValue);\n      }\n  \/\/ Format YYYYMMDD (ACF parfois)\n  else if (typeof dateValue === 'string' && dateValue.match(\/^\\d{8}$\/)) {\n    const year = dateValue.substring(0, 4);\n    const month = dateValue.substring(4, 6);\n    const day = dateValue.substring(6, 8);\n    parsedDate = new Date(year, month - 1, day);\n  }\n  \/\/ Format timestamp ou autre\n  else if (typeof dateValue === 'number' || !isNaN(new Date(dateValue).getTime())) {\n    parsedDate = new Date(dateValue);\n  }\n  \n  if (parsedDate && !isNaN(parsedDate.getTime())) {\n    return parsedDate;\n  }\n  \n  return null;\n}\n\n   \/\/ Format de date pour le badge\nfunction festival_formatDateBadge(dateString) {\n  if (!dateString) return null;\n  \n  const d = new Date(dateString);\n  if (isNaN(d.getTime())) {\n    return null;\n  }\n  \n  const month = d.toLocaleDateString(\"fr-FR\", { month: \"short\" }).toUpperCase();\n  const day = d.getDate();\n  \n  return { month, day };\n}\n\n    \/\/ R\u00e9cup\u00e9ration de l'image\n    async function getPostImage(post) {\n      if (post.featured_media && !post._embedded) {\n        try {\n          const response = await fetch(`\/wp-json\/wp\/v2\/media\/${post.featured_media}`);\n          const media = await response.json();\n          return media.source_url || \"\";\n        } catch (err) {\n          return \"\";\n      }\n      }\n      \n      if (post._embedded && post._embedded[\"wp:featuredmedia\"] && post._embedded[\"wp:featuredmedia\"][0]) {\n        const media = post._embedded[\"wp:featuredmedia\"][0];\n        return media.source_url || media.guid?.rendered || media.url || \"\";\n      }\n      \n      return \"\";\n    }\n\n\/\/ R\u00e9cup\u00e9ration des cat\u00e9gories\n    async function getPostCategories(post) {\n      if (!post.categories || post.categories.length === 0) return [];\n  \n      try {\n        const categoryPromises = post.categories.map(async (catId) => {\n      if (catId === 1) return null; \/\/ Exclure \"Uncategorized\"\n      \n      const response = await fetch(`\/wp-json\/wp\/v2\/categories\/${catId}`);\n          if (response.ok) {\n            const category = await response.json();\n        return category.name; \/\/ Retourner le nom r\u00e9el de la cat\u00e9gorie\n          }\n          return null;\n        });\n    \n        const categoryNames = await Promise.all(categoryPromises);\n    return categoryNames.filter(name => name !== null);\n  } catch (error) {\n    return [];\n  }\n}\n\n    \/\/ Filtrage des posts\nfunction festival_filterPosts() {\n  let results = [...allPosts];\n\n  const q = normalize(searchInput?.value?.trim() || \"\");\n  if (q) {\n    results = results.filter((p) => {\n      const title = normalize(p.title?.rendered || \"\");\n      const excerpt = normalize(p.excerpt?.rendered || \"\");\n      return title.includes(q) || excerpt.includes(q);\n    });\n  }\n\n  \/\/ Filtre de date\n  if (selectedDateFilter === 'past') {\n    const today = new Date();\n    today.setHours(0, 0, 0, 0);\n    \n    results = results.filter((p) => {\n      const eventDate = getPostDateACF(p, 'date_fin');\n      if (!eventDate) {\n        return false;\n      }\n      \n      const isPast = eventDate < today;\n      return isPast;\n    });\n    \n  } else if (selectedDateFilter === 'upcoming') {\n    const today = new Date();\n    today.setHours(0, 0, 0, 0);\n    \n    results = results.filter((p) => {\n      const eventDate = getPostDateACF(p, 'date_fin');\n      \/\/ Inclure les \u00e9v\u00e9nements sans date (\u00c0 confirmer) dans \"\u00c0 venir\"\n      if (!eventDate) {\n        return true;\n      }\n      \n      const isUpcoming = eventDate >= today;\n      return isUpcoming;\n    });\n    \n  } else if (selectedDateFilter === 'custom' && selectedDateFrom && selectedDateTo) {\n    const fromDate = new Date(selectedDateFrom);\n    fromDate.setHours(0, 0, 0, 0);\n    const toDate = new Date(selectedDateTo);\n    toDate.setHours(23, 59, 59, 999);\n    \n    results = results.filter((p) => {\n      const eventDate = getPostDateACF(p, 'date_fin');\n      if (!eventDate) {\n        return false;\n      }\n      \n      const isInRange = eventDate >= fromDate && eventDate <= toDate;\n      return isInRange;\n    });\n  }\n\n  \/\/ Autres filtres...\n  if (selectedProvenance) {\n    results = results.filter((p) => getPostACF(p, 'provenance') === selectedProvenance);\n  }\n  if (selectedMediation) {\n    results = results.filter((p) => getPostACF(p, 'activite_de_mediation') === selectedMediation);\n  }\n  if (selectedDiversite) {\n    results = results.filter((p) => getPostACF(p, 'diversite') === selectedDiversite);\n  }\n  if (selectedParoles) {\n    results = results.filter((p) => getPostACF(p, 'paroles') === selectedParoles);\n  }\n\n  \/\/ Tri: 1) en cours aujourd'hui, 2) \u00e0 venir, 3) pass\u00e9s\n  const today = new Date();\n  today.setHours(0, 0, 0, 0);\n\n  function classifyByAvailability(post) {\n    const start = getPostDateACF(post, 'date_debut');\n    const end = getPostDateACF(post, 'date_fin');\n\n    const hasStart = start && !isNaN(start);\n    const hasEnd = end && !isNaN(end);\n\n    if (hasStart && hasEnd) {\n      if (start <= today && end >= today) return 0;   \/\/ disponible actuellement\n      if (start > today) return 1;                    \/\/ \u00e0 venir\n      if (end < today) return 2;                      \/\/ pass\u00e9\n    }\n    \/\/ Fallbacks s'il manque une des deux dates\n    if (hasStart && start > today) return 1;\n    if (hasEnd && end >= today) return 1;\n    return 2;\n  }\n\n  function timeOr(fallback, d) {\n    return d && !isNaN(d) ? d.getTime() : fallback;\n  }\n\n  results.sort((a, b) => {\n    const ra = classifyByAvailability(a);\n    const rb = classifyByAvailability(b);\n    if (ra !== rb) return ra - rb;\n\n    const sa = getPostDateACF(a, 'date_debut');\n    const ea = getPostDateACF(a, 'date_fin');\n    const sb = getPostDateACF(b, 'date_debut');\n    const eb = getPostDateACF(b, 'date_fin');\n\n    \/\/ Tiebreakers:\n    \/\/ - en cours: fin la plus proche d'abord (croissant)\n    if (ra === 0) {\n      return timeOr(Infinity, ea) - timeOr(Infinity, eb);\n    }\n    \/\/ - \u00e0 venir: d\u00e9but le plus proche d'abord (croissant)\n    if (ra === 1) {\n      return timeOr(Infinity, sa) - timeOr(Infinity, sb);\n    }\n    \/\/ - pass\u00e9s: le plus r\u00e9cent d'abord (fin d\u00e9croissant)\n    return timeOr(-Infinity, eb) - timeOr(-Infinity, ea);\n  });\n\n  filteredPosts = results;\n  return results;\n}\n\n\/\/ Rendu des posts\n    async function renderPosts(posts, append = false) {\n      if (!append) listEl.innerHTML = \"\";\n      if (posts.length === 0) {\n        listEl.innerHTML = `<p>Aucun festival trouv\u00e9<\/p>`;\n        if (loadMoreContainer) loadMoreContainer.style.display = \"none\";\n        return;\n      }\n\n      const sliceStart = append ? (currentPage - 1) * postsPerPage : 0;\n      const sliceEnd = currentPage * postsPerPage;\n  const toRender = append\n    ? posts.slice(sliceStart, sliceEnd)\n    : posts.slice(0, sliceEnd);\n\n      const cardsHTML = await Promise.all(toRender.map(async (p) => {\n        try {\n          \/\/ Traduire le contenu du post si n\u00e9cessaire\n          const translatedPost = await translatePostContent(p);\n          \n          const img = await getPostImage(translatedPost);\n          const filterTags = await festival_getFilterTags(translatedPost);\n        const dateDebut = getPostDateACF(translatedPost, 'date_debut');\n        const dateFin = getPostDateACF(translatedPost, 'date_fin');\n    const producteur = getPostACF(translatedPost, 'producteur_du_spectacle');\n    const lienSpectacle = getPostACF(translatedPost, 'lien_du_spectacle');\n    const villeFestival = getPostACF(translatedPost, 'ville_du_festival');\n\n    \/\/ G\u00e9n\u00e9rer le HTML des tags\n        let tagsHTML = '';\n    if (filterTags.length > 0) {\n      const tagsContent = filterTags.map(tag => `<span class=\"acf-chip\">${tag}<\/span>`).join('');\n      \n      tagsHTML = `\n        <div class=\"acf-tags\">\n          ${tagsContent}\n        <\/div>\n      `;\n    }\n\n    \/\/ Badge de date avec le nouveau format \"Du ... au\"\n        let dateBadgeHTML = '';\n        if (dateDebut && dateFin) {\n          const debutFormatted = festival_formatDateRange(dateDebut);\n          const finFormatted = festival_formatDateRange(dateFin);\n      \n          dateBadgeHTML = `\n            <div class=\"acf-date-badge\">\n          <div class=\"acf-date-header\">\n            <span>${fromText}<\/span>\n            <span class=\"acf-date-separator\">...<\/span>\n            <span>${toText}<\/span>\n          <\/div>\n              <div class=\"acf-date-body\">\n                <div class=\"acf-date-debut\">${debutFormatted}<\/div>\n                <div class=\"acf-date-fin\">${finFormatted}<\/div>\n              <\/div>\n        <\/div>\n      `;\n        } else if (dateDebut) {\n      \/\/ Si seulement date_debut est disponible\n          const debutFormatted = festival_formatDateRange(dateDebut);\n          dateBadgeHTML = `\n            <div class=\"acf-date-badge\">\n          <div class=\"acf-date-header\">Date<\/div>\n          <div class=\"acf-date-body\">\n            <div class=\"acf-date-debut\">${debutFormatted}<\/div>\n          <\/div>\n        <\/div>\n      `;\n        } else {\n      \/\/ Si aucune date n'est disponible\n          const confirmText = isEnglish ? 'To confirm' : '\u00c0 confirmer';\n          dateBadgeHTML = `\n            <div class=\"acf-date-badge\">\n          <div class=\"acf-date-header acf-date-header-centered\">Date<\/div>\n          <div class=\"acf-date-body\">\n            <div class=\"acf-date-debut\">${confirmText}<\/div>\n          <\/div>\n        <\/div>\n      `;\n    }\n\n    \/\/ Gestion de l'image\n    let imageHTML = '';\n    if (img) {\n      imageHTML = `<img decoding=\"async\" class=\"acf-img\" src=\"${img}\" alt=\"${translatedPost.title?.rendered || ''}\">`;\n    } else {\n      imageHTML = `<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;\">Aucune image<\/div>`;\n    }\n\n    \/\/ Construire le lien vers la page de d\u00e9tail du post\n    \/\/ Utiliser le post URL seulement si on n'a pas d'information dans l'ACF \"lien_du_spectacle\"\n    \n    let postLink = null;\n    let isACFLink = false;\n    \n    \/\/ V\u00e9rifier si lienSpectacle existe et n'est pas vide\n    const hasLienSpectacle = lienSpectacle && lienSpectacle.trim();\n    \n    \/\/ Utiliser lienSpectacle s'il existe\n    if (hasLienSpectacle) {\n      postLink = lienSpectacle;\n      isACFLink = true;\n    }\n    \n    \/\/ Si pas de lien ACF, construire le permalink \u00e0 partir du CPT et du slug\n    if (!postLink && translatedPost.slug && translatedPost.slug.trim()) {\n      const langPrefix = isEnglish ? '\/en' : '';\n      \/\/ Construire le permalink relatif: \/[lang]\/[cpt]\/[slug]\/\n      \/\/ Exemple: \/festival\/cirk-opommes\/ ou \/en\/festival\/cirk-opommes\/\n      postLink = `${langPrefix}\/${cpt}\/${translatedPost.slug}\/`;\n    } else if (!postLink) {\n      \/\/ Si pas de slug, utiliser un lien par d\u00e9faut\n      postLink = '#';\n    }\n    \n    \/\/ Ajouter target=\"_blank\" si le lien provient de l'ACF\n    const targetAttr = isACFLink ? 'target=\"_blank\"' : '';\n        return `\n  <a href=\"${postLink}\" class=\"acf-card\" data-lien=\"${postLink}\" ${targetAttr}>\n    <div class=\"acf-img-container\">\n      ${imageHTML}\n      ${dateBadgeHTML}\n    <\/div>\n    <div class=\"acf-body\">\n      <div class=\"acf-content\">\n        <div class=\"acf-producteur\">${producteur || ''}<\/div>\n        <div class=\"acf-title\">${translatedPost.title?.rendered || \"\"}<\/div>\n        ${villeFestival ? `<div class=\"acf-ville-festival\">${villeFestival}<\/div>` : ''}\n        <div class=\"acf-excerpt\">${translatedPost.excerpt?.rendered || \"\"}<\/div>\n      <\/div>\n      <div class=\"acf-bottom-row\">\n        ${tagsHTML}\n      <div class=\"acf-plus\" data-post-id=\"${translatedPost.id}\">Chargement...<\/div>\n      <\/div>\n    <\/div>\n  <\/a>\n`;\n        } catch (error) {\n          console.error('Erreur lors du rendu de la carte:', error);\n          return `<div class=\"acf-card\">Erreur de chargement<\/div>`;\n        }\n      }));\n\n  if (append) {\n    listEl.innerHTML += cardsHTML.join(\"\");\n  } else {\n    listEl.innerHTML = cardsHTML.join(\"\");\n  }\n\n  \/\/ Bouton dynamique \"En savoir plus\"\n      setTimeout(() => {\n        listEl.querySelectorAll(\"[data-post-id]\").forEach((container) => {\n          if (container._loaded) return;\n          container._loaded = true;\n          const postId = container.dataset.postId;\n          fetch(\"\/wp-admin\/admin-ajax.php\", {\n            method: \"POST\",\n            headers: { \"Content-Type\": \"application\/x-www-form-urlencoded\" },\n        body: `action=get_button_plus_dynamique&post_id=${postId}&text=${encodeURIComponent(\n          \"En savoir plus\"\n        )}&custom_class=acf-button-plus`,\n          })\n            .then((r) => r.text())\n            .then((html) => {\n              container.innerHTML = html;\n              const card = container.closest(\".acf-card\");\n              const button = container.querySelector(\".button-plus-dynamique\");\n              if (card && button) {\n            card.addEventListener(\"mouseenter\", () =>\n              button.classList.add(\"hover\")\n            );\n            card.addEventListener(\"mouseleave\", () =>\n              button.classList.remove(\"hover\")\n            );\n                button.style.pointerEvents = \"none\";\n              }\n            })\n            .catch(() => {\n          container.innerHTML =\n            '<button class=\"fallback-button\">En savoir plus<\/button>';\n            });\n        });\n      }, 50);\n\n  \/\/ Bouton \"Voir plus\"\n      if (loadMoreContainer) {\n        if (filteredPosts.length > currentPage * postsPerPage) {\n          loadMoreContainer.style.display = \"block\";\n          if (loadMoreBtn) loadMoreBtn.disabled = false;\n        } else {\n          loadMoreContainer.style.display = \"none\";\n        }\n      }\n    }\n\n\/\/ Fonction pour r\u00e9cup\u00e9rer les tags des filtres - seulement la province\nasync function festival_getFilterTags(post) {\n  \/\/ Retourner seulement la province (provenance)\n  const provenance = getPostACF(post, 'provenance');\n  \n  if (!provenance) {\n    return [];\n  }\n  \n  \/\/ Traduire la province si n\u00e9cessaire\n  let translatedProvenance = provenance;\n  if (isEnglish) {\n    try {\n      const translated = await translateChoices('provenance', [provenance]);\n      if (translated && translated[0]) {\n        translatedProvenance = translated[0];\n      }\n    } catch (error) {\n      console.error('Erreur lors de la traduction de la province:', error);\n    }\n  }\n  \n  return [translatedProvenance];\n}\n\n\n\/\/ Nouvelle fonction pour formater les dates au format \"day.month\"\nfunction festival_formatDateRange(date) {\n  if (!date || !(date instanceof Date) || isNaN(date.getTime())) {\n    return '';\n  }\n  \n  const day = date.getDate().toString().padStart(2, '0');\n  const month = (date.getMonth() + 1).toString().padStart(2, '0');\n  \n  return `${day}.${month}`;\n}\n\n    \/\/ Initialisation des accord\u00e9ons avec animation fluide\n    function initAccordions() {\n  \/\/ Grouper les accord\u00e9ons par dropdown\n      const dropdowns = app.querySelectorAll(\".acf-dropdown\");\n  \n  dropdowns.forEach((dropdown, dropdownIndex) => {\n        const accordions = dropdown.querySelectorAll(\".acf-accordion\");\n\n    if (accordions.length === 0) return; \/\/ Skip si pas d'accord\u00e9ons\n    \n    accordions.forEach((accordion, accordionIndex) => {\n          const header = accordion.querySelector(\".acf-accordion-header\");\n      if (!header) return; \/\/ Skip si pas de header\n      \n      \/\/ Supprimer les event listeners existants pour \u00e9viter les doublons\n          const newHeader = header.cloneNode(true);\n          header.parentNode.replaceChild(newHeader, header);\n\n          newHeader.addEventListener(\"click\", () => {\n            const content = accordion.querySelector(\".acf-accordion-content\");\n        \n        \/\/ Fermer tous les autres accord\u00e9ons dans le m\u00eame dropdown\n        dropdown.querySelectorAll(\".acf-accordion\").forEach((otherAccordion) => {\n          if (otherAccordion !== accordion) {\n            closeAccordion(otherAccordion);\n          }\n        });\n        \n        \/\/ Toggle l'accord\u00e9on actuel\n        if (accordion.classList.contains(\"active\")) {\n          closeAccordion(accordion);\n        } else {\n          openAccordion(accordion);\n        }\n      });\n      \n      \/\/ Ouvrir le premier accord\u00e9on de chaque dropdown par d\u00e9faut\n      if (accordionIndex === 0) {\n        \/\/ D\u00e9lai pour s'assurer que le DOM est pr\u00eat\n        setTimeout(() => {\n          openAccordion(accordion);\n        }, 50);\n      }\n        });\n      });\n    }\n\/\/ Fonction pour ouvrir un accord\u00e9on\n    function openAccordion(accordion) {\n      const content = accordion.querySelector(\".acf-accordion-content\");\n      accordion.classList.add(\"active\");\n  \n  \/\/ Animation fluide\n  content.style.transition = \"none\";\n  content.style.maxHeight = \"0\";\n  content.style.opacity = \"0\";\n  \n      requestAnimationFrame(() => {\n        content.style.transition = \"max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease, padding 0.4s cubic-bezier(0.4, 0, 0.2, 1)\";\n        content.style.maxHeight = content.scrollHeight + \"px\";\n        content.style.opacity = \"1\";\n      });\n    }\n\n\/\/ Fonction pour fermer un accord\u00e9on\n    function closeAccordion(accordion) {\n      const content = accordion.querySelector(\".acf-accordion-content\");\n      accordion.classList.remove(\"active\");\n  \n      content.style.maxHeight = content.scrollHeight + \"px\";\n  \n  requestAnimationFrame(() => {\n    content.style.maxHeight = \"0\";\n    content.style.opacity = \"0\";\n  });\n}\n    \/\/ Initialisation des dropdowns\n    function initDropdowns() {\n      [dateLieuDropdown, filtresDropdown].forEach((dropdown) => {\n        if (!dropdown) return;\n        const trigger = dropdown.querySelector(\".acf-dropdown-trigger\");\n        const menu = dropdown.querySelector(\".acf-dropdown-menu\");\n        if (!trigger || !menu) return;\n\n        trigger.addEventListener(\"click\", (e) => {\n          e.stopPropagation();\n          [dateLieuDropdown, filtresDropdown].forEach((d) => {\n            if (d && d !== dropdown) d.classList.remove(\"active\");\n          });\n          dropdown.classList.toggle(\"active\");\n        });\n      });\n\n      document.addEventListener(\"click\", (e) => {\n        const inside = [dateLieuDropdown, filtresDropdown].some(\n          (d) => d && d.contains(e.target)\n        );\n        if (!inside)\n          [dateLieuDropdown, filtresDropdown].forEach(\n            (d) => d && d.classList.remove(\"active\")\n          );\n      });\n    }\n\n    \/\/ Gestion des filtres\n    function initFilters() {\n      \/\/ Filtres de date\n      const dateFromInput = app.querySelector(\".acf-date-from\");\n      const dateToInput = app.querySelector(\".acf-date-to\");\n      \n      if (dateFromInput) {\n        dateFromInput.addEventListener(\"change\", () => {\n          selectedDateFrom = dateFromInput.value;\n          selectedDateFilter = \"custom\";\n          \/\/ Pr\u00e9visualiser le nombre de r\u00e9sultats\n          festival_previewFilterCount();\n        });\n      }\n      \n      if (dateToInput) {\n        dateToInput.addEventListener(\"change\", () => {\n          selectedDateTo = dateToInput.value;\n          selectedDateFilter = \"custom\";\n          \/\/ Pr\u00e9visualiser le nombre de r\u00e9sultats\n          festival_previewFilterCount();\n        });\n      }\n\n      \/\/ Filtres pr\u00e9d\u00e9finis de date\n      app.querySelectorAll(\".acf-dropdown-item-date\").forEach(item => {\n        item.addEventListener(\"click\", () => {\n          app.querySelectorAll(\".acf-dropdown-item-date\").forEach(i => i.classList.remove(\"selected\"));\n          item.classList.add(\"selected\");\n          selectedDateFilter = item.dataset.value;\n          selectedDateFrom = \"\";\n          selectedDateTo = \"\";\n          \/\/ Pr\u00e9visualiser le nombre de r\u00e9sultats\n          festival_previewFilterCount();\n        });\n      });\n\n      \/\/ Filtres radio (dur\u00e9e, lieu, public, etc.)\n      app.addEventListener(\"change\", (e) => {\n        if (e.target.type === \"radio\") {\n          const name = e.target.name;\n          const value = e.target.value;\n          \n          switch(name) {\n            case 'provenance':\n              selectedProvenance = value;\n              break;\n            case 'mediation':\n              selectedMediation = value;\n              break;\n            case 'diversite':\n              selectedDiversite = value;\n              break;\n            case 'paroles':\n              selectedParoles = value;\n              break;\n          }\n          \n          \/\/ Pr\u00e9visualiser le nombre de r\u00e9sultats apr\u00e8s chaque changement\n          festival_previewFilterCount();\n        }\n      });\n\n      \/\/ Boutons d'action\n      app.querySelectorAll(\".acf-filter-reset\").forEach(btn => {\n        btn.addEventListener(\"click\", () => {\n          \/\/ Reset tous les filtres\n          selectedDateFilter = null;\n          selectedDateFrom = \"\";\n          selectedDateTo = \"\";\n          selectedProvenance = \"\";\n          selectedMediation = \"\";\n          selectedDiversite = \"\";\n          selectedParoles = \"\";\n\n          \/\/ Reset les inputs\n          if (dateFromInput) dateFromInput.value = \"\";\n          if (dateToInput) dateToInput.value = \"\";\n          \n          \/\/ Reset les radios\n          app.querySelectorAll('input[type=\"radio\"]').forEach(radio => {\n            radio.checked = false;\n          });\n\n          \/\/ Reset les s\u00e9lections visuelles\n          app.querySelectorAll(\".acf-dropdown-item-date\").forEach(item => {\n            item.classList.remove(\"selected\");\n          });\n\n          \/\/ Pr\u00e9visualiser le nombre de r\u00e9sultats apr\u00e8s reset\n          festival_previewFilterCount();\n        });\n      });\n\n      app.querySelectorAll(\".acf-filter-close\").forEach(btn => {\n        btn.addEventListener(\"click\", () => {\n          \/\/ Fermer le dropdown parent\n          const dropdown = btn.closest(\".acf-dropdown\");\n          if (dropdown) dropdown.classList.remove(\"active\");\n        });\n      });\n\n      app.querySelectorAll(\".acf-filter-search\").forEach(btn => {\n        btn.addEventListener(\"click\", () => {\n          \/\/ Fermer le dropdown parent\n          const dropdown = btn.closest(\".acf-dropdown\");\n          if (dropdown) dropdown.classList.remove(\"active\");\n          \n          \/\/ Appliquer les filtres\n          festival_applyFilters();\n        });\n      });\n    }\n\n\/\/ Fonction pour mettre \u00e0 jour le compteur des boutons de recherche\n    function updateSearchButtonCount(count) {\n      const icon = `<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"15\" height=\"12\" viewBox=\"0 0 15 12\" fill=\"none\"><path d=\"M14.1998 6.05035L8.99413 11.256C8.91448 11.3356 8.80645 11.3804 8.69381 11.3804C8.58116 11.3804 8.47313 11.3356 8.39348 11.256C8.31383 11.1763 8.26908 11.0683 8.26908 10.9556C8.26908 10.843 8.31383 10.735 8.39348 10.6553L12.8743 6.17448L1.08558 6.17448C0.975604 6.1706 0.871424 6.12418 0.794992 6.045C0.718561 5.96582 0.675845 5.86007 0.675845 5.75002C0.675845 5.63997 0.718561 5.53422 0.794992 5.45504C0.871424 5.37586 0.975605 5.32944 1.08559 5.32556L12.8743 5.32556L8.39348 0.844719C8.31383 0.765068 8.26908 0.657038 8.26908 0.544395C8.26908 0.431751 8.31383 0.323721 8.39348 0.24407C8.47313 0.164419 8.58116 0.119672 8.69381 0.119672C8.80645 0.119672 8.91448 0.164419 8.99413 0.24407L14.1998 5.4497C14.2794 5.52935 14.3242 5.63738 14.3242 5.75002C14.3242 5.86266 14.2794 5.97069 14.1998 6.05035Z\" fill=\"currentColor\"\/><\/svg>`;\n  app.querySelectorAll(\".acf-filter-search\").forEach(btn => {\n    btn.innerHTML = `<span>${searchResultsText.replace('0', count)}<\/span> ${icon}`;\n  });\n \n  \/\/ Mettre \u00e0 jour le bouton \"Rechercher\" principal en dehors des filtres (seulement le nombre)\n      const mainSubmitBtn = app.querySelector(\".acf-submit\");\n  if (mainSubmitBtn) {\n    mainSubmitBtn.textContent = `${searchButtonText} (${count})`;\n  }\n    }\n\n\/\/ Fonction pour pr\u00e9visualiser le nombre de r\u00e9sultats sans appliquer les filtres\nfunction festival_previewFilterCount() {\n  const previewResults = festival_filterPosts();\n      updateSearchButtonCount(previewResults.length);\n    }\n\n\/\/ Appliquer les filtres\nfunction festival_applyFilters() {\n      currentPage = 1;\n  const filtered = festival_filterPosts();\n  renderPosts(filtered, false);\n  \n  \/\/ Mettre \u00e0 jour le compteur de r\u00e9sultats\n      updateSearchButtonCount(filtered.length);\n    }\n\n\/\/ Initialisation : mettre \u00e0 jour le compteur initial\n    function initInitialCount() {\n  \/\/ Calculer le nombre total de posts disponibles\n      const totalPosts = allPosts.length;\n      updateSearchButtonCount(totalPosts);\n    }\n\n\/\/ Active la s\u00e9lection par clic sur tout le bloc et g\u00e8re l'\u00e9tat visuel\n    function enableFilterOptionBlockClick() {\n  \/\/ Mise \u00e0 jour initiale des classes .selected selon l'\u00e9tat des inputs\n      app.querySelectorAll('.acf-filter-option').forEach(opt => {\n        const input = opt.querySelector('input[type=\"radio\"], input[type=\"checkbox\"]');\n        if (input) opt.classList.toggle('selected', input.checked);\n      });\n\n  \/\/ Clic sur tout le bloc\n      app.addEventListener('click', (e) => {\n        const option = e.target.closest('.acf-filter-option');\n        if (!option || !app.contains(option)) return;\n\n        const input = option.querySelector('input[type=\"radio\"], input[type=\"checkbox\"]');\n        if (!input) return;\n\n        if (input.type === 'checkbox') {\n          input.checked = !input.checked;\n          option.classList.toggle('selected', input.checked);\n        } else {\n      \/\/ Radio: cocher celui-ci et d\u00e9cocher les autres du m\u00eame groupe\n          input.checked = true;\n          if (input.name) {\n            app.querySelectorAll(`input[type=\"radio\"][name=\"${input.name}\"]`).forEach(r => {\n              const block = r.closest('.acf-filter-option');\n              if (block) block.classList.toggle('selected', r === input);\n            });\n          } else {\n            option.classList.add('selected');\n          }\n        }\n    \/\/ D\u00e9clenche le change pour garder la logique existante (filtres\/preview)\n        input.dispatchEvent(new Event('change', { bubbles: true }));\n      });\n\n  \/\/ Si l'utilisateur clique directement sur l'input, garder l'\u00e9tat visuel en phase\n      app.addEventListener('change', (e) => {\n        const input = e.target;\n        if (!(input instanceof HTMLInputElement)) return;\n        if (!\/(radio|checkbox)\/.test(input.type)) return;\n\n        const block = input.closest('.acf-filter-option');\n        if (!block) return;\n\n        if (input.type === 'checkbox') {\n          block.classList.toggle('selected', input.checked);\n        } else {\n          if (input.name) {\n            app.querySelectorAll(`input[type=\"radio\"][name=\"${input.name}\"]`).forEach(r => {\n              const b = r.closest('.acf-filter-option');\n              if (b) b.classList.toggle('selected', r.checked);\n            });\n          } else {\n            block.classList.toggle('selected', input.checked);\n          }\n        }\n      });\n    }\n\n\/\/ Appeler apr\u00e8s le rendu initial des options (apr\u00e8s festival_loadFilterOptions())\nenableFilterOptionBlockClick();\n\n\/\/ Fonction pour charger les options de filtres avec traduction\nasync function festival_loadFilterOptions(app, allPosts, isEnglish, translateChoices) {\n  console.log('loadFilterOptions appel\u00e9e, isEnglish:', isEnglish);\n  \n  \/\/ Charger les provenances\n  const provenanceList = app.querySelector(\".acf-provenance-list\");\n  if (provenanceList) {\n    const provenances = [...new Set(allPosts.map(p => getPostACF(p, 'provenance')).filter(Boolean))];\n    let translatedProvenances = provenances;\n    \n    \/\/ Traduire les provenances si n\u00e9cessaire\n    if (isEnglish && provenances.length > 0) {\n      translatedProvenances = await translateChoices('provenance', provenances);\n    }\n    \n    provenanceList.innerHTML = provenances.map((provenance, index) => `\n      <div class=\"acf-filter-option\">\n        <label for=\"provenance-${provenance}\">${translatedProvenances[index] || provenance}<\/label>\n        <input type=\"radio\" id=\"provenance-${provenance}\" name=\"provenance\" value=\"${provenance}\">\n      <\/div>\n    `).join('');\n  }\n\n  \/\/ Charger les activit\u00e9s de m\u00e9diation\n  const mediationList = app.querySelector(\".acf-mediation-options\");\n  if (mediationList) {\n    const mediations = [...new Set(allPosts.map(p => getPostACF(p, 'activite_de_mediation')).filter(Boolean))];\n    let translatedMediations = mediations;\n    \n    \/\/ Traduire les m\u00e9diations si n\u00e9cessaire\n    if (isEnglish && mediations.length > 0) {\n      translatedMediations = await translateChoices('activite_de_mediation', mediations);\n    }\n    \n    mediationList.innerHTML = mediations.map((mediation, index) => `\n      <div class=\"acf-filter-option\">\n        <label for=\"mediation-${mediation}\">${translatedMediations[index] || mediation}<\/label>\n        <input type=\"radio\" id=\"mediation-${mediation}\" name=\"mediation\" value=\"${mediation}\">\n      <\/div>\n    `).join('');\n  }\n\n  \/\/ Charger les diversit\u00e9s\n  const diversiteList = app.querySelector(\".acf-diversite-options\");\n  if (diversiteList) {\n    const diversites = [...new Set(allPosts.map(p => getPostACF(p, 'diversite')).filter(Boolean))];\n    let translatedDiversites = diversites;\n    \n    \/\/ Traduire les diversit\u00e9s si n\u00e9cessaire\n    if (isEnglish && diversites.length > 0) {\n      translatedDiversites = await translateChoices('diversite', diversites);\n    }\n    \n    diversiteList.innerHTML = diversites.map((diversite, index) => `\n      <div class=\"acf-filter-option\">\n        <label for=\"diversite-${diversite}\">${translatedDiversites[index] || diversite}<\/label>\n        <input type=\"radio\" id=\"diversite-${diversite}\" name=\"diversite\" value=\"${diversite}\">\n      <\/div>\n    `).join('');\n  }\n\n  \/\/ Charger les paroles\n  const parolesList = app.querySelector(\".acf-paroles-options\");\n  if (parolesList) {\n    const paroles = [...new Set(allPosts.map(p => getPostACF(p, 'paroles')).filter(Boolean))];\n    let translatedParoles = paroles;\n    \n    \/\/ Traduire les paroles si n\u00e9cessaire\n    if (isEnglish && paroles.length > 0) {\n      translatedParoles = await translateChoices('paroles', paroles);\n    }\n    \n    parolesList.innerHTML = paroles.map((parole, index) => `\n      <div class=\"acf-filter-option\">\n        <label for=\"paroles-${parole}\">${translatedParoles[index] || parole}<\/label>\n        <input type=\"radio\" id=\"paroles-${parole}\" name=\"paroles\" value=\"${parole}\">\n      <\/div>\n    `).join('');\n  }\n\n  \/\/ Fermer tous les accord\u00e9ons d'abord\n  app.querySelectorAll(\".acf-accordion\").forEach(accordion => {\n    const content = accordion.querySelector(\".acf-accordion-content\");\n    if (content) {\n      content.style.maxHeight = \"0\";\n      content.style.opacity = \"0\";\n    }\n  });\n  \n  \/\/ Puis ouvrir le premier de chaque dropdown\n  setTimeout(() => {\n    initAccordions();\n  }, 100);\n}\n\n\/\/ Modifier la fonction fetchPosts pour appeler initAccordions APR\u00c8S loadFilterOptions\n    async function fetchPosts() {\n      listEl.innerHTML = \"Chargement...\";\n      \n      \/\/ Construire l'URL avec le param\u00e8tre de langue\n      \/\/ Note: on n'utilise pas _fields pour 'link' car WordPress peut retourner un lien incorrect avec _fields\n      let apiUrl = `\/wp-json\/wp\/v2\/${cpt}?per_page=100&_fields=id,title,excerpt,slug,date,acf,featured_media,categories&_embed=wp:featuredmedia,wp:term`;\n      \n      \/\/ Ajouter le param\u00e8tre de langue si on est en anglais\n      if (isEnglish) {\n        apiUrl += '&lang=en';\n      }\n      \n  fetch(apiUrl)\n        .then((r) => r.json())\n        .then(async (posts) => {\n          allPosts = Array.isArray(posts) ? posts : [];\n          currentPage = 1;\n      \n      \/\/ Charger les options de filtres d'abord\n          await festival_loadFilterOptions(app, allPosts, isEnglish, translateChoices);\n      \n      \/\/ Initialiser les accord\u00e9ons APR\u00c8S avoir charg\u00e9 les filtres\n      setTimeout(() => {\n        initAccordions();\n      }, 150); \/\/ D\u00e9lai un peu plus long pour s'assurer que le DOM est pr\u00eat\n      \n          initInitialCount();\n      const filtered = festival_filterPosts();\n      renderPosts(filtered, false);\n        })\n    .catch((error) => {\n          listEl.innerHTML = `<p>Erreur de chargement.<\/p>`;\n        });\n    }\n\t\t\n\/\/ Modifier la gestion de la recherche pour mettre \u00e0 jour le compteur\n    if (searchInput) {\n  searchInput.addEventListener(\"keydown\", (e) => {\n    if (e.key === \"Enter\") {\n      e.preventDefault();\n      festival_applyFilters();\n    }\n  });\n  searchInput.addEventListener(\"input\", () => {\n    \/\/ Pr\u00e9visualiser le nombre de r\u00e9sultats pendant la saisie\n    festival_previewFilterCount();\n  });\n}\n\n\/\/ Modifier le bouton submit principal\nif (submitBtn) {\n  submitBtn.addEventListener(\"click\", () => {\n    festival_applyFilters();\n  });\n}\n    \/\/ Voir plus\n    if (loadMoreBtn) {\n      loadMoreBtn.addEventListener(\"click\", () => {\n        currentPage++;\n        renderPosts(filteredPosts, true);\n      });\n    }\n\n    \/\/ Recherche\n    if (searchInput) {\n      searchInput.addEventListener(\"keydown\", (e) => {\n        if (e.key === \"Enter\") {\n          e.preventDefault();\n          festival_applyFilters();\n        }\n      });\n      searchInput.addEventListener(\"input\", festival_applyFilters);\n    }\n\n    if (submitBtn) submitBtn.addEventListener(\"click\", festival_applyFilters);\n\n    \/\/ Clic sur les cartes (fallback pour les \u00e9l\u00e9ments qui ne sont pas des liens)\n    listEl.addEventListener(\"click\", (e) => {\n      \/\/ Ignorer les clics sur les \u00e9l\u00e9ments interactifs\n      if (e.target.closest('button') || e.target.closest('a') || e.target.closest('.acf-button-plus') || e.target.closest('.button-plus-dynamique')) {\n        return;\n      }\n      const card = e.target.closest(\".acf-card\");\n      \/\/ Si la carte n'est pas d\u00e9j\u00e0 un lien, utiliser le fallback\n      if (card && card.tagName !== 'A') {\n        const lien = card.dataset.lien;\n        if (lien && lien !== '#') {\n          window.open(lien, '_blank');\n        }\n      }\n    });\n\n    \/\/ Fonction pour mettre \u00e0 jour les textes des filtres\n    function updateFilterTexts() {\n      \/\/ Mettre \u00e0 jour les textes des dropdowns\n      const dateLocationSpan = app.querySelector('.acf-date-lieu-dropdown .acf-dropdown-text');\n      if (dateLocationSpan) dateLocationSpan.textContent = dateLocationText;\n      \n      const publicSpan = app.querySelector('.acf-public-dropdown .acf-dropdown-text');\n      if (publicSpan) publicSpan.textContent = 'Public'; \/\/ Public reste Public\n      \n      const filtersSpan = app.querySelector('.acf-filtres-dropdown .acf-dropdown-text');\n      if (filtersSpan) filtersSpan.textContent = filtersText;\n      \n      \/\/ Mettre \u00e0 jour les textes des accord\u00e9ons\n      \n      \/\/ Mettre \u00e0 jour les labels de date\n      const fromLabel = app.querySelector('.acf-date-field:first-of-type label');\n      if (fromLabel) fromLabel.textContent = fromText;\n      \n      const toLabel = app.querySelector('.acf-date-field:last-of-type label');\n      if (toLabel) toLabel.textContent = toText;\n      \n      \/\/ Mettre \u00e0 jour les options de date pr\u00e9d\u00e9finies\n      const passedSpan = app.querySelector('.acf-dropdown-item-date[data-value=\"past\"] .acf-dropdown-text');\n      if (passedSpan) passedSpan.textContent = passedText;\n      \n      const comingSoonSpan = app.querySelector('.acf-dropdown-item-date[data-value=\"upcoming\"] .acf-dropdown-text');\n      if (comingSoonSpan) comingSoonSpan.textContent = comingSoonText;\n      \n        const allSpan = app.querySelector('.acf-dropdown-item-date[data-value=\"all\"] .acf-dropdown-text');\n        if (allSpan) allSpan.textContent = allText;\n        \n        \/\/ Mettre \u00e0 jour les labels des filtres sp\u00e9cifiques\n        \n        \/\/ Mettre \u00e0 jour les boutons\n      app.querySelectorAll('.acf-filter-reset').forEach(btn => {\n        btn.textContent = resetText;\n      });\n      \n      app.querySelectorAll('.acf-filter-close').forEach(btn => {\n        btn.textContent = closeText;\n      });\n    }\n\n    \/\/ Init\n    initAccordions();\n    initDropdowns();\n    initFilters();\n    fetchPosts();\n    \n    \/\/ Mettre \u00e0 jour les textes des filtres apr\u00e8s le chargement\n    setTimeout(updateFilterTexts, 100);\n  });\n});\n    <\/script>\n    <\/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<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Festival Directory An overview of the festivals that showcase the circus across the country Patrice Ducharme-Castonguay, H\u00e9lo\u00efse Binette, Louve Bergeron and Mark Breton | Folies Potag\u00e8res | LP Lemay \u00a9 S\u00e9bastien Chion<\/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-826","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>Festival Directory - En Piste<\/title>\n<meta name=\"description\" content=\"Festivals: Directory of circus festivals in Canada and internationally: dates, locations, calls for proposals.\" \/>\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\/repertoire-des-festivals\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Festival Directory - En Piste\" \/>\n<meta property=\"og:description\" content=\"Festivals: Directory of circus festivals in Canada and internationally: dates, locations, calls for proposals.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/\" \/>\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=\"2025-11-17T21:38:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"750\" \/>\n\t<meta property=\"og:image:height\" content=\"540\" \/>\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\/repertoire-des-festivals\/\",\"url\":\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/\",\"name\":\"Festival Directory - En Piste\",\"isPartOf\":{\"@id\":\"https:\/\/enpiste.qc.ca\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg\",\"datePublished\":\"2025-08-28T17:01:39+00:00\",\"dateModified\":\"2025-11-17T21:38:17+00:00\",\"description\":\"Festivals: Directory of circus festivals in Canada and internationally: dates, locations, calls for proposals.\",\"breadcrumb\":{\"@id\":\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#primaryimage\",\"url\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg\",\"contentUrl\":\"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/enpiste.qc.ca\/en\/homepage\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Festival Directory\"}]},{\"@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":"Festival Directory - En Piste","description":"Festivals: Directory of circus festivals in Canada and internationally: dates, locations, calls for proposals.","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\/repertoire-des-festivals\/","og_locale":"en_US","og_type":"article","og_title":"Festival Directory - En Piste","og_description":"Festivals: Directory of circus festivals in Canada and internationally: dates, locations, calls for proposals.","og_url":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/","og_site_name":"En Piste","article_publisher":"https:\/\/www.facebook.com\/EnPiste1\/","article_modified_time":"2025-11-17T21:38:17+00:00","og_image":[{"width":750,"height":540,"url":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/","url":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/","name":"Festival Directory - En Piste","isPartOf":{"@id":"https:\/\/enpiste.qc.ca\/#website"},"primaryImageOfPage":{"@id":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#primaryimage"},"image":{"@id":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#primaryimage"},"thumbnailUrl":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg","datePublished":"2025-08-28T17:01:39+00:00","dateModified":"2025-11-17T21:38:17+00:00","description":"Festivals: Directory of circus festivals in Canada and internationally: dates, locations, calls for proposals.","breadcrumb":{"@id":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#primaryimage","url":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg","contentUrl":"https:\/\/enpiste.qc.ca\/wp-content\/uploads\/2025\/11\/2025_LesFoliesPotageres_02-e1763415474806.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/enpiste.qc.ca\/repertoire-des-festivals\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/enpiste.qc.ca\/en\/homepage\/"},{"@type":"ListItem","position":2,"name":"Festival Directory"}]},{"@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\/826","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=826"}],"version-history":[{"count":0,"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/pages\/826\/revisions"}],"wp:attachment":[{"href":"https:\/\/enpiste.qc.ca\/en\/wp-json\/wp\/v2\/media?parent=826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}