/**
 * Get icon functions from global eb_frontend.
 * Fall back to no-ops if the controls frontend bundle didn't load
 * (e.g. blocked by a firewall/optimizer) so the accordion still works.
 */
const ebFrontend = window.eb_frontend || {};
const EBRenderIconWithSVG = ebFrontend.EBRenderIconWithSVG || (() => "");
const loadSvgIcons = ebFrontend.loadSvgIcons || (() => {});
document.addEventListener("DOMContentLoaded", function (event) {

    let accordions = document.querySelectorAll(
        ".eb-accordion-container > .eb-accordion-inner",
    );

    // Return if there is no accoridion block
    if (!accordions) return;

    const root = document.documentElement;
    let tabletBreakpoint = getComputedStyle(root)
        .getPropertyValue("--eb-tablet-breakpoint")
        .trim();
    tabletBreakpoint = tabletBreakpoint
        ? parseInt(tabletBreakpoint, 10)
        : "1024";
    const windowWidth = window.innerWidth;

    for (let x = 0; x < accordions.length; x++) {
        let accordion = accordions[x].parentElement;

        let transitionDuration = Number(
            accordion.getAttribute("data-transition-duration"),
        );
        let accordionWrapper = accordion.children[0].children;

        let titleNodes = [];
        Array.from(accordionWrapper).forEach(function (item) {
            titleNodes.push(item.querySelector(".eb-accordion-title-wrapper"));
        });

        let accordionType = accordion.getAttribute("data-accordion-type");

        // remove horizontal accordion from tab
        if (accordionType === "horizontal" && windowWidth <= tabletBreakpoint) {
            accordion.classList.remove("eb-accordion-type-horizontal");
            accordionType = "accordion";
        }

        // Take action based on accordion type
        accordionType === "toggle"
            ? setToggleAction(titleNodes)
            : setAccordionAction(titleNodes);

        let hashTag = window.location.hash.substr(1);
        let hashTagExists = false;

        window.addEventListener("hashchange", () => {
            let hashTag = window.location.hash.substr(1);
            titleNodes.forEach(function (item) {
                let id = item.parentElement.getAttribute("id");
                if (id === hashTag) {
                    hashTagExists = true;
                    if (accordionType === "toggle") {
                        onToggleTabClick.call(item);
                    } else {
                        onAccordionTabClick.call(item);
                    }
                }
            });
        });

        titleNodes.forEach(function (item, index) {
            let uniqueId = Math.random().toString(36).substr(2, 7);
            item.setAttribute("id", "eb-accordion-header-" + uniqueId);
            item.setAttribute(
                "aria-controls",
                "eb-accordion-panel-" + uniqueId,
            );
            item.setAttribute("aria-expanded", false);
            item.setAttribute("role", "button");
            let contentWrapper = item.nextElementSibling;
            contentWrapper.setAttribute("id", "eb-accordion-panel-" + uniqueId);
            contentWrapper.setAttribute(
                "aria-labelledby",
                "eb-accordion-header-" + uniqueId,
            );
            contentWrapper.setAttribute("role", "region");
            item.addEventListener("keydown", function (event) {
                let key = event.which.toString();
                let ctrlModifier = event.ctrlKey && key.match(/33|34/);
                if (key.match(/38|40/) || ctrlModifier) {
                    let direction = key.match(/34|40/) ? 1 : -1;
                    let length = titleNodes.length;
                    let newIndex = (index + length + direction) % length;
                    titleNodes[newIndex].focus();
                    event.preventDefault();
                } else if (key.match(/35|36/)) {
                    switch (key) {
                        case "36":
                            titleNodes[0].focus();
                            break;
                        case "35":
                            titleNodes[titleNodes.length - 1].focus();
                            break;
                    }
                    event.preventDefault();
                }
            });
        });

        let contentNodes = [];
        Array.from(accordionWrapper).forEach(function (item) {
            contentNodes.push(
                item.querySelector(".eb-accordion-content-wrapper"),
            );
        });

        let hide = "eb-accordion-hidden";
        //  add a className after the domcontent has been loaded
        accordion.classList.add("eb_accdn_loaded");
        if (accordionType !== "horizontal") {
            for (let i = 0; i < contentNodes.length; i++) {
                contentNodes[i].style.height = "0px";
            }
        }

        // Get all data attributes
        let tabIcon = accordion.getAttribute("data-tab-icon") || "";
        let expandedIcon = accordion.getAttribute("data-expanded-icon") || "";

        // Note: Don't sanitize here - EBRenderIconWithSVG handles sanitization internally

        function changeIcon(clickedTab) {
            // Replace tab icon with expanded or vice versa
            let iconWrapper = clickedTab.querySelector(".eb-accordion-icon-wrapper");
            if (!iconWrapper) return;

            // Check current state by looking for expanded icon data attribute
            let isExpanded = iconWrapper.getAttribute('data-expanded') === 'true';

            // Determine which icon to show
            let iconToShow = isExpanded ? tabIcon : expandedIcon;

            // Use EBRenderIconWithSVG for all icon types (FontAwesome, Dashicons, SVG URLs, inline SVG)
            let iconHtml = EBRenderIconWithSVG(iconToShow, "eb-accordion-icon");
            iconWrapper.innerHTML = iconHtml;

            // Update state
            iconWrapper.setAttribute('data-expanded', isExpanded ? 'false' : 'true');

            // Load SVG icons after DOM insertion (for SVG URLs)
            setTimeout(() => {
                loadSvgIcons(iconWrapper);
            }, 10);
        }

        // without clicked on accordion
        for (let i = 0; i < accordionWrapper.length; i++) {
            // if (accordionType !== "horizontal") {
            let clickable = accordionWrapper[i].getAttribute("data-clickable");
            if (clickable == "true") {
                contentNodes[i].setAttribute("data-collapsed", "false");
                if (accordionType !== "horizontal") {
                    slideDown(contentNodes[i], transitionDuration);
                }
                changeIcon(
                    contentNodes[i].parentElement.querySelector(
                        ".eb-accordion-title-wrapper",
                    ),
                );
                if (accordionType === "image") {
                    const container = accordionWrapper[i].closest(
                        ".eb-accordion-container",
                    );
                    const imgElement = container?.querySelector(
                        ".eb-accordion-image-container img",
                    );
                    const clickedTab = accordionWrapper[i]?.querySelector(
                        ".eb-accordion-title-wrapper",
                    );

                    if (imgElement) {
                        const imageUrl =
                            clickedTab.getAttribute("data-image-url") || "";
                        const imageAlt =
                            clickedTab.getAttribute("data-image-alt") || "";

                        imgElement.classList.add("eb-image-fade-out");

                        setTimeout(() => {
                            imgElement.setAttribute("src", imageUrl);
                            imgElement.setAttribute("alt", imageAlt);

                            imgElement.classList.remove("eb-image-fade-out");
                        }, 500);
                    }
                }
                if (
                    accordionType === "horizontal" &&
                    tabletBreakpoint <= windowWidth
                ) {
                    const clickedTab = accordionWrapper[i]?.querySelector(
                        ".eb-accordion-title-wrapper",
                    );

                    const titleContent = clickedTab.querySelector(
                        ".eb-accordion-title-content-wrap",
                    );
                    const contentWrapper = contentNodes[i].querySelector(
                        ".eb-accordion-content",
                    );
                    setTimeout(() => {
                        contentNodes[i].style.display = "block";
                        contentNodes[i].style.opacity = 1;
                        contentNodes[i].style.visibility = 'visible';
                        contentNodes[i].style.transform = 'translateY(0)';
                    }, transitionDuration);

                    if (titleContent && contentWrapper) {
                        const existingTitleContent =
                            contentWrapper.querySelector(
                                ".eb-accordion-title-content-wrap",
                            );
                        if (existingTitleContent) {
                            existingTitleContent.remove();
                        }
                        const titleContentCopy = titleContent.cloneNode(true);

                        contentWrapper.prepend(titleContentCopy);
                    }

                    // collapseOtherAccordions(clickedTab, transitionDuration);
                    // contentNodes[i].parentElement.classList.remove(hide);
                    clickedTab.style.display = "none";
                    expandHorizontalAccordionContent(
                        clickedTab,
                        contentNodes[i],
                    );
                }
            } else {
                contentNodes[i].setAttribute("data-collapsed", "true");
                if (accordionType !== "horizontal") {
                    slideUp(contentNodes[i], transitionDuration);
                }
                contentNodes[i].parentElement.classList.add(hide);
            }
            // }
        }

        function changeAllExpandIcons(accordion) {
            let iconWrappers = accordion.querySelectorAll(".eb-accordion-icon-wrapper");
            // Replace expand icon with tab icon for all accordions
            for (let i = 0; i < iconWrappers.length; i++) {
                let iconWrapper = iconWrappers[i];
                if (iconWrapper.getAttribute('data-expanded') === 'true') {
                    // Use EBRenderIconWithSVG for all icon types
                    let iconHtml = EBRenderIconWithSVG(tabIcon, "eb-accordion-icon");
                    iconWrapper.innerHTML = iconHtml;
                    iconWrapper.setAttribute('data-expanded', 'false');

                    // Load SVG icons after DOM insertion (for SVG URLs)
                    setTimeout(() => {
                        loadSvgIcons(iconWrapper);
                    }, 10);
                }
            }
        }

        // Toggle action here
        function setToggleAction(titleNodes) {
            for (let i = 0; i < titleNodes.length; i++) {
                let selectedTab = titleNodes[i];

                if (hashTag && !hashTagExists) {
                    let id = selectedTab.parentElement.getAttribute("id");
                    if (id === hashTag) {
                        hashTagExists = true;
                        onToggleTabClick.call(selectedTab);
                    }
                }

                (function (selectedTab) {
                    selectedTab.addEventListener("click", onToggleTabClick);
                    selectedTab.addEventListener("keydown", function (event) {
                        if (event.key === " " || event.key === "Enter") {
                            event.preventDefault();
                            onToggleTabClick.call(selectedTab);
                        }
                    });
                })(selectedTab);
            }
        }

        function onToggleTabClick() {
            let clickedTab = this;
            let contentNode = this.nextElementSibling;
            let isCollapsed =
                contentNode.getAttribute("data-collapsed") === "true";

            if (isCollapsed) {
                slideDown(contentNode, transitionDuration);
                contentNode.setAttribute("data-collapsed", "false");
                clickedTab.setAttribute("aria-expanded", "true");
                clickedTab.parentElement.classList.remove(hide);
            } else {
                slideUp(contentNode, transitionDuration);
                contentNode.setAttribute("data-collapsed", "true");
                clickedTab.setAttribute("aria-expanded", "false");
                clickedTab.parentElement.classList.add(hide);
            }
            // Change tab icon
            changeIcon(clickedTab);
        }

        // Accordion action here
        function setAccordionAction(titleNodes) {
            for (let i = 0; i < titleNodes.length; i++) {
                let selectedTab = titleNodes[i];
                if (hashTag && !hashTagExists) {
                    let id = selectedTab.parentElement.getAttribute("id");
                    if (id === hashTag) {
                        hashTagExists = true;
                        onAccordionTabClick.call(selectedTab);
                    }
                }

                (function (selectedTab) {
                    selectedTab.addEventListener("click", onAccordionTabClick);
                    selectedTab.addEventListener("keydown", function (event) {
                        if (event.key === " " || event.key === "Enter") {
                            event.preventDefault();
                            onAccordionTabClick.call(selectedTab);
                        }
                    });
                })(selectedTab);
            }
        }

        function onAccordionTabClick() {
            let clickedTab = this;
            let contentNode = clickedTab.nextElementSibling;
            changeAllExpandIcons(accordion);
            if (accordionType !== "horizontal") {
                // Find the accordion directly above the clicked one (if it exists)
                let previousAccordion = findOpenAccordionAbove(clickedTab);

                if (previousAccordion) {
                    let previousContentNode = previousAccordion.querySelector(
                        ".eb-accordion-content-wrapper",
                    );
                    let previousHeight = previousContentNode.offsetHeight;
                    let windowHeight = window.innerHeight;

                    if (previousHeight > windowHeight) {
                        // Collapse the accordion above if its height is greater than the window height
                        slideUp(previousContentNode, 0);
                        previousContentNode.setAttribute(
                            "data-collapsed",
                            "true",
                        );

                        // Scroll to the top only if the previous accordion is collapsed
                        scrollToPageTop(() => {
                            collapseOtherAccordions(clickedTab, 0);
                            expandAccordionContent(
                                clickedTab,
                                contentNode,
                                true,
                            );
                        });
                    } else {
                        collapseOtherAccordions(clickedTab, transitionDuration);
                        expandAccordionContent(clickedTab, contentNode);
                    }
                } else {
                    collapseOtherAccordions(clickedTab);
                    expandAccordionContent(
                        clickedTab,
                        contentNode,
                        false,
                        true,
                    );
                }
            }
            // storyboard accordion
            if (accordionType === "image") {
                const container = clickedTab.closest(".eb-accordion-container");
                const imgElement = container?.querySelector(
                    ".eb-accordion-image-container img",
                );

                if (imgElement) {
                    const imageUrl =
                        clickedTab.getAttribute("data-image-url") || "";
                    const imageAlt =
                        clickedTab.getAttribute("data-image-alt") || "";

                    imgElement.classList.add("eb-image-fade-out");

                    setTimeout(() => {
                        imgElement.setAttribute("src", imageUrl);
                        imgElement.setAttribute("alt", imageAlt);

                        imgElement.classList.remove("eb-image-fade-out");
                    }, 500);
                }
            }
            // horizontal accordion
            if (
                accordionType === "horizontal" &&
                windowWidth > tabletBreakpoint
            ) {
                clickedTab.classList.add("eb-transition-add");
                setTimeout(() => {
                    clickedTab.style.display = "none";
                    clickedTab.classList.remove("eb-transition-add");
                }, transitionDuration)
                collapseOtherAccordions(clickedTab, transitionDuration);
                setTimeout(() => {
                    contentNode.style.display = 'block';
                    contentNode.style.opacity = 1;
                    contentNode.style.visibility = 'visible';
                    contentNode.style.transform = 'translateY(0)';
                }, transitionDuration);

                const titleContent = clickedTab.querySelector(
                    ".eb-accordion-title-content-wrap",
                );
                const contentWrapper = contentNode.querySelector(
                    ".eb-accordion-content",
                );
                if (titleContent && contentWrapper) {
                    const existingTitleContent = contentWrapper.querySelector(
                        ".eb-accordion-title-content-wrap",
                    );
                    if (existingTitleContent) {
                        existingTitleContent.remove();
                    }
                    const titleContentCopy = titleContent.cloneNode(true);

                    contentWrapper.prepend(titleContentCopy);
                }

                expandHorizontalAccordionContent(clickedTab, contentNode);
            }
        }

        function expandAccordionContent(
            clickedTab,
            contentNode,
            toTheTop = false,
            checkCondition = false,
        ) {
            let isCollapsed =
                contentNode.getAttribute("data-collapsed") === "true";
            if (isCollapsed) {
                if (toTheTop) {
                    slideDown(contentNode, transitionDuration, function () {
                        scrollToAccordionTitle(clickedTab);
                    });
                } else if (checkCondition) {
                    slideDown(contentNode, transitionDuration, function () {
                        let contentHeight = contentNode.offsetHeight;
                        let windowHeight = window.innerHeight;
                        if (contentHeight > windowHeight) {
                            scrollToAccordionTitle(clickedTab);
                        }
                    });
                } else {
                    slideDown(contentNode, transitionDuration);
                }

                contentNode.setAttribute("data-collapsed", "false");
                clickedTab.setAttribute("aria-expanded", "true");
                clickedTab.parentElement.classList.remove(
                    "eb-accordion-hidden",
                );
            } else {
                // If it's already open, no need to scroll or change anything
                slideUp(contentNode, transitionDuration);
                contentNode.setAttribute("data-collapsed", "true");
                clickedTab.setAttribute("aria-expanded", "false");
                changeIcon(clickedTab);
                clickedTab.parentElement.classList.add("eb-accordion-hidden");
            }
            // Change tab icon (optional)
            changeIcon(clickedTab);
        }

        // Collapse all other accordions except the clicked one
        function collapseOtherAccordions(clickedTab, transitionDuration) {
            let allAccordions = clickedTab
                .closest(".eb-accordion-container")
                .querySelectorAll(".eb-accordion-content-wrapper");
            if (
                accordionType === "horizontal" &&
                tabletBreakpoint <= windowWidth
            ) {
                let allAccordionsTitle = clickedTab
                    .closest(".eb-accordion-inner")
                    .querySelectorAll(".eb-accordion-title-wrapper");
                let allAccordionsContent = clickedTab
                    .closest(".eb-accordion-inner")
                    .querySelectorAll(".eb-accordion-content-wrapper");
                allAccordionsTitle.forEach((title) => {
                    if (title !== clickedTab) {
                        title.style.display = "flex";
                    }
                });
                allAccordionsContent.forEach((item) => {
                    item.style.display = "none";
                    item.style.opacity = 0;
                    item.style.visibility = 'hidden';
                    item.style.transform = 'translateY(-100%)';
                });
            }

            allAccordions.forEach((accordion) => {
                if (
                    accordion !== clickedTab.nextElementSibling &&
                    accordion.getAttribute("data-collapsed") === "false"
                ) {
                    if (accordionType !== "horizontal") {
                        slideUp(accordion, transitionDuration);
                    }

                    accordion.setAttribute("data-collapsed", "true");
                    accordion.previousElementSibling.setAttribute(
                        "aria-expanded",
                        "false",
                    );
                    accordion.parentElement.classList.add(
                        "eb-accordion-hidden",
                    );
                }
            });
            // changeIcon(clickedTab);
        }

        function expandHorizontalAccordionContent(clickedTab, contentNode) {
            let isCollapsed =
                contentNode.getAttribute("data-collapsed") === "true";
            let accordionWrapper = clickedTab
                .closest(".eb-accordion-inner")
                .querySelectorAll(".eb-accordion-wrapper");
            let currentAccordionWrapper = clickedTab.closest(
                ".eb-accordion-wrapper",
            );
            if (isCollapsed) {
                contentNode.setAttribute("data-collapsed", "false");
                clickedTab.setAttribute("aria-expanded", "true");
                clickedTab.parentElement.classList.remove(
                    "eb-accordion-hidden",
                );
            } else {
                contentNode.setAttribute("data-collapsed", "true");
                clickedTab.setAttribute("aria-expanded", "false");
                changeIcon(clickedTab);
                clickedTab.parentElement.classList.add("eb-accordion-hidden");
            }
            const expanded =
                currentAccordionWrapper.getAttribute("aria-expanded") ===
                "true";
            accordionWrapper.forEach((i) => {
                i.setAttribute("aria-expanded", "false");
            });

            currentAccordionWrapper.setAttribute(
                "aria-expanded",
                expanded ? "false" : "true",
            );

            // Change tab icon (optional)
            changeIcon(clickedTab);
        }

        // Load SVG icons after accordion initialization
        setTimeout(() => {
            loadSvgIcons(accordion);
        }, 100);
    }
});

