{"id":16,"date":"2011-10-29T17:44:04","date_gmt":"2011-10-29T16:44:04","guid":{"rendered":"http:\/\/www.visionlarge.ch\/Blog\/?page_id=16"},"modified":"2026-04-22T18:25:55","modified_gmt":"2026-04-22T17:25:55","slug":"gallerie-photos","status":"publish","type":"page","link":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/","title":{"rendered":"A propos de moi"},"content":{"rendered":"\n<p class=\"has-text-align-center wp-block-paragraph\"><strong><em>C&rsquo;est tellement plus beau en Vision Large!<\/em><\/strong><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"533\" height=\"800\" src=\"http:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg\" alt=\"Moi\" class=\"wp-image-1022\" srcset=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg 533w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi-199x300.jpg 199w\" sizes=\"auto, (max-width: 533px) 100vw, 533px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><strong>Bienvenue sur mon blog photo !<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Je ne suis pas photographe professionnel. J&rsquo;aime la photographie comme une passion, un passe-temps qui me lib\u00e8re du monde stressant que l&rsquo;on nous impose aujourd&rsquo;hui. J&rsquo;aime l&rsquo;image. Cet instant vol\u00e9, fig\u00e9 \u00e0 jamais. Une fraction de temps \u00e0 un moment X.<br \/>Vous pouvez aimer ou d\u00e9tester ce que je fais, l&rsquo;image ne peut plaire \u00e0 tout le monde&#8230; Je le fais avant tout pour moi, mais l&rsquo;image se partage, autrement elle ne veut rien dire&#8230; <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vous n&rsquo;aimez pas&#8230; Tant pis, on ne peut pas plaire \u00e0 tout le monde. Il y a tellement de photographes sur les r\u00e9seaux que vous trouverez bien votre \u00ab\u00a0kiffe\u00a0\u00bb quelque part sur un r\u00e9seau ou un blog \ud83d\ude09<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>La photographie, une passion de longue date<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La photographie fait partie de ma vie depuis que je suis tout jeune, gr\u00e2ce \u00e0 un r\u00e9flex argentique que mon p\u00e8re m\u2019avait transmis, il y a bien longtemps. Rapidement, cette passion est devenue une v\u00e9ritable passion. Mais pourtant, comme souvent, le temps m\u2019a \u00e9loign\u00e9 de cet art.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><a href=\"https:\/\/www.visionlarge.ch\/Blog\/galerie-au-moyen-format-argentique\/\">Mes d\u00e9buts argentiques<\/a><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">J\u2019ai eu l\u2019occasion d\u2019explorer divers appareils au fil des ann\u00e9es : du Rolleiflex 4\u00d74 (avec ses films quasi introuvables), au Rolleicord Vb 2 et <a href=\"https:\/\/www.visionlarge.ch\/Blog\/mon-avis-sur-le-yashica-mat-124\/\">Yashica Mat 124<\/a>, tous deux en 6\u00d76. Comme beaucoup, avant ces merveilleux bo\u00eetiers moyen format, je poss\u00e9dais un petit Canon argentique AE-1 Program et ses petites optiques FD. Mais le co\u00fbt du d\u00e9veloppement et des films m\u2019a pouss\u00e9 \u00e0 basculer vers l\u2019\u00e8re num\u00e9rique.<\/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\/LeaAu6x6-scaled.jpg\"\n                         alt=\"Concentr\u00e9e sur son dessin de Bill. Je n&#039;ai pas r\u00e9sist\u00e9 \u00e0 l&#039;envie de l&#039;immortaliser au Rolleicord Vb (6x6) et une Tmax 400.\"\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;\">Image \u00e0 l&rsquo;argentique<\/p>\n                                                <p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">Yashica mat 124 et Tmax 400<\/p>\n                                                                <p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">Concentr\u00e9e sur son dessin de Bill. Je n&#039;ai pas r\u00e9sist\u00e9 \u00e0 l&#039;envie de l&#039;immortaliser au Rolleicord Vb (6x6) et une Tmax 400.<\/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: 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-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\\\/LeaAu6x6-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/LeaAu6x6-scaled.jpg\",\"alt\":\"Concentr\\u00e9e sur son dessin de Bill. Je n&#039;ai pas r\\u00e9sist\\u00e9 \\u00e0 l&#039;envie de l&#039;immortaliser au Rolleicord Vb (6x6) et une Tmax 400.\",\"title\":\"Image \\u00e0 l&rsquo;argentique\",\"caption\":\"Yashica mat 124 et Tmax 400\",\"description\":\"Concentr\\u00e9e sur son dessin de Bill. Je n&#039;ai pas r\\u00e9sist\\u00e9 \\u00e0 l&#039;envie de l&#039;immortaliser au Rolleicord Vb (6x6) et une Tmax 400.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/yverdon_12430410143_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/yverdon_12430410143_o.jpg\",\"alt\":\"J&#039;ai du m&#039;y prendre \\u00e0 plusieurs reprises pour arriver \\u00e0 prendre les nuages et le mouvement de l&#039;eau. Il n&#039;y a pas toujours les bonnes conditions. Malgr\\u00e9 que c&#039;est Yverdon ;) Image prise au Yashica mat 124 et une Tmax 400. Ici pause pus longue.\",\"title\":\"Belv\\u00e9d\\u00e8re d&rsquo;Yverdon sous la pluie\",\"caption\":\"Yashica mat 124 et Tmax 400\",\"description\":\"J\\u2019ai d\\u00fb m\\u2019y reprendre \\u00e0 plusieurs fois pour r\\u00e9ussir \\u00e0 capturer les nuages et le mouvement de l\\u2019eau. Les conditions ne sont pas toujours id\\u00e9ales, m\\u00eame \\u00e0 Yverdon ;) Photo prise avec un Yashica Mat-124 et une pellicule T-Max 400. Ici pause pus longue.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/epfl_14353143445_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/epfl_14353143445_o.jpg\",\"alt\":\"Quand on fait un peu de photo... On fini toujours par passer par le Rolex learning Center pour son architecture et ses lumi\\u00e8res le soir. Impossible de ne pas passer avec mon 6x6 argentique.\",\"title\":\"Rolex Learning center au 6&#215;6\",\"caption\":\"Yashica mat 124 et Ektar 100\",\"description\":\"Quand on fait un peu de photo... On fini toujours par passer par le Rolex learning Center pour son architecture et ses lumi\\u00e8res le soir. Impossible de ne pas passer avec mon 6x6 argentique.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/in-the-forest-last-week_37751582036_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/in-the-forest-last-week_37751582036_o.jpg\",\"alt\":\"photo au 6x6 argentique couleurs Ektar 100 en for\\u00eat\",\"title\":\"in-the-forest-last-week\",\"caption\":\"Yashica mat 124\",\"description\":\"J&#039;adore cette image. C&#039;est une de mes premi\\u00e8re belle image au 6x6 argentique en couleurs. Elle est bien sur, depuis longtemps de ma salon sur un tableau en 60x60cm\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/foret-de-brume-pres-de-mauborget_24795144067_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/foret-de-brume-pres-de-mauborget_24795144067_o.jpg\",\"alt\":\"photo au 6x6 argentique couleurs Ektar 100 en for\\u00eat\",\"title\":\"Fore\\u0302t de Brume\",\"caption\":\"Fore\\u0302t de brume\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/neige-sur-la-plaine_39396788902_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/neige-sur-la-plaine_39396788902_o.jpg\",\"alt\":\"photo au 6x6 argentique couleurs Ektar 100 en for\\u00eat\",\"title\":\"Neige sur la colline de Chamblon\",\"caption\":\"Yashica mat 124\",\"description\":\"D\\u00e8s que j&#039;ai vu la neige tomb\\u00e9. Je n&#039;ai pas r\\u00e9sist\\u00e9 \\u00e0 prendre cette image au 6x6. Je savais que l&#039;endroit \\u00e9tait parfait pour composer en format carr\\u00e9. A la base, elle est prise \\u00e0 L&#039;Ektar 100\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/venise_14014171617_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/venise_14014171617_o.jpg\",\"alt\":\"Les canaux de Venise pris \\u00e0 l&#039;argentique 6x6 bi-objectifs.\",\"title\":\"Venise \\u00e0 l&rsquo;argentique\",\"caption\":\"Rolleicord VB2\",\"description\":\"Les canaux de Venise, captur\\u00e9s en argentique 6x6 avec un bo\\u00eetier bi-objectifs.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/For\\u00eatBrumeJuraPetitArbr2036.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/For\\u00eatBrumeJuraPetitArbr2036.jpg\",\"alt\":\"Photo argentique au 6x6 Ektar 100 de la for\\u00eat en hiver\",\"title\":\"Brume en fore\\u0302t\",\"caption\":\"Yashica mat 124 et Ektar 100\",\"description\":\"J&#039;aime me ballader dans les for\\u00eats \\u00e0 la fin de l&#039;automne. Lorsque l&#039;hiver et l&#039;automne se croise. Cela donne des ambiances magiques.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/la-tine-au-rollei-suite_12134411773_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/la-tine-au-rollei-suite_12134411773_o.jpg\",\"alt\":\"Photo au 6x6 argentique noir et blanc \\u00e0 la chute de la tine de conflens dans le canton de Vaud.\",\"title\":\"la-tine-au-rollei-suite_12134411773_o\",\"caption\":\"Yashica mat 124 et Tmax 400\",\"description\":\"Photo au 6x6 argentique noir et blanc \\u00e0 la chute de la tine de conflens dans le canton de Vaud.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/15860094801_27dcb327ea_b.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/15860094801_27dcb327ea_b.jpg\",\"alt\":\"norlfolk terrier\",\"title\":\"Doudou\",\"caption\":\"Doudou 2000-2015\",\"description\":\"\"}];\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   = 5 * 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 class=\"wp-block-paragraph\"><strong>Retour au num\u00e9rique et d\u00e9couverte du panoramique<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mon grand retour \u00e0 la photographie s\u2019est produit dans les ann\u00e9es 2000, avec l\u2019achat d\u2019un Canon EOS 300D, puis d\u2019un EOS 30D, plus adapt\u00e9. Parall\u00e8lement, ma curiosit\u00e9 m\u2019a conduit \u00e0 fabriquer ma propre t\u00eate <a href=\"https:\/\/www.visionlarge.ch\/Blog\/galerie-de-photos-panoramiques\/\">panoramique<\/a>, marquant ainsi mes d\u00e9buts dans la photographie panoramique par assemblage. J\u2019ai commenc\u00e9 avec des calques sous Photoshop, avant d\u2019adopter le logiciel Autopano Pro de Kolor. La partie m\u00e9canique de la t\u00eate panoramique a \u00e9t\u00e9 am\u00e9lior\u00e9e jusqu&rsquo;\u00e0 devenir une belle t\u00eate r\u00e9alis\u00e9e \u00e0 la CNC.<\/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\/ChamonixFrance2025-42-Panorama-scaled.jpg\"\n                         alt=\"Rochers de Fiz avec tout au fond \u00e0 gauche, en petit, le D\u00e9sert de Plat\u00e9. La vue \u00e9tait vraiment magnifique.\"\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;\">Rochers de Fiz<\/p>\n                                                <p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">Canon EOS R, Canon 24-105 F4 L IS<\/p>\n                                                                <p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">Rochers de Fiz avec tout au fond \u00e0 gauche en petit le D\u00e9sert de Plat\u00e9. La vue \u00e9tait vraiment magnifique.<\/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: 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-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\\\/ChamonixFrance2025-42-Panorama-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ChamonixFrance2025-42-Panorama-scaled.jpg\",\"alt\":\"Rochers de Fiz avec tout au fond \\u00e0 gauche, en petit, le D\\u00e9sert de Plat\\u00e9. La vue \\u00e9tait vraiment magnifique.\",\"title\":\"Rochers de Fiz\",\"caption\":\"Canon EOS R, Canon 24-105 F4 L IS\",\"description\":\"Rochers de Fiz avec tout au fond \\u00e0 gauche en petit le D\\u00e9sert de Plat\\u00e9. La vue \\u00e9tait vraiment magnifique.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/PointeDAIAu30D-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/PointeDAIAu30D-scaled.jpg\",\"alt\":\"Alpes suisses dans la brume au cr\\u00e9puscule. On voit au loin les pointes d\\u2019AI (non\\u202f! ce n\\u2019est pas de l\\u2019IA\\u202f!!). Les couleurs et la lumi\\u00e8re \\u00e9taient juste magnifiques\\u202f!\\u202f\",\"title\":\"Alpes suisse dans la brume au cr\\u00e9puscule\",\"caption\":\"Canon EOS 30D, Canon 135 F2 L USM\",\"description\":\"Alpes suisses dans la brume au cr\\u00e9puscule. On voit au loin les pointes d\\u2019AI (non\\u202f! ce n\\u2019est pas de l\\u2019IA\\u202f!!). Les couleurs et la lumi\\u00e8re \\u00e9taient juste magnifiques\\u202f!\\u202f\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/LumiereSurLePlateauVaudois-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/LumiereSurLePlateauVaudois-scaled.jpg\",\"alt\":\"Lumi\\u00e8re de fin de journ\\u00e9e sur le plateau vaudois et Yverdon Panorama sur les alpes et le lac de Neuch\\u00e2tel. Je l&#039;ai pris depuis le petit village de Villars-Burquin.\",\"title\":\"Lumi\\u00e8re sur le plateau vaudois\",\"caption\":\"Canon EOS R et RF 24-105 F4 L IS\",\"description\":\"Lumi\\u00e8re de fin de journ\\u00e9e sur le plateau vaudois et Yverdon. Panorama sur les alpes et le lac de Neuch\\u00e2tel. Je l&#039;ai pris depuis le petit village de Villars-Burquin.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/IMG_0873_DxO-copie-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/IMG_0873_DxO-copie-scaled.jpg\",\"alt\":\"CGN sur le lac L\\u00e9man, automne. Suisse\",\"title\":\"CGN sur le lac L\\u00e9man, automne\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"CGN sur le lac L\\u00e9man depuis les belles vignes du Lavaux. J&#039;aime la composition de l&#039;image.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Contraste-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Contraste-scaled.jpg\",\"alt\":\"CGN sur le lac L\\u00e9man au couch\\u00e9 du soleil\",\"title\":\"CGN sur le lac L\\u00e9man au couch\\u00e9 du soleil\",\"caption\":\"Canon EOS M50\",\"description\":\"CGN sur le lac L\\u00e9man au couch\\u00e9 du soleil. J&#039;aime le d\\u00e9grad\\u00e9 des teintes, le bateaux dans une esp\\u00e8ce d&#039;ombre chinoise. J&#039;adore cette image!\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Panorama_Montagne_Zermatt-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Panorama_Montagne_Zermatt-scaled.jpg\",\"alt\":\"Zermat, Gornergrat\",\"title\":\"Panorama_Montagne_Zermatt\",\"caption\":\"Canon M50 et (je crois) le Canon 11-22 EFM. Image panoramique.\",\"description\":\"Glacier du Gorner depuis la vue du Gornergrat. Un des 3-4 plus grand glacier de Suisse. La vue est exceptionnelle.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Vignes2.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Vignes2.jpg\",\"alt\":\"Le Lavaux et ses vignes\",\"title\":\"Vignes du Lavaux\",\"caption\":\"Canon EOS M50 et Sigma 56f1.4 (qui est une perle en passant\\u2026 )\",\"description\":\"Prise de vue panoramique des vignes du Lavaux. Les nuages cr\\u00e9ent des halos d\\u2019ombres qui cr\\u00e9ent des taches de contrastes. J\\u2019aime beaucoup cette image. M\\u00eame si elle est un peu banale.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Couch\\u00e9DeSoleilF\\u00e9vrierChexbres2020.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Couch\\u00e9DeSoleilF\\u00e9vrierChexbres2020.jpg\",\"alt\":\"Couch\\u00e9 de soleil depuis Chexbres\",\"title\":\"Couch\\u00e9 de soleil depuis Chexbres\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"Parfois la chance permet d&#039;immortaliser de magnifiques instants de nature. Au mois de f\\u00e9vrier, il y a souvent de magnifiques couch\\u00e9s de soleil sur le L\\u00e9man. Depuis Chexbres, c&#039;est souvent un magnifique spectacle.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/yverdon-belles-couleurs-du-matin-sur-le-lac-de-neuchtel_11818472036_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/yverdon-belles-couleurs-du-matin-sur-le-lac-de-neuchtel_11818472036_o.jpg\",\"alt\":\"Belles couleurs du matin au lev\\u00e9 du soleil \\u00e0 Yverdon et tous ses reflets\",\"title\":\"Thi\\u00e8le, Yverdon\",\"caption\":\"Canon 5D MK II et Canon EF 70-200 F4 L USM\",\"description\":\"Belles couleurs du matin au lev\\u00e9 du soleil \\u00e0 Yverdon et tous ses reflets. Panorama\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/couch-de-soleil_15980128118_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/couch-de-soleil_15980128118_o.jpg\",\"alt\":\"Couch\\u00e9 de soleil pr\\u00e8s de Baumes dans la brume en suisse\",\"title\":\"Pr\\u00e8s de Baumes\",\"caption\":\"Canon 5D MK II et Canon EF 60-200 F4 L USM \",\"description\":\"Magnfigique couche de soleil sur le Jura. Prise de vue depuis le village de Baumes.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/vatican_16687869086_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/vatican_16687869086_o.jpg\",\"alt\":\"Place du vatican en panorama et noir et blanc au fujifilm X100T\",\"title\":\"Vatican\",\"caption\":\"Fujifilm X100T\",\"description\":\"Sur la c\\u00e9l\\u00e8bre place Sainte-Pierre du Vatican. Architecture incroyable et lieu symbolique.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/orage-de-fin-de-journe_14482931205_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/orage-de-fin-de-journe_14482931205_o.jpg\",\"alt\":\"Orage de fin de journ\\u00e9e et son rideau de pluie en fin de journ\\u00e9e\",\"title\":\"Orage de fin de journ\\u00e9e\",\"caption\":\"Canon EOS et Canon EF 70-200 F4 L USM\",\"description\":\"Je le voyais arriver de loin. Un orage immense, un extraordinaire rideau de pluie. Je me suis mis en haut des vignes pr\\u00e8s de Concise. Une vue incroyable et une petite frayeur lorsqu\\u2019il m\\u2019a pass\\u00e9 par dessus!\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/la-tour-deau-de-goumoens_5400642155_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/la-tour-deau-de-goumoens_5400642155_o.jpg\",\"alt\":\"La tour d&#039;eau de Goumoens pr\\u00e8s de Penth\\u00e9r\\u00e9az au couch\\u00e9 du soleil\",\"title\":\"Goumoens\",\"caption\":\"Canon EOS\",\"description\":\"La tour d&#039;eau de Goumoens pr\\u00e8s de Penth\\u00e9r\\u00e9az au couch\\u00e9 du soleil\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/sur-la-route-de-wesport_28301925593_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/sur-la-route-de-wesport_28301925593_o.jpg\",\"alt\":\"sur la route de Wesport en Irlande\",\"title\":\"Sur la route de Wesport\",\"caption\":\"Canon EOS 5D MK II et Canon 17-40 F4 L USM\",\"description\":\"Sur la route en direction de Wesport, nous tombons sur un paysage magnifique digne de l\\u2019Irlande.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/doolin-beach-under-the-rain_28857810573_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/doolin-beach-under-the-rain_28857810573_o.jpg\",\"alt\":\"La plage de Doolin sous la pluie en Irlande\",\"title\":\"La plage de Doolin\",\"caption\":\"Canon 5D MK II et Canon EF 17-40 F4 L\",\"description\":\"La plage de Doolin. On voit au loin les c\\u00e9l\\u00e8bres falaises des cliffs of Moher. Le dernier rempart au assaux de l\\u2019oc\\u00e9an\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/in-the-road_29313945622_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/in-the-road_29313945622_o.jpg\",\"alt\":\"Sur la route en Irlande\",\"title\":\"Ireland, In the road\",\"caption\":\"Canon 5D MK II et Canon 17-40 F4 L USM \",\"description\":\"Paysage d\\u2019Irlande et ses milles tons de vert. J\\u2019adore l\\u2019Irlande pour ses paysages brutes.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/dingle_29016377301_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/dingle_29016377301_o.jpg\",\"alt\":\"Sur la baie de Dingle en Irlande et ses paddles\",\"title\":\"Dans la baie de Dingle\",\"caption\":\"Canon EOS\",\"description\":\"Dans la baie des Dingle en Irlande. M\\u00eame avec un vent et une eau glaciale. Le paddle fait partie des attractions.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/le-chemin-des-lumieres_30949098211_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/le-chemin-des-lumieres_30949098211_o.jpg\",\"alt\":\"Chemin de lumi\\u00e8res dans la for\\u00eat automnale\",\"title\":\"le-chemin-des-lumieres_30949098211_o\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/vue-des-alpes_45591490545_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/vue-des-alpes_45591490545_o.jpg\",\"alt\":\"Vue des Alpes \\u00e0 Mauborget au coucher du soleil\",\"title\":\"Vue des Alpes \\u00e0 Mauborget\",\"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\\\/le-barrage-demosson_45628752922_o.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\\\/du-standard_48102317421_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/du-standard_48102317421_o.jpg\",\"alt\":\"Panoramique de la chute de la Tine de Conflens\",\"title\":\"Panoramique de la chute de la Tine de Conflens\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"La chute de la Tine de Conflens est une petite perle de nature.  J&#039;attendais depuis quelques temps l&#039;occasion de l&#039;immortaliser avec un gros d\\u00e9bit d&#039;eau. C&#039;est une de mes images pr\\u00e9f\\u00e9r\\u00e9es.\"}];\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   = 5 * 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 class=\"wp-block-paragraph\"><strong><a href=\"https:\/\/www.visionlarge.ch\/Blog\/category\/images-spheriques-2\/\">La photo 360\u00b0, une nouvelle passion<\/a><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pendant plusieurs ann\u00e9es, m\u00e9langeant conception m\u00e9canique et photographie, j\u2019ai relev\u00e9 de gros challenges, notamment lors de prises de vue en 360\u00b0. Cette discipline est rapidement devenue une v\u00e9ritable passion. Parmi mes plus grandes fiert\u00e9s, j\u2019ai pu couvrir le <a href=\"https:\/\/www.visionlarge.ch\/Blog\/le-grand-raid\/\">Grand Raid VTT en 2009<\/a> et 2010 avec un reportage in\u00e9dit en 360\u00b0, me permettant de vivre au plus pr\u00e8s cette course mythique.<\/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\/MorrensChene1petit.jpg\"\n                         alt=\"Le grand ch\u00eane de Morrens\"\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;\">MorrensChene1petit<\/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: 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-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: 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-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\\\/MorrensChene1petit.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/MorrensChene1petit.jpg\",\"alt\":\"Le grand ch\\u00eane de Morrens\",\"title\":\"MorrensChene1petit\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/TourEtJardinDesClees_Equi-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/TourEtJardinDesClees_Equi-scaled.jpg\",\"alt\":\"Tour et jardin des cr\\u00e9\\u00e9es en 360 en Suisse\",\"title\":\"TourEtJardinDesClees_Equi\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Place-Pestalozzi-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Place-Pestalozzi-scaled.jpg\",\"alt\":\"Place Pestalozzi\",\"title\":\"Place Pestalozzi\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Abbatiale-de-Payerne-e1526408617379.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Abbatiale-de-Payerne-e1526408617379.jpg\",\"alt\":\"Abbatiale de Payerne en 360\",\"title\":\"Abbatiale de Payerne\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DepartVerbier_equi-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DepartVerbier_equi-scaled.jpg\",\"alt\":\"Panoramique 360 du d\\u00e9part du Grand Raid \\u00e0 Verbier en Suisse\",\"title\":\"DepartVerbier_equi\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CathedraleFribourgINSTA-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CathedraleFribourgINSTA-scaled.jpg\",\"alt\":\"Cath\\u00e9drale de Fribourg en 360\",\"title\":\"CathedraleFribourgINSTA\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/parasol-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/parasol-scaled.jpg\",\"alt\":\"Le plus grand parasol du monde est \\u00e0 Bavois en Suisse\",\"title\":\"Le plus grand parasol du monde\",\"caption\":\"Canon EOS 300 D et Tokina 10-17\",\"description\":\"Le plus grand parasol du monde est \\u00e0 Bavois en Suisse\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Louvre2.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Louvre2.jpg\",\"alt\":\"Place du Louvre en 360 \\u00e0 Paris\",\"title\":\"Place du Louvre en 360 \\u00e0 Paris\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/NeigeArbre2.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/NeigeArbre2.jpg\",\"alt\":\"Pr\\u00e8s du lac \\u00e0 Yverdon sous la neige en 360\",\"title\":\"NeigeArbre2\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lausanne-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/lausanne-scaled.jpg\",\"alt\":\"En haut de la cath\\u00e9drale de Lausanne en Suisse en 360\",\"title\":\"En haut de la cath\\u00e9drale de Lausanne\",\"caption\":\"Canon EOS et Tokina 10-17\",\"description\":\"Sur le haut de la cath\\u00e9drale de la ville de Lausanne. Je suis l\\u00e0 pour r\\u00e9aliser un 360VR des toits de la ville et des sommets de la cath\\u00e9drale ;-)\"}];\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   = 5 * 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 class=\"wp-block-paragraph\"><strong>L\u2019argentique, un appel toujours pr\u00e9sent<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Malgr\u00e9 le num\u00e9rique, l\u2019appel de l\u2019argentique est rest\u00e9 fort. En 2025, je continue \u00e0 utiliser les films argentiques pour certains projets sp\u00e9cifiques, trouvant ce proc\u00e9d\u00e9 toujours aussi magique. Sur ce blog, vous trouverez des images r\u00e9alis\u00e9es avec des films 120 mm (ou 56&#215;56 mm), ainsi que des photos prises avec mes appareils num\u00e9riques. Ces derni\u00e8res ann\u00e9es, je me suis particuli\u00e8rement concentr\u00e9 sur la photographie de paysage, Mais aussi avec un <a href=\"https:\/\/www.visionlarge.ch\/Blog\/instantanes-dauthenticite-les-artisans-du-nord-vaudois-en-lumiere\/\">projet de reportage qui se dessine<\/a> doucement.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aujourd&rsquo;hui, je touche \u00e0 tous les formats. Je n&rsquo;ai pas un format sp\u00e9cifique, fini le panorama \u00e0 tout va!<br \/>Je m&rsquo;amuse avec tout, je fais ce que j&rsquo;ai envie. Sans pression et sans me prendre la t\u00eate. Vive, le Pano, le 24&#215;36, l&rsquo;argentique et le 360!<\/p>\n\n\n\n    \n        <div class=\"vl-slider-wrap\" id=\"vl-slider-inst4-wrap\">\n\n                        \n                <div id=\"vl-slider-inst4\"\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\/IrlandeMoher-scaled.jpg\"\n                         alt=\"Les c\u00e9l\u00e8bres falaises de Moher en Irlande sont \u00e0 couper le souffle. Un panorama incroyable sur ses murs immenses faisant face \u00e0 l&#039;ocean. Il n&#039;y aura plus rien devant elles avant l&#039;Am\u00e9rique.\"\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-inst4-below-wrap\"\n             style=\"display:none;opacity:0;\">\n                        <div class=\"vl-slider-below-text\"\n                 id=\"vl-slider-inst4-below-0\">\n                                <p class=\"vl-sl-title\" style=\"font-weight:bold;font-style:normal;\">Irlande et falaises de Moher<\/p>\n                                                <p class=\"vl-sl-caption\" style=\"font-style:italic;font-weight:normal;\">Canon EOS 5D MK II, Canon 17-40 f4 L<\/p>\n                                                                <p class=\"vl-sl-description\" style=\"font-style:normal;font-weight:normal;\">Les c\u00e9l\u00e8bres falaises de Moher, en Irlande, sont \u00e0 couper le souffle. Un panorama incroyable sur ces murs immenses, dress\u00e9s face \u00e0 l\u2019oc\u00e9an. Devant eux, plus rien jusqu\u2019\u00e0 l\u2019Am\u00e9rique.<\/p>\n                            <\/div>\n                    <\/div>\n\n                        <div class=\"vl-sl-toggle-wrap\" id=\"vl-slider-inst4-toggle-wrap\">\n            <button class=\"vl-sl-toggle-btn\"\n                    id=\"vl-slider-inst4-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-inst4-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-inst4-lb-counter\"\n                      aria-live=\"polite\"><\/span>\n                <button class=\"vl-sl-lb-close\"\n                        id=\"vl-slider-inst4-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-inst4-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-inst4-lb-progress\"><\/div>\n                    <\/div>\n                    <img decoding=\"async\" src=\"\" alt=\"\"\n                         id=\"vl-slider-inst4-lb-img\"\n                         class=\"vl-sl-lb-img\">\n                                        <div class=\"vl-sl-lb-caption\"\n                         id=\"vl-slider-inst4-lb-caption\"\n                         aria-live=\"polite\"><\/div>\n                <\/div>\n\n                <button class=\"vl-sl-lb-next\"\n                        id=\"vl-slider-inst4-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-inst4-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-inst4-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-inst4-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-inst4-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-inst4 {\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-inst4 .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-inst4 .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-inst4 .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-inst4 .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-inst4 .vl-slider-img-active { opacity: 1; }\n        \/* Image suivante : invisible (opacity 0), pr\u00eate pour la prochaine transition *\/\n        #vl-slider-inst4 .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-inst4 .vl-slider-slot { cursor: zoom-in; }\n        #vl-slider-inst4 .vl-slider-img-next { pointer-events: none; }\n        #vl-slider-inst4 .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-inst4 .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-inst4 .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-inst4-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-inst4 .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-inst4');\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-inst4-ghost-left');\n            var ghostRight = document.getElementById('vl-slider-inst4-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-inst4-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\\\/IrlandeMoher-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/IrlandeMoher-scaled.jpg\",\"alt\":\"Les c\\u00e9l\\u00e8bres falaises de Moher en Irlande sont \\u00e0 couper le souffle. Un panorama incroyable sur ses murs immenses faisant face \\u00e0 l&#039;ocean. Il n&#039;y aura plus rien devant elles avant l&#039;Am\\u00e9rique.\",\"title\":\"Irlande et falaises de Moher\",\"caption\":\"Canon EOS 5D MK II, Canon 17-40 f4 L\",\"description\":\"Les c\\u00e9l\\u00e8bres falaises de Moher, en Irlande, sont \\u00e0 couper le souffle. Un panorama incroyable sur ces murs immenses, dress\\u00e9s face \\u00e0 l\\u2019oc\\u00e9an. Devant eux, plus rien jusqu\\u2019\\u00e0 l\\u2019Am\\u00e9rique.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/1erAout2025EnfantDevantLeFeu-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/1erAout2025EnfantDevantLeFeu-scaled.jpg\",\"alt\":\"Alors que le feu se consume dans une violence de chaleur et de lumi\\u00e8re intense. Je cherche une fa\\u00e7on de mettre en valeur l&#039;instant. C&#039;est \\u00e0 ce moment que je vois ce papa portant son fils sur les \\u00e9paules en ombre chinoise. J&#039;attend en esp\\u00e9rant qu&#039;il va se produire quelque chose d&#039;int\\u00e9ressant.\",\"title\":\"Premier Ao\\u00fbt.\",\"caption\":\"Fujifilm XS-20, Fujifilm 56 F1.2\",\"description\":\"Alors que le feu se consume dans une violence de chaleur, je cherche une fa\\u00e7on de mettre en valeur l\\u2019instant. C\\u2019est \\u00e0 ce moment que je vois ce papa portant son fils sur les \\u00e9paules en ombre chinoise. J\\u2019attends en esp\\u00e9rant qu\\u2019il va se passer quelque chose d\\u2019int\\u00e9ressant.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/EzeEtLaCoteDAzur2025-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/EzeEtLaCoteDAzur2025-scaled.jpg\",\"alt\":\"\\u00c9t\\u00e9 en C\\u00f4te d&#039;Azur en Mars 2025. Vue depuis le petit village d&#039;Eze ou la vue panoramique est absolument incroyable!\",\"title\":\"Eze et la C\\u00f4te D&rsquo;Azur 2025\",\"caption\":\"Canon EOS M, Canon EFM \",\"description\":\"\\u00c9t\\u00e9 en C\\u00f4te d&#039;Azur en Mars 2025. Vue depuis le petit village d&#039;Eze ou la vue panoramique est absolument incroyable!\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ChanteurGroupeTrashNYverdon2025-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ChanteurGroupeTrashNYverdon2025-scaled.jpg\",\"alt\":\"Pendant le concert du groupe TrashAndCo \\u00e0 Yverdon lors de la f\\u00eate de la musique 2025.\",\"title\":\"Concert de Trash And CO 2025\",\"caption\":\"Canon EOS R, Canon 135 F2 L\",\"description\":\"Pendant le concert du groupe TrashAndCo \\u00e0 Yverdon lors de la f\\u00eate de la musique 2025.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/LacDeJoux2024-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/LacDeJoux2024-scaled.jpg\",\"alt\":\"Panorama de plusieurs images assembl\\u00e9es de la petite ville du Pont. Les petites maisons de couleurs se refl\\u00e8tent dans le lac de Joux \\u00e0 l&#039;heure bleue d&#039;un jour d&#039;automne. Un petit bateau de p\\u00eacheurs est en premier plan sur la berge. Le redoutable\",\"title\":\"Le Pont \\u00e0 la vall\\u00e9e de Joux en Suisse\",\"caption\":\"Canon EOS R, Canon RF 24-105 F4 L IS\",\"description\":\"Panorama de plusieurs images assembl\\u00e9es de la petite ville du Pont. Les petites maisons de couleurs se refl\\u00e8tent dans le lac de Joux \\u00e0 l&#039;heure bleue d&#039;un jour d&#039;automne. Un petit bateau de p\\u00eacheurs est en premier plan sur la berge. Le redoutable\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Menton2025LesEscaliers-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Menton2025LesEscaliers-scaled.jpg\",\"alt\":\"Les c\\u00e9l\\u00e8bres escaliers de la ville de Menton en France.\",\"title\":\"Menton. 2025. LesEscaliers\",\"caption\":\"Iphone 15\",\"description\":\"Les c\\u00e9l\\u00e8bres escaliers de la ville de Menton, en France.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DansLesBoisEnAutomne2024-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DansLesBoisEnAutomne2024-scaled.jpg\",\"alt\":\"J\\u2019aime me promener dans les for\\u00eats toute l\\u2019ann\\u00e9e. J\\u2019aime la nature, les arbres, l\\u2019odeur de la for\\u00eat et les bruits subtils qui rappellent que la vie n\\u2019est jamais loin, simplement parfois cach\\u00e9e de nous. J\\u2019aime aussi ses jeux de couleurs et de lumi\\u00e8res. D\\u00e9tails du tronc en premier plan.\",\"title\":\"For\\u00eat d&rsquo;automne\",\"caption\":\"Canon EOS R et RF 70-200 F4 L IS\",\"description\":\"J\\u2019aime me promener dans les for\\u00eats toute l\\u2019ann\\u00e9e. J\\u2019aime la nature, les arbres, l\\u2019odeur de la for\\u00eat et les bruits subtils qui rappellent que la vie n\\u2019est jamais loin, simplement parfois cach\\u00e9e de nous. J\\u2019aime aussi ses jeux de couleurs et de lumi\\u00e8res. D\\u00e9tails du tronc en premier plan.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/RefletDautomne-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/RefletDautomne-scaled.jpg\",\"alt\":\"Etang du Seppey, Cossonay\",\"title\":\"Etang du Seppey, Cossonay\",\"caption\":\"Canon EOS R et Canon 17-40 F4 L USM\",\"description\":\"Etang du Seppey, Cossonay. J&#039;avais vu le reflet de cet arbre d\\u00e9j\\u00e0 depuis quelques temps. C&#039;\\u00e9tait le moment de l&#039;immortaliser ;-)\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DansLesBoisAutomne-2024-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DansLesBoisAutomne-2024-scaled.jpg\",\"alt\":\"J\\u2019\\u00e9tais d\\u00e9j\\u00e0 venu, il y a quelques mois, dans cette for\\u00eat. J\\u2019avais ador\\u00e9 cette petite cabane perdue dans les bois. Il me fallait juste trouver une autre mani\\u00e8re de la mettre en valeur, en plus des belles ambiances automnales. J\\u2019aime bien les troncs sur le c\\u00f4t\\u00e9, qui guident vers la cabane. Cette fa\\u00e7on de \\u00ab couper l\\u2019image en deux \\u00bb qui permet de mettre en \\u00e9vidence l\\u2019ambiance automnale.\",\"title\":\"Cabane dans les bois\",\"caption\":\"Canon EOS R, Canon RF 24-105 F4 L\",\"description\":\"J\\u2019\\u00e9tais d\\u00e9j\\u00e0 venu, il y a quelques mois, dans cette for\\u00eat. J\\u2019avais ador\\u00e9 cette petite cabane perdue dans les bois. Il me fallait juste trouver une autre mani\\u00e8re de la mettre en valeur, au-del\\u00e0 des belles ambiances automnales. J\\u2019aime bien les troncs sur le c\\u00f4t\\u00e9, qui guident le regard vers la cabane. Cette fa\\u00e7on de \\u00ab couper l\\u2019image en deux \\u00bb permet de mettre en \\u00e9vidence toute l\\u2019atmosph\\u00e8re de l\\u2019automne.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Dans-les-forets-du-Jura-2024-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Dans-les-forets-du-Jura-2024-scaled.jpg\",\"alt\":\"Petit tour dans la brume sur les hauts du Jura vaudois en Suisse. J&#039;aime me promener dans le brouillard. J&#039;aime les mouvement de cette brume qui modifie le paysage chaque seconde. J&#039;adore cet arbre et ses branches qui s&#039;entrem\\u00ealent.\",\"title\":\"Arbre f\\u00e9\\u00e9rique\",\"caption\":\"Canon EOS R, Canon RF 24-105 F4 L IS\",\"description\":\"Petit tour dans la brume sur les hauts du Jura vaudois en Suisse. J&#039;aime me promener dans le brouillard. J&#039;aime les mouvement de cette brume qui modifie le paysage chaque seconde. J&#039;adore cet arbre et ses branches qui s&#039;entrem\\u00ealent.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/arbremathod.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/arbremathod.jpg\",\"alt\":\"Barri\\u00e8re pr\\u00e8s de Mathod. Suisse.\",\"title\":\"Barri\\u00e8re pr\\u00e8s de Mathod.\",\"caption\":\"Canon EOS 5D MKII et Canon 135 F2 L USM\\nAssemblage de plusieurs images.\",\"description\":\"J\\u2019adore cette image r\\u00e9alis\\u00e9e il y a longtemps en cherchant une all\\u00e9e d\\u2019arbres. Je l\\u2019ai r\\u00e9alis\\u00e9e en prenant une bonne vingtaine d\\u2019image \\u00e0 f2 sur mon 135 et en les assemblant\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Dans-la-brume-dautomne-dans-le-Jura-2024.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Dans-la-brume-dautomne-dans-le-Jura-2024.jpg\",\"alt\":\"Petit tour dans la brume sur les hauts du Jura vaudois en Suisse. J&#039;aime me promener dans le brouillard. J&#039;aime les mouvement de cette brume qui modifie le paysage chaque seconde.\",\"title\":\"Sous la brume du Jura\",\"caption\":\"Canon EOS R, Canon RF 24-105 F4 L IS\",\"description\":\"Petite marche dans la brume sur les hauteurs du Jura vaudois, en Suisse. J\\u2019aime m\\u2019y perdre dans le brouillard, quand le monde se dissout doucement autour de moi. Les mouvements de la brume redessinent le paysage \\u00e0 chaque instant, comme si la montagne respirait et changeait de visage sous mes pas.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/contemplation_39849609594_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/contemplation_39849609594_o.jpg\",\"alt\":\"Contemplation \\u00e0 Amsterdam\",\"title\":\"Contemplation\",\"caption\":\"Canon G7X MK II\",\"description\":\"Au mus\\u00e9e Rijksmuseum d&#039;Amsterdam.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/EOSR4124-Modifier-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/EOSR4124-Modifier-scaled.jpg\",\"alt\":\"J\\u2019ai rencontr\\u00e9 ces pirates dans les petites gorges de la Tine de Conflens, l\\u00e0 o\\u00f9 se trouvent les c\\u00e9l\\u00e8bres chutes du m\\u00eame nom. Ils m\\u2019ont fait le plaisir de se laisser photographier.\",\"title\":\"Pirates \\u00e0 la Chute de la Tine de Conflens\",\"caption\":\"Canon EOS R, Canon 24-105 F4 L IS \",\"description\":\"J\\u2019ai rencontr\\u00e9 ces pirates dans les petites gorges de la Tine de Conflens, l\\u00e0 o\\u00f9 se trouvent les c\\u00e9l\\u00e8bres chutes du m\\u00eame nom. Ils m\\u2019ont fait le plaisir de se laisser photographier.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/the-gate_32172395998_o.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\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/BellcourLyonMetro23-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/BellcourLyonMetro23-scaled.jpg\",\"alt\":\"Dans le m\\u00e9tro de Lyon. Ce n&#039;est pas le m\\u00e9tro le plus vaste de France. Mais celui de Bellecourt est vraiment sympa en architecture. Un petite session photo \\u00e9tait obligatoire ;-)\",\"title\":\"Dans le m\\u00e9tro de Lyon, France\",\"caption\":\"Canon EOS M\",\"description\":\"Dans le m\\u00e9tro de Lyon, un r\\u00e9seau certes moins vaste que d\\u2019autres grandes villes fran\\u00e7aises, mais plein de caract\\u00e8re. La station Bellecour se distingue particuli\\u00e8rement par son architecture agr\\u00e9able et son atmosph\\u00e8re singuli\\u00e8re. Une petite session de photographie s\\u2019imposait ;-)\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/petit-petit_32713638430_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/petit-petit_32713638430_o.jpg\",\"alt\":\"malte petite fille en contre jour\",\"title\":\"Dans les rues de Malte\",\"caption\":\"Fujifilm x100T\",\"description\":\"Dans les petites ruelles de la capitale fortifi\\u00e9e de La Valette sur la petite \\u00eele de Malte. C\\u0153ur historique et culturel de Malte, class\\u00e9e \\u00e0 l&#039;UNESCO\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/OnnensEtSonArbreExtraordinaire-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/OnnensEtSonArbreExtraordinaire-scaled.jpg\",\"alt\":\"L\\u2019arbre de Fiez est s\\u00e9lectionn\\u00e9 parmi les arbres extraordinaires de la Suisse. Chaque printemps, ses feuilles jaunes explosent en vert et jaune magnifiques lorsque les rayons du soleil les frappent. Sa situation au pied de l\\u2019\\u00e9glise du village est une v\\u00e9ritable louange \\u00e0 la beaut\\u00e9\",\"title\":\"Fiez et son arbre extraordinaire\",\"caption\":\"Canon EOS R, Canon RF 15-30 STM\",\"description\":\"L\\u2019arbre de Fiez est s\\u00e9lectionn\\u00e9 parmi les arbres extraordinaires de la Suisse. Chaque printemps, ses feuilles jaunes explosent en vert et jaune magnifiques lorsque les rayons du soleil les frappent. Sa situation au pied de l\\u2019\\u00e9glise du village est une v\\u00e9ritable louange \\u00e0 la beaut\\u00e9\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/OrageDAutomne2Nov2023-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/OrageDAutomne2Nov2023-scaled.jpg\",\"alt\":\"Orage d&#039;automne dans le canton de Vaud pr\\u00e8s de Penth\\u00e9r\\u00e9az. La chance est un crit\\u00e8re aussi, parfois d\\u00e9cisif entre une image banale et le Woua.. Et surtout\\u2026 parfois attendre\\u2026 l\\u2019instant. L\\u2019atmosph\\u00e8re\\u2026 Un peu comme un chasseur\\u2026 Mais d\\u2019images.\",\"title\":\"Orage d&rsquo;automne dans le canton de Vaud pr\\u00e8s de Penth\\u00e9r\\u00e9az\",\"caption\":\"Canon EOS R et RF 24-105 F4 L IS\",\"description\":\"La chance est un crit\\u00e8re aussi, parfois d\\u00e9cisif entre une image banale et le Woua.. Et surtout\\u2026 parfois attendre\\u2026 l\\u2019instant, l\\u2019atmosph\\u00e8re\\u2026 Un peu comme un chasseur\\u2026 Mais d\\u2019images.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Oulans2-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Oulans2-scaled.jpg\",\"alt\":\"Couch\\u00e9 de soleil \\u00e0 Oulans, le soleil perse la brume et les branches de l&#039;arbre.\",\"title\":\"Couch\\u00e9 de soleil pr\\u00e8s de Oulans\",\"caption\":\"Canon EOS R et EF 50 f1.4 USM\",\"description\":\"Pr\\u00e8s de petit village de Oulans, un arbre magnifique prend la pose. Sa silhouette se dessine en ombre, impr\\u00e9gn\\u00e9e dans la brume et la lumi\\u00e8re du couchant. La sc\\u00e8ne est magique, po\\u00e9tique. Le temps s\\u2019arr\\u00eate quelques secondes, contemplation\\u2026 puis la nuit,gentiment, s\\u2019empare de l\\u2019instant.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Seville-2023-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Seville-2023-scaled.jpg\",\"alt\":\"Dans la belle ville de S\\u00e9ville\",\"title\":\"Dans la belle ville de S\\u00e9ville\",\"caption\":\"Canon EOS M50 et Canon EFM 11-22 STM\",\"description\":\"Dans la belle ville de S\\u00e9ville. La place d&#039;Espagne. Les ponts qui traversent les petits cours d\\u2019eau sont recouverts des c\\u00e9l\\u00e8bres azul\\u00e9jos de la ville de S\\u00e9ville. Leurs couleurs contrastes avec le rouge pourpre des palais.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Seville-2023-Arches-entree-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Seville-2023-Arches-entree-scaled.jpg\",\"alt\":\"Place d&#039;Espagne \\u00e0 S\\u00e9ville en Espagne\",\"title\":\"S\\u00e9ville 2023 Arches\",\"caption\":\"Canon EOS M50 et Canon EFM 15-45 STM\",\"description\":\"Les arches de la place d\\u2019Espagne \\u00e0 S\\u00e9ville. Un magnfigique endroit dans la ville.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/SienneTower-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/SienneTower-scaled.jpg\",\"alt\":\"En bas de la tour de Sienne en Italie\",\"title\":\"La tour de la place de Sienne.\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"La Torre del Mangia est la c\\u00e9l\\u00e8bre tour m\\u00e9di\\u00e9vale de 88 m\\u00e8tres (102 m avec le paratonnerre ;-) ) situ\\u00e9e sur la Piazza del Campo \\u00e0 Sienne, en Toscane. Vue depuis l&#039;int\\u00e9rieur du b\\u00e2timent atenant.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ArbresDansLaBrume12-copie-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/ArbresDansLaBrume12-copie-scaled.jpg\",\"alt\":\"En for\\u00eat sous la neige\",\"title\":\"En for\\u00eat sous la neige\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"J&#039;avais depuis quelques sorties dans cette for\\u00eat remarqu\\u00e9 cet arbre au couch\\u00e9 du soleil. Je suis donc retourn\\u00e9 un jour ou il avait fortement neig\\u00e9 pour y prendre l&#039;ambiance.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Montreux-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Montreux-scaled.jpg\",\"alt\":\"Montreux\",\"title\":\"Montreux\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"Cette platerforme est tr\\u00e8s connue \\u00e0 Montreux. Quelques fois dans l&#039;ann\\u00e9e, le soleil vient s&#039;aligner avec elle. Pas facile d&#039;y \\u00eatre sans avoir parfois foule...\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CanonEOSR-Foret-magique-Octobre-2020-3.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CanonEOSR-Foret-magique-Octobre-2020-3.jpg\",\"alt\":\"Arbre et son reflet dans l&#039;eau avec ses couleurs d&#039;automne\",\"title\":\"Arbre et son reflet dans l&rsquo;eau\",\"caption\":\"Canon EOS R et Canon EF 24-70 F2.8 L USM II\",\"description\":\"For\\u00eat magique du Seppey et son \\u00e9tang. L\\u2019arbre \\u00e9tait magnifique avec ses couleurs jaunes-vertes et son reflet dans l\\u2019eau. Je n\\u2019ai pas r\\u00e9sist\\u00e9 \\u00e0 essayer de vous la partager.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CanonEOSR-Foret-135-Chamblon.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/CanonEOSR-Foret-135-Chamblon.jpg\",\"alt\":\"Arbre en automne dans la campagne\",\"title\":\"Arbre en automne dans la campagne\",\"caption\":\"Canon EOS R et Canon 135 F2 L USM\",\"description\":\"Un arbre aux teintes automnales, partiellement \\u00e9clair\\u00e9, se d\\u00e9tache avec douceur sur un arri\\u00e8re-plan estomp\\u00e9. L&#039;effet de bokeh renforce l&#039;impression de calme et de s\\u00e9r\\u00e9nit\\u00e9 qui se d\\u00e9gagent de la sc\\u00e8ne.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Rolex-1.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Rolex-1.jpg\",\"alt\":\"Arr\\u00eat de M\\u00e9tro de l&#039;EPFL et ses multiples couleurs\",\"title\":\"Arr\\u00eat de M\\u00e9tro de l&rsquo;EPFL\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"Un des arr\\u00eats tr\\u00e8s sympa du m\\u00e9tro de l\\u2019EPFL. Une ouverture au plafond permet de laisser passer la lumi\\u00e8re. Elle permet de mettre en valeur les tonalit\\u00e9s de couleurs. Il faudrait que j\\u2019y retourne une fois.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Rolex.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Rolex.jpg\",\"alt\":\"Rolex Learning center \\u00e0 Lausanne en Suisse\",\"title\":\"Rolex Learning center\",\"caption\":\"Canon EOS 5D MKII et Canon 17-40 F4 L USM\",\"description\":\"Dans le complexe du Rolex Learning Center de Lausanne. Un des b\\u00e2timents de l&#039;universit\\u00e9 de Lausanne.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/VeveyEtLavauxPensif.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/VeveyEtLavauxPensif.jpg\",\"alt\":\"Couch\\u00e9 de soleil depuis Chexbres en Suisse\",\"title\":\"VeveyEtLavauxPensif\",\"caption\":\"\",\"description\":\"\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Couch\\u00e9DeSoleilF\\u00e9vrierChexbres202024x36Personnes2.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Couch\\u00e9DeSoleilF\\u00e9vrierChexbres202024x36Personnes2.jpg\",\"alt\":\"Couch\\u00e9 de soleil depuis Chexbres en suisse sur le L\\u00e9man\",\"title\":\"Couch\\u00e9 de soleil depuis Chexbres\",\"caption\":\"Canon EOS M50 et Canon 11-22 EFM\",\"description\":\"Parfois la chance permet d&#039;immortaliser de magnifiques instants de nature. Au mois de f\\u00e9vrier, il y a souvent de magnifiques couch\\u00e9s de soleil sur le L\\u00e9man. Depuis Chexbres, c&#039;est souvent un magnifique spectacle.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Montagne.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Montagne.jpg\",\"alt\":\"Mer de nuages au dessus de la plaine vaudoise et vue du les alpes suisse au couch\\u00e9 du soleil\",\"title\":\"Montagne depuis Mauborget. Suisse. 5Dmkii\",\"caption\":\"Canon EOS 5D MKII et Canon EF 70-200 F4 L USM\",\"description\":\"Les Alpes \\u00e9mergent des nuages. Bient\\u00f4t, la nuit prendra place. Mais je prendre temps de profiter de cette belle lumi\\u00e8re et des ses montagnes incroyables.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Automne2.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/Automne2.jpg\",\"alt\":\"Couleurs d&#039;automne\",\"title\":\"Couleurs d&rsquo;automne\",\"caption\":\"Canon EOS G7X MK II\",\"description\":\"Le lac du barrage d&#039;Emosson en Suisse. Ici les m\\u00e9l\\u00e8zes ont rev\\u00eatu leurs couleurs de l&#039;automne. J&#039;aime le reflet dans le lac noir et la lumi\\u00e8re qui gentiment part de la vall\\u00e9e.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/fort-magique-dirlande_29068221128_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/fort-magique-dirlande_29068221128_o.jpg\",\"alt\":\"for\\u00eat magique d&#039;Irlande et ses branches tordues\",\"title\":\"Irlande\",\"caption\":\"Canon 5D MK II et Canon 17-40 F4 L USM\",\"description\":\"Alors que nous nous sommes perdu dans une for\\u00eat au coeur de l&#039;Irlande (et que nous commen\\u00e7ons \\u00e0 flipper un peu ;-). Nous trouvons enfin les c\\u00e9l\\u00e8bres arbres... Plus qu&#039;\\u00e0 retrouver la voiture...\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/zoiseaux-_27822616649_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/zoiseaux-_27822616649_o.jpg\",\"alt\":\"oiseaux sur le lac L\\u00e9man en Suisse pr\\u00e8s de pr\\u00e9verenges\",\"title\":\"Les oiseaux\",\"caption\":\"Canon G7X MK II \",\"description\":\"Sur les rives pr\\u00e8s du village de Preverenges. Des oiseaux volent dans un ballet coordonn\\u00e9.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/foret-sous-la-pluie_38942164090_o-scaled.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/foret-sous-la-pluie_38942164090_o-scaled.jpg\",\"alt\":\"For\\u00eat sous la pluie\",\"title\":\"Sous la pluie\",\"caption\":\"Canon EOS 5D MK II et Canon EF 70-200 F4 L\",\"description\":\"J&#039;avais envie de r\\u00e9aliser des images. Je suis donc sorti sous la pluie en for\\u00eat. Cela donne souvent de tr\\u00e8s belles ambiances.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/DP0Q0796.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\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/TinePortra6x7Vertical.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/TinePortra6x7Vertical.jpg\",\"alt\":\"La chute de la Tine de Conflens\",\"title\":\"La chute de la Tine de Conflens\",\"caption\":\"Bi-objectif 6x6 et Ektar 100\",\"description\":\"La chute de la Tine de Conflens est une petite perle de nature.  J&#039;attendais depuis quelques temps l&#039;occasion de l&#039;immortaliser avec un gros d\\u00e9bit d&#039;eau. C&#039;est une de mes images pr\\u00e9f\\u00e9r\\u00e9es.\"},{\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/couleurs-du-soir_45852638885_o.jpg\",\"full_url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/couleurs-du-soir_45852638885_o.jpg\",\"alt\":\"Couleurs du soir sur les Alpes suisses\",\"title\":\"couleurs-du-soir_45852638885_o\",\"caption\":\"\",\"description\":\"\"}];\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   = 5 * 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-inst4-lightbox');\n                var lbImg      = document.getElementById('vl-slider-inst4-lb-img');\n                var lbClose    = document.getElementById('vl-slider-inst4-lb-close');\n                var lbOverlay  = lbWrap ? lbWrap.querySelector('.vl-sl-lb-overlay') : null;\n                var lbPrev     = document.getElementById('vl-slider-inst4-lb-prev');\n                var lbNext     = document.getElementById('vl-slider-inst4-lb-next');\n                var lbCounter  = document.getElementById('vl-slider-inst4-lb-counter');\n                var lbCaption  = document.getElementById('vl-slider-inst4-lb-caption');\n                var lbPlay     = document.getElementById('vl-slider-inst4-lb-playpause');\n                var lbSpeedBtn = document.getElementById('vl-slider-inst4-lb-speed');\n                var lbProgress = document.getElementById('vl-slider-inst4-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-inst4-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 class=\"wp-block-paragraph\"><strong>Concours, collaborations et mat\u00e9riel<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Au fil de mon parcours, j\u2019ai eu la chance de participer \u00e0 divers concours, notamment celui de Kolor avec son <a href=\"https:\/\/www.visionlarge.ch\/Blog\/panobook-2014\/\">c\u00e9l\u00e8bre Panobook<\/a>. Ces participations m\u2019ont valu d\u2019\u00eatre publi\u00e9 \u00e0 deux reprises dans le livre des plus beaux panoramas. J\u2019ai \u00e9galement pu tester plusieurs \u00e9quipements photographiques gr\u00e2ce \u00e0 <a href=\"https:\/\/fuji.ch\/fr\/\">Fujifilm Romandie<\/a> et Francine Gambarini et <a href=\"https:\/\/www.sigma-suisseattitude.ch\/x3f-system\">Sigma Romandie, d\u00e9couvrant notamment les capteurs Foveon<\/a>, qui offrent une approche presque \u00ab argentique \u00bb en num\u00e9rique. Je vous encourage d&rsquo;ailleurs \u00e0 jeter un coup d&rsquo;oeil sur le site de <a href=\"https:\/\/www.sigma-suisseattitude.ch\">Sigma Romandie<\/a>. Christian Cuenet vous r\u00e9pondra \u00e0 toutes vos questions!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Je ne poss\u00e8de pas de mat\u00e9riel photo exceptionnel. Beaucoup d\u2019\u00e9quipements sont des pr\u00eats, comme je l\u2019ai mentionn\u00e9 ci-dessus. Lorsque j\u2019en ai l\u2019occasion, cela me fait toujours plaisir d\u2019essayer du mat\u00e9riel que je ne connais pas. Mais mon principe est clair\u2026 Ce n\u2019est pas le mat\u00e9riel le plus important !<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6a1410675fdd3&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6a1410675fdd3\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2000\" height=\"2000\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Sortie-Flickr-Alain-2000x2000.jpg\" alt=\"Image r\u00e9alis\u00e9e par Samuel Gachet\" class=\"wp-image-12076\" srcset=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Sortie-Flickr-Alain-2000x2000.jpg 2000w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Sortie-Flickr-Alain-300x300.jpg 300w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Sortie-Flickr-Alain-150x150.jpg 150w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Sortie-Flickr-Alain-768x768.jpg 768w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Sortie-Flickr-Alain-1536x1536.jpg 1536w, https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/Sortie-Flickr-Alain-2048x2048.jpg 2048w\" sizes=\"auto, (max-width: 2000px) 100vw, 2000px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Image r\u00e9alis\u00e9e par Samuel Gachet<br \/><strong>avec un Rolleiflex 75 f3.5 Planar<\/strong><br \/>Je suis sur cette image avec mon vieux Yashica mat 124 et mon fameux par-soleil en papier qui a bien fait rire&#8230;<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Partager ma passion<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La photographie est avant tout une passion pour moi, et j\u2019aime la partager \u00e0 travers ce blog. Vous y trouverez \u00e9galement mes r\u00e9flexions et mes avis personnels sur le mat\u00e9riel et les techniques. Certains seront peut-\u00eatre partag\u00e9s, d\u2019autres contest\u00e9s\u2026 mais ce ne sont que des opinions d\u2019un passionn\u00e9 qui y prend du plaisir. N\u2019h\u00e9sitez pas \u00e0 me faire part de vos remarques !<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">Mes images sont disponibles \u00e0 la vente. Si l\u2019une d\u2019elles vous int\u00e9resse, contactez-moi par e-mail. (Depuis peu, il existe un petit logo avec un caddy sur les images des galeries d&rsquo;images pour me contacter.)<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><i style=\"color: #339966;\">Vous pouvez rechercher un&nbsp;<\/i><span style=\"color: #339966;\"><i>th\u00e8me<\/i><\/span><i style=\"color: #339966;\">&nbsp;ou un mot sur le site de deux mani\u00e8res, en inscrivant un tags dans l&rsquo;onglet en bas de la page, ou en <\/i><em style=\"color: #339966;\"><a style=\"color: #339966;\" href=\"http:\/\/www.visionlarge.ch\/Blog\/plan-du-site\/\">utilisant le Sitemap du Site<\/a><\/em><strong style=\"color: #339966;\"><em>&nbsp;<\/em><\/strong><\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><em><strong>Rappel :<\/strong>&nbsp;Les images sont prot\u00e9g\u00e9es, elles ne sont pas libres de droits. Merci de respecter les droits d\u2019auteur ! \u00ae All rights reserved<\/em><\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">Visionlarge.ch<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C&rsquo;est tellement plus beau en Vision Large! Bienvenue sur mon blog photo ! Je ne suis pas photographe professionnel. J&rsquo;aime la photographie comme une passion, un passe-temps qui me lib\u00e8re du monde stressant que l&rsquo;on nous impose aujourd&rsquo;hui. J&rsquo;aime l&rsquo;image. Cet instant vol\u00e9, fig\u00e9 \u00e0 jamais. Une fraction de temps&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/\">La suite? C&#039;est par l\u00e0!<span class=\"screen-reader-text\">A propos de moi<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-16","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.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>A propos de moi &#8212; Visionlarge.ch<\/title>\n<meta name=\"description\" content=\"Visionlarge, le Blog. Photographe passionn\u00e9, j&#039;aime re-transcrire, au travers de mes images, les paysages du canton de Vaud. Impression-vente.\" \/>\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\/gallerie-photos\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A propos de moi &#8212; Visionlarge.ch\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/\" \/>\n<meta property=\"og:site_name\" content=\"Visionlarge.ch\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-22T17:25:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"533\" \/>\n\t<meta property=\"og:image:height\" content=\"800\" \/>\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=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/\",\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/\",\"name\":\"A propos de moi &#8212; Visionlarge.ch\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/2013\\\/02\\\/Moi.jpg\",\"datePublished\":\"2011-10-29T16:44:04+00:00\",\"dateModified\":\"2026-04-22T17:25:55+00:00\",\"description\":\"Visionlarge, le Blog. Photographe passionn\u00e9, j'aime re-transcrire, au travers de mes images, les paysages du canton de Vaud. Impression-vente.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/2013\\\/02\\\/Moi.jpg\",\"contentUrl\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/wp-content\\\/uploads\\\/2013\\\/02\\\/Moi.jpg\",\"width\":533,\"height\":800,\"caption\":\"Moi\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/gallerie-photos\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.visionlarge.ch\\\/Blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"A propos de moi\"}]},{\"@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":"A propos de moi &#8212; Visionlarge.ch","description":"Visionlarge, le Blog. Photographe passionn\u00e9, j'aime re-transcrire, au travers de mes images, les paysages du canton de Vaud. Impression-vente.","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\/gallerie-photos\/","og_locale":"fr_FR","og_type":"article","og_title":"A propos de moi &#8212; Visionlarge.ch","og_url":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/","og_site_name":"Visionlarge.ch","article_modified_time":"2026-04-22T17:25:55+00:00","og_image":[{"width":533,"height":800,"url":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_site":"@visionlarge","twitter_misc":{"Dur\u00e9e de lecture estim\u00e9e":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/","url":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/","name":"A propos de moi &#8212; Visionlarge.ch","isPartOf":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/#primaryimage"},"image":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/#primaryimage"},"thumbnailUrl":"http:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg","datePublished":"2011-10-29T16:44:04+00:00","dateModified":"2026-04-22T17:25:55+00:00","description":"Visionlarge, le Blog. Photographe passionn\u00e9, j'aime re-transcrire, au travers de mes images, les paysages du canton de Vaud. Impression-vente.","breadcrumb":{"@id":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/#primaryimage","url":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg","contentUrl":"https:\/\/www.visionlarge.ch\/Blog\/wp-content\/uploads\/2013\/02\/Moi.jpg","width":533,"height":800,"caption":"Moi"},{"@type":"BreadcrumbList","@id":"https:\/\/www.visionlarge.ch\/Blog\/gallerie-photos\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.visionlarge.ch\/Blog\/"},{"@type":"ListItem","position":2,"name":"A propos de moi"}]},{"@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\/16","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=16"}],"version-history":[{"count":97,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/pages\/16\/revisions"}],"predecessor-version":[{"id":12091,"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/pages\/16\/revisions\/12091"}],"wp:attachment":[{"href":"https:\/\/www.visionlarge.ch\/Blog\/wp-json\/wp\/v2\/media?parent=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}