mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 16:42:27 +00:00
* feat(catalog): play the real composition on catalog pages Catalog previews were uploaded MP4s, published by hand to the CDN. Each page now embeds the composition itself, running in <hyperframes-player>, so a preview is the block rather than a recording of it. The composition is delivered as JSON under docs/public/catalog, and the player is mounted inside an iframe. Both are forced: the docs host publishes only JSON and images out of docs/public, and its MDX renderer strips unknown custom elements, so a player written into the page never reaches the DOM and an .html payload 404s in production. Assets are inlined as data URIs, which sidesteps the file-type restriction for fonts, scripts and models alike. 164 of 168 items build a payload; the rest keep their MP4 and say so. * chore: rebuild docs preview * chore: route isolation probe * chore: drop the route isolation probe page * chore: probe which asset types the docs host publishes * refactor(catalog): host preview assets instead of inlining them Fonts were being base64'd into every payload that used them, so a handful of files cost tens of megabytes in the repository to say the same thing over and over. Assets are now written once, content-addressed, under docs/public/catalog/assets and linked. Which types can be hosted was settled by fetching one file of each from a deployed preview: woff2, wav, mp4, svg and the image formats are published, glb is not. Types the host drops still travel inside the payload, because a link that 404s is worse than a larger payload. Also fixes the four type errors the scripts typecheck caught, all of them unchecked index access on a split() result. * refactor(catalog): share preview assets instead of repeating them * style: format the asset module
1 line
41 KiB
JSON
1 line
41 KiB
JSON
{"html":"<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=1920, height=1080\" />\n <title>Blue Sweater Intro Video</title>\n <script src=\"https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js\"></script>\n <style>\n :root {\n --bg: #f7f1ef;\n --ink: #11110f;\n --muted: #807d76;\n --line: #dcd8cf;\n --panel: #fbfaf6;\n --claude: #c85f45;\n --orange: #c86532;\n --blue: #1486b8;\n --panel-shadow: rgba(36, 31, 24, 0.08);\n }\n\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n html,\n body {\n width: 1920px;\n height: 1080px;\n overflow: hidden;\n background: var(--bg);\n color: var(--ink);\n font-family: \"Helvetica Neue\", Arial, sans-serif;\n }\n\n #root {\n position: relative;\n width: 1920px;\n height: 1080px;\n overflow: hidden;\n background: var(--bg);\n isolation: isolate;\n }\n\n .clip,\n .base {\n position: absolute;\n inset: 0;\n overflow: hidden;\n }\n\n .clip {\n opacity: 0;\n }\n\n .base {\n background: var(--bg);\n opacity: 1;\n }\n\n #burst {\n z-index: 6;\n }\n\n #brand {\n z-index: 5;\n }\n\n .scene-content {\n position: relative;\n display: flex;\n width: 100%;\n height: 100%;\n padding: 126px 160px 128px;\n align-items: center;\n justify-content: center;\n }\n\n .warm-block {\n width: 720px;\n height: 154px;\n background: var(--orange);\n border-radius: 6px;\n clip-path: polygon(2% 4%, 98% 0, 100% 88%, 96% 98%, 4% 94%, 0 12%);\n }\n\n .title {\n color: var(--ink);\n font-size: 100px;\n font-weight: 620;\n line-height: 0.92;\n letter-spacing: -0.055em;\n white-space: nowrap;\n }\n\n .wordmark {\n position: absolute;\n left: 50%;\n top: 50.5%;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: baseline;\n gap: 19px;\n color: var(--ink);\n font-size: 88px;\n font-weight: 620;\n line-height: 0.9;\n letter-spacing: -0.058em;\n white-space: nowrap;\n }\n\n .brand-algrow {\n font-weight: 650;\n }\n\n .brand-claude {\n font-weight: 540;\n }\n\n .wordmark .brand-x {\n font-family: Georgia, \"Times New Roman\", serif;\n font-size: 0.84em;\n font-weight: 400;\n letter-spacing: -0.02em;\n }\n\n .cursor {\n position: absolute;\n left: 0;\n top: 0;\n z-index: 20;\n width: 98px;\n height: 120px;\n opacity: 0;\n filter: drop-shadow(0 10px 22px rgba(20, 134, 184, 0.24));\n transform-origin: 13px 6px;\n }\n\n .cursor svg,\n .claude-star svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .claude-star {\n position: absolute;\n color: var(--claude);\n }\n\n .star-center {\n left: 960px;\n top: 530px;\n width: 150px;\n height: 150px;\n transform: translate(-50%, -50%);\n }\n\n .star-brand {\n left: 1084px;\n top: 482px;\n width: 24px;\n height: 24px;\n }\n\n .star-panel {\n left: 398px;\n top: 272px;\n width: 42px;\n height: 42px;\n }\n\n .burst-block {\n position: absolute;\n background: var(--orange);\n border-radius: 9px;\n clip-path: polygon(\n 2% 8%,\n 14% 4%,\n 42% 5%,\n 63% 2%,\n 92% 5%,\n 99% 12%,\n 97% 88%,\n 86% 96%,\n 55% 94%,\n 28% 98%,\n 5% 92%,\n 0 18%\n );\n z-index: 4;\n will-change: transform, opacity, filter;\n }\n\n .burst-a {\n left: 735px;\n top: 418px;\n width: 162px;\n height: 90px;\n }\n\n .burst-b {\n left: 920px;\n top: 414px;\n width: 172px;\n height: 92px;\n }\n\n .burst-c {\n left: 1300px;\n top: 420px;\n width: 96px;\n height: 92px;\n }\n\n .burst-d {\n left: 790px;\n top: 648px;\n width: 172px;\n height: 94px;\n }\n\n .burst-e {\n left: 1042px;\n top: 642px;\n width: 90px;\n height: 96px;\n }\n\n .burst-f {\n left: 1110px;\n top: 476px;\n width: 64px;\n height: 44px;\n opacity: 0;\n }\n\n .selection-box {\n position: absolute;\n left: 380px;\n top: 252px;\n width: 550px;\n height: 176px;\n border: 1px solid rgba(198, 173, 144, 0.32);\n background: rgba(228, 206, 181, 0.34);\n opacity: 0;\n transform-origin: 0 0;\n z-index: 1;\n }\n\n .intro-remnants {\n position: absolute;\n inset: 0;\n z-index: 2;\n pointer-events: none;\n }\n\n .intro-remnant {\n position: absolute;\n left: 50%;\n top: 50%;\n color: var(--ink);\n font-size: 100px;\n font-weight: 620;\n line-height: 0.92;\n letter-spacing: -0.055em;\n white-space: nowrap;\n opacity: 0;\n will-change: transform, opacity, filter;\n }\n\n .rem-a {\n margin-left: -220px;\n margin-top: -44px;\n }\n\n .rem-b {\n margin-left: -42px;\n margin-top: -42px;\n }\n\n .rem-c {\n margin-left: 155px;\n margin-top: -48px;\n }\n\n .rem-d {\n margin-left: -82px;\n margin-top: -4px;\n }\n\n .fragment-word {\n position: absolute;\n inset: 0;\n z-index: 2;\n pointer-events: none;\n }\n\n .frag {\n position: absolute;\n color: var(--ink);\n font-size: 88px;\n font-weight: 590;\n line-height: 0.9;\n letter-spacing: -0.055em;\n opacity: 0;\n white-space: nowrap;\n will-change: transform, opacity, filter;\n }\n\n .frag-alg {\n left: 649px;\n top: 484px;\n }\n\n .frag-row {\n left: 770px;\n top: 495px;\n }\n\n .frag-x {\n left: 932px;\n top: 484px;\n }\n\n .frag-clau {\n left: 1000px;\n top: 480px;\n }\n\n .frag-de {\n left: 1162px;\n top: 480px;\n }\n\n .final-wordmark {\n position: absolute;\n inset: 0;\n z-index: 3;\n color: var(--ink);\n opacity: 0;\n pointer-events: none;\n will-change: transform, opacity, filter;\n }\n\n .final-wordmark span {\n position: absolute;\n white-space: nowrap;\n line-height: 0.9;\n }\n\n .final-algrow {\n left: 690px;\n top: 484px;\n font-size: 88px;\n font-weight: 590;\n letter-spacing: -0.055em;\n transform: scaleX(1);\n transform-origin: 0 0;\n }\n\n .final-x {\n left: 884px;\n top: 484px;\n font-size: 88px;\n font-weight: 590;\n letter-spacing: -0.055em;\n }\n\n .final-claude {\n left: 955px;\n top: 480px;\n font-size: 88px;\n font-weight: 590;\n letter-spacing: -0.055em;\n transform: scaleX(1);\n transform-origin: 0 0;\n }\n\n .ui-content {\n align-items: center;\n justify-content: center;\n }\n\n .input-stack {\n position: relative;\n width: 1300px;\n height: 332px;\n transform-origin: 50% 50%;\n }\n\n .input-panel {\n position: absolute;\n left: 0;\n width: 100%;\n background: var(--panel);\n border: 1px solid var(--line);\n border-radius: 42px;\n box-shadow: 0 18px 50px var(--panel-shadow);\n opacity: 0;\n }\n\n .panel-empty {\n top: -54px;\n height: 306px;\n opacity: 1;\n }\n\n .panel-full {\n top: 0;\n height: 318px;\n }\n\n .panel-thinking {\n top: 7px;\n height: 304px;\n }\n\n .placeholder {\n position: absolute;\n left: 54px;\n top: 48px;\n color: var(--muted);\n font-size: 34px;\n line-height: 1.15;\n letter-spacing: -0.03em;\n }\n\n .prompt-text {\n position: absolute;\n left: 54px;\n right: 56px;\n top: 42px;\n bottom: 110px;\n color: var(--ink);\n font-size: 32px;\n font-weight: 400;\n line-height: 1.16;\n letter-spacing: -0.035em;\n }\n\n .prompt-text span {\n opacity: 0;\n }\n\n .panel-plus {\n position: absolute;\n left: 52px;\n bottom: 44px;\n width: 42px;\n height: 42px;\n }\n\n .panel-plus::before,\n .panel-plus::after {\n content: \"\";\n position: absolute;\n left: 50%;\n top: 50%;\n width: 34px;\n height: 2px;\n background: var(--ink);\n transform: translate(-50%, -50%);\n }\n\n .panel-plus::after {\n transform: translate(-50%, -50%) rotate(90deg);\n }\n\n .model {\n position: absolute;\n right: 126px;\n bottom: 48px;\n display: flex;\n align-items: center;\n gap: 16px;\n color: var(--ink);\n font-size: 30px;\n line-height: 1;\n letter-spacing: -0.045em;\n }\n\n .panel-empty .model {\n right: 78px;\n }\n\n .model .muted {\n color: var(--muted);\n }\n\n .chevron {\n width: 14px;\n height: 14px;\n border-right: 2px solid var(--muted);\n border-bottom: 2px solid var(--muted);\n transform: rotate(45deg) translateY(-5px);\n }\n\n .send-button {\n position: absolute;\n right: 42px;\n bottom: 38px;\n display: grid;\n place-items: center;\n width: 64px;\n height: 64px;\n border-radius: 17px;\n background: var(--claude);\n box-shadow: 0 10px 20px rgba(200, 95, 69, 0.18);\n opacity: 0;\n transform-origin: 50% 50%;\n }\n\n .panel-thinking .send-button {\n opacity: 1;\n }\n\n .send-button svg {\n width: 30px;\n height: 30px;\n }\n\n .thinking-line {\n position: absolute;\n left: 54px;\n top: 48px;\n display: flex;\n align-items: center;\n gap: 16px;\n color: var(--ink);\n font-size: 30px;\n line-height: 1;\n letter-spacing: -0.035em;\n opacity: 0;\n }\n\n .thinking-line .claude-star {\n position: relative;\n left: auto;\n top: auto;\n width: 24px;\n height: 24px;\n }\n\n .x-result {\n position: absolute;\n left: 54px;\n top: 44px;\n display: flex;\n align-items: center;\n gap: 18px;\n color: var(--ink);\n font-size: 30px;\n line-height: 1;\n letter-spacing: -0.035em;\n opacity: 0;\n }\n\n .x-trigger {\n display: grid;\n place-items: center;\n width: 48px;\n height: 48px;\n border-radius: 15px;\n background: var(--ink);\n color: var(--panel);\n font-size: 29px;\n font-weight: 680;\n letter-spacing: -0.06em;\n box-shadow: 0 14px 28px rgba(17, 17, 15, 0.18);\n }\n\n .social-card {\n position: absolute;\n left: 560px;\n top: 178px;\n width: 800px;\n height: 430px;\n border: 1px solid var(--line);\n border-radius: 36px;\n background: var(--panel);\n box-shadow: 0 28px 70px rgba(36, 31, 24, 0.13);\n opacity: 0;\n overflow: hidden;\n transform-origin: 50% 50%;\n }\n\n .social-card::before {\n content: \"\";\n position: absolute;\n inset: 0 0 auto;\n height: 150px;\n background: linear-gradient(135deg, rgba(20, 134, 184, 0.14), rgba(200, 95, 69, 0.12));\n }\n\n .social-x {\n position: absolute;\n right: 28px;\n top: 24px;\n display: grid;\n place-items: center;\n width: 44px;\n height: 44px;\n border-radius: 14px;\n background: var(--ink);\n color: var(--panel);\n font-size: 28px;\n font-weight: 680;\n }\n\n .social-avatar {\n position: absolute;\n left: 52px;\n top: 94px;\n width: 118px;\n height: 118px;\n border: 5px solid var(--panel);\n border-radius: 50%;\n object-fit: cover;\n object-position: 50% 50%;\n box-shadow: 0 18px 34px rgba(20, 134, 184, 0.2);\n }\n\n .social-name {\n position: absolute;\n left: 52px;\n top: 236px;\n color: var(--ink);\n font-size: 44px;\n font-weight: 620;\n line-height: 1;\n letter-spacing: -0.055em;\n }\n\n .social-handle {\n position: absolute;\n left: 52px;\n top: 288px;\n color: var(--muted);\n font-size: 26px;\n line-height: 1;\n letter-spacing: -0.025em;\n }\n\n .social-bio {\n position: absolute;\n left: 52px;\n right: 52px;\n top: 334px;\n color: var(--ink);\n font-size: 25px;\n line-height: 1.16;\n letter-spacing: -0.035em;\n }\n\n .follow-button {\n position: absolute;\n right: 46px;\n top: 236px;\n display: grid;\n place-items: center;\n width: 174px;\n height: 54px;\n border-radius: 18px;\n background: var(--ink);\n color: var(--panel);\n font-size: 24px;\n font-weight: 620;\n letter-spacing: -0.035em;\n overflow: hidden;\n transform-origin: 50% 50%;\n }\n\n .follow-label {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n inset: 0;\n white-space: nowrap;\n }\n\n .follow-label-following {\n opacity: 0;\n }\n\n .follow-check {\n display: block;\n width: 20px;\n height: 20px;\n }\n\n .follow-check svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n </style>\n </head>\n <body>\n <div\n id=\"root\"\n data-composition-id=\"blue-sweater-intro-video\"\n data-start=\"0\"\n data-duration=\"12\"\n data-width=\"1920\"\n data-height=\"1080\"\n >\n <div\n id=\"base\"\n class=\"clip base\"\n data-start=\"0\"\n data-duration=\"12\"\n data-track-index=\"0\"\n style=\"z-index: 0\"\n ></div>\n\n <div\n id=\"warmup\"\n class=\"clip\"\n data-start=\"0\"\n data-duration=\"0.48\"\n data-track-index=\"1\"\n style=\"z-index: 2\"\n >\n <div class=\"scene-content\">\n <div id=\"warmBlock\" class=\"warm-block\"></div>\n </div>\n </div>\n\n <div\n id=\"intro\"\n class=\"clip\"\n data-start=\"0.38\"\n data-duration=\"1.28\"\n data-track-index=\"2\"\n style=\"z-index: 3\"\n >\n <div class=\"scene-content\">\n <h1 id=\"introTitle\" class=\"title\">Introducing</h1>\n </div>\n </div>\n\n <div\n id=\"burst\"\n class=\"clip\"\n data-start=\"1.38\"\n data-duration=\"1.54\"\n data-track-index=\"3\"\n style=\"z-index: 4\"\n >\n <div class=\"scene-content\">\n <div class=\"selection-box\"></div>\n <div class=\"intro-remnants\" aria-hidden=\"true\">\n <span class=\"intro-remnant rem-a\">Intro</span>\n <span class=\"intro-remnant rem-b\">ducin</span>\n <span class=\"intro-remnant rem-c\">g</span>\n <span class=\"intro-remnant rem-d\">tro</span>\n </div>\n <div class=\"burst-block burst-a\"></div>\n <div class=\"burst-block burst-b\"></div>\n <div class=\"burst-block burst-c\"></div>\n <div class=\"burst-block burst-d\"></div>\n <div class=\"burst-block burst-e\"></div>\n <div class=\"burst-block burst-f\"></div>\n <div class=\"claude-star star-center burst-star\" aria-hidden=\"true\">\n <svg viewBox=\"-50 -50 100 100\">\n <g stroke=\"currentColor\" stroke-width=\"8\" stroke-linecap=\"round\">\n <line x1=\"0\" y1=\"-38\" x2=\"0\" y2=\"38\" />\n <line x1=\"-38\" y1=\"0\" x2=\"38\" y2=\"0\" />\n <line x1=\"-27\" y1=\"-27\" x2=\"27\" y2=\"27\" />\n <line x1=\"-27\" y1=\"27\" x2=\"27\" y2=\"-27\" />\n <line x1=\"-14\" y1=\"-35\" x2=\"14\" y2=\"35\" />\n <line x1=\"-35\" y1=\"-14\" x2=\"35\" y2=\"14\" />\n </g>\n </svg>\n </div>\n </div>\n </div>\n\n <div\n id=\"brand\"\n class=\"clip\"\n data-start=\"2.04\"\n data-duration=\"1.04\"\n data-track-index=\"4\"\n style=\"z-index: 5\"\n >\n <div class=\"scene-content\">\n <div class=\"fragment-word\" aria-hidden=\"true\">\n <span class=\"frag frag-alg\">blu</span>\n <span class=\"frag frag-row\">e</span>\n <span class=\"frag frag-x\">x</span>\n <span class=\"frag frag-clau\">swea</span>\n <span class=\"frag frag-de\">ter</span>\n </div>\n <div class=\"final-wordmark\" aria-hidden=\"true\">\n <span class=\"final-algrow\">blue</span>\n <span class=\"final-x\">x</span>\n <span class=\"final-claude\">sweater</span>\n </div>\n </div>\n </div>\n\n <div\n id=\"ui\"\n class=\"clip\"\n data-start=\"2.76\"\n data-duration=\"9\"\n data-track-index=\"5\"\n style=\"z-index: 6\"\n >\n <div class=\"scene-content ui-content\">\n <div class=\"claude-star star-panel\" aria-hidden=\"true\">\n <svg viewBox=\"-50 -50 100 100\">\n <g stroke=\"currentColor\" stroke-width=\"8\" stroke-linecap=\"round\">\n <line x1=\"0\" y1=\"-38\" x2=\"0\" y2=\"38\" />\n <line x1=\"-38\" y1=\"0\" x2=\"38\" y2=\"0\" />\n <line x1=\"-27\" y1=\"-27\" x2=\"27\" y2=\"27\" />\n <line x1=\"-27\" y1=\"27\" x2=\"27\" y2=\"-27\" />\n <line x1=\"-14\" y1=\"-35\" x2=\"14\" y2=\"35\" />\n <line x1=\"-35\" y1=\"-14\" x2=\"35\" y2=\"14\" />\n </g>\n </svg>\n </div>\n\n <div class=\"input-stack\">\n <div class=\"input-panel panel-empty\">\n <div class=\"placeholder\">How can I help you today?</div>\n <div class=\"panel-plus\"></div>\n <div class=\"model\">\n <span>Opus 5.0 <span class=\"muted\">Extended</span></span>\n <span class=\"chevron\"></span>\n </div>\n </div>\n\n <div class=\"input-panel panel-full\">\n <div id=\"promptText\" class=\"prompt-text\">\n Recommend one X creator who actively explores AI technology and, like me, is\n building an AI startup. I want someone practical, curious, and worth following.\n </div>\n <div class=\"panel-plus\"></div>\n <div class=\"model\">\n <span>Opus 5.0 <span class=\"muted\">Extended</span></span>\n <span class=\"chevron\"></span>\n </div>\n <div id=\"sendFull\" class=\"send-button\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 32 32\" fill=\"none\">\n <path\n d=\"M16 25V8M16 8L9 15M16 8L23 15\"\n stroke=\"#FBFAF6\"\n stroke-width=\"3.3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </div>\n\n <div class=\"input-panel panel-thinking\">\n <div class=\"thinking-line\">\n <span class=\"claude-star\" aria-hidden=\"true\">\n <svg viewBox=\"-50 -50 100 100\">\n <g stroke=\"currentColor\" stroke-width=\"8\" stroke-linecap=\"round\">\n <line x1=\"0\" y1=\"-38\" x2=\"0\" y2=\"38\" />\n <line x1=\"-38\" y1=\"0\" x2=\"38\" y2=\"0\" />\n <line x1=\"-27\" y1=\"-27\" x2=\"27\" y2=\"27\" />\n <line x1=\"-27\" y1=\"27\" x2=\"27\" y2=\"-27\" />\n <line x1=\"-14\" y1=\"-35\" x2=\"14\" y2=\"35\" />\n <line x1=\"-35\" y1=\"-14\" x2=\"35\" y2=\"14\" />\n </g>\n </svg>\n </span>\n <span>thinking</span>\n </div>\n <div class=\"x-result\">\n <span class=\"x-trigger\">x</span>\n <span>Open the recommended X profile</span>\n </div>\n <div class=\"panel-plus\"></div>\n <div class=\"model\">\n <span>Opus 5.0 <span class=\"muted\">Extended</span></span>\n <span class=\"chevron\"></span>\n </div>\n <div class=\"send-button\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 32 32\" fill=\"none\">\n <path\n d=\"M16 25V8M16 8L9 15M16 8L23 15\"\n stroke=\"#FBFAF6\"\n stroke-width=\"3.3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </div>\n </div>\n <div class=\"social-card\" aria-hidden=\"true\">\n <div class=\"social-x\">x</div>\n <img class=\"social-avatar\" src=\"/public/catalog/assets/10409e2bcf2a6bc6.png\" alt=\"\" />\n <div class=\"social-name\">joe sai</div>\n <div class=\"social-handle\">@_blue_sweater_</div>\n <div class=\"follow-button\">\n <span class=\"follow-label follow-label-follow\">Follow</span>\n <span class=\"follow-label follow-label-following\">\n <span>Following</span>\n <span class=\"follow-check\" aria-hidden=\"true\">\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#FBFAF6\"\n stroke-width=\"2.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n </span>\n </span>\n </div>\n <div class=\"social-bio\">\n Exploring AI technology and building an AI startup in public.\n </div>\n </div>\n </div>\n </div>\n\n <div\n id=\"cursor\"\n class=\"clip cursor\"\n data-start=\"0\"\n data-duration=\"12\"\n data-track-index=\"9\"\n aria-hidden=\"true\"\n style=\"z-index: 20\"\n >\n <svg viewBox=\"0 0 98 120\" fill=\"none\">\n <path\n d=\"M13 6L86 80L51 85L35 114L13 6Z\"\n fill=\"#1486B8\"\n stroke=\"#F7F5EF\"\n stroke-width=\"7\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <audio\n id=\"audio-mix\"\n data-start=\"0\"\n data-duration=\"12\"\n data-track-index=\"20\"\n src=\"/public/catalog/assets/73c4fffc131648df.wav\"\n data-volume=\"1\"\n ></audio>\n </div>\n\n <script>\n window.__timelines = window.__timelines || {};\n\n const promptEl = document.querySelector(\"#promptText\");\n const promptText = promptEl.textContent.replace(/\\s+/g, \" \").trim();\n promptEl.textContent = \"\";\n for (const char of promptText) {\n const span = document.createElement(\"span\");\n span.textContent = char;\n promptEl.appendChild(span);\n }\n\n const tl = gsap.timeline({ paused: true, defaults: { ease: \"power3.out\" } });\n\n tl.set([\"#warmup\", \"#intro\", \"#burst\", \"#brand\", \"#ui\"], { opacity: 0 });\n tl.set(\"#cursor\", { x: 690, y: 846, rotation: -8, scale: 0.72, opacity: 0 });\n tl.set(\".panel-full\", { opacity: 0 });\n tl.set(\".panel-thinking\", { opacity: 0 });\n tl.set(\".prompt-text span\", { opacity: 0 });\n tl.set(\"#sendFull\", { opacity: 0, scale: 0.84 });\n tl.set([\".selection-box\", \".intro-remnant\", \".frag\", \".final-wordmark\"], { opacity: 0 });\n tl.set([\".x-result\", \".social-card\"], { opacity: 0 });\n tl.set(\".x-trigger\", { scale: 1 });\n\n tl.to(\"#warmup\", { opacity: 1, duration: 0.01 }, 0);\n tl.fromTo(\n \"#warmBlock\",\n { x: -820, scaleX: 0.42, opacity: 0, filter: \"blur(14px)\" },\n { x: -25, scaleX: 1, opacity: 1, filter: \"blur(0px)\", duration: 0.22, ease: \"power2.out\" },\n 0.02,\n );\n tl.to(\n \"#warmBlock\",\n { x: 620, opacity: 0, filter: \"blur(18px)\", duration: 0.24, ease: \"power2.in\" },\n 0.25,\n );\n tl.to(\"#warmup\", { opacity: 0, duration: 0.08 }, 0.4);\n\n tl.to(\"#intro\", { opacity: 1, duration: 0.1 }, 0.44);\n tl.fromTo(\n \"#introTitle\",\n { opacity: 0, y: 26, filter: \"blur(10px)\" },\n { opacity: 1, y: 0, filter: \"blur(0px)\", duration: 0.46, ease: \"expo.out\" },\n 0.48,\n );\n tl.to(\"#cursor\", { opacity: 1, duration: 0.12 }, 0.44);\n tl.to(\n \"#cursor\",\n { x: 942, y: 604, rotation: -3, duration: 0.36, ease: \"power2.inOut\", overwrite: \"auto\" },\n 0.44,\n );\n tl.to(\n \"#cursor\",\n { x: 982, y: 642, rotation: -6, duration: 0.24, ease: \"power2.inOut\", overwrite: \"auto\" },\n 1.28,\n );\n tl.to(\n \"#introTitle\",\n { opacity: 0.26, filter: \"blur(4px)\", duration: 0.03, ease: \"power2.in\" },\n 1.43,\n );\n tl.fromTo(\n \".intro-remnant\",\n { opacity: 0, x: 0, y: 0, filter: \"blur(2px)\" },\n {\n opacity: 0.32,\n x: (index) => [-22, 8, 32, -10][index],\n y: (index) => [-10, 5, -18, 28][index],\n filter: \"blur(7px)\",\n duration: 0.055,\n stagger: 0.004,\n ease: \"power2.out\",\n },\n 1.435,\n );\n tl.to(\n \"#introTitle\",\n { opacity: 0, y: -8, filter: \"blur(10px)\", duration: 0.08, ease: \"power2.in\" },\n 1.47,\n );\n tl.to(\n \".intro-remnant\",\n { opacity: 0, filter: \"blur(11px)\", duration: 0.07, ease: \"power2.in\" },\n 1.49,\n );\n tl.to(\"#intro\", { opacity: 0, duration: 0.06 }, 1.56);\n\n tl.to(\"#burst\", { opacity: 1, duration: 0.02 }, 1.4);\n tl.fromTo(\n \".burst-star\",\n { opacity: 0, scale: 0.08, rotation: -20 },\n { opacity: 1, scale: 0.16, rotation: -6, duration: 0.08, ease: \"power2.out\" },\n 1.43,\n );\n tl.to(\n \".burst-star\",\n { scale: 1, rotation: 0, duration: 0.42, ease: \"expo.out\", overwrite: \"auto\" },\n 1.55,\n );\n const blockPaths = [\n {\n source: [-1, 28],\n scatter: [-160, -96],\n drift: [-151, -126],\n select: [-82, -86],\n squeeze: [19, -68],\n release: [19, -68],\n fade: 2.17,\n },\n {\n source: [-11, 5],\n scatter: [165, -123],\n drift: [153, -126],\n select: [61, -118],\n squeeze: [-81, -65],\n release: [-81, -65],\n fade: 2.17,\n },\n {\n source: [-3, -8],\n scatter: [169, -28],\n drift: [174, -24],\n select: [127, 9],\n squeeze: [37, 70],\n release: [-78, 96],\n fade: 2.33,\n },\n {\n source: [-9, 2],\n scatter: [-153, 80],\n drift: [-157, 76],\n select: [-133, 39],\n squeeze: [-90, -40],\n release: [-90, -40],\n fade: 2.17,\n },\n {\n source: [-7, -13],\n scatter: [-10, 129],\n drift: [-17, 128],\n select: [-38, 83],\n squeeze: [-67, -18],\n release: [-92, -87],\n fade: 2.33,\n },\n ];\n gsap.utils.toArray(\".burst-block\").forEach((block, index) => {\n const path = blockPaths[index];\n if (!path) {\n tl.set(block, { opacity: 0 });\n return;\n }\n tl.set(\n block,\n {\n x: path.source[0],\n y: path.source[1],\n scale: 0.78,\n rotation: index % 2 ? 3 : -3,\n filter: \"blur(8px)\",\n },\n 1.45,\n );\n tl.to(\n block,\n {\n opacity: 1,\n scale: 1,\n rotation: 0,\n filter: \"blur(0px)\",\n duration: 0.055,\n ease: \"power3.out\",\n },\n 1.455,\n );\n tl.to(\n block,\n {\n x: path.scatter[0],\n y: path.scatter[1],\n rotation: index % 2 ? 2 : -2,\n duration: 0.2,\n ease: \"sine.out\",\n },\n 1.5,\n );\n tl.to(\n block,\n {\n x: path.drift[0],\n y: path.drift[1],\n rotation: index % 2 ? 1 : -1,\n duration: 0.2,\n ease: \"sine.inOut\",\n },\n 1.7,\n );\n tl.to(\n block,\n { x: path.select[0], y: path.select[1], rotation: 0, duration: 0.2, ease: \"sine.inOut\" },\n 1.9,\n );\n tl.to(\n block,\n {\n x: path.squeeze[0],\n y: path.squeeze[1],\n scale: 1,\n rotation: 0,\n filter: \"blur(0.6px)\",\n duration: 0.07,\n ease: \"sine.inOut\",\n },\n 2.1,\n );\n tl.to(\n block,\n {\n x: path.release[0],\n y: path.release[1],\n scale: 0.84,\n rotation: 0,\n filter: \"blur(1.5px)\",\n duration: 0.05,\n ease: \"sine.inOut\",\n },\n 2.17,\n );\n tl.to(\n block,\n { opacity: 0, scale: 0.38, filter: \"blur(7px)\", duration: 0.05, ease: \"power2.in\" },\n path.fade,\n );\n });\n tl.to(\n \"#cursor\",\n { x: 1540, y: 112, rotation: -9, duration: 0.26, ease: \"power2.inOut\", overwrite: \"auto\" },\n 1.56,\n );\n tl.to(\n \"#cursor\",\n { x: 380, y: 252, rotation: -7, duration: 0.16, ease: \"power2.inOut\", overwrite: \"auto\" },\n 1.82,\n );\n tl.fromTo(\n \".selection-box\",\n { opacity: 0, scaleX: 0.06, scaleY: 0.1, x: 0, y: 0, filter: \"blur(3px)\" },\n {\n opacity: 1,\n scaleX: 1,\n scaleY: 1,\n x: 42,\n y: 52,\n filter: \"blur(0px)\",\n duration: 0.18,\n ease: \"power2.out\",\n },\n 1.96,\n );\n tl.to(\n \"#cursor\",\n { x: 930, y: 478, rotation: -4, duration: 0.14, ease: \"power2.inOut\", overwrite: \"auto\" },\n 1.96,\n );\n tl.to(\n \"#cursor\",\n { x: 1168, y: 560, rotation: -4, duration: 0.14, ease: \"power2.inOut\", overwrite: \"auto\" },\n 2.12,\n );\n tl.to(\n \".selection-box\",\n { x: 220, y: 158, width: 640, height: 190, duration: 0.2, ease: \"power2.inOut\" },\n 2.16,\n );\n tl.to(\n \".burst-star\",\n {\n x: 118,\n y: -62,\n scale: 0.16,\n opacity: 0.45,\n duration: 0.18,\n ease: \"power2.inOut\",\n overwrite: \"auto\",\n },\n 2.12,\n );\n\n tl.to(\"#brand\", { opacity: 1, duration: 0.04 }, 2.08);\n\n const fragmentMotion = [\n {\n selector: \".frag-alg\",\n from: [112, -118, 4],\n carry: [88, -96],\n settle: [20, -24],\n lock: [0, 0],\n visible: 1,\n },\n {\n selector: \".frag-row\",\n from: [-12, 78, 5],\n carry: [-22, 56],\n settle: [-8, 18],\n lock: [0, 0],\n visible: 1,\n },\n {\n selector: \".frag-x\",\n from: [38, 70, 7],\n carry: [18, 48],\n settle: [6, 14],\n lock: [0, 0],\n visible: 0.82,\n },\n {\n selector: \".frag-clau\",\n from: [-82, -108, 4],\n carry: [-54, -78],\n settle: [-18, -18],\n lock: [0, 0],\n visible: 1,\n },\n {\n selector: \".frag-de\",\n from: [62, 22, 5],\n carry: [38, 12],\n settle: [12, 4],\n lock: [0, 0],\n visible: 1,\n },\n ];\n\n fragmentMotion.forEach((piece, index) => {\n tl.fromTo(\n piece.selector,\n {\n opacity: 0,\n x: piece.from[0],\n y: piece.from[1],\n scale: 0.99,\n filter: `blur(${piece.from[2]}px)`,\n },\n {\n opacity: piece.visible,\n x: piece.carry[0],\n y: piece.carry[1],\n scale: 1,\n filter: \"blur(1.2px)\",\n duration: 0.16,\n ease: \"sine.out\",\n overwrite: \"auto\",\n },\n 2.12 + index * 0.004,\n );\n tl.to(\n piece.selector,\n {\n x: piece.settle[0],\n y: piece.settle[1],\n opacity: piece.visible,\n filter: \"blur(0.35px)\",\n duration: 0.28,\n ease: \"power3.out\",\n overwrite: \"auto\",\n },\n 2.28 + index * 0.003,\n );\n tl.to(\n piece.selector,\n {\n opacity: 0,\n x: piece.settle[0] + [8, -6, 2, -8, 6][index],\n y: piece.settle[1] + [-6, 7, 4, -5, 3][index],\n filter: \"blur(4px)\",\n duration: 0.14,\n ease: \"power2.out\",\n overwrite: \"auto\",\n },\n 2.31 + index * 0.002,\n );\n });\n\n tl.fromTo(\n \".final-wordmark\",\n { opacity: 0, x: -12, y: 8, scale: 0.995, filter: \"blur(5px)\" },\n {\n opacity: 1,\n x: 0,\n y: 0,\n scale: 1,\n filter: \"blur(0px)\",\n duration: 0.24,\n ease: \"power4.out\",\n overwrite: \"auto\",\n },\n 2.38,\n );\n tl.to(\".burst-star\", { opacity: 0, duration: 0.12, ease: \"power2.in\" }, 2.32);\n tl.to(\n \".selection-box\",\n { opacity: 0, filter: \"blur(5px)\", duration: 0.16, ease: \"power2.in\" },\n 2.33,\n );\n tl.to(\n \"#cursor\",\n { x: 1256, y: 587, rotation: -3, duration: 0.3, ease: \"power2.inOut\", overwrite: \"auto\" },\n 2.34,\n );\n tl.to(\"#burst\", { opacity: 0, filter: \"blur(6px)\", duration: 0.14, ease: \"power2.in\" }, 2.58);\n tl.to(\"#cursor\", { opacity: 0, duration: 0.13, ease: \"power2.in\" }, 2.86);\n tl.set(\"#cursor\", { opacity: 0 }, 3.0);\n tl.to(\n \"#brand\",\n { opacity: 0, y: 26, filter: \"blur(9px)\", duration: 0.22, ease: \"power2.in\" },\n 2.9,\n );\n\n tl.to(\"#ui\", { opacity: 1, duration: 0.08 }, 3.02);\n tl.fromTo(\n \".input-stack\",\n { opacity: 0, scale: 0.88, y: 92, filter: \"blur(14px)\" },\n { opacity: 1, scale: 1, y: 0, filter: \"blur(0px)\", duration: 0.66, ease: \"expo.out\" },\n 3.05,\n );\n tl.fromTo(\n \".star-panel\",\n { opacity: 0, scale: 0.5, rotation: -16 },\n { opacity: 1, scale: 1, rotation: 0, duration: 0.38, ease: \"power3.out\" },\n 3.18,\n );\n tl.fromTo(\".placeholder\", { opacity: 0, y: 12 }, { opacity: 1, y: 0, duration: 0.34 }, 3.3);\n tl.fromTo(\n \".panel-empty .panel-plus, .panel-empty .model\",\n { opacity: 0, y: 10 },\n { opacity: 1, y: 0, duration: 0.3, stagger: 0.06 },\n 3.42,\n );\n\n tl.to(\".panel-empty\", { opacity: 0, duration: 0.18, ease: \"power2.inOut\" }, 4.12);\n tl.to(\".panel-full\", { opacity: 1, duration: 0.18, ease: \"power2.inOut\" }, 4.12);\n tl.to(\n \".input-stack\",\n { scale: 1.32, x: 300, y: -100, duration: 0.26, ease: \"power2.inOut\" },\n 4.14,\n );\n tl.to(\".input-stack\", { scale: 1, x: 0, y: 0, duration: 0.74, ease: \"power2.inOut\" }, 4.92);\n\n tl.to(\n \".prompt-text span\",\n { opacity: 1, duration: 0.01, stagger: { amount: 2.85 }, ease: \"none\" },\n 4.18,\n );\n tl.to(\"#sendFull\", { opacity: 1, scale: 1, duration: 0.24, ease: \"power3.out\" }, 7.32);\n tl.fromTo(\n \"#cursor\",\n { x: 1328, y: 900, rotation: -6, scale: 1, opacity: 0 },\n {\n x: 1530,\n y: 900,\n rotation: -5,\n scale: 1,\n opacity: 1,\n duration: 0.48,\n ease: \"power2.inOut\",\n },\n 6.92,\n );\n tl.to(\n \"#cursor\",\n { x: 1512, y: 620, rotation: -5, duration: 0.5, ease: \"power2.inOut\" },\n 7.44,\n );\n\n tl.to(\"#sendFull\", { scale: 0.86, duration: 0.08, ease: \"power2.in\" }, 7.9);\n tl.to(\"#sendFull\", { scale: 1, duration: 0.14, ease: \"back.out(1.7)\" }, 7.98);\n tl.to(\".panel-full\", { opacity: 0, duration: 0.16, ease: \"power2.inOut\" }, 8.15);\n tl.to(\".panel-thinking\", { opacity: 1, duration: 0.18, ease: \"power2.inOut\" }, 8.15);\n tl.set(\".thinking-line\", { opacity: 0 }, 8.24);\n tl.to(\n \".thinking-line\",\n { opacity: 1, duration: 0.3, ease: \"power3.out\", overwrite: \"auto\" },\n 8.25,\n );\n tl.to(\"#cursor\", { x: 1554, y: 620, rotation: -5, duration: 0.28, ease: \"power2.out\" }, 7.94);\n tl.to(\n \".thinking-line\",\n { opacity: 0, duration: 0.18, ease: \"power2.inOut\", overwrite: \"auto\" },\n 8.64,\n );\n tl.fromTo(\n \".x-result\",\n { opacity: 0, y: 12 },\n { opacity: 1, y: 0, duration: 0.28, ease: \"power3.out\" },\n 8.82,\n );\n tl.to(\n \"#cursor\",\n { x: 365, y: 418, rotation: -6, duration: 0.58, ease: \"power2.inOut\", overwrite: \"auto\" },\n 8.74,\n );\n tl.to(\n \".x-trigger\",\n {\n keyframes: [\n { scale: 0.88, duration: 0.08, ease: \"power2.in\" },\n { scale: 1, duration: 0.14, ease: \"back.out(1.7)\" },\n ],\n overwrite: \"auto\",\n },\n 9.34,\n );\n tl.to(\".x-result\", { opacity: 0, y: -8, duration: 0.18, ease: \"power2.inOut\" }, 9.5);\n tl.to(\n \".input-stack\",\n {\n opacity: 0,\n scale: 0.93,\n y: 26,\n filter: \"blur(12px)\",\n duration: 0.4,\n ease: \"power3.inOut\",\n },\n 9.5,\n );\n tl.to(\n \".star-panel\",\n { opacity: 0, scale: 0.72, rotation: 12, duration: 0.28, ease: \"power2.inOut\" },\n 9.5,\n );\n tl.fromTo(\n \".social-card\",\n { opacity: 0, y: 34, scale: 0.88, filter: \"blur(12px)\" },\n { opacity: 1, y: 0, scale: 1, filter: \"blur(0px)\", duration: 0.6, ease: \"expo.out\" },\n 9.86,\n );\n tl.to(\n \"#cursor\",\n { x: 1408, y: 246, rotation: -5, duration: 0.42, ease: \"power2.inOut\", overwrite: \"auto\" },\n 9.96,\n );\n tl.to(\n \"#cursor\",\n { x: 1242, y: 446, rotation: -5, duration: 0.36, ease: \"power2.inOut\", overwrite: \"auto\" },\n 10.5,\n );\n tl.to(\".follow-button\", { scale: 0.9, duration: 0.08, ease: \"power2.in\" }, 10.88);\n tl.to(\n \".follow-button\",\n { scale: 1, backgroundColor: \"#2f2f2f\", duration: 0.28, ease: \"elastic.out(1, 0.45)\" },\n 10.96,\n );\n tl.to(\".follow-label-follow\", { opacity: 0, duration: 0.08, ease: \"none\" }, 10.96);\n tl.to(\".follow-label-following\", { opacity: 1, duration: 0.08, ease: \"none\" }, 10.99);\n tl.to(\n \"#cursor\",\n { x: 1286, y: 472, rotation: -5, duration: 0.16, ease: \"power2.out\", overwrite: \"auto\" },\n 11,\n );\n\n window.__timelines[\"blue-sweater-intro-video\"] = tl;\n </script>\n </body>\n</html>\n"} |