ToolsWaves
Free GSAP Landing Page Template ยท ToolsWaves ยท Tech

Free Tech Studio Hero Template with Lightning Animation

Free tech studio landing page template from ToolsWaves featuring a stroke-drawn lightning-bolt loader with crackling electric arcs, four animated slides, lime pill nav, and spark bursts on interactions. Copy and use it in any project โ€” fully free.

TechBoltSliderSparkLime Accent

About this ToolsWaves template

This free tech studio template on ToolsWaves uses a stroke-drawn lightning-bolt loader complete with crackling electric arcs to establish a high-energy visual tone before the page resolves. Once loaded, it transitions through four slides covering different focus areas โ€” technology, design, growth, teams โ€” making it appropriate for agency, studio, and consulting sites that want to communicate range. Spark bursts on arrow clicks add momentum to every interaction, and the lime accent against a dark background gives the page a confident modern feel.

Use this template for SaaS development studios, growth marketing agencies, technology consultancies, or any tech-adjacent brand that wants to feel current. The template is completely free on ToolsWaves with no sign-up or licensing fee โ€” copy the three files into your project, swap the placeholder content for your own services, and replace the demo branding with your company's identity. The GSAP timeline is structured so you can easily adjust animation speed or remove specific effects without restructuring the code.

Copy the code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Free Tech Studio Hero Template with Lightning Animation</title>
  <meta name="description" content="Free GSAP tech studio landing page hero from ToolsWaves" />
  <meta name="generator" content="ToolsWaves - https://toolswaves.in/landing-pages" />

  <!-- Open Graph -->
  <meta property="og:title" content="Free Tech Studio Hero Template with Lightning Animation" />
  <meta property="og:description" content="Free GSAP tech studio landing page hero from ToolsWaves" />
  <meta property="og:type" content="website" />
  <meta property="og:image" content="https://toolswaves.in/og?title=Free%20Tech%20Studio%20Hero%20Template%20with%20Lightning%20Animation&category=Landing%20Page&icon=%F0%9F%93%84" />

  <!-- Twitter -->
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:title" content="Free Tech Studio Hero Template with Lightning Animation" />
  <meta name="twitter:description" content="Free GSAP tech studio landing page hero from ToolsWaves" />
  <meta name="twitter:image" content="https://toolswaves.in/og?title=Free%20Tech%20Studio%20Hero%20Template%20with%20Lightning%20Animation&category=Landing%20Page&icon=%F0%9F%93%84" />

  <!-- Bootstrap (used by template โ€” replace with your own framework if you prefer) -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />

  <style>
* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
    --bg:     #ffffff;
    --bg-2:   #f6f6f6;
    --ink:    #1a1a1a;
    --ink-soft: rgba(26, 26, 26, 0.65);
    --line:   rgba(26, 26, 26, 0.12);
    --lime:   #c6ff3d;
    --lime-deep: #a8dd1f;
}

html, body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    background: var(--bg);
    color: var(--ink);
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.back-link {
    position: fixed;
    bottom: 0.75rem;
    left: 0.75rem;
    z-index: 1000;
    color: var(--ink);
    text-decoration: none;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    padding: 0.45rem 0.9rem;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 999px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
    opacity: 0.85;
    transition: opacity 0.3s, transform 0.3s;
}
.back-link:hover { opacity: 1; transform: translateY(-2px); }

/* =========================================================
   LOADER โ€” Lightning bolt + electric arcs
   ========================================================= */
.loader {
    position: fixed;
    inset: 0;
    z-index: 999;
    background: var(--bg);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2rem;
}

