/**
 * WS Booster - CSS Widgets
 * Uniquement le strict necessaire pour le fonctionnement des widgets
 */

/* ==========================================================================
   Widget : Stack Cards (ws-stack-cards)
   ========================================================================== */

.ws-stack-cards {
    position: relative;
}

.ws-stack-card {
    position: sticky;
    width: 100%;
    transform-origin: top center;
    will-change: transform;
    overflow: hidden;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: center;
    background-color: #fff;
    border-radius: 20px;
    padding: 40px;
    margin-bottom: 20px;
}

.ws-stack-card__img {
    width: 100%;
    height: auto;
    object-fit: cover;
    border-radius: 12px;
    margin-bottom: 20px;
    display: block;
}

.ws-stack-card__content {
    flex: 1;
}

.ws-stack-card__subtitle {
    display: inline-block;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--e-global-color-accent, #6366f1);
    margin-bottom: 8px;
}

.ws-stack-card__title {
    font-size: 28px;
    font-weight: 700;
    line-height: 1.2;
    margin: 0 0 12px;
    color: var(--e-global-color-primary, #1a1a2e);
}

.ws-stack-card__desc {
    font-size: 16px;
    line-height: 1.65;
    margin: 0;
    color: var(--e-global-color-text, #475569);
}

/* ==========================================================================
   Widget : Marquee (ws-marquee)
   ========================================================================== */

.ws-marquee {
    overflow: hidden;
    width: 100%;
    position: relative;
}

.ws-marquee__track {
    display: flex;
    white-space: nowrap;
    will-change: transform;
    align-items: center;
    line-height: 1;
    margin: 0;
    padding: 0;
}

.ws-marquee__item {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: inherit;
    transition: opacity 0.2s ease, color 0.2s ease;
    line-height: 1.2;
    margin: 0;
}

a.ws-marquee__item:hover {
    opacity: 0.8;
}

.ws-marquee__img {
    height: 1.2em;
    width: auto;
}

.ws-marquee__text {
    display: inline-block;
}

.ws-marquee__sep {
    flex-shrink: 0;
    opacity: 0.5;
}

/* Reset les marges des elements internes (texte, img) pour eviter espace fantome en haut */
.ws-marquee__item > *,
.ws-marquee__sep > * {
    margin: 0;
}

/* Fade edges */
.ws-marquee--fade {
    --ws-marquee-fade: 10%;
    mask-image: linear-gradient(to right, transparent 0, #000 var(--ws-marquee-fade), #000 calc(100% - var(--ws-marquee-fade)), transparent 100%);
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--ws-marquee-fade), #000 calc(100% - var(--ws-marquee-fade)), transparent 100%);
}

/* ==========================================================================
   Widget : Ticker Advanced (ws-ticker)
   ========================================================================== */

.ws-ticker {
    overflow: hidden;
    width: 100%;
    position: relative;
}

.ws-ticker__track {
    display: flex;
    white-space: nowrap;
    will-change: transform;
    align-items: center;
}

.ws-ticker__item {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: inherit;
    transition: color 0.2s ease;
}

.ws-ticker__img {
    height: 1.2em;
    width: auto;
}

.ws-ticker__text { display: inline-block; }

.ws-ticker__sep {
    flex-shrink: 0;
    opacity: 0.5;
}

/* Text Reveal */
.ws-text-reveal .word,
.ws-text-reveal .char {
    display: inline-block;
}

/* ==========================================================================
   Widget : Carte 3D (ws-card-tilt)
   Structure BEM stricte + CSS vars + preserve-3d
   ========================================================================== */

.ws-card-tilt {
    position: relative;
    perspective: 800px;
    display: block;
    isolation: isolate;
}

.ws-card-tilt__link {
    display: block;
    text-decoration: none;
    color: inherit;
}

.ws-card-tilt__inner {
    position: relative;
    overflow: hidden;
    transform-style: preserve-3d;
    will-change: transform;
    background-color: #fff;
    border-radius: 12px;
    transition: box-shadow 0.3s ease, background-color 0.3s ease, border-color 0.3s ease;
    display: flex;
    flex-direction: column;
}

/* === Layout horizontal : image a gauche ou a droite ===
   Pattern CSS Grid pour forcer les 2 cellules a hauteur egale automatiquement.
   L'image-wrap occupe sa cellule a 100% en hauteur, sans dependre d'align-self stretch. */
.ws-card-tilt--img-left .ws-card-tilt__inner,
.ws-card-tilt--img-right .ws-card-tilt__inner {
    display: grid;
    grid-template-columns: var(--ws-ct-img-w, 45%) 1fr;
    align-items: stretch;
    flex-direction: initial;
}

.ws-card-tilt--img-right .ws-card-tilt__inner {
    grid-template-columns: 1fr var(--ws-ct-img-w, 45%);
}

/* Mode right : inverser l'ordre visuel (DOM = image, body) */
.ws-card-tilt--img-right .ws-card-tilt__image-wrap {
    grid-column: 2;
    grid-row: 1;
}

.ws-card-tilt--img-right .ws-card-tilt__body {
    grid-column: 1;
    grid-row: 1;
}

.ws-card-tilt--img-left .ws-card-tilt__image-wrap,
.ws-card-tilt--img-right .ws-card-tilt__image-wrap {
    height: auto;
    width: auto;
    min-height: 0;
    align-self: stretch;
}

.ws-card-tilt--img-left .ws-card-tilt__body,
.ws-card-tilt--img-right .ws-card-tilt__body {
    padding: 32px;
    justify-content: center;
    min-width: 0;
}

/* Responsive : sur mobile on repasse en vertical (flex column) */
@media (max-width: 600px) {
    .ws-card-tilt--img-left .ws-card-tilt__inner,
    .ws-card-tilt--img-right .ws-card-tilt__inner {
        display: flex;
        flex-direction: column;
        grid-template-columns: initial;
    }
    .ws-card-tilt--img-left .ws-card-tilt__image-wrap,
    .ws-card-tilt--img-right .ws-card-tilt__image-wrap {
        width: 100%;
        height: 220px;
        grid-column: auto;
        grid-row: auto;
    }
    .ws-card-tilt--img-right .ws-card-tilt__body {
        grid-column: auto;
        grid-row: auto;
    }
}

/* --- Image --- */
.ws-card-tilt__image-wrap {
    position: relative;
    overflow: hidden;
    flex-shrink: 0;
    height: 240px;
}

/* Image : !important necessaire pour override le `img { height: auto; max-width: 100% }`
   que les themes WordPress imposent par defaut (sinon l'image garde son aspect-ratio
   intrinseque et ne remplit pas le wrap stretche par la grid). */
.ws-card-tilt__image-wrap > .ws-card-tilt__image {
    position: absolute !important;
    inset: 0 !important;
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    max-height: none !important;
    min-width: 0 !important;
    min-height: 0 !important;
    object-fit: cover;
    object-position: center center;
    display: block;
    aspect-ratio: auto;
    transition: transform 0.5s ease;
    transform-origin: center center;
}

/* Zoom au survol */
.ws-card-tilt--zoom-yes:hover .ws-card-tilt__image {
    transform: scale(var(--ws-ct-zoom, 1.08));
}

/* --- Body (contenu texte + CTA) --- */
.ws-card-tilt__body {
    flex: 1;
    padding: 24px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.ws-card-tilt__body > * {
    margin: 0;
}

.ws-card-tilt__body > * + * {
    margin-top: 12px;
}

.ws-card-tilt__subtitle {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    line-height: 1;
    color: var(--e-global-color-accent, #667eea);
}

.ws-card-tilt__title {
    font-size: 22px;
    font-weight: 700;
    line-height: 1.25;
    margin: 0;
    color: var(--e-global-color-primary, #1a1a2e);
    transition: color 0.3s ease;
}

.ws-card-tilt__desc {
    font-size: 15px;
    line-height: 1.65;
    margin: 0;
    color: var(--e-global-color-text, #475569);
}

/* --- Meta (texte intermediaire : prix, badge, mention) --- */
.ws-card-tilt__meta {
    display: inline-block;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--e-global-color-accent, #c9a961);
    letter-spacing: 0.02em;
}

/* --- CTA --- */
.ws-card-tilt__cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 20px;
    border-radius: 6px;
    background-color: var(--e-global-color-accent, #6366f1);
    color: #fff;
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
    cursor: pointer;
    border: none;
    line-height: 1.2;
}

.ws-card-tilt__cta:hover {
    text-decoration: none;
}

.ws-card-tilt__cta-text {
    display: inline-block;
}

.ws-card-tilt__cta-icon {
    display: inline-flex;
    align-items: center;
    font-size: 0.9em;
    transition: transform 0.2s ease;
}

/* Position icone bouton : translateX au hover en sens de la fleche */
.ws-card-tilt__cta--icon-right:hover .ws-card-tilt__cta-icon {
    transform: translateX(3px);
}
.ws-card-tilt__cta--icon-left:hover .ws-card-tilt__cta-icon {
    transform: translateX(-3px);
}
/* Fallback pour l'ancien markup sans classe --icon-* */
.ws-card-tilt__cta:not(.ws-card-tilt__cta--icon-left):not(.ws-card-tilt__cta--icon-right):hover .ws-card-tilt__cta-icon {
    transform: translateX(3px);
}

/* Carte cliquable (card-link via JS) : curseur pointeur sur le wrapper */
.ws-card-tilt--has-link {
    cursor: pointer;
}
/* Mais les enfants <a> gardent leur propre curseur de lien (override visuel coherent) */
.ws-card-tilt--has-link a {
    cursor: pointer;
}

.ws-card-tilt__cta-icon svg,
.ws-card-tilt__cta-icon i {
    width: 1em;
    height: 1em;
    display: inline-block;
}

/* --- Glare (reflet 3D) --- */
.ws-card-tilt__glare {
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, #fff 0%, transparent 60%);
    opacity: 0;
    pointer-events: none;
    will-change: opacity, transform;
    mix-blend-mode: overlay;
}

/* Magnetic Button */
.ws-magnetic-btn-wrap {
    display: inline-block;
    /* Fix : evite l'espace fantome au dessus du bouton (baseline des inline-block) */
    vertical-align: top;
    line-height: 0;
}

.ws-magnetic-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    cursor: pointer;
    will-change: transform;
    transition: none;
    /* Restaure une line-height normale pour le texte du bouton */
    line-height: 1;
    vertical-align: top;
}

.ws-magnetic-btn__text {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    will-change: transform;
    pointer-events: none;
}

/* ===== Swipe effect (texte qui glisse puis revient du cote oppose) ===== */
.ws-magnetic-btn__label-wrap {
    position: relative;
    display: inline-block;
    overflow: hidden;
    line-height: 1.2;
    vertical-align: middle;
}

.ws-magnetic-btn__label-wrap .ws-magnetic-btn__label {
    display: block;
    transition: transform var(--ws-mb-swipe-duration, 400ms) cubic-bezier(0.65, 0, 0.35, 1);
}

.ws-magnetic-btn__label--clone {
    position: absolute;
    top: 0;
    left: 0;
}

/* Swipe UP : visible monte, clone arrive d'en bas */
.ws-mb--swipe-up .ws-magnetic-btn__label--visible { transform: translateY(0); }
.ws-mb--swipe-up .ws-magnetic-btn__label--clone   { transform: translateY(100%); }
.ws-mb--swipe-up .ws-magnetic-btn:hover .ws-magnetic-btn__label--visible { transform: translateY(-100%); }
.ws-mb--swipe-up .ws-magnetic-btn:hover .ws-magnetic-btn__label--clone   { transform: translateY(0); }

/* Swipe DOWN : inverse */
.ws-mb--swipe-down .ws-magnetic-btn__label--visible { transform: translateY(0); }
.ws-mb--swipe-down .ws-magnetic-btn__label--clone   { transform: translateY(-100%); }
.ws-mb--swipe-down .ws-magnetic-btn:hover .ws-magnetic-btn__label--visible { transform: translateY(100%); }
.ws-mb--swipe-down .ws-magnetic-btn:hover .ws-magnetic-btn__label--clone   { transform: translateY(0); }

/* Swipe LEFT */
.ws-mb--swipe-left .ws-magnetic-btn__label--visible { transform: translateX(0); }
.ws-mb--swipe-left .ws-magnetic-btn__label--clone   { transform: translateX(100%); }
.ws-mb--swipe-left .ws-magnetic-btn:hover .ws-magnetic-btn__label--visible { transform: translateX(-100%); }
.ws-mb--swipe-left .ws-magnetic-btn:hover .ws-magnetic-btn__label--clone   { transform: translateX(0); }

/* Swipe RIGHT */
.ws-mb--swipe-right .ws-magnetic-btn__label--visible { transform: translateX(0); }
.ws-mb--swipe-right .ws-magnetic-btn__label--clone   { transform: translateX(-100%); }
.ws-mb--swipe-right .ws-magnetic-btn:hover .ws-magnetic-btn__label--visible { transform: translateX(100%); }
.ws-mb--swipe-right .ws-magnetic-btn:hover .ws-magnetic-btn__label--clone   { transform: translateX(0); }

@media (prefers-reduced-motion: reduce) {
    .ws-magnetic-btn__label-wrap .ws-magnetic-btn__label {
        transition: none;
    }
}

/* ===== Phase 2 Widgets ===== */

/* Floating Grid */
.ws-floating-grid {
    display: flex;
    gap: 16px;
    overflow: hidden;
    align-items: flex-start;
}

.ws-floating-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 16px;
    will-change: transform;
}

.ws-floating-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
}

.ws-floating-item img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
}

.ws-item-name {
    font-weight: 600;
    font-size: 13px;
}

.ws-item-sub {
    font-size: 11px;
    color: #888;
}

/* Stack Sections */
.ws-stack-sections {
    position: relative;
}

.ws-stack-section {
    will-change: transform;
    transform-origin: top center;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.ws-stack-section__content {
    max-width: 800px;
    margin: 0 auto;
}

/* Ticker Advanced */
.ws-ticker-adv {
    overflow: hidden;
    width: 100%;
}

.ws-ticker-track {
    display: flex;
    white-space: nowrap;
    will-change: transform;
    align-items: center;
}

.ws-ticker-item {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    color: inherit;
}

.ws-ticker-item img {
    height: 1.2em;
    width: auto;
}

.ws-ticker-sep {
    flex-shrink: 0;
    opacity: 0.4;
}

/* Reviews Wall */
.ws-reviews-wall {
    display: flex;
    gap: 20px;
    align-items: flex-start;
    position: relative;
    overflow: hidden;
    max-height: 800px;
}

.ws-reviews-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 16px;
    will-change: transform;
}

/* Desactive le parallax (option admin) : les colonnes ne sont plus offsettees et on limite la hauteur pour eviter le chevauchement */
.ws-reviews-no-parallax-yes .ws-reviews-col {
    transform: none !important;
    will-change: auto;
}

.ws-reviews-no-parallax-yes .ws-reviews-wall {
    align-items: stretch;
}

.ws-review-card {
    background: var(--ws-card-bg, #fff);
    border-radius: 16px;
    padding: 20px;
    border: 1px solid rgba(0, 0, 0, 0.08);
}

.ws-review-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
}

.ws-review-stars {
    color: #FFB800;
    font-size: 14px;
    margin: 8px 0;
    letter-spacing: 2px;
}

.ws-review-text {
    font-size: 14px;
    line-height: 1.6;
    margin: 0 0 12px;
}

.ws-review-name {
    font-weight: 600;
    font-size: 14px;
    display: block;
}

.ws-review-role {
    font-size: 12px;
    color: #888;
}

/* Gradient Shader */
.ws-gradient-shader {
    position: relative;
    overflow: hidden;
}

.ws-shader-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.ws-noise-overlay {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    mix-blend-mode: overlay;
    opacity: 0.15;
}

/* X-Ray Hover */
.ws-xray {
    position: relative;
    overflow: hidden;
    cursor: crosshair;
    --ws-xray-border: rgba(255,255,255,0.6);
}

/* !important = override le `img { max-width:100%; height:auto }` que tous les
   themes WP appliquent par defaut. Voir bible §9.13. */
.ws-xray .ws-xray-before {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    max-height: none !important;
    object-fit: cover;
    display: block;
    position: absolute;
    inset: 0;
}

/* Image cachee : on utilise mask-image au lieu de clip-path pour avoir un bord
   doux/feather. Le mask est mis a jour en JS au mousemove. */
.ws-xray-after {
    position: absolute;
    inset: 0;
    -webkit-mask-image: radial-gradient(circle at 50% 50%, black 0px, transparent 0px);
            mask-image: radial-gradient(circle at 50% 50%, black 0px, transparent 0px);
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
}

.ws-xray .ws-xray-after > img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    max-height: none !important;
    object-fit: cover;
    display: block;
}

/* === LABELS === */
.ws-xray-label {
    position: absolute;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(0, 0, 0, 0.65);
    color: #fff;
    padding: 8px 14px;
    border-radius: 6px;
    font-size: 13px;
    line-height: 1.2;
    pointer-events: none;
    z-index: 5;
    max-width: calc(100% - 24px);
}

.ws-xray-label__icon {
    display: inline-flex;
    align-items: center;
}

.ws-xray-label__icon svg,
.ws-xray-label__icon i {
    width: 16px;
    height: 16px;
}

/* === 9 POSITIONS standard (comme background-position) === */
.ws-xray-pos-top-left      { top: 12px; left: 12px; }
.ws-xray-pos-top-center    { top: 12px; left: 50%; transform: translateX(-50%); }
.ws-xray-pos-top-right     { top: 12px; right: 12px; }
.ws-xray-pos-middle-left   { top: 50%; left: 12px; transform: translateY(-50%); }
.ws-xray-pos-middle-center { top: 50%; left: 50%; transform: translate(-50%, -50%); }
.ws-xray-pos-middle-right  { top: 50%; right: 12px; transform: translateY(-50%); }
.ws-xray-pos-bottom-left   { bottom: 12px; left: 12px; }
.ws-xray-pos-bottom-center { bottom: 12px; left: 50%; transform: translateX(-50%); }
.ws-xray-pos-bottom-right  { bottom: 12px; right: 12px; }

/* Indicateur visuel optionnel de la zone de reveal (cercle qui suit le curseur) */
.ws-xray__indicator {
    position: absolute;
    pointer-events: none;
    border: 1px solid var(--ws-xray-border, rgba(255,255,255,0.6));
    border-radius: 50%;
    transform: translate(-50%, -50%);
    opacity: 0;
    transition: opacity 0.2s ease;
}

.ws-xray:hover .ws-xray__indicator {
    opacity: 1;
}

/* Sticky Timeline / Sticky Steps */
.ws-sticky-timeline {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 60px;
    align-items: start;
    /* important : permet au sticky de s'engager dans toute la hauteur disponible */
    position: relative;
}

.ws-timeline-sticky {
    position: -webkit-sticky;
    position: sticky;
    top: 100px;
    /* Conteneur sticky doit avoir une hauteur naturelle, pas force */
    align-self: start;
}

.ws-timeline-sticky-title {
    margin: 0 0 20px;
}

/* Conteneur des images empilees. Toutes en position absolute,
   on switch les classes is-active au scroll. */
.ws-timeline-image-stack {
    --ws-tl-trans-speed: 0.5s;
    --ws-tl-stack-rot: 6deg;
    --ws-tl-stack-offset: 16px;
    position: relative;
    width: 100%;
    height: 70vh;
}

/* Toutes les images : empilees + cachees par defaut.
   !important sur dims pour override theme WP (bible 9.13). */
.ws-timeline-image {
    position: absolute !important;
    top: 0;
    left: 0;
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    max-height: none !important;
    object-fit: cover !important;
    border-radius: 16px;
    will-change: opacity, transform;
}

/* === MODE FADE === */
.ws-tl-trans-fade .ws-timeline-image {
    opacity: 0;
    transform: scale(0.96);
    transition: opacity var(--ws-tl-trans-speed, 0.5s) ease,
                transform var(--ws-tl-trans-speed, 0.5s) ease;
    z-index: 1;
}
.ws-tl-trans-fade .ws-timeline-image.ws-active {
    opacity: 1;
    transform: scale(1);
    z-index: 2;
}

/* === MODE STACK (pile d'images, polaroid) === */
.ws-tl-trans-stack .ws-timeline-image {
    opacity: 0.6;
    transform:
        translate(var(--ws-tl-stack-offset, 16px), var(--ws-tl-stack-offset, 16px))
        rotate(var(--ws-tl-stack-rot, 6deg))
        scale(0.92);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
    transition:
        opacity var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.22, 1, 0.36, 1),
        transform var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.22, 1, 0.36, 1),
        z-index 0s var(--ws-tl-trans-speed, 0.5s);
    z-index: 1;
}

