diff --git a/packages/core/src/compiler/htmlBundler.ts b/packages/core/src/compiler/htmlBundler.ts
index 7933350c..c5905847 100644
--- a/packages/core/src/compiler/htmlBundler.ts
+++ b/packages/core/src/compiler/htmlBundler.ts
@@ -440,6 +440,22 @@ export async function bundleToSingleHtml(
? contentDoc.querySelector(`[data-composition-id="${compId}"]`)
: contentDoc.querySelector("[data-composition-id]");
+ // When a sub-composition is a full HTML document (no ), styles
+ // and scripts in are not part of contentDoc (which only has body
+ // content). Extract them so backgrounds, positioning, fonts, and library
+ // scripts (e.g. GSAP CDN) are not silently dropped.
+ if (!contentRoot && compDoc.head) {
+ for (const s of [...compDoc.head.querySelectorAll("style")]) {
+ compStyleChunks.push(rewriteCssAssetUrls(s.textContent || "", src));
+ }
+ for (const s of [...compDoc.head.querySelectorAll("script")]) {
+ const externalSrc = (s.getAttribute("src") || "").trim();
+ if (externalSrc && !compExternalScriptSrcs.includes(externalSrc)) {
+ compExternalScriptSrcs.push(externalSrc);
+ }
+ }
+ }
+
for (const s of [...contentDoc.querySelectorAll("style")]) {
compStyleChunks.push(rewriteCssAssetUrls(s.textContent || "", src));
s.remove();
diff --git a/packages/core/src/runtime/compositionLoader.ts b/packages/core/src/runtime/compositionLoader.ts
index a2958745..a440cf9a 100644
--- a/packages/core/src/runtime/compositionLoader.ts
+++ b/packages/core/src/runtime/compositionLoader.ts
@@ -81,6 +81,10 @@ async function mountCompositionContent(params: {
injectedStyles: HTMLStyleElement[];
injectedScripts: HTMLScriptElement[];
parseDimensionPx: (value: string | null) => string | null;
+ /** Extra