.loader__stage {
    position: relative;
    width: 220px;
    height: 220px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.loader__bolt {
    width: 100px;
    height: 140px;
    position: relative;
    z-index: 3;
    filter: drop-shadow(0 0 20px rgba(198, 255, 61, 0.5));
}
#bolt-outline { stroke-dasharray: 500; stroke-dashoffset: 500; }
#bolt-fill { opacity: 0; }

.loader__progress {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    z-index: 2;
}

.loader__arcs {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 1;
}
.loader__arcs span {
    position: absolute;
    background: var(--lime);
    height: 1.5px;
    border-radius: 2px;
    transform-origin: left center;
    box-shadow: 0 0 6px rgba(198, 255, 61, 0.8);
    will-change: transform, opacity;
}

.loader__meta {
    display: flex;
    gap: 1.25rem;
    align-items: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.75rem;
    letter-spacing: 0.3em;
    color: var(--ink-soft);
    text-transform: uppercase;
}
.loader__counter {
    color: var(--ink);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    min-width: 3ch;
}

/* =========================================================
   VOLT SECTION
   ========================================================= */
.volt {
    position: relative;
    width: 100%;
    min-height: 100vh;
    overflow: hidden;
    background: var(--bg);
    padding-bottom: 2rem;
}

/* ---------- Top nav ---------- */
.topnav {
    position: relative;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: 2rem;
    padding: 1.5rem 3rem;
}

.topnav__logo {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    text-decoration: none;
    color: var(--ink);
    font-weight: 900;
    font-size: 1.5rem;
    letter-spacing: -0.01em;
    will-change: transform;
}
.topnav__logo-mark {
    width: 18px;
    height: 26px;
    display: inline-flex;
    align-items: center;
}
.topnav__logo-mark svg { width: 100%; height: 100%; display: block; }
.topnav__logo-text { text-transform: uppercase; }

.topnav__nav {
    margin: 0 auto;
    display: flex;
    gap: 2rem;
    align-items: center;
}
.topnav__link {
    position: relative;
    color: var(--ink);
    text-decoration: none;
    font-weight: 500;
    font-size: 1rem;
    padding: 0.55rem 1.5rem;
    border-radius: 999px;
    will-change: transform;
    transition: background 0.3s, color 0.3s;
}
.topnav__link.is-active {
    background: var(--lime);
    font-weight: 700;
}
.topnav__link:not(.is-active):hover {
    background: rgba(26, 26, 26, 0.06);
}

.topnav__cta {
    background: var(--ink);
    color: #fff;
    text-decoration: none;
    padding: 1rem 2rem;
    border-radius: 999px;
    font-weight: 700;
    font-size: 0.85rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    position: relative;
    overflow: hidden;
    will-change: transform;
}
.topnav__cta span { position: relative; z-index: 2; }
.topnav__cta::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--lime);
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.5s cubic-bezier(0.65, 0, 0.35, 1);
    z-index: 1;
}
.topnav__cta:hover { color: var(--ink); }
.topnav__cta:hover::before { transform: scaleX(1); transform-origin: left; }

/* ---------- Hero ---------- */
.hero {
    position: relative;
    z-index: 10;
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    gap: 3rem;
    padding: 2rem 3rem 1.5rem;
    align-items: flex-start;
}

.hero__left {
    position: relative;
}

.hero__title {
    font-family: 'Inter', sans-serif;
    font-weight: 900;
    font-size: clamp(2.5rem, 6vw, 5.5rem);
    line-height: 1;
    letter-spacing: -0.03em;
    color: var(--ink);
    margin-bottom: 2.5rem;
    text-transform: uppercase;
}
.hero__line {
    display: block;
    overflow: hidden;
    padding-bottom: 0.05em;
}
.hero__line--2 {
    display: flex;
    align-items: center;
    gap: 0.3em;
    flex-wrap: wrap;
}
.hero__char {
    display: inline-block;
    will-change: transform, color;
    transition: color 0.3s ease;
}
.hero__char.is-space { width: 0.25em; }
.hero__star {
    display: inline-flex;
    width: 1em;
    height: 1em;
    flex-shrink: 0;
    will-change: transform;
}
.hero__star svg { width: 100%; height: 100%; }

.hero__form {
    display: flex;
    align-items: center;
    border: 1.5px solid var(--line);
    border-radius: 999px;
    padding: 0.35rem;
    max-width: 480px;
    background: var(--bg);
    transition: border-color 0.3s;
}
.hero__form:focus-within { border-color: var(--ink); }
.hero__input {
    flex: 1;
    border: none;
    background: transparent;
    padding: 0.75rem 1.25rem;
    font-size: 0.95rem;
    font-family: inherit;
    color: var(--ink);
    outline: none;
    min-width: 0;
}
.hero__input::placeholder { color: rgba(26, 26, 26, 0.4); }
.hero__form-btn {
    background: var(--bg-2);
    color: var(--ink);
    border: none;
    border-radius: 999px;
    padding: 0.75rem 1.5rem;
    font-size: 0.9rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.3s, color 0.3s;
}
.hero__form-btn:hover { background: var(--ink); color: var(--lime); }

.hero__right {
    padding-top: 1rem;
}

.hero__desc {
    font-size: 1rem;
    line-height: 1.5;
    color: var(--ink-soft);
    margin-bottom: 1.5rem;
    max-width: 360px;
}

.cta-pill {
    display: inline-block;
    background: var(--lime);
    color: var(--ink);
    text-decoration: none;
    padding: 1rem 2.25rem;
    border-radius: 999px;
    font-weight: 600;
    font-size: 1rem;
    will-change: transform;
    transition: box-shadow 0.3s;
    position: relative;
    overflow: hidden;
}
.cta-pill:hover { box-shadow: 0 10px 25px rgba(198, 255, 61, 0.5); }
.cta-pill span { position: relative; z-index: 2; }
.cta-pill::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(26, 26, 26, 0.08);
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.5s cubic-bezier(0.65, 0, 0.35, 1);
    z-index: 1;
}
.cta-pill:hover::before { transform: scaleX(1); transform-origin: left; }

