{"id":4120,"date":"2018-06-09T11:58:41","date_gmt":"2018-06-09T10:58:41","guid":{"rendered":"http:\/\/www.visionlarge.ch\/Blog\/?page_id=4120"},"modified":"2026-04-16T18:13:03","modified_gmt":"2026-04-16T17:13:03","slug":"le-sigma-foveon","status":"publish","type":"page","link":"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/","title":{"rendered":"Le Sigma Foveon"},"content":{"rendered":"\n<p>Comme vous le savez peut-\u00eatre d\u00e9j\u00e0, j&rsquo;ai craqu\u00e9 il y a quelques temps pour la technologie du c\u00e9l\u00e8bre Nipon Sigma. Ce capteur Foveon \u00e0 trois couches permettant la capture directe des trois couleurs primaires d&rsquo;une pr\u00e9cision d\u00e9concertante, mais qui ne pardonne rien.<\/p>\n\n\n\n<p>Afin de ma\u00eetriser la prise d&rsquo;image, le traitement, ses caprices et d\u00e9fauts. Je me suis d\u00e9cid\u00e9 \u00e0 relever les points n\u00e9cessaires \u00e0 son utilisation.<\/p>\n\n\n\n<p>Donc, cela veut dire&#8230; Bient\u00f4t, un test complet des capteurs Foveon quattro via les superbes Dp 0,1,2,3 quattro que j&rsquo;ai pu obtenir gr\u00e2ce \u00e0 la gentillesse du Team Sigma Romandie.<\/p>\n\n\n\n<p>Je recherche encore une version DP Merril afin de pouvoir comparer les deux technologies.<\/p>\n\n\n\n<p>J&rsquo;essayerais de faire des vid\u00e9os (pas trop car j&rsquo;aime pas \u00e7a&#8230;) et de partager mon exp\u00e9rience sur ce capteur si sp\u00e9cifique. Que ce soit \u00e0 la prise de vue, sur les optiques qui m&rsquo;ont l&rsquo;air vraiment de tr\u00e8s haut vol, les param\u00e8tres (y&rsquo;en a un max&#8230;) et les JPG directs du bo\u00eetier, le fameux nouveau DNG Et bien s\u00fbr le RAW X3F et ses diff\u00e9rents r\u00e9glages lors du d\u00e9veloppement avec le soft de Sigma.<\/p>\n\n\n\n<p>J&rsquo;avais d&rsquo;ailleurs \u00e9cris un petit article sur le Foveon apr\u00e8s l&rsquo;avoir d\u00e9couvert avec le magnifique SD quattro et Le DP0 Quattro. C&rsquo;est bien s\u00fbr un avis personnel \ud83d\ude09 et \u00e0 mon niveau \ud83d\ude09<\/p>\n\n\n\n<p>Si vous y voyez des fautes techniques, n&rsquo;h\u00e9sitez pas \u00e0 me contacter. Je ferais en sorte de les corriger si n\u00e9cessaires.<\/p>\n\n\n\n    \n        <div class=\"vl-slider-wrap\" id=\"vl-slider-inst1-wrap\">\n\n                        \n                <div id=\"vl-slider-inst1\"\n             class=\"vl-slider-container vl-slider-cols-1\">\n\n                        <div class=\"vl-slider-row\" data-row=\"0\">\n\n                                                <div class=\"vl-slider-slot\" data-slot=\"0\">\n\n                                        <img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/castle-of-champvent_44190446642_o-2000x1075.jpg\"\n                         alt=\"Castle of Champvent\"\n                         class=\"vl-slider-img vl-slider-img-active\">\n\n                                        <img decoding=\"async\" src=\"\" alt=\"\" class=\"vl-slider-img vl-slider-img-next\">\n\n                                        \n                <\/div>\n            <\/div><!-- \/.vl-slider-row -->\n            \n        <\/div><!-- \/.vl-slider-container -->\n\n                \n                \n                        <div class=\"vl-slider-below-wrap\"\n             id=\"vl-slider-inst1-below-wrap\"\n             style=\"display:none;opacity:0;\">\n                        <div class=\"vl-slider-below-text\"\n                 id=\"vl-slider-inst1-below-0\">\n                                <p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">Castle of Champvent<\/p>\n                                                                <p class=\"vl-sl-alt\" style=\"font-style:normal;font-weight:normal;\">Castle of Champvent<\/p>\n                                                <p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">Panorama de la colline de Champvent o\u00f9 le ch\u00e2teau du m\u00eame nom tr\u00f4ne comme un roi et prot\u00e8ge la plaine.<\/p>\n                            <\/div>\n                    <\/div>\n\n                        <div class=\"vl-sl-toggle-wrap\" id=\"vl-slider-inst1-toggle-wrap\">\n            <button class=\"vl-sl-toggle-btn\"\n                    id=\"vl-slider-inst1-toggle-btn\"\n                    aria-pressed=\"false\"\n                    aria-label=\"Afficher les d\u00e9tails\">\n                                <svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\"\n                     viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n                     stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                    <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8z\"><\/path>\n                    <circle cx=\"12\" cy=\"12\" r=\"3\"><\/circle>\n                <\/svg>\n                <span class=\"vl-sl-btn-label\">Afficher les d\u00e9tails<\/span>\n            <\/button>\n        <\/div>\n                \n    <\/div><!-- \/.vl-slider-wrap -->\n\n                <div class=\"vl-sl-lb-wrap\"\n         id=\"vl-slider-inst1-lightbox\"\n         role=\"dialog\" aria-modal=\"true\" aria-label=\"Visionneuse d'images\"\n         style=\"display:none;\">\n\n                <div class=\"vl-sl-lb-overlay\" aria-hidden=\"true\"><\/div>\n\n        <div class=\"vl-sl-lb-content\">\n\n                        <div class=\"vl-sl-lb-toolbar\">\n                <span class=\"vl-sl-lb-counter\"\n                      id=\"vl-slider-inst1-lb-counter\"\n                      aria-live=\"polite\"><\/span>\n                <button class=\"vl-sl-lb-close\"\n                        id=\"vl-slider-inst1-lb-close\"\n                        aria-label=\"Fermer\">&times;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-stage\">\n                <button class=\"vl-sl-lb-prev\"\n                        id=\"vl-slider-inst1-lb-prev\"\n                        aria-label=\"Image pr\u00e9c\u00e9dente\">&#10094;<\/button>\n\n                <div class=\"vl-sl-lb-img-wrap\">\n                                        <div class=\"vl-sl-lb-progress-container\" aria-hidden=\"true\">\n                        <div class=\"vl-sl-lb-progress-bar\"\n                             id=\"vl-slider-inst1-lb-progress\"><\/div>\n                    <\/div>\n                    <img decoding=\"async\" src=\"\" alt=\"\"\n                         id=\"vl-slider-inst1-lb-img\"\n                         class=\"vl-sl-lb-img\">\n                                        <div class=\"vl-sl-lb-caption\"\n                         id=\"vl-slider-inst1-lb-caption\"\n                         aria-live=\"polite\"><\/div>\n                <\/div>\n\n                <button class=\"vl-sl-lb-next\"\n                        id=\"vl-slider-inst1-lb-next\"\n                        aria-label=\"Image suivante\">&#10095;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-footer\">\n                <div class=\"vl-sl-lb-controls\">\n                    <button class=\"vl-sl-lb-playpause\"\n                            id=\"vl-slider-inst1-lb-playpause\"\n                            aria-label=\"Lancer le diaporama\"\n                            aria-pressed=\"false\">\u25b6<\/button>\n                    <button class=\"vl-sl-lb-speed\"\n                            id=\"vl-slider-inst1-lb-speed\"\n                            aria-label=\"Changer la vitesse\">4s<\/button>\n                <\/div>\n            <\/div>\n\n        <\/div><!-- \/.vl-sl-lb-content -->\n    <\/div><!-- \/.vl-sl-lb-wrap -->\n    \n\n        <style id=\"vl-slider-inst1-style\">\n\n        \/* \u2500\u2500 Wrap ext\u00e9rieur \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:relative est n\u00e9cessaire pour que les fant\u00f4mes (position:absolute)\n           se positionnent par rapport au wrap et non \u00e0 la page enti\u00e8re.          *\/\n        #vl-slider-inst1-wrap {\n            width: 100%;\n            max-width: 100%;\n            margin: 20px auto;\n            position: relative;\n            \/* PAS de overflow:hidden ici \u2014 les fant\u00f4mes d\u00e9bordent intentionnellement *\/\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Conteneur principal : colonne flex (rang\u00e9es empil\u00e9es) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex-direction:column \u2192 les .vl-slider-row s'empilent verticalement.\n           gap:8px \u2192 espacement entre rang\u00e9es.                                    *\/\n        #vl-slider-inst1 {\n            display: flex;\n            flex-direction: column;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            overflow: hidden;\n            border-radius: 8px;\n            background: transparent;\n            box-sizing: border-box;\n        }\n\n        \/* \u2500\u2500 Rang\u00e9e : ligne flex (slots c\u00f4te \u00e0 c\u00f4te) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           height est d\u00e9fini ici par rang\u00e9e pour permettre des hauteurs\n           diff\u00e9rentes entre rang\u00e9e 1 et rang\u00e9e 2 (height_row2).                 *\/\n        #vl-slider-inst1 .vl-slider-row {\n            display: flex;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            height: 400px;\n            overflow: hidden;\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Slot individuel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex:1 \u2192 chaque slot prend la m\u00eame largeur dans sa rang\u00e9e.\n           position:relative \u2192 n\u00e9cessaire pour les images en absolute.            *\/\n        #vl-slider-inst1 .vl-slider-slot {\n            position: relative;\n            flex: 1;\n            min-width: 0;\n            overflow: hidden;\n            border-radius: 6px;\n            box-sizing: border-box;\n            \/* La hauteur est fix\u00e9e par la rang\u00e9e parente (.vl-slider-row) *\/\n        }\n\n        \/* \u2500\u2500 Images : remplissent exactement le slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:absolute + inset:0 \u2192 l'image couvre tout le slot.\n           object-fit:contain \u2192 image enti\u00e8re visible sans recadrage.\n           IMPORTANT : fonctionne uniquement si le slot a une hauteur d\u00e9finie,\n           ce qui est garanti par .vl-slider-row { height: Xpx }.               *\/\n        #vl-slider-inst1 .vl-slider-img {\n            position: absolute;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n            background: transparent;\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* \u2500\u2500 Fix critique : la rang\u00e9e DOIT avoir overflow:hidden \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Sans \u00e7a, les images en position:absolute d\u00e9bordent visuellement\n           m\u00eame si leur taille est contrainte.                                  *\/\n        #vl-slider-inst1 .vl-slider-row {\n            overflow: hidden;\n            contain: strict;       \/* Isole compl\u00e8tement le rendu de la rang\u00e9e *\/\n        }\n        \/* Image active : visible (opacity 1) *\/\n        #vl-slider-inst1 .vl-slider-img-active { opacity: 1; }\n        \/* Image suivante : invisible (opacity 0), pr\u00eate pour la prochaine transition *\/\n        #vl-slider-inst1 .vl-slider-img-next   { opacity: 0; }\n\n                \/* \u2500\u2500 Curseur zoom-in si lightbox activ\u00e9e \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           pointer-events:none sur img-next \u2192 seule l'image active re\u00e7oit les clics. *\/\n        #vl-slider-inst1 .vl-slider-slot { cursor: zoom-in; }\n        #vl-slider-inst1 .vl-slider-img-next { pointer-events: none; }\n        #vl-slider-inst1 .vl-slider-overlay-text { pointer-events: none; }\n        \n        \n        \/* \u2500\u2500 Overlay texte (sur l'image) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Bande semi-transparente en bas de chaque slot.\n           La transition opacity correspond au fade_in configur\u00e9.                 *\/\n        #vl-slider-inst1 .vl-slider-overlay-text {\n            position: absolute;\n            bottom: 0; left: 0; right: 0;\n            background: rgba(0, 0, 0, .5);\n            color: #fff;\n            padding: 10px 16px;\n            font-size: 13px;\n            line-height: 1.5;\n            border-radius: 0 0 6px 6px;\n            transition: opacity 1s ease-in-out;\n        }\n        #vl-slider-inst1 .vl-slider-overlay-text p { margin: 2px 0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2014 scop\u00e9 \u00e0 cette instance \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Pour columns=3 rang\u00e9e 2 (1 slot centr\u00e9) : limiter la largeur du bloc.  *\/\n        #vl-slider-inst1-below-wrap .vl-row-centered .vl-slider-below-text {\n            max-width: 50%;\n        }\n\n        \/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*\/\n        @media (max-width: 767px) {\n            #vl-slider-inst1 .vl-slider-row {\n                height: 200px !important;\n            }\n        }\n        @media (max-width: 479px) {\n                    }\n\n    <\/style>\n\n        <style>\n\n        \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n           LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n           \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n        \/* Fond plein \u00e9cran \u2014 cach\u00e9 par d\u00e9faut, affich\u00e9 via display:flex en JS *\/\n        .vl-sl-lb-wrap {\n            position: fixed;\n            inset: 0;\n            z-index: 99999;\n            display: none; \/* display:flex quand ouverte *\/\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            padding: 1rem;\n            box-sizing: border-box;\n        }\n\n        \/* Fond semi-transparent \u2014 clic = fermeture *\/\n        .vl-sl-lb-overlay {\n            position: fixed;\n            inset: 0;\n            background: rgba(0, 0, 0, .88);\n            cursor: pointer;\n            z-index: 0;\n        }\n\n        \/* Contenu centr\u00e9 au-dessus du fond *\/\n        .vl-sl-lb-content {\n            position: relative;\n            z-index: 1;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 92vw;\n            max-height: 92vh;\n            gap: 8px;\n        }\n\n        \/* Toolbar : compteur + bouton \u00d7 *\/\n        .vl-sl-lb-toolbar {\n            display: flex;\n            width: 100%;\n            align-items: center;\n            justify-content: space-between;\n        }\n        .vl-sl-lb-counter {\n            color: #fff;\n            background: rgba(0, 0, 0, .55);\n            padding: 4px 10px;\n            border-radius: 20px;\n            font-size: 13px;\n        }\n        .vl-sl-lb-close {\n            background: rgba(0, 0, 0, .55);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 34px; height: 34px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            transition: background .2s, transform .2s;\n            line-height: 1;\n        }\n        .vl-sl-lb-close:hover { background: rgba(0, 0, 0, .9); transform: scale(1.15); }\n\n        \/* Stage : fl\u00e8ches + image *\/\n        .vl-sl-lb-stage {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n        }\n        .vl-sl-lb-prev, .vl-sl-lb-next {\n            flex-shrink: 0;\n            background: rgba(0, 0, 0, .5);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 42px; height: 42px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            user-select: none;\n            transition: background .2s, transform .2s;\n        }\n        .vl-sl-lb-prev:hover, .vl-sl-lb-next:hover {\n            background: rgba(0, 0, 0, .9);\n            transform: scale(1.15);\n        }\n\n        \/* Conteneur image : flex-column pour empiler image + caption *\/\n        .vl-sl-lb-img-wrap {\n            position: relative;\n            display: inline-flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 78vw;\n        }\n\n        \/* Image lightbox *\/\n        .vl-sl-lb-img {\n            display: block;\n            max-width: 78vw;\n            max-height: 72vh;\n            border-radius: 8px;\n            box-shadow: 0 4px 32px rgba(0, 0, 0, .5);\n            opacity: 0; \/* commence invisible, JS anime vers 1 *\/\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* Barre de progression du diaporama \u2014 en haut de l'image *\/\n        .vl-sl-lb-progress-container {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 3px;\n            background: rgba(255, 255, 255, .2);\n            border-radius: 2px;\n            overflow: hidden;\n            display: none; \/* visible seulement en mode play *\/\n        }\n        .vl-sl-lb-progress-bar {\n            height: 100%;\n            width: 0%;\n            background: #fff;\n            transition: width linear;\n        }\n\n        \/* Caption sous l'image *\/\n        .vl-sl-lb-caption {\n            color: #fff;\n            font-size: 13px;\n            text-align: center;\n            word-break: break-word;\n            margin-top: 8px;\n            padding: 6px 18px;\n            box-sizing: border-box;\n            max-width: 78vw;\n            line-height: 1.5;\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            border-radius: 14px;\n            display: none; \/* affich\u00e9 par le JS si caption non vide *\/\n        }\n        .vl-sl-lb-caption.has-text { display: inline-block; }\n\n        \/* Footer : boutons play\/pause + vitesse *\/\n        .vl-sl-lb-footer {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            gap: 6px;\n            width: 100%;\n        }\n        .vl-sl-lb-controls { display: flex; gap: 8px; }\n        .vl-sl-lb-playpause, .vl-sl-lb-speed {\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            color: #fff;\n            border-radius: 20px;\n            padding: 4px 14px;\n            font-size: 13px;\n            cursor: pointer;\n            transition: background .2s;\n            min-width: 48px;\n            text-align: center;\n        }\n        .vl-sl-lb-playpause:hover, .vl-sl-lb-speed:hover {\n            background: rgba(255, 255, 255, .28);\n        }\n\n        \/* Mobile : masquer les contr\u00f4les pour ne pas g\u00eaner le swipe *\/\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-prev,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-next,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-caption,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-progress-container,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-close,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-counter { display: none !important; }\n\n        \/* \u2500\u2500 Bouton toggle \"Afficher les d\u00e9tails\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Petit bouton discret align\u00e9 \u00e0 droite, au-dessus des textes below.\n           La classe .active indique l'\u00e9tat \"ouvert\".                             *\/\n        .vl-sl-toggle-wrap { text-align: right; margin-bottom: 10px; }\n        .vl-sl-toggle-btn {\n            background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;\n            padding: 7px 12px; cursor: pointer; font-size: 12px;\n            display: inline-flex; align-items: center; gap: 6px;\n            box-shadow: 0 2px 6px rgba(0, 0, 0, .12);\n            transition: background .2s, box-shadow .2s;\n            line-height: 1;\n        }\n        .vl-sl-toggle-btn:hover  { background: #ececec; box-shadow: 0 3px 8px rgba(0, 0, 0, .18); }\n        .vl-sl-toggle-btn.active { background: #e0e0e0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Le wrap est flex horizontal : un bloc par colonne, c\u00f4te \u00e0 c\u00f4te.\n           Chaque bloc est un bloc normal : les <p> s'empilent naturellement.     *\/\n        .vl-slider-below-wrap {\n            display: flex;\n            flex-direction: row;\n            gap: 8px;\n            width: 100%;\n            box-sizing: border-box;\n            opacity: 0;\n            transition: opacity .3s ease;\n        }\n        .vl-slider-below-wrap.vl-sl-texts-visible { opacity: 1; }\n\n        \/* Bloc texte individuel \u2014 un par image visible *\/\n        .vl-slider-below-text {\n            flex: 1;\n            min-width: 0;\n            padding: 8px 4px;\n            font-size: 13px;\n            line-height: 1.5;\n            text-align: center;\n            box-sizing: border-box;\n        }\n        .vl-slider-below-text p { margin: 2px 0; }\n\n        \/* Styles texte *\/\n        .vl-sl-title       { font-weight: bold; }\n        .vl-sl-caption     { font-style: italic; }\n        .vl-sl-alt         { font-size: 11px; }\n        .vl-sl-description { font-size: 12px; }\n\n        \/* Couleurs overlay (fond sombre \u2192 texte blanc) *\/\n        .vl-slider-overlay-text .vl-sl-title       { color: #fff; }\n        .vl-slider-overlay-text .vl-sl-caption     { color: rgba(255, 255, 255, .8); }\n        .vl-slider-overlay-text .vl-sl-alt         { color: rgba(255, 255, 255, .6); }\n        .vl-slider-overlay-text .vl-sl-description { color: rgba(255, 255, 255, .9); }\n\n        \/* Couleurs below (fond clair \u2192 texte sombre) *\/\n        .vl-slider-below-text .vl-sl-title       { color: #222; }\n        .vl-slider-below-text .vl-sl-caption     { color: #666; }\n        .vl-slider-below-text .vl-sl-alt         { color: #999; font-size: 11px; }\n        .vl-slider-below-text .vl-sl-description { color: #444; font-size: 12px; }\n\n    <\/style>\n\n        <script>\n    (function () {\n        'use strict';\n\n        document.addEventListener('DOMContentLoaded', function () {\n\n            \/\/ \u2500\u2500 R\u00e9f\u00e9rences DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On r\u00e9cup\u00e8re le conteneur principal. Si absent (shortcode mal copi\u00e9),\n            \/\/ on quitte imm\u00e9diatement pour \u00e9viter les erreurs JS.\n            var slider = document.getElementById('vl-slider-inst1');\n            if ( ! slider ) return;\n\n            \/\/ Tous les slots de la grille (inclut toutes les rang\u00e9es)\n            var slots = slider.querySelectorAll('.vl-slider-slot');\n\n            \/\/ Fant\u00f4mes gauche et droit (null si ghost_peek=false \u2192 divs absentes)\n            var ghostLeft  = document.getElementById('vl-slider-inst1-ghost-left');\n            var ghostRight = document.getElementById('vl-slider-inst1-ghost-right');\n            var ghostImgL  = ghostLeft  ? ghostLeft.querySelector('.vl-ghost-img')  : null;\n            var ghostImgR  = ghostRight ? ghostRight.querySelector('.vl-ghost-img') : null;\n\n            \/\/ Overlays texte \u2014 un par slot, cherch\u00e9s dans le conteneur slider\n            var overlayEls = Array.prototype.slice.call(\n                slider.querySelectorAll('.vl-slider-overlay-text')\n            );\n            \/\/ Blocs texte \"below\" \u2014 cibl\u00e9s par classe pour \u00e9viter de capturer le wrap\n            var belowWrap  = document.getElementById('vl-slider-inst1-below-wrap');\n            var belowEls   = belowWrap\n                ? Array.prototype.slice.call( belowWrap.querySelectorAll('.vl-slider-below-text') )\n                : [];\n\n            \/\/ \u2500\u2500 Donn\u00e9es inject\u00e9es par PHP \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ wp_json_encode() c\u00f4t\u00e9 PHP \u2192 JSON valide et safe\n            var slides      = [{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/castle-of-champvent_44190446642_o-2000x1075.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/castle-of-champvent_44190446642_o-scaled.jpg\",\"alt\":\"Castle of Champvent\",\"title\":\"Castle of Champvent\",\"caption\":\"Sigma DP quattro\",\"description\":\"Panorama de la colline de Champvent o\\u00f9 le ch\\u00e2teau du m\\u00eame nom tr\\u00f4ne comme un roi et prot\\u00e8ge la plaine.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50938454608_c3019c55e9_o-2000x1136.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50938454608_c3019c55e9_o.jpg\",\"alt\":\"Vevey, assise sur un banc au bord du lac L\\u00e9man \\u00e0 Vevey\",\"title\":\"Au bord du lac L\\u00e9man \\u00e0 Vevey\",\"caption\":\"Sigma Foveon DP quattro\",\"description\":\"Panorama street au bord du lac L\\u00e9man \\u00e0 Vevey. J\\u2019aime me promener sur les belles rives du lac L\\u00e9man \\u00e0 Vevey. Il y a de jolies possibilit\\u00e9s de faire des images.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/barrage-demosson_43707752510_o-2000x1183.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/barrage-demosson_43707752510_o.jpg\",\"alt\":\"Panoramique du barrage d&#039;Emosson en Suisse au Sigma Fov\\u00e9on DP0 en automne\",\"title\":\"Emosson\",\"caption\":\"Sigma DP0 quatteo\",\"description\":\"Le magnifique barrage d\\u2019Emosson. Un lieu magnifique pour une architecture magnifique et une for\\u00eat de m\\u00e9l\\u00e8zes et un lac incroyable.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/promenade-sous-la-pluie-fine-dautomne_30743713797_o-2000x1183.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/promenade-sous-la-pluie-fine-dautomne_30743713797_o.jpg\",\"alt\":\"panoramique sous la pluie fine d&#039;automne \\u00e0 Yverdon au Foveon\",\"title\":\"Promenade sous la Pluie\",\"caption\":\"Sigma DP quattro \",\"description\":\"Des promeneurs bravent la pluie en ce jour d\\u2019automne. Plage d\\u2019Yverdon-les-Bains, Vaud.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lallee-des-beaux-arbres_35988594465_o-2000x1176.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lallee-des-beaux-arbres_35988594465_o.jpg\",\"alt\":\"All\\u00e9e d&#039;arbres pr\\u00e8s de saint-Sulpice en suisse romande au Fov\\u00e9on de Sigma\",\"title\":\"lallee-des-beaux-arbres_35988594465_o\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/chemin-de-campagne_35768912872_o-2000x1176.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/chemin-de-campagne_35768912872_o.jpg\",\"alt\":\"Chemin de campagne et un arbre au Sigma Fov\\u00e9on DP0\",\"title\":\"chemin-de-campagne_35768912872_o\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/le-barrage-demosson_45628752922_o-2000x1079.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/le-barrage-demosson_45628752922_o.jpg\",\"alt\":\"Panorama du barrage d&#039;Emosson en automne au Foveon\",\"title\":\"Le barrage d&rsquo;Emosson\",\"caption\":\"Sigma DP0 Quattro\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/promenade-en-fort_46056632942_o-2000x1172.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/promenade-en-fort_46056632942_o-scaled.jpg\",\"alt\":\"image r\\u00e9alis\\u00e9e au Sigma Fov\\u00e9on Dp2Q en for\\u00eat en automne en Suisse\",\"title\":\"promenade-en-fort_46056632942_o\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/soleil-rasant_31648556007_o-2000x1175.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/soleil-rasant_31648556007_o-scaled.jpg\",\"alt\":\"panoramique de la tour d&#039;eau de Goumoens au couch\\u00e9 du soleil au Sigma Foveon\",\"title\":\"Goumoens, Vaud\",\"caption\":\"Sigma DP quattro\",\"description\":\"Panoramique de la tour d&#039;eau de Goumoens au couch\\u00e9 du soleil au Sigma Foveon\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/47388336601_c37357e0f4_o-2000x1186.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/47388336601_c37357e0f4_o.jpg\",\"alt\":\"Panoramique au coucher du soleil au DP3Q des Alpes suisse et d&#039;un immense nuages oranges\",\"title\":\"Au coucher du soleil\",\"caption\":\"Sigma Foveon DP3Q \",\"description\":\"Alors que je m&#039;appr\\u00eate \\u00e0 descendre sur la pleine, pensant que ce soir l\\u00e0, aucune lumi\\u00e8re int\\u00e9ressante ne serait pr\\u00e9sente. Je me d\\u00e9cide tout de m\\u00eame \\u00e0 m&#039;arr\\u00eater sur le c\\u00f4t\\u00e9 de la route. Surprise. L&#039;immense nuage est illumin\\u00e9 quelques secondes d&#039;un orange incroyable. J&#039;immortalise l&#039;instant. Le Sigma Foveon n&#039;\\u00e9tait pas id\\u00e9al pour ce genre de prise de vue. Mais l&#039;important c&#039;est l&#039;instant!\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/etang-du-seppey-dans-la-brume-dun-mois-de-novembre_32155062078_o-2000x1026.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/etang-du-seppey-dans-la-brume-dun-mois-de-novembre_32155062078_o.jpg\",\"alt\":\"Etang du Seppey dans la brume d&#039;un mois de Novembre\",\"title\":\"Etang du Seppey dans la brume d&rsquo;un mois de Novembre\",\"caption\":\"Sigma DP0 Quattro \",\"description\":\"Promenade au bord de l\\u2019Etang du Seppey dans la for\\u00eat du m\\u00eame nom pr\\u00e8s de Cossonay.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DP0Q0800-2000x934.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DP0Q0800.jpg\",\"alt\":\"Derni\\u00e8res lumi\\u00e8res sur le site du barrage d&#039;Emosson\",\"title\":\"Derni\\u00e8res lumi\\u00e8res sur le site du barrage d&rsquo;Emosson\",\"caption\":\"Sigma DP0 Quattro\",\"description\":\"Derni\\u00e8res lumi\\u00e8res sur le site du barrage d&#039;Emosson. Le lac est magnifique et sa couleur fonc\\u00e9e se transforme en mirroir.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50939148346_93d1d71469_o-2000x927.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50939148346_93d1d71469_o.jpg\",\"alt\":\"Chute Crissier\",\"title\":\"Chutes d\\u2019eau \\u00e0 Crissier\",\"caption\":\"Sigma DP Foveon \",\"description\":\"Image de la chute de la M\\u00e8bre pr\\u00e8s de Crissier dans le canton de Vaud. Image prise au Foveon en mode noir et blanc. Les d\\u00e9tails sur ce genre d\\u2019appareil sont souvent exceptionnels.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/cloud_44150228342_o-2000x928.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/cloud_44150228342_o-scaled.jpg\",\"alt\":\"Nuages et lumi\\u00e8res pr\\u00e8s de Mathos en Suisse au Fov\\u00e9on\",\"title\":\"cloud_44150228342_o\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/dans-la-brume_43803671490_o-2000x933.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/dans-la-brume_43803671490_o.jpg\",\"alt\":\"en montant sur Emosson vue sur le valais en automne\",\"title\":\"dans-la-brume_43803671490_o\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50939150586_b6719e7cf6_o-2000x923.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50939150586_b6719e7cf6_o-scaled.jpg\",\"alt\":\"Champvent\",\"title\":\"Champvent au Foveon\",\"caption\":\"Sigma DP Foveon\",\"description\":\"Panorama du ch\\u00e2teau de Champvent prise au DP Foveon de Sigma.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/fort-et-brume_45993276012_o-2000x925.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/fort-et-brume_45993276012_o-scaled.jpg\",\"alt\":\"Panoramique au Fov\\u00e9on Dp3Q de la for\\u00eat magique du Seppey\",\"title\":\"For\\u00eat de brumes\",\"caption\":\"Sigma DP\",\"description\":\"Dans la for\\u00eat magique (for\\u00eat du Seppey) pr\\u00e8s de Cossonay. La brume donne un effet de profondeur et un c\\u00f4t\\u00e9 mystique \\u00e0 l&#039;image\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50560228961_27de95cd95_o-2000x2000.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50560228961_27de95cd95_o.jpg\",\"alt\":\"L&#039;Orbe\",\"title\":\"L&rsquo;Orbe\",\"caption\":\"Sigma Foveon DP quattro\",\"description\":\"Dans les belles gorges de l\\u2019Orbe, le pont de la ville du m\\u00eame nom se refl\\u00e8te dans la rivi\\u00e8re.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lumire-sur-le-jura_43463547024_o-2000x2000.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lumire-sur-le-jura_43463547024_o.jpg\",\"alt\":\"Lumi\\u00e8re sur le Jura avec le Sigma Fov\\u00e9on\",\"title\":\"Lumi\\u00e8re sur le Jura\",\"caption\":\"Sigma DP 3\",\"description\":\"Lumi\\u00e8re sur les collines pr\\u00e8s du Jura. Le ciel devient incroyable. Et les possibilit\\u00e9 du DP3 permettent de structurer les couleurs du ciel.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/the-gate_32172395998_o-1378x2000.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/the-gate_32172395998_o.jpg\",\"alt\":\"Porte des bois de la for\\u00eat magique du Seppey en suisse romande pr\\u00e8s de Cossonay au Sigma Fov\\u00e9on\",\"title\":\"La for\\u00eat magique\",\"caption\":\"Sigma DP Foveon \",\"description\":\"Promenade dans la belle for\\u00eat du Seppey. Que l\\u2019on appelle pour certains, la for\\u00eat magique. Je suis avec mon DP Sigma. Je remarque ce passage en deux immenses arbres majestueux. Il me suffit juste d\\u2019attendre le promeneur\\u2026\"}];\n            var columns     = 1;\n            var slotCount   = 1; \/\/ Nb total de slots visibles\n            var lightbox    = true;\n            var showTitle       = true;\n            var showCaption     = false;\n            var showAlt         = true;\n            var showDescription = true;\n\n            \/\/ \u2500\u2500 Variables d'\u00e9tat du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ currentIndex : index dans $slides de la premi\u00e8re image affich\u00e9e\n            var currentIndex  = 0;\n            \/\/ Dur\u00e9es en millisecondes (PHP les envoie en secondes)\n            var displayTime   = 3 * 1000;\n            var fadeInTime    = 1 * 1000;\n            var fadeOutTime   = 1 * 1000;\n            var sliderPaused  = false;  \/\/ Vrai quand la lightbox ou le toggle sont ouverts\n            var sliderTimer   = null;   \/\/ R\u00e9f\u00e9rence au setTimeout en cours\n\n            \/\/ \u2500\u2500 pauseSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Arr\u00eate les transitions (lightbox ouverte, textes below affich\u00e9s).\n            \/\/ clearTimeout annule le prochain changeImage() planifi\u00e9.\n            function pauseSlider() {\n                sliderPaused = true;\n                if ( sliderTimer ) {\n                    clearTimeout( sliderTimer );\n                    sliderTimer = null;\n                }\n            }\n\n            \/\/ \u2500\u2500 resumeSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Reprend les transitions apr\u00e8s fermeture lightbox ou toggle.\n            \/\/ Ne red\u00e9marre que s'il y a assez d'images pour animer.\n            function resumeSlider() {\n                sliderPaused = false;\n                if ( slides.length >= slotCount && slides.length > 1 ) {\n                    sliderTimer = setTimeout( changeImage, displayTime );\n                }\n            }\n\n            \/\/ \u2500\u2500 Protection des images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ D\u00e9sactive le clic droit (contextmenu) et le glisser-d\u00e9poser (dragstart)\n            \/\/ sur toutes les images du slider pour d\u00e9courager la copie.\n            slider.querySelectorAll('.vl-slider-img').forEach(function ( img ) {\n                img.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n                img.addEventListener('dragstart',   function (e) { e.preventDefault(); });\n            });\n            slider.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n            \/\/ Navigation : fl\u00e8ches, clavier, swipe tactile\n            \/\/ Diaporama  : play\/pause, vitesse, barre de progression\n            \/\/ Transitions: fade | slide | none (param\u00e8tre lb_transition)\n            \/\/ Mobile     : masquage automatique des contr\u00f4les, swipe uniquement\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            if ( lightbox ) {\n\n                var lbWrap     = document.getElementById('vl-slider-inst1-lightbox');\n                var lbImg      = document.getElementById('vl-slider-inst1-lb-img');\n                var lbClose    = document.getElementById('vl-slider-inst1-lb-close');\n                var lbOverlay  = lbWrap ? lbWrap.querySelector('.vl-sl-lb-overlay') : null;\n                var lbPrev     = document.getElementById('vl-slider-inst1-lb-prev');\n                var lbNext     = document.getElementById('vl-slider-inst1-lb-next');\n                var lbCounter  = document.getElementById('vl-slider-inst1-lb-counter');\n                var lbCaption  = document.getElementById('vl-slider-inst1-lb-caption');\n                var lbPlay     = document.getElementById('vl-slider-inst1-lb-playpause');\n                var lbSpeedBtn = document.getElementById('vl-slider-inst1-lb-speed');\n                var lbProgress = document.getElementById('vl-slider-inst1-lb-progress');\n                var lbProgWrap = lbProgress ? lbProgress.parentElement : null;\n                var lbTransition  = 'fade';\n                var lbTransSpeed  = 400;\n                var lbSlideTimer  = null;\n                var lbSlideSpeed  = 4000;\n                var lbIsPlaying   = false;\n                var lbCurrentIdx  = 0;\n                var lbImages      = [];\n                var lbNavigating  = false;\n\n                if ( ! lbWrap ) return;\n\n                function lbIsMobile() {\n                    return \/Android|iPhone|iPod\/i.test(navigator.userAgent) &&\n                           ( 'ontouchstart' in window || navigator.maxTouchPoints > 0 );\n                }\n                function lbIsTabletPortrait() {\n                    return ( \/iPad|Android\/i.test(navigator.userAgent) || navigator.maxTouchPoints > 0 ) &&\n                           window.innerWidth <= 1024 && window.innerHeight > window.innerWidth;\n                }\n                function updateMobileNav() {\n                    lbWrap.classList.toggle('vl-lb-hide-nav', lbIsMobile() || lbIsTabletPortrait());\n                }\n\n                function openLightbox( clickedIndex ) {\n                    lbImages = slides.map(function ( s ) {\n                        return { url: s.full_url || s.url, alt: s.alt || '', title: s.title || '', description: s.description || '' };\n                    });\n                    lbCurrentIdx = ( ( clickedIndex % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var single = lbImages.length <= 1;\n                    if ( lbPrev ) lbPrev.style.display = single ? 'none' : '';\n                    if ( lbNext ) lbNext.style.display = single ? 'none' : '';\n                    updateMobileNav();\n                    lbWrap.style.display = 'flex';\n                    document.body.style.overflow = 'hidden';\n                    showLbImage( lbCurrentIdx );\n                    if ( lbClose ) lbClose.focus();\n                }\n\n                function showLbImage( index ) {\n                    if ( ! lbImages.length ) return;\n                    var prevIdx  = lbCurrentIdx;\n                    lbCurrentIdx = ( ( index % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var item     = lbImages[ lbCurrentIdx ];\n                    var dir      = index >= prevIdx ? 1 : -1;\n\n                    if ( lbCounter ) lbCounter.textContent = ( lbCurrentIdx + 1 ) + ' \/ ' + lbImages.length;\n                    var capText = item.description || item.alt || item.title || '';\n                    if ( lbCaption ) {\n                        lbCaption.textContent = capText;\n                        lbCaption.classList.toggle('has-text', capText.length > 0);\n                    }\n                    resetLbProgressBar();\n\n                    if ( lbTransition === 'none' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealNone() { lbImg.style.opacity = '1'; }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealNone() : ( lbImg.onload = lbImg.onerror = revealNone );\n                        return;\n                    }\n\n                    if ( lbTransition === 'fade' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.onload = null; lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealFade() {\n                            void lbImg.offsetWidth;\n                            lbImg.style.transition = 'opacity ' + ( lbTransSpeed \/ 1000 ) + 's ease';\n                            requestAnimationFrame(function () { lbImg.style.opacity = '1'; });\n                        }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealFade() : ( lbImg.onload = lbImg.onerror = revealFade );\n                        return;\n                    }\n\n                    if ( lbTransition === 'slide' ) {\n                        var imgWrap = lbImg.parentElement;\n                        var easing  = 'cubic-bezier(.25,.46,.45,.94)';\n                        var dur     = ( lbTransSpeed \/ 1000 ) + 's';\n                        var newImg  = new Image();\n                        newImg.alt = item.alt; newImg.draggable = false;\n                        newImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;box-shadow:0 4px 32px rgba(0,0,0,.5);opacity:1;transform:translateX(' + ( dir * 100 ) + '%);transition:none;user-select:none';\n                        function doSlide() {\n                            imgWrap.style.cssText = 'position:relative;overflow:hidden;display:inline-flex;width:' + lbImg.offsetWidth + 'px;height:' + lbImg.offsetHeight + 'px';\n                            lbImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;opacity:1;transform:translateX(0);transition:none;user-select:none';\n                            imgWrap.appendChild( newImg );\n                            requestAnimationFrame(function () {\n                                requestAnimationFrame(function () {\n                                    lbImg.style.transition = newImg.style.transition = 'transform ' + dur + ' ' + easing;\n                                    lbImg.style.transform  = 'translateX(' + ( -dir * 100 ) + '%)';\n                                    newImg.style.transform = 'translateX(0)';\n                                    setTimeout(function () {\n                                        lbImg.src = newImg.src; lbImg.alt = newImg.alt;\n                                        lbImg.style.cssText = ''; lbImg.style.opacity = '1';\n                                        if ( imgWrap.contains(newImg) ) imgWrap.removeChild( newImg );\n                                        imgWrap.style.cssText = '';\n                                        lbNavigating = false;\n                                    }, lbTransSpeed + 30);\n                                });\n                            });\n                        }\n                        newImg.onload = newImg.onerror = doSlide;\n                        newImg.src = item.url;\n                        if ( newImg.complete && newImg.naturalWidth > 0 ) { newImg.onload = null; doSlide(); }\n                        return;\n                    }\n                }\n\n                function lbNavigateTo( direction ) {\n                    if ( lbNavigating ) return;\n                    lbNavigating = true;\n                    showLbImage( lbCurrentIdx + direction );\n                    if ( lbTransition !== 'slide' ) setTimeout(function () { lbNavigating = false; }, lbTransSpeed + 50);\n                }\n\n                function closeLightbox() {\n                    lbWrap.style.display = 'none';\n                    lbImg.src = '';\n                    document.body.style.overflow = '';\n                    stopLbSlideshow();\n                    pauseSlider();\n                    setTimeout(function () { resumeSlider(); }, 300);\n                }\n\n                function startLbSlideshow() {\n                    stopLbSlideshow();\n                    lbSlideTimer = setInterval(function () { lbNavigateTo( 1 ); }, lbSlideSpeed);\n                    lbIsPlaying = true;\n                    if ( lbPlay ) { lbPlay.textContent = '\u23f8'; lbPlay.setAttribute('aria-pressed', 'true'); lbPlay.setAttribute('aria-label', 'Arr\u00eater le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'block';\n                    resetLbProgressBar();\n                }\n\n                function stopLbSlideshow() {\n                    if ( lbSlideTimer ) { clearInterval( lbSlideTimer ); lbSlideTimer = null; }\n                    lbIsPlaying = false;\n                    if ( lbPlay ) { lbPlay.textContent = '\u25b6'; lbPlay.setAttribute('aria-pressed', 'false'); lbPlay.setAttribute('aria-label', 'Lancer le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'none';\n                    if ( lbProgress ) { lbProgress.style.transition = 'none'; lbProgress.style.width = '0%'; }\n                }\n\n                function resetLbProgressBar() {\n                    if ( ! lbIsPlaying || ! lbProgress ) return;\n                    lbProgress.style.transition = 'none'; lbProgress.style.width = '0%';\n                    requestAnimationFrame(function () {\n                        requestAnimationFrame(function () {\n                            lbProgress.style.transition = 'width ' + ( lbSlideSpeed \/ 1000 ) + 's linear';\n                            lbProgress.style.width = '100%';\n                        });\n                    });\n                }\n\n                slots.forEach(function ( slot, slotIndex ) {\n                    slot.addEventListener('click', function () {\n                        var clickedIndex = ( currentIndex + slotIndex ) % slides.length;\n                        pauseSlider();\n                        openLightbox( clickedIndex );\n                    });\n                });\n\n                if ( lbClose )   lbClose.addEventListener('click', closeLightbox);\n                if ( lbOverlay ) lbOverlay.addEventListener('click', closeLightbox);\n                if ( lbPrev )    lbPrev.addEventListener('click', function () { lbNavigateTo( -1 ); });\n                if ( lbNext )    lbNext.addEventListener('click', function () { lbNavigateTo(  1 ); });\n\n                document.addEventListener('keydown', function ( e ) {\n                    if ( lbWrap.style.display !== 'flex' ) return;\n                    if ( e.key === 'Escape'     ) closeLightbox();\n                    if ( e.key === 'ArrowLeft'  ) lbNavigateTo( -1 );\n                    if ( e.key === 'ArrowRight' ) lbNavigateTo(  1 );\n                });\n\n                if ( lbPlay ) {\n                    lbPlay.addEventListener('click', function () {\n                        lbIsPlaying ? stopLbSlideshow() : startLbSlideshow();\n                    });\n                }\n\n                var lbSpeeds  = [ 2000, 4000, 6000 ];\n                var lbSpeedLb = [ '2s', '4s', '6s' ];\n                if ( lbSpeedBtn ) {\n                    lbSpeedBtn.addEventListener('click', function () {\n                        var idx = ( lbSpeeds.indexOf( lbSlideSpeed ) + 1 ) % lbSpeeds.length;\n                        lbSlideSpeed = lbSpeeds[ idx ];\n                        lbSpeedBtn.textContent = lbSpeedLb[ idx ];\n                        if ( lbIsPlaying ) startLbSlideshow();\n                    });\n                }\n\n                var lbSwipeStartX = 0, lbSwipeHandled = false;\n                if ( lbImg ) {\n                    lbImg.addEventListener('touchstart', function ( e ) {\n                        lbSwipeStartX = e.changedTouches[0].screenX; lbSwipeHandled = false;\n                    }, { passive: true });\n                    lbImg.addEventListener('touchend', function ( e ) {\n                        if ( lbSwipeHandled ) return;\n                        var diff = lbSwipeStartX - e.changedTouches[0].screenX;\n                        if ( Math.abs(diff) > 40 ) { lbSwipeHandled = true; lbNavigateTo( diff > 0 ? 1 : -1 ); }\n                    }, { passive: true });\n                }\n\n                window.addEventListener('resize',            updateMobileNav);\n                window.addEventListener('orientationchange', updateMobileNav);\n\n            } \/\/ fin if(lightbox)\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TEXTES \u2014 buildTextHtml() et updateTextSlot()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            \/\/ \u2500\u2500 buildTextHtml(slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Construit le HTML des textes pour un slide donn\u00e9.\n            \/\/ Les styles CSS sont inject\u00e9s par PHP (esc_js) au rendu de la page\n            \/\/ \u2192 ils sont des constantes, pas des donn\u00e9es utilisateur.\n            \/\/ Les valeurs slide.title etc. sont d\u00e9j\u00e0 esc_html() c\u00f4t\u00e9 PHP\n            \/\/ \u2192 safe pour innerHTML.\n            function buildTextHtml( slide ) {\n                var html = '';\n                if ( showTitle && slide.title ) {\n                    html += '<p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">'\n                          + slide.title + '<\/p>';\n                }\n                if ( showCaption && slide.caption ) {\n                    html += '<p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">'\n                          + slide.caption + '<\/p>';\n                }\n                if ( showAlt && slide.alt ) {\n                    html += '<p class=\"vl-sl-alt\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.alt + '<\/p>';\n                }\n                if ( showDescription && slide.description ) {\n                    html += '<p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.description + '<\/p>';\n                }\n                return html;\n            }\n\n            \/\/ \u2500\u2500 updateTextSlot(slotIndex, slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour overlay ET below d'un slot donn\u00e9 avec les textes du slide.\n            \/\/ Utilis\u00e9 \u00e0 l'initialisation et lors des transitions.\n            function updateTextSlot( slotIndex, slide ) {\n                if ( overlayEls[ slotIndex ] ) {\n                    overlayEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n                if ( belowEls[ slotIndex ] ) {\n                    belowEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ FANT\u00d4MES \u2014 updateGhosts()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            var ghostPeek = false;\n\n            \/\/ \u2500\u2500 updateGhosts() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour les images des fant\u00f4mes selon la position courante.\n            \/\/ Appel\u00e9e apr\u00e8s chaque transition et lors d'un changement via lightbox.\n            \/\/\n            \/\/ Fant\u00f4me gauche = image juste avant currentIndex (boucle circulaire)\n            \/\/ Fant\u00f4me droit  = image juste apr\u00e8s le dernier slot visible\n            \/\/ Si une seule image : les deux fant\u00f4mes montrent la m\u00eame image.\n            function updateGhosts() {\n                if ( ! ghostPeek ) return;\n                var n = slides.length;\n                var prevIdx = n > 1 ? ( currentIndex - 1 + n ) % n : currentIndex;\n                var nextIdx = n > slotCount ? ( currentIndex + slotCount ) % n : currentIndex;\n\n                \/\/ Fade out \u2192 changer src \u2192 fade in \u2014 synchronis\u00e9 avec fadeOutTime du slider\n                var dur = fadeOutTime \/ 1000;\n\n                if ( ghostImgL ) {\n                    ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgL.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgL.src = slides[ prevIdx ].url;\n                        ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgL.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n                if ( ghostImgR ) {\n                    ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgR.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgR.src = slides[ nextIdx ].url;\n                        ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgR.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n            }\n\n            \/\/ Initialisation des fant\u00f4mes au chargement\n            updateGhosts();\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TRANSITION PRINCIPALE \u2014 changeImage()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Cette fonction orchestre la transition de TOUS les slots en m\u00eame temps.\n            \/\/ Elle utilise des setTimeout cha\u00een\u00e9s (pas setInterval) pour \u00e9viter\n            \/\/ les d\u00e9rives de timing.\n            \/\/\n            \/\/ S\u00e9quence pour chaque slot :\n            \/\/   1. Fade OUT de imgActive  (dur\u00e9e: fadeOutTime)\n            \/\/   2. Apr\u00e8s fadeOut : charger imgNext + Fade IN  (dur\u00e9e: fadeInTime)\n            \/\/   3. Apr\u00e8s fadeIn : permuter imgActive \u2194 imgNext (op\u00e9ration instantan\u00e9e)\n            \/\/   4. Attendre displayTime \u2192 lancer le prochain changeImage()\n            \/\/\n            \/\/ currentIndex est avanc\u00e9 au step 3 du DERNIER slot (c === slots.length-1)\n            \/\/ pour \u00e9viter les race conditions avec la lightbox.\n\n            function changeImage() {\n                if ( slides.length < 2 ) return;\n                if ( sliderPaused ) return;\n\n                var nextIndices = [];\n                for ( var c = 0; c < slotCount; c++ ) {\n                    nextIndices.push( ( currentIndex + slotCount + c ) % slides.length );\n                }\n\n                \/\/ Lancer la transition des fant\u00f4mes en m\u00eame temps que les images\n                updateGhosts();\n\n                \/\/ \u2500\u2500 Transition par slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On it\u00e8re sur chaque slot. Les closures setTimeout capturent\n                \/\/ les variables locales (slot, imgActive, imgNext\u2026) par valeur\n                \/\/ gr\u00e2ce aux param\u00e8tres de fonction.\n                slots.forEach(function ( slot, c ) {\n                    var imgActive   = slot.querySelector('.vl-slider-img-active');\n                    var imgNext     = slot.querySelector('.vl-slider-img-next');\n                    var nextSlide   = slides[ nextIndices[c] ];\n                    var slotOverlay = overlayEls[c] || null;\n\n                    \/\/ \u2500\u2500 Step 1 : Fade OUT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    imgActive.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                    imgActive.style.opacity    = 0;\n                    \/\/ L'overlay texte dispara\u00eet en m\u00eame temps que l'image\n                    if ( slotOverlay ) {\n                        slotOverlay.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                        slotOverlay.style.opacity    = 0;\n                    }\n\n                    \/\/ \u2500\u2500 Step 2 : Apr\u00e8s fade OUT \u2192 charger et afficher imgNext \u2500\n                    \/\/ Les param\u00e8tres pass\u00e9s \u00e0 setTimeout \u00e9vitent les probl\u00e8mes\n                    \/\/ de closure (chaque slot a ses propres valeurs captur\u00e9es).\n                    setTimeout(function ( _slot, _imgActive, _imgNext, _nextSlide, _overlay ) {\n\n                        _imgNext.src = _nextSlide.url;\n                        _imgNext.alt = _nextSlide.alt;\n                        void _imgNext.offsetHeight; \/\/ Force reflow \u2192 garantit la transition\n\n                        _imgNext.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                        _imgNext.style.opacity    = 1;\n\n                        \/\/ Mise \u00e0 jour de l'overlay texte avec le contenu du nouveau slide\n                        if ( _overlay ) {\n                            _overlay.innerHTML = buildTextHtml( _nextSlide );\n                            _overlay.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                            _overlay.style.opacity    = 1;\n                        }\n\n                        \/\/ \u2500\u2500 Step 3 : Apr\u00e8s fade IN \u2192 permuter imgActive \u2194 imgNext \u2500\u2500\n                        \/\/ isLast = true pour le dernier slot \u2192 on avance currentIndex ici\n                        setTimeout(function ( isLast ) {\n                            _imgActive.src              = _imgNext.src;\n                            _imgActive.alt              = _imgNext.alt;\n                            _imgActive.style.transition = 'none'; \/\/ Instantan\u00e9\n                            _imgActive.style.opacity    = 1;\n                            _imgNext.style.transition   = 'none';\n                            _imgNext.style.opacity      = 0;\n                            _imgNext.src = ''; \/\/ Lib\u00e8re la m\u00e9moire\n\n                            \/\/ On avance currentIndex une seule fois (au dernier slot)\n                            \/\/ pour \u00e9viter qu'il soit modifi\u00e9 plusieurs fois simultan\u00e9ment\n                            if ( isLast ) {\n                                currentIndex = ( currentIndex + slotCount ) % slides.length;\n                            }\n                        }, fadeInTime, c === slots.length - 1 );\n\n                    }, fadeOutTime, slot, imgActive, imgNext, nextSlide, slotOverlay );\n                }); \/\/ fin slots.forEach\n\n                \/\/ \u2500\u2500 Mise \u00e0 jour des textes \"below\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On les met \u00e0 jour pendant le fadeOut (quand l'ancien slide\n                \/\/ dispara\u00eet), pour un changement invisible.\n                if ( belowEls.length ) {\n                    setTimeout(function () {\n                        nextIndices.forEach(function ( idx, c ) {\n                            if ( belowEls[c] ) {\n                                belowEls[c].innerHTML = buildTextHtml( slides[ idx ] );\n                            }\n                        });\n                    }, fadeOutTime );\n                }\n\n                \/\/ \u2500\u2500 Step 4 : Planifier la prochaine transition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On attend fadeOut + fadeIn (dur\u00e9e totale de la transition)\n                \/\/ puis displayTime avant de lancer le prochain changeImage().\n                setTimeout(function () {\n                    if ( ! sliderPaused ) {\n                        sliderTimer = setTimeout( changeImage, displayTime );\n                    }\n                }, fadeOutTime + fadeInTime );\n\n            } \/\/ fin changeImage()\n\n            \/\/ \u2500\u2500 D\u00e9marrage du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On d\u00e9marre seulement s'il y a plus d'une image ET assez pour\n            \/\/ remplir au moins un \"\u00e9cran\" complet (slotCount).\n            if ( slides.length >= slotCount && slides.length > 1 ) {\n                sliderTimer = setTimeout( changeImage, displayTime );\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ BOUTON TOGGLE \"Afficher les d\u00e9tails\"\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Visible uniquement si text_position=\"below\".\n            \/\/ Au clic : affiche\/masque le bloc vl-slider-below-wrap avec fade.\n            \/\/ Pause le slider quand les textes sont visibles (pour la lisibilit\u00e9).\n\n            var toggleBtn = document.getElementById('vl-slider-inst1-toggle-btn');\n            if ( toggleBtn && belowWrap ) {\n                var textVisible = false;\n                var toggleDelay = 300; \/\/ Dur\u00e9e de la transition CSS opacity en ms\n\n                toggleBtn.addEventListener('click', function () {\n                    textVisible = ! textVisible;\n                    toggleBtn.classList.toggle('active', textVisible);\n                    toggleBtn.setAttribute('aria-pressed', textVisible ? 'true' : 'false');\n                    toggleBtn.querySelector('.vl-sl-btn-label').textContent =\n                        textVisible ? 'Masquer les d\u00e9tails' : 'Afficher les d\u00e9tails';\n                    belowWrap.setAttribute('aria-hidden', textVisible ? 'false' : 'true');\n\n                    if ( textVisible ) {\n                        pauseSlider();\n                        belowWrap.style.display = 'flex'; \/\/ flex pour aligner les blocs c\u00f4te \u00e0 c\u00f4te\n                        belowWrap.style.opacity = '';\n                        requestAnimationFrame(function () {\n                            requestAnimationFrame(function () {\n                                belowWrap.classList.add('vl-sl-texts-visible');\n                            });\n                        });\n                    } else {\n                        \/\/ \u2500\u2500 Fermeture \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                        \/\/ 1. Lance le fade out (retire la classe, CSS prend en charge)\n                        belowWrap.classList.remove('vl-sl-texts-visible');\n                        \/\/ 2. Apr\u00e8s la transition : cacher le bloc + reprendre le slider\n                        setTimeout(function () {\n                            belowWrap.style.display = 'none';\n                            belowWrap.style.opacity = '0';\n                            resumeSlider();\n                        }, toggleDelay );\n                    }\n                });\n            }\n\n        }); \/\/ fin DOMContentLoaded\n    })(); \/\/ fin IIFE\n    <\/script>\n\n    \n\n\n\n<p>Ici le lien de ce petit article \ud83d\ude09 <a href=\"http:\/\/www.visionlarge.ch\/Blog\/foveon\/\">Mon avis sur le Foveon<\/a><\/p>\n\n\n\n    \n        <div class=\"vl-slider-wrap\" id=\"vl-slider-inst2-wrap\">\n\n                        \n                <div id=\"vl-slider-inst2\"\n             class=\"vl-slider-container vl-slider-cols-1\">\n\n                        <div class=\"vl-slider-row\" data-row=\"0\">\n\n                                                <div class=\"vl-slider-slot\" data-slot=\"0\">\n\n                                        <img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/50605159026_dc81cf3f76_o-2000x1375.jpg\"\n                         alt=\"for\u00eat automne\"\n                         class=\"vl-slider-img vl-slider-img-active\">\n\n                                        <img decoding=\"async\" src=\"\" alt=\"\" class=\"vl-slider-img vl-slider-img-next\">\n\n                                        \n                <\/div>\n            <\/div><!-- \/.vl-slider-row -->\n            \n        <\/div><!-- \/.vl-slider-container -->\n\n                \n                \n                        <div class=\"vl-slider-below-wrap\"\n             id=\"vl-slider-inst2-below-wrap\"\n             style=\"display:none;opacity:0;\">\n                        <div class=\"vl-slider-below-text\"\n                 id=\"vl-slider-inst2-below-0\">\n                                <p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">Dans la for\u00eat magique<\/p>\n                                                <p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">Sigma Foveon DP quattro<\/p>\n                                                                <p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">J\u2019aime les ambiances en for\u00eat. C\u2019est d\u2019ailleurs pour cela que je fais en grand partie encore de la photo. La for\u00eat magique de Cossonay ou for\u00eat du Seppey est magnifique en automne mais elle est aussi une tr\u00e8s belle piste vita.<\/p>\n                            <\/div>\n                    <\/div>\n\n                        <div class=\"vl-sl-toggle-wrap\" id=\"vl-slider-inst2-toggle-wrap\">\n            <button class=\"vl-sl-toggle-btn\"\n                    id=\"vl-slider-inst2-toggle-btn\"\n                    aria-pressed=\"false\"\n                    aria-label=\"Afficher les d\u00e9tails\">\n                                <svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\"\n                     viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n                     stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                    <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8z\"><\/path>\n                    <circle cx=\"12\" cy=\"12\" r=\"3\"><\/circle>\n                <\/svg>\n                <span class=\"vl-sl-btn-label\">Afficher les d\u00e9tails<\/span>\n            <\/button>\n        <\/div>\n                \n    <\/div><!-- \/.vl-slider-wrap -->\n\n                <div class=\"vl-sl-lb-wrap\"\n         id=\"vl-slider-inst2-lightbox\"\n         role=\"dialog\" aria-modal=\"true\" aria-label=\"Visionneuse d'images\"\n         style=\"display:none;\">\n\n                <div class=\"vl-sl-lb-overlay\" aria-hidden=\"true\"><\/div>\n\n        <div class=\"vl-sl-lb-content\">\n\n                        <div class=\"vl-sl-lb-toolbar\">\n                <span class=\"vl-sl-lb-counter\"\n                      id=\"vl-slider-inst2-lb-counter\"\n                      aria-live=\"polite\"><\/span>\n                <button class=\"vl-sl-lb-close\"\n                        id=\"vl-slider-inst2-lb-close\"\n                        aria-label=\"Fermer\">&times;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-stage\">\n                <button class=\"vl-sl-lb-prev\"\n                        id=\"vl-slider-inst2-lb-prev\"\n                        aria-label=\"Image pr\u00e9c\u00e9dente\">&#10094;<\/button>\n\n                <div class=\"vl-sl-lb-img-wrap\">\n                                        <div class=\"vl-sl-lb-progress-container\" aria-hidden=\"true\">\n                        <div class=\"vl-sl-lb-progress-bar\"\n                             id=\"vl-slider-inst2-lb-progress\"><\/div>\n                    <\/div>\n                    <img decoding=\"async\" src=\"\" alt=\"\"\n                         id=\"vl-slider-inst2-lb-img\"\n                         class=\"vl-sl-lb-img\">\n                                        <div class=\"vl-sl-lb-caption\"\n                         id=\"vl-slider-inst2-lb-caption\"\n                         aria-live=\"polite\"><\/div>\n                <\/div>\n\n                <button class=\"vl-sl-lb-next\"\n                        id=\"vl-slider-inst2-lb-next\"\n                        aria-label=\"Image suivante\">&#10095;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-footer\">\n                <div class=\"vl-sl-lb-controls\">\n                    <button class=\"vl-sl-lb-playpause\"\n                            id=\"vl-slider-inst2-lb-playpause\"\n                            aria-label=\"Lancer le diaporama\"\n                            aria-pressed=\"false\">\u25b6<\/button>\n                    <button class=\"vl-sl-lb-speed\"\n                            id=\"vl-slider-inst2-lb-speed\"\n                            aria-label=\"Changer la vitesse\">4s<\/button>\n                <\/div>\n            <\/div>\n\n        <\/div><!-- \/.vl-sl-lb-content -->\n    <\/div><!-- \/.vl-sl-lb-wrap -->\n    \n\n        <style id=\"vl-slider-inst2-style\">\n\n        \/* \u2500\u2500 Wrap ext\u00e9rieur \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:relative est n\u00e9cessaire pour que les fant\u00f4mes (position:absolute)\n           se positionnent par rapport au wrap et non \u00e0 la page enti\u00e8re.          *\/\n        #vl-slider-inst2-wrap {\n            width: 100%;\n            max-width: 100%;\n            margin: 20px auto;\n            position: relative;\n            \/* PAS de overflow:hidden ici \u2014 les fant\u00f4mes d\u00e9bordent intentionnellement *\/\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Conteneur principal : colonne flex (rang\u00e9es empil\u00e9es) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex-direction:column \u2192 les .vl-slider-row s'empilent verticalement.\n           gap:8px \u2192 espacement entre rang\u00e9es.                                    *\/\n        #vl-slider-inst2 {\n            display: flex;\n            flex-direction: column;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            overflow: hidden;\n            border-radius: 8px;\n            background: transparent;\n            box-sizing: border-box;\n        }\n\n        \/* \u2500\u2500 Rang\u00e9e : ligne flex (slots c\u00f4te \u00e0 c\u00f4te) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           height est d\u00e9fini ici par rang\u00e9e pour permettre des hauteurs\n           diff\u00e9rentes entre rang\u00e9e 1 et rang\u00e9e 2 (height_row2).                 *\/\n        #vl-slider-inst2 .vl-slider-row {\n            display: flex;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            height: 500px;\n            overflow: hidden;\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Slot individuel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex:1 \u2192 chaque slot prend la m\u00eame largeur dans sa rang\u00e9e.\n           position:relative \u2192 n\u00e9cessaire pour les images en absolute.            *\/\n        #vl-slider-inst2 .vl-slider-slot {\n            position: relative;\n            flex: 1;\n            min-width: 0;\n            overflow: hidden;\n            border-radius: 6px;\n            box-sizing: border-box;\n            \/* La hauteur est fix\u00e9e par la rang\u00e9e parente (.vl-slider-row) *\/\n        }\n\n        \/* \u2500\u2500 Images : remplissent exactement le slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:absolute + inset:0 \u2192 l'image couvre tout le slot.\n           object-fit:contain \u2192 image enti\u00e8re visible sans recadrage.\n           IMPORTANT : fonctionne uniquement si le slot a une hauteur d\u00e9finie,\n           ce qui est garanti par .vl-slider-row { height: Xpx }.               *\/\n        #vl-slider-inst2 .vl-slider-img {\n            position: absolute;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n            background: transparent;\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* \u2500\u2500 Fix critique : la rang\u00e9e DOIT avoir overflow:hidden \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Sans \u00e7a, les images en position:absolute d\u00e9bordent visuellement\n           m\u00eame si leur taille est contrainte.                                  *\/\n        #vl-slider-inst2 .vl-slider-row {\n            overflow: hidden;\n            contain: strict;       \/* Isole compl\u00e8tement le rendu de la rang\u00e9e *\/\n        }\n        \/* Image active : visible (opacity 1) *\/\n        #vl-slider-inst2 .vl-slider-img-active { opacity: 1; }\n        \/* Image suivante : invisible (opacity 0), pr\u00eate pour la prochaine transition *\/\n        #vl-slider-inst2 .vl-slider-img-next   { opacity: 0; }\n\n                \/* \u2500\u2500 Curseur zoom-in si lightbox activ\u00e9e \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           pointer-events:none sur img-next \u2192 seule l'image active re\u00e7oit les clics. *\/\n        #vl-slider-inst2 .vl-slider-slot { cursor: zoom-in; }\n        #vl-slider-inst2 .vl-slider-img-next { pointer-events: none; }\n        #vl-slider-inst2 .vl-slider-overlay-text { pointer-events: none; }\n        \n        \n        \/* \u2500\u2500 Overlay texte (sur l'image) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Bande semi-transparente en bas de chaque slot.\n           La transition opacity correspond au fade_in configur\u00e9.                 *\/\n        #vl-slider-inst2 .vl-slider-overlay-text {\n            position: absolute;\n            bottom: 0; left: 0; right: 0;\n            background: rgba(0, 0, 0, .5);\n            color: #fff;\n            padding: 10px 16px;\n            font-size: 13px;\n            line-height: 1.5;\n            border-radius: 0 0 6px 6px;\n            transition: opacity 1s ease-in-out;\n        }\n        #vl-slider-inst2 .vl-slider-overlay-text p { margin: 2px 0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2014 scop\u00e9 \u00e0 cette instance \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Pour columns=3 rang\u00e9e 2 (1 slot centr\u00e9) : limiter la largeur du bloc.  *\/\n        #vl-slider-inst2-below-wrap .vl-row-centered .vl-slider-below-text {\n            max-width: 50%;\n        }\n\n        \/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*\/\n        @media (max-width: 767px) {\n            #vl-slider-inst2 .vl-slider-row {\n                height: 200px !important;\n            }\n        }\n        @media (max-width: 479px) {\n                    }\n\n    <\/style>\n\n        <style>\n\n        \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n           LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n           \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n        \/* Fond plein \u00e9cran \u2014 cach\u00e9 par d\u00e9faut, affich\u00e9 via display:flex en JS *\/\n        .vl-sl-lb-wrap {\n            position: fixed;\n            inset: 0;\n            z-index: 99999;\n            display: none; \/* display:flex quand ouverte *\/\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            padding: 1rem;\n            box-sizing: border-box;\n        }\n\n        \/* Fond semi-transparent \u2014 clic = fermeture *\/\n        .vl-sl-lb-overlay {\n            position: fixed;\n            inset: 0;\n            background: rgba(0, 0, 0, .88);\n            cursor: pointer;\n            z-index: 0;\n        }\n\n        \/* Contenu centr\u00e9 au-dessus du fond *\/\n        .vl-sl-lb-content {\n            position: relative;\n            z-index: 1;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 92vw;\n            max-height: 92vh;\n            gap: 8px;\n        }\n\n        \/* Toolbar : compteur + bouton \u00d7 *\/\n        .vl-sl-lb-toolbar {\n            display: flex;\n            width: 100%;\n            align-items: center;\n            justify-content: space-between;\n        }\n        .vl-sl-lb-counter {\n            color: #fff;\n            background: rgba(0, 0, 0, .55);\n            padding: 4px 10px;\n            border-radius: 20px;\n            font-size: 13px;\n        }\n        .vl-sl-lb-close {\n            background: rgba(0, 0, 0, .55);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 34px; height: 34px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            transition: background .2s, transform .2s;\n            line-height: 1;\n        }\n        .vl-sl-lb-close:hover { background: rgba(0, 0, 0, .9); transform: scale(1.15); }\n\n        \/* Stage : fl\u00e8ches + image *\/\n        .vl-sl-lb-stage {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n        }\n        .vl-sl-lb-prev, .vl-sl-lb-next {\n            flex-shrink: 0;\n            background: rgba(0, 0, 0, .5);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 42px; height: 42px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            user-select: none;\n            transition: background .2s, transform .2s;\n        }\n        .vl-sl-lb-prev:hover, .vl-sl-lb-next:hover {\n            background: rgba(0, 0, 0, .9);\n            transform: scale(1.15);\n        }\n\n        \/* Conteneur image : flex-column pour empiler image + caption *\/\n        .vl-sl-lb-img-wrap {\n            position: relative;\n            display: inline-flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 78vw;\n        }\n\n        \/* Image lightbox *\/\n        .vl-sl-lb-img {\n            display: block;\n            max-width: 78vw;\n            max-height: 72vh;\n            border-radius: 8px;\n            box-shadow: 0 4px 32px rgba(0, 0, 0, .5);\n            opacity: 0; \/* commence invisible, JS anime vers 1 *\/\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* Barre de progression du diaporama \u2014 en haut de l'image *\/\n        .vl-sl-lb-progress-container {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 3px;\n            background: rgba(255, 255, 255, .2);\n            border-radius: 2px;\n            overflow: hidden;\n            display: none; \/* visible seulement en mode play *\/\n        }\n        .vl-sl-lb-progress-bar {\n            height: 100%;\n            width: 0%;\n            background: #fff;\n            transition: width linear;\n        }\n\n        \/* Caption sous l'image *\/\n        .vl-sl-lb-caption {\n            color: #fff;\n            font-size: 13px;\n            text-align: center;\n            word-break: break-word;\n            margin-top: 8px;\n            padding: 6px 18px;\n            box-sizing: border-box;\n            max-width: 78vw;\n            line-height: 1.5;\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            border-radius: 14px;\n            display: none; \/* affich\u00e9 par le JS si caption non vide *\/\n        }\n        .vl-sl-lb-caption.has-text { display: inline-block; }\n\n        \/* Footer : boutons play\/pause + vitesse *\/\n        .vl-sl-lb-footer {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            gap: 6px;\n            width: 100%;\n        }\n        .vl-sl-lb-controls { display: flex; gap: 8px; }\n        .vl-sl-lb-playpause, .vl-sl-lb-speed {\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            color: #fff;\n            border-radius: 20px;\n            padding: 4px 14px;\n            font-size: 13px;\n            cursor: pointer;\n            transition: background .2s;\n            min-width: 48px;\n            text-align: center;\n        }\n        .vl-sl-lb-playpause:hover, .vl-sl-lb-speed:hover {\n            background: rgba(255, 255, 255, .28);\n        }\n\n        \/* Mobile : masquer les contr\u00f4les pour ne pas g\u00eaner le swipe *\/\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-prev,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-next,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-caption,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-progress-container,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-close,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-counter { display: none !important; }\n\n        \/* \u2500\u2500 Bouton toggle \"Afficher les d\u00e9tails\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Petit bouton discret align\u00e9 \u00e0 droite, au-dessus des textes below.\n           La classe .active indique l'\u00e9tat \"ouvert\".                             *\/\n        .vl-sl-toggle-wrap { text-align: right; margin-bottom: 10px; }\n        .vl-sl-toggle-btn {\n            background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;\n            padding: 7px 12px; cursor: pointer; font-size: 12px;\n            display: inline-flex; align-items: center; gap: 6px;\n            box-shadow: 0 2px 6px rgba(0, 0, 0, .12);\n            transition: background .2s, box-shadow .2s;\n            line-height: 1;\n        }\n        .vl-sl-toggle-btn:hover  { background: #ececec; box-shadow: 0 3px 8px rgba(0, 0, 0, .18); }\n        .vl-sl-toggle-btn.active { background: #e0e0e0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Le wrap est flex horizontal : un bloc par colonne, c\u00f4te \u00e0 c\u00f4te.\n           Chaque bloc est un bloc normal : les <p> s'empilent naturellement.     *\/\n        .vl-slider-below-wrap {\n            display: flex;\n            flex-direction: row;\n            gap: 8px;\n            width: 100%;\n            box-sizing: border-box;\n            opacity: 0;\n            transition: opacity .3s ease;\n        }\n        .vl-slider-below-wrap.vl-sl-texts-visible { opacity: 1; }\n\n        \/* Bloc texte individuel \u2014 un par image visible *\/\n        .vl-slider-below-text {\n            flex: 1;\n            min-width: 0;\n            padding: 8px 4px;\n            font-size: 13px;\n            line-height: 1.5;\n            text-align: center;\n            box-sizing: border-box;\n        }\n        .vl-slider-below-text p { margin: 2px 0; }\n\n        \/* Styles texte *\/\n        .vl-sl-title       { font-weight: bold; }\n        .vl-sl-caption     { font-style: italic; }\n        .vl-sl-alt         { font-size: 11px; }\n        .vl-sl-description { font-size: 12px; }\n\n        \/* Couleurs overlay (fond sombre \u2192 texte blanc) *\/\n        .vl-slider-overlay-text .vl-sl-title       { color: #fff; }\n        .vl-slider-overlay-text .vl-sl-caption     { color: rgba(255, 255, 255, .8); }\n        .vl-slider-overlay-text .vl-sl-alt         { color: rgba(255, 255, 255, .6); }\n        .vl-slider-overlay-text .vl-sl-description { color: rgba(255, 255, 255, .9); }\n\n        \/* Couleurs below (fond clair \u2192 texte sombre) *\/\n        .vl-slider-below-text .vl-sl-title       { color: #222; }\n        .vl-slider-below-text .vl-sl-caption     { color: #666; }\n        .vl-slider-below-text .vl-sl-alt         { color: #999; font-size: 11px; }\n        .vl-slider-below-text .vl-sl-description { color: #444; font-size: 12px; }\n\n    <\/style>\n\n        <script>\n    (function () {\n        'use strict';\n\n        document.addEventListener('DOMContentLoaded', function () {\n\n            \/\/ \u2500\u2500 R\u00e9f\u00e9rences DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On r\u00e9cup\u00e8re le conteneur principal. Si absent (shortcode mal copi\u00e9),\n            \/\/ on quitte imm\u00e9diatement pour \u00e9viter les erreurs JS.\n            var slider = document.getElementById('vl-slider-inst2');\n            if ( ! slider ) return;\n\n            \/\/ Tous les slots de la grille (inclut toutes les rang\u00e9es)\n            var slots = slider.querySelectorAll('.vl-slider-slot');\n\n            \/\/ Fant\u00f4mes gauche et droit (null si ghost_peek=false \u2192 divs absentes)\n            var ghostLeft  = document.getElementById('vl-slider-inst2-ghost-left');\n            var ghostRight = document.getElementById('vl-slider-inst2-ghost-right');\n            var ghostImgL  = ghostLeft  ? ghostLeft.querySelector('.vl-ghost-img')  : null;\n            var ghostImgR  = ghostRight ? ghostRight.querySelector('.vl-ghost-img') : null;\n\n            \/\/ Overlays texte \u2014 un par slot, cherch\u00e9s dans le conteneur slider\n            var overlayEls = Array.prototype.slice.call(\n                slider.querySelectorAll('.vl-slider-overlay-text')\n            );\n            \/\/ Blocs texte \"below\" \u2014 cibl\u00e9s par classe pour \u00e9viter de capturer le wrap\n            var belowWrap  = document.getElementById('vl-slider-inst2-below-wrap');\n            var belowEls   = belowWrap\n                ? Array.prototype.slice.call( belowWrap.querySelectorAll('.vl-slider-below-text') )\n                : [];\n\n            \/\/ \u2500\u2500 Donn\u00e9es inject\u00e9es par PHP \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ wp_json_encode() c\u00f4t\u00e9 PHP \u2192 JSON valide et safe\n            var slides      = [{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50605159026_dc81cf3f76_o-2000x1375.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50605159026_dc81cf3f76_o.jpg\",\"alt\":\"for\\u00eat automne\",\"title\":\"Dans la for\\u00eat magique\",\"caption\":\"Sigma Foveon DP quattro\",\"description\":\"J\\u2019aime les ambiances en for\\u00eat. C\\u2019est d\\u2019ailleurs pour cela que je fais en grand partie encore de la photo. La for\\u00eat magique de Cossonay ou for\\u00eat du Seppey est magnifique en automne mais elle est aussi une tr\\u00e8s belle piste vita.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/couleurs_34771145561_o-2000x1371.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/couleurs_34771145561_o.jpg\",\"alt\":\"Personne en contre jour dans un passage au fov\\u00e9on Sigma\",\"title\":\"Passage\",\"caption\":\"Sigma Foveon\",\"description\":\"Ma premi\\u00e8re image au Foveon. Dans les petites ruelles d\\u2019Yverdon en Suisse. J\\u2019adore cette image m\\u00eame si elle est surex.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/promeneur-de-brumes_46052360572_o-2000x1378.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/promeneur-de-brumes_46052360572_o.jpg\",\"alt\":\"For\\u00eat magique du Seppey en suisse romande pr\\u00e8s de Cossonay au Sigma Fov\\u00e9on\",\"title\":\"Promeneur de brumes\",\"caption\":\"Sigma DP Foveon\",\"description\":\"Promenade dans la belle for\\u00eat du Seppey. Que l\\u2019on appelle pour certains, la for\\u00eat magique. Je suis avec mon DP Sigma. Je remarque ce passage en deux immenses arbres majestueux. Il me suffit juste d\\u2019attendre le promeneur\\u2026\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DP0Q0788-2000x1378.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DP0Q0788.jpg\",\"alt\":\"La for\\u00eat de m\\u00e9l\\u00e8zes\",\"title\":\"La for\\u00eat de m\\u00e9l\\u00e8zes\",\"caption\":\"Sigma DP\",\"description\":\"La for\\u00eat de m\\u00e9l\\u00e8zes du barrage et du lasc d&#039;Emosson dans le Valais.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DP0Q0796-2000x1378.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DP0Q0796.jpg\",\"alt\":\"Vue sur le lac et les montagnes depuis le barrage d&#039;Emosson au Foveon Dp0Q\",\"title\":\"DP0Q0796\",\"caption\":\"Sigma DP\",\"description\":\"Autour du lac cr\\u00e9\\u00e9 par le barrage d&#039;Emosson dans le Valais. Les m\\u00e9l\\u00e8zes ont rev\\u00eatu leur parure d&#039;automne\"}];\n            var columns     = 1;\n            var slotCount   = 1; \/\/ Nb total de slots visibles\n            var lightbox    = true;\n            var showTitle       = true;\n            var showCaption     = true;\n            var showAlt         = false;\n            var showDescription = true;\n\n            \/\/ \u2500\u2500 Variables d'\u00e9tat du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ currentIndex : index dans $slides de la premi\u00e8re image affich\u00e9e\n            var currentIndex  = 0;\n            \/\/ Dur\u00e9es en millisecondes (PHP les envoie en secondes)\n            var displayTime   = 3 * 1000;\n            var fadeInTime    = 1 * 1000;\n            var fadeOutTime   = 1 * 1000;\n            var sliderPaused  = false;  \/\/ Vrai quand la lightbox ou le toggle sont ouverts\n            var sliderTimer   = null;   \/\/ R\u00e9f\u00e9rence au setTimeout en cours\n\n            \/\/ \u2500\u2500 pauseSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Arr\u00eate les transitions (lightbox ouverte, textes below affich\u00e9s).\n            \/\/ clearTimeout annule le prochain changeImage() planifi\u00e9.\n            function pauseSlider() {\n                sliderPaused = true;\n                if ( sliderTimer ) {\n                    clearTimeout( sliderTimer );\n                    sliderTimer = null;\n                }\n            }\n\n            \/\/ \u2500\u2500 resumeSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Reprend les transitions apr\u00e8s fermeture lightbox ou toggle.\n            \/\/ Ne red\u00e9marre que s'il y a assez d'images pour animer.\n            function resumeSlider() {\n                sliderPaused = false;\n                if ( slides.length >= slotCount && slides.length > 1 ) {\n                    sliderTimer = setTimeout( changeImage, displayTime );\n                }\n            }\n\n            \/\/ \u2500\u2500 Protection des images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ D\u00e9sactive le clic droit (contextmenu) et le glisser-d\u00e9poser (dragstart)\n            \/\/ sur toutes les images du slider pour d\u00e9courager la copie.\n            slider.querySelectorAll('.vl-slider-img').forEach(function ( img ) {\n                img.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n                img.addEventListener('dragstart',   function (e) { e.preventDefault(); });\n            });\n            slider.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n            \/\/ Navigation : fl\u00e8ches, clavier, swipe tactile\n            \/\/ Diaporama  : play\/pause, vitesse, barre de progression\n            \/\/ Transitions: fade | slide | none (param\u00e8tre lb_transition)\n            \/\/ Mobile     : masquage automatique des contr\u00f4les, swipe uniquement\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            if ( lightbox ) {\n\n                var lbWrap     = document.getElementById('vl-slider-inst2-lightbox');\n                var lbImg      = document.getElementById('vl-slider-inst2-lb-img');\n                var lbClose    = document.getElementById('vl-slider-inst2-lb-close');\n                var lbOverlay  = lbWrap ? lbWrap.querySelector('.vl-sl-lb-overlay') : null;\n                var lbPrev     = document.getElementById('vl-slider-inst2-lb-prev');\n                var lbNext     = document.getElementById('vl-slider-inst2-lb-next');\n                var lbCounter  = document.getElementById('vl-slider-inst2-lb-counter');\n                var lbCaption  = document.getElementById('vl-slider-inst2-lb-caption');\n                var lbPlay     = document.getElementById('vl-slider-inst2-lb-playpause');\n                var lbSpeedBtn = document.getElementById('vl-slider-inst2-lb-speed');\n                var lbProgress = document.getElementById('vl-slider-inst2-lb-progress');\n                var lbProgWrap = lbProgress ? lbProgress.parentElement : null;\n                var lbTransition  = 'fade';\n                var lbTransSpeed  = 400;\n                var lbSlideTimer  = null;\n                var lbSlideSpeed  = 4000;\n                var lbIsPlaying   = false;\n                var lbCurrentIdx  = 0;\n                var lbImages      = [];\n                var lbNavigating  = false;\n\n                if ( ! lbWrap ) return;\n\n                function lbIsMobile() {\n                    return \/Android|iPhone|iPod\/i.test(navigator.userAgent) &&\n                           ( 'ontouchstart' in window || navigator.maxTouchPoints > 0 );\n                }\n                function lbIsTabletPortrait() {\n                    return ( \/iPad|Android\/i.test(navigator.userAgent) || navigator.maxTouchPoints > 0 ) &&\n                           window.innerWidth <= 1024 && window.innerHeight > window.innerWidth;\n                }\n                function updateMobileNav() {\n                    lbWrap.classList.toggle('vl-lb-hide-nav', lbIsMobile() || lbIsTabletPortrait());\n                }\n\n                function openLightbox( clickedIndex ) {\n                    lbImages = slides.map(function ( s ) {\n                        return { url: s.full_url || s.url, alt: s.alt || '', title: s.title || '', description: s.description || '' };\n                    });\n                    lbCurrentIdx = ( ( clickedIndex % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var single = lbImages.length <= 1;\n                    if ( lbPrev ) lbPrev.style.display = single ? 'none' : '';\n                    if ( lbNext ) lbNext.style.display = single ? 'none' : '';\n                    updateMobileNav();\n                    lbWrap.style.display = 'flex';\n                    document.body.style.overflow = 'hidden';\n                    showLbImage( lbCurrentIdx );\n                    if ( lbClose ) lbClose.focus();\n                }\n\n                function showLbImage( index ) {\n                    if ( ! lbImages.length ) return;\n                    var prevIdx  = lbCurrentIdx;\n                    lbCurrentIdx = ( ( index % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var item     = lbImages[ lbCurrentIdx ];\n                    var dir      = index >= prevIdx ? 1 : -1;\n\n                    if ( lbCounter ) lbCounter.textContent = ( lbCurrentIdx + 1 ) + ' \/ ' + lbImages.length;\n                    var capText = item.description || item.alt || item.title || '';\n                    if ( lbCaption ) {\n                        lbCaption.textContent = capText;\n                        lbCaption.classList.toggle('has-text', capText.length > 0);\n                    }\n                    resetLbProgressBar();\n\n                    if ( lbTransition === 'none' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealNone() { lbImg.style.opacity = '1'; }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealNone() : ( lbImg.onload = lbImg.onerror = revealNone );\n                        return;\n                    }\n\n                    if ( lbTransition === 'fade' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.onload = null; lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealFade() {\n                            void lbImg.offsetWidth;\n                            lbImg.style.transition = 'opacity ' + ( lbTransSpeed \/ 1000 ) + 's ease';\n                            requestAnimationFrame(function () { lbImg.style.opacity = '1'; });\n                        }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealFade() : ( lbImg.onload = lbImg.onerror = revealFade );\n                        return;\n                    }\n\n                    if ( lbTransition === 'slide' ) {\n                        var imgWrap = lbImg.parentElement;\n                        var easing  = 'cubic-bezier(.25,.46,.45,.94)';\n                        var dur     = ( lbTransSpeed \/ 1000 ) + 's';\n                        var newImg  = new Image();\n                        newImg.alt = item.alt; newImg.draggable = false;\n                        newImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;box-shadow:0 4px 32px rgba(0,0,0,.5);opacity:1;transform:translateX(' + ( dir * 100 ) + '%);transition:none;user-select:none';\n                        function doSlide() {\n                            imgWrap.style.cssText = 'position:relative;overflow:hidden;display:inline-flex;width:' + lbImg.offsetWidth + 'px;height:' + lbImg.offsetHeight + 'px';\n                            lbImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;opacity:1;transform:translateX(0);transition:none;user-select:none';\n                            imgWrap.appendChild( newImg );\n                            requestAnimationFrame(function () {\n                                requestAnimationFrame(function () {\n                                    lbImg.style.transition = newImg.style.transition = 'transform ' + dur + ' ' + easing;\n                                    lbImg.style.transform  = 'translateX(' + ( -dir * 100 ) + '%)';\n                                    newImg.style.transform = 'translateX(0)';\n                                    setTimeout(function () {\n                                        lbImg.src = newImg.src; lbImg.alt = newImg.alt;\n                                        lbImg.style.cssText = ''; lbImg.style.opacity = '1';\n                                        if ( imgWrap.contains(newImg) ) imgWrap.removeChild( newImg );\n                                        imgWrap.style.cssText = '';\n                                        lbNavigating = false;\n                                    }, lbTransSpeed + 30);\n                                });\n                            });\n                        }\n                        newImg.onload = newImg.onerror = doSlide;\n                        newImg.src = item.url;\n                        if ( newImg.complete && newImg.naturalWidth > 0 ) { newImg.onload = null; doSlide(); }\n                        return;\n                    }\n                }\n\n                function lbNavigateTo( direction ) {\n                    if ( lbNavigating ) return;\n                    lbNavigating = true;\n                    showLbImage( lbCurrentIdx + direction );\n                    if ( lbTransition !== 'slide' ) setTimeout(function () { lbNavigating = false; }, lbTransSpeed + 50);\n                }\n\n                function closeLightbox() {\n                    lbWrap.style.display = 'none';\n                    lbImg.src = '';\n                    document.body.style.overflow = '';\n                    stopLbSlideshow();\n                    pauseSlider();\n                    setTimeout(function () { resumeSlider(); }, 300);\n                }\n\n                function startLbSlideshow() {\n                    stopLbSlideshow();\n                    lbSlideTimer = setInterval(function () { lbNavigateTo( 1 ); }, lbSlideSpeed);\n                    lbIsPlaying = true;\n                    if ( lbPlay ) { lbPlay.textContent = '\u23f8'; lbPlay.setAttribute('aria-pressed', 'true'); lbPlay.setAttribute('aria-label', 'Arr\u00eater le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'block';\n                    resetLbProgressBar();\n                }\n\n                function stopLbSlideshow() {\n                    if ( lbSlideTimer ) { clearInterval( lbSlideTimer ); lbSlideTimer = null; }\n                    lbIsPlaying = false;\n                    if ( lbPlay ) { lbPlay.textContent = '\u25b6'; lbPlay.setAttribute('aria-pressed', 'false'); lbPlay.setAttribute('aria-label', 'Lancer le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'none';\n                    if ( lbProgress ) { lbProgress.style.transition = 'none'; lbProgress.style.width = '0%'; }\n                }\n\n                function resetLbProgressBar() {\n                    if ( ! lbIsPlaying || ! lbProgress ) return;\n                    lbProgress.style.transition = 'none'; lbProgress.style.width = '0%';\n                    requestAnimationFrame(function () {\n                        requestAnimationFrame(function () {\n                            lbProgress.style.transition = 'width ' + ( lbSlideSpeed \/ 1000 ) + 's linear';\n                            lbProgress.style.width = '100%';\n                        });\n                    });\n                }\n\n                slots.forEach(function ( slot, slotIndex ) {\n                    slot.addEventListener('click', function () {\n                        var clickedIndex = ( currentIndex + slotIndex ) % slides.length;\n                        pauseSlider();\n                        openLightbox( clickedIndex );\n                    });\n                });\n\n                if ( lbClose )   lbClose.addEventListener('click', closeLightbox);\n                if ( lbOverlay ) lbOverlay.addEventListener('click', closeLightbox);\n                if ( lbPrev )    lbPrev.addEventListener('click', function () { lbNavigateTo( -1 ); });\n                if ( lbNext )    lbNext.addEventListener('click', function () { lbNavigateTo(  1 ); });\n\n                document.addEventListener('keydown', function ( e ) {\n                    if ( lbWrap.style.display !== 'flex' ) return;\n                    if ( e.key === 'Escape'     ) closeLightbox();\n                    if ( e.key === 'ArrowLeft'  ) lbNavigateTo( -1 );\n                    if ( e.key === 'ArrowRight' ) lbNavigateTo(  1 );\n                });\n\n                if ( lbPlay ) {\n                    lbPlay.addEventListener('click', function () {\n                        lbIsPlaying ? stopLbSlideshow() : startLbSlideshow();\n                    });\n                }\n\n                var lbSpeeds  = [ 2000, 4000, 6000 ];\n                var lbSpeedLb = [ '2s', '4s', '6s' ];\n                if ( lbSpeedBtn ) {\n                    lbSpeedBtn.addEventListener('click', function () {\n                        var idx = ( lbSpeeds.indexOf( lbSlideSpeed ) + 1 ) % lbSpeeds.length;\n                        lbSlideSpeed = lbSpeeds[ idx ];\n                        lbSpeedBtn.textContent = lbSpeedLb[ idx ];\n                        if ( lbIsPlaying ) startLbSlideshow();\n                    });\n                }\n\n                var lbSwipeStartX = 0, lbSwipeHandled = false;\n                if ( lbImg ) {\n                    lbImg.addEventListener('touchstart', function ( e ) {\n                        lbSwipeStartX = e.changedTouches[0].screenX; lbSwipeHandled = false;\n                    }, { passive: true });\n                    lbImg.addEventListener('touchend', function ( e ) {\n                        if ( lbSwipeHandled ) return;\n                        var diff = lbSwipeStartX - e.changedTouches[0].screenX;\n                        if ( Math.abs(diff) > 40 ) { lbSwipeHandled = true; lbNavigateTo( diff > 0 ? 1 : -1 ); }\n                    }, { passive: true });\n                }\n\n                window.addEventListener('resize',            updateMobileNav);\n                window.addEventListener('orientationchange', updateMobileNav);\n\n            } \/\/ fin if(lightbox)\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TEXTES \u2014 buildTextHtml() et updateTextSlot()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            \/\/ \u2500\u2500 buildTextHtml(slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Construit le HTML des textes pour un slide donn\u00e9.\n            \/\/ Les styles CSS sont inject\u00e9s par PHP (esc_js) au rendu de la page\n            \/\/ \u2192 ils sont des constantes, pas des donn\u00e9es utilisateur.\n            \/\/ Les valeurs slide.title etc. sont d\u00e9j\u00e0 esc_html() c\u00f4t\u00e9 PHP\n            \/\/ \u2192 safe pour innerHTML.\n            function buildTextHtml( slide ) {\n                var html = '';\n                if ( showTitle && slide.title ) {\n                    html += '<p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">'\n                          + slide.title + '<\/p>';\n                }\n                if ( showCaption && slide.caption ) {\n                    html += '<p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">'\n                          + slide.caption + '<\/p>';\n                }\n                if ( showAlt && slide.alt ) {\n                    html += '<p class=\"vl-sl-alt\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.alt + '<\/p>';\n                }\n                if ( showDescription && slide.description ) {\n                    html += '<p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.description + '<\/p>';\n                }\n                return html;\n            }\n\n            \/\/ \u2500\u2500 updateTextSlot(slotIndex, slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour overlay ET below d'un slot donn\u00e9 avec les textes du slide.\n            \/\/ Utilis\u00e9 \u00e0 l'initialisation et lors des transitions.\n            function updateTextSlot( slotIndex, slide ) {\n                if ( overlayEls[ slotIndex ] ) {\n                    overlayEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n                if ( belowEls[ slotIndex ] ) {\n                    belowEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ FANT\u00d4MES \u2014 updateGhosts()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            var ghostPeek = false;\n\n            \/\/ \u2500\u2500 updateGhosts() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour les images des fant\u00f4mes selon la position courante.\n            \/\/ Appel\u00e9e apr\u00e8s chaque transition et lors d'un changement via lightbox.\n            \/\/\n            \/\/ Fant\u00f4me gauche = image juste avant currentIndex (boucle circulaire)\n            \/\/ Fant\u00f4me droit  = image juste apr\u00e8s le dernier slot visible\n            \/\/ Si une seule image : les deux fant\u00f4mes montrent la m\u00eame image.\n            function updateGhosts() {\n                if ( ! ghostPeek ) return;\n                var n = slides.length;\n                var prevIdx = n > 1 ? ( currentIndex - 1 + n ) % n : currentIndex;\n                var nextIdx = n > slotCount ? ( currentIndex + slotCount ) % n : currentIndex;\n\n                \/\/ Fade out \u2192 changer src \u2192 fade in \u2014 synchronis\u00e9 avec fadeOutTime du slider\n                var dur = fadeOutTime \/ 1000;\n\n                if ( ghostImgL ) {\n                    ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgL.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgL.src = slides[ prevIdx ].url;\n                        ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgL.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n                if ( ghostImgR ) {\n                    ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgR.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgR.src = slides[ nextIdx ].url;\n                        ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgR.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n            }\n\n            \/\/ Initialisation des fant\u00f4mes au chargement\n            updateGhosts();\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TRANSITION PRINCIPALE \u2014 changeImage()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Cette fonction orchestre la transition de TOUS les slots en m\u00eame temps.\n            \/\/ Elle utilise des setTimeout cha\u00een\u00e9s (pas setInterval) pour \u00e9viter\n            \/\/ les d\u00e9rives de timing.\n            \/\/\n            \/\/ S\u00e9quence pour chaque slot :\n            \/\/   1. Fade OUT de imgActive  (dur\u00e9e: fadeOutTime)\n            \/\/   2. Apr\u00e8s fadeOut : charger imgNext + Fade IN  (dur\u00e9e: fadeInTime)\n            \/\/   3. Apr\u00e8s fadeIn : permuter imgActive \u2194 imgNext (op\u00e9ration instantan\u00e9e)\n            \/\/   4. Attendre displayTime \u2192 lancer le prochain changeImage()\n            \/\/\n            \/\/ currentIndex est avanc\u00e9 au step 3 du DERNIER slot (c === slots.length-1)\n            \/\/ pour \u00e9viter les race conditions avec la lightbox.\n\n            function changeImage() {\n                if ( slides.length < 2 ) return;\n                if ( sliderPaused ) return;\n\n                var nextIndices = [];\n                for ( var c = 0; c < slotCount; c++ ) {\n                    nextIndices.push( ( currentIndex + slotCount + c ) % slides.length );\n                }\n\n                \/\/ Lancer la transition des fant\u00f4mes en m\u00eame temps que les images\n                updateGhosts();\n\n                \/\/ \u2500\u2500 Transition par slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On it\u00e8re sur chaque slot. Les closures setTimeout capturent\n                \/\/ les variables locales (slot, imgActive, imgNext\u2026) par valeur\n                \/\/ gr\u00e2ce aux param\u00e8tres de fonction.\n                slots.forEach(function ( slot, c ) {\n                    var imgActive   = slot.querySelector('.vl-slider-img-active');\n                    var imgNext     = slot.querySelector('.vl-slider-img-next');\n                    var nextSlide   = slides[ nextIndices[c] ];\n                    var slotOverlay = overlayEls[c] || null;\n\n                    \/\/ \u2500\u2500 Step 1 : Fade OUT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    imgActive.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                    imgActive.style.opacity    = 0;\n                    \/\/ L'overlay texte dispara\u00eet en m\u00eame temps que l'image\n                    if ( slotOverlay ) {\n                        slotOverlay.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                        slotOverlay.style.opacity    = 0;\n                    }\n\n                    \/\/ \u2500\u2500 Step 2 : Apr\u00e8s fade OUT \u2192 charger et afficher imgNext \u2500\n                    \/\/ Les param\u00e8tres pass\u00e9s \u00e0 setTimeout \u00e9vitent les probl\u00e8mes\n                    \/\/ de closure (chaque slot a ses propres valeurs captur\u00e9es).\n                    setTimeout(function ( _slot, _imgActive, _imgNext, _nextSlide, _overlay ) {\n\n                        _imgNext.src = _nextSlide.url;\n                        _imgNext.alt = _nextSlide.alt;\n                        void _imgNext.offsetHeight; \/\/ Force reflow \u2192 garantit la transition\n\n                        _imgNext.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                        _imgNext.style.opacity    = 1;\n\n                        \/\/ Mise \u00e0 jour de l'overlay texte avec le contenu du nouveau slide\n                        if ( _overlay ) {\n                            _overlay.innerHTML = buildTextHtml( _nextSlide );\n                            _overlay.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                            _overlay.style.opacity    = 1;\n                        }\n\n                        \/\/ \u2500\u2500 Step 3 : Apr\u00e8s fade IN \u2192 permuter imgActive \u2194 imgNext \u2500\u2500\n                        \/\/ isLast = true pour le dernier slot \u2192 on avance currentIndex ici\n                        setTimeout(function ( isLast ) {\n                            _imgActive.src              = _imgNext.src;\n                            _imgActive.alt              = _imgNext.alt;\n                            _imgActive.style.transition = 'none'; \/\/ Instantan\u00e9\n                            _imgActive.style.opacity    = 1;\n                            _imgNext.style.transition   = 'none';\n                            _imgNext.style.opacity      = 0;\n                            _imgNext.src = ''; \/\/ Lib\u00e8re la m\u00e9moire\n\n                            \/\/ On avance currentIndex une seule fois (au dernier slot)\n                            \/\/ pour \u00e9viter qu'il soit modifi\u00e9 plusieurs fois simultan\u00e9ment\n                            if ( isLast ) {\n                                currentIndex = ( currentIndex + slotCount ) % slides.length;\n                            }\n                        }, fadeInTime, c === slots.length - 1 );\n\n                    }, fadeOutTime, slot, imgActive, imgNext, nextSlide, slotOverlay );\n                }); \/\/ fin slots.forEach\n\n                \/\/ \u2500\u2500 Mise \u00e0 jour des textes \"below\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On les met \u00e0 jour pendant le fadeOut (quand l'ancien slide\n                \/\/ dispara\u00eet), pour un changement invisible.\n                if ( belowEls.length ) {\n                    setTimeout(function () {\n                        nextIndices.forEach(function ( idx, c ) {\n                            if ( belowEls[c] ) {\n                                belowEls[c].innerHTML = buildTextHtml( slides[ idx ] );\n                            }\n                        });\n                    }, fadeOutTime );\n                }\n\n                \/\/ \u2500\u2500 Step 4 : Planifier la prochaine transition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On attend fadeOut + fadeIn (dur\u00e9e totale de la transition)\n                \/\/ puis displayTime avant de lancer le prochain changeImage().\n                setTimeout(function () {\n                    if ( ! sliderPaused ) {\n                        sliderTimer = setTimeout( changeImage, displayTime );\n                    }\n                }, fadeOutTime + fadeInTime );\n\n            } \/\/ fin changeImage()\n\n            \/\/ \u2500\u2500 D\u00e9marrage du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On d\u00e9marre seulement s'il y a plus d'une image ET assez pour\n            \/\/ remplir au moins un \"\u00e9cran\" complet (slotCount).\n            if ( slides.length >= slotCount && slides.length > 1 ) {\n                sliderTimer = setTimeout( changeImage, displayTime );\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ BOUTON TOGGLE \"Afficher les d\u00e9tails\"\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Visible uniquement si text_position=\"below\".\n            \/\/ Au clic : affiche\/masque le bloc vl-slider-below-wrap avec fade.\n            \/\/ Pause le slider quand les textes sont visibles (pour la lisibilit\u00e9).\n\n            var toggleBtn = document.getElementById('vl-slider-inst2-toggle-btn');\n            if ( toggleBtn && belowWrap ) {\n                var textVisible = false;\n                var toggleDelay = 300; \/\/ Dur\u00e9e de la transition CSS opacity en ms\n\n                toggleBtn.addEventListener('click', function () {\n                    textVisible = ! textVisible;\n                    toggleBtn.classList.toggle('active', textVisible);\n                    toggleBtn.setAttribute('aria-pressed', textVisible ? 'true' : 'false');\n                    toggleBtn.querySelector('.vl-sl-btn-label').textContent =\n                        textVisible ? 'Masquer les d\u00e9tails' : 'Afficher les d\u00e9tails';\n                    belowWrap.setAttribute('aria-hidden', textVisible ? 'false' : 'true');\n\n                    if ( textVisible ) {\n                        pauseSlider();\n                        belowWrap.style.display = 'flex'; \/\/ flex pour aligner les blocs c\u00f4te \u00e0 c\u00f4te\n                        belowWrap.style.opacity = '';\n                        requestAnimationFrame(function () {\n                            requestAnimationFrame(function () {\n                                belowWrap.classList.add('vl-sl-texts-visible');\n                            });\n                        });\n                    } else {\n                        \/\/ \u2500\u2500 Fermeture \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                        \/\/ 1. Lance le fade out (retire la classe, CSS prend en charge)\n                        belowWrap.classList.remove('vl-sl-texts-visible');\n                        \/\/ 2. Apr\u00e8s la transition : cacher le bloc + reprendre le slider\n                        setTimeout(function () {\n                            belowWrap.style.display = 'none';\n                            belowWrap.style.opacity = '0';\n                            resumeSlider();\n                        }, toggleDelay );\n                    }\n                });\n            }\n\n        }); \/\/ fin DOMContentLoaded\n    })(); \/\/ fin IIFE\n    <\/script>\n\n    \n\n\n\n<p>Mais comme j&rsquo;adore le panorama par assemblage, je ferais aussi un r\u00e9capitulatif de tous les r\u00e9glages pour la pupille d&rsquo;entr\u00e9e, afin de les utiliser dans de volumineux panoramas par assemblage que se soit plats, sph\u00e9riques ou en m\u00e9thode Brenizer!<\/p>\n\n\n\n<p>D&rsquo;aillleurs voici les premi\u00e8res cotes pour placer vos DP&rsquo;s quattro correctement afin d&rsquo;\u00e9viter les erreurs de parallaxe:<\/p>\n\n\n\n<p>Dp0 quattro 83mm, Dp1 quattro 40mm, Dp2 quattro 32mm et Dp3 quattro 42mm<\/p>\n\n\n\n<p>Ouf, y&rsquo;a quelques choses d&rsquo;int\u00e9ressant :-))<\/p>\n\n\n\n<p>Avec le DP3, la focale commence \u00eatre assez longue pour que le r\u00e9glage ne soit plus vraiment une histoire de mm \ud83d\ude09<\/p>\n\n\n\n<p>Le Dp0 Quattro m&rsquo;a permis de r\u00e9aliser un sph\u00e9rique (info bulle ou visite virtuelle) en trois rangs d&rsquo;images. Reste que le processus est lent et vous demandera de la patience. Mais la qualit\u00e9 d&rsquo;image est juste bluffante, surtout pour ce genre d&rsquo;image! Je les ins\u00e8rerai bient\u00f4t dans le blog, patience \ud83d\ude09<\/p>\n\n\n\n<p>Je me lancerais aussi dans un Brenizer au DP3 Quattro, histoire de voir l&rsquo;apport du Foveon sur cette technique. Je l&rsquo;ai r\u00e9alis\u00e9e. Mais le temps me manque ;-).<\/p>\n\n\n\n<p>Je les poss\u00e8derai plusieurs mois (peut-\u00eatre m\u00eame bien plus si Sigma Romandie et Suisse le veulent bien), mais c&rsquo;est sur que je vais les utiliser sans compromis en paysage, street, portrait etc&#8230;<\/p>\n\n\n\n<p>Donc, un gros d\u00e9fi pour un petit passionn\u00e9 de la photographie comme moi qui consacre un temps tout de m\u00eame limit\u00e9.<\/p>\n\n\n\n<p>Pour ceux que cela int\u00e9resse, restez connect\u00e9s \ud83d\ude09<\/p>\n\n\n\n    \n        <div class=\"vl-slider-wrap\" id=\"vl-slider-inst3-wrap\">\n\n                        \n                <div id=\"vl-slider-inst3\"\n             class=\"vl-slider-container vl-slider-cols-1\">\n\n                        <div class=\"vl-slider-row\" data-row=\"0\">\n\n                                                <div class=\"vl-slider-slot\" data-slot=\"0\">\n\n                                        <img decoding=\"async\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/50560228961_27de95cd95_o-2000x2000.jpg\"\n                         alt=\"L&#039;Orbe\"\n                         class=\"vl-slider-img vl-slider-img-active\">\n\n                                        <img decoding=\"async\" src=\"\" alt=\"\" class=\"vl-slider-img vl-slider-img-next\">\n\n                                        \n                <\/div>\n            <\/div><!-- \/.vl-slider-row -->\n            \n        <\/div><!-- \/.vl-slider-container -->\n\n                \n                \n                        <div class=\"vl-slider-below-wrap\"\n             id=\"vl-slider-inst3-below-wrap\"\n             style=\"display:none;opacity:0;\">\n                        <div class=\"vl-slider-below-text\"\n                 id=\"vl-slider-inst3-below-0\">\n                                <p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">L&rsquo;Orbe<\/p>\n                                                <p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">Sigma Foveon DP quattro<\/p>\n                                                                <p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">Dans les belles gorges de l\u2019Orbe, le pont de la ville du m\u00eame nom se refl\u00e8te dans la rivi\u00e8re.<\/p>\n                            <\/div>\n                    <\/div>\n\n                        <div class=\"vl-sl-toggle-wrap\" id=\"vl-slider-inst3-toggle-wrap\">\n            <button class=\"vl-sl-toggle-btn\"\n                    id=\"vl-slider-inst3-toggle-btn\"\n                    aria-pressed=\"false\"\n                    aria-label=\"Afficher les d\u00e9tails\">\n                                <svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\"\n                     viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n                     stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                    <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8z\"><\/path>\n                    <circle cx=\"12\" cy=\"12\" r=\"3\"><\/circle>\n                <\/svg>\n                <span class=\"vl-sl-btn-label\">Afficher les d\u00e9tails<\/span>\n            <\/button>\n        <\/div>\n                \n    <\/div><!-- \/.vl-slider-wrap -->\n\n                <div class=\"vl-sl-lb-wrap\"\n         id=\"vl-slider-inst3-lightbox\"\n         role=\"dialog\" aria-modal=\"true\" aria-label=\"Visionneuse d'images\"\n         style=\"display:none;\">\n\n                <div class=\"vl-sl-lb-overlay\" aria-hidden=\"true\"><\/div>\n\n        <div class=\"vl-sl-lb-content\">\n\n                        <div class=\"vl-sl-lb-toolbar\">\n                <span class=\"vl-sl-lb-counter\"\n                      id=\"vl-slider-inst3-lb-counter\"\n                      aria-live=\"polite\"><\/span>\n                <button class=\"vl-sl-lb-close\"\n                        id=\"vl-slider-inst3-lb-close\"\n                        aria-label=\"Fermer\">&times;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-stage\">\n                <button class=\"vl-sl-lb-prev\"\n                        id=\"vl-slider-inst3-lb-prev\"\n                        aria-label=\"Image pr\u00e9c\u00e9dente\">&#10094;<\/button>\n\n                <div class=\"vl-sl-lb-img-wrap\">\n                                        <div class=\"vl-sl-lb-progress-container\" aria-hidden=\"true\">\n                        <div class=\"vl-sl-lb-progress-bar\"\n                             id=\"vl-slider-inst3-lb-progress\"><\/div>\n                    <\/div>\n                    <img decoding=\"async\" src=\"\" alt=\"\"\n                         id=\"vl-slider-inst3-lb-img\"\n                         class=\"vl-sl-lb-img\">\n                                        <div class=\"vl-sl-lb-caption\"\n                         id=\"vl-slider-inst3-lb-caption\"\n                         aria-live=\"polite\"><\/div>\n                <\/div>\n\n                <button class=\"vl-sl-lb-next\"\n                        id=\"vl-slider-inst3-lb-next\"\n                        aria-label=\"Image suivante\">&#10095;<\/button>\n            <\/div>\n\n                        <div class=\"vl-sl-lb-footer\">\n                <div class=\"vl-sl-lb-controls\">\n                    <button class=\"vl-sl-lb-playpause\"\n                            id=\"vl-slider-inst3-lb-playpause\"\n                            aria-label=\"Lancer le diaporama\"\n                            aria-pressed=\"false\">\u25b6<\/button>\n                    <button class=\"vl-sl-lb-speed\"\n                            id=\"vl-slider-inst3-lb-speed\"\n                            aria-label=\"Changer la vitesse\">4s<\/button>\n                <\/div>\n            <\/div>\n\n        <\/div><!-- \/.vl-sl-lb-content -->\n    <\/div><!-- \/.vl-sl-lb-wrap -->\n    \n\n        <style id=\"vl-slider-inst3-style\">\n\n        \/* \u2500\u2500 Wrap ext\u00e9rieur \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:relative est n\u00e9cessaire pour que les fant\u00f4mes (position:absolute)\n           se positionnent par rapport au wrap et non \u00e0 la page enti\u00e8re.          *\/\n        #vl-slider-inst3-wrap {\n            width: 100%;\n            max-width: 100%;\n            margin: 20px auto;\n            position: relative;\n            \/* PAS de overflow:hidden ici \u2014 les fant\u00f4mes d\u00e9bordent intentionnellement *\/\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Conteneur principal : colonne flex (rang\u00e9es empil\u00e9es) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex-direction:column \u2192 les .vl-slider-row s'empilent verticalement.\n           gap:8px \u2192 espacement entre rang\u00e9es.                                    *\/\n        #vl-slider-inst3 {\n            display: flex;\n            flex-direction: column;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            overflow: hidden;\n            border-radius: 8px;\n            background: transparent;\n            box-sizing: border-box;\n        }\n\n        \/* \u2500\u2500 Rang\u00e9e : ligne flex (slots c\u00f4te \u00e0 c\u00f4te) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           height est d\u00e9fini ici par rang\u00e9e pour permettre des hauteurs\n           diff\u00e9rentes entre rang\u00e9e 1 et rang\u00e9e 2 (height_row2).                 *\/\n        #vl-slider-inst3 .vl-slider-row {\n            display: flex;\n            gap: 8px;\n            width: 100%;\n            max-width: 100%;\n            height: 600px;\n            overflow: hidden;\n            box-sizing: border-box;\n        }\n\n        \n        \/* \u2500\u2500 Slot individuel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           flex:1 \u2192 chaque slot prend la m\u00eame largeur dans sa rang\u00e9e.\n           position:relative \u2192 n\u00e9cessaire pour les images en absolute.            *\/\n        #vl-slider-inst3 .vl-slider-slot {\n            position: relative;\n            flex: 1;\n            min-width: 0;\n            overflow: hidden;\n            border-radius: 6px;\n            box-sizing: border-box;\n            \/* La hauteur est fix\u00e9e par la rang\u00e9e parente (.vl-slider-row) *\/\n        }\n\n        \/* \u2500\u2500 Images : remplissent exactement le slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           position:absolute + inset:0 \u2192 l'image couvre tout le slot.\n           object-fit:contain \u2192 image enti\u00e8re visible sans recadrage.\n           IMPORTANT : fonctionne uniquement si le slot a une hauteur d\u00e9finie,\n           ce qui est garanti par .vl-slider-row { height: Xpx }.               *\/\n        #vl-slider-inst3 .vl-slider-img {\n            position: absolute;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n            background: transparent;\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* \u2500\u2500 Fix critique : la rang\u00e9e DOIT avoir overflow:hidden \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Sans \u00e7a, les images en position:absolute d\u00e9bordent visuellement\n           m\u00eame si leur taille est contrainte.                                  *\/\n        #vl-slider-inst3 .vl-slider-row {\n            overflow: hidden;\n            contain: strict;       \/* Isole compl\u00e8tement le rendu de la rang\u00e9e *\/\n        }\n        \/* Image active : visible (opacity 1) *\/\n        #vl-slider-inst3 .vl-slider-img-active { opacity: 1; }\n        \/* Image suivante : invisible (opacity 0), pr\u00eate pour la prochaine transition *\/\n        #vl-slider-inst3 .vl-slider-img-next   { opacity: 0; }\n\n                \/* \u2500\u2500 Curseur zoom-in si lightbox activ\u00e9e \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           pointer-events:none sur img-next \u2192 seule l'image active re\u00e7oit les clics. *\/\n        #vl-slider-inst3 .vl-slider-slot { cursor: zoom-in; }\n        #vl-slider-inst3 .vl-slider-img-next { pointer-events: none; }\n        #vl-slider-inst3 .vl-slider-overlay-text { pointer-events: none; }\n        \n        \n        \/* \u2500\u2500 Overlay texte (sur l'image) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Bande semi-transparente en bas de chaque slot.\n           La transition opacity correspond au fade_in configur\u00e9.                 *\/\n        #vl-slider-inst3 .vl-slider-overlay-text {\n            position: absolute;\n            bottom: 0; left: 0; right: 0;\n            background: rgba(0, 0, 0, .5);\n            color: #fff;\n            padding: 10px 16px;\n            font-size: 13px;\n            line-height: 1.5;\n            border-radius: 0 0 6px 6px;\n            transition: opacity 1s ease-in-out;\n        }\n        #vl-slider-inst3 .vl-slider-overlay-text p { margin: 2px 0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2014 scop\u00e9 \u00e0 cette instance \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Pour columns=3 rang\u00e9e 2 (1 slot centr\u00e9) : limiter la largeur du bloc.  *\/\n        #vl-slider-inst3-below-wrap .vl-row-centered .vl-slider-below-text {\n            max-width: 50%;\n        }\n\n        \/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*\/\n        @media (max-width: 767px) {\n            #vl-slider-inst3 .vl-slider-row {\n                height: 300px !important;\n            }\n        }\n        @media (max-width: 479px) {\n                    }\n\n    <\/style>\n\n        <style>\n\n        \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n           LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n           \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n        \/* Fond plein \u00e9cran \u2014 cach\u00e9 par d\u00e9faut, affich\u00e9 via display:flex en JS *\/\n        .vl-sl-lb-wrap {\n            position: fixed;\n            inset: 0;\n            z-index: 99999;\n            display: none; \/* display:flex quand ouverte *\/\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            padding: 1rem;\n            box-sizing: border-box;\n        }\n\n        \/* Fond semi-transparent \u2014 clic = fermeture *\/\n        .vl-sl-lb-overlay {\n            position: fixed;\n            inset: 0;\n            background: rgba(0, 0, 0, .88);\n            cursor: pointer;\n            z-index: 0;\n        }\n\n        \/* Contenu centr\u00e9 au-dessus du fond *\/\n        .vl-sl-lb-content {\n            position: relative;\n            z-index: 1;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 92vw;\n            max-height: 92vh;\n            gap: 8px;\n        }\n\n        \/* Toolbar : compteur + bouton \u00d7 *\/\n        .vl-sl-lb-toolbar {\n            display: flex;\n            width: 100%;\n            align-items: center;\n            justify-content: space-between;\n        }\n        .vl-sl-lb-counter {\n            color: #fff;\n            background: rgba(0, 0, 0, .55);\n            padding: 4px 10px;\n            border-radius: 20px;\n            font-size: 13px;\n        }\n        .vl-sl-lb-close {\n            background: rgba(0, 0, 0, .55);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 34px; height: 34px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            transition: background .2s, transform .2s;\n            line-height: 1;\n        }\n        .vl-sl-lb-close:hover { background: rgba(0, 0, 0, .9); transform: scale(1.15); }\n\n        \/* Stage : fl\u00e8ches + image *\/\n        .vl-sl-lb-stage {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n        }\n        .vl-sl-lb-prev, .vl-sl-lb-next {\n            flex-shrink: 0;\n            background: rgba(0, 0, 0, .5);\n            border: none;\n            color: #fff;\n            font-size: 20px;\n            width: 42px; height: 42px;\n            border-radius: 50%;\n            cursor: pointer;\n            display: flex; align-items: center; justify-content: center;\n            user-select: none;\n            transition: background .2s, transform .2s;\n        }\n        .vl-sl-lb-prev:hover, .vl-sl-lb-next:hover {\n            background: rgba(0, 0, 0, .9);\n            transform: scale(1.15);\n        }\n\n        \/* Conteneur image : flex-column pour empiler image + caption *\/\n        .vl-sl-lb-img-wrap {\n            position: relative;\n            display: inline-flex;\n            flex-direction: column;\n            align-items: center;\n            max-width: 78vw;\n        }\n\n        \/* Image lightbox *\/\n        .vl-sl-lb-img {\n            display: block;\n            max-width: 78vw;\n            max-height: 72vh;\n            border-radius: 8px;\n            box-shadow: 0 4px 32px rgba(0, 0, 0, .5);\n            opacity: 0; \/* commence invisible, JS anime vers 1 *\/\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* Barre de progression du diaporama \u2014 en haut de l'image *\/\n        .vl-sl-lb-progress-container {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 3px;\n            background: rgba(255, 255, 255, .2);\n            border-radius: 2px;\n            overflow: hidden;\n            display: none; \/* visible seulement en mode play *\/\n        }\n        .vl-sl-lb-progress-bar {\n            height: 100%;\n            width: 0%;\n            background: #fff;\n            transition: width linear;\n        }\n\n        \/* Caption sous l'image *\/\n        .vl-sl-lb-caption {\n            color: #fff;\n            font-size: 13px;\n            text-align: center;\n            word-break: break-word;\n            margin-top: 8px;\n            padding: 6px 18px;\n            box-sizing: border-box;\n            max-width: 78vw;\n            line-height: 1.5;\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            border-radius: 14px;\n            display: none; \/* affich\u00e9 par le JS si caption non vide *\/\n        }\n        .vl-sl-lb-caption.has-text { display: inline-block; }\n\n        \/* Footer : boutons play\/pause + vitesse *\/\n        .vl-sl-lb-footer {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            gap: 6px;\n            width: 100%;\n        }\n        .vl-sl-lb-controls { display: flex; gap: 8px; }\n        .vl-sl-lb-playpause, .vl-sl-lb-speed {\n            background: rgba(255, 255, 255, .15);\n            border: 1px solid rgba(255, 255, 255, .25);\n            color: #fff;\n            border-radius: 20px;\n            padding: 4px 14px;\n            font-size: 13px;\n            cursor: pointer;\n            transition: background .2s;\n            min-width: 48px;\n            text-align: center;\n        }\n        .vl-sl-lb-playpause:hover, .vl-sl-lb-speed:hover {\n            background: rgba(255, 255, 255, .28);\n        }\n\n        \/* Mobile : masquer les contr\u00f4les pour ne pas g\u00eaner le swipe *\/\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-prev,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-next,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-caption,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-progress-container,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-close,\n        .vl-sl-lb-wrap.vl-lb-hide-nav .vl-sl-lb-counter { display: none !important; }\n\n        \/* \u2500\u2500 Bouton toggle \"Afficher les d\u00e9tails\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Petit bouton discret align\u00e9 \u00e0 droite, au-dessus des textes below.\n           La classe .active indique l'\u00e9tat \"ouvert\".                             *\/\n        .vl-sl-toggle-wrap { text-align: right; margin-bottom: 10px; }\n        .vl-sl-toggle-btn {\n            background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;\n            padding: 7px 12px; cursor: pointer; font-size: 12px;\n            display: inline-flex; align-items: center; gap: 6px;\n            box-shadow: 0 2px 6px rgba(0, 0, 0, .12);\n            transition: background .2s, box-shadow .2s;\n            line-height: 1;\n        }\n        .vl-sl-toggle-btn:hover  { background: #ececec; box-shadow: 0 3px 8px rgba(0, 0, 0, .18); }\n        .vl-sl-toggle-btn.active { background: #e0e0e0; }\n\n        \/* \u2500\u2500 Textes sous le slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n           Le wrap est flex horizontal : un bloc par colonne, c\u00f4te \u00e0 c\u00f4te.\n           Chaque bloc est un bloc normal : les <p> s'empilent naturellement.     *\/\n        .vl-slider-below-wrap {\n            display: flex;\n            flex-direction: row;\n            gap: 8px;\n            width: 100%;\n            box-sizing: border-box;\n            opacity: 0;\n            transition: opacity .3s ease;\n        }\n        .vl-slider-below-wrap.vl-sl-texts-visible { opacity: 1; }\n\n        \/* Bloc texte individuel \u2014 un par image visible *\/\n        .vl-slider-below-text {\n            flex: 1;\n            min-width: 0;\n            padding: 8px 4px;\n            font-size: 13px;\n            line-height: 1.5;\n            text-align: center;\n            box-sizing: border-box;\n        }\n        .vl-slider-below-text p { margin: 2px 0; }\n\n        \/* Styles texte *\/\n        .vl-sl-title       { font-weight: bold; }\n        .vl-sl-caption     { font-style: italic; }\n        .vl-sl-alt         { font-size: 11px; }\n        .vl-sl-description { font-size: 12px; }\n\n        \/* Couleurs overlay (fond sombre \u2192 texte blanc) *\/\n        .vl-slider-overlay-text .vl-sl-title       { color: #fff; }\n        .vl-slider-overlay-text .vl-sl-caption     { color: rgba(255, 255, 255, .8); }\n        .vl-slider-overlay-text .vl-sl-alt         { color: rgba(255, 255, 255, .6); }\n        .vl-slider-overlay-text .vl-sl-description { color: rgba(255, 255, 255, .9); }\n\n        \/* Couleurs below (fond clair \u2192 texte sombre) *\/\n        .vl-slider-below-text .vl-sl-title       { color: #222; }\n        .vl-slider-below-text .vl-sl-caption     { color: #666; }\n        .vl-slider-below-text .vl-sl-alt         { color: #999; font-size: 11px; }\n        .vl-slider-below-text .vl-sl-description { color: #444; font-size: 12px; }\n\n    <\/style>\n\n        <script>\n    (function () {\n        'use strict';\n\n        document.addEventListener('DOMContentLoaded', function () {\n\n            \/\/ \u2500\u2500 R\u00e9f\u00e9rences DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On r\u00e9cup\u00e8re le conteneur principal. Si absent (shortcode mal copi\u00e9),\n            \/\/ on quitte imm\u00e9diatement pour \u00e9viter les erreurs JS.\n            var slider = document.getElementById('vl-slider-inst3');\n            if ( ! slider ) return;\n\n            \/\/ Tous les slots de la grille (inclut toutes les rang\u00e9es)\n            var slots = slider.querySelectorAll('.vl-slider-slot');\n\n            \/\/ Fant\u00f4mes gauche et droit (null si ghost_peek=false \u2192 divs absentes)\n            var ghostLeft  = document.getElementById('vl-slider-inst3-ghost-left');\n            var ghostRight = document.getElementById('vl-slider-inst3-ghost-right');\n            var ghostImgL  = ghostLeft  ? ghostLeft.querySelector('.vl-ghost-img')  : null;\n            var ghostImgR  = ghostRight ? ghostRight.querySelector('.vl-ghost-img') : null;\n\n            \/\/ Overlays texte \u2014 un par slot, cherch\u00e9s dans le conteneur slider\n            var overlayEls = Array.prototype.slice.call(\n                slider.querySelectorAll('.vl-slider-overlay-text')\n            );\n            \/\/ Blocs texte \"below\" \u2014 cibl\u00e9s par classe pour \u00e9viter de capturer le wrap\n            var belowWrap  = document.getElementById('vl-slider-inst3-below-wrap');\n            var belowEls   = belowWrap\n                ? Array.prototype.slice.call( belowWrap.querySelectorAll('.vl-slider-below-text') )\n                : [];\n\n            \/\/ \u2500\u2500 Donn\u00e9es inject\u00e9es par PHP \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ wp_json_encode() c\u00f4t\u00e9 PHP \u2192 JSON valide et safe\n            var slides      = [{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50560228961_27de95cd95_o-2000x2000.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/50560228961_27de95cd95_o.jpg\",\"alt\":\"L&#039;Orbe\",\"title\":\"L&rsquo;Orbe\",\"caption\":\"Sigma Foveon DP quattro\",\"description\":\"Dans les belles gorges de l\\u2019Orbe, le pont de la ville du m\\u00eame nom se refl\\u00e8te dans la rivi\\u00e8re.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lumire-sur-le-jura_43463547024_o-2000x2000.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lumire-sur-le-jura_43463547024_o.jpg\",\"alt\":\"Lumi\\u00e8re sur le Jura avec le Sigma Fov\\u00e9on\",\"title\":\"Lumi\\u00e8re sur le Jura\",\"caption\":\"Sigma DP 3\",\"description\":\"Lumi\\u00e8re sur les collines pr\\u00e8s du Jura. Le ciel devient incroyable. Et les possibilit\\u00e9 du DP3 permettent de structurer les couleurs du ciel.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/the-gate_32172395998_o-1378x2000.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/the-gate_32172395998_o.jpg\",\"alt\":\"Porte des bois de la for\\u00eat magique du Seppey en suisse romande pr\\u00e8s de Cossonay au Sigma Fov\\u00e9on\",\"title\":\"La for\\u00eat magique\",\"caption\":\"Sigma DP Foveon \",\"description\":\"Promenade dans la belle for\\u00eat du Seppey. Que l\\u2019on appelle pour certains, la for\\u00eat magique. Je suis avec mon DP Sigma. Je remarque ce passage en deux immenses arbres majestueux. Il me suffit juste d\\u2019attendre le promeneur\\u2026\"}];\n            var columns     = 1;\n            var slotCount   = 1; \/\/ Nb total de slots visibles\n            var lightbox    = true;\n            var showTitle       = true;\n            var showCaption     = true;\n            var showAlt         = false;\n            var showDescription = true;\n\n            \/\/ \u2500\u2500 Variables d'\u00e9tat du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ currentIndex : index dans $slides de la premi\u00e8re image affich\u00e9e\n            var currentIndex  = 0;\n            \/\/ Dur\u00e9es en millisecondes (PHP les envoie en secondes)\n            var displayTime   = 3 * 1000;\n            var fadeInTime    = 1 * 1000;\n            var fadeOutTime   = 1 * 1000;\n            var sliderPaused  = false;  \/\/ Vrai quand la lightbox ou le toggle sont ouverts\n            var sliderTimer   = null;   \/\/ R\u00e9f\u00e9rence au setTimeout en cours\n\n            \/\/ \u2500\u2500 pauseSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Arr\u00eate les transitions (lightbox ouverte, textes below affich\u00e9s).\n            \/\/ clearTimeout annule le prochain changeImage() planifi\u00e9.\n            function pauseSlider() {\n                sliderPaused = true;\n                if ( sliderTimer ) {\n                    clearTimeout( sliderTimer );\n                    sliderTimer = null;\n                }\n            }\n\n            \/\/ \u2500\u2500 resumeSlider() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Reprend les transitions apr\u00e8s fermeture lightbox ou toggle.\n            \/\/ Ne red\u00e9marre que s'il y a assez d'images pour animer.\n            function resumeSlider() {\n                sliderPaused = false;\n                if ( slides.length >= slotCount && slides.length > 1 ) {\n                    sliderTimer = setTimeout( changeImage, displayTime );\n                }\n            }\n\n            \/\/ \u2500\u2500 Protection des images \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ D\u00e9sactive le clic droit (contextmenu) et le glisser-d\u00e9poser (dragstart)\n            \/\/ sur toutes les images du slider pour d\u00e9courager la copie.\n            slider.querySelectorAll('.vl-slider-img').forEach(function ( img ) {\n                img.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n                img.addEventListener('dragstart',   function (e) { e.preventDefault(); });\n            });\n            slider.addEventListener('contextmenu', function (e) { e.preventDefault(); });\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ LIGHTBOX COMPL\u00c8TE \u2014 style VL Galerie (sans \u00e9toiles de notation)\n            \/\/ Navigation : fl\u00e8ches, clavier, swipe tactile\n            \/\/ Diaporama  : play\/pause, vitesse, barre de progression\n            \/\/ Transitions: fade | slide | none (param\u00e8tre lb_transition)\n            \/\/ Mobile     : masquage automatique des contr\u00f4les, swipe uniquement\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            if ( lightbox ) {\n\n                var lbWrap     = document.getElementById('vl-slider-inst3-lightbox');\n                var lbImg      = document.getElementById('vl-slider-inst3-lb-img');\n                var lbClose    = document.getElementById('vl-slider-inst3-lb-close');\n                var lbOverlay  = lbWrap ? lbWrap.querySelector('.vl-sl-lb-overlay') : null;\n                var lbPrev     = document.getElementById('vl-slider-inst3-lb-prev');\n                var lbNext     = document.getElementById('vl-slider-inst3-lb-next');\n                var lbCounter  = document.getElementById('vl-slider-inst3-lb-counter');\n                var lbCaption  = document.getElementById('vl-slider-inst3-lb-caption');\n                var lbPlay     = document.getElementById('vl-slider-inst3-lb-playpause');\n                var lbSpeedBtn = document.getElementById('vl-slider-inst3-lb-speed');\n                var lbProgress = document.getElementById('vl-slider-inst3-lb-progress');\n                var lbProgWrap = lbProgress ? lbProgress.parentElement : null;\n                var lbTransition  = 'fade';\n                var lbTransSpeed  = 400;\n                var lbSlideTimer  = null;\n                var lbSlideSpeed  = 4000;\n                var lbIsPlaying   = false;\n                var lbCurrentIdx  = 0;\n                var lbImages      = [];\n                var lbNavigating  = false;\n\n                if ( ! lbWrap ) return;\n\n                function lbIsMobile() {\n                    return \/Android|iPhone|iPod\/i.test(navigator.userAgent) &&\n                           ( 'ontouchstart' in window || navigator.maxTouchPoints > 0 );\n                }\n                function lbIsTabletPortrait() {\n                    return ( \/iPad|Android\/i.test(navigator.userAgent) || navigator.maxTouchPoints > 0 ) &&\n                           window.innerWidth <= 1024 && window.innerHeight > window.innerWidth;\n                }\n                function updateMobileNav() {\n                    lbWrap.classList.toggle('vl-lb-hide-nav', lbIsMobile() || lbIsTabletPortrait());\n                }\n\n                function openLightbox( clickedIndex ) {\n                    lbImages = slides.map(function ( s ) {\n                        return { url: s.full_url || s.url, alt: s.alt || '', title: s.title || '', description: s.description || '' };\n                    });\n                    lbCurrentIdx = ( ( clickedIndex % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var single = lbImages.length <= 1;\n                    if ( lbPrev ) lbPrev.style.display = single ? 'none' : '';\n                    if ( lbNext ) lbNext.style.display = single ? 'none' : '';\n                    updateMobileNav();\n                    lbWrap.style.display = 'flex';\n                    document.body.style.overflow = 'hidden';\n                    showLbImage( lbCurrentIdx );\n                    if ( lbClose ) lbClose.focus();\n                }\n\n                function showLbImage( index ) {\n                    if ( ! lbImages.length ) return;\n                    var prevIdx  = lbCurrentIdx;\n                    lbCurrentIdx = ( ( index % lbImages.length ) + lbImages.length ) % lbImages.length;\n                    var item     = lbImages[ lbCurrentIdx ];\n                    var dir      = index >= prevIdx ? 1 : -1;\n\n                    if ( lbCounter ) lbCounter.textContent = ( lbCurrentIdx + 1 ) + ' \/ ' + lbImages.length;\n                    var capText = item.description || item.alt || item.title || '';\n                    if ( lbCaption ) {\n                        lbCaption.textContent = capText;\n                        lbCaption.classList.toggle('has-text', capText.length > 0);\n                    }\n                    resetLbProgressBar();\n\n                    if ( lbTransition === 'none' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealNone() { lbImg.style.opacity = '1'; }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealNone() : ( lbImg.onload = lbImg.onerror = revealNone );\n                        return;\n                    }\n\n                    if ( lbTransition === 'fade' ) {\n                        lbImg.style.transition = 'none'; lbImg.style.opacity = '0'; lbImg.style.transform = '';\n                        lbImg.onload = null; lbImg.src = item.url; lbImg.alt = item.alt;\n                        function revealFade() {\n                            void lbImg.offsetWidth;\n                            lbImg.style.transition = 'opacity ' + ( lbTransSpeed \/ 1000 ) + 's ease';\n                            requestAnimationFrame(function () { lbImg.style.opacity = '1'; });\n                        }\n                        ( lbImg.complete && lbImg.naturalWidth > 0 ) ? revealFade() : ( lbImg.onload = lbImg.onerror = revealFade );\n                        return;\n                    }\n\n                    if ( lbTransition === 'slide' ) {\n                        var imgWrap = lbImg.parentElement;\n                        var easing  = 'cubic-bezier(.25,.46,.45,.94)';\n                        var dur     = ( lbTransSpeed \/ 1000 ) + 's';\n                        var newImg  = new Image();\n                        newImg.alt = item.alt; newImg.draggable = false;\n                        newImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;box-shadow:0 4px 32px rgba(0,0,0,.5);opacity:1;transform:translateX(' + ( dir * 100 ) + '%);transition:none;user-select:none';\n                        function doSlide() {\n                            imgWrap.style.cssText = 'position:relative;overflow:hidden;display:inline-flex;width:' + lbImg.offsetWidth + 'px;height:' + lbImg.offsetHeight + 'px';\n                            lbImg.style.cssText = 'position:absolute;top:0;left:0;max-width:78vw;max-height:72vh;border-radius:8px;opacity:1;transform:translateX(0);transition:none;user-select:none';\n                            imgWrap.appendChild( newImg );\n                            requestAnimationFrame(function () {\n                                requestAnimationFrame(function () {\n                                    lbImg.style.transition = newImg.style.transition = 'transform ' + dur + ' ' + easing;\n                                    lbImg.style.transform  = 'translateX(' + ( -dir * 100 ) + '%)';\n                                    newImg.style.transform = 'translateX(0)';\n                                    setTimeout(function () {\n                                        lbImg.src = newImg.src; lbImg.alt = newImg.alt;\n                                        lbImg.style.cssText = ''; lbImg.style.opacity = '1';\n                                        if ( imgWrap.contains(newImg) ) imgWrap.removeChild( newImg );\n                                        imgWrap.style.cssText = '';\n                                        lbNavigating = false;\n                                    }, lbTransSpeed + 30);\n                                });\n                            });\n                        }\n                        newImg.onload = newImg.onerror = doSlide;\n                        newImg.src = item.url;\n                        if ( newImg.complete && newImg.naturalWidth > 0 ) { newImg.onload = null; doSlide(); }\n                        return;\n                    }\n                }\n\n                function lbNavigateTo( direction ) {\n                    if ( lbNavigating ) return;\n                    lbNavigating = true;\n                    showLbImage( lbCurrentIdx + direction );\n                    if ( lbTransition !== 'slide' ) setTimeout(function () { lbNavigating = false; }, lbTransSpeed + 50);\n                }\n\n                function closeLightbox() {\n                    lbWrap.style.display = 'none';\n                    lbImg.src = '';\n                    document.body.style.overflow = '';\n                    stopLbSlideshow();\n                    pauseSlider();\n                    setTimeout(function () { resumeSlider(); }, 300);\n                }\n\n                function startLbSlideshow() {\n                    stopLbSlideshow();\n                    lbSlideTimer = setInterval(function () { lbNavigateTo( 1 ); }, lbSlideSpeed);\n                    lbIsPlaying = true;\n                    if ( lbPlay ) { lbPlay.textContent = '\u23f8'; lbPlay.setAttribute('aria-pressed', 'true'); lbPlay.setAttribute('aria-label', 'Arr\u00eater le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'block';\n                    resetLbProgressBar();\n                }\n\n                function stopLbSlideshow() {\n                    if ( lbSlideTimer ) { clearInterval( lbSlideTimer ); lbSlideTimer = null; }\n                    lbIsPlaying = false;\n                    if ( lbPlay ) { lbPlay.textContent = '\u25b6'; lbPlay.setAttribute('aria-pressed', 'false'); lbPlay.setAttribute('aria-label', 'Lancer le diaporama'); }\n                    if ( lbProgWrap ) lbProgWrap.style.display = 'none';\n                    if ( lbProgress ) { lbProgress.style.transition = 'none'; lbProgress.style.width = '0%'; }\n                }\n\n                function resetLbProgressBar() {\n                    if ( ! lbIsPlaying || ! lbProgress ) return;\n                    lbProgress.style.transition = 'none'; lbProgress.style.width = '0%';\n                    requestAnimationFrame(function () {\n                        requestAnimationFrame(function () {\n                            lbProgress.style.transition = 'width ' + ( lbSlideSpeed \/ 1000 ) + 's linear';\n                            lbProgress.style.width = '100%';\n                        });\n                    });\n                }\n\n                slots.forEach(function ( slot, slotIndex ) {\n                    slot.addEventListener('click', function () {\n                        var clickedIndex = ( currentIndex + slotIndex ) % slides.length;\n                        pauseSlider();\n                        openLightbox( clickedIndex );\n                    });\n                });\n\n                if ( lbClose )   lbClose.addEventListener('click', closeLightbox);\n                if ( lbOverlay ) lbOverlay.addEventListener('click', closeLightbox);\n                if ( lbPrev )    lbPrev.addEventListener('click', function () { lbNavigateTo( -1 ); });\n                if ( lbNext )    lbNext.addEventListener('click', function () { lbNavigateTo(  1 ); });\n\n                document.addEventListener('keydown', function ( e ) {\n                    if ( lbWrap.style.display !== 'flex' ) return;\n                    if ( e.key === 'Escape'     ) closeLightbox();\n                    if ( e.key === 'ArrowLeft'  ) lbNavigateTo( -1 );\n                    if ( e.key === 'ArrowRight' ) lbNavigateTo(  1 );\n                });\n\n                if ( lbPlay ) {\n                    lbPlay.addEventListener('click', function () {\n                        lbIsPlaying ? stopLbSlideshow() : startLbSlideshow();\n                    });\n                }\n\n                var lbSpeeds  = [ 2000, 4000, 6000 ];\n                var lbSpeedLb = [ '2s', '4s', '6s' ];\n                if ( lbSpeedBtn ) {\n                    lbSpeedBtn.addEventListener('click', function () {\n                        var idx = ( lbSpeeds.indexOf( lbSlideSpeed ) + 1 ) % lbSpeeds.length;\n                        lbSlideSpeed = lbSpeeds[ idx ];\n                        lbSpeedBtn.textContent = lbSpeedLb[ idx ];\n                        if ( lbIsPlaying ) startLbSlideshow();\n                    });\n                }\n\n                var lbSwipeStartX = 0, lbSwipeHandled = false;\n                if ( lbImg ) {\n                    lbImg.addEventListener('touchstart', function ( e ) {\n                        lbSwipeStartX = e.changedTouches[0].screenX; lbSwipeHandled = false;\n                    }, { passive: true });\n                    lbImg.addEventListener('touchend', function ( e ) {\n                        if ( lbSwipeHandled ) return;\n                        var diff = lbSwipeStartX - e.changedTouches[0].screenX;\n                        if ( Math.abs(diff) > 40 ) { lbSwipeHandled = true; lbNavigateTo( diff > 0 ? 1 : -1 ); }\n                    }, { passive: true });\n                }\n\n                window.addEventListener('resize',            updateMobileNav);\n                window.addEventListener('orientationchange', updateMobileNav);\n\n            } \/\/ fin if(lightbox)\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TEXTES \u2014 buildTextHtml() et updateTextSlot()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            \/\/ \u2500\u2500 buildTextHtml(slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Construit le HTML des textes pour un slide donn\u00e9.\n            \/\/ Les styles CSS sont inject\u00e9s par PHP (esc_js) au rendu de la page\n            \/\/ \u2192 ils sont des constantes, pas des donn\u00e9es utilisateur.\n            \/\/ Les valeurs slide.title etc. sont d\u00e9j\u00e0 esc_html() c\u00f4t\u00e9 PHP\n            \/\/ \u2192 safe pour innerHTML.\n            function buildTextHtml( slide ) {\n                var html = '';\n                if ( showTitle && slide.title ) {\n                    html += '<p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">'\n                          + slide.title + '<\/p>';\n                }\n                if ( showCaption && slide.caption ) {\n                    html += '<p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">'\n                          + slide.caption + '<\/p>';\n                }\n                if ( showAlt && slide.alt ) {\n                    html += '<p class=\"vl-sl-alt\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.alt + '<\/p>';\n                }\n                if ( showDescription && slide.description ) {\n                    html += '<p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">'\n                          + slide.description + '<\/p>';\n                }\n                return html;\n            }\n\n            \/\/ \u2500\u2500 updateTextSlot(slotIndex, slide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour overlay ET below d'un slot donn\u00e9 avec les textes du slide.\n            \/\/ Utilis\u00e9 \u00e0 l'initialisation et lors des transitions.\n            function updateTextSlot( slotIndex, slide ) {\n                if ( overlayEls[ slotIndex ] ) {\n                    overlayEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n                if ( belowEls[ slotIndex ] ) {\n                    belowEls[ slotIndex ].innerHTML = buildTextHtml( slide );\n                }\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ FANT\u00d4MES \u2014 updateGhosts()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n            var ghostPeek = false;\n\n            \/\/ \u2500\u2500 updateGhosts() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ Met \u00e0 jour les images des fant\u00f4mes selon la position courante.\n            \/\/ Appel\u00e9e apr\u00e8s chaque transition et lors d'un changement via lightbox.\n            \/\/\n            \/\/ Fant\u00f4me gauche = image juste avant currentIndex (boucle circulaire)\n            \/\/ Fant\u00f4me droit  = image juste apr\u00e8s le dernier slot visible\n            \/\/ Si une seule image : les deux fant\u00f4mes montrent la m\u00eame image.\n            function updateGhosts() {\n                if ( ! ghostPeek ) return;\n                var n = slides.length;\n                var prevIdx = n > 1 ? ( currentIndex - 1 + n ) % n : currentIndex;\n                var nextIdx = n > slotCount ? ( currentIndex + slotCount ) % n : currentIndex;\n\n                \/\/ Fade out \u2192 changer src \u2192 fade in \u2014 synchronis\u00e9 avec fadeOutTime du slider\n                var dur = fadeOutTime \/ 1000;\n\n                if ( ghostImgL ) {\n                    ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgL.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgL.src = slides[ prevIdx ].url;\n                        ghostImgL.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgL.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n                if ( ghostImgR ) {\n                    ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                    ghostImgR.style.opacity = '0';\n                    setTimeout(function() {\n                        ghostImgR.src = slides[ nextIdx ].url;\n                        ghostImgR.style.transition = 'opacity ' + dur + 's ease-in-out';\n                        ghostImgR.style.opacity = '1';\n                    }, fadeOutTime );\n                }\n            }\n\n            \/\/ Initialisation des fant\u00f4mes au chargement\n            updateGhosts();\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ TRANSITION PRINCIPALE \u2014 changeImage()\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Cette fonction orchestre la transition de TOUS les slots en m\u00eame temps.\n            \/\/ Elle utilise des setTimeout cha\u00een\u00e9s (pas setInterval) pour \u00e9viter\n            \/\/ les d\u00e9rives de timing.\n            \/\/\n            \/\/ S\u00e9quence pour chaque slot :\n            \/\/   1. Fade OUT de imgActive  (dur\u00e9e: fadeOutTime)\n            \/\/   2. Apr\u00e8s fadeOut : charger imgNext + Fade IN  (dur\u00e9e: fadeInTime)\n            \/\/   3. Apr\u00e8s fadeIn : permuter imgActive \u2194 imgNext (op\u00e9ration instantan\u00e9e)\n            \/\/   4. Attendre displayTime \u2192 lancer le prochain changeImage()\n            \/\/\n            \/\/ currentIndex est avanc\u00e9 au step 3 du DERNIER slot (c === slots.length-1)\n            \/\/ pour \u00e9viter les race conditions avec la lightbox.\n\n            function changeImage() {\n                if ( slides.length < 2 ) return;\n                if ( sliderPaused ) return;\n\n                var nextIndices = [];\n                for ( var c = 0; c < slotCount; c++ ) {\n                    nextIndices.push( ( currentIndex + slotCount + c ) % slides.length );\n                }\n\n                \/\/ Lancer la transition des fant\u00f4mes en m\u00eame temps que les images\n                updateGhosts();\n\n                \/\/ \u2500\u2500 Transition par slot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On it\u00e8re sur chaque slot. Les closures setTimeout capturent\n                \/\/ les variables locales (slot, imgActive, imgNext\u2026) par valeur\n                \/\/ gr\u00e2ce aux param\u00e8tres de fonction.\n                slots.forEach(function ( slot, c ) {\n                    var imgActive   = slot.querySelector('.vl-slider-img-active');\n                    var imgNext     = slot.querySelector('.vl-slider-img-next');\n                    var nextSlide   = slides[ nextIndices[c] ];\n                    var slotOverlay = overlayEls[c] || null;\n\n                    \/\/ \u2500\u2500 Step 1 : Fade OUT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                    imgActive.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                    imgActive.style.opacity    = 0;\n                    \/\/ L'overlay texte dispara\u00eet en m\u00eame temps que l'image\n                    if ( slotOverlay ) {\n                        slotOverlay.style.transition = 'opacity ' + ( fadeOutTime \/ 1000 ) + 's ease-in-out';\n                        slotOverlay.style.opacity    = 0;\n                    }\n\n                    \/\/ \u2500\u2500 Step 2 : Apr\u00e8s fade OUT \u2192 charger et afficher imgNext \u2500\n                    \/\/ Les param\u00e8tres pass\u00e9s \u00e0 setTimeout \u00e9vitent les probl\u00e8mes\n                    \/\/ de closure (chaque slot a ses propres valeurs captur\u00e9es).\n                    setTimeout(function ( _slot, _imgActive, _imgNext, _nextSlide, _overlay ) {\n\n                        _imgNext.src = _nextSlide.url;\n                        _imgNext.alt = _nextSlide.alt;\n                        void _imgNext.offsetHeight; \/\/ Force reflow \u2192 garantit la transition\n\n                        _imgNext.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                        _imgNext.style.opacity    = 1;\n\n                        \/\/ Mise \u00e0 jour de l'overlay texte avec le contenu du nouveau slide\n                        if ( _overlay ) {\n                            _overlay.innerHTML = buildTextHtml( _nextSlide );\n                            _overlay.style.transition = 'opacity ' + ( fadeInTime \/ 1000 ) + 's ease-in-out';\n                            _overlay.style.opacity    = 1;\n                        }\n\n                        \/\/ \u2500\u2500 Step 3 : Apr\u00e8s fade IN \u2192 permuter imgActive \u2194 imgNext \u2500\u2500\n                        \/\/ isLast = true pour le dernier slot \u2192 on avance currentIndex ici\n                        setTimeout(function ( isLast ) {\n                            _imgActive.src              = _imgNext.src;\n                            _imgActive.alt              = _imgNext.alt;\n                            _imgActive.style.transition = 'none'; \/\/ Instantan\u00e9\n                            _imgActive.style.opacity    = 1;\n                            _imgNext.style.transition   = 'none';\n                            _imgNext.style.opacity      = 0;\n                            _imgNext.src = ''; \/\/ Lib\u00e8re la m\u00e9moire\n\n                            \/\/ On avance currentIndex une seule fois (au dernier slot)\n                            \/\/ pour \u00e9viter qu'il soit modifi\u00e9 plusieurs fois simultan\u00e9ment\n                            if ( isLast ) {\n                                currentIndex = ( currentIndex + slotCount ) % slides.length;\n                            }\n                        }, fadeInTime, c === slots.length - 1 );\n\n                    }, fadeOutTime, slot, imgActive, imgNext, nextSlide, slotOverlay );\n                }); \/\/ fin slots.forEach\n\n                \/\/ \u2500\u2500 Mise \u00e0 jour des textes \"below\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On les met \u00e0 jour pendant le fadeOut (quand l'ancien slide\n                \/\/ dispara\u00eet), pour un changement invisible.\n                if ( belowEls.length ) {\n                    setTimeout(function () {\n                        nextIndices.forEach(function ( idx, c ) {\n                            if ( belowEls[c] ) {\n                                belowEls[c].innerHTML = buildTextHtml( slides[ idx ] );\n                            }\n                        });\n                    }, fadeOutTime );\n                }\n\n                \/\/ \u2500\u2500 Step 4 : Planifier la prochaine transition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                \/\/ On attend fadeOut + fadeIn (dur\u00e9e totale de la transition)\n                \/\/ puis displayTime avant de lancer le prochain changeImage().\n                setTimeout(function () {\n                    if ( ! sliderPaused ) {\n                        sliderTimer = setTimeout( changeImage, displayTime );\n                    }\n                }, fadeOutTime + fadeInTime );\n\n            } \/\/ fin changeImage()\n\n            \/\/ \u2500\u2500 D\u00e9marrage du slider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ On d\u00e9marre seulement s'il y a plus d'une image ET assez pour\n            \/\/ remplir au moins un \"\u00e9cran\" complet (slotCount).\n            if ( slides.length >= slotCount && slides.length > 1 ) {\n                sliderTimer = setTimeout( changeImage, displayTime );\n            }\n\n\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/ BOUTON TOGGLE \"Afficher les d\u00e9tails\"\n            \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n            \/\/\n            \/\/ Visible uniquement si text_position=\"below\".\n            \/\/ Au clic : affiche\/masque le bloc vl-slider-below-wrap avec fade.\n            \/\/ Pause le slider quand les textes sont visibles (pour la lisibilit\u00e9).\n\n            var toggleBtn = document.getElementById('vl-slider-inst3-toggle-btn');\n            if ( toggleBtn && belowWrap ) {\n                var textVisible = false;\n                var toggleDelay = 300; \/\/ Dur\u00e9e de la transition CSS opacity en ms\n\n                toggleBtn.addEventListener('click', function () {\n                    textVisible = ! textVisible;\n                    toggleBtn.classList.toggle('active', textVisible);\n                    toggleBtn.setAttribute('aria-pressed', textVisible ? 'true' : 'false');\n                    toggleBtn.querySelector('.vl-sl-btn-label').textContent =\n                        textVisible ? 'Masquer les d\u00e9tails' : 'Afficher les d\u00e9tails';\n                    belowWrap.setAttribute('aria-hidden', textVisible ? 'false' : 'true');\n\n                    if ( textVisible ) {\n                        pauseSlider();\n                        belowWrap.style.display = 'flex'; \/\/ flex pour aligner les blocs c\u00f4te \u00e0 c\u00f4te\n                        belowWrap.style.opacity = '';\n                        requestAnimationFrame(function () {\n                            requestAnimationFrame(function () {\n                                belowWrap.classList.add('vl-sl-texts-visible');\n                            });\n                        });\n                    } else {\n                        \/\/ \u2500\u2500 Fermeture \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n                        \/\/ 1. Lance le fade out (retire la classe, CSS prend en charge)\n                        belowWrap.classList.remove('vl-sl-texts-visible');\n                        \/\/ 2. Apr\u00e8s la transition : cacher le bloc + reprendre le slider\n                        setTimeout(function () {\n                            belowWrap.style.display = 'none';\n                            belowWrap.style.opacity = '0';\n                            resumeSlider();\n                        }, toggleDelay );\n                    }\n                });\n            }\n\n        }); \/\/ fin DOMContentLoaded\n    })(); \/\/ fin IIFE\n    <\/script>\n\n    \n\n\n\n<p>Ici seront donc link\u00e9s (\u00e7a se dit \u00e7a non ?) tous les articles que j&rsquo;\u00e9crirais sur le Foveon, les DP ect&#8230;<\/p>\n\n\n\n<p>1. <a href=\"http:\/\/www.visionlarge.ch\/Blog\/foveon\/\">Mon avis sur le Foveon<\/a><\/p>\n\n\n\n<p>Et les liens trouv\u00e9s int\u00e9ressant trouv\u00e9s sur le Net<\/p>\n\n\n\n<p>1. <a href=\"https:\/\/www.sigma-global.com\/fr\/cameras\/dp-series\/technology\/\">Lien du constructeur Sigma sur le Foveon<\/a><\/p>\n\n\n\n<p>2. <a href=\"https:\/\/www.sigma-global.com\/fr\/cameras\/dp-series\/technology\/\"> Lien Sigma Merril en anglais <\/a><\/p>\n\n\n\n<p>3. <a href=\"https:\/\/www.sigma-global.com\/fr\/cameras\/dp-series\/technology\/\"> Forum de Passion Foveon, une mine d&rsquo;info !<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Comme vous le savez peut-\u00eatre d\u00e9j\u00e0, j&rsquo;ai craqu\u00e9 il y a quelques temps pour la technologie du c\u00e9l\u00e8bre Nipon Sigma. Ce capteur Foveon \u00e0 trois couches permettant la capture directe des trois couleurs primaires d&rsquo;une pr\u00e9cision d\u00e9concertante, mais qui ne pardonne rien. Afin de ma\u00eetriser la prise d&rsquo;image, le traitement,&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/\">La suite? C&#039;est par l\u00e0!<span class=\"screen-reader-text\">Le Sigma Foveon<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-4120","page","type-page","status-publish","hentry","excerpt","zoom","full-without-featured","even","excerpt-0"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Le Sigma Foveon &#8212; Visionlarge.ch<\/title>\n<meta name=\"description\" content=\"Mon test des capteurs foveon sur plusieurs mois. J&#039;aurais pour se faire la gamme DP quattro au complet. DP0, DP1, DP2, DP3 Quattro. A bient\u00f4t!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Le Sigma Foveon &#8212; Visionlarge.ch\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/\" \/>\n<meta property=\"og:site_name\" content=\"Visionlarge.ch\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-16T17:13:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Dans-les-forets-du-Jura-2024-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1750\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@visionlarge\" \/>\n<meta name=\"twitter:label1\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data1\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/le-sigma-foveon\\\/\",\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/le-sigma-foveon\\\/\",\"name\":\"Le Sigma Foveon &#8212; Visionlarge.ch\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#website\"},\"datePublished\":\"2018-06-09T10:58:41+00:00\",\"dateModified\":\"2026-04-16T17:13:03+00:00\",\"description\":\"Mon test des capteurs foveon sur plusieurs mois. J'aurais pour se faire la gamme DP quattro au complet. DP0, DP1, DP2, DP3 Quattro. A bient\u00f4t!\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/le-sigma-foveon\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/le-sigma-foveon\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/le-sigma-foveon\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Le Sigma Foveon\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#website\",\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/\",\"name\":\"Bovard Alain, mon blog photo\",\"description\":\"C&#039;est toujours plus beau en visionlarge...\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#\\\/schema\\\/person\\\/b1280adcf8dd414efb101660dca80274\"},\"alternateName\":\"visionlarge\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#\\\/schema\\\/person\\\/b1280adcf8dd414efb101660dca80274\",\"name\":\"Visionlarge\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\",\"caption\":\"Visionlarge\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g\"},\"sameAs\":[\"http:\\\/\\\/www.visionlarge.ch\\\/Blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Le Sigma Foveon &#8212; Visionlarge.ch","description":"Mon test des capteurs foveon sur plusieurs mois. J'aurais pour se faire la gamme DP quattro au complet. DP0, DP1, DP2, DP3 Quattro. A bient\u00f4t!","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:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/","og_locale":"fr_FR","og_type":"article","og_title":"Le Sigma Foveon &#8212; Visionlarge.ch","og_url":"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/","og_site_name":"Visionlarge.ch","article_modified_time":"2026-04-16T17:13:03+00:00","og_image":[{"width":2560,"height":1750,"url":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Dans-les-forets-du-Jura-2024-scaled.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_site":"@visionlarge","twitter_misc":{"Dur\u00e9e de lecture estim\u00e9e":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/","url":"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/","name":"Le Sigma Foveon &#8212; Visionlarge.ch","isPartOf":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/#website"},"datePublished":"2018-06-09T10:58:41+00:00","dateModified":"2026-04-16T17:13:03+00:00","description":"Mon test des capteurs foveon sur plusieurs mois. J'aurais pour se faire la gamme DP quattro au complet. DP0, DP1, DP2, DP3 Quattro. A bient\u00f4t!","breadcrumb":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.visionlarge.ch\/Blog\/le-sigma-foveon\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.visionlarge.ch\/Blog\/"},{"@type":"ListItem","position":2,"name":"Le Sigma Foveon"}]},{"@type":"WebSite","@id":"https:\/\/www.visionlarge.ch\/Blog\/#website","url":"https:\/\/www.visionlarge.ch\/Blog\/","name":"Bovard Alain, mon blog photo","description":"C&#039;est toujours plus beau en visionlarge...","publisher":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/#\/schema\/person\/b1280adcf8dd414efb101660dca80274"},"alternateName":"visionlarge","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.visionlarge.ch\/Blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":["Person","Organization"],"@id":"https:\/\/www.visionlarge.ch\/Blog\/#\/schema\/person\/b1280adcf8dd414efb101660dca80274","name":"Visionlarge","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g","caption":"Visionlarge"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/5a4cf7a2f94117044ce51a4d732d4e9e02f76cc87fa0508945a18215c8a0613b?s=96&d=mm&r=g"},"sameAs":["http:\/\/www.visionlarge.ch\/Blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/pages\/4120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/comments?post=4120"}],"version-history":[{"count":52,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/pages\/4120\/revisions"}],"predecessor-version":[{"id":12087,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/pages\/4120\/revisions\/12087"}],"wp:attachment":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/media?parent=4120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}