Code for Glowing Glass Effect

On this page, you’ll find everything you need to create this glowing glass effect.

You can either click the button below to buy and download the template, or you can build it completely from scratch by following my tutorial.

Hover glow:

				
					/* css goes in .card */

selector {
    --blob-size: 250px;
}

selector .content {
    backdrop-filter: blur(80px);
    height: 100%;
}

selector .hover-color {
    width: var(--blob-size);
    height: 80%;
    left: calc(50% - calc(var(--blob-size) / 2));
    filter: blur(40px);
    z-index: -1;
    opacity: 0;
    transition: opacity 300ms 300ms linear;
}

selector .fakecolor {
    visibility: hidden;
    z-index: -1;
    height: 100%;
}
				
			

Bonus - Moving border glow:

				
					/* css goes in .card */

@property --border-angle {
    syntax: "<angle>";
    inherits: false;
    initial-value: 0deg;
}

selector {
    --blob-size: 250px;
    --border-size: 2px;
    --border-speed: 3s;
    --border-angle: 0deg;
    position: relative;
    overflow: hidden;
}

/* Animated border light */
selector::before {
    content: "";
    position: absolute;
    inset: 0;
    padding: var(--border-size);
    border-radius: inherit;
    pointer-events: none;
    z-index: 5;
    opacity: 0.75;
    transition: opacity 250ms ease;

    background: conic-gradient(
        from var(--border-angle),
        transparent 0deg,
        transparent 275deg,
        rgba(0, 180, 255, 0.1) 300deg,
        rgba(0, 200, 255, 1) 325deg,
        rgba(120, 230, 255, 0.9) 340deg,
        transparent 360deg
    );

    animation: border-orbit var(--border-speed) linear infinite;

    /* Show only the border area */
    -webkit-mask:
        linear-gradient(#000 0 0) content-box,
        linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
}

/* Make the border glow stronger on hover */
selector:hover::before {
    opacity: 1;
}

/* Border animation */
@keyframes border-orbit {
    to {
        --border-angle: 360deg;
    }
}

selector .content {
    backdrop-filter: blur(80px);
    height: 100%;
    border: none;
    border-radius: inherit;
}

selector .hover-color {
    width: var(--blob-size);
    height: 80%;
    left: calc(50% - calc(var(--blob-size) / 2));
    filter: blur(40px);
    z-index: -1;
    opacity: 0;
    transition: opacity 300ms 300ms linear;
}

selector .fakecolor {
    visibility: hidden;
    z-index: -1;
    height: 100%;
}
				
			

Classes:

card
content
hover-color
fakecolor

Colors: 
#00235A4D
#00000014
#00A6FF

Script:

				
					<script type="text/javascript">
    
const cards = document.querySelectorAll(".card");

window.addEventListener("mousemove", (ev) => {
  
  cards.forEach((e) => {
    const hoverColor = e.querySelector(".hover-color");
    const fakeColor = e.querySelector(".fakecolor");
    const rec = fakeColor.getBoundingClientRect();

    hoverColor.animate(
      [
        {
          transform: `translate(${
            (ev.clientX - rec.left) - (rec.width / 2)
          }px,${(ev.clientY - rec.top) - (rec.height / 2)}px)`
        }
      ],
      {
        duration: 300,
        fill: "forwards"
      }
    );
  
    hoverColor.style.opacity = "1";
      
  });
  
});
    
</script>


<style>

/* Main menu area CSS start */
nav.elementor-nav-menu--main ul li a:hover,
nav.elementor-nav-menu--main ul li a.elementor-item.elementor-item-active {
    background: #FFFFFF;
    border-radius: 100px;
}

.elementor-menu-toggle {
    padding: 8px;
}
/* Main menu area CSS end */

</style>
				
			

Get the finished version

Don’t want to rebuild everything from scratch?
This exact website is already built for you. 

Build it manually from scratch:

All materials:

Download Images:
  1. hero-section
  2. section
  3. promo-section
  4. promo-heading-wrapper
  5. marquee-container (ID) 
  6. animation-clip
  7. left-cloud
  8. right-cloud
  9. iphone-screen
  10. iphone-frame
  11. image-item

HTML:

				
					  <div class="hero-content-card">
                <div class="card card-one">
                    <div class="container">
                        <div class="text-bar">Branding </div>
                        <div class="icon">
                            <div class="icon-bg"></div>
                            <img decoding="async" src="https://mintcream-gnu-256830.hostingersite.com/wp-content/uploads/2026/02/1.svg" alt="">

                        </div>
                    </div>
                </div>
                <div class="card card-two">
                    <div class="container">
                        <div class="text-bar">Web Design </div>
                        <div class="icon">
                            <div class="icon-bg"></div>
                            <img decoding="async" src="https://mintcream-gnu-256830.hostingersite.com/wp-content/uploads/2026/02/2.svg" alt="">

                        </div>
                    </div>
                </div>
                <div class="card card-three">
                    <div class="container">
                        <div class="text-bar">Strategy</div>
                        <div class="icon">
                            <div class="icon-bg"></div>
                            <img decoding="async" src="https://mintcream-gnu-256830.hostingersite.com/wp-content/uploads/2026/02/3.svg" alt="">

                        </div>
                    </div>
                </div>
                <div class="card card-four">
                    <div class="container">
                        <div class="text-bar">Digital frist</div>
                        <div class="icon">
                            <div class="icon-bg"></div>
                            <img decoding="async" src="https://mintcream-gnu-256830.hostingersite.com/wp-content/uploads/2026/02/5.svg" alt="">

                        </div>
                    </div>
                </div>
                <div class="card card-five">
                    <div class="container">
                        <div class="text-bar">Responsive </div>
                        <div class="icon">
                            <div class="icon-bg"></div>
                            <img decoding="async" src="https://mintcream-gnu-256830.hostingersite.com/wp-content/uploads/2026/02/6.svg" alt="">

                        </div>
                    </div>
                </div>
                <div class="card card-six">
                    <div class="container">
                        <div class="text-bar">Visual Identity</div>
                        <div class="icon">
                            <div class="icon-bg"></div>
                            <img decoding="async" src="https://mintcream-gnu-256830.hostingersite.com/wp-content/uploads/2026/02/4.svg" alt="">

                        </div>
                    </div>
                </div>
            </div>
            
            
            
             <!-- marquee -->
    <style>
    
    
        .card-one .icon-bg {
    background-color: #ffffff;
}
.card-two .icon-bg {
    background-color: #ffffff;
}
.card-three .icon-bg {
    background-color: #ffffff; 
}
.card-four .icon-bg {
    background-color: #ffffff; 
}
.card-five .icon-bg {
    background-color: #ffffff;
}
.card-six .icon-bg {
    background-color: #ffffff;
}

             
        .marquee-container {
            position: relative;
            width: 100%;
            height: 100vh;
            min-height: 800px;
            max-height: 1200px;
            overflow-x: hidden;

        }

        @media screen and (max-width:767px) {
            .marquee-container {
                 height: 70vh;
                 min-height: 500;
                 max-height: 700px;

            }
        }

        .animation-clip {
            position: absolute;
            top: 0;
            left: 50%;
            /* margin-top: 6vw; */
            transform: translateX(-50%);
            width: min(100vw, 2500px);
            height: 100%;
            overflow: hidden;
            pointer-events: none;
        }

        .image-item {
            position: absolute;
            width: 16vw;
            aspect-ratio: 1/2;
            /*margin-top: -.5%;*/
            /* height: 300px; */
            border-radius: 32px;

            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            opacity: 0;
            transition: transform 0.3s ease;
            object-fit: cover;
        }
.image-item img {
    display:block;
    height: 100%;
    object-fit: cover;
    border-radius: 32px;
    
}
        @media only screen and (max-width: 767px) {
            .image-item img {
    display:block;
    height: 100%;
    object-fit: cover;
    border-radius: 24px;
    
}
            .image-item {

                width: 32.5vw;
                aspect-ratio: 1/2;
                border-radius: 24px ;


            }

            .iphone-frame {
                width: 33.5vw !important;
                aspect-ratio: 1/2;
                /*border-radius: 16px;*/
            }

        }

        /* .image-item:hover {
            transform: scale(1.2);
            } */

        .iphone-frame {
            position: absolute;
            /* height: 320px; */
            border-radius: 2.5vw;
            aspect-ratio: 1/2;
            width: 16.5vw;
            z-index: 10;
            display: flex;

            align-items: center;
            justify-content: center;
            transform: translate(-50%, -50%);
        }

        .iphone-screen img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }


        .left-cloud {
    position: absolute;
    top: 0;
    left: 0;
    width: 15%;
    height: 100%;
    background: linear-gradient(to right, #E0DFDF 0%, #E0DFDF 5%, transparent 100%);
    filter: blur(5px);
    z-index: 100;
}

.right-cloud {
    position: absolute;
    top: 0;
    right: 0;
    width: 15%;
    height: 100%;
    background: linear-gradient(to left, #E0DFDF 0%, #E0DFDF 5%, transparent 100%);
    filter: blur(5px);
    z-index: 100;
}

    </style>
    <!-- hero-section -->
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {

            position: relative;
            overflow-x: hidden;
        }

        .hero-section {
            min-height: 100vh;
            background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2));
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
            /* background-attachment: fixed; */
            display: flex;
            align-items: flex-end;
            justify-content: center;
            position: relative;

            /* overflow-x: hidden; */
        }

        .hero-content {
            text-align: center;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            color: white;
            padding: 1rem;
            z-index: 2;
        }

        .hero-heading {
            font-size: clamp(2.5rem, 5vw, 4rem);
            font-weight: 600;
            text-transform: uppercase;
            margin-bottom: 1.5rem;
            letter-spacing: -0.02em;

        }

        .hero-paragraph {
            font-size: clamp(1.1rem, 2vw, 1.25rem);
            margin-bottom: 2.5rem;
            max-width: 550px;
            color: rgba(255, 255, 255, 0.95);
            font-weight: 500;
            line-height: 1.7;

        }
    </style>

    <style>
        :root {
            --icon-width: 56px;
            --icon-height: 56px;
            --text-bar-width: 128px;
            --text-bar-height: 56px;
            --border-radius: 12px;
            --gap: 0px;
        }
          @media screen and (max-width:767px) {
              :root {
                   --icon-width: 40px;
            --icon-height: 40px;
            --text-bar-width: 128px;
            --text-bar-height: 40px;
            --border-radius: 8px;
              }
          }


        .hero-content-card {
            position: absolute;
            inset: 0;
            height: 100vh;
            width: 100vw;
            pointer-events: none;
            z-index: 100;

        }

        .card {

            position: relative;
            display: inline-block;
            position: absolute;
            font-size: 17px;
             font-family: "DM Sans", Sans-serif;
            /* will-change: transform, opacity; */

        }

        .card-one {
            top: 30%;
            left: 15%;
            font-family: "DM Sans", Sans-serif;
            font-weight: 700;
        }

        .card-two {
            top: 50%;
            left: 5%;
        }

        .card-three {
            top: 73%;
            left: 15%;
        }

        .card-four {
            top: 25%;
            right: 17%;
        }

        .card-five {
            top: 45%;
            right: 5%;
        }

        .card-six {
            top: 65%;
            right: 15%;
        }
         @media screen and (max-width:767px) {
             .card-one {
    top: 27%;
    left: 3%; }
             .card-five {
                 top: 28% !important;
                 right: 5%;
             }
             .card-two {
                 top:13%;
                 left: 5%;
             }
             .card-four {
                 top:20%;
                 left: 35%;
             }
            .card-three, .card-six  {
                 opacity: 0;
             }
        }

        .container {
            position: relative;
            border-radius: var(--border-radius);
            display: flex;
            align-items: center;
        }