/* Image active : centree, scale 1, devant */
.ws-tl-trans-stack .ws-timeline-image.ws-active {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg) scale(1);
    z-index: 5;
    transition:
        opacity var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.22, 1, 0.36, 1),
        transform var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.22, 1, 0.36, 1);
}

/* Image precedente (la derniere active) : tombe legerement vers l'autre cote */
.ws-tl-trans-stack .ws-timeline-image.ws-prev {
    opacity: 0.5;
    transform:
        translate(calc(var(--ws-tl-stack-offset, 16px) * -1), var(--ws-tl-stack-offset, 16px))
        rotate(calc(var(--ws-tl-stack-rot, 6deg) * -1))
        scale(0.92);
    z-index: 3;
}

.ws-timeline-steps {
    display: flex;
    flex-direction: column;
    gap: 60px;
}

.ws-timeline-step {
    /* Chaque etape prend une hauteur d'ecran : permet au sticky de fonctionner
       (si toutes les etapes etaient courtes, l'image ne resterait pas collee
       suffisamment longtemps pour qu'on voie l'effet sticky). */
    min-height: 70vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    opacity: 0.4;
    transition: opacity 0.4s;
}

.ws-timeline-step.ws-active {
    opacity: 1;
}

.ws-step-number {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.ws-step-title {
    font-size: 24px;
    font-weight: 700;
    margin: 8px 0;
}

.ws-step-desc {
    font-size: 16px;
    line-height: 1.7;
    margin: 0;
}

/* === MODE ZOOM AVANT (l'image grandit en apparaissant) === */
.ws-tl-trans-zoom-in .ws-timeline-image {
    opacity: 0;
    transform: scale(0.72);
    transition: opacity var(--ws-tl-trans-speed, 0.5s) ease,
                transform var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.22, 1, 0.36, 1);
    z-index: 1;
}
.ws-tl-trans-zoom-in .ws-timeline-image.ws-active {
    opacity: 1;
    transform: scale(1);
    z-index: 2;
}

