/**
 * WS Booster - Effets universels
 * Effets appliquables sur n'importe quel widget / colonne / section / container Elementor.
 *
 * Architecture : chaque effet est active par un attribut data-ws-* sur le wrapper,
 * avec des CSS custom properties pour la personnalisation.
 */

/* ==========================================================================
   FIX Elementor v4 (atomic widgets)
   En v4, le wrapper .elementor-widget-container n'est plus rendu pour certains
   widgets. Les balises HTML enfants (h1-h6, p, ul, ol) gardent alors leurs
   marges natives du navigateur, ce qui cree un espace fantome en haut/bas
   de chaque widget. On reset ces marges UNIQUEMENT quand le container manque.
   ========================================================================== */
.elementor-widget:not(:has(> .elementor-widget-container)) > h1,
.elementor-widget:not(:has(> .elementor-widget-container)) > h2,
.elementor-widget:not(:has(> .elementor-widget-container)) > h3,
.elementor-widget:not(:has(> .elementor-widget-container)) > h4,
.elementor-widget:not(:has(> .elementor-widget-container)) > h5,
.elementor-widget:not(:has(> .elementor-widget-container)) > h6,
.elementor-widget:not(:has(> .elementor-widget-container)) > p,
.elementor-widget:not(:has(> .elementor-widget-container)) > ul,
.elementor-widget:not(:has(> .elementor-widget-container)) > ol,
.elementor-widget:not(:has(> .elementor-widget-container)) > blockquote {
    margin-top: 0;
    margin-bottom: 0;
}

/* ==========================================================================
   Effet Glossy (reflet brillant qui traverse l'element)
   - Active par data-ws-glossy="loop" ou "hover"
   - Personnalisable via --ws-glossy-color, --ws-glossy-width, --ws-glossy-speed,
     --ws-glossy-opacity, --ws-glossy-angle
   ========================================================================== */

[data-ws-glossy] {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

[data-ws-glossy]::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    /* z-index 3 : le reflet passe PAR-DESSUS le contenu du widget
       (les enfants sont en z-index 2). Sinon il reste cache derriere
       le conteneur Elementor et l'effet est invisible. */
    z-index: 3;
    background: linear-gradient(
        var(--ws-glossy-angle, 115deg),
        transparent 0%,
        transparent calc(50% - var(--ws-glossy-width, 80px) / 2),
        var(--ws-glossy-color, rgba(255, 255, 255, 0.55)) 50%,
        transparent calc(50% + var(--ws-glossy-width, 80px) / 2),
        transparent 100%
    );
    background-size: 300% 100%;
    background-repeat: no-repeat;
    background-position: 150% 0;
    opacity: var(--ws-glossy-opacity, 1);
    mix-blend-mode: screen;
}

/* Double reflet : deux bandes de lumiere separees par --ws-glossy-gap,
   centrees autour du milieu (donc la distance = --ws-glossy-gap exactement).
   On override UNIQUEMENT background-image -> background-size / position /
   repeat et toutes les regles d'animation (sur ::before) restent valables. */
[data-ws-glossy].ws-glossy-double-yes::before {
    background-image: linear-gradient(
        var(--ws-glossy-angle, 115deg),
        transparent 0%,
        transparent calc(50% - var(--ws-glossy-gap, 100px) / 2 - var(--ws-glossy-width, 80px) / 2),
        var(--ws-glossy-color, rgba(255, 255, 255, 0.55)) calc(50% - var(--ws-glossy-gap, 100px) / 2),
        transparent calc(50% - var(--ws-glossy-gap, 100px) / 2 + var(--ws-glossy-width, 80px) / 2),
        transparent calc(50% + var(--ws-glossy-gap, 100px) / 2 - var(--ws-glossy-width, 80px) / 2),
        var(--ws-glossy-color, rgba(255, 255, 255, 0.55)) calc(50% + var(--ws-glossy-gap, 100px) / 2),
        transparent calc(50% + var(--ws-glossy-gap, 100px) / 2 + var(--ws-glossy-width, 80px) / 2),
        transparent 100%
    );
}

/* Mode loop : l'effet traverse en boucle */
[data-ws-glossy="loop"]::before {
    animation: ws-glossy-sweep var(--ws-glossy-speed, 3s) linear infinite;
}

/* Mode hover : l'effet se declenche au survol */
[data-ws-glossy="hover"]::before {
    background-position: 150% 0;
    transition: background-position var(--ws-glossy-speed, 1s) ease-out;
}

[data-ws-glossy="hover"]:hover::before {
    background-position: -50% 0;
}

/* Mode both : boucle + acceleration au hover */
[data-ws-glossy="both"]::before {
    animation: ws-glossy-sweep var(--ws-glossy-speed, 4s) linear infinite;
}

[data-ws-glossy="both"]:hover::before {
    animation-duration: calc(var(--ws-glossy-speed, 4s) / 3);
}

@keyframes ws-glossy-sweep {
    0% {
        background-position: 150% 0;
    }
    100% {
        background-position: -150% 0;
    }
}

/* Respect de la preference utilisateur */
@media (prefers-reduced-motion: reduce) {
    [data-ws-glossy="loop"]::before,
    [data-ws-glossy="both"]::before {
        animation: none;
        background-position: 150% 0;
    }
}