.btn-sec-inner {
  display: flex;
  align-items: center;     
  justify-content: center;  
  gap: 10px;                
}

.btn-sec-inner p {
  margin: 0;                
}


        .icon {
            width: var(--icon-width);
            height: var(--icon-height);
            background-color: #ffffff;
            border-radius: var(--border-radius);
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
            position: relative;
            z-index: 2;
            flex-shrink: 0;
        }

        .icon img {
            width: 60%;
            aspect-ratio: 1/1;
        }

        .icon-bg {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 60%;
            aspect-ratio: 1/1;
            border-radius: 50%;
            background-color: rgb(255, 63, 63);
            z-index: -1;
        }

        .text-bar {
            background: rgba(255,255,255,0.12);
  backdrop-filter: blur(20px) saturate(130%);
  
  -webkit-backdrop-filter: blur(20px) saturate(130%);
            height: var(--icon-height);
            
            border-radius: 12px 0 0 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 15px;
            font-weight: 600;
           font-family: "DM Sans", sans-serif;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            clip-path: inset(0 0 0 100%);
            z-index: 1;
            position: relative;
            padding: 0 20px;
            white-space: nowrap;
            min-width: 100px;

        }
        .icon, .text-bar {
            transform: scale(0);
        }
    </style>
    
    <style>
        .spacer {
    width: 100%;
    height: 35vh;
}
@media screen and (max-width: 767px) {
    .spacer {
        height: 20vh;
    }
}
.promo-section {
    margin-bottom: 3rem;
}
.promo-heading-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}
.promo-badge {
    font-size: clamp(1.1rem, 2vw, 1.25rem);
    margin-bottom: 2.5rem;
    font-weight: 500;
    line-height: 1.7;
}