const hideAccordionContents = (accordion, transitionDuration) => {
    let contentNodes = [];
    Array.from(accordion.children).forEach(function (item) {
        contentNodes = item.querySelectorAll(".eb-accordion-content-wrapper");
    });

    for (let i = 0; i < contentNodes.length; i++) {
        if (contentNodes[i].getAttribute("data-collapsed") === "false") {
            slideUp(contentNodes[i], transitionDuration);
            contentNodes[i].setAttribute("data-collapsed", true);
            contentNodes[i].setAttribute("aria-expanded", "false");
        }
    }
};

/* SLIDE UP */
const slideUp = (target, duration = 500) => {
    target.style.transitionProperty = "height, margin, padding";
    target.style.transitionDuration = duration + "ms";
    target.style.boxSizing = "border-box";
    target.style.height = target.offsetHeight + "px";
    target.offsetHeight;
    target.style.overflow = "hidden";
    target.style.height = 0;
    target.style.paddingTop = 0;
    target.style.paddingBottom = 0;
    target.style.marginTop = 0;
    target.style.marginBottom = 0;
    if (duration <= 0) {
        target.style.display = "none";
        target.style.removeProperty("height");
        target.style.removeProperty("padding-top");
        target.style.removeProperty("padding-bottom");
        target.style.removeProperty("margin-top");
        target.style.removeProperty("margin-bottom");
        target.style.removeProperty("overflow");
        target.style.removeProperty("transition-duration");
        target.style.removeProperty("transition-property");
    } else {
        window.setTimeout(() => {
            target.style.display = "none";
            target.style.removeProperty("height");
            target.style.removeProperty("padding-top");
            target.style.removeProperty("padding-bottom");
            target.style.removeProperty("margin-top");
            target.style.removeProperty("margin-bottom");
            target.style.removeProperty("overflow");
            target.style.removeProperty("transition-duration");
            target.style.removeProperty("transition-property");
            //alert("!");
        }, duration);
    }
};

