{"id":1851,"date":"2026-08-21T09:25:07","date_gmt":"2026-08-21T09:25:07","guid":{"rendered":"https:\/\/crypto-grandpa.com.ua\/?page_id=1851"},"modified":"2026-09-12T16:19:45","modified_gmt":"2026-09-12T16:19:45","slug":"support-our-software","status":"publish","type":"page","link":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/support-our-software\/","title":{"rendered":"Support-Our-Software"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1851\" class=\"elementor elementor-1851\">\n\t\t\t\t<div class=\"elementor-element elementor-element-52b0744 e-con-full cg-main-hero e-flex e-con e-parent\" data-id=\"52b0744\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-f0ef843 e-con-full e-flex e-con e-child\" data-id=\"f0ef843\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2a322261 elementor-widget elementor-widget-heading\" data-id=\"2a322261\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h6 class=\"elementor-heading-title elementor-size-default\">BUILDING DIGITAL TOOLS FOR EDUCATION<\/h6>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-699daa7b elementor-widget elementor-widget-heading\" data-id=\"699daa7b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">SUPPORT OUR SOFTWARE<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2a723147 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"2a723147\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Help us develop practical educational software, digital tools and technologies that turn knowledge and experience into real opportunities.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-1ae5fa5e e-flex e-con-boxed e-con e-parent\" data-id=\"1ae5fa5e\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-565dfba1 e-flex e-con-boxed e-con e-child\" data-id=\"565dfba1\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-273d64a9 e-con-full e-flex e-con e-child\" data-id=\"273d64a9\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1f6302a6 elementor-widget elementor-widget-html\" data-id=\"1f6302a6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"cg-currency-token cg-currency-token-left\">\n    <img decoding=\"async\"\n        id=\"cg-token-left\"\n        src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_uah.png\"\n        alt=\"UAH token\"\n    >\n<\/div>\n\n<style>\n.cg-currency-token-left {\n    width: 100%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n\n.cg-currency-token-left img {\n    display: block;\n    width: 190px;\n    height: 190px;\n    object-fit: contain;\n\n    animation:\n        cgTokenRotateLeft\n        12s\n        linear\n        infinite;\n\n    filter:\n        drop-shadow(\n            0 10px 18px\n            rgba(0, 0, 0, 0.38)\n        );\n}\n\n@keyframes cgTokenRotateLeft {\n    from {\n        transform: rotate(0deg);\n    }\n\n    to {\n        transform: rotate(360deg);\n    }\n}\n<\/style>\n\n<script>\n(function () {\n\n    const tokenUrls = {\n        UAH: 'https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_uah.png',\n        USD: 'https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_usd-e1788944391571.png',\n        EUR: 'https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_eur.png'\n    };\n\n    function connectToken() {\n\n        const currency =\n            document.getElementById(\n                'cg-liqpay-currency'\n            );\n\n        const token =\n            document.getElementById(\n                'cg-token-left'\n            );\n\n        if (!currency || !token) {\n            return false;\n        }\n\n        function updateToken() {\n\n            const value =\n                currency.value;\n\n            if (tokenUrls[value]) {\n\n                token.src =\n                    tokenUrls[value];\n\n                token.alt =\n                    value + ' token';\n            }\n        }\n\n        currency.addEventListener(\n            'change',\n            updateToken\n        );\n\n        updateToken();\n\n        return true;\n    }\n\n    let attempts = 0;\n\n    const timer = setInterval(\n        function () {\n\n            attempts++;\n\n            if (\n                connectToken() ||\n                attempts > 30\n            ) {\n                clearInterval(timer);\n            }\n\n        },\n        200\n    );\n\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7951b839 e-con-full e-flex e-con e-child\" data-id=\"7951b839\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b46c613 elementor-widget__width-initial elementor-widget elementor-widget-shortcode\" data-id=\"b46c613\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">\n    <form\n        method=\"post\"\n        action=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-admin\/admin-post.php\"\n        class=\"cg-liqpay-soft-donate-checkout-form\"\n    >\n\n        <div\n            id=\"cg-liqpay-soft-meaning-side\"\n            class=\"cg-liqpay-soft-side-panel cg-liqpay-soft-side-meaning is-hidden\"\n            aria-live=\"polite\"\n        >\n            <div\n                id=\"cg-liqpay-soft-meaning-side-title\"\n                class=\"cg-liqpay-soft-side-title\"\n            >\n            <\/div>\n\n            <img decoding=\"async\"\n                id=\"cg-liqpay-soft-meaning-side-token-img\"\n                class=\"cg-liqpay-soft-side-token cg-liqpay-soft-side-token-meaning\"\n                src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/01_documentation_guides.png\"\n                alt=\"\"\n                aria-hidden=\"true\"\n            >\n\n            <div\n                id=\"cg-liqpay-soft-donor-preference-side\"\n                class=\"cg-liqpay-soft-donor-preference-side is-hidden\"\n                aria-live=\"polite\"\n            >\n                <div\n                    id=\"cg-liqpay-soft-donor-preference-side-title\"\n                    class=\"cg-liqpay-soft-donor-preference-side-title\"\n                >\n                    DONOR'S PREFERENCE\n                <\/div>\n\n                <img decoding=\"async\"\n                    id=\"cg-liqpay-soft-donor-preference-side-token-img\"\n                    class=\"cg-liqpay-soft-side-token cg-liqpay-soft-side-token-donor-preference\"\n                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_message_hands_gear.png\"\n                    alt=\"\"\n                    aria-hidden=\"true\"\n                >\n            <\/div>\n        <\/div>\n\n        <div\n            id=\"cg-liqpay-soft-currency-side\"\n            class=\"cg-liqpay-soft-side-panel cg-liqpay-soft-side-currency\"\n            aria-live=\"polite\"\n        >\n            <div class=\"cg-liqpay-soft-currency-side-heading\">\n                HOW YOUR DONATION HELPS\n            <\/div>\n\n            <div\n                id=\"cg-liqpay-soft-currency-side-amount\"\n                class=\"cg-liqpay-soft-currency-side-amount\"\n            >\n                0 UAH\n            <\/div>\n\n            <img decoding=\"async\"\n                id=\"cg-liqpay-soft-currency-side-token-img\"\n                class=\"cg-liqpay-soft-side-token cg-liqpay-soft-side-token-currency\"\n                src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_uah.png\"\n                alt=\"UAH\"\n            >\n        <\/div>\n\n        <input\n            type=\"hidden\"\n            name=\"action\"\n            value=\"cg_liqpay_soft_donate_checkout_start\"\n        >\n\n        <input type=\"hidden\" id=\"cg_liqpay_soft_donate_checkout_nonce\" name=\"cg_liqpay_soft_donate_checkout_nonce\" value=\"ad593038f7\" \/><input type=\"hidden\" name=\"_wp_http_referer\" value=\"\/ua\/wp-json\/wp\/v2\/pages\/1851\" \/>\n        <div class=\"cg-liqpay-soft-intro\">\n\n            <div class=\"cg-liqpay-soft-top-row\">\n\n                <div class=\"cg-liqpay-soft-heading-stack\">\n\n                    <div class=\"cg-liqpay-soft-kicker\">\n                        SUPPORT THE FOUNDATION\n                    <\/div>\n\n                    <h2 class=\"cg-liqpay-soft-title\">\n                        SUPPORT OUR SOFTWARE\n                    <\/h2>\n\n                    <div class=\"cg-liqpay-soft-navigator-title\">\n                        SOFTWARE SUPPORT NAVIGATOR\n                    <\/div>\n\n                <\/div>\n\n                        <div class=\"cg-liqpay-soft-payment-zone\">\n\n                            <div class=\"cg-liqpay-soft-donate-with\">\n                                DONATE WITH\n                            <\/div>\n\n                            <button\n                                type=\"submit\"\n                                class=\"cg-liqpay-soft-brand-button\"\n                                aria-label=\"Donate securely with LiqPay\"\n                            >\n                                <img decoding=\"async\"\n                                    class=\"cg-liqpay-soft-brand-logo\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/logo_liqpay_for_black@2x.png\"\n                                    alt=\"LiqPay\"\n                                >\n                            <\/button>\n\n                            <div class=\"cg-liqpay-soft-secure-note\">\n                                <span\n                                    class=\"cg-liqpay-soft-lock\"\n                                    aria-hidden=\"true\"\n                                >\ud83d\udd12<\/span>\n                                <span>\n                                    Secure payment via LiqPay\n                                <\/span>\n                            <\/div>\n\n                        <\/div>\n            <\/div>\n\n            <div\n                id=\"cg-liqpay-soft-navigator\"\n                class=\"cg-liqpay-soft-navigator\"\n            >\n                <div\n                    id=\"cg-liqpay-soft-nav-track\"\n                    class=\"cg-liqpay-soft-nav-track\"\n                    aria-label=\"Donation impact navigator\"\n                >\n                    <div class=\"cg-liqpay-soft-nav-line\"><\/div>\n\n                    <div class=\"cg-liqpay-soft-nav-hearts\">\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"0\"\n                                style=\"left: 0%;\"\n                                aria-label=\"Donation level 1\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"1\"\n                                style=\"left: 9.0909090909091%;\"\n                                aria-label=\"Donation level 2\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"2\"\n                                style=\"left: 18.181818181818%;\"\n                                aria-label=\"Donation level 3\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"3\"\n                                style=\"left: 27.272727272727%;\"\n                                aria-label=\"Donation level 4\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"4\"\n                                style=\"left: 36.363636363636%;\"\n                                aria-label=\"Donation level 5\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"5\"\n                                style=\"left: 45.454545454545%;\"\n                                aria-label=\"Donation level 6\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"6\"\n                                style=\"left: 54.545454545455%;\"\n                                aria-label=\"Donation level 7\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"7\"\n                                style=\"left: 63.636363636364%;\"\n                                aria-label=\"Donation level 8\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"8\"\n                                style=\"left: 72.727272727273%;\"\n                                aria-label=\"Donation level 9\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"9\"\n                                style=\"left: 81.818181818182%;\"\n                                aria-label=\"Donation level 10\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"10\"\n                                style=\"left: 90.909090909091%;\"\n                                aria-label=\"Donation level 11\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                                    <button\n                                type=\"button\"\n                                class=\"cg-liqpay-soft-nav-heart-point\"\n                                data-index=\"11\"\n                                style=\"left: 100%;\"\n                                aria-label=\"Donation level 12\"\n                            >\n                                <img decoding=\"async\"\n                                    src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_donate_soft_gear.png\"\n                                    alt=\"\"\n                                    aria-hidden=\"true\"\n                                >\n                            <\/button>\n                                            <\/div>\n\n                    <button\n                        type=\"button\"\n                        id=\"cg-liqpay-soft-nav-thumb\"\n                        class=\"cg-liqpay-soft-nav-thumb\"\n                        role=\"slider\"\n                        aria-label=\"Donation amount slider\"\n                        aria-valuemin=\"25\"\n                        aria-valuemax=\"2000\"\n                        aria-valuenow=\"0\"\n                        aria-valuetext=\"0 UAH\"\n                    >\n                        <img decoding=\"async\"\n                            class=\"cg-liqpay-soft-nav-hands cg-liqpay-soft-nav-hands-empty\"\n                            src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/CG_donate_soft_Hands_without_gear.png\"\n                            alt=\"\"\n                            aria-hidden=\"true\"\n                        >\n\n                        <img decoding=\"async\"\n                            class=\"cg-liqpay-soft-nav-hands cg-liqpay-soft-nav-hands-full\"\n                            src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/CG_donate_soft_Hands_with_gear.png\"\n                            alt=\"\"\n                            aria-hidden=\"true\"\n                        >\n                    <\/button>\n                <\/div>\n\n                <div class=\"cg-liqpay-soft-nav-helper\">\n                    Choose your software support level\n                <\/div>\n            <\/div>\n\n            <div\n                id=\"cg-liqpay-soft-impact-block\"\n                class=\"cg-liqpay-soft-impact-block\"\n                aria-live=\"polite\"\n            >\n                <div\n                    id=\"cg-liqpay-soft-impact-title\"\n                    class=\"cg-liqpay-soft-impact-title\"\n                >\n                    SUPPORT SOFTWARE DEVELOPMENT\n                <\/div>\n\n                <div\n                    id=\"cg-liqpay-soft-impact-text\"\n                    class=\"cg-liqpay-soft-impact-text\"\n                >\n                    Choose a donation amount to see how your support can help our software projects.\n                <\/div>\n\n                <div\n                    id=\"cg-liqpay-soft-impact-note\"\n                    class=\"cg-liqpay-soft-impact-note\"\n                >\n                    Every contribution helps us develop, improve and maintain the Foundation\u2019s software.\n                <\/div>\n            <\/div>\n\n        <\/div>\n\n\n        <div class=\"cg-liqpay-soft-field cg-liqpay-soft-entry-field\">\n\n            <div class=\"cg-liqpay-soft-entry-grid\">\n\n                <div class=\"cg-liqpay-soft-entry-cell\">\n\n                    <label for=\"cg-liqpay-soft-amount\">\n                        Donation amount\n                    <\/label>\n\n                    <div class=\"cg-liqpay-soft-amount-wrap\">\n\n                        <input\n                            id=\"cg-liqpay-soft-amount\"\n                            type=\"number\"\n                            name=\"amount\"\n                            min=\"1\"\n                            step=\"0.01\"\n                            value=\"0\"\n                            inputmode=\"decimal\"\n                            required\n                        >\n\n                        <span\n                            id=\"cg-liqpay-soft-amount-currency\"\n                            class=\"cg-liqpay-soft-amount-currency\"\n                            aria-hidden=\"true\"\n                        >\n                            UAH\n                        <\/span>\n\n                    <\/div>\n\n                <\/div>\n\n                <div class=\"cg-liqpay-soft-entry-cell\">\n\n                    <label for=\"cg-liqpay-soft-donor-comment\">\n                        Personal message (optional)\n                    <\/label>\n\n                    <textarea\n                        id=\"cg-liqpay-soft-donor-comment\"\n                        name=\"donor_comment\"\n                        class=\"cg-liqpay-soft-donor-comment\"\n                        rows=\"2\"\n                        maxlength=\"70\"\n                        wrap=\"soft\"\n                        placeholder=\"Leave a short message for the Foundation\"\n                        disabled\n                    ><\/textarea>\n\n                <\/div>\n\n            <\/div>\n\n            <div\n                id=\"cg-liqpay-soft-quick-amounts\"\n                class=\"cg-liqpay-soft-quick-amounts\"\n                role=\"group\"\n                aria-label=\"Quick donation amount\"\n            ><\/div>\n\n        <\/div>\n\n        <div class=\"cg-liqpay-soft-field\">\n\n            <div class=\"cg-liqpay-soft-field-label\">\n                Currency\n            <\/div>\n\n            <input\n                id=\"cg-liqpay-soft-currency\"\n                type=\"hidden\"\n                name=\"currency\"\n                value=\"UAH\"\n            >\n\n            <div\n                class=\"cg-liqpay-soft-currency-buttons\"\n                role=\"group\"\n                aria-label=\"Currency\"\n            >\n\n                <button\n                    type=\"button\"\n                    class=\"cg-liqpay-soft-currency-btn is-active\"\n                    data-currency=\"UAH\"\n                    aria-pressed=\"true\"\n                >\n                    UAH\n                <\/button>\n\n                <button\n                    type=\"button\"\n                    class=\"cg-liqpay-soft-currency-btn\"\n                    data-currency=\"USD\"\n                    aria-pressed=\"false\"\n                >\n                    USD\n                <\/button>\n\n                <button\n                    type=\"button\"\n                    class=\"cg-liqpay-soft-currency-btn\"\n                    data-currency=\"EUR\"\n                    aria-pressed=\"false\"\n                >\n                    EUR\n                <\/button>\n\n            <\/div>\n\n        <\/div>\n\n    <\/form>\n\n    <\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7a16e73a e-con-full e-flex e-con e-child\" data-id=\"7a16e73a\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1011058d elementor-widget elementor-widget-html\" data-id=\"1011058d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"cg-currency-token cg-currency-token-right\">\n    <img decoding=\"async\"\n        id=\"cg-token-right\"\n        src=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_uah.png\"\n        alt=\"UAH token\"\n    >\n<\/div>\n\n<style>\n.cg-currency-token-right {\n    width: 100%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n\n.cg-currency-token-right img {\n    display: block;\n    width: 190px;\n    height: 190px;\n    object-fit: contain;\n\n    animation:\n        cgTokenRotateRight\n        12s\n        linear\n        infinite;\n\n    filter:\n        drop-shadow(\n            0 10px 18px\n            rgba(0, 0, 0, 0.38)\n        );\n}\n\n@keyframes cgTokenRotateRight {\n    from {\n        transform: rotate(0deg);\n    }\n\n    to {\n        transform: rotate(-360deg);\n    }\n}\n<\/style>\n\n<script>\n(function () {\n\n    const tokenUrls = {\n        UAH: 'https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_uah.png',\n        USD: 'https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_usd-e1788944391571.png',\n        EUR: 'https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/2026\/09\/cg_token_eur.png'\n    };\n\n    function connectToken() {\n\n        const currency =\n            document.getElementById(\n                'cg-liqpay-currency'\n            );\n\n        const token =\n            document.getElementById(\n                'cg-token-right'\n            );\n\n        if (!currency || !token) {\n            return false;\n        }\n\n        function updateToken() {\n\n            const value =\n                currency.value;\n\n            if (tokenUrls[value]) {\n\n                token.src =\n                    tokenUrls[value];\n\n                token.alt =\n                    value + ' token';\n            }\n        }\n\n        currency.addEventListener(\n            'change',\n            updateToken\n        );\n\n        updateToken();\n\n        return true;\n    }\n\n    let attempts = 0;\n\n    const timer = setInterval(\n        function () {\n\n            attempts++;\n\n            if (\n                connectToken() ||\n                attempts > 30\n            ) {\n                clearInterval(timer);\n            }\n\n        },\n        200\n    );\n\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-121aa550 e-flex e-con-boxed e-con e-parent\" data-id=\"121aa550\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-3b4fca62 e-con-full e-flex e-con e-child\" data-id=\"3b4fca62\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3d657a0a elementor-widget elementor-widget-heading\" data-id=\"3d657a0a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h6 class=\"elementor-heading-title elementor-size-default\">ONGOING CHARITABLE SUPPORT<\/h6>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-54edeadb elementor-widget elementor-widget-heading\" data-id=\"54edeadb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">ONGOING CHARITABLE\nSUPPORT PROGRAM<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-30d1cccf elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"30d1cccf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Crypto-Grandpa\u2122 Ukraine Foundation conducts ongoing charitable fundraising to support the implementation and development of its charitable, educational, social and technological programs.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4bd8f46e elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"4bd8f46e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Your contribution helps the Foundation expand access to digital education and modern technologies, strengthen digital literacy and cybersecurity, develop practical educational tools, and create opportunities for cooperation between generations.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-12137dcc elementor-widget elementor-widget-heading\" data-id=\"12137dcc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">PURPOSE OF THE FUNDRAISING<\/h5>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-13ee7cb0 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"13ee7cb0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Charitable contributions help support free digital literacy and computer education, cybersecurity and artificial intelligence training, programming and engineering activities, robotics and 3D modelling, development of educational software and simulators, intergenerational learning projects, and the digital infrastructure required for the Foundation\u2019s charitable activities.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-62a0101f elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"62a0101f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Donations may also support website hosting, domain services, cloud infrastructure, licensed software, artificial intelligence services, professional digital tools, accounting, banking, legal, reporting and other reasonable operating and administrative expenses necessary for the lawful functioning of the Foundation.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5cdc4323 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"5cdc4323\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">At the current stage of the Foundation\u2019s development, many of these operating and technical expenses are being personally financed by the Founder from his own funds. Charitable support helps create a sustainable financial basis for the continued development of the Foundation\u2019s programs and infrastructure.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3a34f607 elementor-widget elementor-widget-heading\" data-id=\"3a34f607\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">FUNDRAISING GOAL<\/h5>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-67d92961 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"67d92961\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Ongoing.\n\nThe fundraising program has no fixed end date and remains active while Crypto-Grandpa\u2122 Ukraine Foundation carries out its charitable programs and statutory activities.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-613c30f4 elementor-widget elementor-widget-heading\" data-id=\"613c30f4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">FUNDRAISING PERIOD<\/h5>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-64f9cf1e elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"64f9cf1e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">The fundraising program has no fixed end date and remains active while Crypto-Grandpa\u2122 Ukraine Foundation carries out its charitable programs and statutory activities.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-61be0815 elementor-widget elementor-widget-heading\" data-id=\"61be0815\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">IMPORTANT DONATION INFORMATION<\/h5>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-72ac3364 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"72ac3364\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">All charitable contributions are voluntary.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-22d8de8e elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"22d8de8e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">A donation is not payment for goods or services, and no goods, software licences or other commercial benefits are provided in exchange for a donation.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1b751984 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"1b751984\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Charitable donations are non-refundable, except where a refund is required by applicable law.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6ba61d6d elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"6ba61d6d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">If the amount received exceeds the current needs of a particular program, or if a program cannot be implemented, is postponed or changed, the remaining funds may be redirected to other charitable programs and statutory activities of Crypto-Grandpa\u2122 Ukraine Foundation.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-76e3380a e-flex e-con-boxed e-con e-parent\" data-id=\"76e3380a\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-55703c61 e-con-full e-flex e-con e-child\" data-id=\"55703c61\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5876e02 elementor-widget elementor-widget-html\" data-id=\"5876e02\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div\n    class=\"cg-json-engine-mount\"\n    data-manifest=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/cg-matryoshka\/donate\/manifest.json\"\n><\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-5f3fa4a8 e-con-full e-flex e-con e-child\" data-id=\"5f3fa4a8\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-54eca900 elementor-widget elementor-widget-html\" data-id=\"54eca900\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\n\n    \/* =========================================================\n       CG MATRYOSHKA ENGINE\n       DYNAMIC ACTIVE WORKSPACE\n       ========================================================= *\/\n\n    .cg-json-engine-mount {\n        position: relative;\n        width: 100%;\n        box-sizing: border-box;\n        overflow: visible;\n    }\n\n\n    \/* =========================================================\n       GENERATED ROW\n       ========================================================= *\/\n\n    .cg-json-engine-row {\n        width: 100%;\n\n        display: flex;\n        flex-direction: row;\n        flex-wrap: nowrap;\n\n        align-items: stretch;\n\n        gap: 40px;\n\n        box-sizing: border-box;\n\n        margin: 0 0 70px 0;\n\n        overflow: visible;\n\n        transition:\n            min-height 0.34s ease;\n    }\n\n\n    \/*\n     * \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043c\u0430\u0442\u0440\u0451\u0448\u043a\u0430:\n     * \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434 \u0444\u0443\u0442\u0435\u0440\u043e\u043c.\n     *\/\n    .cg-json-engine-row:last-child {\n        margin-bottom: 30px;\n    }\n\n\n    .cg-json-engine-icon-col {\n        flex: 0 0 28%;\n\n        width: 28%;\n        max-width: 28%;\n\n        min-width: 0;\n\n        display: flex;\n\n        align-items: flex-start;\n        justify-content: center;\n\n        box-sizing: border-box;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-content-col {\n        flex: 0 0 68%;\n\n        width: 68%;\n        max-width: 68%;\n\n        min-width: 0;\n\n        box-sizing: border-box;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-source {\n        position: relative;\n\n        width: 100%;\n\n        min-height: 300px;\n\n        overflow: visible;\n    }\n\n\n    \/* =========================================================\n       ICON\n       ========================================================= *\/\n\n    .cg-json-engine-icon-ui {\n        width: 100%;\n\n        display: flex;\n        flex-direction: column;\n\n        align-items: center;\n        justify-content: flex-start;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-icon-button {\n        width: 220px;\n        height: 220px;\n\n        display: flex;\n\n        align-items: center;\n        justify-content: center;\n\n        padding: 0;\n        margin: 0;\n\n        border: 0 !important;\n        outline: 0 !important;\n\n        background: transparent !important;\n\n        box-shadow: none !important;\n\n        cursor: pointer;\n\n        overflow: visible;\n\n        appearance: none;\n        -webkit-appearance: none;\n\n        transition:\n            transform 0.22s ease,\n            filter 0.22s ease;\n    }\n\n\n    .cg-json-engine-icon-image {\n        display: block;\n\n        width: 220px;\n        height: 220px;\n\n        object-fit: contain;\n\n        background: transparent !important;\n\n        mix-blend-mode: normal;\n\n        pointer-events: none;\n    }\n\n\n    .cg-json-engine-icon-button:hover {\n        transform: scale(1.055);\n\n        filter:\n            drop-shadow(\n                0 0 8px\n                rgba(240, 199, 107, 0.55)\n            );\n    }\n\n\n    .cg-json-engine-icon-button.is-active {\n        transform: scale(1.055);\n\n        filter:\n            drop-shadow(\n                0 0 13px\n                rgba(240, 199, 107, 0.75)\n            );\n    }\n\n\n    .cg-json-engine-icon-button:focus,\n    .cg-json-engine-icon-button:active,\n    .cg-json-engine-icon-button:focus-visible {\n        outline: none !important;\n\n        background: transparent !important;\n\n        box-shadow: none !important;\n    }\n\n\n    \/* =========================================================\n       CARD TITLE UNDER ICON\n       ========================================================= *\/\n\n    .cg-json-engine-card-title {\n        width: 250px;\n\n        min-height: 42px;\n\n        margin-top: 12px;\n\n        box-sizing: border-box;\n\n        color: #F0C76B;\n\n        font-size: 13px;\n        font-weight: 700;\n\n        line-height: 1.35;\n\n        letter-spacing: 1px;\n\n        text-align: center;\n        text-transform: uppercase;\n\n        opacity: 0;\n        visibility: hidden;\n\n        transform: translateY(-4px);\n\n        pointer-events: none;\n\n        transition:\n            opacity 0.20s ease,\n            visibility 0.20s ease,\n            transform 0.20s ease;\n    }\n\n\n    .cg-json-engine-card-title.is-visible {\n        opacity: 1;\n        visibility: visible;\n\n        transform: translateY(0);\n    }\n\n\n    \/* =========================================================\n       MATRYOSHKA\n       ========================================================= *\/\n\n    .cg-json-engine-matryoshka {\n        position: relative;\n\n        width: 100%;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-stage {\n        position: relative;\n\n        width: 100%;\n\n        height:\n            var(\n                --cg-cover-height,\n                340px\n            );\n\n        overflow: visible;\n\n        transition:\n            height 0.34s ease;\n    }\n\n\n    .cg-json-engine-matryoshka.is-active\n    .cg-json-engine-stage {\n        height:\n            var(\n                --cg-active-workspace-height,\n                900px\n            );\n    }\n\n\n    .cg-json-engine-matryoshka.is-manual\n    .cg-json-engine-stage {\n        height:\n            var(\n                --cg-manual-workspace-height,\n                900px\n            );\n    }\n\n\n    \/* =========================================================\n       COVER\n       ========================================================= *\/\n\n    .cg-json-engine-cover {\n        position: relative;\n\n        z-index: 300;\n\n        width: 100%;\n\n        height:\n            var(\n                --cg-cover-height,\n                340px\n            );\n\n        box-sizing: border-box;\n\n        padding:\n            34px\n            38px\n            76px\n            38px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.88);\n\n        border-radius: 22px;\n\n        background:\n            linear-gradient(\n                145deg,\n                #0A1E36 0%,\n                #102D50 100%\n            );\n\n        box-shadow:\n            0 18px 45px\n            rgba(0, 0, 0, 0.38);\n\n        color: #FFFFFF;\n\n        overflow: hidden;\n    }\n\n\n    .cg-json-engine-cover-label {\n        margin-bottom: 14px;\n\n        color: #F0C76B;\n\n        font-size: 12px;\n        font-weight: 700;\n\n        line-height: 1.2;\n\n        letter-spacing: 2px;\n\n        text-transform: uppercase;\n    }\n\n\n    .cg-json-engine-cover h3 {\n        margin: 0 0 18px 0;\n\n        color: #F0C76B;\n\n        font-size: 30px;\n        font-weight: 700;\n\n        line-height: 1.15;\n    }\n\n\n    .cg-json-engine-cover p {\n        margin: 0 0 14px 0;\n\n        color: #FFFFFF;\n\n        font-size: 17px;\n\n        line-height: 1.55;\n    }\n\n\n    .cg-json-engine-cover-footer {\n        color: #F0C76B !important;\n\n        font-weight: 600;\n    }\n\n\n    \/* =========================================================\n       SCROLL TO EXPLORE\n       ========================================================= *\/\n\n    .cg-json-engine-hint {\n        position: absolute;\n\n        left: 50%;\n        bottom: 18px;\n\n        z-index: 320;\n\n        display: flex;\n        flex-direction: column;\n\n        align-items: center;\n        justify-content: center;\n\n        gap: 5px;\n\n        transform: translateX(-50%);\n\n        color: #F0C76B;\n\n        font-size: 12px;\n        font-weight: 700;\n\n        line-height: 1.1;\n\n        letter-spacing: 1.6px;\n\n        text-align: center;\n        text-transform: uppercase;\n\n        white-space: nowrap;\n\n        opacity: 0;\n        visibility: hidden;\n\n        pointer-events: none;\n\n        transition:\n            opacity 0.22s ease,\n            visibility 0.22s ease;\n    }\n\n\n    .cg-json-engine-matryoshka.is-active\n    .cg-json-engine-hint {\n        opacity: 1;\n        visibility: visible;\n    }\n\n\n    .cg-json-engine-hint-arrows {\n        display: block;\n\n        color: #F0C76B;\n\n        font-size: 17px;\n        font-weight: 700;\n\n        line-height: 1;\n\n        animation:\n            cgJsonEngineScrollArrow\n            1.35s\n            ease-in-out\n            infinite;\n    }\n\n\n    @keyframes cgJsonEngineScrollArrow {\n\n        0%,\n        100% {\n            opacity: 0.55;\n            transform: translateY(0);\n        }\n\n        50% {\n            opacity: 1;\n            transform: translateY(2px);\n        }\n\n    }\n\n\n    \/* =========================================================\n       CARDS\n       ========================================================= *\/\n\n    .cg-json-engine-card {\n        position: absolute;\n\n        top: 0;\n        left: 0;\n\n        z-index: 200;\n\n        width: 100%;\n\n        height:\n            var(\n                --cg-card-height,\n                340px\n            );\n\n        box-sizing: border-box;\n\n        padding:\n            56px\n            38px\n            30px\n            38px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.84);\n\n        border-radius: 21px;\n\n        background:\n            linear-gradient(\n                145deg,\n                #081A30 0%,\n                #102D50 100%\n            );\n\n        box-shadow:\n            0 16px 38px\n            rgba(0, 0, 0, 0.34);\n\n        color: #FFFFFF;\n\n        opacity: 0;\n\n        pointer-events: none;\n\n        will-change:\n            transform,\n            opacity;\n\n        transition:\n            transform 0.16s linear,\n            opacity 0.14s ease,\n            box-shadow 0.25s ease;\n    }\n\n\n    .cg-json-engine-card h4 {\n        margin: 0 0 16px 0;\n\n        color: #F0C76B;\n\n        font-size: 23px;\n        font-weight: 700;\n\n        line-height: 1.25;\n    }\n\n\n    .cg-json-engine-card p {\n        margin: 0;\n\n        color: #FFFFFF;\n\n        font-size: 17px;\n\n        line-height: 1.58;\n    }\n\n\n    .cg-json-engine-card.is-manual-open {\n        z-index: 420 !important;\n\n        box-shadow:\n            0 23px 60px\n            rgba(0, 0, 0, 0.58);\n\n        transition:\n            transform 0.32s ease,\n            opacity 0.20s ease,\n            box-shadow 0.25s ease;\n    }\n\n\n    \/* =========================================================\n       NUMBERS\n       ========================================================= *\/\n\n    .cg-json-engine-tabs {\n        position: absolute;\n\n        inset: 0;\n\n        z-index: 500;\n\n        pointer-events: none;\n    }\n\n\n    .cg-json-engine-tab {\n        position: absolute;\n\n        top: 0;\n        left: 0;\n\n        min-width: 33px;\n        height: 22px;\n\n        display: flex;\n\n        align-items: center;\n        justify-content: center;\n\n        box-sizing: border-box;\n\n        padding: 0 6px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.95) !important;\n\n        border-radius: 5px;\n\n        background:\n            rgba(7, 26, 51, 0.98) !important;\n\n        color:\n            #F0C76B !important;\n\n        font-size: 10px;\n        font-weight: 700;\n\n        line-height: 1;\n\n        letter-spacing: 0.7px;\n\n        opacity: 0;\n        visibility: hidden;\n\n        pointer-events: none;\n\n        cursor: default;\n\n        appearance: none;\n        -webkit-appearance: none;\n\n        outline: none !important;\n\n        box-shadow: none !important;\n\n        transition:\n            opacity 0.18s ease,\n            background-color 0.18s ease,\n            color 0.18s ease,\n            transform 0.16s linear;\n    }\n\n\n    .cg-json-engine-tab:focus,\n    .cg-json-engine-tab:active,\n    .cg-json-engine-tab:focus-visible {\n        background:\n            rgba(7, 26, 51, 0.98) !important;\n\n        color:\n            #F0C76B !important;\n\n        border-color:\n            #F0C76B !important;\n\n        outline: none !important;\n\n        box-shadow: none !important;\n    }\n\n\n    .cg-json-engine-matryoshka.is-assembled\n    .cg-json-engine-tab {\n        pointer-events: auto;\n\n        cursor: pointer;\n    }\n\n\n    .cg-json-engine-matryoshka.is-assembled\n    .cg-json-engine-tab:hover {\n        background:\n            #F0C76B !important;\n\n        color:\n            #071A33 !important;\n    }\n\n\n    \/* =========================================================\n       ERROR\n       ========================================================= *\/\n\n    .cg-json-engine-error {\n        width: 100%;\n\n        min-height: 260px;\n\n        display: flex;\n        flex-direction: column;\n\n        align-items: center;\n        justify-content: center;\n\n        gap: 10px;\n\n        box-sizing: border-box;\n\n        padding: 30px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.65);\n\n        border-radius: 22px;\n\n        background: #0A1E36;\n\n        text-align: center;\n    }\n\n\n    .cg-json-engine-error strong {\n        color: #F0C76B;\n    }\n\n\n    .cg-json-engine-error span {\n        color: #FFFFFF;\n    }\n\n\n\n    \/* =========================================================\n       TABLET\n       ========================================================= *\/\n\n    @media (min-width: 768px) and (max-width: 1024px) {\n\n        .cg-json-engine-icon-button,\n        .cg-json-engine-icon-image {\n            width: 180px;\n            height: 180px;\n        }\n\n    }\n\n\n    \/* =========================================================\n       MOBILE\n       ========================================================= *\/\n\n    @media (max-width: 767px) {\n\n        .cg-json-engine-row {\n            flex-direction: column;\n\n            gap: 18px;\n\n            margin-bottom: 55px;\n        }\n\n\n        .cg-json-engine-row:last-child {\n            margin-bottom: 25px;\n        }\n\n\n        .cg-json-engine-icon-col,\n        .cg-json-engine-content-col {\n            flex: 0 0 100%;\n\n            width: 100%;\n            max-width: 100%;\n        }\n\n\n        .cg-json-engine-icon-button,\n        .cg-json-engine-icon-image {\n            width: 140px;\n            height: 140px;\n        }\n\n\n        .cg-json-engine-card-title {\n            width: 190px;\n\n            font-size: 11px;\n        }\n\n\n        .cg-json-engine-cover {\n            padding:\n                26px\n                24px\n                72px\n                24px;\n        }\n\n\n        .cg-json-engine-cover h3 {\n            font-size: 24px;\n        }\n\n\n        .cg-json-engine-cover p,\n        .cg-json-engine-card p {\n            font-size: 15px;\n        }\n\n\n        .cg-json-engine-card {\n            padding:\n                54px\n                26px\n                26px\n                28px;\n        }\n\n\n        .cg-json-engine-card h4 {\n            font-size: 20px;\n        }\n\n    }\n\n<\/style>\n\n\n<script>\n(function () {\n\n    'use strict';\n\n\n    \/* =========================================================\n       DESTROY PREVIOUS VERSION\n       ========================================================= *\/\n\n    if (\n        window.__CG_JSON_MATRYOSHKA_ENGINE__ &&\n        typeof window.__CG_JSON_MATRYOSHKA_ENGINE__.destroy ===\n        'function'\n    ) {\n\n        window.__CG_JSON_MATRYOSHKA_ENGINE__.destroy();\n\n    }\n\n\n    if (\n        window.__CG_JSON_MATRYOSHKA_TEST__ &&\n        typeof window.__CG_JSON_MATRYOSHKA_TEST__.destroy ===\n        'function'\n    ) {\n\n        window.__CG_JSON_MATRYOSHKA_TEST__.destroy();\n\n    }\n\n\n    \/* =========================================================\n       MOUNT\n       ========================================================= *\/\n\n    const mount =\n        document.querySelector(\n            '.cg-json-engine-mount'\n        );\n\n\n    if (!mount) {\n        return;\n    }\n\n\n    const MANIFEST_URL =\n        mount.dataset.manifest || '';\n\n\n    if (!MANIFEST_URL) {\n        return;\n    }\n\n\n    \/* =========================================================\n       SETTINGS\n       ========================================================= *\/\n\n    const STEP = 420;\n\n    const STACK_SHIFT_X = 14;\n    const STACK_SHIFT_Y = 26;\n\n    const TAB_REVEAL_START = 0.55;\n\n    const TAB_LEFT = 11;\n    const TAB_BOTTOM = 1;\n    const TAB_HEIGHT = 22;\n\n    const CENTER_DURATION = 460;\n\n    const HEADER_GAP = 18;\n\n    const UPPER_VIEWPORT_RATIO = 0.12;\n\n    const ENTRY_BELOW_VIEWPORT = 80;\n\n    const MANUAL_GAP = 28;\n\n    const WORKSPACE_BOTTOM_PAD = 60;\n\n\n    \/* =========================================================\n       GLOBAL STATE\n       ========================================================= *\/\n\n    let instances = [];\n\n    let currentInstance = null;\n\n    let pageLocked = false;\n\n    let lockedScrollY = 0;\n\n    let lastTouchY = null;\n\n    let destroyed = false;\n\n\n    const savedPageStyle = {\n\n        htmlOverflow: '',\n        htmlOverscroll: '',\n\n        bodyOverflow: '',\n        bodyOverscroll: '',\n        bodyTouchAction: ''\n\n    };\n\n\n    \/* =========================================================\n       HELPERS\n       ========================================================= *\/\n\n    function clamp(\n        value,\n        min,\n        max\n    ) {\n\n        return Math.min(\n            max,\n            Math.max(\n                min,\n                value\n            )\n        );\n\n    }\n\n\n    function createElement(\n        tag,\n        className,\n        text\n    ) {\n\n        const element =\n            document.createElement(\n                tag\n            );\n\n\n        if (className) {\n            element.className =\n                className;\n        }\n\n\n        if (\n            text !== undefined &&\n            text !== null\n        ) {\n\n            element.textContent =\n                text;\n\n        }\n\n\n        return element;\n\n    }\n\n\n    \/* =========================================================\n       PAGE LOCK\n       ========================================================= *\/\n\n    function lockPage() {\n\n        if (pageLocked) {\n            return;\n        }\n\n\n        const html =\n            document.documentElement;\n\n\n        const body =\n            document.body;\n\n\n        lockedScrollY =\n            window.scrollY;\n\n\n        savedPageStyle.htmlOverflow =\n            html.style.overflow;\n\n\n        savedPageStyle.htmlOverscroll =\n            html.style.overscrollBehavior;\n\n\n        savedPageStyle.bodyOverflow =\n            body.style.overflow;\n\n\n        savedPageStyle.bodyOverscroll =\n            body.style.overscrollBehavior;\n\n\n        savedPageStyle.bodyTouchAction =\n            body.style.touchAction;\n\n\n        html.style.setProperty(\n            'overflow',\n            'hidden',\n            'important'\n        );\n\n\n        html.style.setProperty(\n            'overscroll-behavior',\n            'none',\n            'important'\n        );\n\n\n        body.style.setProperty(\n            'overflow',\n            'hidden',\n            'important'\n        );\n\n\n        body.style.setProperty(\n            'overscroll-behavior',\n            'none',\n            'important'\n        );\n\n\n        body.style.setProperty(\n            'touch-action',\n            'none',\n            'important'\n        );\n\n\n        pageLocked = true;\n\n    }\n\n\n    function unlockPage() {\n\n        if (!pageLocked) {\n            return;\n        }\n\n\n        const html =\n            document.documentElement;\n\n\n        const body =\n            document.body;\n\n\n        html.style.overflow =\n            savedPageStyle.htmlOverflow;\n\n\n        html.style.overscrollBehavior =\n            savedPageStyle.htmlOverscroll;\n\n\n        body.style.overflow =\n            savedPageStyle.bodyOverflow;\n\n\n        body.style.overscrollBehavior =\n            savedPageStyle.bodyOverscroll;\n\n\n        body.style.touchAction =\n            savedPageStyle.bodyTouchAction;\n\n\n        pageLocked = false;\n\n    }\n\n\n    \/* =========================================================\n       MANIFEST VALIDATION\n       ========================================================= *\/\n\n    function validateManifest(\n        manifest\n    ) {\n\n        if (\n            !manifest ||\n            typeof manifest !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Invalid manifest'\n            );\n\n        }\n\n\n        if (\n            !Array.isArray(\n                manifest.sections\n            ) ||\n            manifest.sections.length === 0\n        ) {\n\n            throw new Error(\n                'Manifest sections missing'\n            );\n\n        }\n\n\n        manifest.sections.forEach(\n            function (\n                section,\n                index\n            ) {\n\n                if (\n                    !section ||\n                    !section.source\n                ) {\n\n                    throw new Error(\n                        'Manifest source missing at section ' +\n                        (\n                            index + 1\n                        )\n                    );\n\n                }\n\n            }\n        );\n\n    }\n\n\n    \/* =========================================================\n       SECTION VALIDATION\n       ========================================================= *\/\n\n    function validateSection(\n        data\n    ) {\n\n        if (\n            !data ||\n            typeof data !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Invalid section JSON'\n            );\n\n        }\n\n\n        if (\n            !data.section ||\n            typeof data.section !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Section data missing'\n            );\n\n        }\n\n\n        if (\n            !data.section.id ||\n            !data.section.title\n        ) {\n\n            throw new Error(\n                'Section ID or title missing'\n            );\n\n        }\n\n\n        if (\n            !data.section.icon ||\n            typeof data.section.icon !==\n            'object' ||\n            !data.section.icon.src\n        ) {\n\n            throw new Error(\n                'Section icon missing'\n            );\n\n        }\n\n\n        if (\n            !data.cover ||\n            typeof data.cover !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Cover missing'\n            );\n\n        }\n\n\n        if (\n            !Array.isArray(\n                data.cards\n            ) ||\n            data.cards.length === 0\n        ) {\n\n            throw new Error(\n                'Cards missing'\n            );\n\n        }\n\n\n        data.cards.forEach(\n            function (\n                card,\n                index\n            ) {\n\n                if (\n                    !card ||\n                    !card.title ||\n                    !card.text\n                ) {\n\n                    throw new Error(\n                        'Invalid card ' +\n                        (\n                            index + 1\n                        )\n                    );\n\n                }\n\n            }\n        );\n\n    }\n\n\n    \/* =========================================================\n       MATRYOSHKA INSTANCE\n       ========================================================= *\/\n\n    class MatryoshkaInstance {\n\n        constructor(\n            data\n        ) {\n\n            this.data = data;\n\n            this.row = null;\n\n            this.iconUI = null;\n            this.iconButton = null;\n            this.iconTitle = null;\n\n            this.source = null;\n\n            this.root = null;\n            this.stage = null;\n            this.cover = null;\n\n            this.cards = [];\n            this.tabs = [];\n\n            this.coverHeight = 340;\n            this.cardHeight = 340;\n\n            this.stackHeight = 340;\n\n            this.activeWorkspaceHeight = 900;\n\n            this.manualWorkspaceHeight = 900;\n\n            this.assemblyDistance = 0;\n\n            this.progress = 0;\n\n            this.mode = 'off';\n\n            this.manualIndex = -1;\n\n            this.centerTimer = null;\n\n            this.build();\n\n        }\n\n\n        \/* =====================================================\n           BUILD ROW\n           ===================================================== *\/\n\n        build() {\n\n            this.row =\n                createElement(\n                    'div',\n                    'cg-json-engine-row'\n                );\n\n\n            this.row.dataset.section =\n                this.data.section.id;\n\n\n            const iconCol =\n                createElement(\n                    'div',\n                    'cg-json-engine-icon-col'\n                );\n\n\n            this.iconUI =\n                createElement(\n                    'div',\n                    'cg-json-engine-icon-ui'\n                );\n\n\n            this.iconButton =\n                createElement(\n                    'button',\n                    'cg-json-engine-icon-button'\n                );\n\n\n            this.iconButton.type =\n                'button';\n\n\n            this.iconButton.setAttribute(\n                'aria-expanded',\n                'false'\n            );\n\n\n            this.iconButton.setAttribute(\n\n                'aria-label',\n\n                this.data.section.icon.aria_label ||\n\n                this.data.section.title ||\n\n                'Open section'\n\n            );\n\n\n            const iconImage =\n                createElement(\n                    'img',\n                    'cg-json-engine-icon-image'\n                );\n\n\n            iconImage.src =\n                this.data.section.icon.src;\n\n\n            iconImage.alt =\n                this.data.section.icon.alt ||\n\n                this.data.section.title ||\n\n                '';\n\n\n            this.iconButton.appendChild(\n                iconImage\n            );\n\n\n            this.iconTitle =\n                createElement(\n                    'div',\n                    'cg-json-engine-card-title'\n                );\n\n\n            this.iconTitle.setAttribute(\n                'aria-live',\n                'polite'\n            );\n\n\n            this.iconUI.appendChild(\n                this.iconButton\n            );\n\n\n            this.iconUI.appendChild(\n                this.iconTitle\n            );\n\n\n            iconCol.appendChild(\n                this.iconUI\n            );\n\n\n            const contentCol =\n                createElement(\n                    'div',\n                    'cg-json-engine-content-col'\n                );\n\n\n            this.source =\n                createElement(\n                    'div',\n                    'cg-json-engine-source'\n                );\n\n\n            contentCol.appendChild(\n                this.source\n            );\n\n\n            this.row.appendChild(\n                iconCol\n            );\n\n\n            this.row.appendChild(\n                contentCol\n            );\n\n\n            mount.appendChild(\n                this.row\n            );\n\n\n            this.buildMatryoshka();\n\n\n            this.iconButton.addEventListener(\n                'click',\n                this.onIconClick\n            );\n\n        }\n\n\n        \/* =====================================================\n           BUILD MATRYOSHKA\n           ===================================================== *\/\n\n        buildMatryoshka() {\n\n            this.root =\n                createElement(\n                    'section',\n                    'cg-json-engine-matryoshka'\n                );\n\n\n            this.root.dataset.section =\n                this.data.section.id;\n\n\n            this.stage =\n                createElement(\n                    'div',\n                    'cg-json-engine-stage'\n                );\n\n\n            this.cover =\n                createElement(\n                    'article',\n                    'cg-json-engine-cover'\n                );\n\n\n            if (\n                this.data.cover.label\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'div',\n                        'cg-json-engine-cover-label',\n                        this.data.cover.label\n                    )\n                );\n\n            }\n\n\n            this.cover.appendChild(\n                createElement(\n                    'h3',\n                    '',\n                    this.data.cover.title || ''\n                )\n            );\n\n\n            if (\n                this.data.cover.description\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'p',\n                        '',\n                        this.data.cover.description\n                    )\n                );\n\n            }\n\n\n            if (\n                this.data.cover.secondary_text\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'p',\n                        '',\n                        this.data.cover.secondary_text\n                    )\n                );\n\n            }\n\n\n            if (\n                this.data.cover.footer_text\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'p',\n                        'cg-json-engine-cover-footer',\n                        this.data.cover.footer_text\n                    )\n                );\n\n            }\n\n\n            const hint =\n                createElement(\n                    'div',\n                    'cg-json-engine-hint'\n                );\n\n\n            hint.appendChild(\n                createElement(\n                    'span',\n                    '',\n                    'SCROLL TO EXPLORE'\n                )\n            );\n\n\n            hint.appendChild(\n                createElement(\n                    'span',\n                    'cg-json-engine-hint-arrows',\n                    '\u2191\u2193'\n                )\n            );\n\n\n            this.cover.appendChild(\n                hint\n            );\n\n\n            this.stage.appendChild(\n                this.cover\n            );\n\n\n            this.cards = [];\n\n\n            this.data.cards.forEach(\n                (\n                    cardData,\n                    index\n                ) => {\n\n                    const card =\n                        createElement(\n                            'article',\n                            'cg-json-engine-card'\n                        );\n\n\n                    card.dataset.cardIndex =\n                        String(index);\n\n\n                    card.dataset.cardTitle =\n                        cardData.title;\n\n\n                    card.appendChild(\n                        createElement(\n                            'h4',\n                            '',\n                            cardData.title\n                        )\n                    );\n\n\n                    card.appendChild(\n                        createElement(\n                            'p',\n                            '',\n                            cardData.text\n                        )\n                    );\n\n\n                    this.stage.appendChild(\n                        card\n                    );\n\n\n                    this.cards.push(\n                        card\n                    );\n\n                }\n            );\n\n\n            const tabsLayer =\n                createElement(\n                    'div',\n                    'cg-json-engine-tabs'\n                );\n\n\n            this.tabs = [];\n\n\n            this.data.cards.forEach(\n                (\n                    cardData,\n                    index\n                ) => {\n\n                    const tab =\n                        createElement(\n                            'button',\n                            'cg-json-engine-tab',\n                            String(\n                                index + 1\n                            ).padStart(\n                                2,\n                                '0'\n                            )\n                        );\n\n\n                    tab.type =\n                        'button';\n\n\n                    tab.dataset.cardIndex =\n                        String(index);\n\n\n                    tab.setAttribute(\n                        'aria-label',\n                        cardData.title\n                    );\n\n\n                    tab.tabIndex =\n                        -1;\n\n\n                    tabsLayer.appendChild(\n                        tab\n                    );\n\n\n                    this.tabs.push(\n                        tab\n                    );\n\n                }\n            );\n\n\n            this.stage.appendChild(\n                tabsLayer\n            );\n\n\n            this.root.appendChild(\n                this.stage\n            );\n\n\n            this.source.appendChild(\n                this.root\n            );\n\n\n            this.bindCardEvents();\n\n\n            this.measure();\n\n        }\n\n\n        \/* =====================================================\n           DYNAMIC WORKSPACE MEASUREMENT\n           ===================================================== *\/\n\n        measure() {\n\n            if (\n                !this.cover ||\n                !this.cards.length\n            ) {\n\n                return;\n\n            }\n\n\n            this.cover.style.height =\n                'auto';\n\n\n            this.cards.forEach(\n                function (\n                    card\n                ) {\n\n                    card.style.height =\n                        'auto';\n\n                }\n            );\n\n\n            this.coverHeight =\n                Math.max(\n\n                    300,\n\n                    Math.ceil(\n                        this.cover.scrollHeight\n                    )\n\n                );\n\n\n            this.cardHeight =\n                this.coverHeight;\n\n\n            this.cards.forEach(\n                (\n                    card\n                ) => {\n\n                    this.cardHeight =\n                        Math.max(\n\n                            this.cardHeight,\n\n                            Math.ceil(\n                                card.scrollHeight\n                            )\n\n                        );\n\n                }\n            );\n\n\n            this.coverHeight =\n                Math.max(\n                    this.coverHeight,\n                    this.cardHeight\n                );\n\n\n            this.cardHeight =\n                this.coverHeight;\n\n\n            this.cover.style.height =\n                '';\n\n\n            this.cards.forEach(\n                function (\n                    card\n                ) {\n\n                    card.style.height =\n                        '';\n\n                }\n            );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-cover-height',\n\n                this.coverHeight +\n                'px'\n\n            );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-card-height',\n\n                this.cardHeight +\n                'px'\n\n            );\n\n\n            this.stackHeight =\n\n                this.coverHeight +\n\n                (\n                    STACK_SHIFT_Y *\n                    this.cards.length\n                ) +\n\n                WORKSPACE_BOTTOM_PAD;\n\n\n            const entryY =\n                this.getEntryY();\n\n\n            const travelHeight =\n\n                entryY +\n\n                this.cardHeight +\n\n                WORKSPACE_BOTTOM_PAD;\n\n\n            this.activeWorkspaceHeight =\n\n                Math.max(\n\n                    this.stackHeight,\n\n                    travelHeight\n\n                );\n\n\n            const manualCardBottom =\n\n                this.coverHeight +\n\n                MANUAL_GAP +\n\n                this.cardHeight +\n\n                WORKSPACE_BOTTOM_PAD;\n\n\n            this.manualWorkspaceHeight =\n\n                Math.max(\n\n                    this.activeWorkspaceHeight,\n\n                    manualCardBottom\n\n                );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-active-workspace-height',\n\n                this.activeWorkspaceHeight +\n                'px'\n\n            );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-manual-workspace-height',\n\n                this.manualWorkspaceHeight +\n                'px'\n\n            );\n\n\n            this.iconUI.style.minHeight =\n                this.coverHeight +\n                'px';\n\n\n            this.iconUI.style.justifyContent =\n                'center';\n\n\n            this.assemblyDistance =\n\n                STEP *\n                this.cards.length;\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           ENTRY POSITION\n           ===================================================== *\/\n\n        getEntryY() {\n\n            const rect =\n                this.stage\n                    .getBoundingClientRect();\n\n\n            return Math.max(\n\n                this.coverHeight +\n                240,\n\n                window.innerHeight -\n                rect.top +\n                ENTRY_BELOW_VIEWPORT\n\n            );\n\n        }\n\n\n        \/* =====================================================\n           ICON TITLE\n           ===================================================== *\/\n\n        setIconTitle(\n            text\n        ) {\n\n            this.iconTitle.textContent =\n                text || '';\n\n\n            this.iconTitle.classList.toggle(\n                'is-visible',\n                Boolean(text)\n            );\n\n        }\n\n\n        \/* =====================================================\n           UPDATE CARDS\n           ===================================================== *\/\n\n        updateCards() {\n\n            if (\n                !this.root ||\n                !this.stage\n            ) {\n\n                return;\n\n            }\n\n\n            const active =\n                this.mode ===\n                'active';\n\n\n            const assembled =\n\n                active &&\n\n                this.progress >=\n                this.assemblyDistance -\n                0.5;\n\n\n            this.root.classList.toggle(\n                'is-active',\n                active\n            );\n\n\n            this.root.classList.toggle(\n                'is-assembled',\n                assembled\n            );\n\n\n            this.root.classList.toggle(\n                'is-manual',\n                this.manualIndex !==\n                -1\n            );\n\n\n            this.row.classList.toggle(\n                'is-active-row',\n                active\n            );\n\n\n            this.iconButton.classList.toggle(\n                'is-active',\n                active\n            );\n\n\n            this.iconButton.setAttribute(\n\n                'aria-expanded',\n\n                active\n                    ?\n                    'true'\n                    :\n                    'false'\n\n            );\n\n\n            const entryY =\n                this.getEntryY();\n\n\n            this.cards.forEach(\n                (\n                    card,\n                    index\n                ) => {\n\n                    const segmentStart =\n\n                        index *\n                        STEP;\n\n\n                    const local =\n\n                        active\n\n                            ?\n\n                            clamp(\n\n                                (\n                                    this.progress -\n                                    segmentStart\n                                ) \/\n                                STEP,\n\n                                0,\n                                1\n\n                            )\n\n                            :\n\n                            0;\n\n\n                    const finalX =\n\n                        -STACK_SHIFT_X *\n                        (\n                            index +\n                            1\n                        );\n\n\n                    const finalY =\n\n                        STACK_SHIFT_Y *\n                        (\n                            index +\n                            1\n                        );\n\n\n                    let x =\n                        finalX *\n                        local;\n\n\n                    let y =\n\n                        entryY +\n\n                        (\n                            (\n                                finalY -\n                                entryY\n                            ) *\n                            local\n                        );\n\n\n                    let opacity =\n\n                        local <= 0\n\n                            ?\n\n                            0\n\n                            :\n\n                            clamp(\n                                local *\n                                1.55,\n                                0,\n                                1\n                            );\n\n\n                    let scale =\n\n                        0.988 +\n\n                        (\n                            0.012 *\n                            local\n                        );\n\n\n                    let zIndex =\n\n                        250 -\n                        index;\n\n\n                    if (\n                        assembled &&\n                        this.manualIndex ===\n                        index\n                    ) {\n\n                        x = 0;\n\n\n                        y =\n\n                            this.coverHeight +\n                            MANUAL_GAP;\n\n\n                        opacity = 1;\n\n                        scale = 1;\n\n                        zIndex = 420;\n\n\n                        card.classList.add(\n                            'is-manual-open'\n                        );\n\n                    } else {\n\n                        card.classList.remove(\n                            'is-manual-open'\n                        );\n\n                    }\n\n\n                    card.style.transform =\n\n                        'translate3d(' +\n\n                        x +\n                        'px,' +\n\n                        y +\n                        'px,0) scale(' +\n\n                        scale +\n\n                        ')';\n\n\n                    card.style.opacity =\n                        String(opacity);\n\n\n                    card.style.zIndex =\n                        String(zIndex);\n\n\n                    card.style.pointerEvents =\n\n                        this.manualIndex ===\n                        index\n\n                            ?\n\n                            'auto'\n\n                            :\n\n                            'none';\n\n\n                    const reveal =\n\n                        clamp(\n\n                            (\n                                local -\n                                TAB_REVEAL_START\n                            ) \/\n\n                            (\n                                1 -\n                                TAB_REVEAL_START\n                            ),\n\n                            0,\n                            1\n\n                        );\n\n\n                    let tabX =\n\n                        x +\n                        TAB_LEFT;\n\n\n                    let tabY =\n\n                        y +\n\n                        this.cardHeight -\n\n                        TAB_BOTTOM -\n\n                        TAB_HEIGHT;\n\n\n                    if (\n                        assembled &&\n                        this.manualIndex ===\n                        index\n                    ) {\n\n                        tabX =\n                            TAB_LEFT;\n\n\n                        tabY =\n\n                            this.coverHeight +\n\n                            MANUAL_GAP +\n\n                            this.cardHeight -\n\n                            TAB_BOTTOM -\n\n                            TAB_HEIGHT;\n\n                    }\n\n\n                    this.tabs[\n                        index\n                    ].style.transform =\n\n                        'translate3d(' +\n\n                        tabX +\n                        'px,' +\n\n                        tabY +\n                        'px,0)';\n\n\n                    this.tabs[\n                        index\n                    ].style.opacity =\n                        String(reveal);\n\n\n                    this.tabs[\n                        index\n                    ].style.visibility =\n\n                        reveal >\n                        0.02\n\n                            ?\n\n                            'visible'\n\n                            :\n\n                            'hidden';\n\n\n                    this.tabs[\n                        index\n                    ].tabIndex =\n\n                        assembled\n\n                            ?\n\n                            0\n\n                            :\n\n                            -1;\n\n                }\n            );\n\n\n            if (\n                !assembled &&\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.manualIndex = -1;\n\n\n                this.setIconTitle(\n                    ''\n                );\n\n\n                this.root.classList.remove(\n                    'is-manual'\n                );\n\n            }\n\n        }\n\n\n        \/* =====================================================\n           CARD EVENTS\n           ===================================================== *\/\n\n        bindCardEvents() {\n\n            this.tabs.forEach(\n                (\n                    tab,\n                    index\n                ) => {\n\n                    tab.addEventListener(\n                        'mouseenter',\n                        () => {\n\n                            if (\n                                this.mode ===\n                                'active' &&\n\n                                this.progress >=\n                                this.assemblyDistance -\n                                0.5\n                            ) {\n\n                                this.setIconTitle(\n\n                                    this.cards[\n                                        index\n                                    ].dataset.cardTitle ||\n\n                                    ''\n\n                                );\n\n                            }\n\n                        }\n                    );\n\n\n                    tab.addEventListener(\n                        'mouseleave',\n                        () => {\n\n                            if (\n                                this.manualIndex ===\n                                -1\n                            ) {\n\n                                this.setIconTitle(\n                                    ''\n                                );\n\n                            }\n\n                        }\n                    );\n\n\n                    tab.addEventListener(\n                        'click',\n                        (\n                            event\n                        ) => {\n\n                            event.preventDefault();\n\n                            event.stopPropagation();\n\n\n                            if (\n                                this.manualIndex ===\n                                index\n                            ) {\n\n                                this.closeManual();\n\n                            } else {\n\n                                this.openManual(\n                                    index\n                                );\n\n                            }\n\n                        }\n                    );\n\n\n                    this.cards[\n                        index\n                    ].addEventListener(\n                        'click',\n                        () => {\n\n                            if (\n                                this.manualIndex ===\n                                index\n                            ) {\n\n                                this.closeManual();\n\n                            }\n\n                        }\n                    );\n\n                }\n            );\n\n        }\n\n\n        \/* =====================================================\n           MANUAL CARD\n           ===================================================== *\/\n\n        openManual(\n            index\n        ) {\n\n            if (\n                this.mode !==\n                'active' ||\n\n                this.progress <\n                this.assemblyDistance -\n                0.5\n            ) {\n\n                return;\n\n            }\n\n\n            this.manualIndex =\n                index;\n\n\n            this.setIconTitle(\n\n                this.cards[\n                    index\n                ].dataset.cardTitle ||\n\n                ''\n\n            );\n\n\n            this.updateCards();\n\n        }\n\n\n        closeManual() {\n\n            if (\n                this.manualIndex ===\n                -1\n            ) {\n\n                return;\n\n            }\n\n\n            this.manualIndex = -1;\n\n\n            this.setIconTitle(\n                ''\n            );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           HEADER \/ TARGET POSITION\n           ===================================================== *\/\n\n        getHeaderBottom() {\n\n            const header =\n                document.querySelector(\n                    '#masthead'\n                );\n\n\n            if (!header) {\n                return 0;\n            }\n\n\n            return Math.max(\n\n                0,\n\n                header\n                    .getBoundingClientRect()\n                    .bottom\n\n            );\n\n        }\n\n\n        getTargetY() {\n\n            const rect =\n                this.row\n                    .getBoundingClientRect();\n\n\n            const desiredTop =\n\n                Math.max(\n\n                    this.getHeaderBottom() +\n                    HEADER_GAP,\n\n                    window.innerHeight *\n                    UPPER_VIEWPORT_RATIO\n\n                );\n\n\n            return Math.max(\n\n                0,\n\n                window.scrollY +\n                rect.top -\n                desiredTop\n\n            );\n\n        }\n\n\n        \/* =====================================================\n           ACTIVATE\n           ===================================================== *\/\n\n        activate() {\n\n            if (\n                this.mode !==\n                'off'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                currentInstance &&\n                currentInstance !==\n                this\n            ) {\n\n                currentInstance.deactivate();\n\n            }\n\n\n            currentInstance =\n                this;\n\n\n            this.mode =\n                'centering';\n\n\n            this.progress = 0;\n\n            this.manualIndex = -1;\n\n\n            this.setIconTitle(\n                ''\n            );\n\n\n            this.measure();\n\n\n            const target =\n                this.getTargetY();\n\n\n            window.scrollTo({\n\n                top: target,\n\n                behavior: 'smooth'\n\n            });\n\n\n            clearTimeout(\n                this.centerTimer\n            );\n\n\n            this.centerTimer =\n                window.setTimeout(\n                    () => {\n\n                        if (\n                            destroyed ||\n\n                            currentInstance !==\n                            this ||\n\n                            this.mode !==\n                            'centering'\n                        ) {\n\n                            return;\n\n                        }\n\n\n                        window.scrollTo(\n                            0,\n                            target\n                        );\n\n\n                        this.measure();\n\n\n                        lockPage();\n\n\n                        this.mode =\n                            'active';\n\n\n                        this.updateCards();\n\n                    },\n\n                    CENTER_DURATION\n                );\n\n        }\n\n\n        \/* =====================================================\n           DEACTIVATE\n           ===================================================== *\/\n\n        deactivate() {\n\n            clearTimeout(\n                this.centerTimer\n            );\n\n\n            this.mode =\n                'off';\n\n\n            this.progress =\n                0;\n\n\n            this.manualIndex =\n                -1;\n\n\n            this.setIconTitle(\n                ''\n            );\n\n\n            this.updateCards();\n\n\n            if (\n                currentInstance ===\n                this\n            ) {\n\n                currentInstance =\n                    null;\n\n\n                unlockPage();\n\n            }\n\n        }\n\n\n        \/* =====================================================\n           WHEEL\n           ===================================================== *\/\n\n        handleWheel(\n            event\n        ) {\n\n            if (\n                this.mode !==\n                'active'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.closeManual();\n\n                return;\n\n            }\n\n\n            let delta =\n                event.deltaY;\n\n\n            if (\n                event.deltaMode ===\n                1\n            ) {\n\n                delta *= 18;\n\n            }\n\n\n            if (\n                event.deltaMode ===\n                2\n            ) {\n\n                delta *=\n                    window.innerHeight;\n\n            }\n\n\n            delta =\n                clamp(\n                    delta,\n                    -140,\n                    140\n                );\n\n\n            this.progress =\n                clamp(\n\n                    this.progress +\n                    delta,\n\n                    0,\n\n                    this.assemblyDistance\n\n                );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           TOUCH\n           ===================================================== *\/\n\n        handleTouchDelta(\n            delta\n        ) {\n\n            if (\n                this.mode !==\n                'active'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.closeManual();\n\n                return;\n\n            }\n\n\n            this.progress =\n                clamp(\n\n                    this.progress +\n\n                    delta *\n                    2.2,\n\n                    0,\n\n                    this.assemblyDistance\n\n                );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           KEYBOARD\n           ===================================================== *\/\n\n        handleKeyDelta(\n            delta\n        ) {\n\n            if (\n                this.mode !==\n                'active'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.closeManual();\n\n                return;\n\n            }\n\n\n            this.progress =\n                clamp(\n\n                    this.progress +\n                    delta,\n\n                    0,\n\n                    this.assemblyDistance\n\n                );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           ICON CLICK\n           ===================================================== *\/\n\n        onIconClick =\n            (\n                event\n            ) => {\n\n                event.preventDefault();\n\n\n                if (\n                    this.mode ===\n                    'off'\n                ) {\n\n                    this.activate();\n\n                } else {\n\n                    this.deactivate();\n\n                }\n\n            };\n\n\n        \/* =====================================================\n           DESTROY\n           ===================================================== *\/\n\n        destroy() {\n\n            clearTimeout(\n                this.centerTimer\n            );\n\n\n            this.iconButton.removeEventListener(\n                'click',\n                this.onIconClick\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       ERROR ROW\n       ========================================================= *\/\n\n    function createErrorRow(\n        title,\n        detail\n    ) {\n\n        const row =\n            createElement(\n                'div',\n                'cg-json-engine-row'\n            );\n\n\n        const iconCol =\n            createElement(\n                'div',\n                'cg-json-engine-icon-col'\n            );\n\n\n        const contentCol =\n            createElement(\n                'div',\n                'cg-json-engine-content-col'\n            );\n\n\n        const box =\n            createElement(\n                'div',\n                'cg-json-engine-error'\n            );\n\n\n        box.appendChild(\n            createElement(\n                'strong',\n                '',\n                title\n            )\n        );\n\n\n        box.appendChild(\n            createElement(\n                'span',\n                '',\n                detail\n            )\n        );\n\n\n        contentCol.appendChild(\n            box\n        );\n\n\n        row.appendChild(\n            iconCol\n        );\n\n\n        row.appendChild(\n            contentCol\n        );\n\n\n        mount.appendChild(\n            row\n        );\n\n    }\n\n\n    \/* =========================================================\n       FETCH JSON\n       ========================================================= *\/\n\n    async function fetchJson(\n        url\n    ) {\n\n        const response =\n            await fetch(\n                url,\n                {\n                    cache: 'no-store'\n                }\n            );\n\n\n        if (\n            !response.ok\n        ) {\n\n            throw new Error(\n                'HTTP ' +\n                response.status\n            );\n\n        }\n\n\n        return await response.json();\n\n    }\n\n\n    \/* =========================================================\n       INIT\n       ========================================================= *\/\n\n    async function init() {\n\n        try {\n\n            mount.innerHTML = '';\n\n\n            const manifest =\n                await fetchJson(\n                    MANIFEST_URL\n                );\n\n\n            validateManifest(\n                manifest\n            );\n\n\n            for (\n                let index = 0;\n                index <\n                manifest.sections.length;\n                index++\n            ) {\n\n                const item =\n                    manifest.sections[\n                        index\n                    ];\n\n\n                try {\n\n                    const sectionUrl =\n                        new URL(\n                            item.source,\n                            MANIFEST_URL\n                        ).href;\n\n\n                    const data =\n                        await fetchJson(\n                            sectionUrl\n                        );\n\n\n                    validateSection(\n                        data\n                    );\n\n\n                    const instance =\n                        new MatryoshkaInstance(\n                            data\n                        );\n\n\n                    instances.push(\n                        instance\n                    );\n\n\n                } catch (\n                    sectionError\n                ) {\n\n                    console.error(\n                        '[CG MATRYOSHKA SECTION]',\n                        sectionError\n                    );\n\n\n                    createErrorRow(\n\n                        'SECTION ' +\n                        String(\n                            index + 1\n                        ).padStart(\n                            2,\n                            '0'\n                        ) +\n                        ' COULD NOT BE LOADED',\n\n                        item.source\n\n                    );\n\n                }\n\n            }\n\n\n        } catch (\n            error\n        ) {\n\n            console.error(\n                '[CG MATRYOSHKA ENGINE]',\n                error\n            );\n\n\n            createErrorRow(\n\n                'MATRYOSHKA ENGINE COULD NOT START',\n\n                String(\n                    error.message ||\n                    error\n                )\n\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL WHEEL\n       ========================================================= *\/\n\n    function onWheel(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode ===\n            'off'\n        ) {\n\n            return;\n\n        }\n\n\n        event.preventDefault();\n\n\n        if (\n            currentInstance.mode ===\n            'active'\n        ) {\n\n            currentInstance.handleWheel(\n                event\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL TOUCH\n       ========================================================= *\/\n\n    function onTouchStart(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode !==\n            'active' ||\n            !event.touches ||\n            event.touches.length !==\n            1\n        ) {\n\n            return;\n\n        }\n\n\n        lastTouchY =\n            event.touches[\n                0\n            ].clientY;\n\n    }\n\n\n    function onTouchMove(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode !==\n            'active' ||\n            !event.touches ||\n            event.touches.length !==\n            1\n        ) {\n\n            return;\n\n        }\n\n\n        event.preventDefault();\n\n\n        const currentY =\n            event.touches[\n                0\n            ].clientY;\n\n\n        const delta =\n\n            lastTouchY -\n            currentY;\n\n\n        lastTouchY =\n            currentY;\n\n\n        currentInstance.handleTouchDelta(\n            delta\n        );\n\n    }\n\n\n    function onTouchEnd() {\n\n        lastTouchY = null;\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL KEYBOARD\n       ========================================================= *\/\n\n    function onKeyDown(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode ===\n            'off'\n        ) {\n\n            return;\n\n        }\n\n\n        let delta = null;\n\n\n        if (\n            event.key ===\n            'ArrowDown'\n        ) {\n\n            delta = 120;\n\n\n        } else if (\n            event.key ===\n            'ArrowUp'\n        ) {\n\n            delta = -120;\n\n\n        } else if (\n            event.key ===\n            'PageDown' ||\n            event.key ===\n            ' '\n        ) {\n\n            delta = 320;\n\n\n        } else if (\n            event.key ===\n            'PageUp'\n        ) {\n\n            delta = -320;\n\n\n        } else if (\n            event.key ===\n            'Home'\n        ) {\n\n            event.preventDefault();\n\n\n            currentInstance.closeManual();\n\n\n            currentInstance.progress = 0;\n\n\n            currentInstance.updateCards();\n\n\n            return;\n\n\n        } else if (\n            event.key ===\n            'End'\n        ) {\n\n            event.preventDefault();\n\n\n            currentInstance.closeManual();\n\n\n            currentInstance.progress =\n                currentInstance\n                    .assemblyDistance;\n\n\n            currentInstance.updateCards();\n\n\n            return;\n\n\n        } else if (\n            event.key ===\n            'Escape'\n        ) {\n\n            event.preventDefault();\n\n\n            currentInstance.deactivate();\n\n\n            return;\n\n\n        } else {\n\n            return;\n\n        }\n\n\n        event.preventDefault();\n\n\n        if (\n            currentInstance &&\n            currentInstance.mode ===\n            'active'\n        ) {\n\n            currentInstance.handleKeyDelta(\n                delta\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       SCROLL GUARD\n       ========================================================= *\/\n\n    function onWindowScroll() {\n\n        if (\n            pageLocked &&\n            currentInstance &&\n            currentInstance.mode ===\n            'active' &&\n            Math.abs(\n                window.scrollY -\n                lockedScrollY\n            ) >\n            1\n        ) {\n\n            window.scrollTo(\n                0,\n                lockedScrollY\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       RESIZE\n       ========================================================= *\/\n\n    function onResize() {\n\n        instances.forEach(\n            function (\n                instance\n            ) {\n\n                instance.measure();\n\n            }\n        );\n\n    }\n\n\n    \/* =========================================================\n       DESTROY ENGINE\n       ========================================================= *\/\n\n    function destroy() {\n\n        destroyed = true;\n\n\n        if (\n            currentInstance\n        ) {\n\n            currentInstance.deactivate();\n\n        }\n\n\n        unlockPage();\n\n\n        instances.forEach(\n            function (\n                instance\n            ) {\n\n                instance.destroy();\n\n            }\n        );\n\n\n        instances = [];\n\n\n        mount.innerHTML = '';\n\n\n        window.removeEventListener(\n            'wheel',\n            onWheel,\n            true\n        );\n\n\n        window.removeEventListener(\n            'touchstart',\n            onTouchStart,\n            true\n        );\n\n\n        window.removeEventListener(\n            'touchmove',\n            onTouchMove,\n            true\n        );\n\n\n        window.removeEventListener(\n            'touchend',\n            onTouchEnd,\n            true\n        );\n\n\n        window.removeEventListener(\n            'keydown',\n            onKeyDown,\n            true\n        );\n\n\n        window.removeEventListener(\n            'scroll',\n            onWindowScroll,\n            true\n        );\n\n\n        window.removeEventListener(\n            'resize',\n            onResize\n        );\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL EVENTS\n       ========================================================= *\/\n\n    window.addEventListener(\n        'wheel',\n        onWheel,\n        {\n            capture: true,\n            passive: false\n        }\n    );\n\n\n    window.addEventListener(\n        'touchstart',\n        onTouchStart,\n        {\n            capture: true,\n            passive: true\n        }\n    );\n\n\n    window.addEventListener(\n        'touchmove',\n        onTouchMove,\n        {\n            capture: true,\n            passive: false\n        }\n    );\n\n\n    window.addEventListener(\n        'touchend',\n        onTouchEnd,\n        {\n            capture: true,\n            passive: true\n        }\n    );\n\n\n    window.addEventListener(\n        'keydown',\n        onKeyDown,\n        true\n    );\n\n\n    window.addEventListener(\n        'scroll',\n        onWindowScroll,\n        true\n    );\n\n\n    window.addEventListener(\n        'resize',\n        onResize\n    );\n\n\n    window.__CG_JSON_MATRYOSHKA_ENGINE__ = {\n\n        destroy: destroy\n\n    };\n\n\n    \/* =========================================================\n       START\n       ========================================================= *\/\n\n    if (\n        document.readyState ===\n        'loading'\n    ) {\n\n        document.addEventListener(\n            'DOMContentLoaded',\n            init,\n            {\n                once: true\n            }\n        );\n\n\n    } else {\n\n        init();\n\n    }\n\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-67d6361 e-flex e-con-boxed e-con e-parent\" data-id=\"67d6361\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-7f62760 e-con-full e-flex e-con e-child\" data-id=\"7f62760\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-61dbd89 elementor-widget elementor-widget-html\" data-id=\"61dbd89\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div\n    class=\"cg-json-engine-mount\"\n    data-manifest=\"https:\/\/stegotool.crypto-grandpa.com.ua\/wp-content\/uploads\/cg-matryoshka\/support-software\/manifest.json\"\n><\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-c4034c3 e-con-full e-flex e-con e-child\" data-id=\"c4034c3\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-0124355 elementor-widget elementor-widget-html\" data-id=\"0124355\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\n\n    \/* =========================================================\n       CG MATRYOSHKA ENGINE\n       DYNAMIC ACTIVE WORKSPACE\n       ========================================================= *\/\n\n    .cg-json-engine-mount {\n        position: relative;\n        width: 100%;\n        box-sizing: border-box;\n        overflow: visible;\n    }\n\n\n    \/* =========================================================\n       GENERATED ROW\n       ========================================================= *\/\n\n    .cg-json-engine-row {\n        width: 100%;\n\n        display: flex;\n        flex-direction: row;\n        flex-wrap: nowrap;\n\n        align-items: stretch;\n\n        gap: 40px;\n\n        box-sizing: border-box;\n\n        margin: 0 0 70px 0;\n\n        overflow: visible;\n\n        transition:\n            min-height 0.34s ease;\n    }\n\n\n    \/*\n     * \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043c\u0430\u0442\u0440\u0451\u0448\u043a\u0430:\n     * \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434 \u0444\u0443\u0442\u0435\u0440\u043e\u043c.\n     *\/\n    .cg-json-engine-row:last-child {\n        margin-bottom: 30px;\n    }\n\n\n    .cg-json-engine-icon-col {\n        flex: 0 0 28%;\n\n        width: 28%;\n        max-width: 28%;\n\n        min-width: 0;\n\n        display: flex;\n\n        align-items: flex-start;\n        justify-content: center;\n\n        box-sizing: border-box;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-content-col {\n        flex: 0 0 68%;\n\n        width: 68%;\n        max-width: 68%;\n\n        min-width: 0;\n\n        box-sizing: border-box;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-source {\n        position: relative;\n\n        width: 100%;\n\n        min-height: 300px;\n\n        overflow: visible;\n    }\n\n\n    \/* =========================================================\n       ICON\n       ========================================================= *\/\n\n    .cg-json-engine-icon-ui {\n        width: 100%;\n\n        display: flex;\n        flex-direction: column;\n\n        align-items: center;\n        justify-content: flex-start;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-icon-button {\n        width: 220px;\n        height: 220px;\n\n        display: flex;\n\n        align-items: center;\n        justify-content: center;\n\n        padding: 0;\n        margin: 0;\n\n        border: 0 !important;\n        outline: 0 !important;\n\n        background: transparent !important;\n\n        box-shadow: none !important;\n\n        cursor: pointer;\n\n        overflow: visible;\n\n        appearance: none;\n        -webkit-appearance: none;\n\n        transition:\n            transform 0.22s ease,\n            filter 0.22s ease;\n    }\n\n\n    .cg-json-engine-icon-image {\n        display: block;\n\n        width: 220px;\n        height: 220px;\n\n        object-fit: contain;\n\n        background: transparent !important;\n\n        mix-blend-mode: normal;\n\n        pointer-events: none;\n    }\n\n\n    .cg-json-engine-icon-button:hover {\n        transform: scale(1.055);\n\n        filter:\n            drop-shadow(\n                0 0 8px\n                rgba(240, 199, 107, 0.55)\n            );\n    }\n\n\n    .cg-json-engine-icon-button.is-active {\n        transform: scale(1.055);\n\n        filter:\n            drop-shadow(\n                0 0 13px\n                rgba(240, 199, 107, 0.75)\n            );\n    }\n\n\n    .cg-json-engine-icon-button:focus,\n    .cg-json-engine-icon-button:active,\n    .cg-json-engine-icon-button:focus-visible {\n        outline: none !important;\n\n        background: transparent !important;\n\n        box-shadow: none !important;\n    }\n\n\n    \/* =========================================================\n       CARD TITLE UNDER ICON\n       ========================================================= *\/\n\n    .cg-json-engine-card-title {\n        width: 250px;\n\n        min-height: 42px;\n\n        margin-top: 12px;\n\n        box-sizing: border-box;\n\n        color: #F0C76B;\n\n        font-size: 13px;\n        font-weight: 700;\n\n        line-height: 1.35;\n\n        letter-spacing: 1px;\n\n        text-align: center;\n        text-transform: uppercase;\n\n        opacity: 0;\n        visibility: hidden;\n\n        transform: translateY(-4px);\n\n        pointer-events: none;\n\n        transition:\n            opacity 0.20s ease,\n            visibility 0.20s ease,\n            transform 0.20s ease;\n    }\n\n\n    .cg-json-engine-card-title.is-visible {\n        opacity: 1;\n        visibility: visible;\n\n        transform: translateY(0);\n    }\n\n\n    \/* =========================================================\n       MATRYOSHKA\n       ========================================================= *\/\n\n    .cg-json-engine-matryoshka {\n        position: relative;\n\n        width: 100%;\n\n        overflow: visible;\n    }\n\n\n    .cg-json-engine-stage {\n        position: relative;\n\n        width: 100%;\n\n        height:\n            var(\n                --cg-cover-height,\n                340px\n            );\n\n        overflow: visible;\n\n        transition:\n            height 0.34s ease;\n    }\n\n\n    .cg-json-engine-matryoshka.is-active\n    .cg-json-engine-stage {\n        height:\n            var(\n                --cg-active-workspace-height,\n                900px\n            );\n    }\n\n\n    .cg-json-engine-matryoshka.is-manual\n    .cg-json-engine-stage {\n        height:\n            var(\n                --cg-manual-workspace-height,\n                900px\n            );\n    }\n\n\n    \/* =========================================================\n       COVER\n       ========================================================= *\/\n\n    .cg-json-engine-cover {\n        position: relative;\n\n        z-index: 300;\n\n        width: 100%;\n\n        height:\n            var(\n                --cg-cover-height,\n                340px\n            );\n\n        box-sizing: border-box;\n\n        padding:\n            34px\n            38px\n            76px\n            38px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.88);\n\n        border-radius: 22px;\n\n        background:\n            linear-gradient(\n                145deg,\n                #0A1E36 0%,\n                #102D50 100%\n            );\n\n        box-shadow:\n            0 18px 45px\n            rgba(0, 0, 0, 0.38);\n\n        color: #FFFFFF;\n\n        overflow: hidden;\n    }\n\n\n    .cg-json-engine-cover-label {\n        margin-bottom: 14px;\n\n        color: #F0C76B;\n\n        font-size: 12px;\n        font-weight: 700;\n\n        line-height: 1.2;\n\n        letter-spacing: 2px;\n\n        text-transform: uppercase;\n    }\n\n\n    .cg-json-engine-cover h3 {\n        margin: 0 0 18px 0;\n\n        color: #F0C76B;\n\n        font-size: 30px;\n        font-weight: 700;\n\n        line-height: 1.15;\n    }\n\n\n    .cg-json-engine-cover p {\n        margin: 0 0 14px 0;\n\n        color: #FFFFFF;\n\n        font-size: 17px;\n\n        line-height: 1.55;\n    }\n\n\n    .cg-json-engine-cover-footer {\n        color: #F0C76B !important;\n\n        font-weight: 600;\n    }\n\n\n    \/* =========================================================\n       SCROLL TO EXPLORE\n       ========================================================= *\/\n\n    .cg-json-engine-hint {\n        position: absolute;\n\n        left: 50%;\n        bottom: 18px;\n\n        z-index: 320;\n\n        display: flex;\n        flex-direction: column;\n\n        align-items: center;\n        justify-content: center;\n\n        gap: 5px;\n\n        transform: translateX(-50%);\n\n        color: #F0C76B;\n\n        font-size: 12px;\n        font-weight: 700;\n\n        line-height: 1.1;\n\n        letter-spacing: 1.6px;\n\n        text-align: center;\n        text-transform: uppercase;\n\n        white-space: nowrap;\n\n        opacity: 0;\n        visibility: hidden;\n\n        pointer-events: none;\n\n        transition:\n            opacity 0.22s ease,\n            visibility 0.22s ease;\n    }\n\n\n    .cg-json-engine-matryoshka.is-active\n    .cg-json-engine-hint {\n        opacity: 1;\n        visibility: visible;\n    }\n\n\n    .cg-json-engine-hint-arrows {\n        display: block;\n\n        color: #F0C76B;\n\n        font-size: 17px;\n        font-weight: 700;\n\n        line-height: 1;\n\n        animation:\n            cgJsonEngineScrollArrow\n            1.35s\n            ease-in-out\n            infinite;\n    }\n\n\n    @keyframes cgJsonEngineScrollArrow {\n\n        0%,\n        100% {\n            opacity: 0.55;\n            transform: translateY(0);\n        }\n\n        50% {\n            opacity: 1;\n            transform: translateY(2px);\n        }\n\n    }\n\n\n    \/* =========================================================\n       CARDS\n       ========================================================= *\/\n\n    .cg-json-engine-card {\n        position: absolute;\n\n        top: 0;\n        left: 0;\n\n        z-index: 200;\n\n        width: 100%;\n\n        height:\n            var(\n                --cg-card-height,\n                340px\n            );\n\n        box-sizing: border-box;\n\n        padding:\n            56px\n            38px\n            30px\n            38px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.84);\n\n        border-radius: 21px;\n\n        background:\n            linear-gradient(\n                145deg,\n                #081A30 0%,\n                #102D50 100%\n            );\n\n        box-shadow:\n            0 16px 38px\n            rgba(0, 0, 0, 0.34);\n\n        color: #FFFFFF;\n\n        opacity: 0;\n\n        pointer-events: none;\n\n        will-change:\n            transform,\n            opacity;\n\n        transition:\n            transform 0.16s linear,\n            opacity 0.14s ease,\n            box-shadow 0.25s ease;\n    }\n\n\n    .cg-json-engine-card h4 {\n        margin: 0 0 16px 0;\n\n        color: #F0C76B;\n\n        font-size: 23px;\n        font-weight: 700;\n\n        line-height: 1.25;\n    }\n\n\n    .cg-json-engine-card p {\n        margin: 0;\n\n        color: #FFFFFF;\n\n        font-size: 17px;\n\n        line-height: 1.58;\n    }\n\n\n    .cg-json-engine-card.is-manual-open {\n        z-index: 420 !important;\n\n        box-shadow:\n            0 23px 60px\n            rgba(0, 0, 0, 0.58);\n\n        transition:\n            transform 0.32s ease,\n            opacity 0.20s ease,\n            box-shadow 0.25s ease;\n    }\n\n\n    \/* =========================================================\n       NUMBERS\n       ========================================================= *\/\n\n    .cg-json-engine-tabs {\n        position: absolute;\n\n        inset: 0;\n\n        z-index: 500;\n\n        pointer-events: none;\n    }\n\n\n    .cg-json-engine-tab {\n        position: absolute;\n\n        top: 0;\n        left: 0;\n\n        min-width: 33px;\n        height: 22px;\n\n        display: flex;\n\n        align-items: center;\n        justify-content: center;\n\n        box-sizing: border-box;\n\n        padding: 0 6px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.95) !important;\n\n        border-radius: 5px;\n\n        background:\n            rgba(7, 26, 51, 0.98) !important;\n\n        color:\n            #F0C76B !important;\n\n        font-size: 10px;\n        font-weight: 700;\n\n        line-height: 1;\n\n        letter-spacing: 0.7px;\n\n        opacity: 0;\n        visibility: hidden;\n\n        pointer-events: none;\n\n        cursor: default;\n\n        appearance: none;\n        -webkit-appearance: none;\n\n        outline: none !important;\n\n        box-shadow: none !important;\n\n        transition:\n            opacity 0.18s ease,\n            background-color 0.18s ease,\n            color 0.18s ease,\n            transform 0.16s linear;\n    }\n\n\n    .cg-json-engine-tab:focus,\n    .cg-json-engine-tab:active,\n    .cg-json-engine-tab:focus-visible {\n        background:\n            rgba(7, 26, 51, 0.98) !important;\n\n        color:\n            #F0C76B !important;\n\n        border-color:\n            #F0C76B !important;\n\n        outline: none !important;\n\n        box-shadow: none !important;\n    }\n\n\n    .cg-json-engine-matryoshka.is-assembled\n    .cg-json-engine-tab {\n        pointer-events: auto;\n\n        cursor: pointer;\n    }\n\n\n    .cg-json-engine-matryoshka.is-assembled\n    .cg-json-engine-tab:hover {\n        background:\n            #F0C76B !important;\n\n        color:\n            #071A33 !important;\n    }\n\n\n    \/* =========================================================\n       ERROR\n       ========================================================= *\/\n\n    .cg-json-engine-error {\n        width: 100%;\n\n        min-height: 260px;\n\n        display: flex;\n        flex-direction: column;\n\n        align-items: center;\n        justify-content: center;\n\n        gap: 10px;\n\n        box-sizing: border-box;\n\n        padding: 30px;\n\n        border:\n            1px solid\n            rgba(240, 199, 107, 0.65);\n\n        border-radius: 22px;\n\n        background: #0A1E36;\n\n        text-align: center;\n    }\n\n\n    .cg-json-engine-error strong {\n        color: #F0C76B;\n    }\n\n\n    .cg-json-engine-error span {\n        color: #FFFFFF;\n    }\n\n\n\n    \/* =========================================================\n       TABLET\n       ========================================================= *\/\n\n    @media (min-width: 768px) and (max-width: 1024px) {\n\n        .cg-json-engine-icon-button,\n        .cg-json-engine-icon-image {\n            width: 180px;\n            height: 180px;\n        }\n\n    }\n\n\n    \/* =========================================================\n       MOBILE\n       ========================================================= *\/\n\n    @media (max-width: 767px) {\n\n        .cg-json-engine-row {\n            flex-direction: column;\n\n            gap: 18px;\n\n            margin-bottom: 55px;\n        }\n\n\n        .cg-json-engine-row:last-child {\n            margin-bottom: 25px;\n        }\n\n\n        .cg-json-engine-icon-col,\n        .cg-json-engine-content-col {\n            flex: 0 0 100%;\n\n            width: 100%;\n            max-width: 100%;\n        }\n\n\n        .cg-json-engine-icon-button,\n        .cg-json-engine-icon-image {\n            width: 140px;\n            height: 140px;\n        }\n\n\n        .cg-json-engine-card-title {\n            width: 190px;\n\n            font-size: 11px;\n        }\n\n\n        .cg-json-engine-cover {\n            padding:\n                26px\n                24px\n                72px\n                24px;\n        }\n\n\n        .cg-json-engine-cover h3 {\n            font-size: 24px;\n        }\n\n\n        .cg-json-engine-cover p,\n        .cg-json-engine-card p {\n            font-size: 15px;\n        }\n\n\n        .cg-json-engine-card {\n            padding:\n                54px\n                26px\n                26px\n                28px;\n        }\n\n\n        .cg-json-engine-card h4 {\n            font-size: 20px;\n        }\n\n    }\n\n<\/style>\n\n\n<script>\n(function () {\n\n    'use strict';\n\n\n    \/* =========================================================\n       DESTROY PREVIOUS VERSION\n       ========================================================= *\/\n\n    if (\n        window.__CG_JSON_MATRYOSHKA_ENGINE__ &&\n        typeof window.__CG_JSON_MATRYOSHKA_ENGINE__.destroy ===\n        'function'\n    ) {\n\n        window.__CG_JSON_MATRYOSHKA_ENGINE__.destroy();\n\n    }\n\n\n    if (\n        window.__CG_JSON_MATRYOSHKA_TEST__ &&\n        typeof window.__CG_JSON_MATRYOSHKA_TEST__.destroy ===\n        'function'\n    ) {\n\n        window.__CG_JSON_MATRYOSHKA_TEST__.destroy();\n\n    }\n\n\n    \/* =========================================================\n       MOUNT\n       ========================================================= *\/\n\n    const mount =\n        document.querySelector(\n            '.cg-json-engine-mount'\n        );\n\n\n    if (!mount) {\n        return;\n    }\n\n\n    const MANIFEST_URL =\n        mount.dataset.manifest || '';\n\n\n    if (!MANIFEST_URL) {\n        return;\n    }\n\n\n    \/* =========================================================\n       SETTINGS\n       ========================================================= *\/\n\n    const STEP = 420;\n\n    const STACK_SHIFT_X = 14;\n    const STACK_SHIFT_Y = 26;\n\n    const TAB_REVEAL_START = 0.55;\n\n    const TAB_LEFT = 11;\n    const TAB_BOTTOM = 1;\n    const TAB_HEIGHT = 22;\n\n    const CENTER_DURATION = 460;\n\n    const HEADER_GAP = 18;\n\n    const UPPER_VIEWPORT_RATIO = 0.12;\n\n    const ENTRY_BELOW_VIEWPORT = 80;\n\n    const MANUAL_GAP = 28;\n\n    const WORKSPACE_BOTTOM_PAD = 60;\n\n\n    \/* =========================================================\n       GLOBAL STATE\n       ========================================================= *\/\n\n    let instances = [];\n\n    let currentInstance = null;\n\n    let pageLocked = false;\n\n    let lockedScrollY = 0;\n\n    let lastTouchY = null;\n\n    let destroyed = false;\n\n\n    const savedPageStyle = {\n\n        htmlOverflow: '',\n        htmlOverscroll: '',\n\n        bodyOverflow: '',\n        bodyOverscroll: '',\n        bodyTouchAction: ''\n\n    };\n\n\n    \/* =========================================================\n       HELPERS\n       ========================================================= *\/\n\n    function clamp(\n        value,\n        min,\n        max\n    ) {\n\n        return Math.min(\n            max,\n            Math.max(\n                min,\n                value\n            )\n        );\n\n    }\n\n\n    function createElement(\n        tag,\n        className,\n        text\n    ) {\n\n        const element =\n            document.createElement(\n                tag\n            );\n\n\n        if (className) {\n            element.className =\n                className;\n        }\n\n\n        if (\n            text !== undefined &&\n            text !== null\n        ) {\n\n            element.textContent =\n                text;\n\n        }\n\n\n        return element;\n\n    }\n\n\n    \/* =========================================================\n       PAGE LOCK\n       ========================================================= *\/\n\n    function lockPage() {\n\n        if (pageLocked) {\n            return;\n        }\n\n\n        const html =\n            document.documentElement;\n\n\n        const body =\n            document.body;\n\n\n        lockedScrollY =\n            window.scrollY;\n\n\n        savedPageStyle.htmlOverflow =\n            html.style.overflow;\n\n\n        savedPageStyle.htmlOverscroll =\n            html.style.overscrollBehavior;\n\n\n        savedPageStyle.bodyOverflow =\n            body.style.overflow;\n\n\n        savedPageStyle.bodyOverscroll =\n            body.style.overscrollBehavior;\n\n\n        savedPageStyle.bodyTouchAction =\n            body.style.touchAction;\n\n\n        html.style.setProperty(\n            'overflow',\n            'hidden',\n            'important'\n        );\n\n\n        html.style.setProperty(\n            'overscroll-behavior',\n            'none',\n            'important'\n        );\n\n\n        body.style.setProperty(\n            'overflow',\n            'hidden',\n            'important'\n        );\n\n\n        body.style.setProperty(\n            'overscroll-behavior',\n            'none',\n            'important'\n        );\n\n\n        body.style.setProperty(\n            'touch-action',\n            'none',\n            'important'\n        );\n\n\n        pageLocked = true;\n\n    }\n\n\n    function unlockPage() {\n\n        if (!pageLocked) {\n            return;\n        }\n\n\n        const html =\n            document.documentElement;\n\n\n        const body =\n            document.body;\n\n\n        html.style.overflow =\n            savedPageStyle.htmlOverflow;\n\n\n        html.style.overscrollBehavior =\n            savedPageStyle.htmlOverscroll;\n\n\n        body.style.overflow =\n            savedPageStyle.bodyOverflow;\n\n\n        body.style.overscrollBehavior =\n            savedPageStyle.bodyOverscroll;\n\n\n        body.style.touchAction =\n            savedPageStyle.bodyTouchAction;\n\n\n        pageLocked = false;\n\n    }\n\n\n    \/* =========================================================\n       MANIFEST VALIDATION\n       ========================================================= *\/\n\n    function validateManifest(\n        manifest\n    ) {\n\n        if (\n            !manifest ||\n            typeof manifest !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Invalid manifest'\n            );\n\n        }\n\n\n        if (\n            !Array.isArray(\n                manifest.sections\n            ) ||\n            manifest.sections.length === 0\n        ) {\n\n            throw new Error(\n                'Manifest sections missing'\n            );\n\n        }\n\n\n        manifest.sections.forEach(\n            function (\n                section,\n                index\n            ) {\n\n                if (\n                    !section ||\n                    !section.source\n                ) {\n\n                    throw new Error(\n                        'Manifest source missing at section ' +\n                        (\n                            index + 1\n                        )\n                    );\n\n                }\n\n            }\n        );\n\n    }\n\n\n    \/* =========================================================\n       SECTION VALIDATION\n       ========================================================= *\/\n\n    function validateSection(\n        data\n    ) {\n\n        if (\n            !data ||\n            typeof data !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Invalid section JSON'\n            );\n\n        }\n\n\n        if (\n            !data.section ||\n            typeof data.section !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Section data missing'\n            );\n\n        }\n\n\n        if (\n            !data.section.id ||\n            !data.section.title\n        ) {\n\n            throw new Error(\n                'Section ID or title missing'\n            );\n\n        }\n\n\n        if (\n            !data.section.icon ||\n            typeof data.section.icon !==\n            'object' ||\n            !data.section.icon.src\n        ) {\n\n            throw new Error(\n                'Section icon missing'\n            );\n\n        }\n\n\n        if (\n            !data.cover ||\n            typeof data.cover !==\n            'object'\n        ) {\n\n            throw new Error(\n                'Cover missing'\n            );\n\n        }\n\n\n        if (\n            !Array.isArray(\n                data.cards\n            ) ||\n            data.cards.length === 0\n        ) {\n\n            throw new Error(\n                'Cards missing'\n            );\n\n        }\n\n\n        data.cards.forEach(\n            function (\n                card,\n                index\n            ) {\n\n                if (\n                    !card ||\n                    !card.title ||\n                    !card.text\n                ) {\n\n                    throw new Error(\n                        'Invalid card ' +\n                        (\n                            index + 1\n                        )\n                    );\n\n                }\n\n            }\n        );\n\n    }\n\n\n    \/* =========================================================\n       MATRYOSHKA INSTANCE\n       ========================================================= *\/\n\n    class MatryoshkaInstance {\n\n        constructor(\n            data\n        ) {\n\n            this.data = data;\n\n            this.row = null;\n\n            this.iconUI = null;\n            this.iconButton = null;\n            this.iconTitle = null;\n\n            this.source = null;\n\n            this.root = null;\n            this.stage = null;\n            this.cover = null;\n\n            this.cards = [];\n            this.tabs = [];\n\n            this.coverHeight = 340;\n            this.cardHeight = 340;\n\n            this.stackHeight = 340;\n\n            this.activeWorkspaceHeight = 900;\n\n            this.manualWorkspaceHeight = 900;\n\n            this.assemblyDistance = 0;\n\n            this.progress = 0;\n\n            this.mode = 'off';\n\n            this.manualIndex = -1;\n\n            this.centerTimer = null;\n\n            this.build();\n\n        }\n\n\n        \/* =====================================================\n           BUILD ROW\n           ===================================================== *\/\n\n        build() {\n\n            this.row =\n                createElement(\n                    'div',\n                    'cg-json-engine-row'\n                );\n\n\n            this.row.dataset.section =\n                this.data.section.id;\n\n\n            const iconCol =\n                createElement(\n                    'div',\n                    'cg-json-engine-icon-col'\n                );\n\n\n            this.iconUI =\n                createElement(\n                    'div',\n                    'cg-json-engine-icon-ui'\n                );\n\n\n            this.iconButton =\n                createElement(\n                    'button',\n                    'cg-json-engine-icon-button'\n                );\n\n\n            this.iconButton.type =\n                'button';\n\n\n            this.iconButton.setAttribute(\n                'aria-expanded',\n                'false'\n            );\n\n\n            this.iconButton.setAttribute(\n\n                'aria-label',\n\n                this.data.section.icon.aria_label ||\n\n                this.data.section.title ||\n\n                'Open section'\n\n            );\n\n\n            const iconImage =\n                createElement(\n                    'img',\n                    'cg-json-engine-icon-image'\n                );\n\n\n            iconImage.src =\n                this.data.section.icon.src;\n\n\n            iconImage.alt =\n                this.data.section.icon.alt ||\n\n                this.data.section.title ||\n\n                '';\n\n\n            this.iconButton.appendChild(\n                iconImage\n            );\n\n\n            this.iconTitle =\n                createElement(\n                    'div',\n                    'cg-json-engine-card-title'\n                );\n\n\n            this.iconTitle.setAttribute(\n                'aria-live',\n                'polite'\n            );\n\n\n            this.iconUI.appendChild(\n                this.iconButton\n            );\n\n\n            this.iconUI.appendChild(\n                this.iconTitle\n            );\n\n\n            iconCol.appendChild(\n                this.iconUI\n            );\n\n\n            const contentCol =\n                createElement(\n                    'div',\n                    'cg-json-engine-content-col'\n                );\n\n\n            this.source =\n                createElement(\n                    'div',\n                    'cg-json-engine-source'\n                );\n\n\n            contentCol.appendChild(\n                this.source\n            );\n\n\n            this.row.appendChild(\n                iconCol\n            );\n\n\n            this.row.appendChild(\n                contentCol\n            );\n\n\n            mount.appendChild(\n                this.row\n            );\n\n\n            this.buildMatryoshka();\n\n\n            this.iconButton.addEventListener(\n                'click',\n                this.onIconClick\n            );\n\n        }\n\n\n        \/* =====================================================\n           BUILD MATRYOSHKA\n           ===================================================== *\/\n\n        buildMatryoshka() {\n\n            this.root =\n                createElement(\n                    'section',\n                    'cg-json-engine-matryoshka'\n                );\n\n\n            this.root.dataset.section =\n                this.data.section.id;\n\n\n            this.stage =\n                createElement(\n                    'div',\n                    'cg-json-engine-stage'\n                );\n\n\n            this.cover =\n                createElement(\n                    'article',\n                    'cg-json-engine-cover'\n                );\n\n\n            if (\n                this.data.cover.label\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'div',\n                        'cg-json-engine-cover-label',\n                        this.data.cover.label\n                    )\n                );\n\n            }\n\n\n            this.cover.appendChild(\n                createElement(\n                    'h3',\n                    '',\n                    this.data.cover.title || ''\n                )\n            );\n\n\n            if (\n                this.data.cover.description\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'p',\n                        '',\n                        this.data.cover.description\n                    )\n                );\n\n            }\n\n\n            if (\n                this.data.cover.secondary_text\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'p',\n                        '',\n                        this.data.cover.secondary_text\n                    )\n                );\n\n            }\n\n\n            if (\n                this.data.cover.footer_text\n            ) {\n\n                this.cover.appendChild(\n                    createElement(\n                        'p',\n                        'cg-json-engine-cover-footer',\n                        this.data.cover.footer_text\n                    )\n                );\n\n            }\n\n\n            const hint =\n                createElement(\n                    'div',\n                    'cg-json-engine-hint'\n                );\n\n\n            hint.appendChild(\n                createElement(\n                    'span',\n                    '',\n                    'SCROLL TO EXPLORE'\n                )\n            );\n\n\n            hint.appendChild(\n                createElement(\n                    'span',\n                    'cg-json-engine-hint-arrows',\n                    '\u2191\u2193'\n                )\n            );\n\n\n            this.cover.appendChild(\n                hint\n            );\n\n\n            this.stage.appendChild(\n                this.cover\n            );\n\n\n            this.cards = [];\n\n\n            this.data.cards.forEach(\n                (\n                    cardData,\n                    index\n                ) => {\n\n                    const card =\n                        createElement(\n                            'article',\n                            'cg-json-engine-card'\n                        );\n\n\n                    card.dataset.cardIndex =\n                        String(index);\n\n\n                    card.dataset.cardTitle =\n                        cardData.title;\n\n\n                    card.appendChild(\n                        createElement(\n                            'h4',\n                            '',\n                            cardData.title\n                        )\n                    );\n\n\n                    card.appendChild(\n                        createElement(\n                            'p',\n                            '',\n                            cardData.text\n                        )\n                    );\n\n\n                    this.stage.appendChild(\n                        card\n                    );\n\n\n                    this.cards.push(\n                        card\n                    );\n\n                }\n            );\n\n\n            const tabsLayer =\n                createElement(\n                    'div',\n                    'cg-json-engine-tabs'\n                );\n\n\n            this.tabs = [];\n\n\n            this.data.cards.forEach(\n                (\n                    cardData,\n                    index\n                ) => {\n\n                    const tab =\n                        createElement(\n                            'button',\n                            'cg-json-engine-tab',\n                            String(\n                                index + 1\n                            ).padStart(\n                                2,\n                                '0'\n                            )\n                        );\n\n\n                    tab.type =\n                        'button';\n\n\n                    tab.dataset.cardIndex =\n                        String(index);\n\n\n                    tab.setAttribute(\n                        'aria-label',\n                        cardData.title\n                    );\n\n\n                    tab.tabIndex =\n                        -1;\n\n\n                    tabsLayer.appendChild(\n                        tab\n                    );\n\n\n                    this.tabs.push(\n                        tab\n                    );\n\n                }\n            );\n\n\n            this.stage.appendChild(\n                tabsLayer\n            );\n\n\n            this.root.appendChild(\n                this.stage\n            );\n\n\n            this.source.appendChild(\n                this.root\n            );\n\n\n            this.bindCardEvents();\n\n\n            this.measure();\n\n        }\n\n\n        \/* =====================================================\n           DYNAMIC WORKSPACE MEASUREMENT\n           ===================================================== *\/\n\n        measure() {\n\n            if (\n                !this.cover ||\n                !this.cards.length\n            ) {\n\n                return;\n\n            }\n\n\n            this.cover.style.height =\n                'auto';\n\n\n            this.cards.forEach(\n                function (\n                    card\n                ) {\n\n                    card.style.height =\n                        'auto';\n\n                }\n            );\n\n\n            this.coverHeight =\n                Math.max(\n\n                    300,\n\n                    Math.ceil(\n                        this.cover.scrollHeight\n                    )\n\n                );\n\n\n            this.cardHeight =\n                this.coverHeight;\n\n\n            this.cards.forEach(\n                (\n                    card\n                ) => {\n\n                    this.cardHeight =\n                        Math.max(\n\n                            this.cardHeight,\n\n                            Math.ceil(\n                                card.scrollHeight\n                            )\n\n                        );\n\n                }\n            );\n\n\n            this.coverHeight =\n                Math.max(\n                    this.coverHeight,\n                    this.cardHeight\n                );\n\n\n            this.cardHeight =\n                this.coverHeight;\n\n\n            this.cover.style.height =\n                '';\n\n\n            this.cards.forEach(\n                function (\n                    card\n                ) {\n\n                    card.style.height =\n                        '';\n\n                }\n            );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-cover-height',\n\n                this.coverHeight +\n                'px'\n\n            );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-card-height',\n\n                this.cardHeight +\n                'px'\n\n            );\n\n\n            this.stackHeight =\n\n                this.coverHeight +\n\n                (\n                    STACK_SHIFT_Y *\n                    this.cards.length\n                ) +\n\n                WORKSPACE_BOTTOM_PAD;\n\n\n            const entryY =\n                this.getEntryY();\n\n\n            const travelHeight =\n\n                entryY +\n\n                this.cardHeight +\n\n                WORKSPACE_BOTTOM_PAD;\n\n\n            this.activeWorkspaceHeight =\n\n                Math.max(\n\n                    this.stackHeight,\n\n                    travelHeight\n\n                );\n\n\n            const manualCardBottom =\n\n                this.coverHeight +\n\n                MANUAL_GAP +\n\n                this.cardHeight +\n\n                WORKSPACE_BOTTOM_PAD;\n\n\n            this.manualWorkspaceHeight =\n\n                Math.max(\n\n                    this.activeWorkspaceHeight,\n\n                    manualCardBottom\n\n                );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-active-workspace-height',\n\n                this.activeWorkspaceHeight +\n                'px'\n\n            );\n\n\n            this.stage.style.setProperty(\n\n                '--cg-manual-workspace-height',\n\n                this.manualWorkspaceHeight +\n                'px'\n\n            );\n\n\n            this.iconUI.style.minHeight =\n                this.coverHeight +\n                'px';\n\n\n            this.iconUI.style.justifyContent =\n                'center';\n\n\n            this.assemblyDistance =\n\n                STEP *\n                this.cards.length;\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           ENTRY POSITION\n           ===================================================== *\/\n\n        getEntryY() {\n\n            const rect =\n                this.stage\n                    .getBoundingClientRect();\n\n\n            return Math.max(\n\n                this.coverHeight +\n                240,\n\n                window.innerHeight -\n                rect.top +\n                ENTRY_BELOW_VIEWPORT\n\n            );\n\n        }\n\n\n        \/* =====================================================\n           ICON TITLE\n           ===================================================== *\/\n\n        setIconTitle(\n            text\n        ) {\n\n            this.iconTitle.textContent =\n                text || '';\n\n\n            this.iconTitle.classList.toggle(\n                'is-visible',\n                Boolean(text)\n            );\n\n        }\n\n\n        \/* =====================================================\n           UPDATE CARDS\n           ===================================================== *\/\n\n        updateCards() {\n\n            if (\n                !this.root ||\n                !this.stage\n            ) {\n\n                return;\n\n            }\n\n\n            const active =\n                this.mode ===\n                'active';\n\n\n            const assembled =\n\n                active &&\n\n                this.progress >=\n                this.assemblyDistance -\n                0.5;\n\n\n            this.root.classList.toggle(\n                'is-active',\n                active\n            );\n\n\n            this.root.classList.toggle(\n                'is-assembled',\n                assembled\n            );\n\n\n            this.root.classList.toggle(\n                'is-manual',\n                this.manualIndex !==\n                -1\n            );\n\n\n            this.row.classList.toggle(\n                'is-active-row',\n                active\n            );\n\n\n            this.iconButton.classList.toggle(\n                'is-active',\n                active\n            );\n\n\n            this.iconButton.setAttribute(\n\n                'aria-expanded',\n\n                active\n                    ?\n                    'true'\n                    :\n                    'false'\n\n            );\n\n\n            const entryY =\n                this.getEntryY();\n\n\n            this.cards.forEach(\n                (\n                    card,\n                    index\n                ) => {\n\n                    const segmentStart =\n\n                        index *\n                        STEP;\n\n\n                    const local =\n\n                        active\n\n                            ?\n\n                            clamp(\n\n                                (\n                                    this.progress -\n                                    segmentStart\n                                ) \/\n                                STEP,\n\n                                0,\n                                1\n\n                            )\n\n                            :\n\n                            0;\n\n\n                    const finalX =\n\n                        -STACK_SHIFT_X *\n                        (\n                            index +\n                            1\n                        );\n\n\n                    const finalY =\n\n                        STACK_SHIFT_Y *\n                        (\n                            index +\n                            1\n                        );\n\n\n                    let x =\n                        finalX *\n                        local;\n\n\n                    let y =\n\n                        entryY +\n\n                        (\n                            (\n                                finalY -\n                                entryY\n                            ) *\n                            local\n                        );\n\n\n                    let opacity =\n\n                        local <= 0\n\n                            ?\n\n                            0\n\n                            :\n\n                            clamp(\n                                local *\n                                1.55,\n                                0,\n                                1\n                            );\n\n\n                    let scale =\n\n                        0.988 +\n\n                        (\n                            0.012 *\n                            local\n                        );\n\n\n                    let zIndex =\n\n                        250 -\n                        index;\n\n\n                    if (\n                        assembled &&\n                        this.manualIndex ===\n                        index\n                    ) {\n\n                        x = 0;\n\n\n                        y =\n\n                            this.coverHeight +\n                            MANUAL_GAP;\n\n\n                        opacity = 1;\n\n                        scale = 1;\n\n                        zIndex = 420;\n\n\n                        card.classList.add(\n                            'is-manual-open'\n                        );\n\n                    } else {\n\n                        card.classList.remove(\n                            'is-manual-open'\n                        );\n\n                    }\n\n\n                    card.style.transform =\n\n                        'translate3d(' +\n\n                        x +\n                        'px,' +\n\n                        y +\n                        'px,0) scale(' +\n\n                        scale +\n\n                        ')';\n\n\n                    card.style.opacity =\n                        String(opacity);\n\n\n                    card.style.zIndex =\n                        String(zIndex);\n\n\n                    card.style.pointerEvents =\n\n                        this.manualIndex ===\n                        index\n\n                            ?\n\n                            'auto'\n\n                            :\n\n                            'none';\n\n\n                    const reveal =\n\n                        clamp(\n\n                            (\n                                local -\n                                TAB_REVEAL_START\n                            ) \/\n\n                            (\n                                1 -\n                                TAB_REVEAL_START\n                            ),\n\n                            0,\n                            1\n\n                        );\n\n\n                    let tabX =\n\n                        x +\n                        TAB_LEFT;\n\n\n                    let tabY =\n\n                        y +\n\n                        this.cardHeight -\n\n                        TAB_BOTTOM -\n\n                        TAB_HEIGHT;\n\n\n                    if (\n                        assembled &&\n                        this.manualIndex ===\n                        index\n                    ) {\n\n                        tabX =\n                            TAB_LEFT;\n\n\n                        tabY =\n\n                            this.coverHeight +\n\n                            MANUAL_GAP +\n\n                            this.cardHeight -\n\n                            TAB_BOTTOM -\n\n                            TAB_HEIGHT;\n\n                    }\n\n\n                    this.tabs[\n                        index\n                    ].style.transform =\n\n                        'translate3d(' +\n\n                        tabX +\n                        'px,' +\n\n                        tabY +\n                        'px,0)';\n\n\n                    this.tabs[\n                        index\n                    ].style.opacity =\n                        String(reveal);\n\n\n                    this.tabs[\n                        index\n                    ].style.visibility =\n\n                        reveal >\n                        0.02\n\n                            ?\n\n                            'visible'\n\n                            :\n\n                            'hidden';\n\n\n                    this.tabs[\n                        index\n                    ].tabIndex =\n\n                        assembled\n\n                            ?\n\n                            0\n\n                            :\n\n                            -1;\n\n                }\n            );\n\n\n            if (\n                !assembled &&\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.manualIndex = -1;\n\n\n                this.setIconTitle(\n                    ''\n                );\n\n\n                this.root.classList.remove(\n                    'is-manual'\n                );\n\n            }\n\n        }\n\n\n        \/* =====================================================\n           CARD EVENTS\n           ===================================================== *\/\n\n        bindCardEvents() {\n\n            this.tabs.forEach(\n                (\n                    tab,\n                    index\n                ) => {\n\n                    tab.addEventListener(\n                        'mouseenter',\n                        () => {\n\n                            if (\n                                this.mode ===\n                                'active' &&\n\n                                this.progress >=\n                                this.assemblyDistance -\n                                0.5\n                            ) {\n\n                                this.setIconTitle(\n\n                                    this.cards[\n                                        index\n                                    ].dataset.cardTitle ||\n\n                                    ''\n\n                                );\n\n                            }\n\n                        }\n                    );\n\n\n                    tab.addEventListener(\n                        'mouseleave',\n                        () => {\n\n                            if (\n                                this.manualIndex ===\n                                -1\n                            ) {\n\n                                this.setIconTitle(\n                                    ''\n                                );\n\n                            }\n\n                        }\n                    );\n\n\n                    tab.addEventListener(\n                        'click',\n                        (\n                            event\n                        ) => {\n\n                            event.preventDefault();\n\n                            event.stopPropagation();\n\n\n                            if (\n                                this.manualIndex ===\n                                index\n                            ) {\n\n                                this.closeManual();\n\n                            } else {\n\n                                this.openManual(\n                                    index\n                                );\n\n                            }\n\n                        }\n                    );\n\n\n                    this.cards[\n                        index\n                    ].addEventListener(\n                        'click',\n                        () => {\n\n                            if (\n                                this.manualIndex ===\n                                index\n                            ) {\n\n                                this.closeManual();\n\n                            }\n\n                        }\n                    );\n\n                }\n            );\n\n        }\n\n\n        \/* =====================================================\n           MANUAL CARD\n           ===================================================== *\/\n\n        openManual(\n            index\n        ) {\n\n            if (\n                this.mode !==\n                'active' ||\n\n                this.progress <\n                this.assemblyDistance -\n                0.5\n            ) {\n\n                return;\n\n            }\n\n\n            this.manualIndex =\n                index;\n\n\n            this.setIconTitle(\n\n                this.cards[\n                    index\n                ].dataset.cardTitle ||\n\n                ''\n\n            );\n\n\n            this.updateCards();\n\n        }\n\n\n        closeManual() {\n\n            if (\n                this.manualIndex ===\n                -1\n            ) {\n\n                return;\n\n            }\n\n\n            this.manualIndex = -1;\n\n\n            this.setIconTitle(\n                ''\n            );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           HEADER \/ TARGET POSITION\n           ===================================================== *\/\n\n        getHeaderBottom() {\n\n            const header =\n                document.querySelector(\n                    '#masthead'\n                );\n\n\n            if (!header) {\n                return 0;\n            }\n\n\n            return Math.max(\n\n                0,\n\n                header\n                    .getBoundingClientRect()\n                    .bottom\n\n            );\n\n        }\n\n\n        getTargetY() {\n\n            const rect =\n                this.row\n                    .getBoundingClientRect();\n\n\n            const desiredTop =\n\n                Math.max(\n\n                    this.getHeaderBottom() +\n                    HEADER_GAP,\n\n                    window.innerHeight *\n                    UPPER_VIEWPORT_RATIO\n\n                );\n\n\n            return Math.max(\n\n                0,\n\n                window.scrollY +\n                rect.top -\n                desiredTop\n\n            );\n\n        }\n\n\n        \/* =====================================================\n           ACTIVATE\n           ===================================================== *\/\n\n        activate() {\n\n            if (\n                this.mode !==\n                'off'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                currentInstance &&\n                currentInstance !==\n                this\n            ) {\n\n                currentInstance.deactivate();\n\n            }\n\n\n            currentInstance =\n                this;\n\n\n            this.mode =\n                'centering';\n\n\n            this.progress = 0;\n\n            this.manualIndex = -1;\n\n\n            this.setIconTitle(\n                ''\n            );\n\n\n            this.measure();\n\n\n            const target =\n                this.getTargetY();\n\n\n            window.scrollTo({\n\n                top: target,\n\n                behavior: 'smooth'\n\n            });\n\n\n            clearTimeout(\n                this.centerTimer\n            );\n\n\n            this.centerTimer =\n                window.setTimeout(\n                    () => {\n\n                        if (\n                            destroyed ||\n\n                            currentInstance !==\n                            this ||\n\n                            this.mode !==\n                            'centering'\n                        ) {\n\n                            return;\n\n                        }\n\n\n                        window.scrollTo(\n                            0,\n                            target\n                        );\n\n\n                        this.measure();\n\n\n                        lockPage();\n\n\n                        this.mode =\n                            'active';\n\n\n                        this.updateCards();\n\n                    },\n\n                    CENTER_DURATION\n                );\n\n        }\n\n\n        \/* =====================================================\n           DEACTIVATE\n           ===================================================== *\/\n\n        deactivate() {\n\n            clearTimeout(\n                this.centerTimer\n            );\n\n\n            this.mode =\n                'off';\n\n\n            this.progress =\n                0;\n\n\n            this.manualIndex =\n                -1;\n\n\n            this.setIconTitle(\n                ''\n            );\n\n\n            this.updateCards();\n\n\n            if (\n                currentInstance ===\n                this\n            ) {\n\n                currentInstance =\n                    null;\n\n\n                unlockPage();\n\n            }\n\n        }\n\n\n        \/* =====================================================\n           WHEEL\n           ===================================================== *\/\n\n        handleWheel(\n            event\n        ) {\n\n            if (\n                this.mode !==\n                'active'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.closeManual();\n\n                return;\n\n            }\n\n\n            let delta =\n                event.deltaY;\n\n\n            if (\n                event.deltaMode ===\n                1\n            ) {\n\n                delta *= 18;\n\n            }\n\n\n            if (\n                event.deltaMode ===\n                2\n            ) {\n\n                delta *=\n                    window.innerHeight;\n\n            }\n\n\n            delta =\n                clamp(\n                    delta,\n                    -140,\n                    140\n                );\n\n\n            this.progress =\n                clamp(\n\n                    this.progress +\n                    delta,\n\n                    0,\n\n                    this.assemblyDistance\n\n                );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           TOUCH\n           ===================================================== *\/\n\n        handleTouchDelta(\n            delta\n        ) {\n\n            if (\n                this.mode !==\n                'active'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.closeManual();\n\n                return;\n\n            }\n\n\n            this.progress =\n                clamp(\n\n                    this.progress +\n\n                    delta *\n                    2.2,\n\n                    0,\n\n                    this.assemblyDistance\n\n                );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           KEYBOARD\n           ===================================================== *\/\n\n        handleKeyDelta(\n            delta\n        ) {\n\n            if (\n                this.mode !==\n                'active'\n            ) {\n\n                return;\n\n            }\n\n\n            if (\n                this.manualIndex !==\n                -1\n            ) {\n\n                this.closeManual();\n\n                return;\n\n            }\n\n\n            this.progress =\n                clamp(\n\n                    this.progress +\n                    delta,\n\n                    0,\n\n                    this.assemblyDistance\n\n                );\n\n\n            this.updateCards();\n\n        }\n\n\n        \/* =====================================================\n           ICON CLICK\n           ===================================================== *\/\n\n        onIconClick =\n            (\n                event\n            ) => {\n\n                event.preventDefault();\n\n\n                if (\n                    this.mode ===\n                    'off'\n                ) {\n\n                    this.activate();\n\n                } else {\n\n                    this.deactivate();\n\n                }\n\n            };\n\n\n        \/* =====================================================\n           DESTROY\n           ===================================================== *\/\n\n        destroy() {\n\n            clearTimeout(\n                this.centerTimer\n            );\n\n\n            this.iconButton.removeEventListener(\n                'click',\n                this.onIconClick\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       ERROR ROW\n       ========================================================= *\/\n\n    function createErrorRow(\n        title,\n        detail\n    ) {\n\n        const row =\n            createElement(\n                'div',\n                'cg-json-engine-row'\n            );\n\n\n        const iconCol =\n            createElement(\n                'div',\n                'cg-json-engine-icon-col'\n            );\n\n\n        const contentCol =\n            createElement(\n                'div',\n                'cg-json-engine-content-col'\n            );\n\n\n        const box =\n            createElement(\n                'div',\n                'cg-json-engine-error'\n            );\n\n\n        box.appendChild(\n            createElement(\n                'strong',\n                '',\n                title\n            )\n        );\n\n\n        box.appendChild(\n            createElement(\n                'span',\n                '',\n                detail\n            )\n        );\n\n\n        contentCol.appendChild(\n            box\n        );\n\n\n        row.appendChild(\n            iconCol\n        );\n\n\n        row.appendChild(\n            contentCol\n        );\n\n\n        mount.appendChild(\n            row\n        );\n\n    }\n\n\n    \/* =========================================================\n       FETCH JSON\n       ========================================================= *\/\n\n    async function fetchJson(\n        url\n    ) {\n\n        const response =\n            await fetch(\n                url,\n                {\n                    cache: 'no-store'\n                }\n            );\n\n\n        if (\n            !response.ok\n        ) {\n\n            throw new Error(\n                'HTTP ' +\n                response.status\n            );\n\n        }\n\n\n        return await response.json();\n\n    }\n\n\n    \/* =========================================================\n       INIT\n       ========================================================= *\/\n\n    async function init() {\n\n        try {\n\n            mount.innerHTML = '';\n\n\n            const manifest =\n                await fetchJson(\n                    MANIFEST_URL\n                );\n\n\n            validateManifest(\n                manifest\n            );\n\n\n            for (\n                let index = 0;\n                index <\n                manifest.sections.length;\n                index++\n            ) {\n\n                const item =\n                    manifest.sections[\n                        index\n                    ];\n\n\n                try {\n\n                    const sectionUrl =\n                        new URL(\n                            item.source,\n                            MANIFEST_URL\n                        ).href;\n\n\n                    const data =\n                        await fetchJson(\n                            sectionUrl\n                        );\n\n\n                    validateSection(\n                        data\n                    );\n\n\n                    const instance =\n                        new MatryoshkaInstance(\n                            data\n                        );\n\n\n                    instances.push(\n                        instance\n                    );\n\n\n                } catch (\n                    sectionError\n                ) {\n\n                    console.error(\n                        '[CG MATRYOSHKA SECTION]',\n                        sectionError\n                    );\n\n\n                    createErrorRow(\n\n                        'SECTION ' +\n                        String(\n                            index + 1\n                        ).padStart(\n                            2,\n                            '0'\n                        ) +\n                        ' COULD NOT BE LOADED',\n\n                        item.source\n\n                    );\n\n                }\n\n            }\n\n\n        } catch (\n            error\n        ) {\n\n            console.error(\n                '[CG MATRYOSHKA ENGINE]',\n                error\n            );\n\n\n            createErrorRow(\n\n                'MATRYOSHKA ENGINE COULD NOT START',\n\n                String(\n                    error.message ||\n                    error\n                )\n\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL WHEEL\n       ========================================================= *\/\n\n    function onWheel(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode ===\n            'off'\n        ) {\n\n            return;\n\n        }\n\n\n        event.preventDefault();\n\n\n        if (\n            currentInstance.mode ===\n            'active'\n        ) {\n\n            currentInstance.handleWheel(\n                event\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL TOUCH\n       ========================================================= *\/\n\n    function onTouchStart(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode !==\n            'active' ||\n            !event.touches ||\n            event.touches.length !==\n            1\n        ) {\n\n            return;\n\n        }\n\n\n        lastTouchY =\n            event.touches[\n                0\n            ].clientY;\n\n    }\n\n\n    function onTouchMove(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode !==\n            'active' ||\n            !event.touches ||\n            event.touches.length !==\n            1\n        ) {\n\n            return;\n\n        }\n\n\n        event.preventDefault();\n\n\n        const currentY =\n            event.touches[\n                0\n            ].clientY;\n\n\n        const delta =\n\n            lastTouchY -\n            currentY;\n\n\n        lastTouchY =\n            currentY;\n\n\n        currentInstance.handleTouchDelta(\n            delta\n        );\n\n    }\n\n\n    function onTouchEnd() {\n\n        lastTouchY = null;\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL KEYBOARD\n       ========================================================= *\/\n\n    function onKeyDown(\n        event\n    ) {\n\n        if (\n            !currentInstance ||\n            currentInstance.mode ===\n            'off'\n        ) {\n\n            return;\n\n        }\n\n\n        let delta = null;\n\n\n        if (\n            event.key ===\n            'ArrowDown'\n        ) {\n\n            delta = 120;\n\n\n        } else if (\n            event.key ===\n            'ArrowUp'\n        ) {\n\n            delta = -120;\n\n\n        } else if (\n            event.key ===\n            'PageDown' ||\n            event.key ===\n            ' '\n        ) {\n\n            delta = 320;\n\n\n        } else if (\n            event.key ===\n            'PageUp'\n        ) {\n\n            delta = -320;\n\n\n        } else if (\n            event.key ===\n            'Home'\n        ) {\n\n            event.preventDefault();\n\n\n            currentInstance.closeManual();\n\n\n            currentInstance.progress = 0;\n\n\n            currentInstance.updateCards();\n\n\n            return;\n\n\n        } else if (\n            event.key ===\n            'End'\n        ) {\n\n            event.preventDefault();\n\n\n            currentInstance.closeManual();\n\n\n            currentInstance.progress =\n                currentInstance\n                    .assemblyDistance;\n\n\n            currentInstance.updateCards();\n\n\n            return;\n\n\n        } else if (\n            event.key ===\n            'Escape'\n        ) {\n\n            event.preventDefault();\n\n\n            currentInstance.deactivate();\n\n\n            return;\n\n\n        } else {\n\n            return;\n\n        }\n\n\n        event.preventDefault();\n\n\n        if (\n            currentInstance &&\n            currentInstance.mode ===\n            'active'\n        ) {\n\n            currentInstance.handleKeyDelta(\n                delta\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       SCROLL GUARD\n       ========================================================= *\/\n\n    function onWindowScroll() {\n\n        if (\n            pageLocked &&\n            currentInstance &&\n            currentInstance.mode ===\n            'active' &&\n            Math.abs(\n                window.scrollY -\n                lockedScrollY\n            ) >\n            1\n        ) {\n\n            window.scrollTo(\n                0,\n                lockedScrollY\n            );\n\n        }\n\n    }\n\n\n    \/* =========================================================\n       RESIZE\n       ========================================================= *\/\n\n    function onResize() {\n\n        instances.forEach(\n            function (\n                instance\n            ) {\n\n                instance.measure();\n\n            }\n        );\n\n    }\n\n\n    \/* =========================================================\n       DESTROY ENGINE\n       ========================================================= *\/\n\n    function destroy() {\n\n        destroyed = true;\n\n\n        if (\n            currentInstance\n        ) {\n\n            currentInstance.deactivate();\n\n        }\n\n\n        unlockPage();\n\n\n        instances.forEach(\n            function (\n                instance\n            ) {\n\n                instance.destroy();\n\n            }\n        );\n\n\n        instances = [];\n\n\n        mount.innerHTML = '';\n\n\n        window.removeEventListener(\n            'wheel',\n            onWheel,\n            true\n        );\n\n\n        window.removeEventListener(\n            'touchstart',\n            onTouchStart,\n            true\n        );\n\n\n        window.removeEventListener(\n            'touchmove',\n            onTouchMove,\n            true\n        );\n\n\n        window.removeEventListener(\n            'touchend',\n            onTouchEnd,\n            true\n        );\n\n\n        window.removeEventListener(\n            'keydown',\n            onKeyDown,\n            true\n        );\n\n\n        window.removeEventListener(\n            'scroll',\n            onWindowScroll,\n            true\n        );\n\n\n        window.removeEventListener(\n            'resize',\n            onResize\n        );\n\n    }\n\n\n    \/* =========================================================\n       GLOBAL EVENTS\n       ========================================================= *\/\n\n    window.addEventListener(\n        'wheel',\n        onWheel,\n        {\n            capture: true,\n            passive: false\n        }\n    );\n\n\n    window.addEventListener(\n        'touchstart',\n        onTouchStart,\n        {\n            capture: true,\n            passive: true\n        }\n    );\n\n\n    window.addEventListener(\n        'touchmove',\n        onTouchMove,\n        {\n            capture: true,\n            passive: false\n        }\n    );\n\n\n    window.addEventListener(\n        'touchend',\n        onTouchEnd,\n        {\n            capture: true,\n            passive: true\n        }\n    );\n\n\n    window.addEventListener(\n        'keydown',\n        onKeyDown,\n        true\n    );\n\n\n    window.addEventListener(\n        'scroll',\n        onWindowScroll,\n        true\n    );\n\n\n    window.addEventListener(\n        'resize',\n        onResize\n    );\n\n\n    window.__CG_JSON_MATRYOSHKA_ENGINE__ = {\n\n        destroy: destroy\n\n    };\n\n\n    \/* =========================================================\n       START\n       ========================================================= *\/\n\n    if (\n        document.readyState ===\n        'loading'\n    ) {\n\n        document.addEventListener(\n            'DOMContentLoaded',\n            init,\n            {\n                once: true\n            }\n        );\n\n\n    } else {\n\n        init();\n\n    }\n\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>BUILDING DIGITAL TOOLS FOR EDUCATION SUPPORT OUR SOFTWARE Help us develop practical educational software, digital tools and technologies that turn knowledge and experience into real opportunities. ONGOING CHARITABLE SUPPORT ONGOING CHARITABLE SUPPORT PROGRAM Crypto-Grandpa\u2122 Ukraine Foundation conducts ongoing charitable fundraising to support the implementation and development of its charitable, educational, social and technological programs. Your [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_surecart_dashboard_logo_width":"180px","_surecart_dashboard_show_logo":true,"_surecart_dashboard_navigation_orders":true,"_surecart_dashboard_navigation_invoices":true,"_surecart_dashboard_navigation_subscriptions":true,"_surecart_dashboard_navigation_downloads":true,"_surecart_dashboard_navigation_billing":true,"_surecart_dashboard_navigation_account":true,"site-sidebar-layout":"no-sidebar","site-content-layout":"page-builder","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"enabled","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-1851","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/pages\/1851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/comments?post=1851"}],"version-history":[{"count":273,"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/pages\/1851\/revisions"}],"predecessor-version":[{"id":3504,"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/pages\/1851\/revisions\/3504"}],"wp:attachment":[{"href":"https:\/\/stegotool.crypto-grandpa.com.ua\/ua\/wp-json\/wp\/v2\/media?parent=1851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}