.promo-heading {
    /*font-size: clamp(2.5rem, 5vw, 4rem);*/
    font-weight: 500;
    text-align: center;
  
    /*margin-bottom: 1.5rem;*/
    letter-spacing: -0.02em;
}

.promo-paragraph {
    font-size: clamp(1.1rem, 2vw, 1.25rem);
    margin-bottom: 2.5rem;
    max-width: 550px;
    text-align: center;
    font-weight: 500;
    line-height: 1.2em;
}
.hero-buttons {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.btn-primary {
    display: flex;
    gap: 1rem;
    justify-content: center;
    align-items: center;
    background-color: white;
    padding: 12px 24px;
    border-radius: 16px;
    color: black;
    transform: translateY(25px);
    opacity: 0; 

}

.btn-icon {
    width: 2rem;
    aspect-ratio: 1/1;
    border-radius: 6px;
    background-color: rgb(0, 0, 0);
    display: flex;
    justify-content: center;
    align-items: center;

}

.btn-icon img {
    width: 60%;


}

.btn-secondary {
    display: flex;
    gap: 1rem;
    justify-content: center;
    align-items: center;
    padding: 12px 12px;
    color: rgb(255, 255, 255);
    position: relative;
    /* opacity: 0; */
    
    
}
.btn-secondary-bg {
    position: absolute;
    z-index: -1;
    inset: 0;
    width: 100%;
    height: 100%;
background-image: radial-gradient(circle at center, #FF587F 0%, #F04A6F 20%, #B4183D 100%);


    border-radius: 10px;
    

}
.btn-sec-inner {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 1rem;
}
.btn-sec-inner p {
    transform: translateX(150%);
}
.btn-sec-icon {
    width: 2rem;
    aspect-ratio: 1/1;
    border-radius: 6px;
    background-color: rgb(255, 255, 255);
    display: flex;
    justify-content: center;
    align-items: center;

}

.btn-sec-icon img {
    width: 60%;


}
    
    

 
  :root{
    --icon-width: 48px;
    --icon-height: 48px;
    --border-radius: 10px;
  }

  .icon{
    border-radius: 10px;
  }

  .text-bar{
    height: var(--icon-height);
    border-radius: 10px 0 0 10px;
    padding: 12px 20px 12px 20px;
  }
  
 /* © Nicolai Palmkvist – https://nicolaipalmkvist.com */

</style>

				
			

CSS:

				
					 <!-- marquee -->
    <style>
    
    
        .card-one .icon-bg {
    background-color: #ffffff;
}
.card-two .icon-bg {
    background-color: #ffffff;
}
.card-three .icon-bg {
    background-color: #ffffff; 
}
.card-four .icon-bg {
    background-color: #ffffff; 
}
.card-five .icon-bg {
    background-color: #ffffff;
}
.card-six .icon-bg {
    background-color: #ffffff;
}

             
        .marquee-container {
            position: relative;
            width: 100%;
            height: 100vh;
            min-height: 800px;
            max-height: 1200px;
            overflow-x: hidden;

        }

        @media screen and (max-width:767px) {
            .marquee-container {
                 height: 70vh;
                 min-height: 500;
                 max-height: 700px;

            }
        }

        .animation-clip {
            position: absolute;
            top: 0;
            left: 50%;
            /* margin-top: 6vw; */
            transform: translateX(-50%);
            width: min(100vw, 2500px);
            height: 100%;
            overflow: hidden;
            pointer-events: none;
        }

        .image-item {
            position: absolute;
            width: 16vw;
            aspect-ratio: 1/2;
            /*margin-top: -.5%;*/
            /* height: 300px; */
            border-radius: 32px;

            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            opacity: 0;
            transition: transform 0.3s ease;
            object-fit: cover;
        }
.image-item img {
    display:block;
    height: 100%;
    object-fit: cover;
    border-radius: 32px;
    
}
        @media only screen and (max-width: 767px) {
            .image-item img {
    display:block;
    height: 100%;
    object-fit: cover;
    border-radius: 24px;
    
}
            .image-item {

                width: 32.5vw;
                aspect-ratio: 1/2;
                border-radius: 24px ;


            }

            .iphone-frame {
                width: 33.5vw !important;
                aspect-ratio: 1/2;
                /*border-radius: 16px;*/
            }

        }

        /* .image-item:hover {
            transform: scale(1.2);
            } */

        .iphone-frame {
            position: absolute;
            /* height: 320px; */
            border-radius: 2.5vw;
            aspect-ratio: 1/2;
            width: 16.5vw;
            z-index: 10;
            display: flex;

            align-items: center;
            justify-content: center;
            transform: translate(-50%, -50%);
        }

        .iphone-screen img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }


        .left-cloud {
    position: absolute;
    top: 0;
    left: 0;
    width: 15%;
    height: 100%;
    background: linear-gradient(to right, #E0DFDF 0%, #E0DFDF 5%, transparent 100%);
    filter: blur(5px);
    z-index: 100;
}

.right-cloud {
    position: absolute;
    top: 0;
    right: 0;
    width: 15%;
    height: 100%;
    background: linear-gradient(to left, #E0DFDF 0%, #E0DFDF 5%, transparent 100%);
    filter: blur(5px);
    z-index: 100;
}

    </style>
    <!-- hero-section -->
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {

            position: relative;
            overflow-x: hidden;
        }

        .hero-section {
            min-height: 100vh;
            background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2));
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
            /* background-attachment: fixed; */
            display: flex;
            align-items: flex-end;
            justify-content: center;
            position: relative;

            /* overflow-x: hidden; */
        }

        .hero-content {
            text-align: center;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            color: white;
            padding: 1rem;
            z-index: 2;
        }

        .hero-heading {
            font-size: clamp(2.5rem, 5vw, 4rem);
            font-weight: 600;
            text-transform: uppercase;
            margin-bottom: 1.5rem;
            letter-spacing: -0.02em;

        }

        .hero-paragraph {
            font-size: clamp(1.1rem, 2vw, 1.25rem);
            margin-bottom: 2.5rem;
            max-width: 550px;
            color: rgba(255, 255, 255, 0.95);
            font-weight: 500;
            line-height: 1.7;

        }
    </style>

    <style>
        :root {
            --icon-width: 56px;
            --icon-height: 56px;
            --text-bar-width: 128px;
            --text-bar-height: 56px;
            --border-radius: 12px;
            --gap: 0px;
        }
          @media screen and (max-width:767px) {
              :root {
                   --icon-width: 40px;
            --icon-height: 40px;
            --text-bar-width: 128px;
            --text-bar-height: 40px;
            --border-radius: 8px;
              }
          }


        .hero-content-card {
            position: absolute;
            inset: 0;
            height: 100vh;
            width: 100vw;
            pointer-events: none;
            z-index: 100;

        }

        .card {

            position: relative;
            display: inline-block;
            position: absolute;
            font-size: 17px;
             font-family: "DM Sans", Sans-serif;
            /* will-change: transform, opacity; */

        }

        .card-one {
            top: 30%;
            left: 15%;
            font-family: "DM Sans", Sans-serif;
            font-weight: 700;
        }

        .card-two {
            top: 50%;
            left: 5%;
        }

        .card-three {
            top: 73%;
            left: 15%;
        }

        .card-four {
            top: 25%;
            right: 17%;
        }

        .card-five {
            top: 45%;
            right: 5%;
        }

        .card-six {
            top: 65%;
            right: 15%;
        }
         @media screen and (max-width:767px) {
             .card-one {
    top: 27%;
    left: 3%; }
             .card-five {
                 top: 28% !important;
                 right: 5%;
             }
             .card-two {
                 top:13%;
                 left: 5%;
             }
             .card-four {
                 top:20%;
                 left: 35%;
             }
            .card-three, .card-six  {
                 opacity: 0;
             }
        }

        .container {
            position: relative;
            border-radius: var(--border-radius);
            display: flex;
            align-items: center;
        }

.btn-sec-inner {
  display: flex;
  align-items: center;     
  justify-content: center;  
  gap: 10px;                
}

.btn-sec-inner p {
  margin: 0;                
}


        .icon {
            width: var(--icon-width);
            height: var(--icon-height);
            background-color: #ffffff;
            border-radius: var(--border-radius);
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
            position: relative;
            z-index: 2;
            flex-shrink: 0;
        }

        .icon img {
            width: 60%;
            aspect-ratio: 1/1;
        }

        .icon-bg {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 60%;
            aspect-ratio: 1/1;
            border-radius: 50%;
            background-color: rgb(255, 63, 63);
            z-index: -1;
        }

        .text-bar {
            background: rgba(255,255,255,0.12);
  backdrop-filter: blur(20px) saturate(130%);
  
  -webkit-backdrop-filter: blur(20px) saturate(130%);
            height: var(--icon-height);
            
            border-radius: 12px 0 0 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 15px;
            font-weight: 600;
           font-family: "DM Sans", sans-serif;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            clip-path: inset(0 0 0 100%);
            z-index: 1;
            position: relative;
            padding: 0 20px;
            white-space: nowrap;
            min-width: 100px;

        }
        .icon, .text-bar {
            transform: scale(0);
        }
    </style>
    
    <style>
        .spacer {
    width: 100%;
    height: 35vh;
}
@media screen and (max-width: 767px) {
    .spacer {
        height: 20vh;
    }
}
.promo-section {
    margin-bottom: 3rem;
}
.promo-heading-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}
.promo-badge {
    font-size: clamp(1.1rem, 2vw, 1.25rem);
    margin-bottom: 2.5rem;
    font-weight: 500;
    line-height: 1.7;
}