/* === MODE ZOOM ARRIERE / DEZOOM === */
.ws-tl-trans-zoom-out .ws-timeline-image {
    opacity: 0;
    transform: scale(1.35);
    transition: opacity var(--ws-tl-trans-speed, 0.5s) ease,
                transform var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.22, 1, 0.36, 1);
    z-index: 1;
}
.ws-tl-trans-zoom-out .ws-timeline-image.ws-active {
    opacity: 1;
    transform: scale(1);
    z-index: 2;
}

/* === MODE SWIPE (glissement horizontal) === */
.ws-tl-trans-swipe .ws-timeline-image-stack {
    overflow: hidden;
}
.ws-tl-trans-swipe .ws-timeline-image {
    opacity: 0;
    transform: translateX(60px);
    transition: opacity var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.65, 0, 0.35, 1),
                transform var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.65, 0, 0.35, 1);
    z-index: 1;
}
.ws-tl-trans-swipe .ws-timeline-image.ws-active {
    opacity: 1;
    transform: translateX(0);
    z-index: 2;
}
.ws-tl-trans-swipe .ws-timeline-image.ws-prev {
    opacity: 0;
    transform: translateX(-60px);
    z-index: 1;
}

/* === MODE TAS EPARPILLE (scatter) ===
   Toutes les photos sont visibles en meme temps, posees en desordre facon
   tas de tirages, debordant un peu de la zone. La photo de l'etape active
   passe devant (droite, centree, plus grande).
   Selecteurs a 3 niveaux (.ws-timeline-image-stack en plus) pour battre les
   regles .ws-tl-trans-* qui restent appliquees (le mode transition est juste
   masque cote reglages, sa classe reste sur le widget). */