/* SLIDE DOWN */
const slideDown = (target, duration = 500, callback = null) => {
    target.style.removeProperty("display");
    let display = window.getComputedStyle(target).display;
    if (display === "none") display = "block";
    setTimeout(function () {
        target.style.display = display;
    }, duration + 1);
    let height = getHiddenElementHeight(target);
    target.style.overflow = "hidden";
    target.style.height = 0;
    target.style.paddingTop = 0;
    target.style.paddingBottom = 0;
    target.style.marginTop = 0;
    target.style.marginBottom = 0;
    target.offsetHeight;
    target.style.boxSizing = "border-box";
    target.style.transitionProperty = "height, margin, padding";
    target.style.transitionDuration = duration + "ms";
    target.style.height = height + "px";
    target.style.removeProperty("padding-top");
    target.style.removeProperty("padding-bottom");
    target.style.removeProperty("margin-top");
    target.style.removeProperty("margin-bottom");
    window.setTimeout(() => {
        target.style.removeProperty("height");
        target.style.removeProperty("overflow");
        target.style.removeProperty("transition-duration");
        target.style.removeProperty("transition-property");
        // Ensure callback after expansion completes
        if (typeof callback === "function") {
            callback();
        }
    }, duration);
};

/* TOOGLE */
const slideToggle = (target, duration = 500) => {
    if (window.getComputedStyle(target).display === "none") {
        return slideDown(target, duration);
    } else {
        return slideUp(target, duration);
    }
};