.promo-heading {
    /*font-size: clamp(2.5rem, 5vw, 4rem);*/
    font-weight: 500;
    text-align: center;
  
    /*margin-bottom: 1.5rem;*/
    letter-spacing: -0.02em;
}

.promo-paragraph {
    font-size: clamp(1.1rem, 2vw, 1.25rem);
    margin-bottom: 2.5rem;
    max-width: 550px;
    text-align: center;
    font-weight: 500;
    line-height: 1.2em;
}
.hero-buttons {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.btn-primary {
    display: flex;
    gap: 1rem;
    justify-content: center;
    align-items: center;
    background-color: white;
    padding: 12px 24px;
    border-radius: 16px;
    color: black;
    transform: translateY(25px);
    opacity: 0; 

}

.btn-icon {
    width: 2rem;
    aspect-ratio: 1/1;
    border-radius: 6px;
    background-color: rgb(0, 0, 0);
    display: flex;
    justify-content: center;
    align-items: center;

}

.btn-icon img {
    width: 60%;


}

.btn-secondary {
    display: flex;
    gap: 1rem;
    justify-content: center;
    align-items: center;
    padding: 12px 12px;
    color: rgb(255, 255, 255);
    position: relative;
    /* opacity: 0; */
    
    
}
.btn-secondary-bg {
    position: absolute;
    z-index: -1;
    inset: 0;
    width: 100%;
    height: 100%;
background-image: radial-gradient(circle at center, #FF587F 0%, #F04A6F 20%, #B4183D 100%);


    border-radius: 10px;
    

}
.btn-sec-inner {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 1rem;
}
.btn-sec-inner p {
    transform: translateX(150%);
}
.btn-sec-icon {
    width: 2rem;
    aspect-ratio: 1/1;
    border-radius: 6px;
    background-color: rgb(255, 255, 255);
    display: flex;
    justify-content: center;
    align-items: center;

}

.btn-sec-icon img {
    width: 60%;


}
    
    

 
  :root{
    --icon-width: 48px;
    --icon-height: 48px;
    --border-radius: 10px;
  }

  .icon{
    border-radius: 10px;
  }

  .text-bar{
    height: var(--icon-height);
    border-radius: 10px 0 0 10px;
    padding: 12px 20px 12px 20px;
  }
  
 /* © Nicolai Palmkvist – https://nicolaipalmkvist.com */

</style>

				
			

HTML button:

				
					<a href="https://nicolaipalmkvist.com" class="btn-secondary-link">
    <div class="btn-secondary">
        <div class="btn-secondary-bg"></div>
        <div class="btn-sec-inner">

            <p>Start a project</p>
            <div class="btn-sec-icon">
                <img decoding="async" src="https://mintcream-gnu-256830.hostingersite.com/wp-content/uploads/2025/09/100.svg" alt="">
            </div>
        </div>
    </div>
</a>

				
			

Javascript:

				
					<link data-minify="1" rel="stylesheet" href="https://nicolaipalmkvist.com/wp-content/cache/min/1/lenis@1.3.11/dist/lenis.css?ver=1783635154"> 
   <script data-minify="1" src="https://nicolaipalmkvist.com/wp-content/cache/min/1/npm/gsap@3.13.0/dist/ScrollToPlugin.min.js?ver=1782830202"> </script>
<script data-minify="1" src="https://nicolaipalmkvist.com/wp-content/cache/min/1/npm/gsap@3.13.0/dist/ScrollTrigger.min.js?ver=1782830202"></script>
<script data-minify="1" src="https://nicolaipalmkvist.com/wp-content/cache/min/1/npm/gsap@3.13.0/dist/SplitText.min.js?ver=1782830202"></script>
<script data-minify="1" src="https://nicolaipalmkvist.com/wp-content/cache/min/1/lenis@1.3.8/dist/lenis.min.js?ver=1782830202"></script>
<script data-minify="1" src="https://nicolaipalmkvist.com/wp-content/cache/min/1/ajax/libs/gsap/3.12.2/gsap.min.js?ver=1782830202"></script>
<script>// Initialize a new Lenis instance for smooth scrolling
const lenis = new Lenis();

// Synchronize Lenis scrolling with GSAP's ScrollTrigger plugin
lenis.on('scroll', ScrollTrigger.update);

// Add Lenis's requestAnimationFrame (raf) method to GSAP's ticker
// This ensures Lenis's smooth scroll animation updates on each GSAP tick
gsap.ticker.add((time) => {
  lenis.raf(time * 1000); // Convert time from seconds to milliseconds
});

// Disable lag smoothing in GSAP to prevent any delay in scroll animations
gsap.ticker.lagSmoothing(0);



// new lenis 




</script>


// <script>
// gsap.registerPlugin(SplitText)
// gsap.registerPlugin(ScrollTrigger)
//      gsap.registerPlugin(ScrollToPlugin) 
//         // Create ScrollTrigger for section 2
//       ScrollTrigger.create({
//     trigger: ".promo-section",
//     start: "bottom 95%",
//     onEnter: () => {
        
//         // Wait for next frame to ensure smooth start
//         requestAnimationFrame(() => {
//             requestAnimationFrame(() => {
//                 gsap.to(window, { 
//                     duration: 3, 
//                     scrollTo: { 
//                         y: "#marquee-container", 
//                         offsetY: 150 
//                     },
//                     ease: "power1.inOut"
//                 });
//             });
//         });
//     },
//     // once: true
// });
// </script>
<script> class ViewportTriggeredMarquee {
    constructor() {
        this.container = document.getElementById('marquee-container');
        this.images = [];
        this.amplitude = 150;
        this.arcMultiplier = .3; // Default arc multiplier
        this.hasAnimated = false;

        this.init();
    }

    init() {
        this.collectImages();
        this.updateResponsiveSettings();
        this.positionIPhoneFrame();
        this.setupIntersectionObserver();

        // Add resize listener
        window.addEventListener('resize', () => {
            this.updateResponsiveSettings();
            this.positionIPhoneFrame();
        });
    }

    updateResponsiveSettings() {
        const width = window.innerWidth;

        if (width < 768) {
            // Mobile: 5 images
            this.visibleImages = 5;
            this.amplitude = 70;
            this.arcMultiplier = -2;
        } else if (width >= 768 && width <= 1200) {
            // Tablet: 7 images
            this.visibleImages = 7;
            this.amplitude = 120;
            this.arcMultiplier = .2;
        } else if (width > 1200 && width <= 1350) {
            // Large tablet: 9 images
            this.visibleImages = 7;
            this.amplitude = 120;
            this.arcMultiplier = .3;
        } else {
            // Desktop: 11 images
            this.visibleImages = 7;
            this.amplitude = 150;
            this.arcMultiplier = .3;
        }

        this.showHideImages();
    }

    showHideImages() {
        // Show/hide images based on screen size
        this.images.forEach((imageObj, index) => {
            if (index < this.visibleImages) {
                imageObj.element.style.display = 'block';
                imageObj.active = true;
            } else {
                // imageObj.element.style.display = 'none';
                imageObj.active = false;
            }
        });

        // Update active images array
        this.activeImages = this.images.filter(img => img.active);
    }

    collectImages() {
        const imageElements = this.container.querySelectorAll('.image-item');

        this.images = Array.from(imageElements).map((element, index) => ({
            element: element,
            index: index,
            active: true
        }));
    }

    positionIPhoneFrame() {
        // Always position at the center of the visible images
        const centerProgress = 0.5;
        const centerPosition = this.calculatePosition(centerProgress);

        const iPhoneFrame = document.querySelector('.iphone-frame');
        if (iPhoneFrame) {
            iPhoneFrame.style.left = centerPosition.x + 'px';
            iPhoneFrame.style.top = centerPosition.y + 'px';
        }
    }

    setupIntersectionObserver() {
        const observer = new IntersectionObserver(
            (entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting && entry.intersectionRatio >= 0.5 && !this.hasAnimated) {
                        this.startAnimation();
                        this.hasAnimated = true;
                    }
                });
            },
            {
                threshold: [0.5]
            }
        );

        observer.observe(this.container);
    }

    calculatePosition(progress) {
        // Cap the effective window width at 2500px for ultra-wide screens
        const actualWidth = window.innerWidth;
        const windowWidth = Math.min(actualWidth, 2500);
        const windowHeight = window.innerHeight;

        // X position: start from right and move to left within the capped width
        const x = (windowWidth + 100) - (progress * (windowWidth + 200));

        // Y position follows an arc above center
        // const normalizedX = Math.max(0, Math.min(1, progress)) * Math.PI;
        // const y = (windowHeight / 2) - Math.sin(normalizedX) * this.amplitude;
        const normalizedX = Math.max(0, Math.min(1, progress)) * Math.PI;
        const arcOffset = this.amplitude * this.arcMultiplier;
        const y = (windowHeight / 2) - Math.sin(normalizedX) * this.amplitude + arcOffset;

        return { x, y };
    }

    getLeftOffset() {
        const actualWidth = window.innerWidth;
        return actualWidth > 2500 ? (actualWidth - 2500) / 2 : 0;
    }

    startAnimation() {
        // Phase 1: Reveal all active cards along the path
        this.revealCards().then(() => {
            // Phase 2: Move cards sequentially
            setTimeout(() => {
                this.moveCardsSequentially();
            }, 1000);
        });
    }

    async revealCards() {
        return new Promise((resolve) => {
            const totalDuration = 2500;
            const startTime = performance.now();

            // Set initial positions for active images only
            this.activeImages.forEach((imageObj, index) => {
                const startProgress = (index / (this.activeImages.length - 1)) - 0.8;
                const startPosition = this.calculatePosition(startProgress);

                imageObj.element.style.left = startPosition.x + 'px';
                imageObj.element.style.top = startPosition.y + 'px';
                imageObj.element.style.transform = 'translate(-50%, -50%)';
                imageObj.element.style.opacity = 1;
            });

            const animate = (currentTime) => {
                const elapsed = currentTime - startTime;
                const progress = Math.min(elapsed / totalDuration, 1);
                const easedProgress = 1 - Math.pow(1 - progress, 3);

                this.activeImages.forEach((imageObj, index) => {
                    const startProgress = (index / (this.activeImages.length - 1)) - 0.8;
                    const targetProgress = index / (this.activeImages.length - 1);
                    const currentProgress = startProgress + (targetProgress - startProgress) * easedProgress;
                    const position = this.calculatePosition(currentProgress);

                    imageObj.element.style.left = position.x + 'px';
                    imageObj.element.style.top = position.y + 'px';
                });

                if (progress < 1) {
                    requestAnimationFrame(animate);
                } else {
                    // Ensure exact final positions
                    this.activeImages.forEach((imageObj, index) => {
                        const finalProgress = index / (this.activeImages.length - 1);
                        const finalPosition = this.calculatePosition(finalProgress);
                        imageObj.element.style.left = finalPosition.x + 'px';
                        imageObj.element.style.top = finalPosition.y + 'px';
                    });
                    resolve();
                }
            };

            requestAnimationFrame(animate);
        });
    }

    moveCardsSequentially() {
        this.stepIndex = 0;

        // Ensure cards are in exact initial positions
        this.activeImages.forEach((imageObj, index) => {
            const initialProgress = index / (this.activeImages.length - 1);
            const position = this.calculatePosition(initialProgress);
            imageObj.element.style.left = position.x + 'px';
            imageObj.element.style.top = position.y + 'px';
            imageObj.element.style.opacity = 1;
        });

        this.moveToNextStep();
    }

    moveToNextStep() {
        const stepDuration = 800;
        const startTime = performance.now();

        const currentPositions = this.activeImages.map((imageObj) => ({
            x: parseFloat(imageObj.element.style.left),
            y: parseFloat(imageObj.element.style.top)
        }));

        const animate = (currentTime) => {
            const elapsed = currentTime - startTime;
            const progress = Math.min(elapsed / stepDuration, 1);
            const easedProgress = 1 - Math.pow(1 - progress, 3);

            this.activeImages.forEach((imageObj, index) => {
                const currentCardPosition = index + this.stepIndex;
                const targetCardPosition = currentCardPosition + 1;

                let normalizedTarget = (targetCardPosition / (this.activeImages.length - 1)) % (this.activeImages.length / (this.activeImages.length - 1));

                const currentPos = currentPositions[index];
                let targetPosition = this.calculatePosition(normalizedTarget);

                if (targetPosition.x > currentPos.x + (window.innerWidth / 2)) {
                    const offScreenRightProgress = -0.3;
                    const offScreenRightPosition = this.calculatePosition(offScreenRightProgress);

                    const x = offScreenRightPosition.x + (targetPosition.x - offScreenRightPosition.x) * easedProgress;
                    const y = offScreenRightPosition.y + (targetPosition.y - offScreenRightPosition.y) * easedProgress;

                    imageObj.element.style.left = x + 'px';
                    imageObj.element.style.top = y + 'px';
                } else {
                    const x = currentPos.x + (targetPosition.x - currentPos.x) * easedProgress;
                    const y = currentPos.y + (targetPosition.y - currentPos.y) * easedProgress;

                    imageObj.element.style.left = x + 'px';
                    imageObj.element.style.top = y + 'px';
                }

                const currentX = parseFloat(imageObj.element.style.left);
                if (currentX < -100) {
                    imageObj.element.style.opacity = 0;
                } else {
                    imageObj.element.style.opacity = 1;
                }
            });

            if (progress < 1) {
                requestAnimationFrame(animate);
            } else {
                this.stepIndex++;
                setTimeout(() => {
                    this.moveToNextStep();
                }, 800);
            }
        };

        requestAnimationFrame(animate);
    }
}