.ws-tl-display-scatter .ws-timeline-image-stack,
.ws-tl-display-scatter .ws-timeline-sticky {
    overflow: visible;
}
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image {
    opacity: 1;
    box-shadow: 0 14px 36px rgba(0, 0, 0, 0.22);
    transition: transform var(--ws-tl-trans-speed, 0.5s) cubic-bezier(0.22, 1, 0.36, 1),
                box-shadow var(--ws-tl-trans-speed, 0.5s) ease,
                opacity var(--ws-tl-trans-speed, 0.5s) ease;
    z-index: 1;
}
/* 6 positions distinctes, cyclees via nth-child(6n+X) */
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image:nth-child(6n+1) {
    transform: translate(calc(var(--ws-tl-scatter-spread, 56px) * -1), calc(var(--ws-tl-scatter-spread, 56px) * -0.5)) rotate(calc(var(--ws-tl-scatter-rot, 9deg) * -1)) scale(0.82);
}
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image:nth-child(6n+2) {
    transform: translate(calc(var(--ws-tl-scatter-spread, 56px) * 0.95), calc(var(--ws-tl-scatter-spread, 56px) * -0.65)) rotate(calc(var(--ws-tl-scatter-rot, 9deg) * 0.7)) scale(0.82);
}
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image:nth-child(6n+3) {
    transform: translate(calc(var(--ws-tl-scatter-spread, 56px) * -0.7), calc(var(--ws-tl-scatter-spread, 56px) * 0.85)) rotate(calc(var(--ws-tl-scatter-rot, 9deg) * 1)) scale(0.82);
}
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image:nth-child(6n+4) {
    transform: translate(calc(var(--ws-tl-scatter-spread, 56px) * 1), calc(var(--ws-tl-scatter-spread, 56px) * 0.6)) rotate(calc(var(--ws-tl-scatter-rot, 9deg) * -0.8)) scale(0.82);
}
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image:nth-child(6n+5) {
    transform: translate(calc(var(--ws-tl-scatter-spread, 56px) * 0.25), calc(var(--ws-tl-scatter-spread, 56px) * -1)) rotate(calc(var(--ws-tl-scatter-rot, 9deg) * 0.45)) scale(0.82);
}
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image:nth-child(6n) {
    transform: translate(calc(var(--ws-tl-scatter-spread, 56px) * -0.45), calc(var(--ws-tl-scatter-spread, 56px) * 0.35)) rotate(calc(var(--ws-tl-scatter-rot, 9deg) * -0.55)) scale(0.82);
}
/* Photo qui vient de quitter l'etat actif : au-dessus du tas, sous l'active */
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image.ws-prev {
    z-index: 5;
}
/* Photo de l'etape active : droite, centree, plus grande, devant le tas */
.ws-tl-display-scatter .ws-timeline-image-stack .ws-timeline-image.ws-active {
    transform: translate(0, 0) rotate(0deg) scale(0.96);
    z-index: 10;
    box-shadow: 0 26px 64px rgba(0, 0, 0, 0.34);
}

/* === BOUTON optionnel par etape === */
.ws-tl-step-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    align-self: flex-start;
    margin-top: 18px;
    padding: 12px 24px;
    background: #0f172a;
    color: #ffffff;
    border-radius: 8px;
    font-weight: 600;
    font-size: 14px;
    line-height: 1;
    text-decoration: none;
    transition: background-color 0.25s ease, color 0.25s ease, transform 0.2s ease;
}
.ws-tl-step-btn:hover {
    background: #1e293b;
}
.ws-tl-step-btn__icon {
    display: inline-flex;
    align-items: center;
}
.ws-tl-step-btn__icon svg,
.ws-tl-step-btn__icon i {
    width: 16px;
    height: 16px;
    font-size: 14px;
}

/* ==========================================================================
   Widget : Titre Premium (ws-heading-enhanced)
   ========================================================================== */

.ws-heading-enhanced-link {
    text-decoration: none;
    color: inherit;
}

.ws-heading-enhanced {
    margin: 0;
    line-height: 1.2;
}

/* Spans wrappers pour pouvoir styliser independemment chaque partie. Display
   inline par defaut pour conserver le wrap naturel du texte. Le user peut
   passer en inline-block ou block via le control "Affichage" pour activer
   padding/border/radius.
   box-decoration-break: clone permet au fond + padding + radius de se
   reproduire proprement sur chaque ligne en mode inline (effet "marqueur").

   v4.9.94 FIX BG OVERFLOW : line-height: 1.1 (plus tight que le 1.2 du
   parent) pour que le bg-color en mode inline colle plus pres du texte
   et ne deborde pas au-dessus / en-dessous des mots. Si l'user veut
   un debordement (effet "marker hauteur de ligne pleine"), il peut le
   override via Typography > line-height. Si l'user a active un bg ET
   veut qu'il colle EXACTEMENT au texte, le mieux reste de passer
   Affichage en "inline-block" (cf description du controle). */
.ws-heading-enhanced__before,
.ws-heading-enhanced__after {
    display: inline;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}

.ws-highlight {
    display: inline;
}

/* v4.9.x : transforms via CSS variables SUPPRIMES sur demande user 2026-05-30.
   Cf widgets/class-widget-heading-enhanced.php pour le contexte. Le user utilise
   le controle natif Elementor (onglet Avance > Transformer) qui marche pour
   l'ensemble du widget. */

/* v4.9.x : disposition "Empilees" - chaque part sur sa propre ligne.
   Pose display:block sur les 3 spans (before / highlight / after) pour
   les passer en colonne sans avoir a inserer des <br> manuels.
   Specificite renforcee (.ws-heading-enhanced--stacked > .ws-highlight)
   pour battre la regle .ws-highlight ci-dessus. */
.ws-heading-enhanced--stacked .ws-heading-enhanced__before,
.ws-heading-enhanced--stacked .ws-highlight,
.ws-heading-enhanced--stacked .ws-heading-enhanced__after {
    display: block;
}
/* En mode stacked, on supprime aussi l'espace separateur entre les parts
   (qui ne serait plus visible mais cree un petit gap horizontal residuel
   sur certaines polices). Le margin-top ajuste l'espace vertical entre
   chaque ligne ; mettre 0 pour qu'elles soient collees. */
.ws-heading-enhanced--stacked .ws-heading-enhanced__before + .ws-highlight,
.ws-heading-enhanced--stacked .ws-highlight + .ws-heading-enhanced__after,
.ws-heading-enhanced--stacked .ws-heading-enhanced__before + .ws-heading-enhanced__after {
    margin-top: 0;
}

/* Couleur unie - v4.9.114 : couleur defaut posee ici pour visibilite immediate
   (le controle dedie a ete supprime, Style > Mot mis en valeur > Couleur texte
   override quand l'user veut une autre couleur). */
.ws-highlight--color {
    color: #667eea;
}

/* Gradient
   IMPORTANT v4.9.105 (fix bug 2) : on definit un background-image PAR DEFAUT
   ici dans le CSS du plugin. Avant ce fix, si Elementor n'avait pas encore
   regenere son CSS inline (cas frequent juste apres l'ajout du widget,
   ou si le cache n'est pas a jour), le texte etait `color: transparent`
   SANS background-image -> totalement invisible. Le default ici (#667eea
   -> #764ba2) MATCH les defaults des controles gradient_color_1/2/angle
   du widget. Quand Elementor injecte son CSS inline avec les valeurs
   choisies par l'user, sa specificite (avec .elementor-element-XXX)
   override ce default. Donc zero changement de comportement pour
   l'user, juste un fail-safe quand le cache n'a pas suivi. */
