/*
Theme Name: Divi-Cactus
Theme URI: http://www.cactussenygrafic.com/
Version: 1.0
Description: Plantilla desenvolupada per Cactus
Author: Cactus Seny Grafic
Author URI: https://www.cactussenygrafic.com/
Template: Divi
*/


/** font custom **/
:root{
  --blur: 40px;
    --button-blur: 10px;

    --glow-duration: 12s;
    --c8:#b5f1ac;
    --c7:#fdb77e;
    --c6:#f8556b;
    --c5:#fc90c6;
    --c4:#b735a4;
    --c3:#3853e9;
    --c2:#9db7ff;
    --c1:#e2b0ff;
}

@font-face {
    font-family: 'HelveticaNowDisplay';
    src: url('fonts/HelveticaNowDisplay-Regular.woff2') format('woff2'),
        url('fonts/HelveticaNowDisplay-Regular.woff') format('woff');
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'HelveticaNowDisplay';
    src: url('fonts/HelveticaNowDisplay-Bold.woff2') format('woff2'),
        url('fonts/HelveticaNowDisplay-Bold.woff') format('woff');
    font-weight: bold;
    font-style: normal;
    font-display: swap;
}

body, p, h1, h2, h3, h4, h5, h6, a, span:not(.ab-icon), li, div, td, th, label, input, textarea, button, .saes {font-family: 'HelveticaNowDisplay', 'Helvetica Now Display', Helvetica,Arial,Lucida,sans-serif;}
.preset--module--divi-text--default .et_pb_text_inner, .preset--module--divi-text--default .et_pb_text_inner p{font-family: 'HelveticaNowDisplay','Helvetica Now Display', Helvetica,Arial,Lucida,sans-serif;}
.preset--module--divi-text--2318b48617 .et_pb_text_inner h2 *{font-family: 'HelveticaNowDisplay',Helvetica,Arial,Lucida,sans-serif;}

.service_card,.glass_card{backdrop-filter: blur(var(--blur));}
.et_pb_button:not(.btn-solid){backdrop-filter: blur(var(--button-blur));}

#offcanvas_open *{color:#fff; cursor: pointer;}
#offcanvas_close{cursor: pointer;}

/* --p es la variable que anima el relleno tipo "pill" (ul.dsm-menu .sub-menu a
   y .csg_pils a) via clip-path. Sin registrarla con @property el navegador
   no sabe que es un <percentage> animable: en el primer hover no tiene un
   valor previo valido para interpolar y el clip-path salta en vez de
   animarse (glitch), y solo a partir del segundo hover se ve la transicion
   bien. Registrandola arranca ya animada desde el primer hover.
   inherits TIENE que ser true: --p se fija en el propio <a> al hacer :hover,
   y de ahi debe heredar a sus hijos (::before y .btn-label--invert), que son
   los que realmente pintan el relleno y el texto invertido via su propio
   calc(100% - var(--p)). Con inherits:false cada hijo cae en su
   initial-value (0%) en vez de heredar el 100% del padre, y el hover no
   llega a verse nunca -- verificado en vivo (sin el fix, el pill no
   reacciona al hover en absoluto). */
@property --p {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 0%;
}

