GSAP, 21 blocks
How to edit GSAP animations
Every animation lives in one script: public/assets/js/tandem.js. GSAP, ScrollTrigger and SplitText are installed from npm (package gsap) and loaded by src/components/CustomCode.astro. Nothing loads from a CDN, and there is no other animation engine in this template.
Each effect is a numbered block (G1 to G21). Elements are found by data-animate="..." attributes or other data- attributes. To switch an effect off on one element, remove its attribute in the markup (src/components/). To remove an effect everywhere, delete its block and its call in the RUN list at the bottom of the script.
Element map
- G1 Page ready (html (head script)): Shows the page once every start state is set. The head script reveals it after 3 seconds at most.
- G2 Navbar (data-nav): The full bar turns into a white floating island after 40px of scroll. Change navShrinkAt in the key variables.
- G3 Nav pill (data-nav-menu, data-nav-pill, data-spy): The white pill follows the hovered link and rests on the section in view. data-spy="#features" ties a link to a section id.
- G4 Nav dropdown (data-dd, data-dd-panel, data-dd-view): One panel morphs between the Product, Customers and Resources views. Each trigger has data-dd and its view has the matching data-dd-view.
- G5 Mobile menu (data-menu-toggle, data-mobile-menu): Opens the full-height menu below 992px. Groups (m_group) open one at a time. Escape closes it.
- G6 Accordions (data-acc): Pricing and help FAQs. One item open per group; the plus turns into a cross.
- G7 FAQ reader (data-faq, data-q, data-a): Home FAQ. A question with data-q="2" shows the answer with data-a="2".
- G8 Filter pills (data-filter-group, data-filter, data-cat): Pills show the items whose data-cat contains the pill value. "all" shows everything.
- G9 Results slider (data-slider, data-slider-prev, data-slider-next, data-slider-bar): Snapping card track with buttons, progress bar and mouse drag.
- G10 Pricing toggle (data-billing, data-period, data-price, data-billing-note): Switches Monthly and Annual. Each price has data-monthly and data-annual values.
- G11 Features (data-animate="features", data-feature-item, data-panel): A sticky stage inside a taller track. Scrolling swaps the four stories. Below 992px the stories become a swipeable row.
- G12 Hero intro (data-animate="hero-title", "hero-fade", "hero-card", data-depth): The headline rises word by word, then the cards cascade in and drift at their data-depth.
- G13 Logo marquee (data-animate="marquee"): The logo set is copied once and loops. Change marqueeSpeed in the key variables.
- G14 Manifesto (data-animate="manifesto"): The sentence reads itself as you scroll and the image pills pop in.
- G15 Entrances (data-animate="reveal", data-animate="stagger"): Blocks fade and lift as they enter; stagger animates the children one after another.
- G16 Art drift (data-animate="drift"): Background art settles from 1.2x as its card scrolls in.
- G17 CTA Petal (data-animate="bloom"): The frosted Petal mark in the CTA Section unfolds, then turns slowly. Change bloomSpin.
- G18 Footer field (data-animate="footer-bloom"): The one mark in the footer is copied into three rows, blooms in a wave and leans toward the cursor.
- G19 Numbers (data-count, data-animate="activity"): Numbers count up from 0; the activity heatmap fills in.
- G20 Hovers (classes (button, text-link, card...)): Parent hovers that plain CSS classes cannot style on the parent: button label roll, arrow swap, card image zoom.
- G21 Sharp images (img[srcset]): Gives each responsive image a sizes value at least as wide as it renders.
Key variables
- ease and easeUI: easing for entrances and for UI feedback.
- speed: global duration multiplier, 0.8 is faster and 1.2 is slower.
- navShrinkAt: pixels scrolled before the navbar shrinks.
- marqueeSpeed, bloomSpin: seconds per loop.
- bloomRadius: reach of the cursor over the footer field.
- countDuration: seconds for number count-ups.
Reduced motion
Visitors who ask their system for reduced motion get the final state of every effect, without movement. The page never waits on an animation.