.ws-highlight--gradient {
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    background-image: linear-gradient(135deg, #667eea, #764ba2);
}

/* Outline (contour uniquement) */
.ws-highlight--outline {
    -webkit-text-stroke: 2px currentColor;
    color: transparent;
    -webkit-text-fill-color: transparent;
}

/* Surlignage (marqueur)
   display: inline + box-decoration-break: clone permet au highlight de
   wrapper proprement sur plusieurs lignes : chaque ligne visible recoit
   son propre rectangle de fond + padding + radius (comme un marqueur
   physique). Sans ca (inline-block), le bloc orange serait UN seul gros
   rectangle qui casse la lisibilite multi-ligne.

   v4.9.x : padding passe de 8px 16px (px fixes) a 0.05em 0.4em
   (em proportionnel au font-size). Le padding vertical fixe en px
   ajoutait un espace fantome enorme sur les gros titres (line-height
   1.4 d'un titre 80px = rectangle 112px haut, alors que le glyph fait
   ~60px). En em, le padding s'adapte a la taille du texte et le
   rectangle colle visuellement aux lettres.
   Override toujours possible via le controle highlight_padding du widget. */
.ws-highlight--highlight {
    display: inline;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    /* v4.9.x : padding vertical = 0 STRICT. Sur un titre 80px, meme 0.05em
       (=4px) creait un gap visible entre 2 lignes consecutives separees par
       <br>. Avec 0, les rectangles se touchent sans espace. Padding lateral
       en em (proportionnel font-size) pour respirer autour des lettres.
       Override via le controle highlight_padding du widget si besoin. */
    padding: 0 0.4em;
    border-radius: 4px;
}

/* Soulignement epais
   Specificite doublee (.ws-highlight.ws-highlight--underline) pour battre
   le helper add_part_style_controls qui applique display: inline par defaut
   sur .ws-highlight (specificite egale, mais cascade order Elementor met
   le helper apres = il gagne sans cette double-class). */
.ws-highlight.ws-highlight--underline {
    border-bottom: 4px solid;
    padding-bottom: 2px;
    display: inline-block;
    line-height: 1;
}

/* Soulignement ondule */
.ws-highlight--wavy {
    text-decoration: underline wavy;
    text-decoration-thickness: 3px;
    text-underline-offset: 6px;
}

/* Gradient ANIME (vague qui se deplace) */
.ws-highlight--gradient_animated {
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    background-size: 300% 100%;
    background-position: 0% 50%;
    animation: ws-highlight-wave var(--ws-hl-anim-speed, 6s) ease-in-out infinite;
}

@keyframes ws-highlight-wave {
    0%, 100% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
}

/* Gradient SHIMMER : trait blanc qui traverse le gradient */
.ws-highlight--gradient_shimmer {
    position: relative;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    background-size: 200% 100%;
    animation: ws-highlight-shimmer var(--ws-hl-anim-speed, 6s) linear infinite;
}

@keyframes ws-highlight-shimmer {
    0% { background-position: -200% 50%; }
    100% { background-position: 200% 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .ws-highlight--gradient_animated,
    .ws-highlight--gradient_shimmer,
    .ws-highlight--text_shine {
        animation: none;
    }
}

/* ==========================================================================
   Titre Premium - DECORATIONS (v4.9.102)
   2 decorations independantes (main + secondary), 9 types (tiret, dot, icon,
   burst, sparkle, chevrons, frame, arrow, shooting_star), 4 positions chacune.
   Structure HTML :
     .ws-he-wrap.ws-he-wrap-outer  (flex column)
       .ws-he-slot--above          (1 ou 2 decos en haut)
       .ws-he-row                  (flex row : before + heading + after)
       .ws-he-slot--below          (1 ou 2 decos en bas)
   Le wrap n'existe QUE quand au moins une deco est active. Sans deco
   le rendu reste strictement identique (zero regression).
   ========================================================================== */

/* === Wrapper outer (flex column verticale pour above/heading/below) === */
.ws-he-wrap-outer {
    --ws-he-deco-color: #C68B5C;
    --ws-he-tiret-len: 60px;
    --ws-he-tiret-thick: 2px;
    --ws-he-dot-size: 10px;
    --ws-he-icon-size: 28px;
    --ws-he-deco-gap: 16px;
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: var(--ws-he-deco-gap, 16px);
}

/* === Row (flex row horizontale pour before/heading/after) === */
.ws-he-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    flex-wrap: nowrap;
    min-width: 0;
    gap: var(--ws-he-deco-gap, 16px);
}

/* === Slot above/below : flex row pour pouvoir avoir 2 decos cote-a-cote === */
.ws-he-slot {
    display: flex;
    align-items: center;
    gap: var(--ws-he-deco-gap, 16px);
}

/* === Heading dans le row : prend l'espace dispo === */
.ws-he-row .ws-heading-enhanced {
    min-width: 0;
    flex: 1 1 auto;
}

/* === DECO BASE : inline-flex centre, couleur via var === */
.ws-he-deco {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    color: var(--ws-he-deco-color, #C68B5C);
    line-height: 1;
}

/* Deco secondaire : fallback en cascade pour la couleur
   (deco2 color -> deco color -> fallback). Permet d'avoir
   independance + heritage si l'user ne configure pas. */
.ws-he-deco--secondary {
    color: var(--ws-he-deco2-color, var(--ws-he-deco-color, #C68B5C));
}

/* ===================== TIRET ===================== */
.ws-he-deco--tiret {
    width: var(--ws-he-tiret-len, 60px);
    height: var(--ws-he-tiret-thick, 2px);
    border-radius: calc(var(--ws-he-tiret-thick, 2px) / 2);
    background: var(--ws-he-deco-color, #C68B5C);
}
.ws-he-deco--secondary.ws-he-deco--tiret {
    width: var(--ws-he-tiret2-len, var(--ws-he-tiret-len, 60px));
    height: var(--ws-he-tiret2-thick, var(--ws-he-tiret-thick, 2px));
    background: var(--ws-he-deco2-color, var(--ws-he-deco-color, #C68B5C));
}

.ws-he-deco--tiret-gradient {
    background: linear-gradient(
        to right,
        transparent 0%,
        var(--ws-he-deco-color, #C68B5C) 25%,
        var(--ws-he-deco-color, #C68B5C) 75%,
        transparent 100%
    );
}

/* Double tiret : pseudo-element ::after */
.ws-he-deco--tiret-double {
    height: 1px;
    background: var(--ws-he-deco-color, #C68B5C);
    position: relative;
    overflow: visible;
}
.ws-he-deco--tiret-double::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    height: var(--ws-he-tiret-thick, 2px);
    background: var(--ws-he-deco-color, #C68B5C);
    border-radius: calc(var(--ws-he-tiret-thick, 2px) / 2);
}

/* ===================== POINT ===================== */
.ws-he-deco--dot {
    width: var(--ws-he-dot-size, 10px);
    height: var(--ws-he-dot-size, 10px);
    border-radius: 50%;
    background: var(--ws-he-deco-color, #C68B5C);
}
.ws-he-deco--secondary.ws-he-deco--dot {
    width: var(--ws-he-dot2-size, var(--ws-he-dot-size, 10px));
    height: var(--ws-he-dot2-size, var(--ws-he-dot-size, 10px));
    background: var(--ws-he-deco2-color, var(--ws-he-deco-color, #C68B5C));
}

/* ===================== ICONE (picker Elementor) ===================== */
.ws-he-deco--icon {
    font-size: var(--ws-he-icon-size, 28px);
    width: auto;
    height: 1em;
    color: var(--ws-he-deco-color, #C68B5C);
}
.ws-he-deco--secondary.ws-he-deco--icon {
    font-size: var(--ws-he-icon2-size, var(--ws-he-icon-size, 28px));
    color: var(--ws-he-deco2-color, var(--ws-he-deco-color, #C68B5C));
}

.ws-he-deco--icon svg,
.ws-he-deco--icon img,
.ws-he-deco--icon i {
    width: 1em;
    height: 1em;
    max-width: 1em;
    max-height: 1em;
    display: block;
    color: inherit;
    fill: currentColor;
}

.ws-he-deco--icon i {
    font-size: inherit;
    line-height: 1;
    width: auto;
    height: auto;
}

/* ===================== TYPES SVG PRESETS v4.9.102 =====================
   burst / sparkle / chevrons / frame / arrow / shooting_star
   Le SVG inline utilise currentColor pour stroke + fill. Taille pilotee
   par font-size (la classe partage la regle .ws-he-deco--icon pour svg). */
.ws-he-deco--svg {
    font-size: var(--ws-he-icon-size, 28px);
    width: 1em;
    height: 1em;
    color: var(--ws-he-deco-color, #C68B5C);
}
.ws-he-deco--secondary.ws-he-deco--svg {
    font-size: var(--ws-he-icon2-size, var(--ws-he-icon-size, 28px));
    color: var(--ws-he-deco2-color, var(--ws-he-deco-color, #C68B5C));
}

.ws-he-deco--svg svg {
    width: 100%;
    height: 100%;
    display: block;
    stroke: currentColor;
    fill: none;
}

/* === AUTO-MIRROR : decorations asymetriques flipees sur position 'after' ===
   Burst/Chevrons/Frame/Arrow pointent par defaut a droite. Sur position
   'after' (apres le titre), on flip horizontalement pour orientation
   naturelle (pointe vers le titre / vers l'interieur).
   Le prefix_class ws-he-pos-after est pose au niveau du widget par Elementor.
   Pour deco 2 -> ws-he-pos2-after. */
.ws-he-pos-after .ws-he-deco--main.ws-he-deco--burst,
.ws-he-pos-after .ws-he-deco--main.ws-he-deco--chevrons,
.ws-he-pos-after .ws-he-deco--main.ws-he-deco--frame,
.ws-he-pos-after .ws-he-deco--main.ws-he-deco--arrow,
.ws-he-pos2-after .ws-he-deco--secondary.ws-he-deco--burst,
.ws-he-pos2-after .ws-he-deco--secondary.ws-he-deco--chevrons,
.ws-he-pos2-after .ws-he-deco--secondary.ws-he-deco--frame,
.ws-he-pos2-after .ws-he-deco--secondary.ws-he-deco--arrow {
    transform: scaleX(-1);
}

/* Sparkle et shooting_star : pas de mirror (symetriques ou directionnels
   non-pointage). */

/* ==========================================================================
   v4.9.104 : Decoration CIBLEE sur une partie (before/highlight/after)
   Quand l'user met une deco avec target=before/highlight/after, la partie
   ciblee est wrappee dans un .ws-he-part-wrap (inline-flex column) pour
   permettre les 4 positions (gauche/haut/droite/bas) autour d'elle SANS
   sortir du flux inline du H2.
   ========================================================================== */

/* Le wrap est inline-flex (column) pour rester dans le flux du texte mais
   permettre un layout vertical interne (slot above / row middle / slot below). */
.ws-he-part-wrap {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    vertical-align: middle;
    line-height: 1.2;
}

/* Row : flex row horizontal pour deco-gauche + partie + deco-droite. */
.ws-he-part-row {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--ws-he-deco-gap, 12px);
    line-height: inherit;
}

/* Slots above/below : flex pour pouvoir avoir 2 decos cote-a-cote. */
.ws-he-part-slot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ws-he-deco-gap, 12px);
    line-height: 1;
}

/* La partie ciblee dans son wrap garde son display naturel (inline) mais
   se comporte comme un flex-item du row. */
.ws-he-part-row > .ws-heading-enhanced__before,
.ws-he-part-row > .ws-heading-enhanced__after,
.ws-he-part-row > .ws-highlight {
    flex: 0 1 auto;
    min-width: 0;
}

/* Patterns de fond */
[data-ws-pattern="dots"] {
    background-image: radial-gradient(circle, var(--ws-pattern-color) 1px, transparent 1px);
    background-size: var(--ws-pattern-size) var(--ws-pattern-size);
}

[data-ws-pattern="grid"] {
    background-image:
        linear-gradient(var(--ws-pattern-color) 1px, transparent 1px),
        linear-gradient(90deg, var(--ws-pattern-color) 1px, transparent 1px);
    background-size: var(--ws-pattern-size) var(--ws-pattern-size);
}

[data-ws-pattern="lines"] {
    background-image: repeating-linear-gradient(
        45deg,
        var(--ws-pattern-color) 0,
        var(--ws-pattern-color) 1px,
        transparent 0,
        transparent 50%
    );
    background-size: var(--ws-pattern-size) var(--ws-pattern-size);
}

[data-ws-pattern="cross"] {
    background-image:
        linear-gradient(var(--ws-pattern-color) 1px, transparent 1px),
        linear-gradient(90deg, var(--ws-pattern-color) 1px, transparent 1px);
    background-size: var(--ws-pattern-size) var(--ws-pattern-size);
    background-position: center center;
}

/* === NOISE / GRAIN === SVG feTurbulence en data-URI, mix-blend-mode pour s'adapter
   au fond. Style "Stripe / Linear / Resend". --ws-pattern-color contole l'intensite. */
[data-ws-pattern="noise"]::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    background-size: 240px 240px;
    opacity: 0.45;
    mix-blend-mode: overlay;
}

[data-ws-pattern="noise"] {
    position: relative;
    isolation: isolate;
}

/* === TOPOGRAPHIC === lignes courbes type carte topo (Apple, Stripe). */
[data-ws-pattern="topographic"] {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><g fill='none' stroke='black' stroke-width='1' opacity='1'><path d='M-20 80 Q 50 40 100 80 T 220 80'/><path d='M-20 110 Q 50 70 100 110 T 220 110'/><path d='M-20 140 Q 50 100 100 140 T 220 140'/><path d='M-20 170 Q 50 130 100 170 T 220 170'/><path d='M-20 50 Q 50 10 100 50 T 220 50'/></g></svg>");
    background-size: var(--ws-pattern-size) var(--ws-pattern-size);
    background-color: transparent;
}

[data-ws-pattern="topographic"] {
    background-image: linear-gradient(0deg, transparent, transparent),
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><g fill='none' stroke-width='1.2' opacity='0.85'><path stroke='currentColor' d='M-20 80 Q 50 40 100 80 T 220 80'/><path stroke='currentColor' d='M-20 110 Q 50 70 100 110 T 220 110'/><path stroke='currentColor' d='M-20 140 Q 50 100 100 140 T 220 140'/><path stroke='currentColor' d='M-20 170 Q 50 130 100 170 T 220 170'/><path stroke='currentColor' d='M-20 50 Q 50 10 100 50 T 220 50'/></g></svg>");
    color: var(--ws-pattern-color);
    background-size: calc(var(--ws-pattern-size) * 8) calc(var(--ws-pattern-size) * 8);
    background-repeat: repeat;
}

/* === HALFTONE === radial-gradient repete avec dots qui paraissent varier */
[data-ws-pattern="halftone"] {
    background-image:
        radial-gradient(circle at 25% 25%, var(--ws-pattern-color) 2px, transparent 2.5px),
        radial-gradient(circle at 75% 75%, var(--ws-pattern-color) 1px, transparent 1.5px),
        radial-gradient(circle at 50% 50%, var(--ws-pattern-color) 0.5px, transparent 1px);
    background-size: var(--ws-pattern-size) var(--ws-pattern-size);
}

/* === WAVY LINES === ondulations horizontales repetees */
[data-ws-pattern="wavy"] {
    background-image: linear-gradient(0deg, transparent, transparent),
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 20'><path fill='none' stroke='currentColor' stroke-width='1.2' d='M0 10 Q 12.5 0 25 10 T 50 10 T 75 10 T 100 10'/></svg>");
    color: var(--ws-pattern-color);
    background-size: calc(var(--ws-pattern-size) * 4) calc(var(--ws-pattern-size) * 0.8);
    background-repeat: repeat;
}

/* === DIAMOND / LOSANGES === pattern losanges via 2 gradients diagonaux */
[data-ws-pattern="diamond"] {
    background-image:
        linear-gradient(45deg, var(--ws-pattern-color) 25%, transparent 25%, transparent 75%, var(--ws-pattern-color) 75%),
        linear-gradient(45deg, var(--ws-pattern-color) 25%, transparent 25%, transparent 75%, var(--ws-pattern-color) 75%);
    background-size: var(--ws-pattern-size) var(--ws-pattern-size);
    background-position: 0 0, calc(var(--ws-pattern-size) / 2) calc(var(--ws-pattern-size) / 2);
    opacity: 1;
}

[data-ws-pattern="diamond"] {
    background-image: linear-gradient(0deg, transparent, transparent),
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'><path fill='none' stroke='currentColor' stroke-width='1' d='M20 4 L36 20 L20 36 L4 20 Z'/></svg>");
    color: var(--ws-pattern-color);
    background-size: calc(var(--ws-pattern-size) * 1.7) calc(var(--ws-pattern-size) * 1.7);
    background-repeat: repeat;
}

/* === HEXAGONAL === nid d'abeille via SVG hex repete */
[data-ws-pattern="hexagonal"] {
    background-image: linear-gradient(0deg, transparent, transparent),
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 52'><g fill='none' stroke='currentColor' stroke-width='1'><path d='M15 4 L30 4 L37 16 L30 28 L15 28 L8 16 Z'/><path d='M37 28 L52 28 L60 40 L52 52 L37 52 L30 40 Z'/><path d='M-7 28 L8 28 L15 40 L8 52 L-7 52 L-15 40 Z'/></g></svg>");
    color: var(--ws-pattern-color);
    background-size: calc(var(--ws-pattern-size) * 2.5) calc(var(--ws-pattern-size) * 2.2);
    background-repeat: repeat;
}

/* ===== Modal ===== */

/* Overlay */
.ws-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 99998;
    background: var(--overlay-color, rgba(0, 0, 0, 0.6));
    backdrop-filter: blur(var(--overlay-blur, 0px));
    -webkit-backdrop-filter: blur(var(--overlay-blur, 0px));
    opacity: 0;
    pointer-events: none;
    transition: none;
}

.ws-modal-overlay.ws-modal-active {
    pointer-events: all;
}

/* Modal base */
.ws-modal {
    position: fixed;
    z-index: 99999;
    overflow-y: auto;
    opacity: 0;
    pointer-events: none;
    will-change: transform, opacity;
}

.ws-modal.ws-modal-active {
    pointer-events: all;
}

.ws-modal[aria-hidden="true"] {
    display: none;
}

/* Mode texte + image cote a cote */
.ws-modal-content--text_image {
    display: grid;
    gap: 24px;
    align-items: center;
}
.ws-modal-content--img-right { grid-template-columns: 1fr minmax(0, 0.8fr); }
.ws-modal-content--img-left  { grid-template-columns: minmax(0, 0.8fr) 1fr; }
.ws-modal-content--img-top,
.ws-modal-content--img-bottom { grid-template-columns: 1fr; }
.ws-modal-content--text_image img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 12px;
}
@media (max-width: 600px) {
    .ws-modal-content--img-right,
    .ws-modal-content--img-left {
        grid-template-columns: 1fr;
    }
}

/* Mode texte + video cote a cote */
.ws-modal-content--text_video {
    display: grid;
    gap: 24px;
    align-items: center;
}
.ws-modal-content--vid-right { grid-template-columns: 1fr minmax(0, 1fr); }
.ws-modal-content--vid-left  { grid-template-columns: minmax(0, 1fr) 1fr; }
.ws-modal-content--vid-top,
.ws-modal-content--vid-bottom { grid-template-columns: 1fr; }
.ws-modal-content--text_video .ws-modal-video-wrapper {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    padding-bottom: 0;
    height: auto;
    border-radius: 12px;
    overflow: hidden;
    background: #000;
}
.ws-modal-content--text_video .ws-modal-video-wrapper iframe,
.ws-modal-content--text_video .ws-modal-video-wrapper video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}
@media (max-width: 600px) {
    .ws-modal-content--vid-right,
    .ws-modal-content--vid-left {
        grid-template-columns: 1fr;
    }
}

/* Centre (fade_scale, flip_3d, blur_in, spotlight) */
.ws-modal[data-animation="fade_scale"],
.ws-modal[data-animation="flip_3d"],
.ws-modal[data-animation="blur_in"],
.ws-modal[data-animation="spotlight"] {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    max-height: 90vh;
    border-radius: var(--modal-radius, 16px);
}

/* Drawer droite */
.ws-modal[data-animation="slide_right"] {
    top: 0;
    right: 0;
    bottom: 0;
    height: 100vh;
    max-height: 100vh;
    border-radius: var(--modal-radius, 16px) 0 0 var(--modal-radius, 16px);
}

/* Drawer gauche */
.ws-modal[data-animation="slide_left"] {
    top: 0;
    left: 0;
    bottom: 0;
    height: 100vh;
    border-radius: 0 var(--modal-radius, 16px) var(--modal-radius, 16px) 0;
}

/* Sheet bas */
.ws-modal[data-animation="slide_bottom"] {
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-height: 85vh;
    border-radius: var(--modal-radius, 24px) var(--modal-radius, 24px) 0 0;
}

/* Sheet haut */
.ws-modal[data-animation="slide_top"] {
    top: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-height: 85vh;
    border-radius: 0 0 var(--modal-radius, 24px) var(--modal-radius, 24px);
}

/* Bouton fermer */
.ws-modal-close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.08);
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s;
    z-index: 1;
}

.ws-modal-close:hover {
    background: rgba(0, 0, 0, 0.15);
}

/* Video responsive */
.ws-modal-video-wrapper {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
}

.ws-modal-video-wrapper iframe,
.ws-modal-video-wrapper video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Trigger styles */
.ws-modal-btn {
    display: inline-flex;
    align-items: center;
    padding: 12px 28px;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    font-weight: 500;
    background: #000;
    color: #fff;
}

.ws-modal-text-trigger {
    cursor: pointer;
    text-decoration: underline;
    display: inline-flex;
    align-items: center;
}

.ws-modal-img-trigger {
    cursor: pointer;
}

/* === Trigger icon (avant/apres le texte) === */
.ws-modal-trigger__label,
.ws-modal-trigger__icon {
    display: inline-flex;
    align-items: center;
    line-height: 1;
}
.ws-modal-trigger__icon {
    flex-shrink: 0;
    transition: transform .3s cubic-bezier(.2,.7,.2,1), color .3s ease, fill .3s ease;
    will-change: transform;
}
.ws-modal-trigger__icon svg {
    width: 1em;
    height: 1em;
    display: block;
    transition: transform .3s cubic-bezier(.2,.7,.2,1);
}

/* Hover : translate dans le sens de la position */
.ws-modal-trigger--ihover-translate.ws-modal-trigger--icon-right:hover .ws-modal-trigger__icon {
    transform: translateX(var(--ws-modal-trigger-icon-dist, 6px));
}
.ws-modal-trigger--ihover-translate.ws-modal-trigger--icon-left:hover .ws-modal-trigger__icon {
    transform: translateX(calc(var(--ws-modal-trigger-icon-dist, 6px) * -1));
}

/* Hover : rotation 360 */
.ws-modal-trigger--ihover-rotate:hover .ws-modal-trigger__icon {
    transform: rotate(360deg);
}

/* Hover : rotation 45 (icone "+" qui devient "x", etc.) */
.ws-modal-trigger--ihover-rotate-45:hover .ws-modal-trigger__icon {
    transform: rotate(45deg);
}

/* Hover : zoom */
.ws-modal-trigger--ihover-scale:hover .ws-modal-trigger__icon {
    transform: scale(1.25);
}

/* Hover : rebond (translateY court) */
.ws-modal-trigger--ihover-bounce:hover .ws-modal-trigger__icon {
    animation: wsModalTriggerIconBounce .55s cubic-bezier(.36,.07,.19,.97);
}
@keyframes wsModalTriggerIconBounce {
    0%, 100% { transform: translateY(0); }
    30%      { transform: translateY(-6px); }
    60%      { transform: translateY(-2px); }
}

/* ===== Fade Edges ===== */

[style*="mask-image"] {
    overflow: hidden;
}

/* ===== Phase 4 Widgets ===== */

/* ==========================================================================
   Widget : Icon Box Premium (ws-icon-box)
   ========================================================================== */

.ws-icon-box {
    display: flex;
    gap: 16px;
    align-items: flex-start;
}

/* Position icone */
.ws-icon-box--position-top {
    flex-direction: column;
    align-items: center;
}

.ws-icon-box--position-left {
    flex-direction: row;
    text-align: left !important;
}

.ws-icon-box--position-right {
    flex-direction: row-reverse;
    text-align: right !important;
}

/* Alignement */
.ws-icon-box[style*="text-align: center"],
.ws-icon-box--position-top {
    align-items: center;
}

/* Icon wrap */
.ws-icon-box__icon-wrap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.ws-icon-box__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    will-change: transform;
    color: var(--e-global-color-accent, #6366f1);
    font-size: 40px;
    line-height: 1;
}

.ws-icon-box__icon svg {
    width: 1em;
    height: 1em;
    fill: currentColor;
    display: block;
}

/* View : stacked (fond) */
.ws-icon-box--view-stacked .ws-icon-box__icon-wrap {
    width: 80px;
    height: 80px;
    background: rgba(99, 102, 241, 0.12);
}

.ws-icon-box--view-stacked.ws-icon-box--shape-circle .ws-icon-box__icon-wrap {
    border-radius: 50%;
}

.ws-icon-box--view-stacked.ws-icon-box--shape-square .ws-icon-box__icon-wrap {
    border-radius: 12px;
}

/* View : framed (bordure) */
.ws-icon-box--view-framed .ws-icon-box__icon-wrap {
    width: 80px;
    height: 80px;
    border: 2px solid #e2e8f0;
}

.ws-icon-box--view-framed.ws-icon-box--shape-circle .ws-icon-box__icon-wrap {
    border-radius: 50%;
}

.ws-icon-box--view-framed.ws-icon-box--shape-square .ws-icon-box__icon-wrap {
    border-radius: 12px;
}

/* Body */
.ws-icon-box__body {
    flex: 1;
}

.ws-icon-box__badge {
    display: inline-block;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 4px 10px;
    border-radius: 20px;
    background: var(--e-global-color-accent, #6366f1);
    color: #fff;
    line-height: 1.4;
}

.ws-icon-box__title {
    font-size: 22px;
    font-weight: 700;
    line-height: 1.3;
    margin: 0;
    color: var(--e-global-color-primary, #1a1a2e);
    transition: color 0.3s ease;
}

.ws-icon-box__desc {
    font-size: 15px;
    line-height: 1.65;
    margin: 0;
    color: var(--e-global-color-text, #475569);
}

.ws-icon-box__link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    color: var(--e-global-color-accent, #6366f1);
    transition: color 0.2s ease;
}

.ws-icon-box__link-arrow {
    transition: transform 0.2s ease;
}

.ws-icon-box__link:hover .ws-icon-box__link-arrow {
    transform: translateX(4px);
}

/* Draw SVG */
.ws-draw-svg svg {
    width: 100%;
    height: auto;
    overflow: visible;
}

/* Parallax Section */
.ws-parallax-section {
    position: relative;
    overflow: hidden;
}

.ws-parallax-bg {
    position: absolute;
    inset: -20%;
    background-size: cover;
    background-position: center;
    will-change: transform;
}

/* Page overlay */
#wsb-page-overlay {
    transition: none;
}

/* Responsive */
@media (max-width: 768px) {
    /* Mobile : 1 colonne, image sticky en HAUT, steps qui scrollent en dessous.
       L'image reste collee en haut du viewport pendant que les steps defilent,
       elle change au passage de chaque step (comme desktop mais en colonne). */
    .ws-sticky-timeline {
        grid-template-columns: 1fr !important;
        gap: 24px !important;
    }

    .ws-timeline-sticky {
        position: -webkit-sticky !important;
        position: sticky !important;
        top: 0 !important;
        z-index: 10;
        background: var(--ws-tl-mobile-bg, transparent);
        padding: 12px 0;
    }

    /* Stack mobile : hauteur reduite a 40vh (au lieu de 70vh desktop) */
    .ws-timeline-image-stack {
        height: 40vh !important;
        min-height: 280px;
    }

    /* Steps gardent leur min-height pour que le sticky ait du scroll a parcourir.
       Min plus court qu'en desktop (60vh suffit pour declencher les changements). */
    .ws-timeline-step {
        min-height: 60vh !important;
        padding: 16px 0;
    }

    .ws-timeline-steps {
        gap: 32px !important;
    }

    /* Mode stack : reduire la rotation et le decalage sur mobile (sinon trop charge) */
    .ws-tl-trans-stack .ws-timeline-image-stack {
        --ws-tl-stack-rot: 4deg;
        --ws-tl-stack-offset: 8px;
    }

    /* Mode scatter : clip le debordement sur mobile (evite le scroll horizontal de page) */
    .ws-tl-display-scatter .ws-timeline-image-stack {
        overflow: hidden !important;
    }

    .ws-reviews-wall {
        flex-direction: column;
    }

    .ws-reviews-col {
        margin-top: 0 !important;
    }

    .ws-floating-grid {
        flex-wrap: wrap;
    }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
    [data-ws-animation] {
        opacity: 1 !important;
        transform: none !important;
    }

    .ws-marquee__track {
        animation: none !important;
    }

    .ws-card-tilt__inner {
        transform: none !important;
    }

    .ws-magnetic-btn {
        transform: none !important;
    }

    .ws-modal {
        transition: opacity 0.2s !important;
    }
}

/* ============================================
   IDLE ANIMATIONS (flotaison, breath, pulse...)
   Applique sur tous les widgets via .ws-idle-{name}
   Variables : --ws-idle-speed (default 3.5s), --ws-idle-amp (default 8px)
   ============================================ */
.ws-idle-float,
.ws-idle-float-x,
.ws-idle-float-rot,
.ws-idle-float-3d,
.ws-idle-breath,
.ws-idle-pulse,
.ws-idle-sway,
.ws-idle-jelly,
.ws-idle-glow-pulse {
    --ws-idle-speed: 3.5s;
    --ws-idle-amp: 8px;
    will-change: transform;
}

/*
 * Pattern : 2 animations en parallele.
 *  1) wsIdleFadeIn : 0.5s de fade-in opacity 0.85 -> 1 (apparait en douceur a l'activation)
 *  2) Animation principale : DELAY 0.5s + boucle infinie
 *     animation-fill-mode: both = pendant le delay, applique frame 0 (repos) -> pas de saut
 *
 * Resultat : l'element apparait en fade-in pendant 0.5s a sa position de repos,
 * puis l'animation principale demarre en douceur depuis le repos.
 */
.ws-idle-float       { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleFloat       var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-float-x     { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleFloatX      var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-float-rot   { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleFloatRot    var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-float-3d    { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleFloat3D     var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-breath      { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleBreath      var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-pulse       { animation: wsIdleFadeIn 0.5s ease-out both, wsIdlePulse       var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-sway        { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleSway        var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-jelly       { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleJelly       var(--ws-idle-speed) ease-in-out 0.5s infinite both; }
.ws-idle-glow-pulse  { animation: wsIdleFadeIn 0.5s ease-out both, wsIdleGlowPulse   var(--ws-idle-speed) ease-in-out 0.5s infinite both; }

@keyframes wsIdleFadeIn {
    from { opacity: 0.6; }
    to   { opacity: 1; }
}

/*
 * REGLE CRITIQUE : tous les keyframes commencent ET finissent a la position de
 * REPOS (transform: identity / translateX(0) / rotate(0) / scale(1) / etc.).
 * Sinon, quand la classe est ajoutee, l'element SAUTE brusquement de sa
 * position naturelle a la position du frame 0 = "sursaut au demarrage".
 * Le mouvement effectif est dans les frames intermediaires (25/50/75%).
 */
@keyframes wsIdleFloat {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(calc(var(--ws-idle-amp) * -1)); }
}
@keyframes wsIdleFloatX {
    0%, 100% { transform: translateX(0); }
    50%      { transform: translateX(var(--ws-idle-amp)); }
}
/* Float + rotation : 4 etapes pour passer par 0 sans saut */
@keyframes wsIdleFloatRot {
    0%, 100% { transform: translateY(0) rotate(0deg); }
    25%      { transform: translateY(calc(var(--ws-idle-amp) * -0.5)) rotate(-1.5deg); }
    50%      { transform: translateY(calc(var(--ws-idle-amp) * -1)) rotate(0deg); }
    75%      { transform: translateY(calc(var(--ws-idle-amp) * -0.5)) rotate(1.5deg); }
}
@keyframes wsIdleFloat3D {
    0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
    25%      { transform: translate3d(var(--ws-idle-amp), calc(var(--ws-idle-amp) * -0.5), 0) rotate(1deg); }
    50%      { transform: translate3d(0, calc(var(--ws-idle-amp) * -1), 0) rotate(0deg); }
    75%      { transform: translate3d(calc(var(--ws-idle-amp) * -1), calc(var(--ws-idle-amp) * -0.5), 0) rotate(-1deg); }
}
@keyframes wsIdleBreath {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.04); }
}
@keyframes wsIdlePulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50%      { transform: scale(1.06); opacity: 0.92; }
}
/* Sway : commence a rotate(0) au lieu de -2deg pour eviter le saut a l'activation */
@keyframes wsIdleSway {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(-2deg); }
    75%      { transform: rotate(2deg); }
}
/* Jelly : skew() syntaxe corrigee (etait skew(0,0) invalide) + start a rest */
@keyframes wsIdleJelly {
    0%, 100% { transform: skewX(0deg); }
    25%      { transform: skewX(2deg); }
    75%      { transform: skewX(-2deg); }
}
@keyframes wsIdleGlowPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(99,102,241,0); }
    50%      { box-shadow: 0 0 24px 4px rgba(99,102,241,0.35); }
}

@media (prefers-reduced-motion: reduce) {
    .ws-idle-float, .ws-idle-float-x, .ws-idle-float-rot, .ws-idle-float-3d,
    .ws-idle-breath, .ws-idle-pulse, .ws-idle-sway, .ws-idle-jelly, .ws-idle-glow-pulse {
        animation: none !important;
    }
}

/* === MODAL : wrapper en fit-content pour que la bordure lumineuse hug le bouton === */
.elementor-widget-ws-modal {
    width: fit-content;
    max-width: 100%;
}
/* Si le widget global beam est applique au wrapper du modal : on le transfere visuellement
   au bouton trigger en faisant en sorte que le wrapper soit aussi etroit que le bouton */
.elementor-widget-ws-modal .ws-modal-wrapper {
    display: inline-block;
}