/* Les enfants du widget sont poses dans la couche positionnee (z-index 2),
   au-dessus du fond mais SOUS le reflet (::before en z-index 3) : le reflet
   glisse par-dessus le contenu, comme un vrai reflet sur une surface. */
[data-ws-glossy] > * {
    position: relative;
    z-index: 2;
}

/* ==========================================================================
   Effet Gardien rotatif (element decoratif qui orbite autour)
   - Active par data-ws-guardian="dot" / "square" / "ring"
   - Personnalisable via --ws-guardian-size, --ws-guardian-color,
     --ws-guardian-radius, --ws-guardian-speed
   - Si combine avec Glossy : overflow:visible pour laisser le gardien sortir
   ========================================================================== */

[data-ws-guardian] {
    position: relative;
    overflow: visible !important;
}

[data-ws-guardian]::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--ws-guardian-size, 16px);
    height: var(--ws-guardian-size, 16px);
    margin-top: calc(var(--ws-guardian-size, 16px) / -2);
    margin-left: calc(var(--ws-guardian-size, 16px) / -2);
    background: var(--ws-guardian-color, #ef3340);
    pointer-events: none;
    z-index: 3;
    transform-origin: center;
    animation: ws-guardian-orbit var(--ws-guardian-speed, 6s) linear infinite;
}

/* Forme : point rond */
[data-ws-guardian="dot"]::after {
    border-radius: 50%;
}

/* Forme : carre */
[data-ws-guardian="square"]::after {
    border-radius: 2px;
}