// Initialize the marquee
const marquee = new ViewportTriggeredMarquee();</script>
<script>
gsap.registerPlugin(SplitText)
gsap.registerPlugin(ScrollTrigger)




const breakpoint = 767;

gsap.set('.icon', { scale: 0 })
gsap.set('.text-bar', { scale: 0 })

let totalDistance;

const marqueeContainer = document.getElementById('marquee-container');

const buttonSecondary = document.querySelector('.btn-secondary')
const secondaryIcon = document.querySelector('.btn-sec-icon');
const buttonSecondaryWidth = buttonSecondary.offsetWidth
const secondaryIconWidth = secondaryIcon.offsetWidth

const buttonSecondarydistancefromLeft = buttonSecondary.getBoundingClientRect().right
const secondaryIcondistancefromLeft = secondaryIcon.getBoundingClientRect().right;

const button_icon_distance = buttonSecondarydistancefromLeft - secondaryIcondistancefromLeft;

const c = (2 * button_icon_distance) + secondaryIconWidth
const ratio_icon_button = c / buttonSecondaryWidth;
const offset = -(buttonSecondaryWidth / 2) + (c / 2);
// console.log({
//     buttonSecondary, secondaryIcon, buttonSecondaryWidth, secondaryIconWidth,
//     buttonSecondarydistancefromLeft, secondaryIcondistancefromLeft, button_icon_distance, c, ratio_icon_button
// })