ul.dsm-menu .menu-item-has-children{display: flex;    align-items: flex-end;}
ul.dsm-menu .menu-item-has-children .sub-menu{display: flex;flex-wrap: nowrap;white-space: nowrap; height: fit-content; gap: 12px;margin-bottom: 12px;}
ul.dsm-menu .menu-item-has-children .sub-menu a{position: relative;overflow: hidden;border: 1px solid #000;border-radius: 999px;padding: 4px 12px;display: inline-flex;align-items: center;background: transparent;color: #000;--p: 0%;}
ul.dsm-menu .menu-item-has-children .sub-menu a::before{content:"";position:absolute;inset:0;background:#000;border-radius: inherit;clip-path: inset(0 calc(100% - var(--p)) 0 0 round 999px);transition: clip-path .35s cubic-bezier(.2,.8,.2,1);z-index: 0;}
ul.dsm-menu .menu-item-has-children .sub-menu a .btn-label{position: relative;z-index: 2;color: #000;line-height: 1;}
ul.dsm-menu .menu-item-has-children .sub-menu a .btn-label--invert{position: absolute;inset: 0;display: inline-flex;align-items: center;padding: 4px 12px;border-radius: inherit;color: #fff;z-index: 1;clip-path: inset(0 calc(100% - var(--p)) 0 0 round 999px);transition: clip-path .35s cubic-bezier(.2,.8,.2,1);pointer-events: none;}
ul.dsm-menu .menu-item-has-children .sub-menu a:hover,ul.dsm-menu .menu-item-has-children .sub-menu a:focus-visible{--p: 100%;}
ul.dsm-menu .menu-item-has-children .sub-menu a:hover .btn-label,ul.dsm-menu .menu-item-has-children .sub-menu a:focus-visible .btn-label{z-index: -1;}

#software_brands, #about_cactus{padding: 36px 0px;position: relative;display: block;width: 100%;}
#software_brands:before, #about_cactus:before{content:"";position: absolute;inset: 0;background: linear-gradient(90deg,rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 100%);pointer-events: none;z-index: 2; width: 15%; left:0px;}
#software_brands:after, #about_cactus:after{content:"";position: absolute;inset: 0;background: linear-gradient(90deg,rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);pointer-events: none;z-index: 2; width: 15%; left:calc(100% - 15%);}

#about_cactus span{margin:0 10px; border-radius:16px; overflow: hidden;}

.csg_pils a, .csg_pils a{position: relative;overflow: hidden;border: 1px solid #000;border-radius: 999px;padding: 4px 12px !important;display: inline-flex;align-items: center;background: transparent;--p: 0%;border:1px solid #fff;}
.csg_pils a::before{content:" " !important;position:absolute;inset:0;background:#fff;border-radius: inherit;clip-path: inset(0 calc(100% - var(--p)) 0 0 round 999px);transition: clip-path .35s cubic-bezier(.2,.8,.2,1);z-index: 0;}
.csg_pils a .btn-label{position: relative;z-index: 2;color: #fff;line-height: 1;}
.csg_pils a .btn-label--invert{position: absolute;inset: 0;display: inline-flex;align-items: center;padding: 4px 12px !important;border-radius: inherit;color: #000;z-index: 1;clip-path: inset(0 calc(100% - var(--p)) 0 0 round 999px);transition: clip-path .35s cubic-bezier(.2,.8,.2,1);pointer-events: none;}
.csg_pils a:hover,.csg_pils a:focus-visible, .csg_pils a.active{--p: 120%;}
.csg_pils a:hover .btn-label,.csg_pils a:focus-visible .btn-label, .csg_pils a.active .btn-label{z-index: -1;}

.h2_big_title h2{line-height: 1em !important;}
.h2_big_title .line-mask{padding:0; letter-spacing: -0.01em;}

.canvasWrapper{position: relative;width: 100%;min-height: 60vh;padding-top: 100%;isolation: isolate;}
/* En pantallas muy anchas y bajas, el alto de .canvasWrapper (atado a su
   ancho, no al de la ventana) puede superar el alto visible. La fila que
   lo contiene usa Sticky Position de Divi (position:fixed), y un
   position:fixed ignora el overflow:hidden de sus ancestros salvo que
   alguno de ellos actue como su "containing block" -- de ahi el
   transform, que no cambia nada visualmente pero hace que el recorte
   funcione de verdad. Asi el canvas mantiene su tamaño/comportamiento de
   siempre y solo se recorta lo que sobra de la ventana. */
section:has(.canvasWrapper){overflow: hidden; transform: translateZ(0);}
#shape-canvas{position: absolute;inset: 0;width: 100%;height: 100%;display: block;z-index: 0;will-change: transform;transform: translateZ(0);pointer-events: none;}

#software_brands .js-marquee span{margin:0 2em; }

.line-mask{overflow: hidden;}
.text-split-line{display: block;}

#menu_section.active{filter: invert(1);}
#menu_section{position: fixed !important;top: 0;left: 0;width: 100%;z-index: 99997 !important;}

/* === CSG Text Animation — RESET SÓLIDO === */
.csg-text-anim{display:block;position:relative;vertical-align:top;margin-top: 10px;height: 1em !important;}
.csg-ta-layer{ position:absolute; left:0; top:0; white-space:nowrap; overflow: hidden; margin-top: -0.15em; }
.csg-ta-layer .line-mask{padding-bottom: 0px; margin-bottom: 0px;}
.csg-ta-layer .line-mask span{padding-bottom: 0.2em;margin-bottom: -0.2em;}
.csg-ta-current{ z-index:1; }
.csg-ta-next{ z-index:2; }
/* padding-bottom + margin-bottom negativo: da hueco de sobra para las
   descendentes (g, j, p...) antes del overflow:hidden, sin cambiar el
   alto que este bloque ocupa en el layout (mismo patron que
   .textAnimation .line-mask). Solo afecta a .csg-text-anim (titulo
   rotativo de home/footer) -- el resto de .line-mask del sitio no toca
   esta regla. */
.csg-text-anim .line-mask{display:block;overflow:hidden;height:1.2em;line-height:1;padding-bottom:1.25em;margin-bottom:-0.15em;}
.csg-text-anim .line-mask > span{display:block;transform:translateY(0%);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}


/* ===== CACTUS Footer (SVG + follower suave) ===== */
.csg-footer-cactus{position: relative;display:block;width:100%;--csg-size: 16vw;--csg-gap:  2vw;--csg-fw: 260px;--csg-fh: 320px;}
.csg-footer-row{display:flex;align-items:flex-end;gap:var(--csg-gap);line-height:0; color:#fff;}
.csg-footer-cactus .csg-letter{display:block;flex:0 0 16.666666%;transition: opacity .3s ease;}
.csg-footer-cactus .csg-letter svg{display:block;width:100%;height: 293px;}
.csg-footer-follower{position:absolute; left:0; top:0;width:var(--csg-fw); height:var(--csg-fh);pointer-events:none; z-index:5;opacity:0;transform: translate(-50%,-50%) rotate(0deg) scale(.95);transition: none;transform-origin: 50% 50%;will-change: transform, opacity;filter: drop-shadow(0 20px 50px rgba(0,0,0,.35));}
.csg-follow-img, .csg-follow-video{position:absolute; inset:0;width:100%; height:100%;object-fit:cover; border-radius:18px;opacity:0;transition: none !important;}
.csg-footer-cactus.blend .csg-footer-follower{ mix-blend-mode:difference; }
.csg-footer-cactus .csg-letter:hover{opacity: 0.5;filter: blur(8px);}


/* ===== Metodologia (semicírculo superior con items en círculo) ===== */
.csg-metodo{
  --csg-size: 1264px;
  --csg-active-scale: 1.15;
  --csg-gap: 16px;
  width: min(100%, var(--csg-size));
  margin-inline: auto;
  position: relative;
  outline: none;
}
.csg-metodo-viewport{width: 100%;aspect-ratio: var(--csg-ratio, 1264 / 717);position: relative;overflow: hidden;}
.csg-metodo-ring{position: absolute;border: 1px solid rgba(255,255,255,.35);border-radius: 50%;pointer-events: none;box-shadow: 0 -16px 32px rgba(0,0,0,.15) inset;}
.csg-metodo-track{ list-style:none; padding:0; margin:0; }
.csg-metodo-item{list-style:none;position: absolute;transform: translate(-50%,-50%);will-change: transform, left, top;cursor: pointer;user-select: none;}
.csg-bubble{--b-size: clamp(180px, 20vw, 260px);width: var(--b-size);height: var(--b-size);border-radius: 50%;border: 1px solid rgba(255,255,255,.5);color: rgba(255,255,255,.8);background: #000;display: flex; align-items: center;justify-content: center;flex-direction: column;text-align: center;padding: 22px;line-height: 1.3;transition: background .2s ease, color .2s ease, box-shadow .2s ease, border-color .2s ease, transform .2s ease;}
.csg-bubble-title{ margin:0 0 .5rem; font-weight:700; font-size:clamp(14px,1.6vw,20px); }
.csg-bubble-text { font-size:clamp(12px,1.3vw,16px); opacity:.85; }
.csg-metodo-item.is-active .csg-bubble{background:#fff; color:#000; border-color:#fff; box-shadow:0 20px 50px rgba(0,0,0,.25);transform: scale(var(--csg-active-scale)); transition: background .2s ease, color .2s ease, box-shadow .2s ease, border-color .2s ease, transform .2s ease;}
.csg-metodo-item.is-active .csg-bubble .csg-bubble-title{color: #000;}

.csg-metodo-item:not(.is-active) .csg-bubble:hover{background-color: #111;}
.csg-metodo-viewport:after{content:" "; position: absolute; bottom: 0; left: 0; width: 100%; height: 40%; background: linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0)); pointer-events: none;}


/* === CSG Button Anim === */
.et_pb_button .csg-btn__overflow{position: relative !important;display: inline-block !important;overflow: hidden !important;vertical-align: top !important;line-height: inherit !important;}
.et_pb_button .csg-btn__anim{position: relative !important;display: block !important;will-change: transform;transform: translateY(0%) !important;transition: transform .4s cubic-bezier(.215,.61,.355,1);}
.et_pb_button .csg-btn__text{ display:block !important; }
.et_pb_button .csg-btn__text.is-absolute{position:absolute !important;inset:0;transform: translateY(150%) !important;}
.et_pb_button.csg-btn-ready:hover .csg-btn__anim{transform: translateY(-150%) !important;}


/* === CSG Blog Accordeon === */
.csg-ba{width:100%;display:flex;flex-direction:column;background:transparent;}
.csg-ba__item{position:relative;display:flex;gap:28px;align-items:center;padding:44px 0;border-top:1px solid rgba(255,255,255,.12);}
.csg-ba__item:last-child{border-bottom:1px solid rgba(255,255,255,.12);}
.csg-ba__item .csg-ba__media_holder{flex: 0 0 25%;overflow:hidden;}
.csg-ba__item .csg-ba__content{flex: 0 0 50%}
.csg-ba__item .csg-ba__media{height:100%;clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);transition: all 0.5s ease-in-out;}
.csg-ba__media{display:block;position:relative;width:100%;aspect-ratio:5/3;border-radius:20px;overflow:hidden;background-size:cover;background-position:center;filter:saturate(1.05) contrast(1.05);}
.csg-ba__cta{display:block;margin-top: auto;}
.csg-ba__btn{border:0px; border-radius: 100px; background-color: rgba(255,255,255,.12); color:#fff; font-size:14px; font-weight:500; padding:12px 22px !important; width:fit-content; transition: background-color .2s ease; font-size: 16px;display: block;}
.csg-ba__btn:after{display: none !important;}
.csg-ba__btn:hover{background-color: rgba(255,255,255,1) !important; padding:12px 22px !important; color: #000;border:0px !important}
.csg-ba__btn:hover *{color: #000 !important;}
.csg-ba__meta, .csg-ba__content{height: -webkit-fill-available;display: flex;flex-direction: column;}
.csg-ba__content{position:relative;z-index:2;display:flex;flex-direction:column;gap:18px;min-width:0;}
.csg-ba__author{display: flex;align-items: center; margin-bottom: 22px;margin-top: auto;}
.csg-ba__avatar{border-radius: 100%;margin-right: 12px; overflow: hidden;}
.csg-ba__authorText{display: flex; flex-direction: column; font-size: 16px;}
.csg-ba__cat{font-size: 16px;}
.csg-ba__titleLink{margin-top:auto; color:#fff;}
.csg-ba__title{color: #fff !important;}
.csg-ba__item.is-active .csg-ba__media{clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);}
.csg-ba__excerpt{overflow:hidden;}
.csg-ba__cta{overflow:hidden;}





.csg-vswipers{display:flex;gap:0px;width:100%;align-items:stretch;transform:scale(1.25);height:720px;overflow:hidden;background-color:#202020;}
.csg-vswipers__col{flex:1;min-width:0;overflow:hidden;border-radius:18px;transform:scale(1.05);}
.csg-vswipers__col .csg-vswiper{height:720px;overflow:hidden;}
.csg-vswiper{will-change:transform;transform:translateZ(0);}
.csg-vswiper .swiper-wrapper{transition-timing-function:linear !important;}
.csg-vswiper .swiper-slide{height:auto;margin-top: -5%;}
.csg-vm__item{display:block;margin-bottom:0px;border-radius:18px;overflow:hidden;transform:translateZ(0);margin-top:-5%;pointer-events:none;-webkit-user-select:none;user-select:none;}
.csg-vm__item img{display:block;width:100%;height:auto;border-radius:18px;pointer-events:none;-webkit-user-drag:none;}
@media (max-width:980px){.csg-vswipers{flex-direction:column;height:auto;transform:none;}.csg-vswipers__col .csg-vswiper{height:420px;}}

.faq_single{padding: 52px 0;border-bottom: 1px solid rgba(255, 255, 255, 0.25);}
.faq_title{cursor: pointer;}
.faq_title {cursor: pointer;display: flex;align-items: center;justify-content: space-between;gap: 16px;}
.faq_title i {flex-shrink: 0;display: block;width: 16px;height: 16px;position: relative;}
.faq_content{margin-right: 3em;}
.faq_title i::before,.faq_title i::after {content: '';display: block;position: absolute;background: currentColor;border-radius: 2px;top: 50%;left: 0;right: 0;height: 1.5px;transform: translateY(-50%);}
.faq_title i::after {transform: translateY(-50%) rotate(90deg);}
.faq_content {overflow: hidden;}
.faq_content p:first-child{padding-top:1.5em}

.service_card.et_clickable{transition: all 0.5s;}
.service_card.et_clickable:active {
  transform: scale(0.95) rotateZ(1.7deg);
}




/* === CSG PORTFOLIO SLIDER === */
/* :not(.forminator-checkbox):not(.forminator-radio) -- el <label> que
   envuelve el checkbox/radio real de Forminator (input + .forminator-*-box)
   tambien matchea ".forminator-field label", asi que sin esta exclusion el
   !important de abajo lo dejaba con display:none -- el checkbox de
   "He llegit i accepto..." desaparecia por completo, no solo su label de
   texto (que va aparte, en .forminator-checkbox__label / -description). */
.forminator-field label:not(.forminator-checkbox):not(.forminator-radio), .forminator-description{display: none !important;}
.forminator-button-submit{padding: 15px 30px 15px 30px !important;border-radius: 50px !important;font-size:18px !important;}
.forminator-ui.forminator-custom-form[data-design=flat] input.forminator-input{border-radius: 12px !important;padding:16px 26px !important; border:1px solid rgba(255,255,255,0.2) !important; background-color: rgba(255,255,255,0.08) !important; transition: all 0.5 ease-in-out;}
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-textarea{border-radius: 12px !important;padding:16px 26px !important; border:1px solid rgba(255,255,255,0.2) !important; background-color: rgba(255,255,255,0.08) !important; transition: all 0.5 ease-in-out;}


.forminator-ui.forminator-custom-form[data-design=flat] input.forminator-input:hover,
.forminator-ui.forminator-custom-form[data-design=flat] input.forminator-input:focus,
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-textarea:hover,
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-textarea:focus{border:1px solid rgba(255,255,255,0.5) !important; background-color: rgba(255,255,255,0.15) !important;}
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-field{position: relative;}
.forminator-ui#forminator-module-6900.forminator-design--flat .forminator-error-message{background: transparent !important;color: white !important;margin-top: 0px;right: 0;padding: 0 !important; position: absolute !important;}

/* Enlace a la politica de privacitat dentro del checkbox de consentimiento
   -- el reset global de subrayados (helpers.css, text-decoration:initial en
   casi todos los <a>) se lo quitaba tambien a este. */
.forminator-consent__label a{text-decoration: underline !important;}

/* Checkbox de consentimiento: mismo estilo (fondo negro semitransparente,
   borde redondeado) que los input/textarea de arriba. El "✓" es el
   ::before de .forminator-checkbox-box con color:inherit (CSS propio de
   Forminator) -- por eso basta con cambiar `color` en el estado :checked
   para que el ✓ pase a negro sin tocar su ::before. */
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-checkbox.forminator-consent .forminator-checkbox-box{
  border-radius: 6px !important;
  border: 1px solid rgba(255,255,255,0.2) !important;
  background-color: rgba(255,255,255,0.08) !important;
  transition: all 0.5s ease-in-out;
}
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-checkbox.forminator-consent .forminator-checkbox-box:hover{
  border-color: rgba(255,255,255,0.5) !important;
  background-color: rgba(255,255,255,0.15) !important;
}
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-checkbox.forminator-consent input:checked + .forminator-checkbox-box{
  background-color: #fff !important;
  border-color: #fff !important;
  color: #000 !important;
}

/* Placeholder de Nom/Correu/textarea -- blanco al 50% en vez del gris
   por defecto de Forminator. */
.forminator-ui.forminator-custom-form[data-design=flat] input.forminator-input::placeholder,
.forminator-ui.forminator-custom-form[data-design=flat] .forminator-textarea::placeholder{
  color: rgba(255,255,255,0.5) !important;
  opacity: 1 !important;
}

/* Separacion del formulario: 12px en total entre columnas (Nom/Correu uno
   al lado del otro) y entre filas -- por defecto Forminator usa 30px entre
   columnas (15px de padding a cada lado de .forminator-col) y 20px entre
   filas (.forminator-row/.forminator-col con margin-bottom). Se reescala
   el mismo mecanismo (padding+margin negativo compensatorio) con la mitad,
   6px, para que sume 12px de hueco visible. */
.forminator-ui.forminator-custom-form .forminator-row,
.forminator-ui.forminator-custom-form .forminator-row-inside{
  margin-left: -6px !important;
  margin-right: -6px !important;
}
.forminator-ui.forminator-custom-form .forminator-col{
  padding-left: 6px !important;
  padding-right: 6px !important;
}
.forminator-ui.forminator-custom-form .forminator-row:not(:last-child),
.forminator-ui.forminator-custom-form .forminator-row-inside:not(:last-child),
.forminator-ui.forminator-custom-form .forminator-col:not(:last-child){
  margin-bottom: 12px !important;
}

/* === CSG PORTFOLIO SLIDER === */

.csg-ps-wrap {
  position: relative;
  width: 100%;
}

.csg-ps {
  width: 100%;
}

/* Swiper assigna width inline — aspect-ratio aquí funciona sempre */
.csg-ps .swiper-slide {
  aspect-ratio: 500 / 560;
  height: auto;
}

/* El <a> omple el swiper-slide */
.csg-ps-slide{
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  text-decoration: none;
  color: #fff;
  clip-path: inset(0% round 20px);
    transition: clip-path 0.4s cubic-bezier(0.16, 1, 0.3, 1);

}
.csg-ps.is-dragging .csg-ps-slide {
  clip-path: inset(2% round 20px);
}

/* Background: imatge */
.csg-ps-bg--img {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

.csg-ps-slide:hover .csg-ps-bg--img {
  transform: scale(1.05);
}

/* Background: vídeo */
.csg-ps-bg--video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Overlay gradient */
.csg-ps-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0,0,0,0.08) 0%,
    rgba(0,0,0,0.0)  40%,
    rgba(0,0,0,0.65) 100%
  );
  transition: opacity 0.4s ease;
}

.csg-ps-slide:hover .csg-ps-overlay {
  opacity: 0.85;
}

/* Contingut */
.csg-ps-body {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 52px;
}

/* Top: favicon + servicios */
.csg-ps-top {
  display: flex;
  align-items: center;
  gap: 12px;
}

.csg-ps-favincon-wrapper {
  width: 48px;
  height: 48px;
  overflow: hidden;
  border-radius: 500px;
  flex-shrink: 0;
}

.csg-ps-favincon-wrapper img,
.csg-ps-favincon-wrapper picture {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Bottom: títol + servicios */
.csg-ps-bottom {
  display: flex;
  align-items: flex-end;
  gap: 16px;
}

.csg-ps-content {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.csg-ps-title {
  font-size: clamp(1.2rem, 2.5vw, 1.6rem);
  font-weight: 600;
  margin: 0;
  line-height: 1.2;
  color: #fff;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
  padding:0px
}



.csg-ps-servicios {
  font-size: 0.8rem;
  color: rgba(255,255,255,0.8);
  margin: 0;
  line-height: 1.4;
}

.csg-ps-arrow {
  font-size: 1.4rem;
  line-height: 1;
  flex-shrink: 0;
  opacity: 0;
  transform: translate(-6px, 6px);
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}



/* Dots */
.csg-ps-pagination.swiper-pagination {
  position: relative !important;
  bottom: auto !important;
  margin-top: 24px;
  display: flex !important;
  justify-content: center;
  align-items: center;
  gap: 6px;
  height: 16px;
}

.csg-ps-pagination .swiper-pagination-bullet {
  display: inline-block !important;
  width: 6px !important;
  height: 6px !important;
  background: currentColor !important;
  opacity: 0.25 !important;
  border-radius: 99px !important;
  transition: width 0.4s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.4s ease !important;
  margin: 0 !important;
  flex-shrink: 0;
}

.csg-ps-pagination .swiper-pagination-bullet-active {
  width: 28px !important;
  opacity: 1 !important;
}

.csg-ps-follower {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 10;
  width: 180px;
  height: 180px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  white-space: nowrap;
  color: #fff;
  background-color: rgba(255,255,255,0.05);
  backdrop-filter: blur(8px);
  border-radius: 99px;
  will-change: transform, opacity;
  pointer-events: none;
}


/* === CSG PORTFOLIO GRID (override sobre classes del slider) === */

.csg-pg-wrap {display: grid;grid-template-columns: repeat(3, 1fr);gap: 24px;}
.csg-pg-cols-2 { grid-template-columns: repeat(2, 1fr); }
.csg-pg-cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 767px) {
  .csg-pg-wrap { grid-template-columns: 1fr; }
}
/* .csg-ps-slide en grid necessita alçada pròpia, no la que li dona .swiper-slide */
.csg-pg-item {aspect-ratio: 500 / 560;position: relative;}
.csg-pg-item .csg-ps-slide {position: absolute;inset: 0;overflow:hidden; border-radius:20px;}
.csg-portfolio-cats{row-gap: 8px;display: flex;flex-wrap: wrap;column-gap: 5px;}


.csg_blog_list .csg_blog_item {display: flex;gap: 40px;padding: 50px 0;border-bottom: 1px solid rgba(255,255,255,0.15);align-items: flex-start; backdrop-filter: blur(var(--blur));position: relative;}
.csg_blog_list .csg_blog_item:first-child{border-top: 1px solid rgba(255,255,255,0.15);}


.csg_blog_list .csg_blog_item a{color:#fff;text-decoration: none;}
.csg_blog_list .csg_blog_item .et_pb_button{background-color:hsl(from var(--gcid-secondary-color) calc(h + 0) calc(s + 0) calc(l + 0) / 0.1);color: var(--gcid-secondary-color) !important;font-size: 18px !important;letter-spacing: -0.5px !important;line-height: 1.2em !important;border-top-left-radius: 50px;border-top-right-radius: 50px;border-bottom-left-radius: 50px;border-bottom-right-radius: 50px;border-width: 0px;transition-duration: 300ms;transition-timing-function: ease;transition-delay: 0ms;padding-top: 20px !important;padding-right: 45px !important;padding-bottom: 20px !important;padding-left: 45px !important;}

.csg_blog_list .csg_blog_item .et_pb_button:hover{background-color:#fff;color: #000 !important;}
.csg_blog_list .csg_blog_item .et_pb_button:hover:after{display: none !important;}

.csg_blog_list .csg_blog_image { flex: 0 0 200px; }
.csg_blog_list .csg_blog_image img { width: 100%; border-radius: 12px; }
.csg_blog_list .csg_blog_content { flex: 1; display:flex; flex-direction:column;height: -webkit-fill-available; }

.csg_blog_list .csg_blog_content .csg_blog_excerpt{width:80%; margin-top:1em; margin-bottom:auto; font-size:var(--gvid-eu42auk7dc);}
.csg_blog_list .csg_blog_meta {align-items: center;gap: 12px;margin-top: 30px;flex-wrap: wrap; margin-top:auto;flex: 0 0 20%}
.csg_blog_list .csg_blog_meta .csg_blog_author {display: flex;align-items: top;gap: 12px;margin-bottom:2em}

.csg_blog_list .csg_blog_author_avatar img {width: 44px; height: 44px; border-radius: 50%; object-fit: cover;}
.csg_blog_list .csg_blog_categories { margin-left: auto; display: flex; gap: 8px; }
.csg_blog_list .csg_blog_cat {border: 1px solid rgba(255,255,255,0.3);border-radius: 20px;padding: 4px 14px;font-size: 13px;}

#header_blog_single .et-pb-background-video:after{content:" "; position:absolute;inset:0;background:linear-gradient(0deg,rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 0) 62%);z-index:1;}
#ez-toc-container{background:transparent;border-radius: var(--gvid-fsgieqizpp);box-shadow: 0 0 0 1px rgba(255,255,255,.15);padding: 32px;width: 100%;max-width: unset;    margin-bottom: 3em;}

#ez-toc-container .ez-toc-title{font-size:var(--gvid-eu42auk7dc) !important; color:#fff}

div#ez-toc-container ul li, div#ez-toc-container ul li a{font-size:var(--gvid-eu42auk7dc) !important;color:rgba(255,255,255,0.5);}
div#ez-toc-container ul li a:hover{color:rgba(255,255,255,1);}

nav.custom-pagination .page-numbers{display: flex; justify-content: center; margin-top: 1em;}
.page-numbers a, .page-numbers span.current{width: 5em;height: 5em;display: flex;align-items: center;justify-content: center;border-radius: 10em;background: #000;margin: 0.5em;color: #fff;box-shadow: 0 0 0 1px rgba(255,255,255,.15);}
.page-numbers span.current{background-color: #fff !important; color:#000 !important;margin-top: 1em;}


.csg_blog_content ul, .csg_blog_content ol{margin-left:1em}
.csg_blog_content ul li, .csg_blog_content ol li{margin-bottom:1em}
.csg_blog_content p a{text-decoration:underline !important; font-size:100%; color:rgba(255,255,255,0.8); }
.csg_blog_content p a:hover{color:rgba(255,255,255,1) !important;}
.csg_blog_content ul li strong{color:#fff}
.et_pb_post_content.csg_blog_content h2{margin-top:1em !important; padding-top:1em !important; border-top:1px solid rgba(255, 255, 255, 0.25) !important;}


.faq_title_text{line-height:1.2}

.video_hero:after {
    content: " ";
    position: absolute;
    inset: 0;
    background: linear-gradient(0deg, rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 0) 62%);
    z-index: 1; height:50%; top:unset; bottom:0; left:0;
}

@media (max-width:650px){

  .et_pb_column .et_pb_module.csg_marquee_item{margin-bottom:0px !important;}
  
  .csg-metodo{
    position: relative;
    overflow: hidden;
    aspect-ratio: 1 / 1.7;            /* 👈 sube, porque el viewport ahora es más alto */
    --csg-gap: 50px !important;       /* 👈 baja bastante, gana radio */
    --csg-offset: -0.05 !important;
  }

  

  .csg-metodo-viewport{
    width: 150vw !important;
    height: auto !important;
    position: absolute;
    left: 50%;
    aspect-ratio: 1 / 0.85 !important; /* 👈 antes 1/0.45 — mucho menos plano */
    transform: translate(-50%, 0%);
    margin: 0;
  }

  .csg-ps-follower{display: none !important;}
  .csg-ps-body{padding:26px !important;}

  
.csg-row-slider-outer{
  color: #fff;
  width: 100%;
  min-width: 0;
}
.csg-row-slider-clip{
  overflow: hidden;
  width: 100%;
  min-width: 0;
}
.csg-row-slider{
  width: 100%;
  min-width: 0;
}
.csg-row-slider .swiper-wrapper{ align-items: stretch; }

.csg-row-slider .swiper-slide{
  display: flex;
  min-width: 0;
  height: auto;
}

/* Genérico (por si el hijo no es .service_card en otras rows) */
.csg-row-slider .swiper-slide > *{
  display: flex !important;
  flex-direction: column !important;
  width: 100% !important;
  height: 100% !important;
  min-width: 0;
}

/* Específico: pisa las reglas flex propias de Divi en .service_card */
.csg-row-slider .swiper-slide .service_card{
  height: 100% !important;
  align-self: stretch !important;
  flex-shrink: 0 !important;
}

.dsm_menu_0_tb_header .menu-item{margin-bottom:-22px !important}


.csg_blog_list .csg_blog_item{flex-direction: column;padding: 30px 0;border: 1px solid rgba(255, 255, 255, 0.25);align-items: flex-start;backdrop-filter: blur(var(--blur));position: relative; border-radius: 12px; margin-bottom: 30px;padding:32px}
.csg_blog_list .csg_blog_content .csg_blog_excerpt{width: 100%;}
.csg_blog_list .csg_blog_image{max-width:45%;    flex: 0 0 45%;}
.csg_blog_meta{display:none;}
.csg_blog_list .csg_blog_item .et_pb_button{display:none}
.csg-footer-cactus .csg-letter svg{height:65px;}
.csg-footer-follower{display:none !important;}

#about_cactus span img{width:auto; max-height:40vh}


/* =====================================================================
   REPASO RESPONSIVE MOBILE / TABLET — 2026-09-10
   Ajustes localizados, sin tocar el resto del CSS. Cada regla indica
   el problema que corrige y en que breakpoint se detecto.
   ===================================================================== */

/* Divi (style.min.css del theme padre) trae de fabrica
   ".et_pb_column .et_pb_module{margin-bottom:30px}" dentro de su propio
   "@media (max-width:980px)" -- mismo rango (tablet + movil, no solo
   tablet) que su regla original, asi que se cubre aqui con el mismo
   max-width en vez del rango 768-980 de "TABLET" de abajo. Sin
   !important no le gana: esa regla de Divi no lo lleva, pero el orden de
   carga entre este stylesheet y el CSS dinamico de Divi no esta
   garantizado. */
@media (max-width: 980px) {
  .et_pb_column .et_pb_module {
    margin-bottom: 0px !important;
  }
}

/* --- TABLET (768px - 980px, breakpoint "Tablet" de Divi) --- */
@media only screen and (min-width: 768px) and (max-width: 980px) {

  /* Menu offcanvas: los enlaces principales (Cactus, Serveis, Projectes...)
     usan font-size:94px con line-height:1em heredado del modulo de Divi
     Theme Builder, y van envueltos en .line-mask (overflow:hidden, usado
     por el efecto de reveal del texto). Con line-height igual al
     font-size el cuadro de linea es mas bajo que la caja de la letra y
     el texto queda recortado o directamente invisible. Se sube el
     line-height para dar aire sin tocar el font-size. */
  .dsm_menu_0_tb_header ul.dsm-menu li a {
    line-height: 1.25em !important;
  }

  /* Panel del menu offcanvas (#offcanvas) usa height:fit-content, asi que
     si el contenido del menu es mas bajo que la pantalla (caso tablet en
     vertical) el panel no llega hasta abajo y se ve la pagina negra de
     detras asomando bajo el menu blanco. Forzamos que cubra siempre el
     alto de la pantalla. */
  #offcanvas {
    min-height: 100vh !important;
  }
}

/* --- MOBILE (hasta 767px, breakpoint "Phone" de Divi) --- */
@media only screen and (max-width: 767px) {

  /* Mismo problema que en tablet pero con font-size:60px: el line-height:1em
     recorta la parte superior de las mayusculas del menu offcanvas dentro
     de .line-mask (overflow:hidden). */
  .dsm_menu_0_tb_header ul.dsm-menu li a {
    line-height: 1.25em !important;
  }

  /* Misma proteccion que en tablet para que el panel #offcanvas cubra
     siempre toda la pantalla aunque el contenido del menu sea bajo. */
  #offcanvas {
    min-height: 100vh !important;
  }
}

}

/* ==========================================================================
   [csg_archived_projects] -- listado de proyectos de archivo
   Mismo layout/interaccion que https://www.doubleplay.studio/projects:
   categoria a la izquierda, titulo en el centro, año a la derecha. Fondo
   negro y, al hacer hover, la fila se cubre de blanco (en la referencia es
   azul) revelando la imagen destacada junto al año.
   ========================================================================== */
.csg-archive-list {
  background: #000;
  width: 100%;
}

.csg-archive-row {
  position: relative;
  overflow: hidden; /* la pastilla (::before) no se sale de la fila -- = .section-layer-div de la referencia */
  display: grid;
  grid-template-columns: minmax(90px, 1fr) auto minmax(90px, 1fr);
  align-items: center;
  gap: clamp(12px, 3vw, 32px);
  padding: clamp(18px, 3vw, 32px) 20px;
  border-bottom: 1px solid rgba(255, 255, 255, .15);
  text-decoration: none;
  color: #fff;
}
.csg-archive-list .csg-archive-row:first-child {
  border-top: 1px solid rgba(255, 255, 255, .15);
}

/* La "pastilla": ocupa toda la fila (position:absolute; inset:0) y crece
   VERTICALMENTE desde ABAJO hacia arriba (scaleY 0 -> 1, transform-origin:
   bottom), no desde el centro ni de lado a lado. El texto no usa
   mix-blend-mode: es un color que transiciona a la vez (mas abajo),
   heredado desde la fila. transform-style/will-change replican el
   scale3d(1,0,1) + preserve-3d que genera Webflow para forzar GPU, aunque
   aqui no haya ninguna rotacion 3D real. */
.csg-archive-row::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #fff;
  transform: scaleY(0);
  transform-origin: bottom;
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform .4s cubic-bezier(.65, 0, .35, 1);
  pointer-events: none;
}
.csg-archive-row:hover::before,
.csg-archive-row.is-active::before,
.csg-archive-row:focus-visible::before {
  transform: scaleY(1);
}

/* Estado hover/activo/foco: el color de texto (heredado por cat/title/year)
   pasa a negro, sincronizado con el crecimiento de la pastilla de arriba. */
.csg-archive-row:hover,
.csg-archive-row.is-active,
.csg-archive-row:focus-visible {
  color: #000;
}

.csg-archive-row__cat,
.csg-archive-row__center,
.csg-archive-row__year {
  position: relative;
  z-index: 1;
}

.csg-archive-row__cat {
  opacity: 1;
  transition: opacity .28s ease, color .28s ease;
}

/* Agrupa titulo + miniatura para que la imagen aparezca pegada al titulo
   (no junto al año) al hacer hover. */
.csg-archive-row__center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.csg-archive-row__title {
  text-align: center;
  font-size: clamp(28px, 5vw, 56px);
  font-weight: 700;
  line-height: 1.05;
  margin: 0;
  color: inherit;
  transition: color .28s ease;
}

/* Oculta hasta el hover -- crece de 0 a 140px pegada al titulo, igual que
   en la referencia. */
.csg-archive-row__thumb {
  display: block;
  width: 0;
  height: 64px;
  margin-left: 0;
  border-radius: 8px;
  overflow: hidden;
  opacity: 0;
  transform: scale(.92);
  transition: width .32s ease, opacity .28s ease, transform .32s ease, margin-left .32s ease;
  flex-shrink: 0;
}
.csg-archive-row__thumb img {
  width: 140px;
  max-width: none;
  height: 64px;
  object-fit: cover;
  display: block;
}

.csg-archive-row__year {
  text-align: right;
  font-size: 13px;
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
  opacity: .75;
  transition: opacity .28s ease, color .28s ease;
}

/* Estado "activo": el ::before (arriba) ya reacciona a :hover/.is-active/
   :focus-visible. Aqui solo el resto de detalles del hover -- reaparicion
   de la miniatura y opacidad plena de categoria/año -- compartidos entre
   :hover (raton), .is-active (tactil, ver cactus_custom.js) y
   :focus-visible (teclado). */
.csg-archive-row:focus-visible,
.csg-archive-row.is-active {
  outline: none;
}
.csg-archive-row:focus-visible .csg-archive-row__thumb,
.csg-archive-row.is-active .csg-archive-row__thumb {
  width: 140px;
  margin-left: 20px;
  opacity: 1;
  transform: scale(1);
}
.csg-archive-row:focus-visible .csg-archive-row__cat,
.csg-archive-row:focus-visible .csg-archive-row__year,
.csg-archive-row.is-active .csg-archive-row__cat,
.csg-archive-row.is-active .csg-archive-row__year {
  opacity: 1;
}

@media (hover: hover) {
  .csg-archive-row:hover .csg-archive-row__thumb {
    width: 140px;
    margin-left: 20px;
    opacity: 1;
    transform: scale(1);
  }
  .csg-archive-row:hover .csg-archive-row__cat,
  .csg-archive-row:hover .csg-archive-row__year {
    opacity: 1;
  }
}

@media only screen and (max-width: 767px) {
  .csg-archive-row {
    grid-template-columns: 1fr;
    justify-items: start;
    gap: 6px;
  }
  .csg-archive-row__center {
    justify-content: flex-start;
  }
  .csg-archive-row__title {
    text-align: left;
    font-size: clamp(24px, 8vw, 36px);
  }
  /* El reveal de imagen es un efecto de hover -- en tactil no hay hover
     real, asi que la ocultamos para no dejar espacio muerto reservado. */
  .csg-archive-row__thumb {
    display: none;
  }
}