/* Forme : anneau creux */
[data-ws-guardian="ring"]::after {
    background: transparent;
    border: 2px solid var(--ws-guardian-color, #ef3340);
    border-radius: 50%;
}

/* Sens inverse (anti-horaire) */
[data-ws-guardian-direction="reverse"]::after {
    animation-direction: reverse;
}

@keyframes ws-guardian-orbit {
    from {
        transform: rotate(0deg) translateX(var(--ws-guardian-radius, 60px)) rotate(0deg);
    }
    to {
        transform: rotate(360deg) translateX(var(--ws-guardian-radius, 60px)) rotate(-360deg);
    }
}

@media (prefers-reduced-motion: reduce) {
    [data-ws-guardian]::after {
        animation: none;
    }
}

/* ==========================================================================
   Effet Gradient BG (fond gradient anime avec 3 couleurs, style shader)
   - Active par data-ws-gradient-bg="animated" / "static"
   - Personnalisable via --ws-grad-c1/c2/c3, --ws-grad-blur, --ws-grad-speed,
     --ws-grad-opacity, --ws-grad-noise
   ========================================================================== */

[data-ws-gradient-bg] {
    position: relative;
    isolation: isolate;
    overflow: hidden;
}

/* MODE BUILDER ELEMENTOR : la "tete de section" (chapeau rose de selection)
 * est un enfant DOM positionne au-dessus de la section. DEUX proprietes de
 * l'effet la rendent inaccessible :
 *   - overflow:hidden  -> clippe la poignee qui deborde en haut
 *   - isolation:isolate -> cree un contexte d'empilement qui piege la poignee
 *                          (elle passe sous la section voisine)
 * En builder on NEUTRALISE LES DEUX. Le gradient ::before est repositionne
 * (inset:0 + z-index:-1) pour rester derriere le contenu meme sans le
 * contexte d'isolation. L'apercu peut etre legerement different du rendu
 * final ; la prod (sans .elementor-editor-active) garde le rendu exact.
 */
.elementor-editor-active [data-ws-gradient-bg] {
    overflow: visible !important;
    isolation: auto !important;
    clip-path: none !important;
}
/* En builder : derriere le contenu UNIQUEMENT si placement != overlay
   (en overlay on garde le z-index eleve, sinon plus de teinte visible). */
.elementor-editor-active [data-ws-gradient-bg]:not([data-ws-gradient-placement="overlay"])::before {
    inset: 0 !important;     /* override le -20% pour ne pas deborder */
    z-index: -1 !important;  /* derriere le contenu sans isolation */
}

[data-ws-gradient-bg]::before {
    content: "";
    position: absolute;
    inset: -20%;
    z-index: -2;
    /* --ws-grad-precision contrôle le HARDNESS du bord (0% = halo flou, 95% = cercle net).
       Stop intermediaire : la couleur est tenue jusqu'a precision%, puis fade vers transparent
       a size%. Si precision=0, gradient = couleur 0% -> transparent size% (effet halo classique).
       Si precision=80% et size=45%, le browser clamp et le rendu reste coherent. */
    background:
        radial-gradient(circle at var(--ws-grad-x-1, 20%) var(--ws-grad-y-1, 30%),
            var(--ws-grad-c1, #667eea) 0%,
            var(--ws-grad-c1, #667eea) var(--ws-grad-precision, 0%),
            transparent var(--ws-grad-size-1, 45%)),
        radial-gradient(circle at var(--ws-grad-x-2, 80%) var(--ws-grad-y-2, 20%),
            var(--ws-grad-c2, #764ba2) 0%,
            var(--ws-grad-c2, #764ba2) var(--ws-grad-precision, 0%),
            transparent var(--ws-grad-size-2, 45%)),
        radial-gradient(circle at var(--ws-grad-x-3, 50%) var(--ws-grad-y-3, 80%),
            var(--ws-grad-c3, #f093fb) 0%,
            var(--ws-grad-c3, #f093fb) var(--ws-grad-precision, 0%),
            transparent var(--ws-grad-size-3, 50%));
    filter: blur(var(--ws-grad-blur, 80px)) saturate(1.1);
    opacity: var(--ws-grad-opacity, 1);
    pointer-events: none;
}

/* Mode statique : pas d'animation, gradient fixe */
[data-ws-gradient-bg="static"]::before {
    /* aucune animation - le gradient reste tel quel */
}

[data-ws-gradient-bg="animated"]::before {
    animation: ws-gradient-morph var(--ws-grad-speed, 14s) ease-in-out infinite alternate;
    will-change: transform, filter;
}

/* ==========================================================================
   PLACEMENT = SUPERPOSITION (overlay) — gradient PAR-DESSUS le contenu
   - z-index eleve pour passer au-dessus du contenu
   - pointer-events: none pour laisser passer les clics
   - mix-blend-mode pour teinter sans cacher (defaut normal)
   - inset:0 (pas de debordement, sinon le gradient sort de la section)
   ========================================================================== */
[data-ws-gradient-bg][data-ws-gradient-placement="overlay"]::before {
    inset: 0;
    z-index: 10;
    pointer-events: none;
    mix-blend-mode: var(--ws-grad-blend, normal);
}
/* En builder, garde l'overlay visible au-dessus mais click-through */
.elementor-editor-active [data-ws-gradient-bg][data-ws-gradient-placement="overlay"]::before {
    inset: 0 !important;
    z-index: 10 !important;
    pointer-events: none !important;
}

@keyframes ws-gradient-morph {
    0% {
        transform: translate(0, 0) rotate(0deg) scale(1);
    }
    33% {
        transform: translate(5%, -4%) rotate(60deg) scale(1.08);
    }
    66% {
        transform: translate(-6%, 5%) rotate(180deg) scale(0.96);
    }
    100% {
        transform: translate(3%, 3%) rotate(300deg) scale(1.04);
    }
}

[data-ws-gradient-noise="yes"]::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
    opacity: var(--ws-grad-noise-intensity, 0.15);
    mix-blend-mode: overlay;
}

/* ==========================================================================
   Effet Fondu sur les bords (mask-image avec gradient)
   - Active par data-ws-edge-fade="all|horizontal|vertical|top|right|bottom|left"
   - Taille personnalisable via --ws-edge-fade-size (default 10%)
   - Intensite (opacite bord) via --ws-edge-fade-alpha (0 = transparent total = defaut)
   - Propagation via --ws-edge-fade-mid-pos (position 0..1 du stop intermediaire, default 0.5)
   - Compatible mobile/desktop, fonctionne sur sections, colonnes, containers, widgets

   Pattern : on remplace "transparent" par var(--_efc-edge) qui est rgba(0,0,0, alpha).
   On ajoute un stop intermediaire pour controler la courbe (propagation).
   ========================================================================== */

[data-ws-edge-fade] {
    --ws-edge-fade-size: 10%;
    --ws-edge-fade-alpha: 0;
    --ws-edge-fade-mid-pos: 0.5;
    /* Calculs derives : couleur du bord + couleur intermediaire (alpha moyen) */
    --_efc-edge: rgba(0, 0, 0, var(--ws-edge-fade-alpha));
    --_efc-mid:  rgba(0, 0, 0, calc((var(--ws-edge-fade-alpha) + 1) / 2));
    /* Position absolue du stop intermediaire (% du size) */
    --_efs-mid:     calc(var(--ws-edge-fade-size) * var(--ws-edge-fade-mid-pos));
    --_efs-mid-far: calc(100% - var(--ws-edge-fade-size) * var(--ws-edge-fade-mid-pos));
}

/* === DIRECTION = OUTSIDE (defaut) : bords -> transparent (selon alpha), centre -> visible ===
   Pattern : edge alpha -> mid alpha -> opaque -> opaque -> mid alpha -> edge alpha */

[data-ws-edge-fade="all"]:not([data-ws-edge-fade-direction="inside"]) {
    -webkit-mask-image:
        linear-gradient(to right, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%),
        linear-gradient(to bottom, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%);
    -webkit-mask-composite: source-in;
    mask-image:
        linear-gradient(to right, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%),
        linear-gradient(to bottom, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%);
    mask-composite: intersect;
}

[data-ws-edge-fade="horizontal"]:not([data-ws-edge-fade-direction="inside"]) {
    -webkit-mask-image: linear-gradient(to right, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%);
    mask-image: linear-gradient(to right, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%);
}

[data-ws-edge-fade="vertical"]:not([data-ws-edge-fade-direction="inside"]) {
    -webkit-mask-image: linear-gradient(to bottom, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%);
    mask-image: linear-gradient(to bottom, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), var(--_efc-edge) 100%);
}

[data-ws-edge-fade="top"]:not([data-ws-edge-fade-direction="inside"]) {
    -webkit-mask-image: linear-gradient(to bottom, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to bottom, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
}

[data-ws-edge-fade="bottom"]:not([data-ws-edge-fade-direction="inside"]) {
    -webkit-mask-image: linear-gradient(to top, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to top, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
}

[data-ws-edge-fade="left"]:not([data-ws-edge-fade-direction="inside"]) {
    -webkit-mask-image: linear-gradient(to right, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to right, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
}

[data-ws-edge-fade="right"]:not([data-ws-edge-fade-direction="inside"]) {
    -webkit-mask-image: linear-gradient(to left, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to left, var(--_efc-edge) 0, var(--_efc-mid) var(--_efs-mid), black var(--ws-edge-fade-size), black 100%);
}

/* === DIRECTION = INSIDE : centre -> transparent (selon alpha), bords -> visible (effet vignette inverse) ===
   Pattern : opaque 0 -> mid -> edge alpha (centre) -> edge alpha -> mid -> opaque 100%.
   Note : ici alpha=0 signifie centre invisible (defaut historique). */

[data-ws-edge-fade="all"][data-ws-edge-fade-direction="inside"] {
    -webkit-mask-image:
        linear-gradient(to right, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%),
        linear-gradient(to bottom, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%);
    -webkit-mask-composite: source-over;
    mask-image:
        linear-gradient(to right, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%),
        linear-gradient(to bottom, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%);
    mask-composite: add;
}

[data-ws-edge-fade="horizontal"][data-ws-edge-fade-direction="inside"] {
    -webkit-mask-image: linear-gradient(to right, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%);
    mask-image: linear-gradient(to right, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%);
}

[data-ws-edge-fade="vertical"][data-ws-edge-fade-direction="inside"] {
    -webkit-mask-image: linear-gradient(to bottom, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%);
    mask-image: linear-gradient(to bottom, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), var(--_efc-edge) calc(100% - var(--ws-edge-fade-size)), var(--_efc-mid) var(--_efs-mid-far), black 100%);
}

[data-ws-edge-fade="top"][data-ws-edge-fade-direction="inside"] {
    -webkit-mask-image: linear-gradient(to bottom, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to bottom, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
}

[data-ws-edge-fade="bottom"][data-ws-edge-fade-direction="inside"] {
    -webkit-mask-image: linear-gradient(to top, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to top, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
}

[data-ws-edge-fade="left"][data-ws-edge-fade-direction="inside"] {
    -webkit-mask-image: linear-gradient(to right, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to right, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
}

[data-ws-edge-fade="right"][data-ws-edge-fade-direction="inside"] {
    -webkit-mask-image: linear-gradient(to left, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
    mask-image: linear-gradient(to left, black 0, var(--_efc-mid) var(--_efs-mid), var(--_efc-edge) var(--ws-edge-fade-size), black 100%);
}

@media (prefers-reduced-motion: reduce) {
    [data-ws-gradient-bg="animated"]::before {
        animation: none;
    }
}

/* ==========================================================================
   Effet Parallax BG (image de fond qui bouge au scroll, via GSAP)
   - Active par data-ws-parallax-bg="true"
   - Personnalise via data-ws-parallax-speed (-3 a 3), data-ws-parallax-image
   ========================================================================== */

[data-ws-parallax-bg="true"] {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.ws-parallax-bg-layer {
    position: absolute;
    top: -20%;
    left: 0;
    width: 100%;
    height: 140%;
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
    z-index: -1;
    will-change: transform;
    pointer-events: none;
}

[data-ws-parallax-bg="true"] > *:not(.ws-parallax-bg-layer) {
    position: relative;
    z-index: 1;
}

/* ==========================================================================
   Bordure Lumineuse Rotative (Border Beam - pattern UICore/Aceternity)
   - Base dim border toujours visible + arc brillant qui tourne
   - Utilise @property pour animer l'angle de conic-gradient (support 97%)
   - Mask-composite pour afficher uniquement la bordure (pas l'interieur)

   Modes :
   - "continuous" : rotation non-stop
   - "hover"      : rotation seulement au survol
   - "gradient"   : gradient statique sans rotation
   ========================================================================== */

/* PATTERN BORDURE LUMINEUSE (v2.6.13) :
   - Pattern offset-path : un trait lumineux voyage le long du contour exact du widget
   - PAS un conic-gradient qui tourne au centre (qui creait un effet "rectangle qui tourne")
   - PAS besoin de fond opaque
   - Le trait suit la forme arrondie (border-radius) sans jamais traverser l'element
   - Marche aussi bien sur un bouton de 80px que sur un container de 1200px

   5 modes :
     continuous        : 1 trait qui voyage en boucle le long du contour
     continuous-double : 2 traits opposes (180deg) -> rotation visuellement constante
     hover             : 1 trait paused, declenche au survol
     gradient          : pas d'animation, gradient statique sur le bord
     star              : etoile lumineuse + trail (effet premium)

   Fallback : navigateurs sans support offset-path (Firefox <128, vieux Safari)
              retombent sur un gradient statique mask-composite (pas d'animation).
*/

[data-ws-beam] {
    position: relative;
    /* Aucun override du widget user (border-radius, background, etc. restent ceux choisis dans Elementor) */
}

/* === Pattern Webflow "glowing border" pour modes CONTINU / DOUBLE / HOVER === */
/* Le shell + rotor sont injectes par injectBeamShell() dans ws-booster-init.js */

/* SHELL : positionne en absolute, prend toute la place du parent,
   border-radius copie via JS, mask-composite ne laisse voir que le contour */
.wsb-beam-shell {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
    /* Mask-composite : le rotor n'est visible qu'au niveau du contour */
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    /* padding (= epaisseur du bord visible) injecte via style inline JS */
}

/* ROTOR : carre centre avec conic-gradient circulaire, qui tourne */
.wsb-beam-rotor {
    position: absolute;
    top: 50%;
    left: 50%;
    /* width MAX du parent pour bien couvrir tout le contour */
    width: max(150%, 200px);
    aspect-ratio: 1 / 1;
    transform: translate(-50%, -50%);
    background: conic-gradient(
        from 0deg,
        transparent 0deg,
        var(--ws-beam-color, #ef3340) 60deg,
        transparent 120deg,
        transparent 360deg
    );
    will-change: transform;
}

/* Mode CONTINU : le rotor tourne en boucle */
[data-ws-beam="continuous"] .wsb-beam-rotor {
    animation: ws-beam-rotor-spin var(--ws-beam-speed, 4s) linear infinite;
}

/* Mode CONTINU-DOUBLE : conic avec 2 zones de couleur a 180deg */
[data-ws-beam="continuous-double"] .wsb-beam-rotor {
    background: conic-gradient(
        from 0deg,
        transparent 0deg,
        var(--ws-beam-color, #ef3340) 60deg,
        transparent 120deg,
        transparent 180deg,
        var(--ws-beam-color2, var(--ws-beam-color, #ef3340)) 240deg,
        transparent 300deg,
        transparent 360deg
    );
    animation: ws-beam-rotor-spin var(--ws-beam-speed, 4s) linear infinite;
}

/* Mode HOVER : rotation paused, lancee au survol */
[data-ws-beam="hover"] .wsb-beam-rotor {
    animation: ws-beam-rotor-spin var(--ws-beam-speed, 4s) linear infinite;
    animation-play-state: paused;
}
[data-ws-beam="hover"]:hover .wsb-beam-rotor {
    animation-play-state: running;
}

/* Le contenu visible doit etre AU-DESSUS du shell */
[data-ws-beam] > *:not(.wsb-beam-shell) {
    position: relative;
    z-index: 1;
}

@keyframes ws-beam-rotor-spin {
    from { transform: translate(-50%, -50%) rotate(0deg); }
    to   { transform: translate(-50%, -50%) rotate(360deg); }
}

/* === Mode GRADIENT : pas d'animation, juste une bordure degrade statique === */
[data-ws-beam="gradient"]::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--wsb-beam-actual-radius, 14px);
    padding: var(--ws-beam-width, 2px);
    background: linear-gradient(
        135deg,
        var(--ws-beam-color, #ef3340) 0%,
        var(--ws-beam-color2, var(--ws-beam-color, #ef3340)) 100%
    );
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    pointer-events: none;
    z-index: 1;
}

/* === Mode STAR : etoile lumineuse + trail derriere, qui orbitent le contour === */
[data-ws-beam="star"]::before {
    content: "";
    position: absolute;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: radial-gradient(
        circle,
        #fff 0%,
        var(--ws-beam-color, #ef3340) 35%,
        transparent 75%
    );
    box-shadow:
        0 0 16px var(--ws-beam-color, #ef3340),
        0 0 32px var(--ws-beam-color, #ef3340);
    offset-path: inset(0 round var(--wsb-beam-actual-radius, 14px));
    offset-distance: 0%;
    offset-rotate: auto;
    animation: ws-beam-orbit var(--ws-beam-speed, 4s) linear infinite;
    pointer-events: none;
    z-index: 1;
    will-change: offset-distance;
}

[data-ws-beam="star"]::after {
    content: "";
    position: absolute;
    width: 60px;
    height: 2px;
    background: linear-gradient(90deg, transparent 0%, var(--ws-beam-color, #ef3340) 100%);
    border-radius: 999px;
    box-shadow: 0 0 4px var(--ws-beam-color, #ef3340);
    offset-path: inset(0 round var(--wsb-beam-actual-radius, 14px));
    offset-distance: 0%;
    offset-rotate: auto;
    animation: ws-beam-orbit var(--ws-beam-speed, 4s) linear infinite;
    pointer-events: none;
    z-index: 1;
    opacity: 0.7;
}

/* === Glow externe optionnel : halo autour du wrapper === */
[data-ws-beam][data-ws-beam-glow="yes"] {
    box-shadow: 0 0 var(--ws-beam-glow-size, 16px) -2px var(--ws-beam-color, #ef3340);
}

@keyframes ws-beam-orbit {
    to { offset-distance: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    [data-ws-beam]::before,
    [data-ws-beam]::after {
        animation: none !important;
    }
}

/* === Fallback pour le mode STAR : navigateurs sans support offset-path === */
@supports not (offset-path: inset(0)) {
    [data-ws-beam="star"]::before {
        offset-path: none;
        position: absolute;
        inset: 0;
        width: auto;
        height: auto;
        border-radius: var(--wsb-beam-actual-radius, 14px);
        padding: var(--ws-beam-width, 2px);
        background: linear-gradient(135deg, var(--ws-beam-color, #ef3340) 0%, transparent 50%);
        box-shadow: none;
        -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
                mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
        -webkit-mask-composite: xor;
                mask-composite: exclude;
        animation: none;
        opacity: 1;
    }
    [data-ws-beam="star"]::after {
        display: none;
    }
}

/* ==========================================================================
   Spotlight au curseur (sur les patterns dots/grid/lines/cross)
   - Mode "masked" : le pattern est INVISIBLE au repos, apparait uniquement
     autour de la souris (via double mask).
   - Mode "blend" : le pattern reste visible, le spotlight ajoute une tache
     coloree au-dessus.
   - Personnalise via --ws-spotlight-color, --ws-spotlight-size.
   ========================================================================== */

[data-ws-spotlight] {
    position: relative;
    isolation: isolate;
    overflow: hidden;
}

/* Couche du spotlight suit la souris via CSS vars --ws-mx / --ws-my (%).
   left/top en % se calent sur le CONTENEUR (bloc englobant positionne) ;
   translate(-50%,-50%) recentre la tache sur ce point. Un % dans translate()
   se cale sur l'element transforme lui-meme, donc -50% = demi-tache, peu
   importe --ws-spotlight-size. (Ancien bug : translate(calc(var(--ws-mx)
   - taille/2)) prenait --ws-mx comme % de la tache, pas du conteneur =>
   la tache ne suivait pas la souris.) */
[data-ws-spotlight="blend"]::after,
[data-ws-spotlight="tint"]::after {
    content: "";
    position: absolute;
    top: var(--ws-my, 50%);
    left: var(--ws-mx, 50%);
    width: var(--ws-spotlight-size, 400px);
    height: var(--ws-spotlight-size, 400px);
    background: var(--ws-spotlight-color, rgba(99, 102, 241, 0.45));
    transform: translate3d(-50%, -50%, 0);
    pointer-events: none;
    z-index: 0;
    border-radius: 50%;
    filter: blur(0);
    -webkit-mask-image: radial-gradient(circle at center, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 70%);
    mask-image: radial-gradient(circle at center, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 70%);
    opacity: 0;
    transition: opacity 0.25s ease;
}

[data-ws-spotlight="blend"]:hover::after,
[data-ws-spotlight="tint"]:hover::after {
    opacity: 1;
}

/* Mode tint : la tache recolore le contenu (mix-blend-mode) au lieu d'eclairer */
[data-ws-spotlight="tint"]::after {
    mix-blend-mode: color;
}

/* Mode masked : le pattern est masque globalement sauf sur la zone du spot */
[data-ws-spotlight="masked"][data-ws-pattern] {
    background-image: none !important;
}

[data-ws-spotlight="masked"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image: inherit;
    opacity: 0;
    transition: opacity 0.25s ease;
}

/* On reconstruit le pattern dans ::before avec les memes background */
[data-ws-spotlight="masked"][data-ws-pattern="dots"]::before {
    background-image: radial-gradient(circle, var(--ws-pattern-color, rgba(0,0,0,0.2)) 1px, transparent 1px);
    background-size: var(--ws-pattern-size, 24px) var(--ws-pattern-size, 24px);
    -webkit-mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
    mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
}

[data-ws-spotlight="masked"][data-ws-pattern="grid"]::before {
    background-image:
        linear-gradient(var(--ws-pattern-color, rgba(0,0,0,0.2)) 1px, transparent 1px),
        linear-gradient(90deg, var(--ws-pattern-color, rgba(0,0,0,0.2)) 1px, transparent 1px);
    background-size: var(--ws-pattern-size, 24px) var(--ws-pattern-size, 24px);
    -webkit-mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
    mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
}

[data-ws-spotlight="masked"][data-ws-pattern="lines"]::before {
    background-image: repeating-linear-gradient(45deg, var(--ws-pattern-color, rgba(0,0,0,0.2)) 0, var(--ws-pattern-color, rgba(0,0,0,0.2)) 1px, transparent 0, transparent 50%);
    background-size: var(--ws-pattern-size, 24px) var(--ws-pattern-size, 24px);
    -webkit-mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
    mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
}

[data-ws-spotlight="masked"][data-ws-pattern="cross"]::before {
    background-image:
        linear-gradient(var(--ws-pattern-color, rgba(0,0,0,0.2)) 1px, transparent 1px),
        linear-gradient(90deg, var(--ws-pattern-color, rgba(0,0,0,0.2)) 1px, transparent 1px);
    background-size: var(--ws-pattern-size, 24px) var(--ws-pattern-size, 24px);
    background-position: center center;
    -webkit-mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
    mask-image: radial-gradient(circle at calc(var(--ws-mx, 50%)) calc(var(--ws-my, 50%)), black 0%, transparent var(--ws-spotlight-size, 400px));
}

[data-ws-spotlight="masked"]:hover::before {
    opacity: 1;
}

/* En mode masked, on enleve la tache de couleur (juste le pattern apparait) */
[data-ws-spotlight="masked"]::after {
    display: none;
}

/* =========================================================================
   Modes spotlight additionnels (curseur). Tous suivent --ws-mx / --ws-my.
   z-index:2 => la couche passe au-dessus du contenu du widget.
   ========================================================================= */

/* TORCHE : voile sombre, trou de lumiere qui suit la souris (revele le contenu) */
[data-ws-spotlight="torch"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: var(--ws-torch-veil, rgba(10, 10, 12, 0.88));
    -webkit-mask-image: radial-gradient(circle var(--ws-spotlight-size, 360px) at var(--ws-mx, 50%) var(--ws-my, 50%),
        transparent 0, transparent 52%, #000 100%);
    mask-image: radial-gradient(circle var(--ws-spotlight-size, 360px) at var(--ws-mx, 50%) var(--ws-my, 50%),
        transparent 0, transparent 52%, #000 100%);
    opacity: 0;
    transition: opacity 0.3s ease;
}
[data-ws-spotlight="torch"]:hover::before {
    opacity: 1;
}

/* BORDURE : halo lumineux le long du contour, point chaud sous la souris.
   Le double masque (full + content-box, composite exclude) ne garde que
   l'anneau de la largeur du padding. */
[data-ws-spotlight="border"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    border-radius: inherit;
    padding: 2px;
    background: radial-gradient(circle var(--ws-spotlight-size, 280px) at var(--ws-mx, 50%) var(--ws-my, 50%),
        var(--ws-spotlight-color, rgba(99, 102, 241, 0.9)) 0%,
        transparent 70%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    opacity: 0;
    transition: opacity 0.3s ease;
}
[data-ws-spotlight="border"]:hover::before {
    opacity: 1;
}

/* IMAGE REVELEE : l'image de l'utilisateur apparait dans le cercle
   autour de la souris (meme principe que le mode masque, image custom). */
[data-ws-spotlight="image"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background-image: var(--ws-spotlight-image, none);
    background-size: var(--ws-spotlight-img-size, cover);
    background-position: center;
    background-repeat: var(--ws-spotlight-img-repeat, no-repeat);
    -webkit-mask-image: radial-gradient(circle var(--ws-spotlight-size, 340px) at var(--ws-mx, 50%) var(--ws-my, 50%),
        #000 0, #000 42%, transparent 100%);
    mask-image: radial-gradient(circle var(--ws-spotlight-size, 340px) at var(--ws-mx, 50%) var(--ws-my, 50%),
        #000 0, #000 42%, transparent 100%);
    opacity: 0;
    transition: opacity 0.3s ease;
}
[data-ws-spotlight="image"]:hover::before {
    opacity: 1;
}

/* Accessibilite */
@media (prefers-reduced-motion: reduce) {
    [data-ws-spotlight]::after,
    [data-ws-spotlight]::before {
        transition: none;
    }
}

/* ============================================================
   EFFET "TRAIT LUMINEUX SVG" (onglet Avance)
   Le handler JS (ws-effects-master.js, effet ws_glowpath) injecte un
   <div.ws-gp-layer> contenant un <svg> reel dans l'element. Le trace est
   anime via stroke-dashoffset (vrai self-drawing). Blur / opacite /
   hauteur / decalage = CSS vars posees par les selectors PHP.
   ============================================================ */
.ws-gp-host {
    position: relative;
}

/* Couche decorative injectee : derriere le contenu de l'element */
.ws-gp-host > .ws-gp-layer {
    position: absolute;
    left: var(--ws-gp-x, 0px);
    top: var(--ws-gp-y, 0px);
    width: 100%;
    height: var(--ws-gp-h, 100%);
    /* plafond pour eviter les artefacts de blur GPU sur tres grande surface */
    max-height: 250vh;
    pointer-events: none;
    z-index: 0;
    /* blur capped a 60px (perf GPU) */
    filter: blur(min(var(--ws-gp-blur, 26px), 60px));
    opacity: var(--ws-gp-opacity, 1);
    will-change: filter, opacity;
}

/* Le SVG remplit la couche. overflow visible : le stroke epais ne se fait
   pas clipper par le viewport du SVG. */
.ws-gp-host > .ws-gp-layer .ws-gp-layer__svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.ws-gp-layer__path {
    fill: none;
    will-change: stroke-dashoffset;
}

/* Le contenu reel de l'element passe au-dessus du trait */
.ws-gp-host > *:not(.ws-gp-layer) {
    position: relative;
    z-index: 1;
}

/* Mode debordement : le trait peut sortir de l'element (decor d'arriere-plan) */
.ws-gp-host.ws-gp-overflow {
    overflow: visible !important;
}
.ws-gp-host.ws-gp-overflow > .elementor-widget-container {
    overflow: visible !important;
}

/* Reduce motion : trace complet affiche sans animation */
@media (prefers-reduced-motion: reduce) {
    .ws-gp-layer__path {
        stroke-dasharray: none !important;
        stroke-dashoffset: 0 !important;
    }
}

/* ==========================================================================
   Effet "Champ de Points" (ws_dotfield) - fond interactif injecte.
   Le JS (ws-dotfield-fx.js) injecte un <canvas.ws-df-canvas> en 1er enfant.
   Le canvas est EN FOND (z-index 0) ; le contenu reel passe au-dessus (z 1).
   ========================================================================== */
.ws-df-host {
    position: relative;
}

.ws-df-host > .ws-df-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
    display: block;
}

/* Le contenu reel de la section passe au-dessus du champ de points */
.ws-df-host > *:not(.ws-df-canvas) {
    position: relative;
    z-index: 1;
}

/* ============================================================
   FIX BEAM : pour les widgets dont le contenu est plus etroit que le wrapper
   (button, icon, icon-box, image, link, etc.), on force le wrapper en
   fit-content pour que la bordure lumineuse hug l'element et pas la section.
   ============================================================ */
.elementor-widget-button[data-ws-beam],
.elementor-widget-icon[data-ws-beam],
.elementor-widget-icon-box[data-ws-beam],
.elementor-widget-image[data-ws-beam],
.elementor-widget-image-box[data-ws-beam],
.elementor-widget-text-editor[data-ws-beam],
.elementor-widget-heading[data-ws-beam],
.elementor-widget-ws-modal[data-ws-beam],
.elementor-widget-ws-magnetic-button[data-ws-beam],
.elementor-widget-ws-flip-card[data-ws-beam],
.elementor-widget-ws-announcement-badge[data-ws-beam] {
    width: fit-content;
    max-width: 100%;
    /* Centre le wrapper sur sa colonne (sinon il colle a gauche) */
    margin-left: auto;
    margin-right: auto;
}

/* Si le widget a un alignement Elementor explicite (left/right), on garde le centrage par defaut */
.elementor-widget-button[data-ws-beam].elementor-align-left,
.elementor-widget-icon[data-ws-beam].elementor-align-left,
.elementor-widget-icon-box[data-ws-beam].elementor-align-left,
.elementor-widget-image[data-ws-beam].elementor-align-left,
.elementor-widget-heading[data-ws-beam].elementor-align-left {
    margin-left: 0;
}
.elementor-widget-button[data-ws-beam].elementor-align-right,
.elementor-widget-icon[data-ws-beam].elementor-align-right,
.elementor-widget-icon-box[data-ws-beam].elementor-align-right,
.elementor-widget-image[data-ws-beam].elementor-align-right,
.elementor-widget-heading[data-ws-beam].elementor-align-right {
    margin-right: 0;
}
/* ==========================================================================
   WS Lire la suite — clippe la section a une hauteur max + overlay gradient
   en bas + bouton "Lire la suite" injecte en JS. Pose par PHP via :
     data-ws-readmore="yes" + CSS vars + classe ws-readmore-pos-{pos}
   v4.9.148
   ========================================================================== */

[data-ws-readmore="yes"] {
    position: relative;
    overflow: hidden;
    max-height: var(--ws-readmore-h, 400px);
    transition: max-height var(--ws-readmore-dur, 0.4s) cubic-bezier(.2,.7,.2,1);
}

[data-ws-readmore="yes"].is-readmore-open {
    max-height: var(--ws-readmore-full-h, 5000px);
}

/* Overlay gradient en bas (cache quand ouvert) */
[data-ws-readmore="yes"]::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--ws-readmore-overlay-h, 140px);
    background: linear-gradient(to bottom, transparent 0%, var(--ws-readmore-overlay-color, #ffffff) 100%);
    pointer-events: none;
    z-index: 2;
    transition: opacity 0.35s ease;
}
[data-ws-readmore="yes"].is-readmore-open::after {
    opacity: 0;
}

/* Wrapper du bouton : absolute bas, alignement via position */
.ws-readmore-btn-wrap {
    position: absolute;
    left: 0;
    right: 0;
    bottom: var(--ws-readmore-btn-bottom, 20px);
    display: flex;
    justify-content: center;
    z-index: 3;
    pointer-events: none;
}
[data-ws-readmore="yes"].ws-readmore-pos-left  .ws-readmore-btn-wrap { justify-content: flex-start; padding-left: 24px; }
[data-ws-readmore="yes"].ws-readmore-pos-right .ws-readmore-btn-wrap { justify-content: flex-end;   padding-right: 24px; }

/* Bouton lui-meme */
.ws-readmore-btn {
    pointer-events: auto;
    cursor: pointer;
    border: none;
    font-family: inherit;
    font-size: var(--ws-readmore-btn-fs, 14px);
    font-weight: 600;
    line-height: 1;
    padding: var(--ws-readmore-btn-py, 12px) var(--ws-readmore-btn-px, 24px);
    border-radius: var(--ws-readmore-btn-radius, 999px);
    background: var(--ws-readmore-btn-bg, #111827);
    color: var(--ws-readmore-btn-color, #ffffff);
    box-shadow: 0 6px 20px rgba(0,0,0,0.12);
    transition: transform 0.2s ease, background 0.25s ease, color 0.25s ease, box-shadow 0.25s ease;
}
.ws-readmore-btn:hover {
    transform: translateY(-2px);
    background: var(--ws-readmore-btn-bg-hover, var(--ws-readmore-btn-bg, #111827));
    color: var(--ws-readmore-btn-color-hover, var(--ws-readmore-btn-color, #ffffff));
    box-shadow: 0 10px 28px rgba(0,0,0,0.18);
}
.ws-readmore-btn:active { transform: translateY(0); }

/* En editeur Elementor : section toujours ouverte (gere par le JS via la
   classe .is-readmore-open posee au boot quand body.elementor-editor-active). */