/* ---------- Image block ---------- */
.image-wrap {
    position: relative;
    margin: 0 3rem;
    aspect-ratio: 16 / 7;
    will-change: transform;
}
.image-wrap__photo {
    position: absolute;
    inset: 0;
    border-radius: 40% 6px 6px 6px / 55% 6px 6px 6px;
    overflow: hidden;
    will-change: transform;
    z-index: 1;
}
.image-wrap__photo img {
    width: 100%; height: 100%;
    object-fit: cover;
    object-position: center 35%;
    user-select: none;
    transition: transform 0.8s ease;
}
.image-wrap__arrow {
    position: absolute;
    top: -45px;
    right: 80px;
    z-index: 15;
    width: 90px; height: 90px;
    background: var(--ink);
    color: #fff;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    box-shadow: 0 0 0 12px var(--bg);
    will-change: transform;
    transition: background 0.3s, color 0.3s;
}
.image-wrap__arrow:hover { background: var(--lime); color: var(--ink); }
.image-wrap__arrow svg { width: 28px; height: 28px; transition: transform 0.4s cubic-bezier(0.65, 0, 0.35, 1); }
.image-wrap__arrow:hover svg { transform: rotate(45deg); }

/* ---------- Slider side arrows (vertical middle) ---------- */
.slide-nav__arrow {
    width: 54px; height: 54px;
    border-radius: 50%;
    background: var(--bg);
    border: 1.5px solid var(--line);
    color: var(--ink);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    will-change: transform;
    transition: background 0.3s, color 0.3s, border-color 0.3s, box-shadow 0.3s;
}
.slide-nav__arrow svg { width: 20px; height: 20px; transition: transform 0.3s; }
.slide-nav__arrow:hover {
    background: var(--lime);
    color: var(--ink);
    border-color: var(--lime);
    box-shadow: 0 8px 20px rgba(198, 255, 61, 0.45);
}
.slide-nav__arrow--side {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 40;
}
.slide-nav__arrow--left  { left: 1.25rem; }
.slide-nav__arrow--right { right: 1.25rem; }
.slide-nav__arrow--left:hover svg  { transform: translateX(-3px); }
.slide-nav__arrow--right:hover svg { transform: translateX(3px); }

.slide-dots {
    position: absolute;
    bottom: 1rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 20;
    display: flex;
    gap: 0.4rem;
    align-items: center;
}
.slide-dots span {
    width: 8px; height: 8px;
    border-radius: 50%;
    background: rgba(26, 26, 26, 0.2);
    cursor: pointer;
    transition: background 0.3s, width 0.3s;
}
.slide-dots span.is-active {
    background: var(--ink);
    width: 30px;
    border-radius: 4px;
}

/* ---------- Initial states ---------- */
[data-magnetic], [data-link], [data-desc], [data-cta], [data-arrow], [data-form], [data-dots] {
    opacity: 0;
}