gsap.set(buttonSecondary, { x: -(buttonSecondaryWidth / 2) + (c / 2) })
gsap.set('.btn-secondary-bg', { width: c, x: (buttonSecondaryWidth - c) })
// gsap.set('.btn-sec-inner p', {xPercent: 100})
// gsap.timeline({ delay: 2 }).to('.btn-secondary-bg', { width: buttonSecondaryWidth, x: (buttonSecondaryWidth / 2) - (c / 2) })
//     .to('.btn-sec-icon', { x: (buttonSecondaryWidth / 2) - (c / 2) }, '<')
//     .to('.btn-sec-inner p', { x: (buttonSecondaryWidth / 2) - (c / 2) }, '<')


document.fonts.ready.then(() => {
    const mainTimelineLanding = gsap.timeline()
    const promoTimeline = gsap.timeline();
    const splitHeading = SplitText.create(".hero-heading", {
        type: "words,lines",
        linesClass: "line",
        autoSplit: true
    });

    const splitPara = SplitText.create(".hero-paragraph", {
        type: "words,lines",
        linesClass: "line",
        autoSplit: true
    });
    const splitPromoHeading = SplitText.create(".promo-heading", {
        type: "words,lines",
        linesClass: "line",
        autoSplit: true
    });

    const splitPromoPara = SplitText.create(".promo-paragraph", {
        type: "lines",
        linesClass: "line",
        autoSplit: true
    });
    const splitPromoBadge = SplitText.create(".promo-badge", {
        type: "lines",
        linesClass: "line",
        autoSplit: true
    });
    gsap.set(".hero-heading", { opacity: 1 });
    gsap.set(".hero-paragraph", { opacity: 1 });
    mainTimelineLanding
        .from(splitHeading.words, {
            duration: 1.3,
            filter: 'blur(5px)',
            yPercent: 40,
            opacity: 0,
            stagger: 0.02,
            ease: "expo.out"
        })
        .from(splitPara.lines, {
            duration: 1.3,
            filter: 'blur(5px)',
            yPercent: 100,
            opacity: 0,
            stagger: 0.2,
            ease: "expo.out"
        }, '-=1')
        .to('.btn-primary', {
            y: 0,
            filter: 'blue(5px)',
            duration: .3,
            opacity: 1,
            stagger: 0.1,
            ease:'sine.out',
        }, '-=.8')

    gsap.from(splitPromoHeading.words, {
        duration: 0.5,
        filter: 'blur(5px)',
        yPercent: 40,
        opacity: 0,
        stagger: 0.02,
        ease: "expo.out",
        scrollTrigger: {
            trigger: splitPromoHeading.words[0]?.parentElement || ".promo-heading",
            start: "top 90%",
            // toggleActions: "play none none reverse"
        }
    });

    // Badge animation
    gsap.from(splitPromoPara.lines, {
        duration: 1.3,
        filter: 'blur(5px)',
        yPercent: 100,
        opacity: 0,
        stagger: 0.2,
        ease: "expo.out",
        scrollTrigger: {
            trigger: splitPromoBadge.lines[0]?.parentElement || ".promo-badge",
            start: "top 70%",
            // toggleActions: "play none none reverse"
        }
    });

    // Button animation
    gsap.from(splitPromoBadge.lines, {
        yPercent: 80,
        filter: 'blur(5px)',
        duration: .8,
        opacity: 0,
        stagger: 0.2,
        scrollTrigger: {
            trigger: ".btn-primary",
            start: "top 70%",
            // toggleActions: "play none none reverse"
        }
    });


    gsap.timeline({
        scrollTrigger: {
            trigger: ".btn-secondary", // Or use a parent container
            start: "top 70%", // Animation starts when top of element hits 70% from top of viewport
            // end: "bottom 30%", // Optional: end point
            // toggleActions: "play none none reverse", // play on enter, reverse on leave
            // markers: true, // Uncomment for debugging
        }
    })
        .from('.btn-secondary', { scale: .1, duration: .4, transformOrigin: `${(buttonSecondaryWidth / 2) - offset}px center` })
        .to('.btn-secondary-bg', {
            width: buttonSecondaryWidth,
            x: (buttonSecondaryWidth / 2) - (c / 2)
        })
        .to('.btn-sec-icon', {
            x: (buttonSecondaryWidth / 2) - (c / 2)
        }, '<')
        .to('.btn-sec-inner p', {
            x: (buttonSecondaryWidth / 2) - (c / 2)
        }, '<');

})


