{"id":2380,"date":"2026-02-04T10:31:02","date_gmt":"2026-02-04T09:31:02","guid":{"rendered":"https:\/\/esd-digital-event.com\/2026\/?page_id=2380"},"modified":"2026-02-05T11:12:46","modified_gmt":"2026-02-05T10:12:46","slug":"accueil","status":"publish","type":"page","link":"https:\/\/esd-digital-event.com\/2026\/","title":{"rendered":"Accueil"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"2380\" class=\"elementor elementor-2380\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-96084dd e-con-full e-flex e-con e-parent\" data-id=\"96084dd\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-022ba11 elementor-widget elementor-widget-html\" data-id=\"022ba11\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<div id=\"esd-roulette\">\n   <!-- Overlay Grain -->\n   <div class=\"grain-overlay\">\n       <img decoding=\"async\" src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/grain.svg\" alt=\"Grain Overlay\">\n   <\/div>\n\n\n   <div class=\"main-container\">\n       <!-- Zone Gauche : Titre + Bobine -->\n       <div class=\"left-section\">\n           <div class=\"bobine-wrapper\">\n               <div class=\"bobine\" id=\"bobine\">\n                   <img decoding=\"async\" src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/bobine.svg\"\n                       alt=\"Bobine Interactive\" draggable=\"false\">\n               <\/div>\n           <\/div>\n\n\n           <div class=\"titles-container\" id=\"titles-container\">\n               <div class=\"title-item\">Creative<br>Technologies<\/div>\n               <div class=\"title-item\">Photo Lab<\/div>\n               <div class=\"title-item\">Interface Web<\/div>\n               <div class=\"title-item\">Podcast &<br>Cin\u00e9phonie<\/div>\n               <div class=\"title-item\">Cin\u00e9 Lab<\/div>\n               <div class=\"title-item\">Immersive Games<\/div>\n               <div class=\"title-item\">Team Orga<\/div>\n           <\/div>\n       <\/div>\n\n\n       <!-- Zone Droite : Colonne d'affiches -->\n       <div class=\"right-section\">\n           <div class=\"posters-viewport\">\n               <div class=\"posters-background-container\">\n                   <div class=\"bg-poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_CreativeTechnologies.jpg\"\n                               alt=\"\"><\/div>\n                   <\/div>\n                   <div class=\"bg-poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_PhotoLab.jpg\"\n                               alt=\"\"><\/div>\n                   <\/div>\n                   <div class=\"bg-poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_InterfaceWeb.jpg\"\n                               alt=\"\">\n                       <\/div>\n                   <\/div>\n                   <div class=\"bg-poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_PodcastCinephonie.jpg\"\n                               alt=\"\"><\/div>\n                   <\/div>\n                   <div class=\"bg-poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_cineLab.jpg\"\n                               alt=\"\"><\/div>\n                   <\/div>\n                   <div class=\"bg-poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_EscapeGame.jpg\"\n                               alt=\"\"><\/div>\n                   <\/div>\n                   <div class=\"bg-poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_TeamOrga.jpg\"\n                               alt=\"\"><\/div>\n                   <\/div>\n               <\/div>\n\n\n               <div class=\"posters-container\">\n                   <a href=\"https:\/\/esd-digital-event.com\/2026\/atelier-creative-technologies\" class=\"poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_CreativeTechnologies.jpg\"\n                               alt=\"\"><\/div>\n                   <\/a>\n                   <a href=\"https:\/\/esd-digital-event.com\/2026\/atelier-photo-lab\" class=\"poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_PhotoLab.jpg\"\n                               alt=\"\"><\/div>\n                   <\/a>\n                   <a href=\"https:\/\/esd-digital-event.com\/2026\/atelier-interface-web\" class=\"poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_InterfaceWeb.jpg\"\n                               alt=\"\">\n                       <\/div>\n                   <\/a>\n                   <a href=\"https:\/\/esd-digital-event.com\/2026\/atelier-podcast-cinephonie\" class=\"poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_PodcastCinephonie.jpg\"\n                               alt=\"\"><\/div>\n                   <\/a>\n                   <a href=\"https:\/\/esd-digital-event.com\/2026\/atelier-cine-lab\" class=\"poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_cineLab.jpg\"\n                               alt=\"\"><\/div>\n                   <\/a>\n                   <a href=\"https:\/\/esd-digital-event.com\/2026\/atelier-immersive-games\" class=\"poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_EscapeGame.jpg\"\n                               alt=\"\"><\/div>\n                   <\/a>\n                   <a href=\"https:\/\/esd-digital-event.com\/2026\/atelier-team-orga\" class=\"poster-card\">\n                       <div class=\"poster-inner\"><img decoding=\"async\"\n                               src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/Affiche_TeamOrga.jpg\"\n                               alt=\"\"><\/div>\n                   <\/a>\n               <\/div>\n           <\/div>\n       <\/div>\n   <\/div>\n\n\n   <!-- Logo -->\n   <div class=\"logo\">\n       <img decoding=\"async\" src=\"https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/DigitalEvent2026_logo.svg\" alt=\"Logo\">\n   <\/div>\n<\/div>\n\n\n<!-- GSAP -->\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/gsap\/3.12.5\/gsap.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/gsap\/3.12.5\/Draggable.min.js\"><\/script>\n\n\n<script>\n   (function () {\n\n\n       function initRoulette(root) {\n           if (!root) return;\n\n\n           \/\/ \u00e9vite double init (Elementor peut rappeler)\n           if (root.dataset.inited === \"1\") return;\n           root.dataset.inited = \"1\";\n\n\n           function boot() {\n               if (!window.gsap || !window.Draggable) return requestAnimationFrame(boot);\n\n\n               gsap.registerPlugin(Draggable);\n\n\n               const CONFIG = {\n                   durationBase: 0.8,\n                   easeBase: \"power4.out\",\n                   zoomActivePoster: 1.0,\n                   zoomInactivePoster: 0.75,\n                   opacityActive: 1,\n                   opacityInactive: 0.4,\n                   blurInactive: 4\n               };\n\n\n               const dom = {\n                   bobine: root.querySelector('#bobine'),\n                   postersContainer: root.querySelector('.posters-container'),\n                   bgContainer: root.querySelector('.posters-background-container'),\n                   titlesContainer: root.querySelector('#titles-container'),\n                   postersViewport: root.querySelector('.posters-viewport')\n               };\n\n\n               if (!dom.bobine || !dom.postersContainer || !dom.titlesContainer || !dom.postersViewport) {\n                   console.warn(\"Roulette: \u00e9l\u00e9ments manquants dans le widget.\");\n                   return;\n               }\n\n\n               const state = {\n                   rotation: 0,\n                   targetRotation: 0,\n                   totalItems: 0,\n                   snapAngle: 0,\n                   posters: [],\n                   bgPosters: [],\n                   titleElements: []\n               };\n\n\n               function initDOM() {\n                   state.posters = Array.from(dom.postersContainer.querySelectorAll('.poster-card'));\n                   state.bgPosters = dom.bgContainer ? Array.from(dom.bgContainer.querySelectorAll('.bg-poster-card')) : [];\n                   state.titleElements = Array.from(dom.titlesContainer.querySelectorAll('.title-item'));\n                   state.totalItems = state.posters.length;\n                   state.snapAngle = state.totalItems ? 360 \/ state.totalItems : 0;\n\n\n                   \/\/ Initialiser targetRotation avec la rotation actuelle (0 au d\u00e9but)\n                   state.targetRotation = 0;\n               }\n               initDOM();\n\n\n               let metrics = { itemHeight: 0, totalHeight: 0, isMobile: false, gap: 0, bgOffsetCount: 0, mobileRadius: 0 };\n\n\n               function updateMetrics() {\n                   metrics.isMobile = window.innerWidth <= 600;\n\n\n                   let pHeight = state.posters[0]?.offsetHeight || 0;\n                   if (!pHeight) pHeight = metrics.isMobile ? window.innerWidth * 1.0 : 550;\n\n\n                   metrics.gap = metrics.isMobile ? 20 : 40;\n                   metrics.itemHeight = pHeight + metrics.gap;\n                   metrics.totalHeight = metrics.itemHeight * state.totalItems;\n                   metrics.bgOffsetCount = Math.floor(state.totalItems \/ 2);\n                   metrics.mobileRadius = window.innerWidth * 0.50;\n               }\n\n\n               function updatePosterLayer(elements, targetY, baseScale, isBg) {\n                   const halfTotal = metrics.totalHeight \/ 2 || 1;\n\n\n                   elements.forEach((el, i) => {\n                       const naturalY = targetY + (i * metrics.itemHeight);\n                       const wrappedY = gsap.utils.wrap(-halfTotal, halfTotal, naturalY);\n                       const dist = Math.abs(wrappedY);\n\n\n                       let scale, opacity, blur, zIndex, rotateX, translateZ;\n\n\n                       if (isBg) {\n                           scale = baseScale;\n                           opacity = 0.3;\n                           blur = 3;\n                           zIndex = 1;\n                           rotateX = 0;\n                           translateZ = -200;\n                       } else {\n                           const range = metrics.itemHeight * 1.5;\n                           const progress = Math.min(dist \/ range, 1);\n\n\n                           const curve = 1 - Math.pow(progress, 2);\n                           const smoothCurve = Math.max(0, curve);\n\n\n                           scale = CONFIG.zoomInactivePoster + (CONFIG.zoomActivePoster - CONFIG.zoomInactivePoster) * smoothCurve;\n                           opacity = CONFIG.opacityInactive + (CONFIG.opacityActive - CONFIG.opacityInactive) * smoothCurve;\n                           blur = CONFIG.blurInactive * (1 - smoothCurve);\n\n\n                           translateZ = smoothCurve * 150;\n                           rotateX = wrappedY * -0.05;\n\n\n                           zIndex = Math.floor(smoothCurve * 100);\n\n\n                           if (dist < metrics.itemHeight * 0.3) {\n                               el.classList.add('active');\n                           } else {\n                               el.classList.remove('active');\n                           }\n\n\n                           if (dist > halfTotal * 0.8) {\n                               const fadeProgress = (dist - halfTotal * 0.8) \/ (halfTotal * 0.2);\n                               opacity *= (1 - fadeProgress);\n                           }\n                       }\n\n\n                       gsap.set(el, {\n                           xPercent: -50,\n                           yPercent: -50,\n                           y: wrappedY,\n                           scale: scale,\n                           opacity: opacity,\n                           zIndex: zIndex,\n                           rotateX: rotateX,\n                           translateZ: translateZ,\n                           filter: `blur(${blur}px)`\n                       });\n                   });\n               }\n\n\n               function updateTitles() {\n                   if (!state.snapAngle) return;\n\n\n                   if (metrics.isMobile) {\n                       const textRadius = metrics.mobileRadius;\n\n\n                       state.titleElements.forEach((el, i) => {\n                           const itemAngle = (i * state.snapAngle) + state.rotation;\n                           const normAngle = gsap.utils.wrap(-180, 180, itemAngle);\n                           const absAngle = Math.abs(normAngle);\n\n\n                           const isActive = absAngle < 20;\n                           const curve = Math.max(0, 1 - Math.pow(absAngle \/ 60, 2));\n                           const opacity = curve;\n                           const scale = 0.8 + (0.2 * curve);\n                           const color = gsap.utils.interpolate(\"rgba(255, 255, 255, 0.4)\", \"#ffffff\", curve);\n\n\n                           el.classList.toggle('active', isActive);\n\n\n                           const angleForTrig = itemAngle - 90;\n                           const rad = angleForTrig * (Math.PI \/ 180);\n                           const xPos = Math.cos(rad) * textRadius;\n                           const yPos = Math.sin(rad) * textRadius;\n\n\n                           gsap.set(el, {\n                               left: \"50%\",\n                               x: xPos,\n                               y: yPos,\n                               xPercent: -50,\n                               yPercent: -50,\n                               rotation: 0,\n                               transformOrigin: \"center center\",\n                               scale: scale,\n                               opacity: opacity,\n                               color: color,\n                               visibility: opacity > 0.01 ? \"visible\" : \"hidden\"\n                           });\n                       });\n\n\n                   } else {\n                       state.titleElements.forEach((el, i) => {\n                           const itemAngle = (i * state.snapAngle) + state.rotation;\n                           const TARGET_ZONE = 35;\n                           const finalVisualAngle = itemAngle + TARGET_ZONE;\n                           const normAngle = gsap.utils.wrap(-180, 180, itemAngle);\n                           const absAngle = Math.abs(normAngle);\n\n\n                           const isActive = absAngle < 35;\n                           const curve = Math.max(0, 1 - Math.pow(absAngle \/ 90, 1.5));\n                           const opacity = curve;\n                           const scale = 0.85 + (0.35 * curve);\n                           const color = gsap.utils.interpolate(\"rgba(255, 255, 255, 0.4)\", \"#ffffff\", curve);\n\n\n                           el.classList.toggle('active', isActive);\n\n\n                           gsap.set(el, {\n                               rotation: finalVisualAngle,\n                               x: 0,\n                               left: 0,\n                               opacity: opacity,\n                               scale: scale,\n                               color: color,\n                               visibility: opacity > 0.01 ? \"visible\" : \"hidden\",\n                               y: 0,\n                               xPercent: 0,\n                               yPercent: 0,\n                               transformOrigin: \"0% 0%\"\n                           });\n                       });\n                   }\n               }\n\n\n               function updateLayout() {\n                   if (!state.snapAngle) return;\n                   const ratio = metrics.itemHeight \/ state.snapAngle;\n                   const targetY = (state.rotation * ratio);\n\n\n                   updatePosterLayer(state.posters, targetY, 1, false);\n\n\n                   if (!metrics.isMobile && dom.bgContainer) {\n                       const boxOffset = metrics.bgOffsetCount * metrics.itemHeight;\n                       updatePosterLayer(state.bgPosters, targetY + boxOffset, 0.8, true);\n                   }\n\n\n                   updateTitles();\n               }\n\n\n               function updateGlobalRotation() {\n                   state.rotation = gsap.getProperty(dom.bobine, \"rotation\");\n                   updateLayout();\n               }\n\n\n               function stepInteraction(direction) {\n                   \/\/ On arrondit la target actuelle au snap le plus proche avant d'ajouter la rotation\n                   \/\/ Cela permet d'avoir un comportement pr\u00e9visible m\u00eame en spamant le scroll\n                   state.targetRotation = Math.round(state.targetRotation \/ state.snapAngle) * state.snapAngle;\n                   state.targetRotation += (direction * state.snapAngle);\n\n\n                   gsap.to(dom.bobine, {\n                       rotation: state.targetRotation,\n                       duration: 0.85,\n                       ease: \"power4.out\",\n                       overwrite: \"auto\",\n                       onUpdate: updateGlobalRotation\n                   });\n               }\n\n\n               \/\/ Draggable bobine\n               let bobineStartRot = 0;\n               Draggable.create(dom.bobine, {\n                   type: \"rotation\",\n                   onPress: function () {\n                       bobineStartRot = gsap.getProperty(this.target, \"rotation\");\n                       state.targetRotation = bobineStartRot;\n                   },\n                   onDrag: updateGlobalRotation,\n                   onDragEnd: function () {\n                       const currentRot = gsap.getProperty(this.target, \"rotation\");\n                       const diff = currentRot - bobineStartRot;\n                       if (Math.abs(diff) > 15) {\n                           stepInteraction(diff > 0 ? 1 : -1);\n                       } else {\n                           state.targetRotation = Math.round(currentRot \/ state.snapAngle) * state.snapAngle;\n                           gsap.to(dom.bobine, {\n                               rotation: state.targetRotation,\n                               duration: CONFIG.durationBase,\n                               ease: CONFIG.easeBase,\n                               onUpdate: updateGlobalRotation\n                           });\n                       }\n                   }\n               });\n\n\n               \/\/ Drag posters (proxy) \u2014 FIX Android click sur <a>\n               let dragStartY = 0;\n               let dragStartX = 0;\n               let hasTriggeredStep = false;\n\n\n               let pressedLink = null;\n               let movedEnoughForClickCancel = false;\n\n\n               Draggable.create(document.createElement(\"div\"), {\n                   trigger: dom.postersViewport,\n                   type: \"x,y\",\n                   dragClickables: true,\n                   minimumMovement: 6,\n                   allowEventDefault: true,\n\n\n                   onPress: function (e) {\n                       dragStartY = this.y;\n                       dragStartX = this.x;\n                       hasTriggeredStep = false;\n\n\n                       movedEnoughForClickCancel = false;\n\n\n                       \/\/ on capte le lien tap\u00e9 (si tap sur une affiche)\n                       const a = e.target && e.target.closest && e.target.closest(\"a.poster-card\");\n                       pressedLink = a ? a.href : null;\n\n\n                       \/\/ On synchronise la target rotation au d\u00e9but du drag\n                       state.targetRotation = gsap.getProperty(dom.bobine, \"rotation\");\n                   },\n\n\n                   onDrag: function () {\n                       const dy = this.y - dragStartY;\n                       const dx = this.x - dragStartX;\n\n\n                       \/\/ D\u00e8s qu'on bouge un peu, on consid\u00e8re que ce n'est plus un \"tap\"\n                       if (Math.abs(dy) + Math.abs(dx) > 6) movedEnoughForClickCancel = true;\n\n\n                       if (hasTriggeredStep) return;\n\n\n                       \/\/ Seuil ajust\u00e9 mobile \/ desktop (comme chez toi)\n                       const threshold = metrics.isMobile ? 20 : 40;\n                       const combinedDist = metrics.isMobile ? dy : (dy + dx * 0.5);\n\n\n                       if (Math.abs(combinedDist) > threshold) {\n                           stepInteraction(combinedDist > 0 ? 1 : -1);\n                           hasTriggeredStep = true;\n                       }\n                   },\n\n\n                   onRelease: function () {\n                       \/\/ Si c'\u00e9tait un tap (pas de step, pas de mouvement), on ouvre le lien manuellement\n                       \/\/ => contourne le preventDefault Android qui tue le click natif\n                       if (pressedLink && !hasTriggeredStep && !movedEnoughForClickCancel) {\n                           window.location.href = pressedLink;\n                       }\n                       pressedLink = null;\n                   }\n               });\n\n\n\n\n               let wheelAccumulator = 0;\n               let wheelLock = false;\n\n\n               function onWheel(e) {\n                   if (!root.contains(e.target)) return;\n                   e.preventDefault();\n\n\n                   if (wheelLock) return;\n\n\n                   \/\/ Normalisation basique\n                   let dy = e.deltaY;\n                   if (e.deltaMode === 1) dy *= 20; \/\/ lines\n                   if (e.deltaMode === 2) dy *= 400; \/\/ pages\n\n\n                   wheelAccumulator += dy;\n\n\n                   \/\/ Seuil pour d\u00e9clencher un changement de poster\n                   \/\/ On l'ajuste pour que ce soit moins sensible au trackpad\n                   const threshold = 60;\n\n\n                   if (Math.abs(wheelAccumulator) >= threshold) {\n                       const dir = wheelAccumulator > 0 ? 1 : -1;\n                       stepInteraction(dir);\n\n\n                       wheelAccumulator = 0;\n                       wheelLock = true;\n\n\n                       \/\/ Blocage temporaire pour g\u00e9rer l'inertie du trackpad\n                       \/\/ 700ms offre un bon compromis entre contr\u00f4le et fluidit\u00e9\n                       setTimeout(() => { wheelLock = false; }, 700);\n                   }\n\n\n                   \/\/ Reset de l'accumulateur si le scroll s'arr\u00eate (\u00e9vite les sauts impr\u00e9vus plus tard)\n                   clearTimeout(window.wheelResetTimer);\n                   window.wheelResetTimer = setTimeout(() => {\n                       wheelAccumulator = 0;\n                   }, 150);\n               }\n\n\n               root.addEventListener('wheel', onWheel, { passive: false, capture: true });\n               root.addEventListener('mousewheel', onWheel, { passive: false, capture: true }); \/\/ fallback\n\n\n               \/\/ Keys\n               window.addEventListener('keydown', (e) => {\n                   if (e.key.startsWith('Arrow')) stepInteraction((e.key === 'ArrowDown' || e.key === 'ArrowRight') ? 1 : -1);\n               });\n\n\n               window.addEventListener('resize', () => { updateMetrics(); updateLayout(); });\n\n\n               updateMetrics();\n               updateLayout();\n           }\n\n\n           boot();\n       }\n\n\n       \/\/ init \u201cnormal\u201d\n       function initAll() {\n           document.querySelectorAll('#esd-roulette').forEach(initRoulette);\n       }\n\n\n       if (document.readyState === \"loading\") {\n           document.addEventListener(\"DOMContentLoaded\", initAll);\n       } else {\n           initAll();\n       }\n\n\n       \/\/ init Elementor (important)\n       if (window.elementorFrontend && window.elementorFrontend.hooks) {\n           window.elementorFrontend.hooks.addAction('frontend\/element_ready\/html.default', function ($scope) {\n               const root = $scope[0].querySelector('#esd-roulette');\n               if (root) initRoulette(root);\n           });\n       }\n\n\n   })();\n<\/script>\n\n\n<style>\n   * {\n       margin: 0px;\n       padding: 0px;\n   }\n\n\n   \/* IMPORTANT: on scope tout au wrapper Elementor *\/\n   #esd-roulette {\n       position: relative;\n       width: 100%;\n       height: 100vh;\n       overflow: hidden;\n       font-family: 'Courier', Courier, monospace;\n       color: #fff;\n       background: linear-gradient(135deg, #050408 35%, #2C6381 100%);\n\n\n       \/* \u2705 petit plus pour macOS *\/\n       overscroll-behavior: none;\n   }\n\n\n   #esd-roulette * {\n       box-sizing: border-box;\n       -webkit-tap-highlight-color: transparent;\n   }\n\n\n   \/* Autoriser la s\u00e9lection de texte ou les interactions sur les liens *\/\n   .poster-card,\n   .title-item,\n   .logo {\n       user-select: auto;\n       -webkit-user-drag: none;\n   }\n\n\n   \/* Global Light Source (Top Right) *\/\n   #esd-roulette::after {\n       content: '';\n       position: absolute;\n       top: -10vh;\n       right: -10vw;\n       width: 70vw;\n       height: 70vw;\n       background: radial-gradient(circle at center, rgba(144, 203, 230, 0.15) 0%, transparent 70%);\n       pointer-events: none;\n       z-index: 100;\n       filter: blur(40px);\n   }\n\n\n   .grain-overlay {\n       position: absolute;\n       inset: 0;\n       z-index: 9;\n       pointer-events: none;\n   }\n\n\n   .grain-overlay img {\n       width: 100%;\n       height: 100%;\n       object-fit: cover;\n       opacity: 0.7;\n       mix-blend-mode: overlay;\n   }\n\n\n   .main-container {\n       position: relative;\n       width: 100%;\n       height: 100%;\n       display: flex;\n       z-index: 10;\n   }\n\n\n   \/* --- Left Section (Bobine + Titles) --- *\/\n   .left-section {\n       position: absolute;\n       top: 0;\n       left: 0;\n       width: 100%;\n       height: 100%;\n       pointer-events: none;\n       z-index: 20;\n   }\n\n\n   .bobine-wrapper {\n       position: absolute;\n       top: -10vw;\n       left: -10vw;\n       width: 35vw;\n       height: 35vw;\n       cursor: grab;\n       pointer-events: auto;\n       z-index: 25;\n   }\n\n\n   .bobine-wrapper:active {\n       cursor: grabbing;\n   }\n\n\n   .bobine {\n       position: relative;\n       width: 100%;\n       height: 100%;\n   }\n\n\n   .bobine::before {\n       content: '';\n       position: absolute;\n       top: 0;\n       left: 0;\n       width: 100%;\n       height: 100%;\n       border-radius: 50%;\n       background:\n           repeating-radial-gradient(circle at center,\n               transparent 0,\n               transparent 1px,\n               rgba(255, 255, 255, 0.3) 1.5px,\n               transparent 2px),\n           repeating-radial-gradient(circle at center,\n               transparent 0,\n               transparent 4px,\n               rgba(255, 255, 255, 0.2) 4.5px,\n               transparent 5px);\n       mix-blend-mode: overlay;\n       opacity: 0.9;\n       z-index: 3;\n       pointer-events: none;\n   }\n\n\n   .bobine::after {\n       content: '';\n       position: absolute;\n       top: 0;\n       left: 0;\n       width: 100%;\n       height: 100%;\n       border-radius: 50%;\n       background: conic-gradient(from 0deg,\n               rgba(255, 255, 255, 0) 0%,\n               rgba(255, 255, 255, 0.3) 10%,\n               rgba(255, 255, 255, 0) 20%,\n               rgba(255, 255, 255, 0.4) 45%,\n               rgba(255, 255, 255, 0) 60%,\n               rgba(255, 255, 255, 0.3) 80%,\n               rgba(255, 255, 255, 0.4) 95%,\n               rgba(255, 255, 255, 0) 100%);\n       mix-blend-mode: soft-light;\n       opacity: 0.6;\n       pointer-events: none;\n       z-index: 2;\n   }\n\n\n   .bobine img {\n       width: 100%;\n       height: 100%;\n       display: block;\n       pointer-events: none;\n       position: relative;\n       z-index: 1;\n   }\n\n\n   .titles-container {\n       position: absolute;\n       top: 7.5vw;\n       left: 7.5vw;\n       width: 0;\n       height: 0;\n       z-index: 24;\n       overflow: visible;\n   }\n\n\n   .title-item {\n       position: absolute;\n       top: 0;\n       left: 0;\n       line-height: 1.1;\n       transform-origin: 0 0;\n       font-size: clamp(1.2rem, 1.66vw, 2rem);\n       color: rgba(255, 255, 255, .4);\n       padding-left: 22vw;\n   }\n\n\n   .title-item.active {\n       font-weight: 500;\n       text-shadow: 0 0 30px rgba(0, 0, 0, .8);\n       z-index: 100;\n   }\n\n\n   .right-section {\n       position: absolute;\n       top: 0;\n       right: 0;\n       width: 65%;\n       height: 100%;\n       display: flex;\n       justify-content: center;\n       align-items: center;\n       perspective: 2000px;\n       z-index: 10;\n   }\n\n\n   .posters-viewport {\n       position: relative;\n       width: 40vw;\n       height: 100%;\n       transform: rotateZ(8deg);\n       transform-style: preserve-3d;\n       display: flex;\n       justify-content: center;\n       align-items: center;\n       cursor: grab;\n       pointer-events: auto;\n       translate: -50px;\n   }\n\n\n   .posters-container {\n       position: relative;\n       width: 100%;\n       height: 100%;\n       z-index: 20;\n   }\n\n\n   .posters-background-container {\n       position: absolute;\n       inset: 0;\n       transform: translateZ(-400px) translateX(400px) rotateZ(20deg);\n       pointer-events: none;\n       z-index: 5;\n   }\n\n\n   .poster-card {\n       position: absolute;\n       top: 50%;\n       left: 50%;\n       width: 32vw;\n       aspect-ratio: 35\/50;\n       max-width: 450px;\n       background: #1a1a1a;\n       border: 1px solid rgba(255, 255, 255, .2);\n       box-shadow: 0 40px 80px rgba(0, 0, 0, .6);\n       display: flex;\n       overflow: hidden;\n       will-change: transform, opacity;\n       cursor: pointer;\n       text-decoration: none;\n       pointer-events: auto;\n       \/* Optimisation pour mobile *\/\n       touch-action: manipulation;\n   }\n\n\n   .poster-card:active {\n       filter: brightness(0.9);\n   }\n\n\n   .poster-card::before,\n   .bg-poster-card::before {\n       content: '';\n       position: absolute;\n       inset: 0;\n       background:\n           radial-gradient(circle at 90% 10%, rgba(255, 255, 255, 0.15) 0%, transparent 60%),\n           linear-gradient(to bottom left, transparent 50%, rgba(0, 0, 0, 0.3) 100%),\n           linear-gradient(to right top, transparent 50%, rgba(255, 255, 255, 0.05) 100%);\n       z-index: 3;\n       pointer-events: none;\n   }\n\n\n   .poster-card::after,\n   .bg-poster-card::after {\n       content: '';\n       position: absolute;\n       inset: 0;\n       background-image: url('https:\/\/esd-digital-event.com\/2026\/wp-content\/uploads\/2026\/02\/grain.svg');\n       background-size: 200px 200px;\n       opacity: 0.12;\n       mix-blend-mode: soft-light;\n       z-index: 4;\n       pointer-events: none;\n       filter: contrast(1.2);\n   }\n\n\n   .bg-poster-card {\n       position: absolute;\n       top: 50%;\n       left: 50%;\n       width: 30vw;\n       aspect-ratio: 35\/50;\n       max-width: 450px;\n       background: #000;\n       border: 1px solid rgba(255, 255, 255, .1);\n       display: flex;\n       pointer-events: none;\n       opacity: .6 !important;\n       filter: blur(2px);\n       overflow: hidden;\n   }\n\n\n   .poster-inner {\n       width: 100%;\n       height: 100%;\n       display: flex;\n       align-items: center;\n       justify-content: center;\n       position: relative;\n       z-index: 1;\n   }\n\n\n   .poster-inner img,\n   .bg-poster-card img {\n       width: 100%;\n       height: 100%;\n       object-fit: cover;\n       display: block;\n   }\n\n\n   .logo {\n       position: absolute;\n       bottom: 4vh;\n       left: 4vw;\n       width: clamp(120px, 12vw, 220px);\n       z-index: 200;\n   }\n\n\n   .logo img {\n       width: 60%;\n       height: auto;\n   }\n\n\n   @media (max-width:600px) {\n\n\n       .bg-poster-card,\n       .posters-background-container {\n           display: none;\n       }\n\n\n       .title-item.active {\n           font-weight: 700 !IMPORTANT;\n       }\n\n\n       .bobine-wrapper {\n           top: auto;\n           left: 50%;\n           bottom: -35vw;\n           margin-left: -40vw;\n           width: 80vw;\n           height: 80vw;\n       }\n\n\n       .titles-container {\n           top: auto;\n           bottom: 5vw;\n           left: 50%;\n           z-index: 30;\n       }\n\n\n       .title-item {\n           width: 50vw;\n           padding-left: 0;\n           text-align: center;\n       }\n\n\n       .right-section {\n           width: 100%;\n           height: 80%;\n           right: auto;\n           left: 0;\n           align-items: flex-start;\n       }\n\n\n       .posters-viewport {\n           transform: rotateZ(0deg);\n           width: 100%;\n           height: 80%;\n           translate: 0;\n       }\n\n\n       .poster-card {\n           width: 50vw;\n           max-width: none;\n           top: 60%;\n       }\n   }\n<\/style>\n\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>CreativeTechnologies Photo Lab Interface Web Podcast &#038;Cin\u00e9phonie Cin\u00e9 Lab Immersive Games Team Orga<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-2380","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/pages\/2380","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/comments?post=2380"}],"version-history":[{"count":112,"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/pages\/2380\/revisions"}],"predecessor-version":[{"id":3599,"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/pages\/2380\/revisions\/3599"}],"wp:attachment":[{"href":"https:\/\/esd-digital-event.com\/2026\/wp-json\/wp\/v2\/media?parent=2380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}