/* ---------- Responsive ---------- */
@media (max-width: 1100px) {
    .topnav { padding: 1.25rem 1.5rem; gap: 1rem; }
    .topnav__nav { gap: 0.5rem; }
    .topnav__link { padding: 0.5rem 1rem; font-size: 0.9rem; }
    .topnav__cta { padding: 0.75rem 1.25rem; font-size: 0.75rem; }
    .hero { grid-template-columns: 1fr; gap: 1.5rem; padding: 1.5rem 1.5rem 1rem; }
    .hero__right { padding-top: 0; }
    .image-wrap { margin: 0 1rem; aspect-ratio: 4 / 3; }
    .image-wrap__arrow { right: 1rem; top: -20px; width: 64px; height: 64px; }
    .image-wrap__arrow svg { width: 22px; height: 22px; }
}
@media (max-width: 760px) {
    .topnav__logo-text { font-size: 1.1rem; }
    .topnav__nav a { font-size: 0.75rem; padding: 0.4rem 0.75rem; }
    .topnav__cta { padding: 0.55rem 0.9rem; }
    .hero__title { font-size: clamp(2rem, 10vw, 3rem); }
    .hero__form { max-width: 100%; }
    .hero__desc { font-size: 0.9rem; }
    .cta-pill { padding: 0.75rem 1.75rem; font-size: 0.9rem; }
    .image-wrap { margin: 0; border-radius: 45% 0 0 0 / 60% 0 0 0; aspect-ratio: 4 / 3; }
    .image-wrap__arrow { width: 50px; height: 50px; top: -25px; box-shadow: 0 0 0 8px var(--bg); }
}
@media (max-width: 480px) {
    .topnav { flex-wrap: wrap; padding: 0.75rem 1rem; }
    .topnav__nav { order: 3; width: 100%; justify-content: center; margin: 0; }
    .topnav__cta { padding: 0.45rem 0.75rem; font-size: 0.7rem; }
    .image-wrap__arrow { width: 44px; height: 44px; }
}

  </style>
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Banner โ€” Volt</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@500;600&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="banner-volt.css">
</head>
<body>
    

    <!-- ========== LOADER โ€” Lightning bolt + electric arcs ========== -->
    <div class="loader" id="loader">
        <div class="loader__stage">
            <!-- Arcs (crackling electricity) -->
            <div class="loader__arcs" id="loader-arcs"></div>
            <!-- Lightning bolt SVG -->
            <svg class="loader__bolt" viewBox="0 0 120 160" aria-hidden="true">
                <path id="bolt-outline" d="M 65 10 L 25 90 L 55 90 L 35 150 L 95 60 L 70 60 L 90 10 Z"
                      fill="none" stroke="#c6ff3d" stroke-width="3" stroke-linejoin="round" stroke-linecap="round"/>
                <path id="bolt-fill" d="M 65 10 L 25 90 L 55 90 L 35 150 L 95 60 L 70 60 L 90 10 Z"
                      fill="#c6ff3d"/>
            </svg>
            <!-- Progress circle around bolt -->
            <svg class="loader__progress" viewBox="0 0 200 200" aria-hidden="true">
                <circle cx="100" cy="100" r="90" fill="none" stroke="rgba(0,0,0,0.08)" stroke-width="2"/>
                <circle id="loader-circle" cx="100" cy="100" r="90" fill="none" stroke="#c6ff3d" stroke-width="3"
                        stroke-dasharray="565" stroke-dashoffset="565"
                        transform="rotate(-90 100 100)" stroke-linecap="round"/>
            </svg>
        </div>
        <div class="loader__meta">
            <span class="loader__label" id="loader-label">CHARGING</span>
            <span class="loader__counter" id="loader-counter">0%</span>
        </div>
    </div>

    <section class="volt" id="volt">
        <!-- ========== TOP NAV ========== -->
        <header class="topnav">
            <a href="#" class="topnav__logo" data-magnetic>
                <span class="topnav__logo-mark" id="logo-mark">
                    <svg viewBox="0 0 24 32" aria-hidden="true">
                        <path d="M13 2 L 5 18 L 11 18 L 7 30 L 19 14 L 14 14 L 18 2 Z"
                              fill="#1a1a1a" stroke="#1a1a1a" stroke-linejoin="round"/>
                    </svg>
                </span>
                <span class="topnav__logo-text">Volt</span>
            </a>

            <nav class="topnav__nav">
                <a href="#" class="topnav__link is-active" data-magnetic data-link data-slide="0">Work</a>
                <a href="#" class="topnav__link" data-magnetic data-link data-slide="1">About</a>
                <a href="#" class="topnav__link" data-magnetic data-link data-slide="2">Service</a>
                <a href="#" class="topnav__link" data-magnetic data-link data-slide="3">Contact</a>
            </nav>

            <a href="#" class="topnav__cta" data-magnetic>
                <span>GET STARTED</span>
            </a>
        </header>

        <!-- ========== MAIN HERO ========== -->
        <div class="hero" id="hero">
            <div class="hero__left">
                <h1 class="hero__title" id="title">
                    <span class="hero__line" data-title-line id="title-line-1"></span>
                    <span class="hero__line hero__line--2" data-title-line id="title-line-2">
                        <span class="hero__star" id="title-star">
                            <svg viewBox="0 0 24 24" aria-hidden="true">
                                <circle cx="12" cy="12" r="12" fill="#1a1a1a"/>
                                <path d="M12 4 L 14 10 L 20 12 L 14 14 L 12 20 L 10 14 L 4 12 L 10 10 Z" fill="#c6ff3d"/>
                            </svg>
                        </span>
                        <span id="line2-text"></span>
                    </span>
                </h1>

                <form class="hero__form" data-form onsubmit="event.preventDefault()">
                    <input type="email" class="hero__input" id="email-input" placeholder="Enter your email address">
                    <button type="submit" class="hero__form-btn">Get Started</button>
                </form>
            </div>

            <div class="hero__right">
                <p class="hero__desc" id="desc" data-desc></p>
                <a href="#" class="cta-pill" data-magnetic data-cta id="cta-pill">
                    <span id="cta-label">Get Started</span>
                </a>
            </div>
        </div>

        <!-- ========== BIG IMAGE ========== -->
        <div class="image-wrap" id="image-wrap">
            <a href="#" class="image-wrap__arrow" data-magnetic data-arrow aria-label="View">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
                    <path d="M7 17 L 17 7 M 17 7 L 9 7 M 17 7 L 17 15" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
            </a>
            <div class="image-wrap__photo" id="photo">
                <img id="photo-img"
                     src="https://images.unsplash.com/photo-1558494949-ef010cbdcc31?auto=format&fit=crop&w=1600&q=80"
                     alt=""
                     draggable="false" onerror="this.style.display='none'">
            </div>
        </div>

        <!-- Side arrows (mid-screen) -->
        <button class="slide-nav__arrow slide-nav__arrow--side slide-nav__arrow--left" id="slide-prev" data-magnetic aria-label="Previous slide">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2">
                <path d="M15 6l-6 6 6 6" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
        </button>
        <button class="slide-nav__arrow slide-nav__arrow--side slide-nav__arrow--right" id="slide-next" data-magnetic aria-label="Next slide">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2">
                <path d="M9 6l6 6-6 6" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
        </button>

        <!-- Slide indicator dots -->
        <div class="slide-dots" data-dots>
            <span class="is-active" data-dot="0"></span>
            <span data-dot="1"></span>
            <span data-dot="2"></span>
            <span data-dot="3"></span>
        </div>
    </section>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
    <script src="banner-volt.js"></script>