function animateCard(card, delay = 0) {
    const icon = card.querySelector('.icon');
    const textBar = card.querySelector('.text-bar');
    const container = card.querySelector('.container');

    // Get actual dimensions
    const textBarWidth = textBar.offsetWidth;
    const iconWidth = icon.offsetWidth;
    totalDistance = textBarWidth + iconWidth;

    // Create timeline for this card
    const tl = gsap.timeline({
        delay: delay,
        // repeat: -1,
        repeatDelay: 2,
    });

    // Animation sequence
    tl.to(icon, { scale: 1 })
    tl.to(textBar, { scale: 1 }, '<')
        .to(icon, {
            x: -totalDistance * 2 / 3,
            borderRadius: "12px 0 0 12px",
            duration: 1.2,
            ease: 'power2.out'
        })
        .to(textBar, {
            clipPath: 'inset(0 0 0 0%)',
            borderRadius: "0 12px 12px 0",
            duration: 1.2,
            x: totalDistance / 3,
            ease: 'power2.out'
        }, "<") // Start at the same time as icon animation


}


// Wait for page load then start animations
const cards = document.querySelectorAll('.card');
// window.addEventListener('load', () => {
    // gsap.matchMedia().add(`(min-width: ${breakpoint + 1}px)`, () => {

        // Animate each card with a slight delay between them
        cards.forEach((card, index) => {
            // animateCard(card, 1.5 + (index * 0.3));
            animateCard(card, 1.2);
        });
    // })
// });




function calculateDistance() {
    const cardThree = document.querySelector('.card-three');
    const btnSecondary = document.querySelector('.btn-secondary');

    if (!cardThree || !btnSecondary) {
        console.log('Elements not found!');
        return null;
    }

    // Get bounding rectangles
    const cardRect = cardThree.getBoundingClientRect();
    const btnRect = btnSecondary.getBoundingClientRect();

    // Calculate different types of distances
    const verticalDistance = btnRect.top - cardRect.bottom;
    const horizontalDistance = btnRect.left - cardRect.right;
    const centerToCenter = Math.sqrt(
        Math.pow(btnRect.left + btnRect.width / 2 - (cardRect.left + cardRect.width / 2), 2) +
        Math.pow(btnRect.top + btnRect.height / 2 - (cardRect.top + cardRect.height / 2), 2)
    );

    // Get absolute positions (accounting for scroll)
    const scrollY = window.scrollY;
    const cardAbsoluteTop = cardRect.top + scrollY;
    const btnAbsoluteTop = btnRect.top + scrollY;
    const absoluteVerticalDistance = btnAbsoluteTop - (cardAbsoluteTop + cardRect.height);

    const distances = {
        vertical: verticalDistance,
        horizontal: horizontalDistance,
        centerToCenter: centerToCenter,
        absoluteVertical: absoluteVerticalDistance,
        cardPosition: cardAbsoluteTop,
        buttonPosition: btnAbsoluteTop
    };

    console.log('Distance Results:', distances);
    return distances;
}

// Call the function
const verticalDistance = calculateDistance().absoluteVertical 