function getHiddenElementHeight(el) {
  // Save original styles
  const originalDisplay = el.style.display;
  const originalVisibility = el.style.visibility;
  const originalPosition = el.style.position;

  // Apply temporary styles
  el.style.display = 'block';
  el.style.visibility = 'hidden';
  el.style.position = 'absolute';

  const height = el.offsetHeight;

  // Revert original styles
  el.style.display = originalDisplay;
  el.style.visibility = originalVisibility;
  el.style.position = originalPosition;

  return height;
}

// Helper function to get the accordion directly above the clicked one
function findOpenAccordionAbove(clickedTab) {
    let previousSiblings = [];
    let sibling = clickedTab.parentElement.previousElementSibling;

    while (sibling) {
        if (sibling.querySelector(".eb-accordion-title-wrapper")) {
            let contentNode = sibling.querySelector(
                ".eb-accordion-content-wrapper",
            );
            if (contentNode.getAttribute("data-collapsed") === "false") {
                previousSiblings.push(sibling);
            }
        }
        sibling = sibling.previousElementSibling;
    }

    return previousSiblings.length ? previousSiblings[0] : null;
}

// Only scroll the accordion title to the top if content height is greater than window height
function scrollToAccordionTitle(accordionTitle, duration = 500) {
    const startPosition = window.pageYOffset;
    const targetPosition =
        accordionTitle.getBoundingClientRect().top + window.pageYOffset;
    const offset = 10; // Adjust if you want some padding at the top
    const distance = targetPosition - startPosition - offset;

    let startTime = null;

    function animation(currentTime) {
        if (startTime === null) startTime = currentTime;
        const timeElapsed = currentTime - startTime;
        const run = ease(timeElapsed, startPosition, distance, duration);
        window.scrollTo(0, run);
        if (timeElapsed < duration) requestAnimationFrame(animation);
    }

    // Ease function for smooth scrolling
    function ease(t, b, c, d) {
        t /= d / 2;
        if (t < 1) return (c / 2) * t * t + b;
        t--;
        return (-c / 2) * (t * (t - 2) - 1) + b;
    }

    requestAnimationFrame(animation);
}

function scrollToPageTop(callback, duration = 10) {
    const startPosition = window.pageYOffset;
    const distance = -startPosition; // Scroll to top
    let startTime = null;

    function animation(currentTime) {
        if (startTime === null) startTime = currentTime;
        const timeElapsed = currentTime - startTime;
        const run = ease(timeElapsed, startPosition, distance, duration);
        window.scrollTo(0, run);
        if (timeElapsed < duration) {
            requestAnimationFrame(animation);
        } else if (typeof callback === "function") {
            callback();
        }
    }

    // Ease function for smooth scrolling
    function ease(t, b, c, d) {
        t /= d / 2;
        if (t < 1) return (c / 2) * t * t + b;
        t--;
        return (-c / 2) * (t * (t - 2) - 1) + b;
    }

    requestAnimationFrame(animation);
}