</body>
</html>

</body>
</html>
JSbanner-volt.jsโ€” GSAP animation timeline
(() => {
    const root = document.getElementById('volt');
    if (!root) return;

    // -------------------------------------------------------------------
    //  SLIDES
    // -------------------------------------------------------------------
    const slides = [
        {
            line1: 'DIGITAL DREAMS',
            line2: 'REAL RESULTS',
            desc: 'Stay Informed, Stay Ahead: Unveiling the Future of Technology, Gadgets, and Innovation. Your Gateway to the Digital Universe where Innovation Meets Insight.',
            cta: 'Get Started',
            image: 'https://images.unsplash.com/photo-1558494949-ef010cbdcc31?auto=format&fit=crop&w=1600&q=80',
        },
        {
            line1: 'CREATIVE VISION',
            line2: 'BOLD EXECUTION',
            desc: 'From first sketch to final shipping brand: end-to-end identity, product, and campaign design that sparks conversation and converts intent into loyalty.',
            cta: 'Explore Studio',
            image: 'https://images.unsplash.com/photo-1517077304055-6e89abbf09b0?auto=format&fit=crop&w=1600&q=80',
        },
        {
            line1: 'SMART STRATEGY',
            line2: 'SCALABLE GROWTH',
            desc: 'Data-driven playbooks, weekly experiments, and market-fit insights that compound into month-over-month gains for hungry startups and mature teams alike.',
            cta: 'See Case Studies',
            image: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?auto=format&fit=crop&w=1600&q=80',
        },
        {
            line1: 'BUILT FOR TEAMS',
            line2: 'READY FOR MORE',
            desc: 'Collaboration tools, workflow automation, and shared dashboards designed so every function โ€” design, dev, ops, marketing โ€” moves in the same direction.',
            cta: 'Talk to Us',
            image: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?auto=format&fit=crop&w=1600&q=80',
        },
    ];
    let currentSlide = 0;

    // -------------------------------------------------------------------
    //  BUILD LOADER ELECTRIC ARCS
    // -------------------------------------------------------------------
    const arcsHost = document.getElementById('loader-arcs');
    const ARC_COUNT = 8;
    for (let i = 0; i < ARC_COUNT; i++) {
        const arc = document.createElement('span');
        const angle = (i / ARC_COUNT) * 360;
        arc.style.left = '50%';
        arc.style.top = '50%';
        arc.style.width = (30 + Math.random() * 40) + 'px';
        arc.style.transform = `rotate(${angle}deg) translate(60px, 0)`;
        arcsHost.appendChild(arc);
    }
    const arcEls = arcsHost.querySelectorAll('span');

    // -------------------------------------------------------------------
    //  REFERENCES
    // -------------------------------------------------------------------
    const loader = document.getElementById('loader');
    const loaderCounter = document.getElementById('loader-counter');
    const loaderLabel = document.getElementById('loader-label');
    const boltOutline = document.getElementById('bolt-outline');
    const boltFill = document.getElementById('bolt-fill');
    const loaderCircle = document.getElementById('loader-circle');

    const magnetics = root.querySelectorAll('[data-magnetic]');
    const descEl = document.getElementById('desc');
    const ctaPill = document.getElementById('cta-pill');
    const ctaLabel = document.getElementById('cta-label');
    const form = root.querySelector('[data-form]');
    const titleLine1 = document.getElementById('title-line-1');
    const titleLine2 = document.getElementById('title-line-2');
    const line2Text = document.getElementById('line2-text');
    const titleStar = document.getElementById('title-star');
    const photoImg = document.getElementById('photo-img');
    const imageWrap = document.getElementById('image-wrap');
    const photo = document.getElementById('photo');
    const arrowBtn = root.querySelector('[data-arrow]');
    const dots = root.querySelectorAll('.slide-dots span');
    const navLinks = root.querySelectorAll('[data-slide]');
    const logoMark = document.getElementById('logo-mark');

    // -------------------------------------------------------------------
    //  HELPERS
    // -------------------------------------------------------------------
    function makeChars(el, text) {
        el.innerHTML = '';
        [...text].forEach((ch) => {
            const span = document.createElement('span');
            span.className = 'hero__char';
            if (ch === ' ') { span.classList.add('is-space'); span.innerHTML = '&nbsp;'; }
            else span.textContent = ch;
            el.appendChild(span);
        });
        return el.querySelectorAll('.hero__char');
    }

    // -------------------------------------------------------------------
    //  INITIAL STATES
    // -------------------------------------------------------------------
    gsap.set(magnetics, { y: -15, opacity: 0 });
    gsap.set(descEl, { y: 20, opacity: 0 });
    gsap.set(ctaPill, { scale: 0.85, opacity: 0 });
    gsap.set(form, { y: 20, opacity: 0 });
    gsap.set(photo, { scale: 1.15, opacity: 0 });
    gsap.set(arrowBtn, { scale: 0, opacity: 0, rotation: -45 });
    gsap.set(titleStar, { scale: 0, rotation: -90 });
    gsap.set(document.querySelector('[data-dots]'), { y: 10, opacity: 0 });

    // -------------------------------------------------------------------
    //  LOADER TIMELINE
    // -------------------------------------------------------------------
    const loaderTl = gsap.timeline({ onComplete: playScene });

    // Bolt draws
    loaderTl.to(boltOutline, {
        strokeDashoffset: 0,
        duration: 1.2,
        ease: 'power2.inOut',
    }, 0);

    // Bolt fills
    loaderTl.to(boltFill, {
        opacity: 1,
        duration: 0.4,
        ease: 'power2.out',
    }, 1);

    // Progress circle fills
    loaderTl.to(loaderCircle, {
        strokeDashoffset: 0,
        duration: 2,
        ease: 'power1.inOut',
    }, 0.2);

    // Arcs crackle
    arcEls.forEach((arc, i) => {
        gsap.to(arc, {
            scaleX: () => Math.random() * 0.8 + 0.2,
            opacity: () => Math.random() * 0.8 + 0.2,
            duration: 0.1,
            repeat: -1,
            ease: 'none',
            delay: i * 0.05,
        });
    });

    // Counter
    const p = { v: 0 };
    loaderTl.to(p, {
        v: 100,
        duration: 2.2,
        ease: 'power1.inOut',
        onUpdate: () => {
            loaderCounter.textContent = Math.floor(p.v) + '%';
            if (p.v > 30 && loaderLabel.textContent === 'CHARGING') loaderLabel.textContent = 'POWERING UP';
            if (p.v > 70 && loaderLabel.textContent === 'POWERING UP') loaderLabel.textContent = 'FULL VOLTAGE';
            if (p.v > 96 && loaderLabel.textContent === 'FULL VOLTAGE') loaderLabel.textContent = 'READY';
        },
    }, 0);

    // Flash on completion
    loaderTl.to(boltFill, {
        opacity: 0.3,
        duration: 0.1,
        yoyo: true,
        repeat: 3,
        ease: 'sine.inOut',
    }, '+=0.2');

    // Exit
    loaderTl.to([loaderCounter, loaderLabel], {
        y: -10, opacity: 0, duration: 0.3, stagger: 0.05,
    }, '+=0.2');
    loaderTl.to('.loader__stage', {
        scale: 2, opacity: 0, duration: 0.6, ease: 'power3.in',
    }, '-=0.2');
    loaderTl.to(loader, {
        opacity: 0, duration: 0.4, ease: 'power2.inOut',
    }, '-=0.3');
    loaderTl.set(loader, { display: 'none' });

    // -------------------------------------------------------------------
    //  RENDER SLIDE
    // -------------------------------------------------------------------
    let line1Chars = [], line2Chars = [];

    function renderSlide(idx, direction = 1) {
        const slide = slides[idx];
        const outTl = gsap.timeline();

        outTl.to([...line1Chars, ...line2Chars, titleStar], {
            yPercent: -110,
            opacity: 0,
            duration: 0.35,
            stagger: 0.015,
            ease: 'power2.in',
        }, 0);
        outTl.to(descEl, { y: -15, opacity: 0, duration: 0.3, ease: 'power2.in' }, 0);
        outTl.to(ctaLabel, { y: -15, opacity: 0, duration: 0.25, ease: 'power2.in' }, 0);
        outTl.to(photo, {
            scale: 1.08, opacity: 0.3, duration: 0.4, ease: 'power2.in',
        }, 0);

        outTl.call(() => {
            // Rebuild title
            line1Chars = makeChars(titleLine1, slide.line1);
            line2Text.textContent = '';
            const line2CharsList = [...slide.line2].map((ch) => {
                const span = document.createElement('span');
                span.className = 'hero__char';
                if (ch === ' ') { span.classList.add('is-space'); span.innerHTML = '&nbsp;'; }
                else span.textContent = ch;
                line2Text.appendChild(span);
                return span;
            });
            line2Chars = line2CharsList;

            descEl.textContent = slide.desc;
            ctaLabel.textContent = slide.cta;
            photoImg.src = slide.image;

            // Update dots
            dots.forEach((d, i) => d.classList.toggle('is-active', i === idx));
            // Update nav active
            navLinks.forEach((l, i) => l.classList.toggle('is-active', i === idx));

            // Animate in
            gsap.set([...line1Chars, ...line2Chars], { yPercent: 110, opacity: 0 });
            gsap.set(titleStar, { scale: 0, rotation: -90 });
            gsap.set(descEl, { y: 15, opacity: 0 });
            gsap.set(ctaLabel, { y: 15, opacity: 0 });

            gsap.to(line1Chars, {
                yPercent: 0, opacity: 1,
                duration: 0.7,
                stagger: 0.018,
                ease: 'power3.out',
            });
            gsap.to(line2Chars, {
                yPercent: 0, opacity: 1,
                duration: 0.7,
                stagger: 0.018,
                delay: 0.15,
                ease: 'power3.out',
            });
            gsap.to(titleStar, {
                scale: 1, rotation: 0,
                duration: 0.6,
                delay: 0.3,
                ease: 'back.out(2)',
            });
            gsap.to(descEl, {
                y: 0, opacity: 1,
                duration: 0.6,
                delay: 0.25,
                ease: 'power3.out',
            });
            gsap.to(ctaLabel, {
                y: 0, opacity: 1,
                duration: 0.5,
                delay: 0.35,
                ease: 'power3.out',
            });
            gsap.to(photo, {
                scale: 1, opacity: 1,
                duration: 0.9,
                ease: 'power3.out',
            });

            attachTitleHover();
        });
    }

    function attachTitleHover() {
        [...line1Chars, ...line2Chars].forEach((c) => {
            c.addEventListener('mouseenter', () => gsap.to(c, { color: '#a8dd1f', duration: 0.2 }));
            c.addEventListener('mouseleave', () => gsap.to(c, { color: '#1a1a1a', duration: 0.4 }));
        });
    }

    // -------------------------------------------------------------------
    //  MAIN SCENE ENTRANCE
    // -------------------------------------------------------------------
    function playScene() {
        // Initial slide
        const slide = slides[0];
        line1Chars = makeChars(titleLine1, slide.line1);
        line2Chars = [...slide.line2].map((ch) => {
            const span = document.createElement('span');
            span.className = 'hero__char';
            if (ch === ' ') { span.classList.add('is-space'); span.innerHTML = '&nbsp;'; }
            else span.textContent = ch;
            line2Text.appendChild(span);
            return span;
        });
        descEl.textContent = slide.desc;
        ctaLabel.textContent = slide.cta;

        gsap.set([...line1Chars, ...line2Chars], { yPercent: 110, opacity: 0 });

        const tl = gsap.timeline({ defaults: { ease: 'power3.out' } });

        // Nav
        tl.to(magnetics, {
            y: 0, opacity: 1,
            duration: 0.6,
            stagger: 0.05,
        }, 0);

        // Title line 1
        tl.to(line1Chars, {
            yPercent: 0, opacity: 1,
            duration: 0.9,
            stagger: 0.025,
            ease: 'expo.out',
        }, 0.3);

        // Star
        tl.to(titleStar, {
            scale: 1, rotation: 0,
            duration: 0.6,
            ease: 'back.out(2)',
        }, 0.7);

        // Title line 2
        tl.to(line2Chars, {
            yPercent: 0, opacity: 1,
            duration: 0.9,
            stagger: 0.025,
            ease: 'expo.out',
        }, 0.75);

        // Form
        tl.to(form, { y: 0, opacity: 1, duration: 0.7 }, 1.2);

        // Desc + CTA
        tl.to(descEl, { y: 0, opacity: 1, duration: 0.7 }, 1);
        tl.to(ctaPill, {
            scale: 1, opacity: 1,
            duration: 0.7,
            ease: 'back.out(1.6)',
        }, 1.2);

        // Photo
        tl.to(photo, {
            scale: 1, opacity: 1,
            duration: 1.4,
            ease: 'power4.out',
        }, 0.8);

        // Arrow button
        tl.to(arrowBtn, {
            scale: 1, opacity: 1, rotation: 0,
            duration: 0.7,
            ease: 'back.out(1.8)',
        }, 1.4);

        // Dots
        tl.to(document.querySelector('[data-dots]'), {
            y: 0, opacity: 1, duration: 0.5,
        }, 1.6);

        tl.call(() => {
            attachTitleHover();
            enableInteractions();
        }, null, 1.7);
    }

    // -------------------------------------------------------------------
    //  INTERACTIONS
    // -------------------------------------------------------------------
    function enableInteractions() {

        // ---- Magnetic ----
        magnetics.forEach((el) => {
            const strength = el.classList.contains('topnav__cta') ? 0.3
                : el.classList.contains('cta-pill') ? 0.3
                : el.classList.contains('image-wrap__arrow') ? 0.4
                : el.classList.contains('topnav__logo') ? 0.2
                : 0.22;
            el.addEventListener('mousemove', (e) => {
                const r = el.getBoundingClientRect();
                const cx = r.left + r.width / 2;
                const cy = r.top + r.height / 2;
                gsap.to(el, {
                    x: (e.clientX - cx) * strength,
                    y: (e.clientY - cy) * strength,
                    duration: 0.4, ease: 'power3.out',
                });
            });
            el.addEventListener('mouseleave', () => {
                gsap.to(el, { x: 0, y: 0, duration: 0.6, ease: 'elastic.out(1, 0.4)' });
            });
        });

        // ---- Logo bolt flash ----
        const logoEl = root.querySelector('.topnav__logo');
        logoEl.addEventListener('mouseenter', () => {
            gsap.fromTo(logoMark,
                { scale: 1 },
                { scale: 1.3, duration: 0.15, yoyo: true, repeat: 1, ease: 'back.out(2)' }
            );
        });

        // ---- Nav links: click advances slide ----
        navLinks.forEach((link, i) => {
            link.addEventListener('click', (e) => {
                e.preventDefault();
                if (i === currentSlide) return;
                const direction = i > currentSlide ? 1 : -1;
                currentSlide = i;
                renderSlide(i, direction);
            });
        });

        // ---- Dots click ----
        dots.forEach((dot, i) => {
            dot.addEventListener('click', () => {
                if (i === currentSlide) return;
                const direction = i > currentSlide ? 1 : -1;
                currentSlide = i;
                renderSlide(i, direction);
            });
        });

        // ---- Slider prev/next arrows ----
        const slidePrev = document.getElementById('slide-prev');
        const slideNext = document.getElementById('slide-next');
        const goSlide = (dir) => {
            const next = (currentSlide + dir + slides.length) % slides.length;
            currentSlide = next;
            renderSlide(next, dir);
        };
        slidePrev.addEventListener('click', () => goSlide(-1));
        slideNext.addEventListener('click', () => goSlide(1));

        // ---- Keyboard ----
        window.addEventListener('keydown', (e) => {
            if (e.key === 'ArrowLeft') goSlide(-1);
            if (e.key === 'ArrowRight') goSlide(1);
        });

        // Auto advance every 8s
        let autoTimer = setInterval(() => {
            const next = (currentSlide + 1) % slides.length;
            currentSlide = next;
            renderSlide(next, 1);
        }, 8000);
        root.addEventListener('mouseenter', () => clearInterval(autoTimer));
        root.addEventListener('mouseleave', () => {
            clearInterval(autoTimer);
            autoTimer = setInterval(() => {
                const next = (currentSlide + 1) % slides.length;
                currentSlide = next;
                renderSlide(next, 1);
            }, 8000);
        });

        // ---- Arrow button click: spark burst ----
        arrowBtn.addEventListener('click', (e) => {
            e.preventDefault();
            gsap.fromTo(arrowBtn,
                { scale: 1 },
                { scale: 0.9, duration: 0.1, yoyo: true, repeat: 1, ease: 'back.out(2)' }
            );
            const rect = arrowBtn.getBoundingClientRect();
            const cx = rect.left + rect.width / 2;
            const cy = rect.top + rect.height / 2;
            for (let i = 0; i < 8; i++) {
                const s = document.createElement('span');
                s.style.cssText = `position:fixed;left:${cx}px;top:${cy}px;width:3px;height:20px;background:#c6ff3d;pointer-events:none;z-index:200;transform-origin:center;transform:translate(-50%,-50%) rotate(${i * 45}deg);box-shadow:0 0 8px #c6ff3d;`;
                document.body.appendChild(s);
                gsap.fromTo(s,
                    { scale: 0, opacity: 1 },
                    {
                        scale: 2.5, opacity: 0,
                        duration: 0.6,
                        ease: 'power2.out',
                        onComplete: () => s.remove(),
                    }
                );
            }
        });

        // ---- CTA pill click ----
        ctaPill.addEventListener('click', (e) => {
            e.preventDefault();
            gsap.fromTo(ctaPill,
                { scale: 1 },
                { scale: 0.95, duration: 0.1, yoyo: true, repeat: 1, ease: 'sine.inOut' }
            );
        });

        // ---- Photo parallax ----
        let mx = 0, my = 0, cmx = 0, cmy = 0;
        imageWrap.addEventListener('mousemove', (e) => {
            const r = imageWrap.getBoundingClientRect();
            mx = ((e.clientX - r.left) / r.width - 0.5) * 2;
            my = ((e.clientY - r.top) / r.height - 0.5) * 2;
        });
        imageWrap.addEventListener('mouseleave', () => { mx = 0; my = 0; });
        gsap.ticker.add(() => {
            cmx += (mx - cmx) * 0.05;
            cmy += (my - cmy) * 0.05;
            gsap.set(photoImg, {
                scale: 1.05,
                x: -cmx * 20,
                y: -cmy * 15,
            });
        });

        // ---- Star rotates on hover ----
        titleStar.addEventListener('mouseenter', () => {
            gsap.to(titleStar, { rotation: 180, duration: 0.7, ease: 'back.out(2)' });
        });
        titleStar.addEventListener('mouseleave', () => {
            gsap.to(titleStar, { rotation: 0, duration: 0.6, ease: 'elastic.out(1, 0.4)' });
        });

        // Continuous star idle rotation
        gsap.to(titleStar, {
            rotation: '+=360',
            duration: 20,
            repeat: -1,
            ease: 'none',
            transformOrigin: 'center',
        });
    }
})();

More GSAP landing pages