{"id":14405,"date":"2026-08-02T21:48:04","date_gmt":"2026-08-02T19:48:04","guid":{"rendered":"https:\/\/pimpestudio.fr\/?page_id=14405"},"modified":"2026-08-05T12:05:35","modified_gmt":"2026-08-05T10:05:35","slug":"cider","status":"publish","type":"page","link":"https:\/\/pimpestudio.fr\/en\/cider\/","title":{"rendered":"Projet &#8211; CIDER"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"14405\" class=\"elementor elementor-14405\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-06b93fd e-con e-atomic-element e-flexbox-base e-74305da \" data-id=\"06b93fd\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"06b93fd\" data-e-type=\"e-flexbox\" data-id=\"06b93fd\">\n    \t\t<div class=\"elementor-element elementor-element-d51db66 elementor-widget elementor-widget-html\" data-id=\"d51db66\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- =========================================================\n     PIMP\u00c9 STUDIO \u2014 PAGE PROJET V26 \u2014 ORDRE MOBILE + FONDU CORRIG\u00c9\n     Version nettoy\u00e9e : Header et Popup Infos g\u00e9r\u00e9s globalement par Elementor.\n\n     STRUCTURE ELEMENTOR ATTENDUE\n\n     HEADER ELEMENTOR GLOBAL\n     - Conteneur : pimpe-global-header\n     - Logo : pimpe-global-logo\n     - Baseline : pimpe-global-tagline\n     - Menu : pimpe-global-menu\n     - Bouton Home : pimpe-global-home\n     - Bouton Infos : pimpe-global-infos\n\n     CONTENU CENTRAL\n     - Conteneur g\u00e9n\u00e9ral : project-content\n     - Titre : project-title\n     - Texte : project-description\n     - Bloc cr\u00e9dits : project-credits\n\n     IMAGE DE COUVERTURE\n     - Conteneur : project-cover hero-image\n     - Ce conteneur contient un widget Image.\n     - C'est la seule image avec un ratio impos\u00e9 : 41 \/ 28.\n     - Elle reprend les coins arrondis et l'ombre des cards de la Home.\n     - La classe hero-image permet de l'utiliser pour le fond flout\u00e9.\n\n     GALERIE MODULAIRE\n     - Chaque rang\u00e9e : project-gallery-row\n     - Une rang\u00e9e peut contenir 1, 2 ou 3 colonnes Elementor.\n     - Chaque colonne contient simplement un widget Image.\n     - Les images de galerie conservent leurs proportions naturelles.\n     - Le nombre de rang\u00e9es est illimit\u00e9.\n========================================================= -->\n\n<style>\n  :root {\n    --pimpe-project-max-width: 900px;\n    --pimpe-project-side-padding: clamp(24px, 4vw, 64px);\n    --pimpe-project-header-y: 38px;\n    --pimpe-project-index-width: min(18vw, 250px);\n\n    \/* M\u00eame valeur entre les colonnes, entre les lignes et sous la couverture. *\/\n    --pimpe-project-gallery-gap: 14px;\n  }\n\n  \/* =========================================================\n     BASE + TRANSITION ENTRE LES PAGES\n  ========================================================= *\/\n\n  html,\n  body {\n    margin: 0;\n    padding: 0;\n    min-height: 100%;\n  }\n\n  html {\n    background: #111;\n  }\n\n  body {\n    background: transparent;\n    overflow-x: clip !important;\n  }\n\n  @supports not (overflow-x: clip) {\n    body {\n      overflow-x: hidden !important;\n    }\n  }\n\n  @view-transition {\n    navigation: auto;\n  }\n\n  ::view-transition-old(root) {\n    animation: pimpe-page-out .22s ease both;\n  }\n\n  ::view-transition-new(root) {\n    animation: pimpe-page-in .32s cubic-bezier(.22, .61, .36, 1) both;\n  }\n\n  @keyframes pimpe-page-out {\n    to { opacity: .82; }\n  }\n\n  @keyframes pimpe-page-in {\n    from { opacity: 0; }\n    to { opacity: 1; }\n  }\n\n  \/* =========================================================\n     ARRI\u00c8RE-PLAN FLOUT\u00c9\n  ========================================================= *\/\n\n  .project-bg-blur {\n    position: fixed;\n    inset: -8%;\n    z-index: 0;\n    pointer-events: none;\n\n    background-size: cover;\n    background-position: center;\n    background-repeat: no-repeat;\n\n    filter: blur(55px) saturate(1.25);\n    transform: scale(1.08);\n    opacity: 0;\n\n    transition: opacity .95s cubic-bezier(.22, .61, .36, 1);\n    will-change: opacity;\n  }\n\n  .project-bg-blur.is-visible {\n    opacity: .6;\n  }\n\n  .project-bg-overlay {\n    position: fixed;\n    inset: 0;\n    z-index: 1;\n    pointer-events: none;\n    background: rgba(0, 0, 0, .36);\n  }\n\n  \/* =========================================================\n     HEADER ELEMENTOR GLOBAL \u2014 INT\u00c9GRATION UNIQUEMENT\n  ========================================================= *\/\n\n  \/* Le positionnement et le style visuel sont d\u00e9sormais g\u00e9r\u00e9s dans\n     le Theme Builder Elementor. *\/\n  .pimpe-global-logo,\n  .pimpe-global-home,\n  .pimpe-global-infos {\n    cursor: pointer !important;\n  }\n\n  .pimpe-global-home:hover,\n  .pimpe-global-infos:hover,\n  .pimpe-global-infos.is-active {\n    opacity: .55 !important;\n  }\n\n  \/* =========================================================\n     CONTENEUR CENTRAL\n     Ordre : titre > texte > cr\u00e9dits > couverture > rang\u00e9es galerie\n  ========================================================= *\/\n\n  .project-content {\n    position: relative !important;\n    z-index: 3 !important;\n\n    display: flex !important;\n    flex-direction: column !important;\n    align-items: stretch !important;\n\n    width: min(\n      var(--pimpe-project-max-width),\n      calc(100vw - 2 * var(--pimpe-project-side-padding) - 320px)\n    ) !important;\n\n    max-width: var(--pimpe-project-max-width) !important;\n    min-width: 0 !important;\n\n    margin: 0 auto !important;\n    padding: 118px 0 110px !important;\n    box-sizing: border-box !important;\n  }\n\n\n  \/*\n   * GALERIE VERTICALE\n   *\n   * Elementor peut injecter un wrapper .e-con-inner entre\n   * .project-content et ses enfants. Les deux niveaux sont donc forc\u00e9s\n   * en colonne afin que chaque m\u00e9dia arrive sous le pr\u00e9c\u00e9dent.\n   *\/\n  .project-content,\n  .project-content > .e-con-inner {\n    flex-direction: column !important;\n    flex-wrap: nowrap !important;\n    align-items: stretch !important;\n    justify-content: flex-start !important;\n  }\n\n  .project-content > .e-con-inner {\n    display: flex !important;\n    width: 100% !important;\n    max-width: none !important;\n    min-width: 0 !important;\n    height: auto !important;\n    min-height: 0 !important;\n\n    margin: 0 !important;\n    padding: 0 !important;\n    gap: 0 !important;\n\n    overflow: visible !important;\n    box-sizing: border-box !important;\n  }\n\n  .project-content > .e-con-inner > * {\n    min-width: 0 !important;\n    max-width: 100% !important;\n    flex-shrink: 0 !important;\n  }\n\n  .project-title {\n    order: 1 !important;\n    width: 100% !important;\n    margin: 0 0 24px !important;\n    padding: 0 !important;\n\n    color: #fff !important;\n    font-family:\n      \"Akira Expanded UltraBold\",\n      \"Akira Expanded Ultra Bold\",\n      \"Akira Expanded\",\n      \"Arial Black\",\n      sans-serif !important;\n    font-size: clamp(58px, 6.3vw, 100px) !important;\n    font-weight: 900 !important;\n    font-style: normal !important;\n    line-height: .88 !important;\n    letter-spacing: -.045em !important;\n    text-transform: uppercase !important;\n  }\n\n  .project-title .elementor-heading-title,\n  .project-title .elementor-widget-container {\n    margin: 0 !important;\n    padding: 0 !important;\n    color: inherit !important;\n    font: inherit !important;\n    line-height: inherit !important;\n    letter-spacing: inherit !important;\n    text-transform: inherit !important;\n  }\n\n  .project-description {\n    order: 2 !important;\n    width: min(100%, 660px) !important;\n    margin: 0 0 44px !important;\n    padding: 0 !important;\n\n    color: #fff !important;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif !important;\n    font-size: clamp(15px, 1.08vw, 18px) !important;\n    font-weight: 400 !important;\n    line-height: 1.18 !important;\n    letter-spacing: -.025em !important;\n  }\n\n  .project-description p,\n  .project-description .elementor-widget-container {\n    margin: 0 !important;\n    padding: 0 !important;\n    color: inherit !important;\n    font: inherit !important;\n    line-height: inherit !important;\n  }\n\n  .project-credits {\n    order: 3 !important;\n    width: min(100%, 500px) !important;\n    margin: 0 0 34px !important;\n    padding: 0 !important;\n\n    color: #fff !important;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif !important;\n    font-size: 13px !important;\n    font-weight: 400 !important;\n    line-height: 1.28 !important;\n    letter-spacing: -.02em !important;\n  }\n\n  .project-credits strong,\n  .project-credits b {\n    font-weight: 700 !important;\n  }\n\n  .project-credits p,\n  .project-credits .elementor-widget-container {\n    margin: 0 !important;\n    padding: 0 !important;\n    color: inherit !important;\n    font: inherit !important;\n    line-height: inherit !important;\n  }\n\n  \/* =========================================================\n     IMAGE DE COUVERTURE\n     Classe du conteneur Elementor :\n     project-cover hero-image\n  ========================================================= *\/\n\n  .project-cover {\n    position: relative !important;\n    order: 4 !important;\n\n    display: block !important;\n    flex: 0 0 auto !important;\n    align-self: stretch !important;\n\n    width: 100% !important;\n    max-width: 100% !important;\n    min-width: 0 !important;\n    height: auto !important;\n    aspect-ratio: 16 \/ 9 !important;\n\n    margin: 0 0 var(--pimpe-project-gallery-gap) !important;\n    padding: 0 !important;\n\n    \/*\n     * L'ombre appartient au conteneur ext\u00e9rieur : overflow visible \u00e9vite\n     * qu'elle soit coup\u00e9e. Le recadrage des coins est d\u00e9plac\u00e9 sur les\n     * wrappers internes de l'image.\n     *\/\n    overflow: visible !important;\n    border-radius: 22px !important;\n    background: transparent !important;\n\n    \/* M\u00eame ombre que les cards de la Home. *\/\n    box-shadow:\n      0 9px 20px rgba(0, 0, 0, .34),\n      0 3px 7px rgba(0, 0, 0, .20) !important;\n  }\n\n  .project-cover > .e-con-inner,\n  .project-cover .elementor-widget,\n  .project-cover .elementor-widget-container,\n  .project-cover .elementor-widget-image,\n  .project-cover picture {\n    display: block !important;\n    width: 100% !important;\n    height: 100% !important;\n    max-width: 100% !important;\n    min-width: 0 !important;\n    margin: 0 !important;\n    padding: 0 !important;\n    border-radius: inherit !important;\n  }\n\n  \/*\n   * Tous les wrappers restent ouverts. Le recadrage des coins est port\u00e9\n   * directement par l'image : l'ombre peut donc d\u00e9passer librement.\n   *\/\n  .project-cover > .e-con-inner,\n  .project-cover .elementor-widget,\n  .project-cover .elementor-widget-container,\n  .project-cover .elementor-widget-image,\n  .project-cover picture,\n  .project-cover a {\n    overflow: visible !important;\n  }\n\n  .project-cover img,\n  .project-cover video {\n    display: block !important;\n    width: 100% !important;\n    height: 100% !important;\n    max-width: none !important;\n    object-fit: cover !important;\n    object-position: center !important;\n    border-radius: 22px !important;\n  }\n\n  \/* =========================================================\n     GALERIE MODULAIRE\n     Classe de chaque conteneur de rang\u00e9e :\n     project-gallery-row\n\n     La direction, le nombre de colonnes et le gap restent pilot\u00e9s\n     directement dans Elementor.\n  ========================================================= *\/\n\n  .project-gallery-row {\n    position: relative !important;\n    order: 5 !important;\n\n    width: 100% !important;\n    max-width: 100% !important;\n    min-width: 0 !important;\n    height: auto !important;\n\n    margin: 0 0 var(--pimpe-project-gallery-gap) !important;\n    padding: 0 !important;\n\n    gap: var(--pimpe-project-gallery-gap) !important;\n    column-gap: var(--pimpe-project-gallery-gap) !important;\n    row-gap: var(--pimpe-project-gallery-gap) !important;\n\n    overflow: visible !important;\n    box-sizing: border-box !important;\n  }\n\n  .project-gallery-row:last-child,\n  .project-gallery-row:last-of-type {\n    margin-bottom: 0 !important;\n  }\n\n  \/*\n   * On ne force ni la direction ni la largeur des colonnes :\n   * une, deux ou trois colonnes restent enti\u00e8rement configurables\n   * depuis les r\u00e9glages responsive d'Elementor.\n   *\/\n  .project-gallery-row > .e-con-inner {\n    width: 100% !important;\n    max-width: none !important;\n    min-width: 0 !important;\n    height: auto !important;\n    margin: 0 !important;\n    padding: 0 !important;\n\n    gap: var(--pimpe-project-gallery-gap) !important;\n    column-gap: var(--pimpe-project-gallery-gap) !important;\n    row-gap: var(--pimpe-project-gallery-gap) !important;\n\n    overflow: visible !important;\n    box-sizing: border-box !important;\n  }\n\n  .project-gallery-row,\n  .project-gallery-row > .e-con-inner,\n  .project-gallery-row .e-con,\n  .project-gallery-row .elementor-element {\n    min-width: 0 !important;\n  }\n\n  .project-gallery-row .elementor-widget-image,\n  .project-gallery-row .elementor-widget-image .elementor-widget-container,\n  .project-gallery-row picture {\n    display: block !important;\n    width: 100% !important;\n    max-width: 100% !important;\n    min-width: 0 !important;\n    height: auto !important;\n    margin: 0 !important;\n    padding: 0 !important;\n  }\n\n  .project-gallery-row img,\n  .project-gallery-row video {\n    display: block !important;\n    width: 100% !important;\n    max-width: 100% !important;\n    height: auto !important;\n\n    object-fit: cover !important;\n    object-position: center !important;\n\n    border-radius: 18px !important;\n  }\n\n  \/* =========================================================\n     INDEX FIXE \u00c0 DROITE\n  ========================================================= *\/\n\n  .pimpe-project-index {\n    position: fixed !important;\n    top: 50% !important;\n    right: clamp(28px, 4vw, 72px) !important;\n    z-index: 700 !important;\n\n    display: flex !important;\n    flex-direction: column !important;\n    align-items: flex-end !important;\n    gap: 2px !important;\n\n    width: var(--pimpe-project-index-width) !important;\n    margin: 0 !important;\n    padding: 0 !important;\n\n    transform: translateY(-50%) !important;\n  }\n\n  .pimpe-project-index__item {\n    display: block !important;\n    width: 100% !important;\n    margin: 0 !important;\n    padding: 0 !important;\n    border: 0 !important;\n    outline: 0 !important;\n    background: transparent !important;\n\n    color: rgba(255, 255, 255, .58) !important;\n    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif !important;\n    font-size: clamp(16px, 1.45vw, 27px) !important;\n    font-weight: 700 !important;\n    line-height: 1.05 !important;\n    letter-spacing: -.045em !important;\n    text-align: right !important;\n    text-decoration: none !important;\n    white-space: nowrap !important;\n\n    cursor: pointer !important;\n    transition: color .24s ease, opacity .24s ease !important;\n  }\n\n  .pimpe-project-index__item:hover {\n    color: rgba(255, 255, 255, .88) !important;\n  }\n\n  .pimpe-project-index__item.is-active {\n    color: #fff !important;\n  }\n\n  \/* =========================================================\n     ANIMATIONS D\u2019APPARITION\n  ========================================================= *\/\n\n  .project-title {\n    opacity: 0;\n    transform: translateY(46px);\n    clip-path: inset(100% 0 0 0);\n    will-change: opacity, transform, clip-path;\n  }\n\n  .project-description,\n  .project-credits {\n    opacity: 0;\n    transform: translateY(28px);\n    filter: blur(7px);\n    will-change: opacity, transform, filter;\n  }\n\n  .project-cover,\n  .project-gallery-row,\n  .pimpe-project-index {\n    opacity: 0;\n    transform: translateY(24px);\n  }\n\n  body.pimpe-project-ready .project-title {\n    animation: pimpe-title-sweep 1.05s .16s cubic-bezier(.16,1,.3,1) forwards;\n  }\n\n  body.pimpe-project-ready .project-description {\n    animation: pimpe-copy-reveal .88s .42s cubic-bezier(.16,1,.3,1) forwards;\n  }\n\n  body.pimpe-project-ready .project-credits {\n    animation: pimpe-copy-reveal .88s .56s cubic-bezier(.16,1,.3,1) forwards;\n  }\n\n  @keyframes pimpe-title-sweep {\n    0% {\n      opacity: 0;\n      transform: translateY(46px);\n      clip-path: inset(100% 0 0 0);\n    }\n    35% {\n      opacity: 1;\n    }\n    100% {\n      opacity: 1;\n      transform: translateY(0);\n      clip-path: inset(0 0 0 0);\n    }\n  }\n\n  @keyframes pimpe-copy-reveal {\n    from {\n      opacity: 0;\n      transform: translateY(28px);\n      filter: blur(7px);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0);\n      filter: blur(0);\n    }\n  }\n\n  body.pimpe-project-ready .project-cover.is-in-view,\n  body.pimpe-project-ready .project-gallery-row.is-in-view {\n    animation: pimpe-reveal-up .82s .34s cubic-bezier(.22,.61,.36,1) forwards;\n  }\n\n  body.pimpe-project-ready .pimpe-project-index {\n    animation: pimpe-index-in .68s .30s cubic-bezier(.22,.61,.36,1) forwards;\n  }\n\n  @keyframes pimpe-reveal-up {\n    from {\n      opacity: 0;\n      transform: translateY(24px);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(0);\n    }\n  }\n\n  @keyframes pimpe-index-in {\n    from {\n      opacity: 0;\n      transform: translateY(-50%) translateX(18px);\n    }\n    to {\n      opacity: 1;\n      transform: translateY(-50%) translateX(0);\n    }\n  }\n\n  \/* Transition sortante lors d\u2019un clic vers une autre page. *\/\n  body.pimpe-project-leaving .project-content,\n  body.pimpe-project-leaving .pimpe-project-index {\n    opacity: 0 !important;\n    transform: translateY(10px) !important;\n    transition:\n      opacity .18s ease,\n      transform .22s ease !important;\n  }\n\n  \/* =========================================================\n     TABLETTE\n  ========================================================= *\/\n\n  @media (max-width: 1100px) and (min-width: 768px) {\n    .project-content {\n      width: min(66vw, 760px) !important;\n    }\n\n    .pimpe-project-index {\n      right: 24px !important;\n      width: 190px !important;\n    }\n\n    .pimpe-project-index__item {\n      font-size: clamp(14px, 2vw, 20px) !important;\n    }\n  }\n\n  \/* =========================================================\n     MOBILE\n  ========================================================= *\/\n\n  @media (max-width: 767px) {\n    :root {\n      --pimpe-project-side-padding: 18px;\n      --pimpe-project-gallery-gap: 10px;\n      --pimpe-project-cover-text-gap: 26px;\n    }\n\n    .project-content {\n      max-width: none !important;\n\n      \/*\n       * Le haut du contenu commence juste sous le header.\n       * La grande marge auparavant visible au-dessus du titre dispara\u00eet :\n       * c'est d\u00e9sormais la couverture qui occupe cette premi\u00e8re zone.\n       *\/\n      padding-top: 76px !important;\n      padding-bottom: 64px !important;\n    }\n\n    \/*\n     * Elementor contient aussi des widgets et des spacers sans classe\n     * projet. Ils avaient donc order:0 et passaient avant la couverture,\n     * malgr\u00e9 son order:1.\n     *\n     * On r\u00e9initialise tous les enfants directs, puis on place uniquement\n     * la couverture avant tout le reste avec un ordre n\u00e9gatif.\n     *\/\n    .project-content > *,\n    .project-content > .e-con-inner > * {\n      order: 0 !important;\n    }\n\n    .project-content > .project-cover,\n    .project-content > .e-con-inner > .project-cover {\n      order: -100 !important;\n    }\n\n    \/*\n     * Ordre mobile final :\n     * 1. couverture\n     * 2. tous les textes dans leur ordre Elementor\n     * 3. galerie\n     *\/\n    .project-cover {\n      order: -100 !important;\n\n      width: 100% !important;\n      max-width: 100% !important;\n      margin:\n        0\n        0\n        var(--pimpe-project-cover-text-gap)\n        0 !important;\n\n      border-radius: 17px !important;\n      aspect-ratio: 16 \/ 9 !important;\n    }\n\n    .project-title {\n      order: 0 !important;\n      width: 100% !important;\n\n      margin:\n        0\n        0\n        18px\n        0 !important;\n\n      padding: 0 !important;\n      font-size: clamp(42px, 14vw, 70px) !important;\n    }\n\n    .project-title,\n    .project-title .elementor-widget-container,\n    .project-title .elementor-heading-title {\n      margin-top: 0 !important;\n      padding-top: 0 !important;\n    }\n\n    .project-description {\n      order: 0 !important;\n      margin:\n        0\n        0\n        32px\n        0 !important;\n      font-size: 15px !important;\n    }\n\n    .project-credits {\n      order: 0 !important;\n      margin:\n        0\n        0\n        26px\n        0 !important;\n    }\n\n    .project-gallery-row {\n      order: 0 !important;\n    }\n\n    .project-cover img,\n    .project-cover video {\n      border-radius: 17px !important;\n    }\n\n    .project-gallery-row {\n      order: 0 !important;\n      width: 100% !important;\n      max-width: 100% !important;\n      margin-bottom: var(--pimpe-project-gallery-gap) !important;\n    }\n\n    .project-gallery-row img,\n    .project-gallery-row video {\n      border-radius: 14px !important;\n    }\n\n    .pimpe-project-index {\n      display: none !important;\n    }\n\n    .project-bg-blur {\n      inset: -12%;\n      filter: blur(42px) saturate(1.2);\n    }\n  }\n\n  \/* =========================================================\n     ACCESSIBILIT\u00c9\n  ========================================================= *\/\n\n  @media (prefers-reduced-motion: reduce) {\n    *,\n    *::before,\n    *::after {\n      animation-duration: .01ms !important;\n      animation-delay: 0ms !important;\n      transition-duration: .01ms !important;\n    }\n\n    .project-title,\n    .project-description,\n    .project-credits,\n    .project-cover,\n    .project-gallery-row,\n    .pimpe-project-index {\n      opacity: 1 !important;\n      transform: none !important;\n      clip-path: none !important;\n      filter: none !important;\n    }\n  }\n\n\/* =========================================================\n   TRANSITION NOIRE ENTRE LES PAGES\n========================================================= *\/\n\n.pimpe-page-fade {\n  position: fixed !important;\n  inset: 0 !important;\n  z-index: 2147483600 !important;\n  background: #000 !important;\n  opacity: 0 !important;\n  visibility: hidden !important;\n  pointer-events: none !important;\n  transition:\n    opacity .34s cubic-bezier(.22, .61, .36, 1),\n    visibility .34s ease !important;\n}\n\n.pimpe-page-fade.is-visible {\n  opacity: 1 !important;\n  visibility: visible !important;\n  pointer-events: auto !important;\n}\n\nhtml.pimpe-page-entering .pimpe-page-fade {\n  opacity: 1 !important;\n  visibility: visible !important;\n}\n\nhtml.pimpe-logo-transition .pimpe-page-fade {\n  transition:\n    opacity .58s cubic-bezier(.16, 1, .3, 1),\n    visibility 0s linear .58s !important;\n}\n\nhtml.pimpe-logo-transition .pimpe-page-fade.is-visible {\n  transition:\n    opacity .58s cubic-bezier(.16, 1, .3, 1),\n    visibility 0s linear 0s !important;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .pimpe-page-fade {\n    transition-duration: .01ms !important;\n  }\n}\n\n\n\/* Le projet reste masqu\u00e9 derri\u00e8re le noir jusqu'\u00e0 ce que la page soit pr\u00eate. *\/\nbody:not(.pimpe-project-ready) .project-content,\nbody:not(.pimpe-project-ready) .pimpe-project-index,\nbody:not(.pimpe-project-ready) .pimpe-contact-sticker {\n  opacity: 0 !important;\n}\n\n\/* Apparition coordonn\u00e9e du contenu projet apr\u00e8s disparition du noir. *\/\nbody.pimpe-project-ready .pimpe-contact-sticker {\n  animation: pimpe-project-header-in .68s .16s cubic-bezier(.22,.61,.36,1) both;\n}\n\n@keyframes pimpe-project-header-in {\n  from {\n    opacity: 0;\n    transform: translateY(-6px);\n  }\n  to {\n    opacity: 1;\n  }\n}\n\n\/* Le voile noir doit partir franchement mais sans cut. *\/\n.pimpe-page-fade {\n  transition:\n    opacity .78s cubic-bezier(.22, .61, .36, 1),\n    visibility 0s linear .78s !important;\n}\n\n.pimpe-page-fade.is-visible {\n  transition:\n    opacity .34s cubic-bezier(.22, .61, .36, 1),\n    visibility 0s linear 0s !important;\n}\n\n\n\/* =========================================================\n   ALIGNEMENT EXACT SUR LES \u00c9L\u00c9MENTS VISUELS DU HEADER\n   - bord gauche du projet = bord gauche visible du logo PIMP\u00c9\n   - bord droit de l\u2019index = bord droit visible de INFOS\n   Les valeurs sont calcul\u00e9es automatiquement en JavaScript.\n========================================================= *\/\n\n:root {\n  --pimpe-header-logo-left: 32px;\n  --pimpe-header-infos-right: 32px;\n  --pimpe-project-wide-max: 1180px;\n  --pimpe-project-index-reserve: 290px;\n}\n\n.project-content {\n  width: min(\n    var(--pimpe-project-wide-max),\n    calc(\n      100vw\n      - var(--pimpe-header-logo-left)\n      - var(--pimpe-header-infos-right)\n      - var(--pimpe-project-index-reserve)\n    )\n  ) !important;\n\n  max-width: var(--pimpe-project-wide-max) !important;\n  min-width: 0 !important;\n\n  margin-left: var(--pimpe-header-logo-left) !important;\n  margin-right: auto !important;\n}\n\n.pimpe-project-index {\n  right: var(--pimpe-header-infos-right) !important;\n}\n\n@media (max-width: 1100px) and (min-width: 768px) {\n  :root {\n    --pimpe-project-index-reserve: 220px;\n  }\n\n  .project-content {\n    width: calc(\n      100vw\n      - var(--pimpe-header-logo-left)\n      - var(--pimpe-header-infos-right)\n      - var(--pimpe-project-index-reserve)\n    ) !important;\n\n    max-width: none !important;\n  }\n\n  .pimpe-project-index {\n    width: 190px !important;\n  }\n}\n\n@media (max-width: 767px) {\n  :root {\n    \/*\n     * Ces valeurs correspondent aux bords int\u00e9rieurs du header.\n     * Elles sont recalcul\u00e9es en JavaScript depuis son conteneur r\u00e9el.\n     *\/\n    --pimpe-header-logo-left: 18px;\n    --pimpe-header-infos-right: 18px;\n  }\n\n  .project-content {\n    width: calc(\n      100vw\n      - var(--pimpe-header-logo-left)\n      - var(--pimpe-header-infos-right)\n    ) !important;\n\n    max-width: none !important;\n    margin-left: var(--pimpe-header-logo-left) !important;\n    margin-right: var(--pimpe-header-infos-right) !important;\n  }\n}\n\n\n\/* =========================================================\n   FONDU DU CONTENU SOUS LE HEADER \u2014 SANS ROGNER LES OMBRES\n\n   Le masque n'est plus appliqu\u00e9 \u00e0 TEST CENTRAL (.project-content),\n   car un masque sur le parent coupe toutes les ombres qui d\u00e9passent.\n   Le JavaScript masque d\u00e9sormais s\u00e9par\u00e9ment les textes et les images,\n   tandis que les conteneurs qui portent les ombres restent libres.\n========================================================= *\/\n\n.project-content {\n  -webkit-mask-image: none !important;\n  mask-image: none !important;\n}\n\n\n  \/* =========================================================\n     \u00c9DITEUR ELEMENTOR \u2014 M\u00c9DIAS TOUJOURS VISIBLES\n  ========================================================= *\/\n\n  \/*\n   * Dans l'\u00e9diteur Elementor, IntersectionObserver ne se d\u00e9clenche pas\n   * toujours dans l'iframe. Ces r\u00e8gles ne concernent que l'\u00e9dition :\n   * le reveal au scroll reste inchang\u00e9 sur le site publi\u00e9.\n   *\/\n  body.elementor-editor-active .project-content,\n  body.elementor-editor-preview .project-content,\n  body.elementor-edit-mode .project-content,\n  html.elementor-html body .project-content,\n  body.elementor-editor-active .project-cover,\n  body.elementor-editor-preview .project-cover,\n  body.elementor-edit-mode .project-cover,\n  html.elementor-html body .project-cover,\n  body.elementor-editor-active .project-gallery-row,\n  body.elementor-editor-preview .project-gallery-row,\n  body.elementor-edit-mode .project-gallery-row,\n  html.elementor-html body .project-gallery-row {\n    opacity: 1 !important;\n    visibility: visible !important;\n    transform: none !important;\n    animation: none !important;\n    filter: none !important;\n    -webkit-mask-image: none !important;\n    mask-image: none !important;\n  }\n\n  body.elementor-editor-active:not(.pimpe-project-ready) .project-content,\n  body.elementor-editor-preview:not(.pimpe-project-ready) .project-content,\n  body.elementor-edit-mode:not(.pimpe-project-ready) .project-content,\n  html.elementor-html body:not(.pimpe-project-ready) .project-content {\n    opacity: 1 !important;\n  }\n\n  \/*\n   * Chaque widget Image devient une cellule propre.\n   * Le JavaScript synchronise ensuite la hauteur des images qui se trouvent\n   * sur une m\u00eame ligne visuelle, d'apr\u00e8s l'image la plus \u00e0 gauche.\n   *\/\n  \/*\n   * L'ombre est appliqu\u00e9e directement au m\u00e9dia : elle reste visible m\u00eame\n   * si Elementor change le wrapper du widget Image.\n   *\/\n  .project-gallery-row .elementor-widget-image,\n  .project-gallery-row .elementor-widget-image .elementor-widget-container,\n  .project-gallery-row picture,\n  .project-gallery-row a,\n  .project-gallery-row .e-con,\n  .project-gallery-row .elementor-element {\n    overflow: visible !important;\n  }\n\n  .project-gallery-row img,\n  .project-gallery-row video {\n    object-fit: cover !important;\n    object-position: center !important;\n    border-radius: 18px !important;\n\n    box-shadow:\n      0 9px 20px rgba(0, 0, 0, .34),\n      0 3px 7px rgba(0, 0, 0, .20) !important;\n  }\n\n  @media (max-width: 767px) {\n    .project-gallery-row .elementor-widget-image,\n    .project-gallery-row .elementor-widget-image .elementor-widget-container,\n    .project-gallery-row picture {\n      border-radius: 14px !important;\n    }\n  }\n\n\n  \/* =========================================================\n     ANTI-ROGNAGE DES OMBRES\n  ========================================================= *\/\n\n  .project-content,\n  .project-content > .e-con-inner,\n  .project-content .e-con,\n  .project-content .elementor-element,\n  .project-content .elementor-widget,\n  .project-content .elementor-widget-container,\n  .project-cover,\n  .project-gallery-row,\n  .project-gallery-row > .e-con-inner {\n    overflow: visible !important;\n  }\n\n  \/*\n   * Les ombres ont de la place dans le gap commun sans modifier\n   * la largeur ni les proportions de la couverture ou des grilles.\n   *\/\n  .project-cover,\n  .project-gallery-row .elementor-widget-image {\n    isolation: isolate !important;\n  }\n\n<\/style>\n\n<div class=\"project-bg-blur\" aria-hidden=\"true\"><\/div>\n<div class=\"project-bg-overlay\" aria-hidden=\"true\"><\/div>\n\n<script>\n(function () {\n  \"use strict\";\n\n  \/*\n    IMPORTANT :\n    Modifie uniquement les URL ci-dessous si les slugs WordPress diff\u00e8rent.\n  *\/\n  \/* Liste de secours uniquement. La liste principale est d\u00e9sormais lue\n     automatiquement depuis les cartes de la Home. *\/\n  const FALLBACK_PROJECTS = [\n    { title: \"Glitch Beauty\", url: \"\/glitch-beauty\/\" },\n    { title: \"Test\", url: \"\/test\/\" },\n    { title: \"R\u00e9miniscence\", url: \"\/reminiscence\/\" },\n    { title: \"Sorb\u00e9\", url: \"\/sorbe\/\" },\n    { title: \"Bold\", url: \"\/bold\/\" },\n    { title: \"Hotel Mahfouf\", url: \"\/hotel-mahfouf\/\" }\n  ];\n\n  function cleanProjectCatalog(projects) {\n    const seen = new Set();\n\n    return (Array.isArray(projects) ? projects : [])\n      .map(function (project) {\n        return {\n          title: String(project?.title || \"\").trim(),\n          url: String(project?.url || \"\").trim()\n        };\n      })\n      .filter(function (project) {\n        if (!project.title || !project.url) return false;\n\n        const key = normalizedPath(project.url);\n        if (seen.has(key)) return false;\n        seen.add(key);\n        return true;\n      });\n  }\n\n  function readStoredProjectCatalog() {\n    try {\n      return cleanProjectCatalog(\n        JSON.parse(window.localStorage.getItem(\"pimpeProjectCatalog\") || \"[]\")\n      );\n    } catch (error) {\n      return [];\n    }\n  }\n\n  function extractProjectUrl(card) {\n    const explicitUrl =\n      card.getAttribute(\"data-project-url\") ||\n      card.dataset.projectUrl ||\n      \"\";\n\n    if (explicitUrl) return explicitUrl.trim();\n\n    if (card.matches(\"a[href]\")) {\n      return card.getAttribute(\"href\") || \"\";\n    }\n\n    const innerLink = card.querySelector(\"a[href]\");\n    if (innerLink) return innerLink.getAttribute(\"href\") || \"\";\n\n    const settingsNodes = [card].concat(\n      Array.from(card.querySelectorAll(\"[data-settings]\"))\n    );\n\n    for (const node of settingsNodes) {\n      const rawSettings = node.getAttribute(\"data-settings\");\n      if (!rawSettings) continue;\n\n      try {\n        const settings = JSON.parse(rawSettings);\n        const candidate =\n          settings?.link?.url ||\n          settings?.__globals__?.link ||\n          settings?.url ||\n          \"\";\n\n        if (typeof candidate === \"string\" && candidate.trim()) {\n          return candidate.trim();\n        }\n      } catch (error) {}\n    }\n\n    return \"\";\n  }\n\n  function extractProjectTitle(card) {\n    const source = card.querySelector(\".card-project-title\");\n    if (!source) return \"\";\n\n    const heading = source.querySelector(\".elementor-heading-title\");\n    const editor = source.querySelector(\".elementor-text-editor\");\n    const container = source.querySelector(\".elementor-widget-container\");\n\n    return (\n      heading?.textContent ||\n      editor?.textContent ||\n      container?.textContent ||\n      source.textContent ||\n      \"\"\n    ).trim();\n  }\n\n  async function fetchHomeProjectCatalog() {\n    try {\n      const response = await fetch(\"\/\", {\n        credentials: \"same-origin\",\n        cache: \"no-store\"\n      });\n\n      if (!response.ok) return [];\n\n      const html = await response.text();\n      const documentHome = new DOMParser().parseFromString(html, \"text\/html\");\n      const cards = Array.from(\n        documentHome.querySelectorAll(\".card-stage > .project-card\")\n      );\n\n      const catalog = cleanProjectCatalog(\n        cards.map(function (card) {\n          return {\n            title: extractProjectTitle(card),\n            url: extractProjectUrl(card)\n          };\n        })\n      );\n\n      if (catalog.length) {\n        try {\n          window.localStorage.setItem(\n            \"pimpeProjectCatalog\",\n            JSON.stringify(catalog)\n          );\n        } catch (error) {}\n      }\n\n      return catalog;\n    } catch (error) {\n      return [];\n    }\n  }\n\n  async function getProjectCatalog() {\n    const freshCatalog = await fetchHomeProjectCatalog();\n    if (freshCatalog.length) return freshCatalog;\n\n    const storedCatalog = readStoredProjectCatalog();\n    if (storedCatalog.length) return storedCatalog;\n\n    return FALLBACK_PROJECTS;\n  }\n\n  function normalizedPath(path) {\n    return (path || \"\/\")\n      .replace(\/\\\/+\/g, \"\/\")\n      .replace(\/\\\/$\/, \"\")\n      .toLowerCase() || \"\/\";\n  }\n\n  function getDirectLayoutChild(layout, element) {\n    if (!layout || !element) return null;\n\n    let current = element;\n\n    while (\n      current &&\n      current.parentElement &&\n      current.parentElement !== layout\n    ) {\n      current = current.parentElement;\n    }\n\n    return (\n      current &&\n      current.parentElement === layout\n    )\n      ? current\n      : null;\n  }\n\n  function enforceMobileProjectOrder() {\n    const content =\n      document.querySelector(\".project-content\");\n\n    if (!content) return;\n\n    const layout =\n      content.querySelector(\":scope > .e-con-inner\") ||\n      content;\n\n    const children = Array.from(layout.children);\n    const cover =\n      document.querySelector(\".project-cover\");\n\n    if (window.innerWidth > 767) {\n      children.forEach(function (child) {\n        child.style.removeProperty(\"order\");\n      });\n      return;\n    }\n\n    children.forEach(function (child) {\n      child.style.setProperty(\n        \"order\",\n        \"0\",\n        \"important\"\n      );\n    });\n\n    const coverBlock =\n      getDirectLayoutChild(layout, cover);\n\n    if (coverBlock) {\n      coverBlock.style.setProperty(\n        \"order\",\n        \"-100\",\n        \"important\"\n      );\n    }\n  }\n\n  \/* =========================================================\n     FOND FLOUT\u00c9 DEPUIS L\u2019IMAGE HERO\n  ========================================================= *\/\n\n  function createProjectBackground() {\n    const image = document.querySelector(\".project-cover.hero-image img, .hero-image img\");\n    const background = document.querySelector(\".project-bg-blur\");\n\n    if (!image || !background) return;\n\n    const source =\n      image.currentSrc ||\n      image.getAttribute(\"src\") ||\n      image.getAttribute(\"data-src\") ||\n      \"\";\n\n    if (!source) return;\n\n    background.style.backgroundImage =\n      'url(\"' + source.replace(\/\"\/g, '\\\\\"') + '\")';\n\n    background.classList.add(\"is-visible\");\n  }\n\n  \/* =========================================================\n     INDEX PROJETS\n  ========================================================= *\/\n\n  async function createProjectIndex() {\n    if (document.querySelector(\".pimpe-project-index\")) return;\n\n    const index = document.createElement(\"nav\");\n    index.className = \"pimpe-project-index\";\n    index.setAttribute(\"aria-label\", \"Acc\u00e8s rapide aux projets\");\n\n    const currentPath = normalizedPath(window.location.pathname);\n    const projects = await getProjectCatalog();\n\n    projects.forEach(function (project) {\n      const link = document.createElement(\"a\");\n\n      link.className = \"pimpe-project-index__item\";\n      link.href = project.url;\n      link.textContent = project.title;\n\n      const isActive =\n        currentPath === normalizedPath(project.url);\n\n      link.classList.toggle(\"is-active\", isActive);\n\n      if (isActive) {\n        link.setAttribute(\"aria-current\", \"page\");\n      }\n\n      index.appendChild(link);\n    });\n\n    document.body.appendChild(index);\n  }\n\n  \/* =========================================================\n     LIEN HOME DU HEADER GLOBAL\n     La Popup Infos est d\u00e9sormais g\u00e9r\u00e9e uniquement par Elementor.\n  ========================================================= *\/\n\n  function initializeProjectHomeLink() {\n    const openHome = document.querySelector(\".pimpe-global-home\");\n\n    if (!openHome || openHome.dataset.pimpeHomeReady === \"true\") return;\n\n    openHome.dataset.pimpeHomeReady = \"true\";\n    openHome.setAttribute(\"role\", \"link\");\n    openHome.setAttribute(\"tabindex\", \"0\");\n    openHome.setAttribute(\"aria-label\", \"Revenir \u00e0 la page d\u2019accueil\");\n\n    function goHomeFromMenu(event) {\n      event.preventDefault();\n      try { sessionStorage.setItem(\"pimpeLogoTransition\", \"1\"); } catch (error) {}\n      document.documentElement.classList.add(\"pimpe-logo-transition\");\n      window.pimpeNavigateWithBlackFade(\"\/\");\n    }\n\n    openHome.addEventListener(\"click\", goHomeFromMenu);\n    openHome.addEventListener(\"keydown\", function (event) {\n      if (event.key === \"Enter\" || event.key === \" \") goHomeFromMenu(event);\n    });\n  }\n\n  \/* =========================================================\n     LOGO CLIQUABLE VERS LA HOME\n  ========================================================= *\/\n\n  function initializeProjectLogo() {\n    const logo = document.querySelector(\".pimpe-global-logo\");\n\n    if (!logo || logo.dataset.projectLogoReady === \"true\") return;\n\n    logo.dataset.projectLogoReady = \"true\";\n    logo.setAttribute(\"role\", \"link\");\n    logo.setAttribute(\"tabindex\", \"0\");\n    logo.setAttribute(\"aria-label\", \"Revenir \u00e0 la page d\u2019accueil\");\n\n    function goHome(event) {\n      event.preventDefault();\n      try { sessionStorage.setItem(\"pimpeLogoTransition\", \"1\"); } catch (error) {}\n      document.documentElement.classList.add(\"pimpe-logo-transition\");\n      window.pimpeNavigateWithBlackFade(\"\/\");\n    }\n\n    logo.addEventListener(\"click\", goHome);\n\n    logo.addEventListener(\"keydown\", function (event) {\n      if (event.key === \"Enter\" || event.key === \" \") {\n        goHome(event);\n      }\n    });\n  }\n\n  \/* =========================================================\n     APPARITION DE LA COUVERTURE ET DES RANG\u00c9ES AU SCROLL\n  ========================================================= *\/\n\n  function initializeMediaReveal() {\n    const mediaElements = Array.from(\n      document.querySelectorAll(\n        \".project-cover, .project-gallery-row\"\n      )\n    );\n\n    if (!mediaElements.length) return;\n\n    if (!(\"IntersectionObserver\" in window)) {\n      mediaElements.forEach(function (media) {\n        media.classList.add(\"is-in-view\");\n      });\n      return;\n    }\n\n    const observer = new IntersectionObserver(function (entries) {\n      entries.forEach(function (entry) {\n        if (!entry.isIntersecting) return;\n\n        entry.target.classList.add(\"is-in-view\");\n        observer.unobserve(entry.target);\n      });\n    }, {\n      root: null,\n      rootMargin: \"0px 0px -8% 0px\",\n      threshold: .08\n    });\n\n    mediaElements.forEach(function (media) {\n      observer.observe(media);\n    });\n  }\n\n  \/* =========================================================\n     TRANSITION DE NAVIGATION\n  ========================================================= *\/\n\n  function navigateWithTransition(url) {\n    if (!url) return;\n\n    if (typeof window.pimpeNavigateWithBlackFade === \"function\") {\n      window.pimpeNavigateWithBlackFade(url);\n      return;\n    }\n\n    window.location.href = url;\n  }\n\n  function initializeInternalTransitions() {\n    document.addEventListener(\"click\", function (event) {\n      const link = event.target.closest(\n        \".pimpe-project-index__item\"\n      );\n\n      if (!link) return;\n      if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;\n      if (link.target === \"_blank\") return;\n\n      const targetPath = normalizedPath(\n        new URL(link.href, window.location.href).pathname\n      );\n\n      if (targetPath === normalizedPath(window.location.pathname)) {\n        event.preventDefault();\n        return;\n      }\n\n      event.preventDefault();\n      navigateWithTransition(link.href);\n    });\n  }\n\n  \/* =========================================================\n     INITIALISATION\n  ========================================================= *\/\n\n  function waitForHeroBackground() {\n    return new Promise(function (resolve) {\n      const image = document.querySelector(\".project-cover.hero-image img, .hero-image img\");\n      const finish = function () {\n        createProjectBackground();\n        resolve();\n      };\n\n      if (!image) {\n        finish();\n        return;\n      }\n\n      if (image.complete && (image.currentSrc || image.src)) {\n        if (typeof image.decode === \"function\") {\n          image.decode().then(finish).catch(finish);\n        } else {\n          finish();\n        }\n        return;\n      }\n\n      image.addEventListener(\"load\", finish, { once: true });\n      image.addEventListener(\"error\", finish, { once: true });\n\n      \/* S\u00e9curit\u00e9 : la page ne reste jamais bloqu\u00e9e si l'image tarde. *\/\n      window.setTimeout(finish, 900);\n    });\n  }\n\n  async function initializeProjectPage() {\n    enforceMobileProjectOrder();\n    await createProjectIndex();\n    initializeProjectHomeLink();\n    initializeProjectLogo();\n    initializeMediaReveal();\n    initializeInternalTransitions();\n\n    await waitForHeroBackground();\n\n    window.requestAnimationFrame(function () {\n      window.requestAnimationFrame(function () {\n        document.body.classList.add(\"pimpe-project-ready\");\n        window.dispatchEvent(new Event(\"pimpe:project-ready\"));\n      });\n    });\n  }\n\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\n      \"DOMContentLoaded\",\n      initializeProjectPage,\n      { once: true }\n    );\n  } else {\n    initializeProjectPage();\n  }\n\n  window.addEventListener(\"load\", function () {\n    enforceMobileProjectOrder();\n    createProjectBackground();\n  }, { once: true });\n\n  window.addEventListener(\"resize\", enforceMobileProjectOrder);\n\n  window.addEventListener(\"pageshow\", function (event) {\n    enforceMobileProjectOrder();\n    document.body.classList.remove(\n      \"pimpe-project-leaving\",\n      \"pimpe-page-leaving\"\n    );\n    document.body.classList.add(\"pimpe-project-ready\");\n    createProjectBackground();\n\n    const fade = document.querySelector(\".pimpe-page-fade\");\n\n    if (event.persisted && fade) {\n      fade.classList.add(\"is-visible\");\n\n      window.requestAnimationFrame(function () {\n        window.requestAnimationFrame(function () {\n          fade.classList.remove(\"is-visible\");\n        });\n      });\n      return;\n    }\n\n    if (fade) {\n      window.requestAnimationFrame(function () {\n        fade.classList.remove(\"is-visible\");\n      });\n    }\n  });\n\n  window.addEventListener(\"pagehide\", function () {\n    const fade = document.querySelector(\".pimpe-page-fade\");\n    if (fade) fade.classList.add(\"is-visible\");\n  });\n\n  window.setTimeout(createProjectBackground, 300);\n  window.setTimeout(createProjectBackground, 800);\n})();\n<\/script>\n\n\n<script>\n(function () {\n  \"use strict\";\n\n  let alignmentFrame = null;\n  let resizeObserver = null;\n\n  function isVisible(element) {\n    if (!element) return false;\n\n    const rect = element.getBoundingClientRect();\n    const style = window.getComputedStyle(element);\n\n    return (\n      rect.width > 0 &&\n      rect.height > 0 &&\n      style.display !== \"none\" &&\n      style.visibility !== \"hidden\" &&\n      style.opacity !== \"0\"\n    );\n  }\n\n  \/*\n   * Elementor applique parfois la classe au widget entier.\n   * On cherche donc l\u2019\u00e9l\u00e9ment r\u00e9ellement visible \u00e0 l\u2019int\u00e9rieur :\n   * image, lien, titre ou texte.\n   *\/\n  function getVisualTarget(root, type) {\n    if (!root) return null;\n\n    const selectors = type === \"logo\"\n      ? [\n          \"img\",\n          \"svg\",\n          \"a\",\n          \".elementor-heading-title\",\n          \".elementor-widget-container\"\n        ]\n      : [\n          \".elementor-heading-title\",\n          \".elementor-button-text\",\n          \"a\",\n          \"span\",\n          \".elementor-widget-container\"\n        ];\n\n    for (const selector of selectors) {\n      const candidates = Array.from(root.querySelectorAll(selector));\n\n      const target = candidates.find(function (candidate) {\n        const text = (candidate.textContent || \"\").trim();\n\n        if (!isVisible(candidate)) return false;\n\n        if (type === \"infos\") {\n          return \/infos\/i.test(text) || candidate.matches(\"a, .elementor-button-text\");\n        }\n\n        return true;\n      });\n\n      if (target) return target;\n    }\n\n    return isVisible(root) ? root : null;\n  }\n\n  function getHeaderContentEdges(header) {\n    if (!header) return null;\n\n    const inner =\n      header.querySelector(\":scope > .e-con-inner\") ||\n      header;\n\n    const rect = inner.getBoundingClientRect();\n    const style = window.getComputedStyle(inner);\n\n    const paddingLeft =\n      parseFloat(style.paddingLeft) || 0;\n\n    const paddingRight =\n      parseFloat(style.paddingRight) || 0;\n\n    return {\n      left: Math.max(0, rect.left + paddingLeft),\n      right: Math.max(\n        0,\n        document.documentElement.clientWidth\n          - rect.right\n          + paddingRight\n      )\n    };\n  }\n\n  function updateHeaderAlignment() {\n    alignmentFrame = null;\n\n    const header =\n      document.querySelector(\".pimpe-global-header\");\n\n    const logoRoot =\n      document.querySelector(\".pimpe-global-logo\");\n\n    const infosRoot =\n      document.querySelector(\".pimpe-global-infos\");\n\n    \/*\n     * En mobile, TEST CENTRAL reprend exactement la largeur int\u00e9rieure\n     * du header, ind\u00e9pendamment de la largeur visuelle du logo ou d'INFOS.\n     *\/\n    if (window.innerWidth <= 767) {\n      const headerEdges =\n        getHeaderContentEdges(header);\n\n      if (headerEdges) {\n        document.documentElement.style.setProperty(\n          \"--pimpe-header-logo-left\",\n          headerEdges.left + \"px\"\n        );\n\n        document.documentElement.style.setProperty(\n          \"--pimpe-header-infos-right\",\n          headerEdges.right + \"px\"\n        );\n\n        return;\n      }\n    }\n\n    const logoTarget =\n      getVisualTarget(logoRoot, \"logo\");\n\n    const infosTarget =\n      getVisualTarget(infosRoot, \"infos\");\n\n    if (logoTarget) {\n      const logoRect =\n        logoTarget.getBoundingClientRect();\n\n      document.documentElement.style.setProperty(\n        \"--pimpe-header-logo-left\",\n        Math.max(0, logoRect.left) + \"px\"\n      );\n    }\n\n    if (infosTarget) {\n      const infosRect =\n        infosTarget.getBoundingClientRect();\n\n      const rightSpace = Math.max(\n        0,\n        document.documentElement.clientWidth\n          - infosRect.right\n      );\n\n      document.documentElement.style.setProperty(\n        \"--pimpe-header-infos-right\",\n        rightSpace + \"px\"\n      );\n    }\n  }\n\n  function requestHeaderAlignment() {\n    if (alignmentFrame !== null) return;\n\n    alignmentFrame = window.requestAnimationFrame(\n      updateHeaderAlignment\n    );\n  }\n\n  function observeHeader() {\n    if (!(\"ResizeObserver\" in window)) return;\n\n    const header = document.querySelector(\".pimpe-global-header\");\n    const logo = document.querySelector(\".pimpe-global-logo\");\n    const infos = document.querySelector(\".pimpe-global-infos\");\n\n    resizeObserver = new ResizeObserver(requestHeaderAlignment);\n\n    [header, logo, infos].forEach(function (element) {\n      if (element) resizeObserver.observe(element);\n    });\n  }\n\n  function initializeHeaderAlignment() {\n    requestHeaderAlignment();\n    observeHeader();\n\n    \/*\n     * Elementor et les polices peuvent modifier les dimensions\n     * quelques instants apr\u00e8s le chargement.\n     *\/\n    window.setTimeout(requestHeaderAlignment, 100);\n    window.setTimeout(requestHeaderAlignment, 350);\n    window.setTimeout(requestHeaderAlignment, 800);\n    window.setTimeout(requestHeaderAlignment, 1500);\n\n    if (document.fonts && document.fonts.ready) {\n      document.fonts.ready.then(requestHeaderAlignment);\n    }\n  }\n\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\n      \"DOMContentLoaded\",\n      initializeHeaderAlignment,\n      { once: true }\n    );\n  } else {\n    initializeHeaderAlignment();\n  }\n\n  window.addEventListener(\"load\", requestHeaderAlignment);\n  window.addEventListener(\"resize\", requestHeaderAlignment);\n  window.addEventListener(\"pageshow\", requestHeaderAlignment);\n})();\n<\/script>\n\n\n<div class=\"pimpe-page-fade is-visible\" aria-hidden=\"true\"><\/div>\n\n<script>\n(function () {\n  \"use strict\";\n\n  const FADE_DURATION = 340;\n  const LOGO_FADE_DURATION = 580;\n\n  function getFade() {\n    return document.querySelector(\".pimpe-page-fade\");\n  }\n\n  function revealPage() {\n    const fade = getFade();\n    if (!fade) return;\n\n    const reveal = function () {\n      document.documentElement.classList.remove(\"pimpe-page-entering\");\n\n      \/* Petit maintien noir, puis disparition progressive coordonn\u00e9e\n         avec le blur et les \u00e9l\u00e9ments du projet. *\/\n      window.setTimeout(function () {\n        window.requestAnimationFrame(function () {\n          fade.classList.remove(\"is-visible\");\n        });\n      }, 120);\n    };\n\n    if (document.body.classList.contains(\"pimpe-project-ready\")) {\n      reveal();\n      return;\n    }\n\n    window.addEventListener(\"pimpe:project-ready\", reveal, { once: true });\n\n    \/* S\u00e9curit\u00e9 suppl\u00e9mentaire si un script Elementor retarde l'\u00e9v\u00e8nement. *\/\n    window.setTimeout(function () {\n      if (fade.classList.contains(\"is-visible\")) reveal();\n    }, 1500);\n  }\n\n  function navigateWithBlackFade(url) {\n    const fade = getFade();\n\n    if (!fade || !url) {\n      window.location.href = url;\n      return;\n    }\n\n    fade.classList.add(\"is-visible\");\n\n    const duration = document.documentElement.classList.contains(\"pimpe-logo-transition\")\n      ? LOGO_FADE_DURATION\n      : FADE_DURATION;\n\n    window.setTimeout(function () {\n      window.location.href = url;\n    }, duration);\n  }\n\n  window.pimpeNavigateWithBlackFade = navigateWithBlackFade;\n\n  \/* Permet aussi aux scripts existants du site de demander la m\u00eame transition. *\/\n  window.pimpeGoTo = navigateWithBlackFade;\n\n  const initialFade = getFade();\n  if (initialFade) {\n    initialFade.classList.add(\"is-visible\");\n  }\n\n  \/* Fondu sur tous les liens internes du site :\n     logo, index, cartes, liens de navigation, etc. *\/\n  document.addEventListener(\"click\", function (event) {\n    \/*\n     * IMPORTANT :\n     * Le bouton INFOS est pilot\u00e9 par Elementor Popup.\n     * Il ne doit jamais \u00eatre intercept\u00e9 par la transition noire\n     * r\u00e9serv\u00e9e aux v\u00e9ritables changements de page.\n     *\/\n    if (event.target.closest(\".pimpe-global-infos\")) {\n      return;\n    }\n\n    const link = event.target.closest(\"a\");\n    if (!link) return;\n\n    if (link.closest(\".pimpe-global-infos\")) {\n      return;\n    }\n\n    if (event.defaultPrevented) return;\n    if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;\n    if (link.target === \"_blank\") return;\n    if (link.hasAttribute(\"download\")) return;\n    if (link.dataset.pimpeNoFade === \"true\") return;\n\n    const rawHref = link.getAttribute(\"href\") || \"\";\n    if (\n      !rawHref ||\n      rawHref.startsWith(\"#\") ||\n      rawHref.startsWith(\"mailto:\") ||\n      rawHref.startsWith(\"tel:\") ||\n      rawHref.startsWith(\"javascript:\")\n    ) {\n      return;\n    }\n\n    const target = new URL(link.href, window.location.href);\n\n    if (target.origin !== window.location.origin) return;\n\n    \/* Autorise un refresh volontaire avec le m\u00eame fondu. *\/\n    if (target.href === window.location.href) {\n      event.preventDefault();\n      navigateWithBlackFade(target.href);\n      return;\n    }\n\n    event.preventDefault();\n    event.stopImmediatePropagation();\n    navigateWithBlackFade(target.href);\n  }, true);\n\n  try {\n    if (sessionStorage.getItem(\"pimpeLogoTransition\") === \"1\") {\n      document.documentElement.classList.add(\"pimpe-logo-transition\");\n    }\n  } catch (error) {}\n\n  document.documentElement.classList.add(\"pimpe-page-entering\");\n\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\"DOMContentLoaded\", revealPage, { once: true });\n  } else {\n    revealPage();\n  }\n\n  window.addEventListener(\"pageshow\", revealPage);\n})();\n<\/script>\n\n\n<!-- =========================================================\n     PIMP\u00c9 STUDIO \u2014 FONDU GLOBAL DES BLOCS, SANS ROGNER LES OMBRES\n========================================================= -->\n<script>\n(function () {\n  \"use strict\";\n\n  \/*\n   * Desktop :\n   * 0 \u00e0 88 px   = invisible\n   * 88 \u00e0 215 px = fondu\n   *\n   * Mobile :\n   * zone beaucoup plus courte, situ\u00e9e juste sous le header.\n   * Aucun masque n'est appliqu\u00e9 tant que l'utilisateur n'a pas commenc\u00e9\n   * \u00e0 faire d\u00e9filer la page.\n   *\/\n  const DESKTOP_HIDE_END = 88;\n  const DESKTOP_FADE_END = 215;\n  const MOBILE_HIDE_END = 48;\n  const MOBILE_FADE_END = 112;\n\n  function getFadeLimits() {\n    if (window.innerWidth <= 767) {\n      return {\n        hideEnd: MOBILE_HIDE_END,\n        fadeEnd: MOBILE_FADE_END\n      };\n    }\n\n    return {\n      hideEnd: DESKTOP_HIDE_END,\n      fadeEnd: DESKTOP_FADE_END\n    };\n  }\n\n  let frame = null;\n  let resizeObserver = null;\n  let mutationObserver = null;\n\n  function clamp(value, minimum, maximum) {\n    return Math.min(Math.max(value, minimum), maximum);\n  }\n\n  \/*\n   * D\u00e9tection volontairement stricte.\n   * La classe html \"elementor-html\" peut aussi exister hors de l'\u00e9diteur\n   * selon la configuration Elementor : elle n'est donc plus utilis\u00e9e.\n   *\/\n  function isElementorEditor() {\n    const body = document.body;\n\n    if (\n      body.classList.contains(\"elementor-editor-active\") ||\n      body.classList.contains(\"elementor-editor-preview\") ||\n      body.classList.contains(\"elementor-edit-mode\")\n    ) {\n      return true;\n    }\n\n    try {\n      return Boolean(\n        window.elementorFrontend &&\n        typeof window.elementorFrontend.isEditMode === \"function\" &&\n        window.elementorFrontend.isEditMode()\n      );\n    } catch (error) {\n      return false;\n    }\n  }\n\n  function isUsableTarget(element) {\n    if (!element) return false;\n\n    const rect = element.getBoundingClientRect();\n    const style = window.getComputedStyle(element);\n\n    return (\n      rect.width > 0 &&\n      rect.height > 0 &&\n      style.display !== \"none\" &&\n      style.visibility !== \"hidden\"\n    );\n  }\n\n  function uniqueElements(elements) {\n    return elements.filter(function (element, index, array) {\n      return element && array.indexOf(element) === index;\n    });\n  }\n\n  \/*\n   * On cible d\u00e9sormais les blocs Elementor entiers plac\u00e9s dans TEST CENTRAL,\n   * plut\u00f4t que d'essayer de deviner quel enfant interne dessine le texte.\n   *\n   * Sont exclus :\n   * - project-cover : son ombre doit rester totalement libre ;\n   * - project-gallery-row : m\u00eame principe pour les ombres de la grille.\n   *\n   * Les images elles-m\u00eames sont ajout\u00e9es s\u00e9par\u00e9ment afin qu'elles continuent\n   * de dispara\u00eetre progressivement sans masquer leur box-shadow.\n   *\/\n  function getProjectContentBlocks() {\n    const content = document.querySelector(\".project-content\");\n    if (!content) return [];\n\n    const layout =\n      content.querySelector(\":scope > .e-con-inner\") ||\n      content;\n\n    return Array.from(layout.children).filter(function (element) {\n      if (!isUsableTarget(element)) return false;\n\n      if (\n        element.matches(\n          \".project-cover, .project-gallery-row\"\n        )\n      ) {\n        return false;\n      }\n\n      if (\n        element.closest(\".project-cover, .project-gallery-row\")\n      ) {\n        return false;\n      }\n\n      return true;\n    });\n  }\n\n  \/*\n   * Secours pour les structures Elementor atypiques :\n   * les widgets identifi\u00e9s par leurs classes projet sont inclus m\u00eame s'ils\n   * ne sont pas des enfants directs du wrapper .e-con-inner.\n   *\/\n  function getNamedTextBlocks() {\n    return Array.from(\n      document.querySelectorAll(\n        \".project-title, \" +\n        \".project-description, \" +\n        \".project-credits\"\n      )\n    ).filter(isUsableTarget);\n  }\n\n  function getMediaPixels() {\n    return Array.from(\n      document.querySelectorAll(\n        \".project-cover img, \" +\n        \".project-cover video, \" +\n        \".project-gallery-row img, \" +\n        \".project-gallery-row video\"\n      )\n    ).filter(isUsableTarget);\n  }\n\n  function getFadeTargets() {\n    return uniqueElements(\n      getProjectContentBlocks()\n        .concat(getNamedTextBlocks())\n        .concat(getMediaPixels())\n    );\n  }\n\n  \/*\n   * Nettoie les masques des versions pr\u00e9c\u00e9dentes sur le parent et sur\n   * les \u00e9ventuels enfants de texte, avant d'appliquer le nouveau syst\u00e8me.\n   *\/\n  function getLegacyMaskTargets() {\n    return Array.from(\n      document.querySelectorAll(\n        \".project-content, \" +\n        \".project-title, \" +\n        \".project-title .elementor-heading-title, \" +\n        \".project-title .elementor-widget-container, \" +\n        \".project-description, \" +\n        \".project-description .elementor-widget-container, \" +\n        \".project-description .elementor-text-editor, \" +\n        \".project-credits, \" +\n        \".project-credits .elementor-widget-container, \" +\n        \".project-credits .elementor-text-editor\"\n      )\n    );\n  }\n\n  function clearTargetMask(target) {\n    if (!target) return;\n\n    target.style.removeProperty(\"-webkit-mask-image\");\n    target.style.removeProperty(\"mask-image\");\n    target.style.removeProperty(\"-webkit-mask-repeat\");\n    target.style.removeProperty(\"mask-repeat\");\n    target.style.removeProperty(\"-webkit-mask-size\");\n    target.style.removeProperty(\"mask-size\");\n  }\n\n  function setTargetMask(target, mask) {\n    target.style.webkitMaskImage = mask;\n    target.style.maskImage = mask;\n    target.style.webkitMaskRepeat = \"no-repeat\";\n    target.style.maskRepeat = \"no-repeat\";\n    target.style.webkitMaskSize = \"100% 100%\";\n    target.style.maskSize = \"100% 100%\";\n  }\n\n  function updateTargetMask(target) {\n    const rect = target.getBoundingClientRect();\n    const height = Math.max(rect.height, 1);\n    const limits = getFadeLimits();\n    const hideEnd = limits.hideEnd;\n    const fadeEnd = limits.fadeEnd;\n\n    if (rect.top >= fadeEnd) {\n      clearTargetMask(target);\n      return;\n    }\n\n    if (rect.bottom <= hideEnd) {\n      setTargetMask(\n        target,\n        \"linear-gradient(to bottom, transparent 0%, transparent 100%)\"\n      );\n      return;\n    }\n\n    const hiddenUntil = clamp(\n      hideEnd - rect.top,\n      0,\n      height\n    );\n\n    const fullyVisibleFrom = clamp(\n      fadeEnd - rect.top,\n      0,\n      height\n    );\n\n    const mask =\n      \"linear-gradient(to bottom,\" +\n      \" transparent 0px,\" +\n      \" transparent \" + hiddenUntil + \"px,\" +\n      \" #000 \" + fullyVisibleFrom + \"px,\" +\n      \" #000 100%)\";\n\n    setTargetMask(target, mask);\n  }\n\n  function updateProjectContentFade() {\n    frame = null;\n\n    \/*\n     * Le parent TEST CENTRAL ne re\u00e7oit jamais de masque :\n     * ses ombres ne peuvent donc plus \u00eatre rogn\u00e9es.\n     *\/\n    getLegacyMaskTargets().forEach(clearTargetMask);\n\n    const targets = getFadeTargets();\n\n    if (isElementorEditor()) {\n      targets.forEach(clearTargetMask);\n      return;\n    }\n\n    \/*\n     * Sur mobile, la page doit \u00eatre enti\u00e8rement visible \u00e0 son \u00e9tat initial.\n     * Le fondu sup\u00e9rieur ne commence qu'apr\u00e8s le premier mouvement de scroll.\n     *\/\n    if (\n      window.innerWidth <= 767 &&\n      window.scrollY <= 1\n    ) {\n      targets.forEach(clearTargetMask);\n      return;\n    }\n\n    targets.forEach(updateTargetMask);\n  }\n\n  function requestProjectContentFade() {\n    if (frame !== null) return;\n\n    frame = window.requestAnimationFrame(\n      updateProjectContentFade\n    );\n  }\n\n  function observeFadeTargets() {\n    if (!(\"ResizeObserver\" in window)) return;\n\n    if (!resizeObserver) {\n      resizeObserver = new ResizeObserver(\n        requestProjectContentFade\n      );\n    }\n\n    getFadeTargets().forEach(function (target) {\n      resizeObserver.observe(target);\n\n      if (\n        target.tagName === \"IMG\" &&\n        !target.complete\n      ) {\n        target.addEventListener(\n          \"load\",\n          requestProjectContentFade,\n          { once: true }\n        );\n      }\n\n      if (target.tagName === \"VIDEO\") {\n        target.addEventListener(\n          \"loadedmetadata\",\n          requestProjectContentFade,\n          { once: true }\n        );\n      }\n    });\n  }\n\n  function initializeProjectContentFade() {\n    observeFadeTargets();\n    requestProjectContentFade();\n\n    window.addEventListener(\n      \"scroll\",\n      requestProjectContentFade,\n      { passive: true }\n    );\n\n    window.addEventListener(\n      \"resize\",\n      function () {\n        observeFadeTargets();\n        requestProjectContentFade();\n      },\n      { passive: true }\n    );\n\n    window.addEventListener(\n      \"pageshow\",\n      requestProjectContentFade\n    );\n\n    window.addEventListener(\n      \"pimpe:project-ready\",\n      function () {\n        observeFadeTargets();\n        requestProjectContentFade();\n      }\n    );\n\n    \/*\n     * Les widgets Elementor peuvent \u00eatre reconstruits apr\u00e8s le chargement.\n     * On recalcule les blocs sans modifier la mise en page.\n     *\/\n    mutationObserver = new MutationObserver(\n      function () {\n        observeFadeTargets();\n        requestProjectContentFade();\n      }\n    );\n\n    mutationObserver.observe(\n      document.documentElement,\n      {\n        childList: true,\n        subtree: true\n      }\n    );\n\n    [100, 350, 800, 1400, 2200].forEach(\n      function (delay) {\n        window.setTimeout(function () {\n          observeFadeTargets();\n          requestProjectContentFade();\n        }, delay);\n      }\n    );\n  }\n\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\n      \"DOMContentLoaded\",\n      initializeProjectContentFade,\n      { once: true }\n    );\n  } else {\n    initializeProjectContentFade();\n  }\n})();\n<\/script>\n\n\n<script>\n(function () {\n  \"use strict\";\n\n  let equalizeFrame = null;\n  let equalizeRunning = false;\n  let resizeObserver = null;\n  let mutationObserver = null;\n\n  const HEIGHT_MARK = \"pimpeGalleryEqualized\";\n\n  function getGalleryRows() {\n    return Array.from(\n      document.querySelectorAll(\".project-gallery-row\")\n    );\n  }\n\n  function getGalleryImages(row) {\n    return Array.from(\n      row.querySelectorAll(\"img, video\")\n    ).filter(function (media) {\n      const rect = media.getBoundingClientRect();\n      const style = window.getComputedStyle(media);\n\n      return (\n        rect.width > 0 &&\n        style.display !== \"none\" &&\n        style.visibility !== \"hidden\"\n      );\n    });\n  }\n\n  function getMediaWrappers(media, row) {\n    const wrappers = [\n      media,\n      media.closest(\"picture\"),\n      media.closest(\".elementor-widget-container\"),\n      media.closest(\".elementor-widget-image\")\n    ].filter(function (element, index, array) {\n      return (\n        element &&\n        row.contains(element) &&\n        array.indexOf(element) === index\n      );\n    });\n\n    return wrappers;\n  }\n\n  function clearEqualizedHeight(media, row) {\n    getMediaWrappers(media, row).forEach(function (element) {\n      if (element.dataset[HEIGHT_MARK] !== \"true\") return;\n\n      element.style.removeProperty(\"height\");\n      element.style.removeProperty(\"min-height\");\n      element.style.removeProperty(\"max-height\");\n      delete element.dataset[HEIGHT_MARK];\n    });\n  }\n\n  function setEqualizedHeight(media, row, height) {\n    const safeHeight = Math.max(1, Math.round(height));\n\n    getMediaWrappers(media, row).forEach(function (element) {\n      element.style.setProperty(\n        \"height\",\n        safeHeight + \"px\",\n        \"important\"\n      );\n      element.style.setProperty(\n        \"min-height\",\n        safeHeight + \"px\",\n        \"important\"\n      );\n      element.style.setProperty(\n        \"max-height\",\n        safeHeight + \"px\",\n        \"important\"\n      );\n      element.dataset[HEIGHT_MARK] = \"true\";\n    });\n\n    media.style.setProperty(\"object-fit\", \"cover\", \"important\");\n  }\n\n  function groupMediaByVisualLine(mediaElements) {\n    const tolerance = 8;\n    const groups = [];\n\n    mediaElements\n      .map(function (media) {\n        return {\n          media: media,\n          rect: media.getBoundingClientRect()\n        };\n      })\n      .sort(function (a, b) {\n        if (Math.abs(a.rect.top - b.rect.top) > tolerance) {\n          return a.rect.top - b.rect.top;\n        }\n\n        return a.rect.left - b.rect.left;\n      })\n      .forEach(function (entry) {\n        let group = groups.find(function (candidate) {\n          return Math.abs(candidate.top - entry.rect.top) <= tolerance;\n        });\n\n        if (!group) {\n          group = {\n            top: entry.rect.top,\n            entries: []\n          };\n          groups.push(group);\n        }\n\n        group.entries.push(entry);\n      });\n\n    groups.forEach(function (group) {\n      group.entries.sort(function (a, b) {\n        return a.rect.left - b.rect.left;\n      });\n    });\n\n    return groups;\n  }\n\n  function equalizeProjectGalleryRows() {\n    equalizeFrame = null;\n\n    if (equalizeRunning) return;\n    equalizeRunning = true;\n\n    const rows = getGalleryRows();\n\n    rows.forEach(function (row) {\n      let mediaElements = getGalleryImages(row);\n\n      \/*\n       * On r\u00e9tablit d'abord les dimensions naturelles afin que la premi\u00e8re\n       * image de chaque ligne soit mesur\u00e9e sans influence d'un ancien calcul.\n       *\/\n      mediaElements.forEach(function (media) {\n        clearEqualizedHeight(media, row);\n      });\n\n      mediaElements = getGalleryImages(row);\n\n      const groups = groupMediaByVisualLine(mediaElements);\n\n      groups.forEach(function (group) {\n        \/*\n         * Une image seule sur sa ligne conserve son ratio naturel.\n         * C'est notamment le comportement attendu quand une grille passe\n         * automatiquement \u00e0 une colonne sur mobile.\n         *\/\n        if (group.entries.length < 2) return;\n\n        const leftmost = group.entries[0];\n        const referenceHeight =\n          leftmost.media.getBoundingClientRect().height;\n\n        if (!Number.isFinite(referenceHeight) || referenceHeight <= 1) {\n          return;\n        }\n\n        group.entries.forEach(function (entry) {\n          setEqualizedHeight(\n            entry.media,\n            row,\n            referenceHeight\n          );\n        });\n      });\n    });\n\n    equalizeRunning = false;\n  }\n\n  function requestGalleryEqualization() {\n    if (equalizeFrame !== null) return;\n\n    equalizeFrame = window.requestAnimationFrame(function () {\n      window.requestAnimationFrame(\n        equalizeProjectGalleryRows\n      );\n    });\n  }\n\n  function observeGalleryRows() {\n    if (\"ResizeObserver\" in window && !resizeObserver) {\n      resizeObserver = new ResizeObserver(\n        requestGalleryEqualization\n      );\n    }\n\n    getGalleryRows().forEach(function (row) {\n      if (resizeObserver) resizeObserver.observe(row);\n\n      getGalleryImages(row).forEach(function (media) {\n        if (resizeObserver) resizeObserver.observe(media);\n\n        if (media.tagName === \"IMG\" && !media.complete) {\n          media.addEventListener(\n            \"load\",\n            requestGalleryEqualization,\n            { once: true }\n          );\n        }\n\n        if (media.tagName === \"VIDEO\") {\n          media.addEventListener(\n            \"loadedmetadata\",\n            requestGalleryEqualization,\n            { once: true }\n          );\n        }\n      });\n    });\n  }\n\n  function initializeProjectGalleryEqualization() {\n    observeGalleryRows();\n    requestGalleryEqualization();\n\n    \/*\n     * Elementor peut ajouter, dupliquer ou r\u00e9organiser les grilles apr\u00e8s\n     * l'initialisation. L'observer garde le calcul \u00e0 jour dans l'\u00e9diteur.\n     *\/\n    mutationObserver = new MutationObserver(function () {\n      observeGalleryRows();\n      requestGalleryEqualization();\n    });\n\n    mutationObserver.observe(document.documentElement, {\n      childList: true,\n      subtree: true,\n      attributes: true,\n      attributeFilter: [\"class\", \"style\", \"src\", \"srcset\"]\n    });\n\n    [80, 220, 500, 900, 1500, 2500].forEach(function (delay) {\n      window.setTimeout(function () {\n        observeGalleryRows();\n        requestGalleryEqualization();\n      }, delay);\n    });\n\n    if (document.fonts && document.fonts.ready) {\n      document.fonts.ready.then(\n        requestGalleryEqualization\n      );\n    }\n\n    window.addEventListener(\n      \"load\",\n      requestGalleryEqualization\n    );\n\n    window.addEventListener(\n      \"resize\",\n      requestGalleryEqualization,\n      { passive: true }\n    );\n\n    window.addEventListener(\n      \"pageshow\",\n      requestGalleryEqualization\n    );\n\n    window.addEventListener(\n      \"pimpe:project-ready\",\n      requestGalleryEqualization\n    );\n  }\n\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\n      \"DOMContentLoaded\",\n      initializeProjectGalleryEqualization,\n      { once: true }\n    );\n  } else {\n    initializeProjectGalleryEqualization();\n  }\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\n<\/div>\n<div class=\"elementor-element elementor-element-369f8d6 e-con e-atomic-element e-flexbox-base e-7ab160a project-content \" data-id=\"369f8d6\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"369f8d6\" data-e-type=\"e-flexbox\" data-id=\"369f8d6\">\n    \t\t<div class=\"elementor-element elementor-element-4160717 elementor-widget-mobile__width-inherit elementor-widget elementor-widget-heading\" data-id=\"4160717\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">CIDER<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7286824 elementor-widget elementor-widget-spacer\" data-id=\"7286824\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9cf67ae elementor-widget__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-heading\" data-id=\"9cf67ae\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Pour cette campagne r\u00e9alis\u00e9e autour de l\u2019influenceuse et mod\u00e8le Tabata, la mission consistait \u00e0 int\u00e9grer un \u00e9chiquier g\u00e9ant en 3D au sein d\u2019une photographie existante, afin de cr\u00e9er un visuel immersif, graphique et impactant pour la marque Cider.\n\nL\u2019enjeu \u00e9tait de faire cohabiter de mani\u00e8re cr\u00e9dible l\u2019image photographique et l\u2019environnement CGI, en travaillant l\u2019int\u00e9gration du d\u00e9cor, les perspectives, la lumi\u00e8re et l\u2019\u00e9chelle, afin que l\u2019\u00e9chiquier s\u2019inscrive naturellement dans la sc\u00e8ne tout en apportant une dimension spectaculaire.\n\nCe projet a \u00e9t\u00e9 pens\u00e9 comme un croisement entre mode, image publicitaire et d\u00e9cor digital, avec une attention particuli\u00e8re port\u00e9e au r\u00e9alisme du compositing et \u00e0 la force visuelle de l\u2019ensemble.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4fbd0cb elementor-widget elementor-widget-spacer\" data-id=\"4fbd0cb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-21d7e03 elementor-widget elementor-widget-heading\" data-id=\"21d7e03\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Services<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-290d185 elementor-widget elementor-widget-heading\" data-id=\"290d185\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Direction artistique<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-62ac0b0 elementor-widget elementor-widget-heading\" data-id=\"62ac0b0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">CGI<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-08ada0b elementor-widget elementor-widget-heading\" data-id=\"08ada0b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Post production<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-104fa86 elementor-widget elementor-widget-spacer\" data-id=\"104fa86\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f20b261 e-con e-atomic-element e-flexbox-base e-f20b261-ea9a85e project-cover hero-image \" data-id=\"f20b261\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"f20b261\" data-e-type=\"e-flexbox\" data-id=\"f20b261\">\n    \t\t<div class=\"elementor-element elementor-element-da15d4f elementor-widget elementor-widget-image\" data-id=\"da15d4f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"2048\" height=\"2560\" src=\"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-scaled.png\" class=\"attachment-large size-large wp-image-14389\" alt=\"\" srcset=\"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-scaled.png 2048w, https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-768x960.png 768w, https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-1229x1536.png 1229w, https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-1638x2048.png 1638w\" sizes=\"(max-width: 2048px) 100vw, 2048px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\n<\/div>\n<div class=\"elementor-element elementor-element-bc98344 e-grid project-gallery-row e-con-boxed e-con e-parent\" data-id=\"bc98344\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<img decoding=\"async\" class=\"e-image-base \" data-interaction-id=\"2480b05\" data-e-type=\"widget\" data-id=\"2480b05\" id=\"14388\" src=\"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-2-scaled.png\" width=\"2048\" height=\"2560\" srcset=\"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-2-scaled.png 2048w, https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-2-768x960.png 768w, https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-2-1229x1536.png 1229w, https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-2-1638x2048.png 1638w\" alt=\"\"\/>\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>CIDER Pour cette campagne r\u00e9alis\u00e9e autour de l\u2019influenceuse et mod\u00e8le Tabata, la mission consistait \u00e0 int\u00e9grer un \u00e9chiquier g\u00e9ant en 3D au sein d\u2019une photographie existante, afin de cr\u00e9er un visuel immersif, graphique et impactant pour la marque Cider. L\u2019enjeu \u00e9tait de faire cohabiter de mani\u00e8re cr\u00e9dible l\u2019image photographique et l\u2019environnement CGI, en travaillant l\u2019int\u00e9gration [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-14405","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Projet - CIDER<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/pimpestudio.fr\/en\/cider\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Projet - CIDER\" \/>\n<meta property=\"og:description\" content=\"CIDER Pour cette campagne r\u00e9alis\u00e9e autour de l\u2019influenceuse et mod\u00e8le Tabata, la mission consistait \u00e0 int\u00e9grer un \u00e9chiquier g\u00e9ant en 3D au sein d\u2019une photographie existante, afin de cr\u00e9er un visuel immersif, graphique et impactant pour la marque Cider. L\u2019enjeu \u00e9tait de faire cohabiter de mani\u00e8re cr\u00e9dible l\u2019image photographique et l\u2019environnement CGI, en travaillant l\u2019int\u00e9gration [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/pimpestudio.fr\/en\/cider\/\" \/>\n<meta property=\"og:site_name\" content=\"Pimp\u00e9 Studio\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-05T10:05:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-scaled.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2048\" \/>\n\t<meta property=\"og:image:height\" content=\"2560\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/\",\"url\":\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/\",\"name\":\"Projet - CIDER\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pimpestudio.fr\\\/wp-content\\\/uploads\\\/VISUEL-1-scaled.png\",\"datePublished\":\"2026-08-02T19:48:04+00:00\",\"dateModified\":\"2026-08-05T10:05:35+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/#primaryimage\",\"url\":\"https:\\\/\\\/pimpestudio.fr\\\/wp-content\\\/uploads\\\/VISUEL-1-scaled.png\",\"contentUrl\":\"https:\\\/\\\/pimpestudio.fr\\\/wp-content\\\/uploads\\\/VISUEL-1-scaled.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/cider\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/pimpestudio.fr\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Projet &#8211; CIDER\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/#website\",\"url\":\"https:\\\/\\\/pimpestudio.fr\\\/\",\"name\":\"Pimp\u00e9 Studio\",\"description\":\"Studio cr\u00e9atif\",\"publisher\":{\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/#\\\/schema\\\/person\\\/f01b954736bb16a50ed6447f2a231615\"},\"alternateName\":\"Pimp\u00e9\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/pimpestudio.fr\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/#\\\/schema\\\/person\\\/f01b954736bb16a50ed6447f2a231615\",\"name\":\"admin2823\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/wp-content\\\/uploads\\\/DTS_EDEN_Marlen_Stahlhuth_10129.webp\",\"url\":\"https:\\\/\\\/pimpestudio.fr\\\/wp-content\\\/uploads\\\/DTS_EDEN_Marlen_Stahlhuth_10129.webp\",\"contentUrl\":\"https:\\\/\\\/pimpestudio.fr\\\/wp-content\\\/uploads\\\/DTS_EDEN_Marlen_Stahlhuth_10129.webp\",\"width\":1280,\"height\":1217,\"caption\":\"admin2823\"},\"logo\":{\"@id\":\"https:\\\/\\\/pimpestudio.fr\\\/wp-content\\\/uploads\\\/DTS_EDEN_Marlen_Stahlhuth_10129.webp\"},\"sameAs\":[\"https:\\\/\\\/pimpestudio.fr\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Projet - CIDER","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:\/\/pimpestudio.fr\/en\/cider\/","og_locale":"en_US","og_type":"article","og_title":"Projet - CIDER","og_description":"CIDER Pour cette campagne r\u00e9alis\u00e9e autour de l\u2019influenceuse et mod\u00e8le Tabata, la mission consistait \u00e0 int\u00e9grer un \u00e9chiquier g\u00e9ant en 3D au sein d\u2019une photographie existante, afin de cr\u00e9er un visuel immersif, graphique et impactant pour la marque Cider. L\u2019enjeu \u00e9tait de faire cohabiter de mani\u00e8re cr\u00e9dible l\u2019image photographique et l\u2019environnement CGI, en travaillant l\u2019int\u00e9gration [&hellip;]","og_url":"https:\/\/pimpestudio.fr\/en\/cider\/","og_site_name":"Pimp\u00e9 Studio","article_modified_time":"2026-08-05T10:05:35+00:00","og_image":[{"url":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-scaled.png","width":2048,"height":2560,"type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/pimpestudio.fr\/cider\/","url":"https:\/\/pimpestudio.fr\/cider\/","name":"Projet - CIDER","isPartOf":{"@id":"https:\/\/pimpestudio.fr\/#website"},"primaryImageOfPage":{"@id":"https:\/\/pimpestudio.fr\/cider\/#primaryimage"},"image":{"@id":"https:\/\/pimpestudio.fr\/cider\/#primaryimage"},"thumbnailUrl":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-scaled.png","datePublished":"2026-08-02T19:48:04+00:00","dateModified":"2026-08-05T10:05:35+00:00","breadcrumb":{"@id":"https:\/\/pimpestudio.fr\/cider\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/pimpestudio.fr\/cider\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/pimpestudio.fr\/cider\/#primaryimage","url":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-scaled.png","contentUrl":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/VISUEL-1-scaled.png"},{"@type":"BreadcrumbList","@id":"https:\/\/pimpestudio.fr\/cider\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/pimpestudio.fr\/"},{"@type":"ListItem","position":2,"name":"Projet &#8211; CIDER"}]},{"@type":"WebSite","@id":"https:\/\/pimpestudio.fr\/#website","url":"https:\/\/pimpestudio.fr\/","name":"Pimp\u00e9 Studio","description":"Studio cr\u00e9atif","publisher":{"@id":"https:\/\/pimpestudio.fr\/#\/schema\/person\/f01b954736bb16a50ed6447f2a231615"},"alternateName":"Pimp\u00e9","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/pimpestudio.fr\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/pimpestudio.fr\/#\/schema\/person\/f01b954736bb16a50ed6447f2a231615","name":"admin2823","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/DTS_EDEN_Marlen_Stahlhuth_10129.webp","url":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/DTS_EDEN_Marlen_Stahlhuth_10129.webp","contentUrl":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/DTS_EDEN_Marlen_Stahlhuth_10129.webp","width":1280,"height":1217,"caption":"admin2823"},"logo":{"@id":"https:\/\/pimpestudio.fr\/wp-content\/uploads\/DTS_EDEN_Marlen_Stahlhuth_10129.webp"},"sameAs":["https:\/\/pimpestudio.fr"]}]}},"_links":{"self":[{"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/pages\/14405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/comments?post=14405"}],"version-history":[{"count":13,"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/pages\/14405\/revisions"}],"predecessor-version":[{"id":14575,"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/pages\/14405\/revisions\/14575"}],"wp:attachment":[{"href":"https:\/\/pimpestudio.fr\/en\/wp-json\/wp\/v2\/media?parent=14405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}