setTimeout(() => {
    gsap.matchMedia().add(`(min-width: ${breakpoint + 1}px)`, () => {

        cards.forEach((card, i) => {
            const cardTimeline = gsap.timeline({
                scrollTrigger: {
                    trigger: ".card-three",
                    start: "top 70%",
                    endTrigger: ".promo-section",
                    end: "top 90%",
                    scrub: true,
                    // markers:true,

                }
            })
            const icon = card.querySelector('.icon')
            const textBar = card.querySelector('.text-bar')
            cardTimeline.to(icon, {

                x: - totalDistance / 3,
                borderRadius: "12px 12px 12px 12px",
                duration: 1.2,
                // ease: 'power2.out'
            })
                .to(textBar, {
                    clipPath: 'inset(0 0 0 100%)',
                    borderRadius: "12px 12px 12px 12px",
                    duration: .7,
                    x: -totalDistance * 1 / 3,
                    opacity: 0
                    // ease: 'power2.out'
                }, '<') // Start at the same time as the reverse icon animation


            const cardTimelineScale = gsap.timeline({
                scrollTrigger: {
                    trigger: ".promo-section",
                    start: "top 90%",
                    endTrigger: ".btn-secondary",
                    end: "top center",
                    scrub: true,
                }
            })
            cardTimelineScale.to(icon, {
                borderRadius: "12px 12px 12px 12px",
                scale: 1.3
            })


        const offseta = (i % 3) * 100
            
        gsap.to(card, {
            scrollTrigger: {
                trigger: ".card-three",
                start: "top 70%",
                endTrigger: ".btn-secondary",
                end: "top center",
                scrub: true,



            },

            y: verticalDistance + offseta,
            borderRadius: "12px 12px 12px 12px",
            ease: "none",

        });

        })


        // card vertical travel animation

    })
    gsap.matchMedia().add(`(max-width: ${breakpoint }px)`, () => {
ScrollTrigger.normalizeScroll(true);
        cards.forEach((card, i) => {
            const cardTimeline = gsap.timeline({
                scrollTrigger: {
                    trigger: ".card-three",
                    start: "top 70%",
                    endTrigger: ".promo-section",
                    end: "top 50%",
                    scrub: true,
                    // markers:true,

                }
            })
            const icon = card.querySelector('.icon')
            const textBar = card.querySelector('.text-bar')
            cardTimeline.to(icon, {

                x: - totalDistance / 3,
                borderRadius: "12px 12px 12px 12px",
                duration: 1.2,
                // ease: 'power2.out'
            })
                .to(textBar, {
                    clipPath: 'inset(0 0 0 100%)',
                    borderRadius: "12px 12px 12px 12px",
                    duration: .7,
                    x: -totalDistance * 1 / 3,
                    opacity: 0
                    // ease: 'power2.out'
                }, '<') // Start at the same time as the reverse icon animation


            const cardTimelineScale = gsap.timeline({
                scrollTrigger: {
                    trigger: ".promo-section",
                    start: "top 90%",
                    endTrigger: ".btn-secondary",
                    end: "top center",
                    scrub: true,
                }
            })
            // cardTimelineScale.to(icon, {
            //     borderRadius: "12px 12px 12px 12px",
            //     scale: 1.3
            // })


        })
            const offseta = 200;
                  const animationConfig = {
                0: verticalDistance + offseta,
                1: (verticalDistance * 1.5) + offseta,
                3: (verticalDistance * 1.3) + offseta,  // Example: 1.5x distance
                4: (verticalDistance * 1) + offseta   // Example: 0.7x distance
            };
            
            cards.forEach((card, i) => {
                if (animationConfig[i] !== undefined) {
                    gsap.to(card, {
                        scrollTrigger: {
                            trigger: ".card-three",
                            start: "top 70%",
                            endTrigger: ".btn-secondary",
                            end: "top center",
                            scrub: .5,
                            invalidateOnRefresh: true,
                            // markers:true,
                        },
                        y: animationConfig[i],
                        x:(i % 2) * 30,
                        borderRadius: "12px 12px 12px 12px",
                        ease: "none",
                    });
                }
            });


        // card vertical travel animation

    })




}, 4000)




// gsap.matchMedia().add(`(min-width: ${breakpoint + 1}px)`, () => {

    cards.forEach((card, i) => {

        gsap.to(cards[0].querySelector('.container'), { // Animate each card, not just cards[0]
            scale: 0,
            opacity: 0,
            x: 120,
            y: 70,
            // x: 20 + (i * 50), // Different x for each card
            // y: 15 + (i * 30),
            // duration: 2.5,
            scrollTrigger: {
                trigger: marqueeContainer,
                // trigger: '.btn-secondary',
                start: "top 52%",
                end: '+=500',
                toggleActions: "play none none reverse",
                // scrub: true,
            },
        });
        gsap.to(cards[1].querySelector('.container'), { // Animate each card, not just cards[0]
            scale: 0,
            opacity: 0,
            x: 150,


            scrollTrigger: {
                trigger: marqueeContainer,
                // trigger: '.btn-secondary',
                start: "top 50%",
                end: '+=500',
                toggleActions: "play none none reverse",
                // scrub: true,
            },
        });
        gsap.to(cards[2].querySelector('.container'), { // Animate each card, not just cards[0]
            scale: 0,
            opacity: 0,
            x: 150,
            y: -60,

            scrollTrigger: {
                trigger: marqueeContainer,
                // trigger: '.btn-secondary',
                start: "top 50%",
                end: '+=500',
                toggleActions: "play none none reverse",
                // scrub: true,
            },
        });
        gsap.to(cards[3].querySelector('.container'), { // Animate each card, not just cards[0]
            scale: 0,
            opacity: 0,
            x: -150,
            y: 70,
            // x: 20 + (i * 50), // Different x for each card
            // y: 15 + (i * 30),
            // duration: 2.5,
            scrollTrigger: {
                trigger: marqueeContainer,
                // trigger: '.btn-secondary',
                start: "top 50%",
                end: '+=500',
                toggleActions: "play none none reverse",
                // scrub: true,
            },
        });
        gsap.to(cards[4].querySelector('.container'), { // Animate each card, not just cards[0]
            scale: 0,
            opacity: 0,
            x: -100,


            scrollTrigger: {
                trigger: marqueeContainer,
                // trigger: '.btn-secondary',
                start: "top 50%",
                end: '+=500',
                toggleActions: "play none none reverse",
                // scrub: true,
            },
        });
        gsap.to(cards[5].querySelector('.container'), { // Animate each card, not just cards[0]
            scale: 0,
            opacity: 0,
            x: -150,
            y: -50,

            scrollTrigger: {
                trigger: marqueeContainer,
                // trigger: '.btn-secondary',
                start: "top 50%",
                end: '+=500',
                toggleActions: "play none none reverse",
                // scrub: true,
            },
        });
    });
// });







</script>
				
			

Make image move:

				
					selector {
    transform-origin: center center;
    animation: kenBurns 10s ease-in-out infinite alternate;
}

@keyframes kenBurns {
    0% {
        transform: scale(1);
    }
    100% {
        transform: scale(1.2);
    }
}
				
			

Unlock your best work yet

Launch premium websites and save hours on every project.

All Access — 12 Months

One-time payment. Access for 12 months. Instant access. 

$199

$259

All access — Lifetime

Most people choose

One-time payment. Never pay again.
Instant access.

$249

$459