@godot-scene-web/html 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["isCssContainerType","containerLayoutKind","cssSize","isBoxContainerType","themeNumber","isFlowContainerType","gradientStops","curvePoints","appendAnchorName","mergeAnchorName","textureRepeat","cssSize","assignTextureMetadata","cssSize"],"sources":["../src/anchor-css.ts","../src/base-css.ts","../src/lru.ts","../src/atlas.ts","../src/resources.ts","../src/style-box.ts","../src/browser-layout.ts","../src/browser-zoom.ts","../src/content-scale.ts","../src/default-font-data.ts","../src/default-font.ts","../src/render-tree.ts","../src/dom.ts","../src/easing.ts","../src/html-string.ts","../src/material.ts","../src/browser-anchors.ts","../src/container-layout.ts","../src/node-style.ts","../src/text-scale.ts","../src/text.ts","../src/textures.ts","../src/visual-2d.ts","../src/model.ts","../src/render-stabilize.ts","../src/text-auto-fit.ts","../src/tint-bake.ts"],"sourcesContent":["import { round } from \"./css-values\";\n\n/**\n * Pure CSS Anchor Positioning string-building helpers. Shared by any anchor-name emitter in\n * this package — the offline `browser-anchors.ts` model builder, and consumers outside this\n * package (e.g. spirectl's hover-tip materializer) that emit CSS anchor properties directly\n * onto their own node/style records without going through the offline HTML-model pipeline at\n * all. Kept dependency-free (no `GodotHtmlNode`/model types) so it can be imported from either\n * side without pulling in this package's whole model.\n */\n\n/** Merge `name` into an existing `anchor-name` value (comma-separated), or start a fresh one. */\nexport function appendAnchorName(existing: string | undefined, name: string): string {\n if (existing === undefined) return name;\n return existing.split(\",\").some((entry) => entry.trim() === name) ? existing : `${existing}, ${name}`;\n}\n\n/**\n * Build an inset value (for `top`/`right`/`bottom`/`left`) that anchors to one or more named\n * targets: `anchor(name side)`, `min()`/`max()` over several candidates, optionally wrapped in\n * `calc(... ± Npx)` for a nonzero offset. `combine` only matters when `targetNames.length > 1`.\n */\nexport function anchorInsetExpression(\n side: string,\n targetNames: string[],\n combine: \"min\" | \"max\",\n offset: number,\n): string {\n const anchorOf = (name: string): string => `anchor(${name} ${side})`;\n const base =\n targetNames.length === 0\n ? anchorOf(\"\")\n : targetNames.length === 1\n ? anchorOf(targetNames[0] as string)\n : `${combine}(${targetNames.map(anchorOf).join(\", \")})`;\n if (offset === 0) {\n // anchor() is valid as the entire value of an inset property; a bare function is fine.\n return base;\n }\n const magnitude = `${round(Math.abs(offset))}px`;\n return offset < 0 ? `calc(${base} - ${magnitude})` : `calc(${base} + ${magnitude})`;\n}\n\n/**\n * A `position-try-fallbacks` value for the common \"flip to the opposite side when the planned\n * placement would overflow the viewport\" case. `flip-inline` flips the inline-axis insets\n * (left/right) and reproduces a manual \"flush to the owner's opposite edge\" overflow-flip\n * exactly (verified against a real Chromium/Firefox render: a right-anchored box positioned\n * near the viewport's right edge flips so its own right edge sits flush at the owner's left\n * edge — the same target a hand-written overflow-flip computes). `flip-block` is the same for\n * the block axis (top/bottom).\n */\nexport function positionTryFallback(...kinds: Array<\"flip-inline\" | \"flip-block\" | \"flip-start\">): string {\n return kinds.join(\", \");\n}\n","export const godotSceneBaseCss = `\n.godot-scene-stage {\n position: relative;\n overflow: hidden;\n background: transparent;\n transform-origin: top left;\n}\n.godot-scene-frame {\n container-type: size;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n}\n.godot-scene-frame > .godot-scene-stage {\n flex: 0 0 auto;\n transform-origin: center center;\n}\n.godot-scene-node {\n box-sizing: border-box;\n position: absolute;\n min-width: 0;\n min-height: 0;\n}\n.godot-scene-self-layer {\n box-sizing: border-box;\n}\n.godot-scene-node.godot-type-Label > .godot-scene-self-layer,\n.godot-scene-node.godot-type-Button > .godot-scene-self-layer,\n.godot-scene-node.godot-type-RichTextLabel > .godot-scene-self-layer {\n display: flex;\n font-family: \"Godot Default\", sans-serif;\n font-synthesis: none;\n white-space: pre-wrap;\n}\n.godot-scene-node.godot-type-Label > .godot-scene-self-layer {\n letter-spacing: var(--godot-label-letter-spacing, 0.25px);\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-normal {\n letter-spacing: var(--godot-rich-letter-spacing, 0.25px);\n font-size: var(--godot-rich-normal-font-size, 1em);\n font-style: normal;\n font-weight: var(--godot-rich-normal-font-weight, 400);\n font-variation-settings: inherit;\n}\n/* Each styled role can carry its own letter-spacing (a Godot font's glyph spacing\n is a per-font-file property, so the bold/italic faces may space differently from\n the normal one). Every role var falls back to the value that role renders with\n today: the generic spacing for bold, and the italic 0.7 factor for the italic\n roles, so a consumer that sets nothing lays out exactly as before. */\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-bold {\n font-family: var(--godot-rich-bold-font-family, inherit);\n letter-spacing: var(--godot-rich-bold-letter-spacing, var(--godot-rich-letter-spacing, 0.25px));\n font-size: var(--godot-rich-bold-font-size, 1em);\n font-style: normal;\n font-weight: var(--godot-rich-bold-font-weight, 700);\n font-variation-settings: inherit;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-italic {\n font-family: var(--godot-rich-italic-font-family, inherit);\n letter-spacing: var(--godot-rich-italic-letter-spacing, calc(var(--godot-rich-letter-spacing, 0.25px) * 0.7));\n font-size: var(--godot-rich-italic-font-size, 1em);\n font-style: italic;\n font-weight: var(--godot-rich-normal-font-weight, 400);\n font-variation-settings: inherit;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-bold .godot-rich-italic {\n font-family: var(--godot-rich-bold-italic-font-family, inherit);\n letter-spacing: var(--godot-rich-bold-italic-letter-spacing, calc(var(--godot-rich-letter-spacing, 0.25px) * 0.7));\n font-size: var(--godot-rich-bold-italic-font-size, 1em);\n font-style: italic;\n font-weight: var(--godot-rich-bold-font-weight, 700);\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-stack {\n display: grid;\n width: 100%;\n position: relative;\n /* No transform here: a translateZ(0) permanently promotes every rich label to its own\n compositor layer, whose raster goes stale (blurry) after ancestor transform animations. */\n isolation: isolate;\n white-space: inherit;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-align {\n margin: 0;\n}\n/* One block per hard-newline-separated Godot paragraph inside an aligned region.\n WRAPPED lines within a block share --godot-rich-line-height; the gap between\n consecutive blocks (an explicit newline) is --godot-rich-paragraph-spacing.\n Both default to the plain flow (normal / 0), so only a consumer that sets the\n custom properties (e.g. CouchCoop's card DescriptionLabel) changes spacing;\n every other aligned label lays out exactly as before. */\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-paragraph {\n display: block;\n line-height: var(--godot-rich-line-height, normal);\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-paragraph + .godot-rich-paragraph {\n margin-top: var(--godot-rich-paragraph-spacing, 0);\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-layer {\n grid-area: 1 / 1;\n pointer-events: none;\n white-space: inherit;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-shadow-outline {\n color: transparent;\n -webkit-text-stroke: var(--godot-rich-shadow-outline-size, 0px) var(--godot-rich-shadow-color, rgba(0, 0, 0, 0));\n paint-order: stroke fill;\n transform: translate(var(--godot-rich-shadow-x, 0px), var(--godot-rich-shadow-y, 0px));\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-shadow-fill {\n color: var(--godot-rich-shadow-color, rgba(0, 0, 0, 0));\n transform: translate(var(--godot-rich-shadow-x, 0px), var(--godot-rich-shadow-y, 0px));\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-outline {\n color: transparent;\n -webkit-text-stroke: var(--godot-rich-outline-size, 0px) var(--godot-rich-outline-color, rgba(0, 0, 0, 0));\n paint-order: stroke fill;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-fill {\n color: var(--godot-rich-text-color, currentColor);\n position: relative;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-layer:not(.godot-rich-fill) * {\n color: inherit !important;\n background-color: transparent !important;\n}\n.godot-scene-node.godot-type-LineEdit > .godot-scene-self-layer,\n.godot-scene-node.godot-type-TextEdit > .godot-scene-self-layer {\n display: flex;\n align-items: center;\n font-family: \"Godot Default\", sans-serif;\n white-space: pre-wrap;\n}\n.godot-scene-node.godot-type-TextEdit > .godot-scene-self-layer {\n align-items: flex-start;\n overflow: hidden;\n}\n.godot-scene-node.godot-type-Range > .godot-scene-self-layer {\n background: rgba(255, 255, 255, 0.14);\n}\n.godot-scene-node.godot-type-Range > .godot-scene-self-layer::before {\n content: \"\";\n display: block;\n width: var(--godot-range-percent, 0%);\n height: 100%;\n background: currentColor;\n opacity: 0.55;\n}\n.godot-scene-debug .godot-scene-node {\n outline: 1px solid rgba(0, 255, 255, 0.35);\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-code {\n font-family: ui-monospace, \"Cascadia Code\", \"Source Code Pro\", monospace;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-hr {\n border: none;\n border-top: 1px solid currentColor;\n opacity: 0.5;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-img {\n display: inline-block;\n vertical-align: middle;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-layer:not(.godot-rich-fill) .godot-rich-img {\n visibility: hidden;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-word {\n display: inline-block;\n white-space: nowrap;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-char {\n display: inline-block;\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-effect-wave .godot-rich-char {\n animation: godot-rich-wave 1.6s ease-in-out infinite;\n animation-delay: calc(var(--i, 0) * 0.06s);\n}\n@keyframes godot-rich-wave {\n 0%, 100% { transform: translateY(0); }\n 25% { transform: translateY(-0.18em); }\n 75% { transform: translateY(0.18em); }\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-effect-shake .godot-rich-char {\n animation: godot-rich-shake 0.3s steps(2, end) infinite;\n animation-delay: calc(var(--i, 0) * -0.05s);\n}\n@keyframes godot-rich-shake {\n 0% { transform: translate(0, 0); }\n 25% { transform: translate(0.04em, -0.04em); }\n 50% { transform: translate(-0.04em, 0.04em); }\n 75% { transform: translate(0.04em, 0.04em); }\n 100% { transform: translate(0, 0); }\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-effect-tornado .godot-rich-char {\n animation: godot-rich-tornado 2s linear infinite;\n animation-delay: calc(var(--i, 0) * 0.1s);\n}\n@keyframes godot-rich-tornado {\n 0% { transform: translate(0.12em, 0); }\n 25% { transform: translate(0, 0.12em); }\n 50% { transform: translate(-0.12em, 0); }\n 75% { transform: translate(0, -0.12em); }\n 100% { transform: translate(0.12em, 0); }\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-fill .godot-rich-effect-rainbow .godot-rich-char {\n animation: godot-rich-rainbow 4s linear infinite;\n animation-delay: calc(var(--i, 0) * -0.08s);\n}\n@keyframes godot-rich-rainbow {\n 0% { color: hsl(0, 80%, 65%); }\n 100% { color: hsl(360, 80%, 65%); }\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-effect-pulse {\n animation: godot-rich-pulse 1s ease-in-out infinite;\n}\n@keyframes godot-rich-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n}\n.godot-scene-node.godot-type-RichTextLabel .godot-rich-effect-fade .godot-rich-char {\n animation: godot-rich-fade 2s ease-in-out infinite;\n animation-delay: calc(var(--i, 0) * 0.08s);\n}\n@keyframes godot-rich-fade {\n 0%, 100% { opacity: 0.25; }\n 50% { opacity: 1; }\n}\n`.trim();\n","// A tiny insertion-ordered LRU over string keys — the shape gsw's hot-path memos share\n// (`webgl/runtime`'s `staticFrameCache` was the first of them, hand-rolled). A `Map` iterates in\n// insertion order, so the \"oldest\" entry is just the first key and a hit re-inserts to bump it.\n//\n// Every consumer memoizes a PURE function, so a hit is byte-identical to a fresh compute and the\n// cache is invisible except in cost. Each exposes its own `__reset…ForTest` hook (these are\n// module-scoped and survive across tests, so a test that counts computes must start empty).\n\nexport interface StringLru<T> {\n get(key: string): T | undefined;\n set(key: string, value: T): void;\n clear(): void;\n readonly size: number;\n}\n\nexport function createStringLru<T>(limit: number): StringLru<T> {\n const entries = new Map<string, T>();\n return {\n get(key) {\n const hit = entries.get(key);\n if (hit === undefined) {\n return undefined;\n }\n entries.delete(key);\n entries.set(key, hit); // LRU bump\n return hit;\n },\n set(key, value) {\n entries.set(key, value);\n while (entries.size > limit) {\n const oldest = entries.keys().next().value;\n if (oldest === undefined) {\n break;\n }\n entries.delete(oldest);\n }\n },\n clear() {\n entries.clear();\n },\n get size() {\n return entries.size;\n },\n };\n}\n","import {\n type ColorMatrix,\n colorMatrixFeValues,\n escapeAttribute,\n round,\n} from \"./css-values\";\nimport { createStringLru } from \"./lru\";\n\nexport interface AtlasRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface AtlasSize {\n width: number;\n height: number;\n}\n\nexport function zeroAtlasMargin(): AtlasRect {\n return { x: 0, y: 0, width: 0, height: 0 };\n}\n\nexport function hasAtlasMargin(\n margin: AtlasRect | undefined,\n): margin is AtlasRect {\n return (\n !!margin &&\n (margin.x !== 0 ||\n margin.y !== 0 ||\n margin.width !== 0 ||\n margin.height !== 0)\n );\n}\n\nexport function atlasTextureMetrics(\n region: { width: number; height: number },\n margin: { width: number; height: number } | undefined,\n): AtlasSize {\n return {\n width: region.width + (margin?.width ?? 0),\n height: region.height + (margin?.height ?? 0),\n };\n}\n\n/**\n * Crop an atlas region (plus its transparent margin) into a standalone SVG data\n * URL. Producing a self-contained image lets every downstream consumer treat an\n * AtlasTexture sprite exactly like a plain Texture2D (stretch modes, nine-patch,\n * modulate tint) instead of re-deriving Godot's atlas draw rect via CSS offsets.\n *\n * When a `tint` is given, the color matrix is baked onto the raster image inside\n * this single SVG (alpha-preserving `feColorMatrix`). Doing the crop and the tint\n * in ONE flat SVG avoids wrapping the cropped SVG in a second SVG `<image>` — a\n * nested SVG-data-URI that browsers refuse to rasterize as a CSS background.\n */\nexport function atlasTextureDataUrl(\n imageUrl: string,\n atlasSize: AtlasSize,\n region: AtlasRect,\n margin: AtlasRect,\n tint?: ColorMatrix,\n): string {\n const key = atlasDataUrlKey(imageUrl, atlasSize, region, margin, tint);\n const hit = atlasDataUrlCache.get(key);\n if (hit !== undefined) {\n return hit;\n }\n const url = buildAtlasTextureDataUrl(\n imageUrl,\n atlasSize,\n region,\n margin,\n tint,\n );\n atlasDataUrlCache.set(key, url);\n return url;\n}\n\n// Memo for the atlas crop URLs (module-scoped LRU). WHY: every atlas sprite rebuilds the same\n// SVG markup + `encodeURIComponent` on every render, and a card burst re-renders hundreds of\n// them from a handful of distinct crops. Pure string→string, so a hit is byte-identical.\nconst ATLAS_DATA_URL_CACHE_LIMIT = 200;\nconst atlasDataUrlCache = createStringLru<string>(ATLAS_DATA_URL_CACHE_LIMIT);\n\n// Full input signature. Fixed-arity numeric fields FIRST and the (unbounded, arbitrary-content)\n// image url LAST, so a url containing the separator can never alias another key's fields.\nfunction atlasDataUrlKey(\n imageUrl: string,\n atlasSize: AtlasSize,\n region: AtlasRect,\n margin: AtlasRect,\n tint: ColorMatrix | undefined,\n): string {\n const tintKey = tint ? tint.rows.map((row) => row.join(\",\")).join(\";\") : \"\";\n return (\n `${atlasSize.width},${atlasSize.height}` +\n `|${region.x},${region.y},${region.width},${region.height}` +\n `|${margin.x},${margin.y},${margin.width},${margin.height}` +\n `|${tintKey}|${imageUrl}`\n );\n}\n\n/** TEST-ONLY: clear the atlas data-URL memo so a test starts from an empty cache. */\nexport function __resetAtlasDataUrlCacheForTest(): void {\n atlasDataUrlCache.clear();\n}\n\nfunction buildAtlasTextureDataUrl(\n imageUrl: string,\n atlasSize: AtlasSize,\n region: AtlasRect,\n margin: AtlasRect,\n tint?: ColorMatrix,\n): string {\n const texture = atlasTextureMetrics(region, margin);\n const source = {\n x: region.x - margin.x,\n y: region.y - margin.y,\n width: texture.width,\n height: texture.height,\n };\n const left = Math.max(region.x, source.x);\n const top = Math.max(region.y, source.y);\n const right = Math.min(region.x + region.width, source.x + source.width);\n const bottom = Math.min(region.y + region.height, source.y + source.height);\n const clipped = {\n x: left,\n y: top,\n width: Math.max(0, right - left),\n height: Math.max(0, bottom - top),\n };\n const dest = {\n x: clipped.x - source.x,\n y: clipped.y - source.y,\n width: clipped.width,\n height: clipped.height,\n };\n const filterId = \"godot-texture-tint\";\n const defs = tint\n ? `<defs><filter id=\"${filterId}\" color-interpolation-filters=\"sRGB\"><feColorMatrix type=\"matrix\" values=\"${colorMatrixFeValues(tint)}\"/></filter></defs>`\n : \"\";\n const filterAttr = tint ? ` filter=\"url(#${filterId})\"` : \"\";\n const image =\n clipped.width > 0 && clipped.height > 0\n ? `<svg x=\"${round(dest.x)}\" y=\"${round(dest.y)}\" width=\"${round(dest.width)}\" height=\"${round(dest.height)}\" viewBox=\"${round(clipped.x)} ${round(clipped.y)} ${round(clipped.width)} ${round(clipped.height)}\" preserveAspectRatio=\"none\">${defs}<image href=\"${escapeAttribute(imageUrl)}\" x=\"0\" y=\"0\" width=\"${round(atlasSize.width)}\" height=\"${round(atlasSize.height)}\"${filterAttr}/></svg>`\n : \"\";\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${round(texture.width)}\" height=\"${round(texture.height)}\" viewBox=\"0 0 ${round(texture.width)} ${round(texture.height)}\">${image}</svg>`;\n return `data:image/svg+xml,${encodeURIComponent(svg)}`;\n}\n","import {\n asBoolean,\n asNumber,\n asRect2,\n asResourceRef,\n asString,\n type GodotNode,\n type GodotResource,\n type GodotVariant,\n} from \"@godot-scene-web/core\";\nimport type { GodotSceneTreeNode } from \"@godot-scene-web/layout\";\nimport {\n atlasTextureDataUrl,\n atlasTextureMetrics,\n hasAtlasMargin,\n zeroAtlasMargin,\n} from \"./atlas\";\nimport { isEmbeddedAssetUrl } from \"./css-values\";\nimport type {\n GodotHtmlFontFace,\n GodotHtmlRenderOptions,\n GodotResolvedResource,\n} from \"./types\";\n\nexport function resolveFont(\n value: GodotVariant | undefined,\n node: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n): GodotResolvedResource | undefined {\n const fontRef = asResourceRef(value);\n if (!fontRef) {\n return undefined;\n }\n const source = sourceNodeForLayout(node);\n return fontResource(\n normalizeResource(options.resolveResource?.(fontRef, source)),\n options,\n source,\n );\n}\n\nexport function sourceNodeForLayout(node: GodotSceneTreeNode): GodotNode {\n return (\n node.source ?? {\n name: node.name,\n type: node.type,\n parent: node.parentPath ?? undefined,\n attributes: {},\n properties: node.properties,\n }\n );\n}\n\nexport function registerFontFace(\n fontFaces: GodotHtmlFontFace[],\n font: GodotResolvedResource | undefined,\n): void {\n if (!font?.fontFamily || !font.fontUrl) {\n return;\n }\n fontFaces.push({\n fontFamily: font.fontFamily,\n url: font.fontUrl,\n style: font.fontStyle ?? \"normal\",\n weight: String(font.fontWeight ?? \"400\"),\n });\n}\n\nexport function uniqueFontFaces(\n fontFaces: GodotHtmlFontFace[],\n): GodotHtmlFontFace[] {\n const byKey = new Map<string, GodotHtmlFontFace>();\n for (const face of fontFaces) {\n byKey.set(\n `${face.fontFamily}\\n${face.url}\\n${face.style}\\n${face.weight}`,\n face,\n );\n }\n return [...byKey.values()];\n}\n\nexport function normalizeResource(\n value: unknown,\n): GodotResolvedResource | undefined {\n if (typeof value === \"string\") {\n return { path: value, url: value };\n }\n if (isResourceDocument(value)) {\n return { type: asString(value.header?.attributes.type), document: value };\n }\n if (value && typeof value === \"object\") {\n return value as GodotResolvedResource;\n }\n return undefined;\n}\n\nexport function imageResource(\n resource: GodotResolvedResource | undefined,\n options: GodotHtmlRenderOptions,\n source: GodotNode,\n): GodotResolvedResource {\n if (!resource) {\n return {};\n }\n const document = resource.document;\n if (\n document &&\n asString(document.header?.attributes.type) === \"AtlasTexture\"\n ) {\n const region = asRect2(document.properties.region);\n const margin = asRect2(document.properties.margin) ?? zeroAtlasMargin();\n const atlasRef = asResourceRef(document.properties.atlas);\n const atlas =\n resource.atlas ??\n (atlasRef\n ? normalizeResource(options.resolveResource?.(atlasRef, source))\n : undefined);\n // Resolve AtlasTexture sprites to a standalone cropped image so downstream\n // rendering treats them like any plain Texture2D (stretch modes, nine-patch,\n // tint) rather than re-deriving Godot's atlas draw rect from region/margin.\n if (resource.url) {\n // The host already provides a directly-usable sprite image (e.g. a\n // pre-cropped raster); use it as-is rather than re-embedding the atlas.\n return {\n ...resource,\n atlas,\n region: undefined,\n margin: undefined,\n size:\n resource.size ??\n (region ? atlasTextureMetrics(region, margin) : undefined),\n };\n }\n if (atlas?.url && atlas?.size && region && isEmbeddedAssetUrl(atlas.url)) {\n // Crop the region (+margin) out of the atlas into a standalone image.\n // Keep the crop inputs in `atlasCrop` so a later tint can re-bake the crop\n // and the color matrix into one flat SVG (see `assignTextureTintStyles`).\n // ONLY for an EMBEDDED (`data:`) atlas: an SVG `<image>` can rasterize its own\n // bytes but NOT an external URL (browsers load CSS-image SVGs in a restricted\n // mode that blocks external refs — see `isEmbeddedAssetUrl`). An external atlas\n // `.tres` sprite must fall through to the raw-atlas branch below and paint the\n // region via CSS `background-position`/`-size`, else it renders blank.\n return {\n ...resource,\n atlas,\n url: atlasTextureDataUrl(atlas.url, atlas.size, region, margin),\n atlasCrop: { region, margin },\n path: atlas.path ?? resource.path,\n region: undefined,\n margin: undefined,\n size: atlasTextureMetrics(region, margin),\n };\n }\n // Fall back to the raw atlas when its size is unknown: keep region/margin so\n // the texture layer can still paint the region via CSS offsets.\n return {\n ...resource,\n atlas,\n url: atlas?.url,\n path: atlas?.path ?? resource.path,\n region: resource.region ?? region,\n margin: resource.margin ?? (hasAtlasMargin(margin) ? margin : undefined),\n size:\n resource.size ??\n (region ? atlasTextureMetrics(region, margin) : undefined),\n };\n }\n return resource;\n}\n\nexport function fontResource(\n resource: GodotResolvedResource | undefined,\n options: GodotHtmlRenderOptions,\n source: GodotNode,\n): GodotResolvedResource {\n if (!resource) {\n return {};\n }\n const document = resource.document;\n if (\n document &&\n asString(document.header?.attributes.type) === \"FontVariation\"\n ) {\n const baseRef = asResourceRef(document.properties.base_font);\n const baseResource = baseRef\n ? normalizeResource(options.resolveResource?.(baseRef, source))\n : undefined;\n const base =\n baseResource?.path !== resource.path\n ? fontResource(baseResource, options, source)\n : {};\n const fontMsdf = asBoolean(\n document.properties.multichannel_signed_distance_field,\n );\n return {\n ...base,\n ...resource,\n fontFamily: resource.fontFamily ?? base.fontFamily,\n fontUrl: resource.fontUrl ?? base.fontUrl,\n fontStyle: resource.fontStyle ?? base.fontStyle,\n fontWeight:\n resource.fontWeight ??\n fontWeightFromVariation(document) ??\n base.fontWeight,\n glyphSpacing:\n resource.glyphSpacing ??\n asNumber(document.properties.spacing_glyph) ??\n base.glyphSpacing,\n fontMsdf: resource.fontMsdf ?? fontMsdf ?? base.fontMsdf,\n path: resource.path ?? base.path,\n url: resource.url ?? base.url,\n };\n }\n if (document && asString(document.header?.attributes.type) === \"FontFile\") {\n const fontPath = asString(document.properties.font_path);\n if (fontPath) {\n const fontUrlValue =\n resource.fontUrl ??\n (resource.url && !resource.url.startsWith(\"res://\")\n ? resource.url\n : undefined);\n return {\n ...resource,\n fontFamily:\n resource.fontFamily ??\n fontPath\n .split(\"/\")\n .at(-1)\n ?.replace(/\\.[^.]+$/, \"\"),\n fontUrl: fontUrlValue,\n fontStyle: resource.fontStyle ?? fontStyleFromPath(fontPath),\n fontWeight: resource.fontWeight ?? \"400\",\n fontMsdf:\n resource.fontMsdf ??\n asBoolean(document.properties.multichannel_signed_distance_field),\n };\n }\n }\n return {\n ...resource,\n fontFamily:\n resource.fontFamily ??\n resource.path\n ?.split(\"/\")\n .at(-1)\n ?.replace(/\\.[^.]+$/, \"\"),\n fontUrl: resource.fontUrl ?? fontUrl(resource),\n fontStyle: resource.fontStyle ?? fontStyleFromPath(resource.path),\n fontWeight: resource.fontWeight ?? \"400\",\n };\n}\n\nfunction fontWeightFromVariation(document: GodotResource): number | undefined {\n const variation = document.properties.variation_opentype;\n if (\n !variation ||\n typeof variation !== \"object\" ||\n Array.isArray(variation) ||\n \"type\" in variation\n ) {\n return undefined;\n }\n return asNumber((variation as Record<string, GodotVariant>)[\"2003265652\"]);\n}\n\nfunction fontUrl(resource: GodotResolvedResource): string | undefined {\n if (!resource.url || resource.url.startsWith(\"res://\")) {\n return undefined;\n }\n return /\\.(?:ttf|otf|woff2?|ttc)(?:$|[?#])/i.test(resource.url)\n ? resource.url\n : undefined;\n}\n\nfunction fontStyleFromPath(\n path: string | undefined,\n): \"normal\" | \"italic\" | undefined {\n return path && /italic/i.test(path) ? \"italic\" : undefined;\n}\n\nfunction isResourceDocument(value: unknown): value is GodotResource {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n \"kind\" in value &&\n \"properties\" in value,\n );\n}\n","import {\n asNumber,\n asResourceRef,\n asString,\n type GodotVariant,\n} from \"@godot-scene-web/core\";\nimport type { GodotSceneTreeNode } from \"@godot-scene-web/layout\";\nimport { colorCss, round } from \"./css-values\";\nimport { normalizeResource, sourceNodeForLayout } from \"./resources\";\nimport type { GodotHtmlRenderOptions, GodotResolvedResource } from \"./types\";\n\nexport function assignPanelStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n node: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n): void {\n const source = sourceNodeForLayout(node);\n const stylebox =\n resolveStyleBox(props[\"theme_override_styles/panel\"], node, options) ??\n resolveStyleBox(options.resolveTheme?.(source, \"panel\"), node, options);\n applyStyleBox(style, attributes, stylebox, \"panel\");\n}\n\nexport function assignInputStyleBoxStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n node: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n): void {\n const source = sourceNodeForLayout(node);\n const stylebox =\n resolveStyleBox(props[\"theme_override_styles/normal\"], node, options) ??\n resolveStyleBox(options.resolveTheme?.(source, \"normal\"), node, options);\n applyStyleBox(style, attributes, stylebox, \"normal\");\n}\n\nfunction resolveStyleBox(\n value: GodotVariant | undefined,\n node: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n): GodotResolvedResource | undefined {\n const ref = asResourceRef(value);\n return ref\n ? normalizeResource(\n options.resolveResource?.(ref, sourceNodeForLayout(node)),\n )\n : normalizeResource(value);\n}\n\nfunction applyStyleBox(\n style: Record<string, string>,\n attributes: Record<string, string>,\n resource: GodotResolvedResource | undefined,\n slot: string,\n): void {\n const document = resource?.document;\n const type = resource?.type ?? asString(document?.header?.attributes.type);\n if (!type) {\n return;\n }\n attributes[`data-godot-stylebox-${slot}`] = type;\n if (type === \"StyleBoxEmpty\") {\n style.background = \"transparent\";\n style.border = \"0\";\n return;\n }\n if (type !== \"StyleBoxFlat\" || !document) {\n return;\n }\n const props = document.properties;\n const bg = colorCss(props.bg_color);\n const borderColor = colorCss(props.border_color);\n if (bg) {\n style.background = bg;\n }\n if (borderColor) {\n style[\"border-color\"] = borderColor;\n }\n style[\"border-style\"] = \"solid\";\n const widths = [\n asNumber(props.border_width_top) ?? asNumber(props.border_width_all) ?? 0,\n asNumber(props.border_width_right) ?? asNumber(props.border_width_all) ?? 0,\n asNumber(props.border_width_bottom) ??\n asNumber(props.border_width_all) ??\n 0,\n asNumber(props.border_width_left) ?? asNumber(props.border_width_all) ?? 0,\n ];\n if (widths.some((width) => width !== 0)) {\n style[\"border-width\"] = widths\n .map((width) => `${round(width)}px`)\n .join(\" \");\n }\n const radii = [\n asNumber(props.corner_radius_top_left) ??\n asNumber(props.corner_radius_all) ??\n 0,\n asNumber(props.corner_radius_top_right) ??\n asNumber(props.corner_radius_all) ??\n 0,\n asNumber(props.corner_radius_bottom_right) ??\n asNumber(props.corner_radius_all) ??\n 0,\n asNumber(props.corner_radius_bottom_left) ??\n asNumber(props.corner_radius_all) ??\n 0,\n ];\n if (radii.some((radius) => radius !== 0)) {\n style[\"border-radius\"] = radii\n .map((radius) => `${round(radius)}px`)\n .join(\" \");\n }\n const margins = [\n asNumber(props.content_margin_top),\n asNumber(props.content_margin_right),\n asNumber(props.content_margin_bottom),\n asNumber(props.content_margin_left),\n ];\n if (margins.some((margin) => margin !== undefined)) {\n style.padding = margins\n .map((margin) => `${round(margin ?? 0)}px`)\n .join(\" \");\n }\n}\n\nexport interface StyleBoxMetrics {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\nexport function panelStyleBoxMetrics(\n node: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n): StyleBoxMetrics {\n const source = sourceNodeForLayout(node);\n return styleBoxMetrics(\n resolveStyleBox(\n node.properties[\"theme_override_styles/panel\"],\n node,\n options,\n ) ??\n resolveStyleBox(options.resolveTheme?.(source, \"panel\"), node, options),\n );\n}\n\nfunction styleBoxMetrics(\n resource: GodotResolvedResource | undefined,\n): StyleBoxMetrics {\n const document = resource?.document;\n const type = resource?.type ?? asString(document?.header?.attributes.type);\n if (!type || type === \"StyleBoxEmpty\") {\n return { left: 0, top: 0, right: 0, bottom: 0 };\n }\n const props = document?.properties ?? {};\n if (type === \"StyleBoxFlat\") {\n const borders = {\n left:\n asNumber(props.border_width_left) ??\n asNumber(props.border_width_all) ??\n 0,\n top:\n asNumber(props.border_width_top) ??\n asNumber(props.border_width_all) ??\n 0,\n right:\n asNumber(props.border_width_right) ??\n asNumber(props.border_width_all) ??\n 0,\n bottom:\n asNumber(props.border_width_bottom) ??\n asNumber(props.border_width_all) ??\n 0,\n };\n return {\n left: styleBoxMargin(props, \"left\", borders.left),\n top: styleBoxMargin(props, \"top\", borders.top),\n right: styleBoxMargin(props, \"right\", borders.right),\n bottom: styleBoxMargin(props, \"bottom\", borders.bottom),\n };\n }\n return {\n left: Math.max(\n 0,\n asNumber(props.content_margin_left) ??\n asNumber(props.content_margin_all) ??\n 0,\n ),\n top: Math.max(\n 0,\n asNumber(props.content_margin_top) ??\n asNumber(props.content_margin_all) ??\n 0,\n ),\n right: Math.max(\n 0,\n asNumber(props.content_margin_right) ??\n asNumber(props.content_margin_all) ??\n 0,\n ),\n bottom: Math.max(\n 0,\n asNumber(props.content_margin_bottom) ??\n asNumber(props.content_margin_all) ??\n 0,\n ),\n };\n}\n\nfunction styleBoxMargin(\n props: Record<string, GodotVariant>,\n side: \"left\" | \"top\" | \"right\" | \"bottom\",\n fallback: number,\n): number {\n const value =\n asNumber(props[`content_margin_${side}`]) ??\n asNumber(props.content_margin_all);\n return value !== undefined && value >= 0 ? value : fallback;\n}\n","import {\n asBoolean,\n asNumber,\n asVector2,\n type GodotVariant,\n} from \"@godot-scene-web/core\";\nimport type { GodotSceneTreeNode } from \"@godot-scene-web/layout\";\nimport { cssSize, round } from \"./css-values\";\nimport { sourceNodeForLayout } from \"./resources\";\nimport { panelStyleBoxMetrics } from \"./style-box\";\nimport type {\n GodotHtmlContainerLayout,\n GodotHtmlNode,\n GodotHtmlRenderOptions,\n} from \"./types\";\n\n// Godot `Control.SizeFlags` bits.\nconst SIZE_FILL = 1;\nconst SIZE_EXPAND = 2;\nconst SIZE_SHRINK_CENTER = 4;\nconst SIZE_SHRINK_END = 8;\n\n/**\n * Browser-native geometry pass — the rect-free counterpart of\n * `assignContainerLayoutStyles`. Instead of pinning every node to a computed\n * pixel rect, it lets the CSS engine resolve layout: containers become flex/grid\n * boxes and their children flow; anchored Controls map their anchors+offsets to\n * CSS `position:absolute` insets; the root takes the viewport size. Real DOM text\n * therefore sizes itself (a label with no fixed size grows to its text), which is\n * the whole point — and why a missing `resolveTextContentSize` no longer collapses\n * a `RichTextLabel`.\n */\nexport function assignBrowserNativeLayout(\n nodes: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n viewport: { width: number; height: number },\n): void {\n const htmlByPath = new Map(nodes.map((node) => [node.path, node]));\n // Pass 1 — per-node box: the outer box from anchors (root takes the viewport).\n // Container children are reflowed in pass 2, which overrides this.\n for (const node of nodes) {\n const layout = layoutByPath.get(node.path);\n if (!layout) {\n continue;\n }\n if (node.parentPath === null) {\n assignRootGeometry(node, viewport);\n } else {\n assignAnchorGeometry(node, layout);\n }\n }\n // Pass 2 — CSS containers: emit the parent's flex/grid box (from properties, no\n // rects) and reflow each direct child as a native flow item.\n for (const parent of nodes) {\n const layout = layoutByPath.get(parent.path);\n if (!layout || !isCssContainerType(parent.type)) {\n continue;\n }\n parent.containerLayout = containerLayoutKind(parent.type);\n parent.attributes[\"data-godot-container-layout\"] = parent.containerLayout;\n const horizontal = containerIsHorizontal(parent.type, layout);\n assignContainerParentStyle(parent, layout, options, horizontal);\n const children = parent.children\n .map((path) => htmlByPath.get(path))\n .filter((child): child is GodotHtmlNode => Boolean(child))\n .filter(\n (child) => layoutByPath.get(child.path)?.parentPath === parent.path,\n );\n for (const child of children) {\n // Godot containers only lay out CONTROL children (Container::_sort_children);\n // a Node2D child keeps its own canvas transform.\n if (isNode2DType(child.type)) {\n continue;\n }\n const childLayout = layoutByPath.get(child.path);\n if (childLayout) {\n setFlowChild(child, childLayout, parent.type, horizontal);\n }\n }\n }\n // Pass 3 — the self-layer (fill vs in-flow text). Runs after pass 2 so it reads\n // each node's FINAL outer box: a container child's anchor insets were replaced by\n // flow styles (and possibly a `min-height` from `custom_minimum_size`), which\n // changes the fill-vs-auto decision for text.\n for (const node of nodes) {\n if (layoutByPath.has(node.path)) {\n configureSelfLayer(node);\n }\n }\n // Invisible nodes need no geometry pass: the model builder prunes effectively\n // hidden subtrees to comment placeholders, which take no space in any flow —\n // matching Godot containers allocating nothing for a hidden child.\n}\n\n// What a container parent tells each of its children about itself, so the child\n// can compute its own flow box (`setFlowChild` needs only the parent's TYPE and\n// axis — never the parent's resolved style or its siblings). `parentType === null`\n// ⇒ the parent is not a CSS container, so the child keeps its anchor box.\nexport interface BrowserNativeParentContext {\n parentType: string | null;\n parentHorizontal: boolean;\n}\n\nexport const ROOT_PARENT_CONTEXT: BrowserNativeParentContext = {\n parentType: null,\n parentHorizontal: false,\n};\n\n// The per-node counterpart of `assignBrowserNativeLayout`: run the SAME three\n// passes for ONE node, in the same order, and return the context this node hands\n// to ITS children. The batch loop above does pass 1 for all nodes, then pass 2,\n// then pass 3; but each pass touches only a node's own props + (for pass 2) the\n// parent's type/axis — never a sibling — so collapsing them per node is identical\n// as long as parents are visited before children (the Vue component renderer\n// walks the structure parent-first). Keeping this beside the batch — calling the\n// same private `assignRootGeometry`/`assignAnchorGeometry`/`assignContainerParentStyle`/\n// `setFlowChild`/`configureSelfLayer` — means the only thing mirrored is the\n// 4-step ORDER; the geometry math has a single source of truth. The batch path\n// (and its goldens) is untouched.\nexport function assignBrowserNativeNodeLayout(\n node: GodotHtmlNode,\n layout: GodotSceneTreeNode,\n parent: BrowserNativeParentContext,\n options: GodotHtmlRenderOptions,\n viewport: { width: number; height: number },\n): BrowserNativeParentContext {\n // Pass 1 — own outer box (root takes the viewport; others map anchors→insets).\n if (node.parentPath === null) {\n assignRootGeometry(node, viewport);\n } else {\n assignAnchorGeometry(node, layout);\n }\n // Pass 2a — this node AS a container parent: emit its flex/grid box and the\n // context its children consume.\n let childContext = ROOT_PARENT_CONTEXT;\n if (isCssContainerType(node.type)) {\n node.containerLayout = containerLayoutKind(node.type);\n node.attributes[\"data-godot-container-layout\"] = node.containerLayout;\n const horizontal = containerIsHorizontal(node.type, layout);\n assignContainerParentStyle(node, layout, options, horizontal);\n childContext = { parentType: node.type, parentHorizontal: horizontal };\n }\n // Pass 2b — this node AS a container's child: replace the anchor box with flow.\n // Node2D children are exempt — Godot containers only lay out Controls\n // (Container::_sort_children); a Node2D keeps its own canvas transform.\n if (\n parent.parentType !== null &&\n isCssContainerType(parent.parentType) &&\n !isNode2DType(node.type)\n ) {\n setFlowChild(node, layout, parent.parentType, parent.parentHorizontal);\n }\n // Pass 3 — the self-layer, reading the node's FINAL outer box.\n configureSelfLayer(node);\n return childContext;\n}\n\n// Text gives a node its height: make the painted/text self-layer IN-FLOW so the\n// real DOM text contributes content height to the outer element (which a parent\n// container then flows). Non-text paint nodes keep an absolute self-layer that\n// fills the anchor-/flow-sized outer box.\nfunction configureSelfLayer(node: GodotHtmlNode): void {\n if (isTextNode(node.type)) {\n node.selfStyle.position = \"relative\";\n node.selfStyle.width = \"100%\";\n // The self-layer carries the real DOM text and its `vertical_alignment`\n // (emitted as `align-items` by assignTextStyles). When the OUTER box already\n // has a definite height — an explicit `height`, or both `top`+`bottom` insets\n // from stretch anchors — fill it so bottom/center alignment has room to work\n // (e.g. stacked lobby-nameplate Labels that bottom-align to avoid overlapping).\n // A flow child sized by `min-height` (from `custom_minimum_size`, e.g. the\n // TopBar HpLabel's 80px box) gets the SAME min-height mirrored onto the\n // self-layer — `height:100%` cannot resolve against a min-height-only parent,\n // but a px min-height gives the alignment its room while longer text can still\n // grow the box. When the height is indefinite — container-flowed, or\n // point-anchored with no size — leave it auto so the text DRIVES the box\n // height (the InfoPanel RichTextLabel fix).\n if (hasDefiniteHeight(node.style)) {\n node.selfStyle.height = \"100%\";\n } else {\n delete node.selfStyle.height;\n const minHeight = node.style[\"min-height\"];\n if (minHeight !== undefined) {\n node.selfStyle[\"min-height\"] = minHeight;\n }\n }\n delete node.selfStyle.left;\n delete node.selfStyle.top;\n } else {\n node.selfStyle.position = \"absolute\";\n node.selfStyle.left = \"0\";\n node.selfStyle.top = \"0\";\n node.selfStyle.width = \"100%\";\n node.selfStyle.height = \"100%\";\n }\n}\n\n// The outer box has a CSS-resolvable height when an explicit `height` is set, or\n// when both `top` and `bottom` insets are pinned (absolute positioning then\n// resolves the height). A lone `top` (point anchor / flow placeholder) does not.\nfunction hasDefiniteHeight(style: Record<string, string>): boolean {\n if (style.height !== undefined) {\n return true;\n }\n return style.top !== undefined && style.bottom !== undefined;\n}\n\n// The horizontal counterpart: a definite width is an explicit px `width` (NOT the\n// content-driven `min-content`/`max-content` keywords a point-anchored container\n// emits), or both `left`+`right` insets pinned (stretch). An auto width (a grid/\n// flow item, whose `width` was deleted) is NOT definite — it hugs/fills via its\n// container. Used to decide whether an overlay grid may let a child's min-content\n// grow it (content-driven) or must stay at its given size (definite).\nfunction hasDefiniteWidth(style: Record<string, string>): boolean {\n if (\n style.width !== undefined &&\n style.width !== \"min-content\" &&\n style.width !== \"max-content\"\n ) {\n return true;\n }\n return style.left !== undefined && style.right !== undefined;\n}\n\nfunction assignRootGeometry(\n node: GodotHtmlNode,\n viewport: { width: number; height: number },\n): void {\n node.positioning = \"root\";\n node.attributes[\"data-godot-positioning\"] = \"root\";\n node.style.position = \"relative\";\n node.style.width = `${round(viewport.width)}px`;\n node.style.height = `${round(viewport.height)}px`;\n delete node.style.left;\n delete node.style.top;\n}\n\n// Node2D subclasses this renderer knows (the 2D branch of RENDERABLE_TYPES). A\n// Node2D has NO anchors/offsets: in Godot its placement is its own canvas\n// transform — `position`, then rotation/skew/scale around the node ORIGIN\n// (Node2D::get_transform, scene/2d/node_2d.cpp) — not the Control anchor cascade.\n// Containers also never lay out Node2D children (Container::_sort_children only\n// touches Controls), so these keep their own transform even inside a flex/grid\n// parent.\nconst NODE2D_TYPES = new Set([\n \"AnimatedSprite2D\",\n \"BackBufferCopy\",\n \"Camera2D\",\n \"CanvasGroup\",\n \"CPUParticles2D\",\n \"FmodListener2D\",\n \"GPUParticles2D\",\n \"LightOccluder2D\",\n \"Line2D\",\n \"Marker2D\",\n \"MeshInstance2D\",\n \"Node2D\",\n \"Path2D\",\n \"PathFollow2D\",\n \"Sprite2D\",\n]);\n\nexport function isNode2DType(type: string): boolean {\n return NODE2D_TYPES.has(type);\n}\n\n// Browser-native placement for a Node2D: the anchor recompute (below) would delete\n// the type-specific box the visual assigners computed RELATIVE TO THE NODE ORIGIN\n// (a particle emitter's visibility-rect box, a centered sprite's -w/2 shift, a\n// Line2D's points bbox) and reset the node to the parent origin at 0×0 (anchors/\n// offsets read as 0) — which parked every background emitter/sprite at its parent's\n// top-left corner. Instead, keep that own-origin box and translate it by the node's\n// `position` (Godot: a Node2D's rect is position + transform · local — the computed\n// rect path reads the same `position`/`position_x` fallbacks in layout/rects.ts).\n// Rotation/scale/skew must pivot around the NODE ORIGIN, not the box corner or its\n// center: the box corner sits at (bx, by) relative to the origin, so the origin in\n// box-local coordinates is (-bx, -by). (For a centered Sprite2D this reproduces the\n// `w/2 - offset` origin `assignSprite2DStyles` already emits.)\nfunction assignNode2DGeometry(\n node: GodotHtmlNode,\n layout: GodotSceneTreeNode,\n): void {\n node.positioning = \"absolute\";\n node.attributes[\"data-godot-positioning\"] = \"absolute\";\n node.style.position = \"absolute\";\n const props = layout.properties;\n const position = asVector2(props.position);\n const x = asNumber(props.position_x) ?? position?.x ?? 0;\n const y = asNumber(props.position_y) ?? position?.y ?? 0;\n const boxX = cssSize(node.style.left) ?? 0;\n const boxY = cssSize(node.style.top) ?? 0;\n if (x !== 0 || y !== 0) {\n node.style.left = `${round(boxX + x)}px`;\n node.style.top = `${round(boxY + y)}px`;\n }\n if (node.style.transform && (boxX !== 0 || boxY !== 0)) {\n node.style[\"transform-origin\"] = `${round(-boxX)}px ${round(-boxY)}px`;\n }\n}\n\n// Map a Control's anchors (fraction of parent) + offsets (px) to CSS absolute\n// insets. Setting all four insets lets the browser resolve width/height exactly\n// the way Godot derives the rect from anchors+offsets — for any anchor config\n// (point anchors give a fixed size, FULL_RECT fills, …). The nearest positioned\n// ancestor (the root, or another anchored Control — both `position:absolute`/\n// `relative`) is the containing block, mirroring Godot's parent-relative anchors.\nfunction assignAnchorGeometry(\n node: GodotHtmlNode,\n layout: GodotSceneTreeNode,\n): void {\n // Node2Ds (Line2D, Sprite2D, particles, …) bypass the anchor recompute entirely —\n // see `assignNode2DGeometry`.\n if (isNode2DType(node.type)) {\n assignNode2DGeometry(node, layout);\n return;\n }\n const props = layout.properties;\n const anchorLeft = anchorFraction(props.anchor_left);\n const anchorTop = anchorFraction(props.anchor_top);\n const anchorRight = anchorFraction(props.anchor_right);\n const anchorBottom = anchorFraction(props.anchor_bottom);\n const offsetLeft = asNumber(props.offset_left) ?? 0;\n const offsetTop = asNumber(props.offset_top) ?? 0;\n const offsetRight = asNumber(props.offset_right) ?? 0;\n const offsetBottom = asNumber(props.offset_bottom) ?? 0;\n node.positioning = \"absolute\";\n node.attributes[\"data-godot-positioning\"] = \"absolute\";\n node.style.position = \"absolute\";\n for (const side of [\"left\", \"top\", \"right\", \"bottom\", \"width\", \"height\"]) {\n delete node.style[side];\n }\n // Horizontal: a stretch anchor (left != right) pins both insets so the browser\n // resolves width; a point anchor (left == right) pins `left` plus an explicit\n // width from the offsets — or leaves width `auto` (content / min-size) when the\n // offsets give no size, so a container sizes to its children the way Godot's\n // `get_minimum_size()` does instead of collapsing to 0.\n //\n // A point-anchored box smaller than its `custom_minimum_size` grows to it the\n // way Godot's Control::_size_changed does (the inspect-relic FrameBg: a 40px\n // authored box with a 300px minimum): BEGIN(0) shifts the start edge back,\n // BOTH(2) centers, END(1, the default) extends forward. Offsets and minimum\n // are both static doc values, so the grown box is emitted directly. Zero-size\n // boxes keep the content-driven `auto` behavior above.\n const minimum = customMinimumSize(props);\n const growHorizontal = asNumber(props.grow_horizontal) ?? 1;\n node.style.left = cssInset(anchorLeft, offsetLeft);\n if (anchorLeft === anchorRight) {\n let width = offsetRight - offsetLeft;\n if (width > 0 && minimum.width > width) {\n const delta = minimum.width - width;\n if (growHorizontal === 0) {\n node.style.left = cssInset(anchorLeft, offsetLeft - delta);\n } else if (growHorizontal === 2) {\n node.style.left = cssInset(anchorLeft, offsetLeft - delta / 2);\n }\n width = minimum.width;\n }\n if (width > 0) {\n if (isCssContainerType(node.type)) {\n // A point-anchored container sizes to its content the way Godot's\n // `get_minimum_size()` does, growing past the authored box per\n // `grow_horizontal` (END right, BEGIN left, BOTH centered). Emit the\n // authored/min box as a `min-width` FLOOR and let CSS hug the content;\n // when content fits the box this resolves to the box width unchanged, so\n // only oversized content grows (e.g. a caption whose text exceeds a fixed\n // `MarginContainer`). Centering uses the independent `translate` longhand\n // so it composes with any scale/rotation `transform`.\n //\n // Use `min-content`, NOT `max-content`: Godot's `get_minimum_size()` is the\n // child MINIMUM, which for a wrapping `RichTextLabel`/`Label` (autowrap) is\n // the longest WORD — it wraps within the box rather than forcing the box to\n // its full unwrapped width. `max-content` measures the text UNWRAPPED (the\n // whole paragraph on one line), so a wrapping event/description label blew the\n // container far past its anchored width and never wrapped. `min-content` still\n // grows the box for NON-wrapping content (a single-line Label can't break, so\n // its min-content IS its full text), preserving the caption-exceeds-box case.\n node.style[\"min-width\"] = `${round(width)}px`;\n node.style.width = \"min-content\";\n if (growHorizontal === 2) {\n node.style.left = cssInset(\n anchorLeft,\n (offsetLeft + offsetRight) / 2,\n );\n node.style.translate = \"-50% 0\";\n } else if (growHorizontal === 0) {\n delete node.style.left;\n node.style.right = cssInset(1 - anchorRight, -offsetRight);\n }\n } else {\n node.style.width = `${round(width)}px`;\n }\n }\n } else {\n node.style.right = cssInset(1 - anchorRight, -offsetRight);\n }\n node.style.top = cssInset(anchorTop, offsetTop);\n if (anchorTop === anchorBottom) {\n let height = offsetBottom - offsetTop;\n if (height > 0 && minimum.height > height) {\n const delta = minimum.height - height;\n const grow = asNumber(props.grow_vertical) ?? 1;\n if (grow === 0) {\n node.style.top = cssInset(anchorTop, offsetTop - delta);\n } else if (grow === 2) {\n node.style.top = cssInset(anchorTop, offsetTop - delta / 2);\n }\n height = minimum.height;\n }\n if (height > 0) {\n node.style.height = `${round(height)}px`;\n }\n } else {\n node.style.bottom = cssInset(1 - anchorBottom, -offsetBottom);\n }\n}\n\nfunction anchorFraction(value: GodotVariant | undefined): number {\n return asNumber(value) ?? 0;\n}\n\n// `<fraction>*100% (+|-) <px>px`, collapsed to the simplest form CSS accepts.\nfunction cssInset(fraction: number, px: number): string {\n const percent = round(fraction * 100);\n const offset = round(px);\n if (offset === 0) {\n return `${percent}%`;\n }\n if (percent === 0) {\n return `${offset}px`;\n }\n return offset < 0\n ? `calc(${percent}% - ${round(Math.abs(px))}px)`\n : `calc(${percent}% + ${offset}px)`;\n}\n\n// Reflow a container's direct child as a native flow item: drop the absolute box,\n// carry `custom_minimum_size` to CSS min-size, and translate Godot size flags to\n// flex grow (main axis EXPAND) + align-self (cross-axis fill/shrink).\nfunction setFlowChild(\n child: GodotHtmlNode,\n layout: GodotSceneTreeNode,\n parentType: string,\n parentHorizontal: boolean,\n): void {\n child.positioning = \"container-managed\";\n child.attributes[\"data-godot-positioning\"] = \"container-managed\";\n child.style.position = \"relative\";\n for (const side of [\"left\", \"top\", \"right\", \"bottom\", \"width\", \"height\"]) {\n delete child.style[side];\n }\n const props = layout.properties;\n const min = customMinimumSize(props);\n if (min.width > 0) {\n child.style[\"min-width\"] = `${round(min.width)}px`;\n }\n if (min.height > 0) {\n child.style[\"min-height\"] = `${round(min.height)}px`;\n }\n if (parentType === \"GridContainer\") {\n // Grid cells are tracked by the parent's `grid-template`; default stretch.\n return;\n }\n if (\n parentType === \"CenterContainer\" ||\n parentType === \"AspectRatioContainer\"\n ) {\n // The parent centers a single child; let it size to content.\n child.style.flex = \"0 0 auto\";\n return;\n }\n if (parentType === \"MarginContainer\" || parentType === \"PanelContainer\") {\n // EVERY child fills the same content rect and overlaps the others (Godot fits each\n // child to the rect; it never stacks them). One grid cell (overlayGrid on the parent)\n // + grid-area 1/1 overlays them — a column flex would split the height between them.\n child.style[\"grid-area\"] = \"1 / 1\";\n // The grid cell is a DEFINITE rect (the parent fits each child to its content rect),\n // but grid-stretch alone is invisible to `hasDefiniteHeight` (it only reads inline\n // `height`/`top`+`bottom`). Make the fill explicit so a text child's self-layer gets\n // `height:100%` and `vertical_alignment` (align-items) has room to center — e.g. the\n // reward-row RichTextLabel inside its LabelContainer MarginContainer. A grid item's\n // `height:100%` resolves against the cell when definite and degrades to auto otherwise.\n child.style.height = \"100%\";\n return;\n }\n // Box / Flow containers.\n const horizontalFlags = asNumber(props.size_flags_horizontal) ?? SIZE_FILL;\n const verticalFlags = asNumber(props.size_flags_vertical) ?? SIZE_FILL;\n const mainFlags = parentHorizontal ? horizontalFlags : verticalFlags;\n const crossFlags = parentHorizontal ? verticalFlags : horizontalFlags;\n child.style.flex =\n (mainFlags & SIZE_EXPAND) === SIZE_EXPAND ? \"1 1 auto\" : \"0 0 auto\";\n const align = crossAlignSelf(crossFlags);\n if (align) {\n child.style[\"align-self\"] = align;\n }\n}\n\nfunction crossAlignSelf(flags: number): string | undefined {\n if ((flags & SIZE_SHRINK_CENTER) === SIZE_SHRINK_CENTER) {\n return \"center\";\n }\n if ((flags & SIZE_SHRINK_END) === SIZE_SHRINK_END) {\n return \"flex-end\";\n }\n if ((flags & SIZE_FILL) === SIZE_FILL) {\n return \"stretch\";\n }\n return \"flex-start\";\n}\n\nfunction customMinimumSize(props: Record<string, GodotVariant>): {\n width: number;\n height: number;\n} {\n const vector = asVector2(props.custom_minimum_size);\n return {\n width: vector?.x ?? asNumber(props.custom_minimum_size_x) ?? 0,\n height: vector?.y ?? asNumber(props.custom_minimum_size_y) ?? 0,\n };\n}\n\n// Emit the container's own CSS box from its properties/theme (rect-free). Mirrors\n// the parent-side decisions of `assignContainerLayoutStyles` without the per-child\n// pixel math.\nfunction assignContainerParentStyle(\n parent: GodotHtmlNode,\n layout: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n horizontal: boolean,\n): void {\n const type = parent.type;\n const style = parent.style;\n if (isBoxContainerType(type)) {\n const separation = themeNumber(layout, \"separation\", options) ?? 0;\n style.display = \"flex\";\n style[\"flex-direction\"] = horizontal ? \"row\" : \"column\";\n style[\"align-items\"] = \"stretch\";\n const justify = alignmentJustify(layout);\n if (justify) {\n style[\"justify-content\"] = justify;\n }\n if (separation !== 0) {\n style.gap = `${round(separation)}px`;\n }\n return;\n }\n if (isFlowContainerType(type)) {\n const hSeparation =\n themeNumber(layout, \"h_separation\", options) ??\n themeNumber(layout, \"separation\", options) ??\n 0;\n const vSeparation =\n themeNumber(layout, \"v_separation\", options) ??\n themeNumber(layout, \"separation\", options) ??\n 0;\n style.display = \"flex\";\n style[\"flex-direction\"] = horizontal ? \"row\" : \"column\";\n style[\"flex-wrap\"] = \"wrap\";\n style[\"align-content\"] = \"flex-start\";\n style[\"align-items\"] = \"flex-start\";\n const justify = alignmentJustify(layout);\n if (justify) {\n style[\"justify-content\"] = justify;\n }\n if (hSeparation !== 0) {\n style[\"column-gap\"] = `${round(hSeparation)}px`;\n }\n if (vSeparation !== 0) {\n style[\"row-gap\"] = `${round(vSeparation)}px`;\n }\n return;\n }\n if (type === \"GridContainer\") {\n const columns = Math.max(1, asNumber(layout.properties.columns) ?? 1);\n const hSeparation =\n themeNumber(layout, \"h_separation\", options) ??\n themeNumber(layout, \"separation\", options) ??\n 0;\n const vSeparation =\n themeNumber(layout, \"v_separation\", options) ??\n themeNumber(layout, \"separation\", options) ??\n 0;\n style.display = \"grid\";\n style[\"grid-template-columns\"] = `repeat(${columns}, auto)`;\n style[\"justify-items\"] = \"start\";\n style[\"align-items\"] = \"start\";\n if (hSeparation !== 0) {\n style[\"column-gap\"] = `${round(hSeparation)}px`;\n }\n if (vSeparation !== 0) {\n style[\"row-gap\"] = `${round(vSeparation)}px`;\n }\n return;\n }\n if (type === \"CenterContainer\" || type === \"AspectRatioContainer\") {\n style.display = \"flex\";\n style[\"align-items\"] = \"center\";\n style[\"justify-content\"] = \"center\";\n return;\n }\n if (type === \"MarginContainer\") {\n const left = Math.max(0, themeNumber(layout, \"margin_left\", options) ?? 0);\n const top = Math.max(0, themeNumber(layout, \"margin_top\", options) ?? 0);\n const right = Math.max(\n 0,\n themeNumber(layout, \"margin_right\", options) ?? 0,\n );\n const bottom = Math.max(\n 0,\n themeNumber(layout, \"margin_bottom\", options) ?? 0,\n );\n overlayGrid(style);\n growContentColumn(style);\n style.padding = `${round(top)}px ${round(right)}px ${round(bottom)}px ${round(left)}px`;\n return;\n }\n if (type === \"PanelContainer\") {\n const margins = panelStyleBoxMetrics(layout, options);\n overlayGrid(style);\n growContentColumn(style);\n style.padding = `${round(margins.top)}px ${round(margins.right)}px ${round(margins.bottom)}px ${round(margins.left)}px`;\n return;\n }\n if (type === \"ScrollContainer\") {\n const margins = panelStyleBoxMetrics(layout, options);\n style.display = \"block\";\n style.padding = `${round(margins.top)}px ${round(margins.right)}px ${round(margins.bottom)}px ${round(margins.left)}px`;\n style.overflow = \"auto\";\n }\n}\n\nfunction isTextNode(type: string): boolean {\n return (\n type === \"Label\" ||\n type === \"RichTextLabel\" ||\n type === \"Button\" ||\n type === \"LineEdit\" ||\n type === \"TextEdit\"\n );\n}\n\nfunction isCssContainerType(type: string): boolean {\n return (\n isBoxContainerType(type) ||\n isFlowContainerType(type) ||\n type === \"AspectRatioContainer\" ||\n type === \"GridContainer\" ||\n type === \"CenterContainer\" ||\n type === \"MarginContainer\" ||\n type === \"PanelContainer\" ||\n type === \"ScrollContainer\"\n );\n}\n\nfunction containerLayoutKind(type: string): GodotHtmlContainerLayout {\n if (isBoxContainerType(type)) {\n return \"box\";\n }\n if (isFlowContainerType(type)) {\n return \"flow\";\n }\n if (type === \"AspectRatioContainer\") {\n return \"aspect-ratio\";\n }\n if (type === \"GridContainer\") {\n return \"grid\";\n }\n if (type === \"CenterContainer\") {\n return \"center\";\n }\n if (type === \"MarginContainer\") {\n return \"margin\";\n }\n if (type === \"PanelContainer\") {\n return \"panel\";\n }\n return \"scroll\";\n}\n\nfunction isBoxContainerType(type: string): boolean {\n return (\n type === \"BoxContainer\" ||\n type === \"HBoxContainer\" ||\n type === \"VBoxContainer\"\n );\n}\n\nfunction isFlowContainerType(type: string): boolean {\n return (\n type === \"FlowContainer\" ||\n type === \"HFlowContainer\" ||\n type === \"VFlowContainer\"\n );\n}\n\n// Row vs column for Box/Flow containers: typed `H*`/`V*` win, else the `vertical`\n// property (default horizontal).\nfunction containerIsHorizontal(\n type: string,\n layout: GodotSceneTreeNode,\n): boolean {\n if (type === \"HBoxContainer\" || type === \"HFlowContainer\") {\n return true;\n }\n if (type === \"VBoxContainer\" || type === \"VFlowContainer\") {\n return false;\n }\n // A bare BoxContainer/FlowContainer carries its axis as the boolean `vertical`\n // property (asBoolean, mirroring the computed path) — NOT a number; `asNumber(true)`\n // is undefined, which would wrongly flow a `vertical=true` list as a row.\n return !(asBoolean(layout.properties.vertical) ?? false);\n}\n\n// A Godot MarginContainer/PanelContainer fits EVERY child to the same content rect —\n// children overlap as layers, they never stack. Model that as ONE grid cell that fills\n// the (definite-size) container content box; grid's default `stretch` items + each child\n// at `grid-area:1/1` (see setFlowChild) overlay and fill it. `minmax(0,1fr)` lets the\n// track fill without a child's min-content forcing it larger.\nfunction overlayGrid(style: Record<string, string>): void {\n style.display = \"grid\";\n style[\"grid-template-columns\"] = \"minmax(0, 1fr)\";\n style[\"grid-template-rows\"] = \"minmax(0, 1fr)\";\n delete style[\"flex-direction\"];\n}\n\n// An overlay-grid container with NO definite width is content-driven (point-anchored\n// `width:min-content`, or an auto-width grid/flow item). Its `minmax(0, 1fr)` column\n// floor of 0 (chosen so a DEFINITE-size overlay's child can't force it wider) also\n// blocks a NON-wrapping child's full-line min-content from growing it — collapsing a\n// content-hugging container to its `min-width` floor (the card-pile/deck `BottomText`\n// backdrop: a one-line RichTextLabel whose text lives in an out-of-flow self-layer, so\n// only the grid track can carry its width up). Raise the floor to `min-content` so the\n// child's minimum propagates and the container (and its ColorRect backdrop) hug the text\n// the way Godot's `get_minimum_size()` does. Definite-width overlays keep `minmax(0,1fr)`.\nfunction growContentColumn(style: Record<string, string>): void {\n if (!hasDefiniteWidth(style)) {\n style[\"grid-template-columns\"] = \"minmax(min-content, 1fr)\";\n }\n}\n\n// Godot Box/Flow `alignment` (BEGIN=0 / CENTER=1 / END=2) packs children along the\n// container's MAIN axis — exactly what CSS `justify-content` controls (for both row and\n// column flex). BEGIN is the flex default, so emit nothing for it (mirrors the computed\n// path's `alignmentOffset`). Without this, a centered HBox (e.g. the char-select button\n// row) left-aligns and overflows instead of centering.\nfunction alignmentJustify(layout: GodotSceneTreeNode): string | undefined {\n const alignment = asNumber(layout.properties.alignment) ?? 0;\n if (alignment === 1) {\n return \"center\";\n }\n if (alignment === 2) {\n return \"flex-end\";\n }\n return undefined;\n}\n\nfunction themeNumber(\n node: GodotSceneTreeNode,\n name: string,\n options: GodotHtmlRenderOptions,\n): number | undefined {\n return (\n asNumber(node.properties[`theme_override_constants/${name}`]) ??\n asNumber(node.properties[`theme_constant_${name}`]) ??\n asNumber(options.resolveTheme?.(sourceNodeForLayout(node), name))\n );\n}\n","// Live-DOM browser-zoom detector: reports the page-zoom factor relative to the\n// zoom level at install time (1 = unchanged). Desktop browser zoom (ctrl +/-,\n// desktop-touchpad pinch) multiplies `devicePixelRatio` by the zoom step and\n// shrinks the layout viewport by it; hosts that want zoom to *apply* to a\n// scale-to-fit surface (instead of being neutralized by a refit) can hold the\n// surface at `layoutViewport · zoom` CSS px and let the page scroll.\n//\n// What this deliberately does NOT react to:\n// - Mobile pinch-zoom: that scales the VISUAL viewport only — `devicePixelRatio`\n// and the layout viewport are untouched, the browser magnifies and pans\n// natively. All reads here are layout-viewport reads (`documentElement\n// .clientWidth`, never `innerWidth`, which tracks the visual viewport on\n// mobile), so a pinch leaves the detector inert.\n// - Plain window resizes: `devicePixelRatio` is unchanged, so the zoom stays 1.\n//\n// Known limits (no web API separates browser zoom from system DPI): a page\n// loaded pre-zoomed treats that level as 100%, and a `devicePixelRatio` change\n// is classified by heuristic — zoom keeps the window's *physical* pixel size\n// ~constant while monitor/OS-scale moves do not, so a simultaneous physical-size\n// change rebases the baseline instead of reporting zoom. A misclassification\n// degrades to reporting 1 (the legacy fit behavior) until the next zoom event.\n\nexport type BrowserZoomWindow = Pick<\n Window,\n \"addEventListener\" | \"removeEventListener\" | \"devicePixelRatio\" | \"matchMedia\"\n> & {\n document: { documentElement: Pick<HTMLElement, \"clientWidth\"> };\n};\n\n// `devicePixelRatio` deltas below this are floating-point noise (real zoom\n// steps are >= 10%); physical-size drift below the tolerance is rounding from\n// the integer `clientWidth`.\nexport const BROWSER_ZOOM_EPSILON = 0.005;\nexport const BROWSER_ZOOM_REBASE_TOLERANCE = 0.02;\n\nexport function observeBrowserZoom(\n onChange: (zoom: number) => void,\n targetWindow: BrowserZoomWindow = window,\n): () => void {\n const readDpr = (): number => {\n const dpr = targetWindow.devicePixelRatio;\n return Number.isFinite(dpr) && dpr > 0 ? dpr : 1;\n };\n const physicalWidth = (dpr: number): number =>\n targetWindow.document.documentElement.clientWidth * dpr;\n\n let baselineDpr = readDpr();\n let lastDpr = baselineDpr;\n let lastPhysicalWidth = physicalWidth(lastDpr);\n let lastReported = 1;\n let disposed = false;\n\n // A `(resolution: …dppx)` query stops matching the moment the effective DPR\n // changes, catching DPR-only transitions (e.g. dragging the window onto a\n // different-DPI monitor) that fire no `resize`. Re-armed for the new DPR\n // after every change.\n let mediaQuery: MediaQueryList | null = null;\n const disarmMediaQuery = (): void => {\n mediaQuery?.removeEventListener(\"change\", update);\n mediaQuery = null;\n };\n const armMediaQuery = (dpr: number): void => {\n disarmMediaQuery();\n if (typeof targetWindow.matchMedia !== \"function\") {\n return;\n }\n mediaQuery = targetWindow.matchMedia(`(resolution: ${dpr}dppx)`);\n mediaQuery.addEventListener(\"change\", update);\n };\n\n function update(): void {\n if (disposed) {\n return;\n }\n const dpr = readDpr();\n if (Math.abs(dpr - lastDpr) > BROWSER_ZOOM_EPSILON) {\n const physical = physicalWidth(dpr);\n const physRatio = physical / lastPhysicalWidth;\n if (\n !Number.isFinite(physRatio) ||\n Math.abs(physRatio - 1) > BROWSER_ZOOM_REBASE_TOLERANCE\n ) {\n // Physical size moved with the DPR: monitor/OS-scale change, not zoom.\n // Shift the baseline so the currently-reported zoom is preserved.\n baselineDpr *= dpr / lastDpr;\n }\n armMediaQuery(dpr);\n }\n lastDpr = dpr;\n lastPhysicalWidth = physicalWidth(dpr);\n let zoom = dpr / baselineDpr;\n if (!Number.isFinite(zoom) || zoom <= 0) {\n zoom = 1;\n }\n if (Math.abs(zoom - lastReported) > BROWSER_ZOOM_EPSILON) {\n lastReported = zoom;\n onChange(zoom);\n }\n }\n\n onChange(1);\n targetWindow.addEventListener(\"resize\", update);\n armMediaQuery(lastDpr);\n\n return () => {\n disposed = true;\n targetWindow.removeEventListener(\"resize\", update);\n disarmMediaQuery();\n };\n}\n","import { round } from \"./css-values\";\n\n// Godot Window content-scale settings (`Window.content_scale_*` /\n// `display/window/stretch/*`). Only `keep` is interpreted today; the rest of the\n// enum is accepted so callers can pass real Godot values without a type error and\n// so the aspect-specific math has a single place to grow.\nexport interface GodotContentScaleSize {\n width: number;\n height: number;\n}\n\nexport type GodotContentScaleAspect =\n | \"ignore\"\n | \"keep\"\n | \"keep_width\"\n | \"keep_height\"\n | \"expand\";\n\nexport type GodotContentScaleTechnique = \"container\" | \"transform\";\n\nexport interface GodotContentScale {\n /** Godot `content_scale_aspect`. Only `\"keep\"` is implemented for now. */\n aspect: GodotContentScaleAspect;\n /**\n * How the uniform scale is realized in the DOM:\n * - `\"container\"` (default): CSS-only, every length in the stage subtree is\n * expressed in container-query units. No JavaScript; identical in Vue and the\n * static HTML document.\n * - `\"transform\"`: the stage keeps its px layout and is scaled with\n * `transform: scale(var(--godot-scale))`; the factor is set by JS on resize.\n */\n technique?: GodotContentScaleTechnique;\n /** Base/reference resolution (Godot `content_scale_size`). Defaults to the model viewport. */\n baseSize?: GodotContentScaleSize;\n /** Letterbox/pillarbox bar color painted by the frame around the centered stage. */\n background?: string;\n}\n\nexport interface ResolvedContentScale {\n aspect: GodotContentScaleAspect;\n technique: GodotContentScaleTechnique;\n base: GodotContentScaleSize;\n background?: string;\n}\n\n// Resolve user options against the model viewport. Returns `null` (no framing,\n// today's behavior) when content-scale is absent, the base size is degenerate, or\n// the aspect is one we don't model yet.\nexport function resolveContentScale(\n contentScale: GodotContentScale | undefined,\n viewport: GodotContentScaleSize,\n): ResolvedContentScale | null {\n if (!contentScale) {\n return null;\n }\n // Only `keep` (uniform fit + letterbox) is interpreted for now. Other aspects\n // fall through to the unscaled render rather than guessing.\n if (contentScale.aspect !== \"keep\") {\n return null;\n }\n const base = contentScale.baseSize ?? viewport;\n if (!(base.width > 0) || !(base.height > 0)) {\n return null;\n }\n return {\n aspect: contentScale.aspect,\n technique: contentScale.technique ?? \"container\",\n base: { width: base.width, height: base.height },\n background: contentScale.background,\n };\n}\n\n// Matches a CSS px length token (`120px`, `-8px`, `.5px`, `0.25px`). The\n// `(?![\\w.])` lookahead keeps it from biting into identifiers/filenames such as\n// `icon20px.png` or base64 data, so it is safe to run over whole HTML/CSS strings.\nconst PX_TOKEN = /(-?(?:\\d+\\.?\\d*|\\.\\d+))px(?![\\w.])/g;\n\n// Rewrite every px length in `text` into the container-query form for a uniform\n// \"Keep\" fit of a `base` (A×B) box: scale `s = min(W/A, H/B)`, so a length `p`\n// becomes `p·s = min(p·100/A cqw, p·100/B cqh)` for `p >= 0`, and `max(...)` for\n// `p < 0` (multiplying by a negative flips the comparison). `cqw`/`cqh` resolve\n// against the nearest `.godot-scene-frame` (which sets `container-type: size`).\nexport function rewritePxLengths(\n text: string,\n base: GodotContentScaleSize,\n): string {\n return text.replace(PX_TOKEN, (_match, raw: string) => {\n const px = Number.parseFloat(raw);\n if (!Number.isFinite(px) || px === 0) {\n return \"0\";\n }\n const widthShare = round((px * 100) / base.width);\n const heightShare = round((px * 100) / base.height);\n const fn = px < 0 ? \"max\" : \"min\";\n return `${fn}(${widthShare}cqw, ${heightShare}cqh)`;\n });\n}\n\n// Rewrite every px value of a style record in place (container technique).\nexport function scaleStyleRecord(\n style: Record<string, string>,\n base: GodotContentScaleSize,\n): void {\n for (const [name, value] of Object.entries(style)) {\n const rewritten = rewritePxLengths(value, base);\n if (rewritten !== value) {\n style[name] = rewritten;\n }\n }\n}\n\n// Inline style merged onto the `.godot-scene-stage` element so the base canvas\n// fits the frame while preserving aspect ratio.\nexport function contentScaleStageStyle(\n resolved: ResolvedContentScale,\n): Record<string, string> {\n const { base } = resolved;\n if (resolved.technique === \"transform\") {\n return {\n width: `${round(base.width)}px`,\n height: `${round(base.height)}px`,\n transform: \"scale(var(--godot-scale, 1))\",\n };\n }\n // Container technique: the fitted box is `base · s` expressed in cq units.\n const widthAspect = round((base.width / base.height) * 100);\n const heightAspect = round((base.height / base.width) * 100);\n return {\n width: `min(100cqw, ${widthAspect}cqh)`,\n height: `min(${heightAspect}cqw, 100cqh)`,\n };\n}\n\n// Live-DOM (Vue / `mountHtmlScene`) scale driver for the transform technique.\n// Sets `--godot-scale` on the frame and keeps it in sync on resize. Returns a\n// disposer.\nexport function observeContentScale(\n frame: HTMLElement,\n base: GodotContentScaleSize,\n): () => void {\n const fit = (): void => {\n const rect = frame.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) {\n return;\n }\n const scale = Math.min(rect.width / base.width, rect.height / base.height);\n frame.style.setProperty(\"--godot-scale\", String(scale));\n };\n fit();\n if (typeof ResizeObserver !== \"undefined\") {\n const observer = new ResizeObserver(fit);\n observer.observe(frame);\n return () => observer.disconnect();\n }\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"resize\", fit);\n return () => window.removeEventListener(\"resize\", fit);\n }\n return () => {};\n}\n\n// Self-contained `<script>` for the static HTML document (transform technique):\n// the string-renderer equivalent of `observeContentScale`, applied to every\n// `.godot-scene-frame` on the page.\nexport function contentScaleScript(base: GodotContentScaleSize): string {\n const a = round(base.width);\n const b = round(base.height);\n return `<script>(function(){var A=${a},B=${b};function fit(f){var r=f.getBoundingClientRect();if(r.width<=0||r.height<=0)return;f.style.setProperty(\"--godot-scale\",String(Math.min(r.width/A,r.height/B)));}var frames=document.querySelectorAll(\".godot-scene-frame\");var ro=typeof ResizeObserver!==\"undefined\"?new ResizeObserver(function(es){for(var i=0;i<es.length;i++)fit(es[i].target);}):null;for(var i=0;i<frames.length;i++){fit(frames[i]);if(ro)ro.observe(frames[i]);}if(!ro)window.addEventListener(\"resize\",function(){for(var i=0;i<frames.length;i++)fit(frames[i]);});})();</script>`;\n}\n","/*\n * Generated from ../vendor/OpenSans_SemiBold.woff2 by scripts/inline-default-font.mjs.\n * Keep this data URL byte-identical with the vendored binary; the vendor test asserts it.\n */\nexport const GODOT_DEFAULT_FONT_DATA_URL =\n \"data:font/woff2;base64,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\";\n","import { GODOT_DEFAULT_FONT_DATA_URL } from \"./default-font-data\";\n\n// Godot 4.5.1's default theme embeds OpenSans_SemiBold.woff2. Keep this\n// separate from resolved FontFile / FontVariation faces: it is only the browser\n// counterpart of a Control whose effective theme has no explicit font file.\nexport const GODOT_DEFAULT_FONT_FAMILY = \"Godot Default\";\n\nexport const godotDefaultFontFace = {\n fontFamily: GODOT_DEFAULT_FONT_FAMILY,\n url: GODOT_DEFAULT_FONT_DATA_URL,\n style: \"normal\",\n // The actual file is SemiBold, but Godot uses this same face for its normal\n // role and synthesizes the bold variation itself. Advertising it as 400 makes\n // browser role selection follow that effective default without replacing any\n // explicit FontFile/FontVariation mapping.\n weight: \"400\",\n} as const;\n","import { contentScaleStageStyle } from \"./content-scale\";\nimport { cssUrl, escapeHtml, styleAttribute } from \"./css-values\";\nimport { godotDefaultFontFace } from \"./default-font\";\nimport {\n FRAME_CLASS,\n partitionChildren,\n SELF_LAYER_CLASS,\n STAGE_CLASS,\n tintFilterDefsMarkup,\n} from \"./render-structure\";\nimport type { GodotHtmlFontFace, GodotHtmlModel, GodotHtmlNode } from \"./types\";\n\n// A framework-agnostic description of one rendered element. The three renderers\n// (DOM, HTML string, Vue) all build the SAME `RenderElement` tree from a\n// `GodotHtmlModel` and then emit it to their target, so the scene structure —\n// node element + self-layer + behind/self/normal child order, the stage/frame\n// wrappers, the tint-filter defs, the font/base-css `<style>` — is decided in\n// ONE place. Drift bugs (a renderer forgetting the tint defs, or wrapping rich\n// text in an extra span) can no longer happen per-target.\n//\n// Exactly one content form is used: `children` (element children), `rawHtml`\n// (assigned verbatim as innerHTML — rich text, the tint-defs SVG, `<style>` CSS),\n// or `text` (escaped/`textContent`). `sourceNode` is set on per-node elements so\n// a target that exposes a per-node hook (the Vue `#node` slot) can recover the\n// model node; it is absent on scaffolding (stage/frame/self-layer/defs/style).\n//\n// `kind: \"comment\"` (with `tag: \"#comment\"` so stabilization's tag/key/text\n// equality works unchanged) marks a hidden-placeholder node: every target emits\n// it as a comment node carrying `text` — the v-if pattern.\nexport interface RenderElement {\n tag: string;\n kind?: \"comment\";\n className?: string;\n attributes?: Record<string, string>;\n style?: Record<string, string>;\n children?: RenderElement[];\n rawHtml?: string;\n text?: string;\n key?: string;\n sourceNode?: GodotHtmlNode;\n}\n\n// `@font-face` rules mapping each resolved font family to its font-file URL. Shared by\n// every renderer so all register fonts identically (without it a node's `font-family`\n// resolves to a name the browser can't load -> fallback). Lives here (not in the\n// string renderer) so the shared `<style>` builder can reuse it without a cycle.\nexport function renderFontFaceCss(fontFaces: GodotHtmlFontFace[]): string {\n return [godotDefaultFontFace, ...fontFaces]\n .map(\n (face) =>\n `@font-face { font-family: \"${cssFontString(face.fontFamily)}\"; src: url(\"${cssUrl(face.url)}\") format(\"${face.url.startsWith(\"data:font/woff2\") || /\\\\.woff2(?:$|[?#])/i.test(face.url) ? \"woff2\" : \"truetype\"}\"); font-style: ${face.style}; font-weight: ${face.weight}; }`,\n )\n .join(\"\\n\");\n}\n\n// CSS string escaping for `@font-face` family/url literals (quotes/backslashes).\nfunction cssFontString(value: string): string {\n return value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n}\n\n// One model node -> its outer element with `[behind, self-layer, normal]`\n// children (the paint order Godot uses around a node's own draw). The self-layer\n// carries the node's paint/text; `node.html` (rich text) becomes its DIRECT\n// innerHTML and `node.text` its text content.\nexport function buildNodePresentation(\n node: GodotHtmlNode,\n behind: RenderElement[] = [],\n normal: RenderElement[] = [],\n): RenderElement {\n if (node.kind === \"hidden-placeholder\") {\n // An effectively-hidden subtree renders as a single comment in the node's\n // sibling slot (no element, no descendants) — what Vue emits for `v-if`.\n return {\n tag: \"#comment\",\n kind: \"comment\",\n key: node.path,\n text: `godot:hidden ${node.path} (${node.type})`,\n };\n }\n const selfLayer: RenderElement = {\n tag: \"div\",\n className: SELF_LAYER_CLASS,\n attributes: node.selfAttributes,\n style: node.selfStyle,\n ...(node.html !== null\n ? { rawHtml: node.html }\n : node.text !== null\n ? { text: node.text }\n : {}),\n };\n return {\n tag: \"div\",\n className: node.className,\n // `node.attributes` already carries `data-godot-path` (set in the model).\n attributes: node.attributes,\n style: node.style,\n key: node.path,\n sourceNode: node,\n children: [...behind, selfLayer, ...normal],\n };\n}\n\nexport function buildNodeElement(\n node: GodotHtmlNode,\n nodeByPath: Map<string, GodotHtmlNode>,\n): RenderElement {\n if (node.kind === \"hidden-placeholder\") return buildNodePresentation(node);\n const { behind, normal } = partitionChildren(node, nodeByPath);\n return buildNodePresentation(\n node,\n behind.map((child) => buildNodeElement(child, nodeByPath)),\n normal.map((child) => buildNodeElement(child, nodeByPath)),\n );\n}\n\n// The stage element (`STAGE_CLASS`) with the scene roots as children. Tint defs\n// and the font/base-css `<style>` are composed alongside it by `buildSceneFragment`\n// so a full-document target can hoist them into `<head>` if it prefers.\nexport function buildStageElement(\n model: GodotHtmlModel,\n options: { debug?: boolean; background?: string } = {},\n): RenderElement {\n const nodeByPath = new Map(model.nodes.map((node) => [node.path, node]));\n const roots = model.nodes.filter((node) => node.parentPath === null);\n const style: Record<string, string> = model.contentScale\n ? { ...contentScaleStageStyle(model.contentScale) }\n : {\n width: `${model.viewport.width}px`,\n height: `${model.viewport.height}px`,\n };\n if (options.background) {\n style.background = options.background;\n }\n return {\n tag: \"div\",\n className: options.debug ? `${STAGE_CLASS} godot-scene-debug` : STAGE_CLASS,\n attributes: { \"data-godot-stage\": \"true\" },\n style,\n children: roots.map((root) => buildNodeElement(root, nodeByPath)),\n };\n}\n\n// Wrap the stage in the content-scale frame (`FRAME_CLASS`) when the model is\n// content-scaled; otherwise return the stage unchanged. The transform-technique\n// runtime scaling (ResizeObserver / `contentScaleScript`) is a per-target\n// lifecycle concern and stays in each renderer.\nexport function buildFrameElement(\n model: GodotHtmlModel,\n stage: RenderElement,\n options: { background?: string } = {},\n): RenderElement {\n if (!model.contentScale) {\n return stage;\n }\n const background = model.contentScale.background ?? options.background;\n return {\n tag: \"div\",\n className: FRAME_CLASS,\n style: background ? { background } : {},\n children: [stage],\n };\n}\n\n// The hidden `<svg><defs>` of color-matrix `<filter>` tints referenced by\n// external textures, wrapped in a zero-size host div. `undefined` when the model\n// registered no tints.\nexport function buildTintDefsElement(\n model: Pick<GodotHtmlModel, \"tintFilters\">,\n): RenderElement | undefined {\n const markup = tintFilterDefsMarkup(model.tintFilters);\n if (!markup) {\n return undefined;\n }\n return {\n tag: \"div\",\n key: \"godot-tint-defs\",\n attributes: { \"aria-hidden\": \"true\" },\n style: {\n position: \"absolute\",\n width: \"0\",\n height: \"0\",\n overflow: \"hidden\",\n },\n rawHtml: markup,\n };\n}\n\n// A `<style>` element carrying `@font-face` rules (always) plus, when\n// `includeBaseCss`, the model's base CSS. Lets a fragment-mounting target\n// (DOM / Vue) self-contain its styling instead of relying on the host to inject\n// it. `undefined` when there is nothing to emit.\nexport function buildStyleElement(\n model: Pick<GodotHtmlModel, \"fontFaces\" | \"css\">,\n options: { includeBaseCss?: boolean } = {},\n): RenderElement | undefined {\n const parts: string[] = [];\n if (model.fontFaces.length > 0) {\n parts.push(renderFontFaceCss(model.fontFaces));\n }\n if (options.includeBaseCss) {\n parts.push(model.css);\n }\n if (parts.length === 0) {\n return undefined;\n }\n return { tag: \"style\", key: \"godot-style\", rawHtml: parts.join(\"\\n\") };\n}\n\nexport interface SceneFragmentOptions {\n debug?: boolean;\n background?: string;\n // Emit the `<style>` element (fonts + optional base css) as the fragment's\n // first child. Fragment-mounting targets (DOM/Vue) want this so the render is\n // self-contained; a full-document target (HTML string) hoists styles into\n // `<head>` itself and passes `false`.\n includeStyle?: boolean;\n includeBaseCss?: boolean;\n}\n\n// The ordered top-level elements of a rendered scene: an optional `<style>`\n// (fonts + optional base css), an optional tint-defs element, and the stage\n// (wrapped in a frame when content-scaled). Every renderer builds this and emits\n// it to its target.\nexport function buildSceneFragment(\n model: GodotHtmlModel,\n options: SceneFragmentOptions = {},\n): RenderElement[] {\n const fragment: RenderElement[] = [];\n if (options.includeStyle ?? true) {\n const style = buildStyleElement(model, {\n includeBaseCss: options.includeBaseCss ?? false,\n });\n if (style) {\n fragment.push(style);\n }\n }\n const tintDefs = buildTintDefsElement(model);\n if (tintDefs) {\n fragment.push(tintDefs);\n }\n const stage = buildStageElement(model, {\n debug: options.debug,\n background: options.background,\n });\n fragment.push(\n buildFrameElement(model, stage, { background: options.background }),\n );\n return fragment;\n}\n\n// ---- target emitters --------------------------------------------------------\n\n// A comment payload must not contain `--` (it would close or malform the\n// comment) nor end with `-` against the closing delimiter.\nfunction escapeCommentText(value: string): string {\n return value.replaceAll(\"--\", \"- -\").replace(/-$/, \"- \");\n}\n\n// Emit a `RenderElement` tree as an HTML string (the static document renderer).\nexport function renderElementToHtml(element: RenderElement): string {\n if (element.kind === \"comment\") {\n return `<!--${escapeCommentText(element.text ?? \"\")}-->`;\n }\n const attrs: Record<string, string> = {\n ...(element.className ? { class: element.className } : {}),\n ...element.attributes,\n };\n const attrString = Object.entries(attrs)\n .map(([name, value]) => `${escapeHtml(name)}=\"${escapeHtml(value)}\"`)\n .join(\" \");\n const styleString =\n element.style && Object.keys(element.style).length > 0\n ? ` style=\"${escapeHtml(styleAttribute(element.style))}\"`\n : \"\";\n const open = attrString\n ? `<${element.tag} ${attrString}${styleString}>`\n : `<${element.tag}${styleString}>`;\n const content =\n element.rawHtml !== undefined\n ? element.rawHtml\n : element.text !== undefined\n ? escapeHtml(element.text)\n : (element.children ?? [])\n .map((child) => renderElementToHtml(child))\n .join(\"\");\n return `${open}${content}</${element.tag}>`;\n}\n\n// Emit a `RenderElement` tree as live DOM (the mount renderer).\nexport function renderElementToDom(\n element: RenderElement,\n): HTMLElement | Comment {\n if (element.kind === \"comment\") {\n return document.createComment(element.text ?? \"\");\n }\n const node = document.createElement(element.tag);\n if (element.className) {\n node.className = element.className;\n }\n for (const [name, value] of Object.entries(element.attributes ?? {})) {\n node.setAttribute(name, value);\n }\n for (const [name, value] of Object.entries(element.style ?? {})) {\n node.style.setProperty(name, value);\n }\n if (element.rawHtml !== undefined) {\n node.innerHTML = element.rawHtml;\n } else if (element.text !== undefined) {\n node.textContent = element.text;\n } else {\n for (const child of element.children ?? []) {\n node.appendChild(renderElementToDom(child));\n }\n }\n return node;\n}\n","import { observeContentScale } from \"./content-scale\";\nimport { FRAME_CLASS, STAGE_CLASS } from \"./render-structure\";\nimport { buildSceneFragment, renderElementToDom } from \"./render-tree\";\nimport { createHtmlEffectsHost } from \"./runtime\";\nimport type { GodotHtmlMountOptions } from \"./runtime-options\";\nimport type { GodotHtmlModel } from \"./types\";\n\nconst disposers = new WeakMap<HTMLElement, () => void>();\n\n// Mount a model as live DOM. A thin emitter over the shared structural tree\n// (`buildSceneFragment` -> `renderElementToDom`): the node/self-layer/stage/frame\n// structure, the tint-filter defs, and the font + base-css `<style>` all come\n// from the shared builder, so this renderer can't drift from the HTML-string or\n// Vue ones. Returns the stage element. Pass `options` to opt into the live WebGL\n// shader runtime (`enableWebglShaders`).\nexport function mountHtmlScene(\n container: HTMLElement,\n model: GodotHtmlModel,\n options?: GodotHtmlMountOptions,\n): HTMLElement {\n disposers.get(container)?.();\n disposers.delete(container);\n let disposeScale: (() => void) | undefined;\n container.replaceChildren();\n // Tint defs + stage/frame. Base CSS and fonts are injected by the host (the\n // historical mount contract — `container.firstElementChild` is the tint defs or\n // the stage), so the style element is omitted here.\n const fragment = buildSceneFragment(model, { includeStyle: false });\n for (const element of fragment) {\n container.appendChild(renderElementToDom(element));\n }\n // Transform-technique content scale needs the live frame size; drive\n // `--godot-scale` from a ResizeObserver on the frame.\n if (model.contentScale?.technique === \"transform\") {\n const frame = container.querySelector<HTMLElement>(`.${FRAME_CLASS}`);\n if (frame) {\n disposeScale = observeContentScale(frame, model.contentScale.base);\n }\n }\n const stage = container.querySelector<HTMLElement>(\n `.${STAGE_CLASS}`,\n ) as HTMLElement;\n const host = createHtmlEffectsHost(stage, options);\n host.reconcile();\n disposers.set(container, () => {\n host.dispose();\n disposeScale?.();\n });\n return stage;\n}\n\n/** Release a mounted scene's observers and effect bindings before removing its DOM. */\nexport function unmountHtmlScene(container: HTMLElement): void {\n disposers.get(container)?.();\n disposers.delete(container);\n container.replaceChildren();\n}\n","// Godot Tween easing → CSS timing-function. A Godot `Tween` step carries a TransitionType (`trans`) and an\n// EaseType (`ease`); to replay that tween as a CSS `transition`/animation a consumer needs the matching CSS\n// timing function. This is the generic (any-Godot-streamer) form of the mapping, ported from\n// @spirectl/presentation's `render/interactivity.ts:godotEasingToCss` (gsw cannot import upward from presentation).\n//\n// Difference from the presentation copy: this accepts the RAW Godot enum names as they arrive over a live wire\n// (`EaseType` = \"In\"/\"Out\"/\"InOut\"/\"OutIn\", `TransitionType` = \"Expo\"/\"Back\"/\"Elastic\"/\"Linear\"/…), so it\n// lowercases BOTH `ease` and `trans` (the presentation copy assumed catalog-normalized lowercase input).\n\n// CSS `linear()` approximation of Godot ElasticOut: 2^(-10t)·sin((10t − 0.75)·2π/3) + 1, sampled at 17 evenly\n// spaced points (cubic-bezier cannot oscillate). Browsers without `linear()` ignore it and snap.\nexport const ELASTIC_OUT_LINEAR =\n \"linear(0, 0.832, 1.364, 1.193, 0.912, 0.889, 1, 1.047, 1.016, 0.986, 0.989, 1.002, 1.006, 1.001, 0.998, 0.999, 1)\";\n\n// The POLYNOMIAL / trigonometric Godot transition families (`scene/animation/easing_equations.h`) are the classic\n// Penner equations, and each one has a cubic-bezier fit that is accurate to ~1-2% of the travel distance. They used\n// to fall through to the generic `ease-in`/`ease-out`/`ease-in-out` curves, which is NOT a small error: Godot's\n// QuintOut has covered 97% of the distance at the half-way point where CSS `ease-out` has covered 68% — a max\n// deviation of 0.388 (measured), i.e. the browser visibly lags the game through the whole second half of every such\n// tween. STS2's shop-inventory open slide (`SlotsContainer`, position:y, 700ms, Quint/Out — captured live in\n// couch-coop's `.sts2/bench/audit-shop-open.ndjson`) is the reported case: the panel looked ~2× slower to arrive in\n// the mirror than in the game. Max |error| against the exact Godot curve, sampled at 201 points:\n// sine in/out 0.0076 inout 0.0020 quad in/out 0.0019 inout 0.0053\n// cubic in/out 0.0028 inout 0.0095 quart in/out 0.0056 inout 0.0217\n// quint in/out 0.0113 inout 0.0322 circ in/out 0.0018 inout 0.0387\n// (`bounce` and `spring` are NOT expressible as a cubic-bezier — they keep the `ease-*` fallback, like elastic-in.)\nconst POLY_BEZIERS: Record<string, readonly [string, string, string]> = {\n // [in, out, in-out]\n sine: [\"cubic-bezier(0.12, 0, 0.39, 0)\", \"cubic-bezier(0.61, 1, 0.88, 1)\", \"cubic-bezier(0.37, 0, 0.63, 1)\"],\n quad: [\"cubic-bezier(0.11, 0, 0.5, 0)\", \"cubic-bezier(0.5, 1, 0.89, 1)\", \"cubic-bezier(0.45, 0, 0.55, 1)\"],\n cubic: [\"cubic-bezier(0.32, 0, 0.67, 0)\", \"cubic-bezier(0.33, 1, 0.68, 1)\", \"cubic-bezier(0.65, 0, 0.35, 1)\"],\n quart: [\"cubic-bezier(0.5, 0, 0.75, 0)\", \"cubic-bezier(0.25, 1, 0.5, 1)\", \"cubic-bezier(0.76, 0, 0.24, 1)\"],\n quint: [\"cubic-bezier(0.64, 0, 0.78, 0)\", \"cubic-bezier(0.22, 1, 0.36, 1)\", \"cubic-bezier(0.83, 0, 0.17, 1)\"],\n circ: [\"cubic-bezier(0.55, 0, 1, 0.45)\", \"cubic-bezier(0, 0.55, 0.45, 1)\", \"cubic-bezier(0.85, 0, 0.15, 1)\"],\n};\n\n// Godot easing (`ease` In/Out/InOut + `trans` Expo/Linear/Back/Elastic/Sine/Quad/Cubic/Quart/Quint/Circ/…) → a CSS\n// timing-function string. Case-insensitive in both arguments.\n//\n// A MISSING `trans` maps to `linear`, not to a curve: Godot's `Tween::default_transition` is `TRANS_LINEAR` (4.5.1,\n// `scene/animation/tween.h`), so a step that never called `set_trans()` really does play linearly — the old\n// `ease-in-out` fallback deviated from it by up to 0.121. (`default_ease` IS `EASE_IN_OUT`, which is why a missing\n// `ease` still selects the in-out column.) Only an UNRECOGNISED family name keeps the generic `ease-*` guess.\nexport function godotEasingToCss(ease?: string, trans?: string): string {\n const e = typeof ease === \"string\" ? ease.toLowerCase() : \"\";\n const dir = e === \"out\" ? \"out\" : e === \"in\" ? \"in\" : \"in-out\";\n const t = typeof trans === \"string\" ? trans.toLowerCase() : \"\";\n if (t === \"expo\") {\n return dir === \"out\"\n ? \"cubic-bezier(0.19, 1, 0.22, 1)\"\n : dir === \"in\"\n ? \"cubic-bezier(0.95, 0.05, 0.795, 0.035)\"\n : \"cubic-bezier(1, 0, 0, 1)\";\n }\n // A step with no `trans` at all: Godot's Tween default is TRANS_LINEAR (see the note above).\n if (t === \"linear\" || t === \"\") return \"linear\";\n const poly = POLY_BEZIERS[t];\n if (poly) {\n return dir === \"out\" ? poly[1] : dir === \"in\" ? poly[0] : poly[2];\n }\n if (t === \"back\") {\n // Godot Back easing: a single overshoot, expressible as a cubic-bezier.\n return dir === \"out\"\n ? \"cubic-bezier(0.34, 1.56, 0.64, 1)\"\n : dir === \"in\"\n ? \"cubic-bezier(0.36, 0, 0.66, -0.56)\"\n : \"cubic-bezier(0.68, -0.6, 0.32, 1.6)\";\n }\n if (t === \"elastic\") {\n // Only `out` has an oscillating approximation (via linear()); in/in-out fall back to a single-overshoot bezier.\n return dir === \"out\" ? ELASTIC_OUT_LINEAR : \"cubic-bezier(0.68, -0.6, 0.32, 1.6)\";\n }\n return dir === \"out\" ? \"ease-out\" : dir === \"in\" ? \"ease-in\" : \"ease-in-out\";\n}\n","import { contentScaleScript } from \"./content-scale\";\nimport {\n buildNodeElement,\n buildSceneFragment,\n renderElementToHtml,\n renderFontFaceCss,\n} from \"./render-tree\";\nimport type { GodotHtmlModel, GodotHtmlNode } from \"./types\";\n\n// Default Godot editor viewport gray, used as the stage/page background when a\n// caller (e.g. the parity harness) screenshots the rendered scene.\nconst DEFAULT_VIEWPORT_BACKGROUND = \"rgb(76, 76, 76)\";\n\n// Server-side string form of one node: the shared structural element rendered to\n// HTML text. Kept as a named export for callers that render a single node.\nexport function renderGodotNodeHtml(\n node: GodotHtmlNode,\n nodeByPath: Map<string, GodotHtmlNode>,\n): string {\n return renderElementToHtml(buildNodeElement(node, nodeByPath));\n}\n\n// Full standalone `<!doctype html>` document. A thin emitter over the shared\n// structural tree: `@font-face` + base CSS are hoisted into `<head>` (the\n// full-document convention), and the body is the shared scene fragment (tint defs\n// + stage/frame) rendered to a string.\nexport function renderGodotSceneHtml(\n model: GodotHtmlModel,\n options: {\n viewport: { width: number; height: number };\n background?: string;\n },\n): string {\n const background = options.background ?? DEFAULT_VIEWPORT_BACKGROUND;\n const fontFaceCss = renderFontFaceCss(model.fontFaces);\n // The document hoists styles into `<head>`, so the body fragment omits its own\n // `<style>` (`includeStyle: false`).\n const fragment = buildSceneFragment(model, {\n includeStyle: false,\n background,\n });\n const bodyInner = fragment\n .map((element) => renderElementToHtml(element))\n .join(\"\\n\");\n const body =\n model.contentScale?.technique === \"transform\"\n ? `${bodyInner}\\n${contentScaleScript(model.contentScale.base)}`\n : bodyInner;\n return `<!doctype html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<style>\n${fontFaceCss}\n${model.css}\nhtml, body { margin: 0; width: 100%; height: 100%; overflow: hidden; background: ${background}; }\n</style>\n</head>\n<body>\n${body}\n</body>\n</html>`;\n}\n","import {\n asNumber,\n asResourceRef,\n asString,\n type GodotNode,\n type GodotResourceRefValue,\n type GodotVariant,\n} from \"@godot-scene-web/core\";\nimport {\n type ColorMatrix,\n colorMatrixIsIdentity,\n safeClassSegment,\n} from \"./css-values\";\nimport { createStringLru } from \"./lru\";\nimport { imageResource, normalizeResource } from \"./resources\";\nimport type { GodotHtmlRenderOptions, GodotResolvedResource } from \"./types\";\nimport type {\n CurvePoint,\n GradientStop,\n TextureBakeSpec,\n} from \"./webgl/bake-texture\";\n\nexport function assignMaterialAttributes(\n attributes: Record<string, string>,\n style: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n nodePath?: string,\n): void {\n const materialRef = asResourceRef(props.material);\n if (!materialRef) {\n return;\n }\n const material = normalizeResource(\n options.resolveResource?.(materialRef, source),\n );\n const type = resourceType(material);\n if (!type) {\n return;\n }\n const materialProperties = effectiveShaderMaterialProperties(\n material?.document?.properties ?? {},\n props,\n );\n attributes[\"data-godot-material-type\"] = type;\n if (material?.path) {\n attributes[\"data-godot-material-path\"] = material.path;\n }\n\n const blendMode = asNumber(material?.document?.properties.blend_mode);\n if (blendMode !== undefined) {\n attributes[\"data-godot-material-blend-mode\"] = String(blendMode);\n attributes[\"data-godot-material-blend-mode-name\"] =\n canvasItemBlendModeName(blendMode);\n // CanvasItemMaterial BLEND_MODE_ADD -> CSS additive compositing. Placed on\n // the node's OUTER element, not the self-layer: the outer element carries\n // the node's transform/opacity/z-index, and a transform there would create\n // a stacking context that isolates a self-layer blend against an empty\n // backdrop — while a transform on the blended element itself does not\n // block its own blending. Divergence from the engine: in Godot the\n // material affects only the item's own drawing, whereas mix-blend-mode\n // also composites the node's CHILDREN additively; additive nodes are in\n // practice leaf paint nodes (glow NinePatchRects/Sprites), so this is\n // acceptable. Other blend modes (subtract/multiply/...) have no faithful\n // CSS equivalent and stay inert data attributes.\n if (type === \"CanvasItemMaterial\" && blendMode === 1) {\n style[\"mix-blend-mode\"] = \"plus-lighter\";\n }\n }\n\n const shaderRef = asResourceRef(material?.document?.properties.shader);\n if (shaderRef) {\n attributes[\"data-godot-shader-ref\"] =\n `${shaderRef.type}:${shaderRef.id ?? shaderRef.path}`;\n const { path, uid } = resolveShaderIdentity(\n material,\n shaderRef,\n source,\n options,\n );\n if (path) {\n attributes[\"data-godot-shader-path\"] = path;\n }\n if (uid) {\n attributes[\"data-godot-shader-uid\"] = uid;\n }\n // Live WebGL runtime opt-in: flag ShaderMaterial nodes and emit the runtime's\n // inputs (shader params + node modulate). The runtime fetches `path`/`uid`\n // source, transpiles, and — on success — replaces this node's CSS/SVG paint\n // with a canvas; unresolved or unsupported shaders keep their fallback.\n if (\n options.enableWebglShaders &&\n (path || uid) &&\n isWebglShaderEnabled(options, nodePath, path, uid)\n ) {\n attributes[\"data-godot-shader-webgl\"] = \"1\";\n const params = shaderParams(materialProperties);\n attributes[\"data-godot-shader-params\"] = JSON.stringify(params);\n const paramKinds = shaderParamKinds(materialProperties);\n if (paramKinds) {\n attributes[\"data-godot-shader-param-kinds\"] =\n JSON.stringify(paramKinds);\n }\n attributes[\"data-godot-shader-modulate\"] =\n combinedModulate(props).join(\",\");\n // Procedural sampler inputs (e.g. a noise field + gradient ramp): serialize a\n // pixel-free bake spec per `shader_parameter/<sampler>` SubResource so the\n // live runtime (the only place with a canvas) can realize the pixels.\n const samplers = samplerBakeSpecs(material, source, options);\n if (samplers) {\n attributes[\"data-godot-shader-samplers\"] = JSON.stringify(samplers);\n }\n const samplerUrls = samplerImageUrls(material, source, options);\n if (samplerUrls) {\n attributes[\"data-godot-shader-sampler-urls\"] =\n JSON.stringify(samplerUrls);\n }\n }\n }\n\n for (const [name, value] of Object.entries(materialProperties)) {\n if (!name.startsWith(\"shader_parameter/\")) {\n continue;\n }\n attributes[\n `data-godot-shader-param-${safeClassSegment(name.slice(\"shader_parameter/\".length))}`\n ] = godotValueLabel(value);\n }\n}\n\n/**\n * The exact linear RGB color transform produced by a node's `ShaderMaterial`,\n * or `undefined` when there is no material, the shader is not a recognized color\n * transform, or the transform is the identity (so a `v = 1.0` no-op stays\n * untouched). The consumer names which shaders are a standard HSV color adjust via\n * `hsvAdjustShaderIds`; other shaders are left as inert diagnostics, matching\n * `assignMaterialAttributes`.\n *\n * An HSV-adjust `fragment()` is linear (every step is a matrix/scalar multiply\n * with no offset), so the whole effect is one 3×3 matrix. We recover it by probing\n * the three RGB basis vectors through a literal port of that color math\n * (`applyHsv`) from the node's `h`/`s`/`v` `shader_parameter` values — this\n * sidesteps GLSL's mixed row/column conventions and Godot's column-major `mat3`.\n */\nexport function materialColorMatrix(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): ColorMatrix | undefined {\n const materialRef = asResourceRef(props.material);\n if (!materialRef) {\n return undefined;\n }\n const material = normalizeResource(\n options.resolveResource?.(materialRef, source),\n );\n if (!material) {\n return undefined;\n }\n const shaderRef = asResourceRef(material.document?.properties.shader);\n if (!shaderRef) {\n return undefined;\n }\n const { path: shaderPath, uid: shaderUid } = resolveShaderIdentity(\n material,\n shaderRef,\n source,\n options,\n );\n if (\n !shaderIdListMatches(\n options.hsvAdjustShaderIds ?? [],\n shaderPath,\n shaderUid,\n )\n ) {\n attributes[\"data-godot-shader-tint\"] = shaderPath\n ? `unhandled:${shaderPath}`\n : \"unhandled\";\n return undefined;\n }\n const params = effectiveShaderMaterialProperties(\n material.document?.properties ?? {},\n props,\n );\n const h = asNumber(params[\"shader_parameter/h\"]) ?? 1;\n const s = asNumber(params[\"shader_parameter/s\"]) ?? 1;\n const v = asNumber(params[\"shader_parameter/v\"]) ?? 1;\n const matrix = hsvColorMatrix(h, s, v);\n if (colorMatrixIsIdentity(matrix)) {\n return undefined;\n }\n attributes[\"data-godot-shader-tint\"] = \"hsv\";\n return matrix;\n}\n\n// Bake specs (numbers only — no pixels) for each `shader_parameter/<name>` that is\n// a procedural texture SubResource (NoiseTexture2D / GradientTexture1D). The live\n// runtime realizes these to RGBA via `webgl/bake-texture`. Nested SubResources\n// (a NoiseTexture2D's `noise`, a GradientTexture1D's `gradient`) are resolved from\n// the material document's own sub-resource table (an inline ShaderMaterial carries\n// the full scene table), falling back to `resolveResource`.\nfunction samplerBakeSpecs(\n material: GodotResolvedResource | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): Record<string, TextureBakeSpec> | undefined {\n const properties = material?.document?.properties ?? {};\n const subResources = material?.document?.subResources ?? [];\n const resolveSub = (\n ref: GodotResourceRefValue,\n ):\n | { type?: string; properties: Record<string, GodotVariant> }\n | undefined => {\n const local = subResources.find((entry) => entry.id === ref.id);\n if (local) return { type: local.type, properties: local.properties ?? {} };\n const resolved = normalizeResource(options.resolveResource?.(ref, source));\n if (resolved?.document) {\n return {\n type: resourceType(resolved),\n properties: resolved.document.properties ?? {},\n };\n }\n return undefined;\n };\n\n const out: Record<string, TextureBakeSpec> = {};\n for (const [name, value] of Object.entries(properties)) {\n if (!name.startsWith(\"shader_parameter/\")) continue;\n const ref = asResourceRef(value);\n if (ref?.type !== \"SubResource\") continue;\n const spec = bakeSpecFromResource(resolveSub(ref), resolveSub);\n if (spec) out[name.slice(\"shader_parameter/\".length)] = spec;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction samplerImageUrls(\n material: GodotResolvedResource | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): Record<string, string> | undefined {\n const properties = material?.document?.properties ?? {};\n const extResources = material?.document?.extResources ?? [];\n const out: Record<string, string> = {};\n for (const [name, value] of Object.entries(properties)) {\n if (!name.startsWith(\"shader_parameter/\")) continue;\n const ref = asResourceRef(value);\n if (!ref) continue;\n // An ExtResource id in a material's shader_parameters indexes the material\n // document's own ext-resource table, not the scene's — so attach its path\n // before resolving (mirrors resolveShaderIdentity). Without this, a sampler\n // bound to an external texture (e.g. an affliction's card-shape mask) fails\n // to resolve against the node's scene and is dropped, leaving it unbound.\n const ext = ref.id\n ? extResources.find((entry) => entry.id === ref.id)\n : undefined;\n const pathRef = ext?.path ? { ...ref, path: ext.path } : ref;\n const image = imageResource(\n normalizeResource(options.resolveResource?.(pathRef, source)),\n options,\n source,\n );\n if (image.url) {\n out[name.slice(\"shader_parameter/\".length)] = image.url;\n }\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction bakeSpecFromResource(\n sub: { type?: string; properties: Record<string, GodotVariant> } | undefined,\n resolveSub: (\n ref: GodotResourceRefValue,\n ) => { type?: string; properties: Record<string, GodotVariant> } | undefined,\n): TextureBakeSpec | undefined {\n if (!sub) return undefined;\n if (sub.type === \"GradientTexture1D\") {\n const gradientRef = asResourceRef(sub.properties.gradient);\n const gradient = gradientRef ? resolveSub(gradientRef) : undefined;\n const stops = gradientStops(gradient?.properties ?? {});\n if (stops.length === 0) return undefined;\n return {\n kind: \"gradient\",\n width: asNumber(sub.properties.width) ?? 256,\n stops,\n };\n }\n if (sub.type === \"NoiseTexture2D\") {\n const noiseRef = asResourceRef(sub.properties.noise);\n const np = (noiseRef ? resolveSub(noiseRef) : undefined)?.properties ?? {};\n return {\n kind: \"noise\",\n width: asNumber(sub.properties.width) ?? 512,\n height: asNumber(sub.properties.height) ?? 512,\n seamless: sub.properties.seamless === true,\n // Godot FastNoiseLite enums/defaults (TYPE_PERLIN=3, FRACTAL_FBM=1).\n noiseType: asNumber(np.noise_type) ?? 3,\n frequency: asNumber(np.frequency) ?? 0.01,\n fractalType: asNumber(np.fractal_type) ?? 1,\n octaves: asNumber(np.fractal_octaves) ?? 5,\n lacunarity: asNumber(np.fractal_lacunarity) ?? 2,\n gain: asNumber(np.fractal_gain) ?? 0.5,\n seed: asNumber(np.seed) ?? 0,\n };\n }\n if (sub.type === \"CurveTexture\") {\n const curveRef = asResourceRef(sub.properties.curve);\n const curve = curveRef ? resolveSub(curveRef) : undefined;\n return {\n kind: \"curve\",\n width: asNumber(sub.properties.width) ?? 256,\n channels: [curvePoints(curve?.properties ?? {})],\n };\n }\n if (sub.type === \"CurveXYZTexture\") {\n const channels = [\"curve_x\", \"curve_y\", \"curve_z\"].map((name) => {\n const curveRef = asResourceRef(sub.properties[name]);\n const curve = curveRef ? resolveSub(curveRef) : undefined;\n return curvePoints(curve?.properties ?? {});\n });\n return {\n kind: \"curve\",\n width: asNumber(sub.properties.width) ?? 256,\n channels,\n };\n }\n return undefined;\n}\n\nexport function curvePoints(\n properties: Record<string, GodotVariant>,\n): CurvePoint[] {\n const items = variantItems(properties._data);\n const points: CurvePoint[] = [];\n for (const item of items) {\n const point = vector2Point(item);\n if (point) points.push(point);\n }\n return points;\n}\n\nfunction variantItems(value: GodotVariant): unknown[] {\n if (Array.isArray(value)) return value;\n if (\n value &&\n typeof value === \"object\" &&\n \"args\" in value &&\n Array.isArray((value as { args?: unknown[] }).args)\n ) {\n return (value as { args: unknown[] }).args;\n }\n return [];\n}\n\nfunction vector2Point(value: unknown): CurvePoint | undefined {\n if (\n value &&\n typeof value === \"object\" &&\n \"type\" in value &&\n \"args\" in value &&\n (value as { type?: unknown }).type === \"Vector2\" &&\n Array.isArray((value as { args?: unknown[] }).args)\n ) {\n const args = (value as { args: unknown[] }).args;\n const x = asNumber(args[0] as GodotVariant);\n const y = asNumber(args[1] as GodotVariant);\n if (x !== undefined && y !== undefined) return { x, y };\n }\n return undefined;\n}\n\nfunction gradientStops(\n properties: Record<string, GodotVariant>,\n): GradientStop[] {\n const offsets = packedArgs(properties.offsets);\n const colors = packedArgs(properties.colors);\n const stops: GradientStop[] = [];\n for (let i = 0; i < offsets.length; i += 1) {\n const c = i * 4;\n stops.push({\n offset: offsets[i],\n color: [\n colors[c] ?? 0,\n colors[c + 1] ?? 0,\n colors[c + 2] ?? 0,\n colors[c + 3] ?? 1,\n ],\n });\n }\n return stops;\n}\n\n// The numeric components of a PackedFloat32Array / PackedColorArray variant\n// (`{ type, args }`).\nfunction packedArgs(value: GodotVariant): number[] {\n if (\n value &&\n typeof value === \"object\" &&\n \"args\" in value &&\n Array.isArray((value as { args?: unknown[] }).args)\n ) {\n return (value as { args: unknown[] }).args.filter(\n (x): x is number => typeof x === \"number\",\n );\n }\n return [];\n}\n\n// The node modulate·self_modulate as RGBA floats (0..1) — the shader `MODULATE`\n// the WebGL runtime feeds in (Godot applies this to a canvas_item's COLOR).\nfunction combinedModulate(\n props: Record<string, GodotVariant>,\n): [number, number, number, number] {\n const out: [number, number, number, number] = [1, 1, 1, 1];\n for (const value of [props.modulate, props.self_modulate]) {\n if (\n value &&\n typeof value === \"object\" &&\n \"type\" in value &&\n value.type === \"Color\" &&\n Array.isArray((value as { args?: unknown[] }).args)\n ) {\n const args = (value as { args: number[] }).args;\n out[0] *= args[0] ?? 1;\n out[1] *= args[1] ?? 1;\n out[2] *= args[2] ?? 1;\n out[3] *= args[3] ?? 1;\n }\n }\n return out;\n}\n\n// `shader_parameter/*` values keyed by the EXACT uniform name (number for scalars,\n// component array for vectors) for the WebGL runtime.\nfunction shaderParams(\n properties: Record<string, GodotVariant>,\n): Record<string, number | number[]> {\n const out: Record<string, number | number[]> = {};\n for (const [name, value] of Object.entries(properties)) {\n if (!name.startsWith(\"shader_parameter/\")) {\n continue;\n }\n const key = name.slice(\"shader_parameter/\".length);\n const scalar = asNumber(value);\n if (scalar !== undefined) {\n out[key] = scalar;\n continue;\n }\n // A `uniform bool` param (e.g. an InvertNoiseMask toggle) is authored as a JSON\n // boolean; serialize it as 0/1 so the runtime's `uniform1i` upload sees it —\n // dropping it silently flipped such toggles to `false` on the GPU.\n if (typeof value === \"boolean\") {\n out[key] = value ? 1 : 0;\n continue;\n }\n if (\n value &&\n typeof value === \"object\" &&\n \"args\" in value &&\n Array.isArray((value as { args?: unknown[] }).args)\n ) {\n const args = (value as { args: unknown[] }).args.filter(\n (x): x is number => typeof x === \"number\",\n );\n if (args.length > 0) {\n out[key] = args;\n }\n }\n }\n return out;\n}\n\nfunction effectiveShaderMaterialProperties(\n materialProperties: Record<string, GodotVariant>,\n props: Record<string, GodotVariant>,\n): Record<string, GodotVariant> {\n let merged: Record<string, GodotVariant> | undefined;\n for (const [name, value] of Object.entries(props)) {\n if (!name.startsWith(\"shader_parameter/\")) {\n continue;\n }\n merged ??= { ...materialProperties };\n const materialValue = materialProperties[name];\n if (\n Array.isArray(value) &&\n materialValue &&\n typeof materialValue === \"object\" &&\n \"type\" in materialValue &&\n typeof (materialValue as { type?: unknown }).type === \"string\"\n ) {\n merged[name] = {\n ...(materialValue as Record<string, unknown>),\n args: value,\n } as GodotVariant;\n } else {\n merged[name] = value;\n }\n }\n return merged ?? materialProperties;\n}\n\nfunction shaderParamKinds(\n properties: Record<string, GodotVariant>,\n): Record<string, string> | undefined {\n const out: Record<string, string> = {};\n for (const [name, value] of Object.entries(properties)) {\n if (!name.startsWith(\"shader_parameter/\")) {\n continue;\n }\n if (\n value &&\n typeof value === \"object\" &&\n \"type\" in value &&\n typeof (value as { type?: unknown }).type === \"string\"\n ) {\n out[name.slice(\"shader_parameter/\".length)] = (\n value as { type: string }\n ).type;\n }\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\n/**\n * Whether a node carries a `ShaderMaterial` with a resolvable shader (path/uid).\n */\nexport function isShaderMaterialNode(\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): boolean {\n const materialRef = asResourceRef(props.material);\n if (!materialRef) {\n return false;\n }\n const material = normalizeResource(\n options.resolveResource?.(materialRef, source),\n );\n if (resourceType(material) !== \"ShaderMaterial\") {\n return false;\n }\n const shaderRef = asResourceRef(material?.document?.properties.shader);\n if (!shaderRef) {\n return false;\n }\n const { path, uid } = resolveShaderIdentity(\n material,\n shaderRef,\n source,\n options,\n );\n return Boolean(path || uid);\n}\n\n/**\n * Whether a node's `ShaderMaterial` is opted into the WebGL runtime. This is\n * generic renderer metadata: node path, shader path, or shader uid. No project or\n * shader name is recognized implicitly.\n */\nexport function isWebglShaderMaterialNode(\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n nodePath?: string,\n): boolean {\n if (!options.enableWebglShaders) {\n return false;\n }\n const materialRef = asResourceRef(props.material);\n if (!materialRef) {\n return false;\n }\n const material = normalizeResource(\n options.resolveResource?.(materialRef, source),\n );\n if (resourceType(material) !== \"ShaderMaterial\") {\n return false;\n }\n const shaderRef = asResourceRef(material?.document?.properties.shader);\n if (!shaderRef) {\n return false;\n }\n const { path, uid } = resolveShaderIdentity(\n material,\n shaderRef,\n source,\n options,\n );\n return (\n Boolean(path || uid) && isWebglShaderEnabled(options, nodePath, path, uid)\n );\n}\n\nfunction isWebglShaderEnabled(\n options: GodotHtmlRenderOptions,\n nodePath?: string,\n shaderPath?: string,\n shaderUid?: string,\n): boolean {\n // An HSV-adjust shader is the sanctioned NON-WebGL color primitive: gsw bakes it to a static\n // `feColorMatrix` tint (`materialColorMatrix`), far cheaper than a per-node WebGL canvas and how both\n // render paths handle it. So a shader designated HSV-adjust is NEVER run on WebGL — even under a\n // `webglShaderIds: [\"*\"]` wildcard or a per-node opt-in. This is what makes \"run every shader\" safe: a\n // consumer can pass `[\"*\"]` without HSV nodes getting a double paint (WebGL canvas + feColorMatrix tint).\n if (shaderIdListMatches(options.hsvAdjustShaderIds ?? [], shaderPath, shaderUid)) {\n return false;\n }\n if (nodePath) {\n if (options.shaderLoadingFallbacksByPath?.[nodePath]) return true;\n if (options.webglShaderNodesByPath?.[nodePath]) return true;\n }\n return shaderIdListMatches(\n options.webglShaderIds ?? [],\n shaderPath,\n shaderUid,\n );\n}\n\n// Whether a shader-id list (`webglShaderIds` / `hsvAdjustShaderIds` / …) selects a\n// node's shader. An entry matches by exact resource path or uid, by `\"*\"` (every\n// shader), or — when it ends in `/*` — by directory prefix on the path (e.g.\n// `res://shaders/my_family/*` selects a whole shader family without enumerating\n// every file).\nexport function shaderIdListMatches(\n ids: readonly string[],\n shaderPath?: string,\n shaderUid?: string,\n): boolean {\n if (ids.includes(\"*\")) return true;\n return ids.some((id) => {\n if (id.endsWith(\"/*\")) {\n const prefix = id.slice(0, -1); // keep the trailing slash so it's a directory match\n return Boolean(shaderPath?.startsWith(prefix));\n }\n return id === shaderPath || id === shaderUid;\n });\n}\n\n// Whether a node's static (non-WebGL) shader paint should be suppressed (the raw\n// texture beneath an activated WebGL canvas must not show through). Fully consumer-\n// driven: by rendered node path (`hiddenRawShaderFallbacksByPath`) or by shader\n// identity (`hiddenRawShaderFallbackShaderIds`, for a whole shader family).\nexport function isHiddenRawShaderFallbackMaterial(\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n nodePath?: string,\n): boolean {\n if (!options.enableWebglShaders) {\n return false;\n }\n if (nodePath && options.hiddenRawShaderFallbacksByPath?.[nodePath] === true) {\n return true;\n }\n const ids = options.hiddenRawShaderFallbackShaderIds ?? [];\n if (ids.length === 0) {\n return false;\n }\n const materialRef = asResourceRef(props.material);\n if (!materialRef) {\n return false;\n }\n const material = normalizeResource(\n options.resolveResource?.(materialRef, source),\n );\n if (resourceType(material) !== \"ShaderMaterial\") {\n return false;\n }\n const shaderRef = asResourceRef(material?.document?.properties.shader);\n if (!shaderRef) {\n return false;\n }\n const { path, uid } = resolveShaderIdentity(\n material,\n shaderRef,\n source,\n options,\n );\n return shaderIdListMatches(ids, path, uid);\n}\n\n/**\n * The shader's `res://` path and uid. The live presentation glue resolves a\n * `Shader` ExtResource to `undefined` (shaders are not bundled assets), so the\n * authoritative source is the material document's ext-resource table. A\n * path-first ref (a runtime producer emits `{type:\"ExtResource\", path}` with no\n * table) carries its own identity. Only then fall back to `resolveResource`\n * (used by unit tests / hosts that surface a path).\n */\nfunction resolveShaderIdentity(\n material: GodotResolvedResource | undefined,\n shaderRef: GodotResourceRefValue,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): { path: string | undefined; uid: string | undefined } {\n const ext = material?.document?.extResources?.find(\n (entry) => entry.id === shaderRef.id,\n );\n const path =\n ext?.path ??\n shaderRef.path ??\n (\n material?.shader ??\n normalizeResource(options.resolveResource?.(shaderRef, source))\n )?.path;\n return { path, uid: ext?.uid };\n}\n\n// Memo for `hsvColorMatrix` (module-scoped LRU, like `webgl/runtime`'s staticFrameCache).\n// WHY: the matrix is a 3× basis probe through `applyHsv` — 9 mat3 multiplies plus 9 `denoise`\n// rounds — and it is recomputed for EVERY hsv-adjust node on EVERY render, from a tiny set of\n// distinct (h,s,v) triples (phone traces put ~28% of a play-a-card burst inside this math).\n// Keyed on the EXACT inputs (no quantization) so a hit is byte-identical to a fresh compute;\n// the returned `ColorMatrix` has `readonly` rows, so sharing one instance is safe.\nconst HSV_COLOR_MATRIX_CACHE_LIMIT = 64;\nconst hsvColorMatrixCache = createStringLru<ColorMatrix>(\n HSV_COLOR_MATRIX_CACHE_LIMIT,\n);\n\n// Exact, round-trippable key part. `String` collapses -0 to \"0\", so spell it out: -0 and 0\n// are different inputs (they propagate to differently-signed zeros in the output rows).\nfunction hsvKeyPart(value: number): string {\n return Object.is(value, -0) ? \"-0\" : String(value);\n}\n\n/** TEST-ONLY: clear the HSV color-matrix memo so a test starts from an empty cache. */\nexport function __resetHsvColorMatrixCacheForTest(): void {\n hsvColorMatrixCache.clear();\n}\n\n/**\n * The 3×3 matrix realizing a standard HSV color adjust. Recovered by probing the\n * RGB basis vectors through `applyHsv`; the constant column is `0` because the\n * transform is linear (black maps to black). Memoized (see the LRU above) — pure,\n * so a hit is indistinguishable from a fresh compute.\n */\nexport function hsvColorMatrix(h: number, s: number, v: number): ColorMatrix {\n const key = `${hsvKeyPart(h)}|${hsvKeyPart(s)}|${hsvKeyPart(v)}`;\n const hit = hsvColorMatrixCache.get(key);\n if (hit) {\n return hit;\n }\n const c0 = applyHsv([1, 0, 0], h, s, v);\n const c1 = applyHsv([0, 1, 0], h, s, v);\n const c2 = applyHsv([0, 0, 1], h, s, v);\n const matrix: ColorMatrix = {\n rows: [\n [denoise(c0[0]), denoise(c1[0]), denoise(c2[0])],\n [denoise(c0[1]), denoise(c1[1]), denoise(c2[1])],\n [denoise(c0[2]), denoise(c1[2]), denoise(c2[2])],\n ],\n };\n hsvColorMatrixCache.set(key, matrix);\n return matrix;\n}\n\n// Erase the ~1e-16 float noise the YIQ round-trip leaves behind (it is far\n// finer than any meaningful per-channel difference) so identity/diagonal cases\n// land on exact values — e.g. v=0.9 stays 0.9, not 0.8999999999999999, which\n// otherwise straddles the 0.9*255=229.5 byte-rounding boundary.\nfunction denoise(value: number): number {\n return Math.round(value * 1e12) / 1e12;\n}\n\ntype Vec3 = [number, number, number];\n// A `mat3` in GLSL's column-major form: `mat3(col0, col1, col2)`.\ntype Mat3 = [Vec3, Vec3, Vec3];\n\n// The standard RGB→YIQ basis the HSV-adjust shader uses, and its inverse. Both are\n// CONSTANTS: the inverse used to be recomputed (a full cofactor/determinant pass) on every\n// `applyHsv` call — i.e. three times per `hsvColorMatrix`, per node, per render.\nconst RGB_TO_YIQ: Mat3 = [\n [0.2989, 0.5959, 0.2115],\n [0.587, -0.2774, -0.5229],\n [0.114, -0.3216, 0.3114],\n];\nconst YIQ_TO_RGB: Mat3 = mat3Inverse(RGB_TO_YIQ);\n\n/**\n * A statement-by-statement port of the standard HSV-adjust `fragment()` color math\n * for a single input RGB (modulate excluded — it is composed separately as the outer\n * diagonal in `textures.ts`). Kept literal so the basis-probe matrix is exact\n * regardless of GLSL convention.\n */\nexport function applyHsv(rgb: Vec3, h: number, s: number, v: number): Vec3 {\n let col: Vec3 = [rgb[0], rgb[1], rgb[2]];\n\n // col.rgb = RGB_to_YIQ * col.rgb\n col = mat3MulVec(RGB_TO_YIQ, col);\n\n // hue = mix(0, TAU, 1.0 - h)\n const hue = (1.0 - h) * 6.283185;\n const sinHue = Math.sin(hue);\n const cosHue = Math.cos(hue);\n const hueShift: Mat3 = [\n [1.0, 0, 0],\n [0, cosHue, -sinHue],\n [0, sinHue, cosHue],\n ];\n // col.rgb *= hue_shift (GLSL row-vector × matrix)\n col = vecMulMat3(col, hueShift);\n\n const satShift: Mat3 = [\n [1.0, 0, 0],\n [0, s, 0],\n [0, 0, s],\n ];\n // col.rgb = sat_shift * col.rgb\n col = mat3MulVec(satShift, col);\n\n // col.rgb = mix(vec3(0), col.rgb, v)\n col = [col[0] * v, col[1] * v, col[2] * v];\n\n // col.rgb = inverse(RGB_to_YIQ) * col.rgb\n col = mat3MulVec(YIQ_TO_RGB, col);\n\n return col;\n}\n\n// `m * v`: column-major `m`, so `m[k]` is column k. result = Σ_k v[k] · m[k].\nfunction mat3MulVec(m: Mat3, v: Vec3): Vec3 {\n return [\n m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2],\n m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2],\n m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2],\n ];\n}\n\n// `v * m` (GLSL row-vector × matrix): result[j] = dot(v, m[j]) (column j).\nfunction vecMulMat3(v: Vec3, m: Mat3): Vec3 {\n return [\n v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2],\n v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2],\n v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2],\n ];\n}\n\n// Inverse of a column-major `mat3`, returned in the same column-major form.\nfunction mat3Inverse(m: Mat3): Mat3 {\n // Element accessor in row/col terms: a(row, col) = m[col][row].\n const a = (row: number, col: number): number => m[col][row];\n const c00 = a(1, 1) * a(2, 2) - a(1, 2) * a(2, 1);\n const c01 = a(1, 2) * a(2, 0) - a(1, 0) * a(2, 2);\n const c02 = a(1, 0) * a(2, 1) - a(1, 1) * a(2, 0);\n const det = a(0, 0) * c00 + a(0, 1) * c01 + a(0, 2) * c02;\n const invDet = det !== 0 ? 1 / det : 0;\n // inv(row, col) = cofactor(col, row) / det.\n const inv = (row: number, col: number): number => {\n const r0 = (col + 1) % 3;\n const r1 = (col + 2) % 3;\n const c0 = (row + 1) % 3;\n const c1 = (row + 2) % 3;\n return (a(r0, c0) * a(r1, c1) - a(r0, c1) * a(r1, c0)) * invDet;\n };\n // Pack back into column-major columns.\n return [\n [inv(0, 0), inv(1, 0), inv(2, 0)],\n [inv(0, 1), inv(1, 1), inv(2, 1)],\n [inv(0, 2), inv(1, 2), inv(2, 2)],\n ];\n}\n\nfunction canvasItemBlendModeName(blendMode: number): string {\n switch (blendMode) {\n case 0:\n return \"mix\";\n case 1:\n return \"add\";\n case 2:\n return \"subtract\";\n case 3:\n return \"multiply\";\n case 4:\n return \"premultiplied-alpha\";\n case 5:\n return \"disabled\";\n default:\n return \"unknown\";\n }\n}\n\nfunction resourceType(\n resource: GodotResolvedResource | undefined,\n): string | undefined {\n return (\n resource?.type ?? asString(resource?.document?.header?.attributes.type)\n );\n}\n\nfunction godotValueLabel(value: GodotVariant): string {\n if (value === null) {\n return \"null\";\n }\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return String(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map(godotValueLabel).join(\", \")}]`;\n }\n if (typeof value === \"object\" && \"type\" in value) {\n const record = value as Record<string, unknown>;\n if (\n (record.type === \"ExtResource\" || record.type === \"SubResource\") &&\n (typeof record.id === \"string\" || typeof record.path === \"string\")\n ) {\n return `${record.type}(${record.id ?? record.path})`;\n }\n // Every other variant is the uniform `{ type, args }` shape (Vector/Color/\n // Rect/StringName/NodePath and arbitrary constructors).\n if (typeof record.type === \"string\" && Array.isArray(record.args)) {\n return `${record.type}(${(record.args as GodotVariant[]).map(godotValueLabel).join(\", \")})`;\n }\n }\n return JSON.stringify(value);\n}\n","import {\n type GodotAnchorHorizontalEdge,\n type GodotAnchorMap,\n type GodotAnchorVerticalEdge,\n type GodotSceneTreeDiagnostic,\n type GodotSceneTreeNode,\n parseAnchorEdge,\n} from \"@godot-scene-web/layout\";\nimport {\n anchorInsetExpression,\n appendAnchorName as mergeAnchorName,\n} from \"./anchor-css\";\nimport type { GodotHtmlNode } from \"./types\";\n\n/**\n * Browser-native counterpart of the computed pipeline's `resolveAnchors`:\n * instead of translating rects after a layout cascade, it emits native CSS\n * Anchor Positioning (`anchor-name` + `anchor()` inset functions) so the\n * BROWSER keeps the anchored node glued to its target's rendered geometry —\n * including `content*` edges, which become `min()`/`max()` over the target's\n * visible children's anchors (e.g. \"below however many relic rows exist\").\n * Geometry then tracks wrap/resize/scale with no JavaScript; the expressions\n * are regenerated with every model rebuild, which is also when the child list\n * can change. Browsers without anchor-positioning support drop the\n * declarations and keep the node's static scene position.\n *\n * Spec constraint honored here: an absolutely-positioned anchor that occurs\n * LATER in tree order than the positioned element is \"not acceptable\" (CSS\n * Anchor Positioning §target anchor element), and so is anything inside it.\n * When target and positioned node are siblings, the positioned node is moved\n * directly after its target in the parent's child order. DOM order is paint\n * order in this model, but the only pairwise order that changes is\n * target↔positioned — and a successfully anchored node no longer overlaps its\n * target by construction.\n */\nexport function applyBrowserAnchorPositioning(\n byPath: Map<string, GodotHtmlNode>,\n layoutByPath: Map<string, GodotSceneTreeNode>,\n anchors: GodotAnchorMap,\n diagnostics: GodotSceneTreeDiagnostic[],\n): void {\n const namesByTarget = new Map<string, string>();\n const anchorName = (targetPath: string): string => {\n let name = namesByTarget.get(targetPath);\n if (name === undefined) {\n name = `--gswa${namesByTarget.size}`;\n namesByTarget.set(targetPath, name);\n }\n return name;\n };\n\n for (const [selfPath, anchor] of Object.entries(anchors)) {\n const self = byPath.get(selfPath);\n if (!self || self.kind === \"hidden-placeholder\") {\n // Matches resolveAnchors: a declared-but-unrendered self is skipped\n // silently — an effectively-hidden node renders as a comment, so there\n // is no box to position.\n continue;\n }\n const target = byPath.get(anchor.anchorTo);\n if (!target) {\n diagnostics.push({\n severity: \"warning\",\n code: \"anchor-target-missing\",\n message: `Anchor target '${anchor.anchorTo}' not found for ${selfPath}.`,\n nodePath: selfPath,\n });\n continue;\n }\n const from = parseAnchorEdge(anchor.from);\n const to = parseAnchorEdge(anchor.to);\n if (!from || !to) {\n diagnostics.push({\n severity: \"warning\",\n code: \"anchor-edge-unparsed\",\n message: `Unrecognized anchor edge (from='${anchor.from}', to='${anchor.to}') for ${selfPath}.`,\n nodePath: selfPath,\n });\n continue;\n }\n if (\n to.vertical.startsWith(\"content\") ||\n to.horizontal.startsWith(\"content\") ||\n to.vertical === \"vcenter\" ||\n to.horizontal === \"hcenter\"\n ) {\n // `to` decides WHICH inset property is written; only the node's own box\n // corners map onto CSS insets. (Centering would need anchor-center\n // alignment — add when a consumer declares it.)\n diagnostics.push({\n severity: \"warning\",\n code: \"anchor-edge-unsupported\",\n message: `Browser anchor positioning only supports corner 'to' edges, got '${anchor.to}' for ${selfPath}.`,\n nodePath: selfPath,\n });\n continue;\n }\n if (self.positioning === \"container-managed\") {\n // A flow item can't be yanked to an absolute position without reflowing\n // its siblings — computed mode translates it, but that has no faithful\n // CSS counterpart here.\n diagnostics.push({\n severity: \"warning\",\n code: \"anchor-order-unresolvable\",\n message: `Anchored node ${selfPath} is container-managed; browser anchor positioning needs an absolutely positioned node.`,\n nodePath: selfPath,\n });\n continue;\n }\n\n ensureTargetPrecedesSelf(self, target, byPath);\n\n const name = anchorName(anchor.anchorTo);\n appendAnchorName(target, name);\n const needsContent =\n from.vertical.startsWith(\"content\") ||\n from.horizontal.startsWith(\"content\");\n const childNames: string[] = [];\n if (needsContent) {\n let index = 0;\n for (const childPath of target.children) {\n const child = byPath.get(childPath);\n if (!child || layoutByPath.get(childPath)?.visible === false) {\n continue;\n }\n const childName = `${name}c${index}`;\n appendAnchorName(child, childName);\n childNames.push(childName);\n index += 1;\n }\n }\n\n const targetNames = childNames.length > 0 ? childNames : [name];\n const offsetX = anchor.offset?.x ?? 0;\n const offsetY = anchor.offset?.y ?? 0;\n const vertical = anchorInsetExpression(\n verticalSide(from.vertical, childNames.length > 0),\n targetNames,\n from.vertical === \"contentBottom\" ? \"max\" : \"min\",\n // `bottom:` insets grow upward, so a downward catalog offset negates.\n to.vertical === \"bottom\" ? -offsetY : offsetY,\n );\n const horizontal = anchorInsetExpression(\n horizontalSide(from.horizontal, childNames.length > 0),\n targetNames,\n from.horizontal === \"contentRight\" ? \"max\" : \"min\",\n to.horizontal === \"right\" ? -offsetX : offsetX,\n );\n\n // Writing one inset of an axis releases the other so the box keeps its\n // content/min size instead of stretching between old and new insets.\n delete self.style.top;\n delete self.style.bottom;\n delete self.style.left;\n delete self.style.right;\n self.style[to.vertical === \"bottom\" ? \"bottom\" : \"top\"] = vertical;\n self.style[to.horizontal === \"right\" ? \"right\" : \"left\"] = horizontal;\n self.style.position = \"absolute\";\n self.positioning = \"absolute\";\n self.attributes[\"data-godot-positioning\"] = \"absolute\";\n }\n}\n\nfunction appendAnchorName(node: GodotHtmlNode, name: string): void {\n node.style[\"anchor-name\"] = mergeAnchorName(node.style[\"anchor-name\"], name);\n}\n\n// The anchor() side queried on the target (or its children) for a given edge\n// token. Zero-content fallback matches resolveAnchors' zero-size box at the\n// node's own origin: content edges collapse to the target's top/left.\nfunction verticalSide(\n edge: GodotAnchorVerticalEdge,\n hasContent: boolean,\n): \"top\" | \"bottom\" | \"center\" {\n switch (edge) {\n case \"bottom\":\n return \"bottom\";\n case \"vcenter\":\n return \"center\";\n case \"contentBottom\":\n return hasContent ? \"bottom\" : \"top\";\n default:\n return \"top\";\n }\n}\n\nfunction horizontalSide(\n edge: GodotAnchorHorizontalEdge,\n hasContent: boolean,\n): \"left\" | \"right\" | \"center\" {\n switch (edge) {\n case \"right\":\n return \"right\";\n case \"hcenter\":\n return \"center\";\n case \"contentRight\":\n return hasContent ? \"right\" : \"left\";\n default:\n return \"left\";\n }\n}\n\n// CSS Anchor Positioning's acceptability rule: an abs-pos anchor LATER in tree\n// order than the positioned element never resolves. When both are siblings,\n// move the positioned node directly after its target. Cross-parent late\n// targets are left alone (the declarations then no-op, keeping the static\n// position) — no real consumer has that shape.\nfunction ensureTargetPrecedesSelf(\n self: GodotHtmlNode,\n target: GodotHtmlNode,\n byPath: Map<string, GodotHtmlNode>,\n): void {\n if (self.parentPath === null || self.parentPath !== target.parentPath) {\n return;\n }\n const parent = byPath.get(self.parentPath);\n if (!parent) {\n return;\n }\n const selfIndex = parent.children.indexOf(self.path);\n const targetIndex = parent.children.indexOf(target.path);\n if (selfIndex === -1 || targetIndex === -1 || selfIndex > targetIndex) {\n return;\n }\n parent.children.splice(selfIndex, 1);\n // Recompute the target's slot after the removal shifted indices.\n parent.children.splice(\n parent.children.indexOf(target.path) + 1,\n 0,\n self.path,\n );\n}\n","import { asBoolean, asNumber } from \"@godot-scene-web/core\";\nimport type { GodotSceneTreeNode } from \"@godot-scene-web/layout\";\nimport { round } from \"./css-values\";\nimport { sourceNodeForLayout } from \"./resources\";\nimport { panelStyleBoxMetrics } from \"./style-box\";\nimport type {\n GodotHtmlContainerLayout,\n GodotHtmlNode,\n GodotHtmlRenderOptions,\n} from \"./types\";\n\nexport function assignContainerLayoutStyles(\n nodes: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n): void {\n const htmlByPath = new Map(nodes.map((node) => [node.path, node]));\n for (const parent of nodes) {\n const parentLayout = layoutByPath.get(parent.path);\n if (!parentLayout || !isCssContainerType(parent.type)) {\n continue;\n }\n parent.containerLayout = containerLayoutKind(parent.type);\n parent.attributes[\"data-godot-container-layout\"] = parent.containerLayout;\n const children = parent.children\n .map((path) => htmlByPath.get(path))\n .filter((child): child is GodotHtmlNode => Boolean(child))\n .filter(\n (child) => layoutByPath.get(child.path)?.parentPath === parent.path,\n );\n if (children.length === 0) {\n continue;\n }\n if (isBoxContainerType(parent.type)) {\n assignBoxContainerStyles(\n parent,\n parentLayout,\n children,\n layoutByPath,\n options,\n boxContainerHorizontal(parentLayout),\n );\n } else if (parent.type === \"AspectRatioContainer\") {\n assignAspectRatioContainerStyles(\n parent,\n parentLayout,\n children,\n layoutByPath,\n );\n } else if (isFlowContainerType(parent.type)) {\n assignFlowContainerStyles(\n parent,\n parentLayout,\n children,\n layoutByPath,\n options,\n flowContainerVertical(parentLayout),\n );\n } else if (parent.type === \"GridContainer\") {\n assignGridContainerStyles(\n parent,\n parentLayout,\n children,\n layoutByPath,\n options,\n );\n } else if (parent.type === \"CenterContainer\") {\n assignCenterContainerStyles(parent, parentLayout, children, layoutByPath);\n } else if (parent.type === \"MarginContainer\") {\n assignMarginContainerStyles(\n parent,\n parentLayout,\n children,\n layoutByPath,\n options,\n );\n } else if (parent.type === \"PanelContainer\") {\n assignPanelContainerStyles(\n parent,\n parentLayout,\n children,\n layoutByPath,\n options,\n );\n } else if (parent.type === \"ScrollContainer\") {\n assignScrollContainerStyles(\n parent,\n parentLayout,\n children,\n layoutByPath,\n options,\n );\n }\n }\n}\n\nfunction isCssContainerType(type: string): boolean {\n return (\n type === \"AspectRatioContainer\" ||\n type === \"BoxContainer\" ||\n type === \"HBoxContainer\" ||\n type === \"VBoxContainer\" ||\n type === \"HFlowContainer\" ||\n type === \"FlowContainer\" ||\n type === \"VFlowContainer\" ||\n type === \"GridContainer\" ||\n type === \"CenterContainer\" ||\n type === \"MarginContainer\" ||\n type === \"PanelContainer\" ||\n type === \"ScrollContainer\"\n );\n}\n\nfunction containerLayoutKind(type: string): GodotHtmlContainerLayout {\n if (isBoxContainerType(type)) {\n return \"box\";\n }\n if (isFlowContainerType(type)) {\n return \"flow\";\n }\n if (type === \"AspectRatioContainer\") {\n return \"aspect-ratio\";\n }\n if (type === \"GridContainer\") {\n return \"grid\";\n }\n if (type === \"CenterContainer\") {\n return \"center\";\n }\n if (type === \"MarginContainer\") {\n return \"margin\";\n }\n if (type === \"PanelContainer\") {\n return \"panel\";\n }\n return \"scroll\";\n}\n\nfunction isBoxContainerType(type: string): boolean {\n return (\n type === \"BoxContainer\" ||\n type === \"HBoxContainer\" ||\n type === \"VBoxContainer\"\n );\n}\n\nfunction boxContainerHorizontal(node: GodotSceneTreeNode): boolean {\n if (node.type === \"HBoxContainer\") {\n return true;\n }\n if (node.type === \"VBoxContainer\") {\n return false;\n }\n return !(asBoolean(node.properties.vertical) ?? false);\n}\n\nfunction isFlowContainerType(type: string): boolean {\n return (\n type === \"FlowContainer\" ||\n type === \"HFlowContainer\" ||\n type === \"VFlowContainer\"\n );\n}\n\nfunction flowContainerVertical(node: GodotSceneTreeNode): boolean {\n if (node.type === \"VFlowContainer\") {\n return true;\n }\n if (node.type === \"HFlowContainer\") {\n return false;\n }\n return asBoolean(node.properties.vertical) ?? false;\n}\n\nfunction assignBoxContainerStyles(\n parent: GodotHtmlNode,\n parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n horizontal: boolean,\n): void {\n const separation = themeNumber(parentLayout, \"separation\", options) ?? 0;\n parent.style.display = \"flex\";\n parent.style[\"flex-direction\"] = horizontal ? \"row\" : \"column\";\n parent.style[\"align-items\"] = \"flex-start\";\n if (separation !== 0) {\n parent.style.gap = `${round(separation)}px`;\n }\n let previousEnd = horizontal ? parentLayout.rect.x : parentLayout.rect.y;\n children.forEach((child, index) => {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n return;\n }\n setManagedChildPosition(child);\n if (horizontal) {\n child.style.flex = `0 0 ${round(layout.rect.width)}px`;\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n setMargin(\n child.style,\n \"left\",\n layout.rect.x - previousEnd - (index > 0 ? separation : 0),\n );\n setMargin(child.style, \"top\", layout.rect.y - parentLayout.rect.y);\n previousEnd = layout.rect.x + layout.rect.width;\n } else {\n child.style.flex = `0 0 ${round(layout.rect.height)}px`;\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n setMargin(\n child.style,\n \"top\",\n layout.rect.y - previousEnd - (index > 0 ? separation : 0),\n );\n setMargin(child.style, \"left\", layout.rect.x - parentLayout.rect.x);\n previousEnd = layout.rect.y + layout.rect.height;\n }\n });\n}\n\nfunction assignFlowContainerStyles(\n parent: GodotHtmlNode,\n _parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n vertical: boolean,\n): void {\n const hSeparation =\n themeNumber(_parentLayout, \"h_separation\", options) ??\n themeNumber(_parentLayout, \"separation\", options) ??\n 0;\n const vSeparation =\n themeNumber(_parentLayout, \"v_separation\", options) ??\n themeNumber(_parentLayout, \"separation\", options) ??\n 0;\n parent.style.display = \"flex\";\n parent.style[\"flex-direction\"] = vertical ? \"column\" : \"row\";\n parent.style[\"flex-wrap\"] = \"wrap\";\n parent.style[\"align-content\"] = \"flex-start\";\n parent.style[\"align-items\"] = \"flex-start\";\n if (hSeparation !== 0) {\n parent.style[\"column-gap\"] = `${round(hSeparation)}px`;\n }\n if (vSeparation !== 0) {\n parent.style[\"row-gap\"] = `${round(vSeparation)}px`;\n }\n for (const child of children) {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n continue;\n }\n setManagedChildPosition(child);\n child.style.flex = `0 0 ${round(vertical ? layout.rect.height : layout.rect.width)}px`;\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n }\n}\n\nfunction assignAspectRatioContainerStyles(\n parent: GodotHtmlNode,\n parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n): void {\n parent.style.display = \"grid\";\n parent.style[\"justify-items\"] = \"start\";\n parent.style[\"align-items\"] = \"start\";\n parent.attributes[\"data-godot-aspect-ratio\"] = String(\n asNumber(parentLayout.properties.ratio) ?? 1,\n );\n parent.attributes[\"data-godot-stretch-mode\"] = String(\n asNumber(parentLayout.properties.stretch_mode) ?? 2,\n );\n parent.attributes[\"data-godot-alignment-horizontal\"] = String(\n asNumber(parentLayout.properties.alignment_horizontal) ?? 1,\n );\n parent.attributes[\"data-godot-alignment-vertical\"] = String(\n asNumber(parentLayout.properties.alignment_vertical) ?? 1,\n );\n for (const child of children) {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n continue;\n }\n setManagedChildPosition(child);\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n child.style[\"grid-area\"] = \"1 / 1\";\n setMargin(child.style, \"left\", layout.rect.x - parentLayout.rect.x);\n setMargin(child.style, \"top\", layout.rect.y - parentLayout.rect.y);\n }\n}\n\nfunction assignGridContainerStyles(\n parent: GodotHtmlNode,\n parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n): void {\n const hSeparation =\n themeNumber(parentLayout, \"h_separation\", options) ??\n themeNumber(parentLayout, \"separation\", options) ??\n 0;\n const vSeparation =\n themeNumber(parentLayout, \"v_separation\", options) ??\n themeNumber(parentLayout, \"separation\", options) ??\n 0;\n const layouts = children\n .map((child) => layoutByPath.get(child.path))\n .filter((node): node is GodotSceneTreeNode => Boolean(node));\n const columns = layoutTracks(layouts, \"x\", \"width\");\n const rows = layoutTracks(layouts, \"y\", \"height\");\n parent.style.display = \"grid\";\n parent.style[\"grid-template-columns\"] = columns\n .map((track) => `${round(track.size)}px`)\n .join(\" \");\n parent.style[\"grid-template-rows\"] = rows\n .map((track) => `${round(track.size)}px`)\n .join(\" \");\n parent.style[\"justify-items\"] = \"start\";\n parent.style[\"align-items\"] = \"start\";\n if (hSeparation !== 0) {\n parent.style[\"column-gap\"] = `${round(hSeparation)}px`;\n }\n if (vSeparation !== 0) {\n parent.style[\"row-gap\"] = `${round(vSeparation)}px`;\n }\n for (const child of children) {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n continue;\n }\n const columnIndex = columns.findIndex((track) =>\n nearlyEqual(track.start, layout.rect.x),\n );\n const rowIndex = rows.findIndex((track) =>\n nearlyEqual(track.start, layout.rect.y),\n );\n setManagedChildPosition(child);\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n child.style[\"grid-column\"] = String(Math.max(1, columnIndex + 1));\n child.style[\"grid-row\"] = String(Math.max(1, rowIndex + 1));\n }\n}\n\nfunction assignCenterContainerStyles(\n parent: GodotHtmlNode,\n parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n): void {\n parent.style.display = \"grid\";\n parent.style[\"place-items\"] = \"center\";\n for (const child of children) {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n continue;\n }\n setManagedChildPosition(child);\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n child.style[\"grid-area\"] = \"1 / 1\";\n setMargin(\n child.style,\n \"left\",\n layout.rect.x -\n parentLayout.rect.x -\n (parentLayout.rect.width - layout.rect.width) / 2,\n );\n setMargin(\n child.style,\n \"top\",\n layout.rect.y -\n parentLayout.rect.y -\n (parentLayout.rect.height - layout.rect.height) / 2,\n );\n }\n}\n\nfunction assignMarginContainerStyles(\n parent: GodotHtmlNode,\n parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n): void {\n const left = themeNumber(parentLayout, \"margin_left\", options) ?? 0;\n const top = themeNumber(parentLayout, \"margin_top\", options) ?? 0;\n const right = themeNumber(parentLayout, \"margin_right\", options) ?? 0;\n const bottom = themeNumber(parentLayout, \"margin_bottom\", options) ?? 0;\n // CSS padding cannot be negative, but Godot MarginContainer margins can be (and\n // commonly are — e.g. top-bar icon positioners use negative margins to make a child\n // overflow its box). A negative padding is silently dropped by the browser, which\n // would leave the child at the container's top-left instead of shifted outward. Clamp\n // the padding inset to >= 0 and let the (negative-capable) child margin carry the full\n // remaining offset, so the child lands at its computed rect for any margin sign.\n const padLeft = Math.max(0, left);\n const padTop = Math.max(0, top);\n const padRight = Math.max(0, right);\n const padBottom = Math.max(0, bottom);\n parent.style.display = \"grid\";\n parent.style.padding = `${round(padTop)}px ${round(padRight)}px ${round(padBottom)}px ${round(padLeft)}px`;\n parent.style[\"justify-items\"] = \"start\";\n parent.style[\"align-items\"] = \"start\";\n for (const child of children) {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n continue;\n }\n setManagedChildPosition(child);\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n child.style[\"grid-area\"] = \"1 / 1\";\n setMargin(\n child.style,\n \"left\",\n layout.rect.x - parentLayout.rect.x - padLeft,\n );\n setMargin(child.style, \"top\", layout.rect.y - parentLayout.rect.y - padTop);\n }\n}\n\nfunction assignPanelContainerStyles(\n parent: GodotHtmlNode,\n parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n): void {\n const margins = panelStyleBoxMetrics(parentLayout, options);\n // The stylebox border is painted on the absolutely-positioned self-layer, so\n // it is out of flow here: the grid's content inset is the full content margin.\n parent.style.display = \"grid\";\n parent.style.padding = `${round(margins.top)}px ${round(margins.right)}px ${round(margins.bottom)}px ${round(margins.left)}px`;\n parent.style[\"justify-items\"] = \"start\";\n parent.style[\"align-items\"] = \"start\";\n for (const child of children) {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n continue;\n }\n setManagedChildPosition(child);\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n child.style[\"grid-area\"] = \"1 / 1\";\n setMargin(\n child.style,\n \"left\",\n layout.rect.x - parentLayout.rect.x - margins.left,\n );\n setMargin(\n child.style,\n \"top\",\n layout.rect.y - parentLayout.rect.y - margins.top,\n );\n }\n}\n\nfunction assignScrollContainerStyles(\n parent: GodotHtmlNode,\n parentLayout: GodotSceneTreeNode,\n children: GodotHtmlNode[],\n layoutByPath: Map<string, GodotSceneTreeNode>,\n options: GodotHtmlRenderOptions,\n): void {\n const margins = panelStyleBoxMetrics(parentLayout, options);\n // The stylebox border lives on the out-of-flow self-layer, so the scroll\n // viewport inset is the full content margin (see assignPanelContainerStyles).\n parent.style.display = \"block\";\n parent.style.padding = `${round(margins.top)}px ${round(margins.right)}px ${round(margins.bottom)}px ${round(margins.left)}px`;\n parent.style[\"overflow-x\"] = scrollOverflow(\n asNumber(parentLayout.properties.horizontal_scroll_mode),\n );\n parent.style[\"overflow-y\"] = scrollOverflow(\n asNumber(parentLayout.properties.vertical_scroll_mode),\n );\n delete parent.style.overflow;\n for (const child of children) {\n const layout = layoutByPath.get(child.path);\n if (!layout) {\n continue;\n }\n setManagedChildPosition(child);\n child.style.width = `${round(layout.rect.width)}px`;\n child.style.height = `${round(layout.rect.height)}px`;\n setMargin(\n child.style,\n \"left\",\n layout.rect.x - parentLayout.rect.x - margins.left,\n );\n setMargin(\n child.style,\n \"top\",\n layout.rect.y - parentLayout.rect.y - margins.top,\n );\n }\n}\n\nfunction scrollOverflow(mode: number | undefined): string {\n if (mode === 0 || mode === 3) {\n return \"hidden\";\n }\n if (mode === 2) {\n return \"scroll\";\n }\n return \"auto\";\n}\n\nfunction setManagedChildPosition(child: GodotHtmlNode): void {\n child.positioning = \"container-managed\";\n child.attributes[\"data-godot-positioning\"] = \"container-managed\";\n child.style.position = \"relative\";\n delete child.style.left;\n delete child.style.top;\n}\n\nfunction setMargin(\n style: Record<string, string>,\n side: \"left\" | \"top\",\n value: number,\n): void {\n const property = side === \"left\" ? \"margin-left\" : \"margin-top\";\n if (Math.abs(value) > 0.001) {\n style[property] = `${round(value)}px`;\n } else {\n delete style[property];\n }\n}\n\nfunction layoutTracks(\n nodes: GodotSceneTreeNode[],\n startKey: \"x\" | \"y\",\n sizeKey: \"width\" | \"height\",\n): Array<{ start: number; size: number }> {\n const byStart = new Map<number, number>();\n for (const node of nodes) {\n const start = node.rect[startKey];\n const existing = byStart.get(start) ?? 0;\n byStart.set(start, Math.max(existing, node.rect[sizeKey]));\n }\n return [...byStart.entries()]\n .sort(([left], [right]) => left - right)\n .map(([start, size]) => ({ start, size }));\n}\n\nfunction nearlyEqual(left: number, right: number): boolean {\n return Math.abs(left - right) < 0.001;\n}\n\nfunction themeNumber(\n node: GodotSceneTreeNode,\n name: string,\n options: GodotHtmlRenderOptions,\n): number | undefined {\n return (\n asNumber(node.properties[`theme_override_constants/${name}`]) ??\n asNumber(node.properties[`theme_constant_${name}`]) ??\n asNumber(options.resolveTheme?.(sourceNodeForLayout(node), name))\n );\n}\n","import {\n asBoolean,\n asNumber,\n type GodotVariant,\n isColorValue,\n} from \"@godot-scene-web/core\";\nimport type { GodotSceneTreeNode } from \"@godot-scene-web/layout\";\nimport { clamp, colorAlpha, colorCss, round } from \"./css-values\";\nimport type { GodotHtmlPositioning } from \"./types\";\n\nexport function assignPositionStyle(\n style: Record<string, string>,\n node: GodotSceneTreeNode,\n): GodotHtmlPositioning {\n if (node.parentPath === null) {\n style.position = \"relative\";\n delete style.left;\n delete style.top;\n return \"root\";\n } else {\n style.position = \"absolute\";\n return \"absolute\";\n }\n}\n\nexport function assignZIndexStyle(\n style: Record<string, string>,\n node: GodotSceneTreeNode,\n): void {\n if (node.zIndex !== 0) {\n style[\"z-index\"] = String(node.zIndex);\n }\n}\n\nexport function assignBackgroundColor(\n style: Record<string, string>,\n props: Record<string, GodotVariant>,\n nodeType?: string,\n): void {\n // A particle node's `color` is the PER-PARTICLE modulate (CPUParticles2D.color,\n // multiplied into every particle's color in cpu_particles_2d.cpp) — never a\n // CanvasItem rect fill. Painting it as a background filled the emitter's\n // visibility-rect-sized box with a translucent color wash (e.g. the Neow\n // background's `stars` emitter tinting the whole scene warm yellow). The\n // particle preview/runtime already applies it per particle.\n if (nodeType === \"CPUParticles2D\" || nodeType === \"GPUParticles2D\") {\n return;\n }\n // A ColorRect's fill defaults to Godot's white and is tinted by the node's\n // (self_)modulate RGB (e.g. an authored-white fullscreen Backstop modulated\n // black). Modulate alpha is applied separately by `assignOpacity`, so only the\n // RGB channels fold into the fill here.\n let color = props.color;\n if (nodeType === \"ColorRect\") {\n if (!isColorValue(color)) {\n color = { type: \"Color\", args: [1, 1, 1, 1] };\n }\n const [r = 0, g = 0, b = 0, a = 1] = color.args as number[];\n let [tr, tg, tb] = [r, g, b];\n for (const tint of [props.modulate, props.self_modulate]) {\n if (!isColorValue(tint)) {\n continue;\n }\n const [mr = 1, mg = 1, mb = 1] = tint.args as number[];\n tr *= clamp(mr, 0, 1);\n tg *= clamp(mg, 0, 1);\n tb *= clamp(mb, 0, 1);\n }\n color = { type: \"Color\", args: [tr, tg, tb, a] };\n }\n const background = colorCss(color);\n if (background) {\n style.background = background;\n }\n}\n\n// Godot control types whose default mouse_filter is IGNORE. Scenes omit mouse_filter on\n// these decorations, so without this the renderer would leave them inheriting\n// pointer-events:auto — and an oversized one (e.g. an event button's BlueFlash\n// confirmation flash, anchored centre and overflowing far past the button) would wrongly\n// become a click target. Honouring the class default makes them pointer-events:none,\n// matching the game's per-control-rect picking. NinePatchRect's IGNORE default is\n// established by the shipped game's event buttons working with these children unset\n// (STOP would block the button; PASS would bubble overflow clicks to it) and confirmed\n// end-to-end on the live render; Label is the documented Godot 4 default. Types whose\n// scenes set mouse_filter explicitly (TextureRect, RichTextLabel) are deliberately left\n// off — explicit values already drive them, and they aren't broadened here.\nconst MOUSE_FILTER_IGNORE_DEFAULT_TYPES = new Set([\"NinePatchRect\", \"Label\"]);\n\nexport function assignPointerEvents(\n style: Record<string, string>,\n props: Record<string, GodotVariant>,\n nodeType?: string,\n): void {\n // Godot mouse_filter: 0=STOP (consumes input), 1=PASS (handles, then bubbles to\n // the parent), 2=IGNORE. STOP must be an explicit `auto` — pointer-events\n // inherits, so a STOP node inside an IGNORE subtree (a fullscreen overlay's\n // backstop under a mouse_filter=2 global UI layer) would otherwise stay\n // hit-transparent. PASS is left unmapped: it neither blocks nor needs to\n // override an inherited value for parity.\n //\n // When the scene omits mouse_filter, fall back to the node type's Godot default:\n // IGNORE-by-default decorations map to pointer-events:none so they don't become\n // spurious click targets (everything else stays unmapped/inherited as before).\n let filter = asNumber(props.mouse_filter);\n if (\n filter === undefined &&\n nodeType &&\n MOUSE_FILTER_IGNORE_DEFAULT_TYPES.has(nodeType)\n ) {\n filter = 2;\n }\n if (filter === 2) {\n style[\"pointer-events\"] = \"none\";\n } else if (filter === 0) {\n style[\"pointer-events\"] = \"auto\";\n }\n}\n\nexport function assignOpacity(\n style: Record<string, string>,\n selfStyle: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n): void {\n const modulate = colorCss(props.modulate);\n const selfModulate = colorCss(props.self_modulate);\n if (modulate) {\n attributes[\"data-godot-modulate\"] = modulate;\n }\n if (selfModulate) {\n attributes[\"data-godot-self-modulate\"] = selfModulate;\n }\n const modulateAlpha = colorAlpha(props.modulate);\n const selfModulateAlpha = colorAlpha(props.self_modulate);\n if (modulateAlpha < 1) {\n style.opacity = String(round(modulateAlpha));\n }\n if (selfModulateAlpha < 1) {\n selfStyle.opacity = String(round(selfModulateAlpha));\n }\n}\n\nexport function assignTransform(\n style: Record<string, string>,\n node: GodotSceneTreeNode,\n props: Record<string, GodotVariant>,\n): void {\n // NOTE: `flip_h`/`flip_v` are deliberately NOT folded into this outer-element\n // transform. In Godot they mirror only the node's OWN texture, never its child\n // nodes, but a CSS transform on the outer element cascades to children. The flip\n // is applied to the self-layer instead — see `assignSelfLayerFlip`.\n const scaleX = node.scale.x;\n const scaleY = node.scale.y;\n const rotation = asNumber(props.rotation) ?? asNumber(props.rotation_degrees);\n const rotationUnit = asNumber(props.rotation) !== undefined ? \"rad\" : \"deg\";\n const skew = asNumber(props.skew);\n const transforms: string[] = [];\n if (rotation !== undefined && rotation !== 0) {\n transforms.push(`rotate(${round(rotation)}${rotationUnit})`);\n }\n if (skew !== undefined && skew !== 0) {\n transforms.push(`skewX(${round(skew)}rad)`);\n }\n if (scaleX !== 1 || scaleY !== 1) {\n transforms.push(`scale(${round(scaleX)}, ${round(scaleY)})`);\n }\n if (transforms.length > 0) {\n style.transform = transforms.join(\" \");\n // Godot Control scales/rotates around `pivot_offset`, whose default is\n // (0,0) = top-left. A genuine non-identity `node.scale` must therefore grow\n // from the pivot (top-left by default) to agree with `renderedRect`/live\n // `get_global_rect()`. Rotation/skew keep the legacy center default when no\n // explicit pivot is set.\n const hasGenuineScale = node.scale.x !== 1 || node.scale.y !== 1;\n if (node.pivotOffset.x !== 0 || node.pivotOffset.y !== 0) {\n style[\"transform-origin\"] =\n `${round(node.pivotOffset.x)}px ${round(node.pivotOffset.y)}px`;\n } else if (hasGenuineScale) {\n style[\"transform-origin\"] = \"0px 0px\";\n } else {\n style[\"transform-origin\"] = \"50% 50%\";\n }\n }\n}\n\n// Applies a `flip_h`/`flip_v` mirror to a node's self-layer style (the element that\n// paints the node's own texture, a sibling of the node's child elements). Keeping the\n// flip on the self-layer mirrors only the texture — matching Godot, where TextureRect/\n// Sprite flips never affect child nodes — instead of cascading to children via the\n// outer element transform. Composes with any pre-existing self-layer transform.\nexport function assignSelfLayerFlip(\n selfStyle: Record<string, string>,\n props: Record<string, GodotVariant>,\n): void {\n const flipX = asBoolean(props.flip_h) === true;\n const flipY = asBoolean(props.flip_v) === true;\n if (!flipX && !flipY) {\n return;\n }\n const flip = `scale(${flipX ? -1 : 1}, ${flipY ? -1 : 1})`;\n selfStyle.transform = selfStyle.transform\n ? `${selfStyle.transform} ${flip}`\n : flip;\n if (!selfStyle[\"transform-origin\"]) {\n selfStyle[\"transform-origin\"] = \"50% 50%\";\n }\n}\n\nexport function assignDrawAttributes(\n attributes: Record<string, string>,\n node: GodotSceneTreeNode,\n props: Record<string, GodotVariant>,\n): void {\n attributes[\"data-godot-draw-order\"] = String(node.drawOrder);\n attributes[\"data-godot-z-index\"] = String(node.zIndex);\n if (node.zAsRelative === false) {\n attributes[\"data-godot-z-as-relative\"] = \"false\";\n }\n if (node.showBehindParent) {\n attributes[\"data-godot-show-behind-parent\"] = \"true\";\n }\n if (asBoolean(props.flip_h) === true) {\n attributes[\"data-godot-flip-h\"] = \"true\";\n }\n if (asBoolean(props.flip_v) === true) {\n attributes[\"data-godot-flip-v\"] = \"true\";\n }\n}\n\nexport function assignRangeStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n): void {\n const min = asNumber(props.min_value) ?? 0;\n const max = asNumber(props.max_value) ?? 100;\n const value = asNumber(props.value) ?? min;\n const percent =\n max > min ? clamp((value - min) / (max - min), 0, 1) * 100 : 0;\n attributes[\"data-godot-range-min\"] = String(min);\n attributes[\"data-godot-range-max\"] = String(max);\n attributes[\"data-godot-range-value\"] = String(value);\n if (asNumber(props.step) !== undefined) {\n attributes[\"data-godot-range-step\"] = String(asNumber(props.step));\n }\n style[\"--godot-range-percent\"] = `${round(percent)}%`;\n}\n","// Player-adjustable text scaling. When enabled, every text size and font-derived\n// decoration is emitted as `calc(<px> * var(--godot-text-scale, 1))`, so a host can\n// set `--godot-text-scale` on the stage at runtime (e.g. an accessibility slider)\n// and resize all text live, with no re-render. The fallback `1` makes it inert\n// until a value is set.\n\nexport const TEXT_SCALE_VAR = \"--godot-text-scale\";\n\nexport interface GodotTextScale {\n // Keep auto-fit text fitted to its box and unscaled (the scale still applies to\n // all other text). Default `false`: the scale applies to auto-fit text too.\n exemptAutoFit?: boolean;\n}\n\nexport type GodotTextScaleOption = boolean | GodotTextScale;\n\nexport interface ResolvedTextScale {\n exemptAutoFit: boolean;\n}\n\nexport function resolveTextScale(\n option: GodotTextScaleOption | undefined,\n): ResolvedTextScale | null {\n if (!option) {\n return null;\n }\n return {\n exemptAutoFit: option === true ? false : Boolean(option.exemptAutoFit),\n };\n}\n\n// Wrap a px length so it tracks `--godot-text-scale`, or pass it through unchanged\n// when text scaling is off for this node.\nexport function textScaleLength(px: number, enabled: boolean): string {\n return enabled ? `calc(${px}px * var(${TEXT_SCALE_VAR}, 1))` : `${px}px`;\n}\n\n// Host convenience: set the live text scale on a stage/frame element (or any text\n// ancestor). The value cascades to all text within.\nexport function setGodotTextScale(element: HTMLElement, value: number): void {\n element.style.setProperty(TEXT_SCALE_VAR, String(value));\n}\n","import { asNumber, type GodotVariant } from \"@godot-scene-web/core\";\nimport type { GodotSceneTreeNode } from \"@godot-scene-web/layout\";\nimport {\n colorCss,\n cssUrl,\n escapeAttribute,\n escapeHtml,\n round,\n safeClassSegment,\n styleAttribute,\n} from \"./css-values\";\nimport { createStringLru } from \"./lru\";\nimport {\n registerFontFace,\n resolveFont,\n sourceNodeForLayout,\n} from \"./resources\";\nimport { textScaleLength } from \"./text-scale\";\nimport type {\n GodotHtmlFontFace,\n GodotHtmlRenderOptions,\n GodotResolvedResource,\n} from \"./types\";\n\nconst DEFAULT_TEXT_COLOR = \"rgba(255, 255, 255, 1)\";\n\nexport function assignTextStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n node: GodotSceneTreeNode,\n props: Record<string, GodotVariant>,\n options: GodotHtmlRenderOptions,\n fontFaces: GodotHtmlFontFace[],\n // When true, every text size/decoration tracks `var(--godot-text-scale, 1)`.\n scaleText: boolean,\n): void {\n const len = (px: number): string => textScaleLength(px, scaleText);\n const source = sourceNodeForLayout(node);\n style[\"align-items\"] = textAlignItems(node.textVerticalAlign);\n style[\"justify-content\"] = textJustify(node.textAlign);\n style[\"text-align\"] = node.textAlign === \"fill\" ? \"justify\" : node.textAlign;\n // Honor Godot's `autowrap_mode`: AUTOWRAP_OFF (0) text never reflows, so it must\n // not inherit the base `white-space: pre-wrap`. Without this, a non-wrapping label\n // in a point-anchored container (whose CSS width is `min-content`) collapses to its\n // longest word and wraps — the bottom prompt of the deck-card-selection dialog\n // (\"Elige 2 cartas para quitar.\"). `pre` keeps explicit newlines, only dropping the\n // auto-wrap. Defaults match Godot: Label OFF (0), RichTextLabel WORD_SMART (3).\n const autowrapMode = asNumber(\n firstGodotValue(\n props.autowrap_mode,\n options.resolveTheme?.(source, \"autowrap_mode\"),\n ),\n );\n const wraps =\n node.type === \"RichTextLabel\"\n ? (autowrapMode ?? 3) !== 0\n : (autowrapMode ?? 0) !== 0;\n if (!wraps) style[\"white-space\"] = \"pre\";\n const color =\n colorCss(\n firstGodotValue(\n props[\"theme_override_colors/font_color\"],\n props[\"theme_override_colors/default_color\"],\n options.resolveTheme?.(source, \"font_color\"),\n options.resolveTheme?.(source, \"default_color\"),\n ),\n ) ?? DEFAULT_TEXT_COLOR;\n style.color = color;\n const normalFont = resolveFont(\n firstGodotValue(\n props[\"theme_override_fonts/font\"],\n props[\"theme_override_fonts/normal_font\"],\n options.resolveTheme?.(source, \"font\"),\n options.resolveTheme?.(source, \"normal_font\"),\n ),\n node,\n options,\n );\n const hasExplicitFontFile =\n node.type === \"RichTextLabel\" && Boolean(normalFont?.fontUrl);\n const fontSize = asNumber(\n firstGodotValue(\n props[\"theme_override_font_sizes/font_size\"],\n props[\"theme_override_font_sizes/normal_font_size\"],\n options.resolveTheme?.(source, \"font_size\"),\n options.resolveTheme?.(source, \"normal_font_size\"),\n ),\n );\n const shouldScaleRichTextSize =\n node.type === \"RichTextLabel\" && !hasExplicitFontFile;\n if (node.type === \"RichTextLabel\") {\n attributes[\"data-godot-rich-text-scale-font-size\"] = String(\n shouldScaleRichTextSize,\n );\n }\n const renderedFontSize = renderRichTextFontSize(\n fontSize,\n shouldScaleRichTextSize,\n );\n if (renderedFontSize !== undefined && node.type !== \"RichTextLabel\") {\n style[\"font-size\"] = len(renderedFontSize);\n }\n const lineSeparation = asNumber(\n firstGodotValue(\n props[\"theme_override_constants/line_separation\"],\n options.resolveTheme?.(source, \"line_separation\"),\n ),\n );\n if (lineSeparation !== undefined && renderedFontSize !== undefined) {\n style[\"line-height\"] = len(Math.max(1, renderedFontSize + lineSeparation));\n }\n if (lineSeparation !== undefined) {\n // Surfaced for auto-fit, which recomputes line-height from the fitted size.\n attributes[\"data-godot-line-separation-px\"] = String(lineSeparation);\n }\n const outlineColor =\n colorCss(\n firstGodotValue(\n props[\"theme_override_colors/font_outline_color\"],\n options.resolveTheme?.(source, \"font_outline_color\"),\n ),\n ) ?? \"rgba(0, 0, 0, 1)\";\n const outlineSize =\n asNumber(\n firstGodotValue(\n props[\"theme_override_constants/outline_size\"],\n options.resolveTheme?.(source, \"outline_size\"),\n ),\n ) ?? 0;\n const shadowColor =\n colorCss(\n firstGodotValue(\n props[\"theme_override_colors/font_shadow_color\"],\n options.resolveTheme?.(source, \"font_shadow_color\"),\n ),\n ) ?? \"rgba(0, 0, 0, 0)\";\n const shadowX =\n asNumber(\n firstGodotValue(\n props[\"theme_override_constants/shadow_offset_x\"],\n options.resolveTheme?.(source, \"shadow_offset_x\"),\n ),\n ) ?? 0;\n const shadowY =\n asNumber(\n firstGodotValue(\n props[\"theme_override_constants/shadow_offset_y\"],\n options.resolveTheme?.(source, \"shadow_offset_y\"),\n ),\n ) ?? 0;\n const shadowOutlineSize =\n asNumber(\n firstGodotValue(\n props[\"theme_override_constants/shadow_outline_size\"],\n options.resolveTheme?.(source, \"shadow_outline_size\"),\n ),\n ) ?? 1;\n const cssOutlineSize = cssOutlineSizeForFont(outlineSize, normalFont);\n const cssShadowOutlineSize = cssOutlineSizeForFont(\n shadowOutlineSize,\n normalFont,\n );\n if (node.type === \"RichTextLabel\") {\n style[\"--godot-rich-text-color\"] = color ?? \"currentColor\";\n style[\"--godot-rich-outline-color\"] = outlineColor;\n style[\"--godot-rich-outline-size\"] = len(cssOutlineSize);\n style[\"--godot-rich-shadow-color\"] = shadowColor;\n style[\"--godot-rich-shadow-x\"] = len(round(shadowX));\n style[\"--godot-rich-shadow-y\"] = len(round(shadowY));\n style[\"--godot-rich-shadow-outline-size\"] = len(cssShadowOutlineSize);\n // Each rich-text role size: an inline `theme_override_font_sizes/*` wins; otherwise\n // fall back to the node's theme (resolveTheme), so a RichTextLabel sized only by its\n // theme's `default_font_size` no longer collapses to the 1em CSS fallback. The normal\n // role also accepts the generic `font_size` item the theme default lives under.\n assignRichTextFontSize(\n style,\n \"--godot-rich-normal-font-size\",\n firstGodotValue(\n props[\"theme_override_font_sizes/normal_font_size\"],\n options.resolveTheme?.(source, \"normal_font_size\"),\n options.resolveTheme?.(source, \"font_size\"),\n ),\n shouldScaleRichTextSize,\n scaleText,\n );\n assignRichTextFontSize(\n style,\n \"--godot-rich-bold-font-size\",\n firstGodotValue(\n props[\"theme_override_font_sizes/bold_font_size\"],\n options.resolveTheme?.(source, \"bold_font_size\"),\n ),\n shouldScaleRichTextSize,\n scaleText,\n );\n assignRichTextFontSize(\n style,\n \"--godot-rich-italic-font-size\",\n firstGodotValue(\n props[\"theme_override_font_sizes/italics_font_size\"],\n options.resolveTheme?.(source, \"italics_font_size\"),\n ),\n shouldScaleRichTextSize,\n scaleText,\n );\n assignRichTextFontSize(\n style,\n \"--godot-rich-bold-italic-font-size\",\n firstGodotValue(\n props[\"theme_override_font_sizes/bold_italics_font_size\"],\n options.resolveTheme?.(source, \"bold_italics_font_size\"),\n ),\n shouldScaleRichTextSize,\n scaleText,\n );\n } else {\n if (outlineSize > 0) {\n style[\"-webkit-text-stroke\"] = `${len(cssOutlineSize)} ${outlineColor}`;\n style[\"paint-order\"] = \"stroke fill\";\n }\n if (\n shadowColor !== \"rgba(0, 0, 0, 0)\" &&\n (shadowX !== 0 || shadowY !== 0)\n ) {\n style[\"text-shadow\"] = `${len(shadowX)} ${len(shadowY)} 0 ${shadowColor}`;\n }\n }\n if (normalFont) {\n registerFontFace(fontFaces, normalFont);\n const font = normalFont;\n if (font.fontFamily) {\n style[\"font-family\"] = font.fontFamily;\n attributes[\"data-godot-font-family\"] = font.fontFamily;\n }\n if (font.path) {\n attributes[\"data-godot-font-path\"] = font.path;\n }\n if (font.glyphSpacing !== undefined) {\n style[\"--godot-rich-letter-spacing\"] = len(\n round(font.glyphSpacing * 0.75),\n );\n } else if (hasExplicitFontFile) {\n style[\"--godot-rich-letter-spacing\"] = len(0);\n }\n }\n // Godot's embedded default DynamicFont has no glyph spacing. The historical\n // browser fallback needed 0.25px tracking, but retaining it after selecting\n // the exact Open Sans bytes widens implicit Labels (for example\n // SpriteFrames) beyond Godot's measured advance. Explicit faces continue to\n // use their own spacing path above.\n if (node.type === \"Label\" && !normalFont) {\n style[\"--godot-label-letter-spacing\"] = len(0);\n }\n if (node.type === \"RichTextLabel\") {\n // Each rich-text role (bold/italics/bold-italics) can override the font with\n // its own FontVariation. Register the resolved face and expose its family as\n // a CSS var so `.godot-rich-bold`/`-italic` use it instead of inheriting the\n // normal font. Gate on a usable face (family + url); otherwise the run falls\n // back via `inherit` to the normal font, matching prior behavior.\n for (const [role, cssVar] of [\n [\"bold_font\", \"--godot-rich-bold-font-family\"],\n [\"italics_font\", \"--godot-rich-italic-font-family\"],\n [\"bold_italics_font\", \"--godot-rich-bold-italic-font-family\"],\n ] as const) {\n const roleFont = resolveFont(\n firstGodotValue(\n props[`theme_override_fonts/${role}`],\n options.resolveTheme?.(source, role),\n ),\n node,\n options,\n );\n registerFontFace(fontFaces, roleFont);\n if (roleFont?.fontFamily && roleFont.fontUrl) {\n style[cssVar] = roleFont.fontFamily;\n }\n if (role === \"bold_font\" && !roleFont?.fontUrl) {\n // Godot's default theme owns a separate synthetic bold FontVariation\n // (`variation_embolden = 1.2`), rather than inheriting a normal-role\n // FontVariation's glyph spacing. TextServerAdvanced adds\n // `embolden * (font_size * 64) / 4096` to each glyph advance (0.3px at\n // the 16px default); CSS synthetic weight only expands ink, not Range\n // advances. The 0.5px browser advance emulation includes the measured\n // cross-shaper/hinting rounding gap after that source-derived 0.3px.\n // Conversely, a normal role that supplied `spacing_glyph` must not leak\n // that spacing into this separate bold role. Explicit FontFile and\n // FontVariation bold faces remain untouched.\n style[\"--godot-rich-bold-letter-spacing\"] = len(\n normalFont?.glyphSpacing === undefined ? 0.5 : 0,\n );\n }\n }\n }\n}\n\nfunction firstGodotValue(\n ...values: Array<GodotVariant | undefined>\n): GodotVariant | undefined {\n return values.find((value) => value !== undefined);\n}\n\nfunction assignRichTextFontSize(\n style: Record<string, string>,\n property: string,\n value: GodotVariant | undefined,\n shouldScale: boolean,\n scaleText: boolean,\n): void {\n const fontSize = renderRichTextFontSize(asNumber(value), shouldScale);\n if (fontSize !== undefined) {\n style[property] = textScaleLength(fontSize, scaleText);\n }\n}\n\nexport function renderRichTextFontSize(\n fontSize: number | undefined,\n shouldScale: boolean,\n): number | undefined {\n if (fontSize === undefined) {\n return undefined;\n }\n return shouldScale ? round(fontSize * 0.8) : fontSize;\n}\n\n// `outline_size` is a Godot theme constant, not a CSS stroke width, and the two halves of this\n// ternary convert it under two different engine mechanisms.\n//\n// NON-MSDF — the `* 0.5`, and it is exact. Godot strokes the glyph with FreeType's stroker at a\n// RADIUS of `outline_size / 4` (`FT_Stroker_Set(stroker, outline_size * 16, …)`, whose argument is\n// 26.6 fixed point, so `16 / 64` px), which reaches `outline_size / 4` px OUTSIDE the silhouette\n// and does not move with `font_size`. `-webkit-text-stroke` is CENTRED on the glyph's contour, so a\n// width `W` reaches `W / 2` outward: `W = outline_size * 0.5` lands the browser's outer edge on\n// Godot's. `round` here is `css-values.ts`'s 3-decimal quantizer, NOT an integer snap — an odd\n// `outline_size` keeps its half pixel, and `outline_size` 3 emits `1.5px`. See\n// `docs/text-rendering.md` (\"What `-webkit-text-stroke` has to be…\") for the reach measured in a\n// browser against that arithmetic.\n//\n// MSDF — the passthrough, and it rests on an ASSUMPTION NOTHING HERE CHECKS. An MSDF face is\n// rasterised once at `msdf_size` and its outline is a threshold shift in the canvas shader\n// (`cr = outline_size / msdf_pixel_range`), which moves the contour `outline_size` px outward in\n// SOURCE-SIZE units and is then scaled to the screen by `font_size / msdf_size`. So Godot reaches\n// `outline_size * font_size / msdf_size` while this branch's `W = outline_size` reaches\n// `outline_size / 2` — equal only when `font_size == msdf_size / 2`.\n//\n// That equality is PER LABEL, and UNVERIFIED IN ANY REAL CONSUMER — there is no pixel-parity\n// coverage of this branch anywhere. sts2 imports its faces at `msdf_size = 48`, so it would need\n// `font_size` 24 exactly; a census of its own recordings finds outlined labels at 15 through 96,\n// with 24 real but a minority — 1565 of 10 046 samples, against 2208 at 26 and 1716 at 96. So the\n// branch would be right for about one outlined label in six and wrong for the rest, if it ran at\n// all. It does not: that consumer's live path never sets `fontMsdf` (the flag is absent from the\n// scene-state wire protocol), so what ships there is the non-MSDF arm above. Treat this one as\n// unexercised rather than confirmed, and measure before trusting it.\nfunction cssOutlineSizeForFont(\n outlineSize: number,\n font: GodotResolvedResource | undefined,\n): number {\n return font?.fontMsdf === true ? outlineSize : round(outlineSize * 0.5);\n}\n\nfunction textJustify(value: GodotSceneTreeNode[\"textAlign\"]): string {\n switch (value) {\n case \"center\":\n return \"center\";\n case \"right\":\n return \"flex-end\";\n default:\n return \"flex-start\";\n }\n}\n\nfunction textAlignItems(\n value: GodotSceneTreeNode[\"textVerticalAlign\"],\n): string {\n switch (value) {\n case \"center\":\n return \"center\";\n case \"bottom\":\n return \"flex-end\";\n default:\n return \"flex-start\";\n }\n}\n\nexport function textProp(value: GodotVariant | undefined): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\ninterface RichTextEffect {\n name: string;\n perChar: boolean;\n perWord: boolean;\n className?: string;\n}\n\ninterface RichTextTag {\n type:\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"strike\"\n | \"code\"\n | \"align\"\n | \"indent\"\n | \"color\"\n | \"bgcolor\"\n | \"url\"\n | \"font_size\"\n | \"style\"\n | \"effect\"\n | \"structural\";\n // Identity used to match an opening tag with its closing tag (the bbcode name).\n id: string;\n value?: string;\n css?: Record<string, string>;\n effect?: RichTextEffect;\n}\n\n/** Public tag kinds produced by Godot's built-in BBCode grammar. */\nexport type GodotBbcodeTagKind = RichTextTag[\"type\"] | \"image\" | \"void\";\n\n// Official Godot effect tags with the visible animation we model. `perChar`\n// nodes are split into word/char spans so external CSS can stagger them.\nexport const GODOT_BBCODE_BUILT_IN_EFFECTS: Readonly<\n Record<string, Readonly<{ perChar: boolean; perWord: boolean }>>\n> = Object.freeze({\n rainbow: Object.freeze({ perChar: true, perWord: false }),\n wave: Object.freeze({ perChar: true, perWord: false }),\n shake: Object.freeze({ perChar: true, perWord: false }),\n tornado: Object.freeze({ perChar: true, perWord: false }),\n pulse: Object.freeze({ perChar: false, perWord: false }),\n fade: Object.freeze({ perChar: true, perWord: false }),\n});\n\nconst SIMPLE_RICH_TEXT_TAGS: Record<string, RichTextTag[\"type\"]> = {\n b: \"bold\",\n i: \"italic\",\n u: \"underline\",\n s: \"strike\",\n code: \"code\",\n indent: \"indent\",\n};\n\n// Inline image (`[img]`) options parsed from the tag. The path is the tag's\n// content, read separately by the main loop.\ninterface RichTextImgOptions {\n width?: number;\n height?: number;\n valign?: \"top\" | \"middle\" | \"bottom\";\n region?: { x: number; y: number; width: number; height: number };\n alt?: string;\n}\n\ntype ParsedRichTextTag =\n | { close: boolean; void: true; html: string }\n | { close: boolean; img: true; options?: RichTextImgOptions }\n | ({ close: boolean; void?: false; img?: false } & RichTextTag);\n\n// Context threaded through the rich-text renderer. `resolveImage` is a closure\n// built in model.ts so this module stays free of node/resolveResource plumbing.\nexport interface RichTextRenderContext {\n customTags?: GodotHtmlRenderOptions[\"bbcodeTags\"];\n resolveImage?: (path: string) => GodotResolvedResource | undefined;\n // When true, `[font_size]` runs track `var(--godot-text-scale, 1)`.\n textScale?: boolean;\n}\n\nfunction richTextHtml(value: string, ctx: RichTextRenderContext = {}): string {\n const out: string[] = [];\n const styleStack: RichTextTag[] = [];\n const charCounter = { value: 0 };\n let buffer = \"\";\n // Godot applies `[center]/[left]/[right]/[fill]` (and `[p align=…]`) per\n // PARAGRAPH: a contiguous aligned region is one `<p>` block whose `text-align`\n // centers each visual line. Inside that region a hard newline (`\\n`/`\\r\\n`)\n // also starts a NEW paragraph in Godot (see RichTextLabel docs) — so the runs\n // between newlines become separate `.godot-rich-paragraph` BLOCKS: each block's\n // WRAPPED lines share `--godot-rich-line-height` while the gap BETWEEN blocks is\n // `--godot-rich-paragraph-spacing` (both default to `normal`/`0`, so a region\n // with no consumer overrides renders identically to the old single-line-height\n // flow). We collect the runs of the active alignment as one segment per newline\n // and emit the `<p>` (with its blocks) when the alignment changes or clears.\n // `null` = no active alignment, so runs emit inline at the top level —\n // byte-identical to the common no-`[center]` label (top-level `\\n` stays inline\n // via `white-space: pre-wrap`, untouched).\n let para: { align: string; segments: string[][] } | null = null;\n const closeParagraph = (): void => {\n if (!para) {\n return;\n }\n out.push(renderAlignParagraph(para.align, para.segments));\n para = null;\n };\n // Route one finished fragment (text run, void tag, or image) into the open\n // alignment paragraph's CURRENT segment, or straight to the top level when no\n // alignment is active. The style stack is popped only AFTER a run's content is\n // flushed, so the alignment seen here is the one the fragment was styled with.\n const pushHtml = (html: string): void => {\n const align = lastRichTextTag(styleStack, \"align\")?.value;\n if (align === undefined) {\n closeParagraph();\n out.push(html);\n return;\n }\n if (para && para.align !== align) {\n closeParagraph();\n }\n if (!para) {\n para = { align, segments: [[]] };\n }\n para.segments[para.segments.length - 1]!.push(html);\n };\n // A hard newline inside an aligned region: end the current paragraph block and\n // start a fresh one. Ensures the para exists (a `\\n` before any run opens an\n // empty leading block, matching a leading Godot newline).\n const breakSegment = (align: string): void => {\n if (para && para.align !== align) {\n closeParagraph();\n }\n if (!para) {\n para = { align, segments: [[]] };\n }\n para.segments.push([]);\n };\n const flushBuffer = (): void => {\n if (!buffer) {\n return;\n }\n const runs: string[] = [];\n flushRichText(\n runs,\n buffer,\n styleStack,\n charCounter,\n ctx.textScale ?? false,\n );\n buffer = \"\";\n for (const run of runs) {\n pushHtml(run);\n }\n };\n for (let index = 0; index < value.length; ) {\n if (value[index] === \"[\") {\n const end = value.indexOf(\"]\", index + 1);\n const tag =\n end >= 0\n ? parseRichTextTag(value.slice(index + 1, end), ctx.customTags)\n : null;\n if (!tag) {\n buffer += value[index] ?? \"\";\n index += 1;\n continue;\n }\n flushBuffer();\n if (\"void\" in tag && tag.void) {\n if (!tag.close) {\n pushHtml(tag.html);\n }\n index = end + 1;\n } else if (\"img\" in tag && tag.img) {\n if (tag.close) {\n // [/img] is a no-op: the path was consumed when the open tag was seen.\n index = end + 1;\n } else {\n // The image path is the content up to the next \"[\" (matching Godot).\n let pathEnd = value.indexOf(\"[\", end + 1);\n if (pathEnd === -1) {\n pathEnd = value.length;\n }\n const path = value.slice(end + 1, pathEnd).trim();\n pushHtml(richTextImageHtml(path, tag.options ?? {}, ctx));\n index = pathEnd;\n }\n } else if (tag.close) {\n popRichTextStyle(styleStack, tag.type, tag.id);\n index = end + 1;\n } else {\n styleStack.push({\n type: tag.type,\n id: tag.id,\n value: tag.value,\n css: tag.css,\n effect: tag.effect,\n });\n index = end + 1;\n }\n } else {\n const ch = value[index] ?? \"\";\n // Inside an aligned region a hard newline starts a new paragraph BLOCK\n // (Godot semantics), so it is consumed as a segment break rather than left\n // in the buffer. `\\r\\n` collapses to one break. At the top level (no active\n // alignment) newlines stay in the buffer and render via `white-space:\n // pre-wrap`, exactly as before.\n const align = lastRichTextTag(styleStack, \"align\")?.value;\n if (align !== undefined && (ch === \"\\n\" || ch === \"\\r\")) {\n flushBuffer();\n breakSegment(align);\n index += ch === \"\\r\" && value[index + 1] === \"\\n\" ? 2 : 1;\n continue;\n }\n buffer += ch;\n index += 1;\n }\n }\n flushBuffer();\n closeParagraph();\n return out.join(\"\");\n}\n\n// One `<p>` per contiguous BBCode alignment region; `text-align` centers each\n// visual line. Its runs are grouped into one `.godot-rich-paragraph` BLOCK per\n// hard-newline-separated segment: a block's WRAPPED lines flow at the label width\n// (the `.godot-rich-stack` is full-width) under `--godot-rich-line-height`, and\n// consecutive blocks are separated by `--godot-rich-paragraph-spacing`. Both\n// custom properties default to `normal`/`0` (base-css), so a region with a single\n// segment and no consumer override lays out exactly like a plain wrapped block.\n// Keeps `data-godot-bbcode-align` for downstream inspection.\nfunction renderAlignParagraph(align: string, segments: string[][]): string {\n const textAlign = align === \"fill\" ? \"justify\" : align;\n const blocks = segments\n .map((runs) => `<span class=\"godot-rich-paragraph\">${runs.join(\"\")}</span>`)\n .join(\"\");\n return `<p class=\"godot-rich-align\" data-godot-bbcode-align=\"${escapeAttribute(align)}\" style=\"text-align: ${escapeAttribute(textAlign)}\">${blocks}</p>`;\n}\n\n// Memo for the layered BBCode render (module-scoped LRU, like `atlas.ts`'s data-URL memo). WHY:\n// every RichTextLabel re-parses its whole BBCode string — tag scan, style stack, per-char effect\n// spans — and then stamps the result into FOUR layers, on every render, for text that almost never\n// changes. Phone traces showed these re-parses inside a play-a-card burst.\n//\n// CORRECTNESS: the key covers every input `richTextHtml` reads — the bbcode string, `ctx.textScale`\n// and `ctx.customTags` — EXCEPT `ctx.resolveImage`, which is an opaque host callback whose answer\n// can change over time (a texture resolving later). So a string carrying an `[img…]` tag, the only\n// path that consults it, is never memoized at all.\nconst RICH_TEXT_CACHE_LIMIT = 200;\nconst richTextLayeredCache = createStringLru<string>(RICH_TEXT_CACHE_LIMIT);\n\n// Any BBCode that could parse as an `[img]`/`[/img]` tag (`parseRichTextTag` trims the brackets'\n// content and lowercases the name, so leading space and case both count). Deliberately loose —\n// over-matching only costs a memo miss.\nconst RICH_TEXT_IMG_TAG = /\\[\\s*\\/?\\s*img\\b/i;\n\n// Content signature for the custom-tag table, cached per table OBJECT so a host that rebuilds an\n// equal table each render still hits (and one that keeps a stable table pays for it once).\n// Caveat: a table mutated IN PLACE keeps its old signature — gsw's `bbcodeTags` is render options,\n// treated as immutable everywhere else too.\nconst customTagsSignatures = new WeakMap<object, string>();\n\nfunction customTagsSignature(\n customTags: RichTextRenderContext[\"customTags\"],\n): string {\n if (!customTags) {\n return \"\";\n }\n let signature = customTagsSignatures.get(customTags);\n if (signature === undefined) {\n signature = JSON.stringify(customTags);\n customTagsSignatures.set(customTags, signature);\n }\n return signature;\n}\n\n/** TEST-ONLY: clear the layered rich-text memo so a test starts from an empty cache. */\nexport function __resetRichTextLayeredCacheForTest(): void {\n richTextLayeredCache.clear();\n}\n\nexport function richTextLayeredHtml(\n value: string,\n ctx?: RichTextRenderContext,\n): string {\n // Fixed-arity fields first, the arbitrary-content bbcode last, so a `|` in the text can\n // never alias another key's fields.\n const key = RICH_TEXT_IMG_TAG.test(value)\n ? null\n : `${ctx?.textScale ? \"1\" : \"0\"}|${customTagsSignature(ctx?.customTags)}|${value}`;\n if (key !== null) {\n const hit = richTextLayeredCache.get(key);\n if (hit !== undefined) {\n return hit;\n }\n }\n const html = richTextHtml(value, ctx);\n const layered = [\n '<span class=\"godot-rich-stack\">',\n `<span class=\"godot-rich-layer godot-rich-shadow-outline\" data-godot-rich-layer=\"shadow-outline\" aria-hidden=\"true\">${html}</span>`,\n `<span class=\"godot-rich-layer godot-rich-shadow-fill\" data-godot-rich-layer=\"shadow-fill\" aria-hidden=\"true\">${html}</span>`,\n `<span class=\"godot-rich-layer godot-rich-outline\" data-godot-rich-layer=\"outline\" aria-hidden=\"true\">${html}</span>`,\n `<span class=\"godot-rich-layer godot-rich-fill\" data-godot-rich-layer=\"fill\">${html}</span>`,\n \"</span>\",\n ].join(\"\");\n if (key !== null) {\n richTextLayeredCache.set(key, layered);\n }\n return layered;\n}\n\nfunction parseRichTextTag(\n raw: string,\n customTags?: GodotHtmlRenderOptions[\"bbcodeTags\"],\n): ParsedRichTextTag | null {\n const close = raw.startsWith(\"/\");\n const body = (close ? raw.slice(1) : raw).trim();\n const match = body.match(/^([a-zA-Z_][\\w-]*)(?:[=\\s]+([\\s\\S]*))?$/);\n if (!match) {\n return null;\n }\n const name = (match[1] ?? \"\").toLowerCase();\n const rest = match[2]?.trim();\n\n // Simple paired formatting tags. Close tags only need to match on type+id.\n if (SIMPLE_RICH_TEXT_TAGS[name]) {\n return { close, type: SIMPLE_RICH_TEXT_TAGS[name], id: name };\n }\n\n // Paragraph alignment, both shorthand and `[p align=...]`.\n if (\n name === \"center\" ||\n name === \"left\" ||\n name === \"right\" ||\n name === \"fill\"\n ) {\n return { close, type: \"align\", id: name, value: name };\n }\n if (name === \"p\") {\n const align = rest?.match(/align\\s*=\\s*([a-zA-Z]+)/)?.[1]?.toLowerCase();\n return {\n close,\n type: \"align\",\n id: \"p\",\n value: close ? undefined : (align ?? \"left\"),\n };\n }\n\n // Color family. fgcolor is an alias of color; bgcolor paints a background.\n if (name === \"color\" || name === \"fgcolor\" || name === \"outline_color\") {\n return { close, type: \"color\", id: name, value: close ? undefined : rest };\n }\n if (name === \"bgcolor\") {\n return {\n close,\n type: \"bgcolor\",\n id: name,\n value: close ? undefined : rest,\n };\n }\n\n if (name === \"font_size\") {\n return {\n close,\n type: \"font_size\",\n id: name,\n value: close ? undefined : rest,\n };\n }\n\n if (name === \"url\") {\n return { close, type: \"url\", id: name, value: close ? undefined : rest };\n }\n\n // Recognized-but-structural tags: consumed so the brackets never leak as\n // literal text, but not visually modeled in this pass.\n if (\n name === \"font\" ||\n name === \"outline_size\" ||\n name === \"lang\" ||\n name === \"hint\"\n ) {\n return { close, type: \"structural\", id: name };\n }\n\n // Inline images. The path is the tag content (handled by the main loop); the\n // closing tag is a no-op that just keeps the brackets from leaking as text.\n if (name === \"img\") {\n return close\n ? { close: true, img: true }\n : {\n close: false,\n img: true,\n options: parseImgOptions(body.slice(name.length)),\n };\n }\n\n // Void tags (no closing form).\n if (!close && name === \"br\") {\n return { close, void: true, html: \"<br>\" };\n }\n if (!close && name === \"hr\") {\n return { close, void: true, html: '<hr class=\"godot-rich-hr\">' };\n }\n\n // Built-in official effects.\n if (GODOT_BBCODE_BUILT_IN_EFFECTS[name]) {\n const spec = GODOT_BBCODE_BUILT_IN_EFFECTS[name];\n return {\n close,\n type: \"effect\",\n id: name,\n effect: { name, perChar: spec.perChar, perWord: spec.perWord },\n };\n }\n\n // Externally-fed custom tags (e.g. Slay the Spire 2's `red`, `thinky_dots`).\n const descriptor = customTags?.[name] ?? customTags?.[match[1] ?? \"\"];\n if (descriptor) {\n switch (descriptor.kind) {\n case \"color\":\n return {\n close,\n type: \"color\",\n id: name,\n value: close ? undefined : descriptor.value,\n };\n case \"style\":\n return {\n close,\n type: \"style\",\n id: name,\n css: close ? undefined : descriptor.css,\n };\n case \"effect\":\n return {\n close,\n type: \"effect\",\n id: name,\n effect: {\n name,\n perChar: Boolean(descriptor.perChar),\n perWord: Boolean(descriptor.perWord),\n className: descriptor.className,\n },\n };\n }\n }\n\n return null;\n}\n\n/**\n * Classify one BBCode tag name with the same parser used by rich-text output.\n *\n * The return is `undefined` for unknown tags. Custom descriptors are accepted\n * so callers can classify the exact grammar passed to `richTextLayeredHtml`.\n */\nexport function godotBbcodeTagKind(\n name: string,\n customTags?: GodotHtmlRenderOptions[\"bbcodeTags\"],\n): GodotBbcodeTagKind | undefined {\n const tag = parseRichTextTag(name, customTags);\n if (!tag) return undefined;\n if (\"img\" in tag && tag.img) return \"image\";\n if (\"void\" in tag && tag.void) return \"void\";\n return tag.type;\n}\n\n// Parse the part of an `[img ...]` tag after the name: a leading `=VALUE`\n// (dimensions `N`/`NxM` or vertical alignment) plus space-separated options.\nfunction parseImgOptions(afterName: string): RichTextImgOptions {\n const options: RichTextImgOptions = {};\n let rest = afterName;\n const valueMatch = rest.match(/^=\\s*([^\\s]+)/);\n if (valueMatch) {\n applyImgValue(options, valueMatch[1] ?? \"\");\n rest = rest.slice(valueMatch[0].length);\n }\n const optionRe = /([a-zA-Z_]+)\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s]+)/g;\n for (let match = optionRe.exec(rest); match; match = optionRe.exec(rest)) {\n applyImgOption(\n options,\n (match[1] ?? \"\").toLowerCase(),\n unquote(match[2] ?? \"\"),\n );\n }\n return options;\n}\n\nfunction applyImgValue(options: RichTextImgOptions, value: string): void {\n const valign = imgValign((value.split(\",\")[0] ?? \"\").toLowerCase());\n if (valign) {\n options.valign = valign;\n return;\n }\n const sep = value.indexOf(\"x\");\n if (sep === -1) {\n const width = Number.parseInt(value, 10);\n if (Number.isFinite(width) && width > 0) {\n options.width = width;\n }\n return;\n }\n const width = Number.parseInt(value.slice(0, sep), 10);\n const height = Number.parseInt(value.slice(sep + 1), 10);\n if (Number.isFinite(width) && width > 0) {\n options.width = width;\n }\n if (Number.isFinite(height) && height > 0) {\n options.height = height;\n }\n}\n\nfunction applyImgOption(\n options: RichTextImgOptions,\n key: string,\n value: string,\n): void {\n switch (key) {\n case \"width\":\n case \"height\": {\n // Percent sizing is out of scope for this pass.\n if (value.endsWith(\"%\")) {\n return;\n }\n const size = Number.parseInt(value, 10);\n if (Number.isFinite(size) && size > 0) {\n options[key] = size;\n }\n return;\n }\n case \"region\": {\n const parts = value.split(\",\").map((part) => Number.parseFloat(part));\n if (parts.length === 4 && parts.every((part) => Number.isFinite(part))) {\n options.region = {\n x: parts[0]!,\n y: parts[1]!,\n width: parts[2]!,\n height: parts[3]!,\n };\n }\n return;\n }\n case \"alt\":\n options.alt = value;\n return;\n }\n}\n\nfunction imgValign(token: string): RichTextImgOptions[\"valign\"] | undefined {\n if (token === \"top\" || token === \"t\") {\n return \"top\";\n }\n if (token === \"center\" || token === \"c\") {\n return \"middle\";\n }\n if (token === \"bottom\" || token === \"b\") {\n return \"bottom\";\n }\n return undefined;\n}\n\nfunction unquote(value: string): string {\n return value.length >= 2 && /^[\"']/.test(value) && value.endsWith(value[0]!)\n ? value.slice(1, -1)\n : value;\n}\n\n// Godot's default `[img]` alignment is InlineAlignment.Center, which centers the\n// image on the text line-box midpoint — ~`(ascent - descent) / 2` above the\n// baseline. CSS `vertical-align: middle` instead centers on the x-height midpoint\n// (`x-height / 2` above the baseline), which sits lower, so inline icons (energy\n// orbs, etc.) render below where the game draws them. For the default-centered\n// case, nudge the image up by the font-metric delta so it matches Godot. Measured\n// against the game UI font (kreon): ascent 0.974em, descent 0.286em, x-height\n// 0.500em -> delta = (0.974 - 0.286)/2 - 0.500/2 ≈ 0.094em. Applied as a\n// layout-neutral relative offset (no reflow); the `em` tracks the run's (scaled)\n// font size. Explicit `[img=top]` / `[img=bottom]` keep their own alignment.\nconst RICH_IMG_CENTER_NUDGE_EM = 0.094;\nfunction applyCenterValignNudge(\n style: Record<string, string>,\n valign: NonNullable<RichTextImgOptions[\"valign\"]>,\n): void {\n if (valign !== \"middle\") {\n return;\n }\n style.position = \"relative\";\n style.top = `-${RICH_IMG_CENTER_NUDGE_EM}em`;\n}\n\nfunction richTextImageHtml(\n path: string,\n options: RichTextImgOptions,\n ctx: RichTextRenderContext,\n): string {\n const resolved = ctx.resolveImage?.(path);\n const url = resolved?.url;\n const region = options.region ?? resolved?.region;\n const valign = options.valign ?? \"middle\";\n const attributes = [\n `data-godot-bbcode-img=\"${escapeAttribute(path)}\"`,\n `data-godot-bbcode-img-valign=\"${valign}\"`,\n ];\n const resourcePath = resolved?.path ?? path;\n if (resourcePath) {\n attributes.push(\n `data-godot-resource-path=\"${escapeAttribute(resourcePath)}\"`,\n );\n }\n if (options.width !== undefined) {\n attributes.push(`data-godot-bbcode-img-width=\"${options.width}\"`);\n }\n if (options.height !== undefined) {\n attributes.push(`data-godot-bbcode-img-height=\"${options.height}\"`);\n }\n if (region) {\n attributes.push(\n `data-godot-bbcode-img-region=\"${region.x},${region.y},${region.width},${region.height}\"`,\n );\n }\n\n // No resolvable URL: keep a placeholder so the path is consumed (not leaked as\n // text), mirroring Godot dropping the image when the texture fails to load.\n if (!url) {\n return `<span class=\"godot-rich-img\" ${attributes.join(\" \")} style=\"vertical-align: ${valign}\"></span>`;\n }\n\n if (region) {\n return richTextImageRegionHtml(\n url,\n region,\n options,\n resolved,\n valign,\n attributes,\n );\n }\n\n const style: Record<string, string> = { \"vertical-align\": valign };\n applyCenterValignNudge(style, valign);\n if (options.width !== undefined) {\n style.width = `${options.width}px`;\n }\n if (options.height !== undefined) {\n style.height = `${options.height}px`;\n }\n const altAttr = ` alt=\"${escapeAttribute(options.alt ?? \"\")}\"`;\n return `<img class=\"godot-rich-img\" ${attributes.join(\" \")} src=\"${escapeAttribute(url)}\"${altAttr} style=\"${escapeAttribute(styleAttribute(style))}\">`;\n}\n\n// Region crops render as an inline-block span with a positioned background,\n// reusing the same scale/offset math as TextureRect regions in textures.ts.\nfunction richTextImageRegionHtml(\n url: string,\n region: { x: number; y: number; width: number; height: number },\n options: RichTextImgOptions,\n resolved: GodotResolvedResource | undefined,\n valign: NonNullable<RichTextImgOptions[\"valign\"]>,\n attributes: string[],\n): string {\n const boxWidth = options.width ?? region.width;\n const boxHeight = options.height ?? region.height;\n const textureSize = resolved?.atlas?.size ?? resolved?.size;\n const style: Record<string, string> = {\n display: \"inline-block\",\n \"vertical-align\": valign,\n width: `${round(boxWidth)}px`,\n height: `${round(boxHeight)}px`,\n \"background-image\": `url(\"${cssUrl(url)}\")`,\n \"background-repeat\": \"no-repeat\",\n };\n applyCenterValignNudge(style, valign);\n if (\n textureSize &&\n textureSize.width > 0 &&\n textureSize.height > 0 &&\n region.width > 0 &&\n region.height > 0\n ) {\n const scaleX = boxWidth / region.width;\n const scaleY = boxHeight / region.height;\n style[\"background-position\"] =\n `${round(-region.x * scaleX)}px ${round(-region.y * scaleY)}px`;\n style[\"background-size\"] =\n `${round(textureSize.width * scaleX)}px ${round(textureSize.height * scaleY)}px`;\n } else {\n style[\"background-position\"] =\n `${round(-region.x)}px ${round(-region.y)}px`;\n style[\"background-size\"] = \"auto\";\n }\n return `<span class=\"godot-rich-img\" ${attributes.join(\" \")} style=\"${escapeAttribute(styleAttribute(style))}\"></span>`;\n}\n\nfunction flushRichText(\n result: string[],\n text: string,\n styleStack: RichTextTag[],\n charCounter: { value: number },\n scaleText: boolean,\n): void {\n if (!text) {\n return;\n }\n const style = currentRichTextStyle(styleStack);\n let base = style.effect?.perChar\n ? richTextCharWordHtml(text, charCounter)\n : escapeHtml(text);\n if (style.code) {\n base = `<code class=\"godot-rich-code\">${base}</code>`;\n }\n let html: string;\n if (style.bold && style.italic) {\n html = `<strong class=\"godot-rich-bold\"><em class=\"godot-rich-italic\">${base}</em></strong>`;\n } else if (style.bold) {\n html = `<strong class=\"godot-rich-bold\">${base}</strong>`;\n } else if (style.italic) {\n html = `<em class=\"godot-rich-italic\">${base}</em>`;\n } else {\n html = `<span class=\"godot-rich-normal\">${base}</span>`;\n }\n if (style.underline) {\n html = `<span class=\"godot-rich-underline\" style=\"text-decoration: underline\">${html}</span>`;\n }\n if (style.strike) {\n html = `<span class=\"godot-rich-strike\" style=\"text-decoration: line-through\">${html}</span>`;\n }\n if (style.fontSize) {\n const numericSize = Number.parseFloat(style.fontSize);\n const fontSizeCss =\n scaleText && Number.isFinite(numericSize)\n ? textScaleLength(numericSize, true)\n : `${escapeAttribute(style.fontSize)}px`;\n html = `<span class=\"godot-rich-font-size\" data-godot-bbcode-font-size=\"${escapeAttribute(style.fontSize)}\" style=\"font-size: ${fontSizeCss}\">${html}</span>`;\n }\n if (style.styleCss) {\n html = `<span class=\"godot-rich-style\" style=\"${escapeAttribute(inlineCssText(style.styleCss))}\">${html}</span>`;\n }\n if (style.color) {\n html = `<span class=\"godot-rich-color\" data-godot-bbcode-color=\"${escapeAttribute(style.color)}\" style=\"color: ${escapeAttribute(style.color)}\">${html}</span>`;\n }\n if (style.bgcolor) {\n html = `<span class=\"godot-rich-bgcolor\" data-godot-bbcode-bgcolor=\"${escapeAttribute(style.bgcolor)}\" style=\"background-color: ${escapeAttribute(style.bgcolor)}\">${html}</span>`;\n }\n if (style.url) {\n html = `<span class=\"godot-rich-url\" data-godot-bbcode-url=\"${escapeAttribute(style.url)}\" style=\"text-decoration: underline\">${html}</span>`;\n }\n if (style.effect) {\n const effect = style.effect;\n const className = [\n \"godot-rich-effect\",\n `godot-rich-effect-${safeClassSegment(effect.name)}`,\n effect.className,\n ]\n .filter(Boolean)\n .join(\" \");\n html = `<span class=\"${escapeAttribute(className)}\" data-godot-bbcode-effect=\"${escapeAttribute(effect.name)}\">${html}</span>`;\n }\n // Alignment is applied at the paragraph level (richTextHtml/renderAlignParagraph),\n // not per run, so a `[center]` region wraps as one block instead of forcing each\n // styled run onto its own line.\n if (style.indent) {\n html = `<span class=\"godot-rich-indent\" style=\"display: block; padding-left: 2em\">${html}</span>`;\n }\n result.push(html);\n}\n\n// Split a run into per-word and per-char spans (mirroring the Godot/STS2 web\n// structure) so effects can animate individual letters via the `--i` index.\nfunction richTextCharWordHtml(\n text: string,\n charCounter: { value: number },\n): string {\n const parts = text.match(/\\s+|\\S+/g) ?? [];\n const out: string[] = [];\n for (const part of parts) {\n if (/^\\s+$/.test(part)) {\n out.push(escapeHtml(part));\n continue;\n }\n const chars: string[] = [];\n for (const char of part) {\n chars.push(\n `<span class=\"godot-rich-char\" style=\"--i: ${charCounter.value}\">${escapeHtml(char)}</span>`,\n );\n charCounter.value += 1;\n }\n out.push(`<span class=\"godot-rich-word\">${chars.join(\"\")}</span>`);\n }\n return out.join(\"\");\n}\n\nfunction inlineCssText(css: Record<string, string>): string {\n return Object.entries(css)\n .map(([property, value]) => `${property}: ${value}`)\n .join(\"; \");\n}\n\nfunction currentRichTextStyle(styleStack: RichTextTag[]): {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strike: boolean;\n code: boolean;\n indent: boolean;\n align?: string;\n color?: string;\n bgcolor?: string;\n url?: string;\n fontSize?: string;\n styleCss?: Record<string, string>;\n effect?: RichTextEffect;\n} {\n return {\n bold: styleStack.some((tag) => tag.type === \"bold\"),\n italic: styleStack.some((tag) => tag.type === \"italic\"),\n underline: styleStack.some((tag) => tag.type === \"underline\"),\n strike: styleStack.some((tag) => tag.type === \"strike\"),\n code: styleStack.some((tag) => tag.type === \"code\"),\n indent: styleStack.some((tag) => tag.type === \"indent\"),\n align: lastRichTextTag(styleStack, \"align\")?.value,\n color: lastRichTextTag(styleStack, \"color\")?.value,\n bgcolor: lastRichTextTag(styleStack, \"bgcolor\")?.value,\n url: lastRichTextTag(styleStack, \"url\")?.value,\n fontSize: lastRichTextTag(styleStack, \"font_size\")?.value,\n styleCss: lastRichTextTag(styleStack, \"style\")?.css,\n effect: lastRichTextTag(styleStack, \"effect\")?.effect,\n };\n}\n\nfunction lastRichTextTag(\n styleStack: RichTextTag[],\n type: RichTextTag[\"type\"],\n): RichTextTag | undefined {\n for (let index = styleStack.length - 1; index >= 0; index -= 1) {\n const tag = styleStack[index];\n if (tag?.type === type && tag.value !== undefined) {\n return tag;\n }\n if (tag?.type === type && (type === \"style\" || type === \"effect\")) {\n return tag;\n }\n }\n return undefined;\n}\n\nfunction popRichTextStyle(\n styleStack: RichTextTag[],\n type: RichTextTag[\"type\"],\n id: string,\n): void {\n for (let index = styleStack.length - 1; index >= 0; index -= 1) {\n const tag = styleStack[index];\n if (tag?.type === type && tag.id === id) {\n styleStack.splice(index, 1);\n return;\n }\n }\n for (let index = styleStack.length - 1; index >= 0; index -= 1) {\n if (styleStack[index]?.type === type) {\n styleStack.splice(index, 1);\n return;\n }\n }\n}\n","import {\n asBoolean,\n asNumber,\n asRect2,\n asResourceRef,\n asString,\n asVector2,\n type GodotNode,\n type GodotResource,\n type GodotResourceRefValue,\n type GodotVariant,\n} from \"@godot-scene-web/core\";\nimport { atlasTextureDataUrl, atlasTextureMetrics } from \"./atlas\";\nimport {\n type ColorMatrix,\n clamp,\n colorMatrixDiagonalCss,\n colorMatrixFeValues,\n colorMatrixIsDiagonal,\n composeColorMatrix,\n cssUrl,\n escapeAttribute,\n isEmbeddedAssetUrl,\n modulateTint,\n round,\n styleAttribute,\n} from \"./css-values\";\nimport { createStringLru } from \"./lru\";\nimport {\n isHiddenRawShaderFallbackMaterial,\n isWebglShaderMaterialNode,\n materialColorMatrix,\n} from \"./material\";\nimport { imageResource, normalizeResource } from \"./resources\";\nimport type { GodotHtmlRenderOptions, GodotResolvedResource } from \"./types\";\n\n// The shared per-render `<filter>` table is keyed by each filter's inner SVG\n// markup (so a tint and a glow with identical markup dedupe to one def) and maps\n// to its emitted id. `model.ts` serializes it to `{ id, markup }` and every\n// renderer emits the `<filter>` once (see `tintFilterDefsMarkup`).\nfunction registerFilterMarkup(\n tintFilters: Map<string, string>,\n markup: string,\n idPrefix: string,\n): string {\n let id = tintFilters.get(markup);\n if (id === undefined) {\n id = `${idPrefix}${tintFilters.size}`;\n tintFilters.set(markup, id);\n }\n return id;\n}\n\nfunction registerTintFilter(\n tintFilters: Map<string, string> | undefined,\n tint: ColorMatrix | undefined,\n idPrefix: string,\n): string | undefined {\n if (!tintFilters || !tint) {\n return undefined;\n }\n return registerFilterMarkup(\n tintFilters,\n `<feColorMatrix type=\"matrix\" values=\"${colorMatrixFeValues(tint)}\"/>`,\n idPrefix,\n );\n}\n\n/**\n * Tint a node's self layer via a CSS `filter: url(#id)` color matrix,\n * registering the matrix in the shared per-render filter table so its\n * `<filter>` def is emitted once. Used when the texture URL is external (see\n * `isEmbeddedAssetUrl`).\n */\nfunction applyTintFilterStyle(\n style: Record<string, string>,\n attributes: Record<string, string>,\n tintFilters: Map<string, string> | undefined,\n tint: ColorMatrix | undefined,\n idPrefix: string,\n): boolean {\n const id = registerTintFilter(tintFilters, tint, idPrefix);\n if (id === undefined || !tint) {\n return false;\n }\n const ref = `url(#${id})`;\n style.filter = style.filter ? `${style.filter} ${ref}` : ref;\n attributes[\"data-godot-texture-tint\"] = \"css-filter\";\n // A CSS filter forces an axis-aligned raster of the layer that a ROTATED\n // ancestor then resamples (visible blur on rotated combat cards). Expose the\n // matrix + filter id so a post-mount pass (`bakeExternalTextureTints`) can\n // bake the tint into the bitmap itself and drop the filter boundary.\n attributes[\"data-godot-tint-filter-id\"] = id;\n attributes[\"data-godot-tint-matrix\"] = tint.rows\n .flat()\n .map((value) => String(value))\n .join(\" \");\n return true;\n}\n\nexport function assignTextureStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n ninePatch: boolean,\n // The node's *outer* element style/attributes. A `clip_children` nine-patch\n // masks the node's CHILDREN, which are siblings of the self-layer in the outer\n // element — so the alpha mask must be applied there, not on the self-layer\n // (`style`), which paints nothing for CLIP_CHILDREN_ONLY and never contains the\n // children. Defaults to the self-layer when a caller does not split the two.\n outerStyle: Record<string, string> = style,\n outerAttributes: Record<string, string> = attributes,\n // Shared per-render table of color-matrix `<filter>` defs, keyed by their\n // feColorMatrix values, used to tint external textures via `filter: url(#id)`.\n tintFilters?: Map<string, string>,\n nodePath?: string,\n): string | undefined {\n const texture = asResourceRef(props.texture);\n if (!texture) {\n return undefined;\n }\n const resource = normalizeResource(\n options.resolveResource?.(texture, source),\n );\n const image = imageResource(resource, options, source);\n if (!image.url) {\n return undefined;\n }\n if (image.path) {\n attributes[\"data-godot-resource-path\"] = image.path;\n }\n // For a WebGL-eligible shader node, also expose the RAW (untinted) texture url\n // so the runtime samples the source the shader expects, regardless of the CSS\n // tint/SVG glow OR nine-patch border-image on the self-layer below (which stays\n // the fallback when the shader can't run). Needed even for nodes with no\n // background-image (e.g. a NinePatchRect fill), where the runtime relies on this\n // attribute for `COLOR.a`. Harmless on non-activated shader nodes (the\n // runtime only acts on `[data-godot-shader-webgl]`).\n if (isWebglShaderMaterialNode(props, source, options, nodePath)) {\n attributes[\"data-godot-shader-texture-url\"] = image.url;\n }\n attributes[\"data-godot-resource-kind\"] = ninePatch\n ? \"NinePatchRect\"\n : \"TextureRect\";\n assignTextureMetadata(style, attributes, props);\n // `COLOR *= modulate_color` runs after the shader's color transform, so the\n // modulate diagonal is the OUTER factor: M = diag(modulate) · M_material.\n const textureTint = composeColorMatrix(\n modulateTint(props),\n materialColorMatrix(attributes, props, source, options),\n );\n const tintIdPrefix = options.tintFilterIdPrefix ?? \"godot-tint-\";\n const externalImage = !isEmbeddedAssetUrl(image.url);\n\n if (ninePatch) {\n const margins = patchMargins(props);\n attributes[\"data-godot-patch-margins\"] =\n `${margins[3]},${margins[0]},${margins[1]},${margins[2]}`;\n const axisHorizontal = asNumber(props.axis_stretch_horizontal);\n const axisVertical = asNumber(props.axis_stretch_vertical);\n if (axisHorizontal !== undefined) {\n attributes[\"data-godot-axis-stretch-horizontal\"] = String(axisHorizontal);\n }\n if (axisVertical !== undefined) {\n attributes[\"data-godot-axis-stretch-vertical\"] = String(axisVertical);\n }\n // A CLIP_CHILDREN_ONLY node paints nothing and only clips its children to its\n // texture's alpha shape. The embedded path bakes that shape into an `<image>`\n // SVG mask, which a sandboxed `data:` URI can't load for an EXTERNAL URL — so\n // for external textures clip with a native nine-patch mask (`mask-border` /\n // `-webkit-mask-box-image`) referencing the URL directly instead.\n if (asNumber(props.clip_children) === 1) {\n if (externalImage) {\n assignNinePatchBorderMaskStyles(\n outerStyle,\n outerAttributes,\n image,\n margins,\n axisHorizontal,\n axisVertical,\n );\n } else {\n assignNinePatchClipMaskStyles(\n outerStyle,\n outerAttributes,\n style,\n props,\n image,\n margins,\n axisHorizontal,\n axisVertical,\n );\n }\n return undefined;\n }\n const hasAxisStretch =\n (axisHorizontal !== undefined && axisHorizontal !== 0) ||\n (axisVertical !== undefined && axisVertical !== 0);\n // Per-slice spans paint each slice through an `<image>` SVG, so they only\n // work for embedded URLs. External tiled patches fall to the border-image\n // path, whose `border-image-repeat` (round/repeat) tiles without any SVG.\n const html =\n hasAxisStretch && !externalImage\n ? ninePatchHtml(\n style,\n props,\n image,\n margins,\n axisHorizontal,\n axisVertical,\n textureTint,\n )\n : undefined;\n if (html) {\n if (textureTint) {\n attributes[\"data-godot-texture-tint\"] = \"svg-color-matrix\";\n }\n style.overflow = \"hidden\";\n return html;\n }\n const tintViaFilter = externalImage && Boolean(textureTint);\n const borderSource = tintViaFilter\n ? (image.url ?? \"\")\n : ninePatchBorderImageUrl(image, textureTint, attributes);\n // `border-image-slice` drops the `fill` center when two opposing slices meet\n // or overlap in the SOURCE (margin_left + margin_right >= texture width — e.g.\n // event_button.png is 284px wide with 192px L/R margins), leaving the button\n // with caps but no stretched middle. Godot instead stretches the degenerate\n // center column, so clamp the SOURCE slices to keep a >=1px center for `fill`\n // while leaving the authored margins as the destination border geometry.\n const sliceMargins = clampNinePatchSlices(\n margins,\n image.atlas?.size ?? image.size,\n );\n style[\"border-style\"] = \"solid\";\n style[\"border-width\"] = `${margins.join(\"px \")}px`;\n style[\"border-image-source\"] = `url(\"${cssUrl(borderSource)}\")`;\n style[\"border-image-slice\"] = `${sliceMargins.join(\" \")} fill`;\n style[\"border-image-repeat\"] =\n `${axisStretchRepeat(axisHorizontal)} ${axisStretchRepeat(axisVertical)}`;\n if (sliceMargins !== margins) {\n attributes[\"data-godot-patch-slice-clamped\"] = sliceMargins.join(\",\");\n }\n // External textures have no intrinsic size at string-render time, so the\n // `clampNinePatchSlices` above is a no-op — and `border-image-slice ... fill` then\n // DROPS the center for a texture whose opposing patch margins meet/overlap in the\n // source (caps render, the stretched middle does not). Mark it so a post-mount pass\n // (`clampExternalNinePatchSlices`) re-clamps once the image's natural size is known.\n // Value is the raw [top,right,bottom,left] margins.\n const sourceSize = image.atlas?.size ?? image.size;\n if (externalImage && (!sourceSize?.width || !sourceSize.height)) {\n attributes[\"data-godot-nine-patch-unclamped\"] = margins.join(\",\");\n }\n // For a WebGL-eligible nine-patch shader node, publish the fill nine-patch as a\n // ready-to-use `mask-box-image` (RAW texture alpha = the SHAPE, incl. the slanted\n // end caps). The runtime clips its full-node canvas to this so the live shader\n // fills the WHOLE segment — diagonal caps included — instead of the caps falling\n // back to a static border-image. Read from this STABLE attribute, not the live\n // border-image (which the runtime clears, so a re-read after DOM reuse sees none).\n if (\n image.url &&\n isWebglShaderMaterialNode(props, source, options, nodePath)\n ) {\n attributes[\"data-godot-shader-fill-mask\"] =\n `url(\"${cssUrl(image.url)}\") ${sliceMargins.join(\" \")} fill / ` +\n `${margins.join(\"px \")}px / 0 ` +\n `${axisStretchRepeat(axisHorizontal)} ${axisStretchRepeat(axisVertical)}`;\n }\n if (tintViaFilter) {\n applyTintFilterStyle(\n style,\n attributes,\n tintFilters,\n textureTint,\n tintIdPrefix,\n );\n }\n return undefined;\n }\n\n if (asNumber(props.clip_children) === 1) {\n assignTextureRectClipMaskStyles(outerStyle, outerAttributes, image, props);\n return undefined;\n }\n\n style[\"background-image\"] = `url(\"${cssUrl(image.url)}\")`;\n style[\"background-repeat\"] = textureRepeat(\n asNumber(props.texture_repeat),\n asNumber(props.stretch_mode),\n );\n const region =\n image.region ?? (ninePatch ? asRect2(props.region_rect) : undefined);\n if (region) {\n // AtlasTexture sprites are pre-cropped to standalone images in\n // `imageResource`, so `image.region` only survives when the atlas size was\n // unknown (raw fallback) or for a NinePatchRect `region_rect`.\n attributes[\n image.region ? \"data-godot-atlas-region\" : \"data-godot-region-rect\"\n ] = `${region.x},${region.y},${region.width},${region.height}`;\n const margin = image.region ? image.margin : undefined;\n assignRegionBackgroundStyles(\n style,\n region,\n image.atlas?.size,\n asNumber(props.stretch_mode),\n margin,\n );\n } else {\n style[\"background-size\"] = stretchModeBackgroundSize(\n asNumber(props.stretch_mode),\n );\n style[\"background-position\"] = \"center\";\n }\n if (isHiddenRawShaderFallbackMaterial(props, source, options, nodePath)) {\n delete style[\"background-image\"];\n delete style.filter;\n delete attributes[\"data-godot-texture-tint\"];\n attributes[\"data-godot-shader-raw-fallback\"] = \"hidden\";\n return undefined;\n }\n // Consumer-supplied static-fallback filter (e.g. an animated glow approximating an\n // un-runnable shader). The consumer owns the SVG primitives + any baked colors; we\n // register the inner markup and reference it. See `shaderFallbackFiltersByPath`.\n const fallbackFilterMarkup = nodePath\n ? options.shaderFallbackFiltersByPath?.[nodePath]\n : undefined;\n if (fallbackFilterMarkup && tintFilters) {\n const filterId = registerFilterMarkup(\n tintFilters,\n fallbackFilterMarkup,\n tintIdPrefix,\n );\n const ref = `url(#${filterId})`;\n style.filter = style.filter ? `${style.filter} ${ref}` : ref;\n attributes[\"data-godot-texture-tint\"] = \"shader-fallback-filter\";\n return undefined;\n }\n assignTextureTintStyles(\n style,\n attributes,\n image,\n textureTint,\n tintFilters,\n tintIdPrefix,\n );\n return undefined;\n}\n\nfunction assignTextureRectClipMaskStyles(\n outerStyle: Record<string, string>,\n outerAttributes: Record<string, string>,\n image: GodotResolvedResource,\n props: Record<string, GodotVariant>,\n): void {\n if (!image.url) return;\n const url = `url(\"${cssUrl(image.url)}\")`;\n outerStyle.overflow = \"hidden\";\n outerStyle[\"-webkit-mask-image\"] = url;\n outerStyle[\"mask-image\"] = url;\n outerStyle[\"-webkit-mask-repeat\"] = \"no-repeat\";\n outerStyle[\"mask-repeat\"] = \"no-repeat\";\n outerStyle[\"-webkit-mask-position\"] = \"center\";\n outerStyle[\"mask-position\"] = \"center\";\n const size = stretchModeBackgroundSize(asNumber(props.stretch_mode));\n outerStyle[\"-webkit-mask-size\"] = size;\n outerStyle[\"mask-size\"] = size;\n outerStyle[\"mask-mode\"] = \"alpha\";\n outerAttributes[\"data-godot-clip-mask\"] = \"texture-alpha\";\n}\n\nfunction ninePatchBorderImageUrl(\n image: GodotResolvedResource,\n tint: ColorMatrix | undefined,\n attributes: Record<string, string>,\n): string {\n if (!tint || !image.url) {\n return image.url ?? \"\";\n }\n const textureSize = image.atlas?.size ?? image.size;\n if (!textureSize?.width || !textureSize.height) {\n attributes[\"data-godot-texture-tint\"] = \"missing-image-size\";\n return image.url;\n }\n attributes[\"data-godot-texture-tint\"] = \"svg-color-matrix\";\n return svgImageDataUrl(\n image.url,\n textureSize,\n { x: 0, y: 0, width: textureSize.width, height: textureSize.height },\n tint,\n );\n}\n\n// Clamp opposing nine-patch SOURCE slices [top, right, bottom, left] so they fit\n// inside the texture with a >=1px center for the `border-image-slice` fill region.\n// CSS collapses the fill center when a pair meets/overlaps (a + b >= dim); Godot\n// keeps a (degenerate) stretched center instead, so scale an overflowing pair\n// down proportionally. Returns the original tuple unchanged when nothing overflows\n// or the texture size is unknown (preserving the prior border-image behavior).\nexport function clampNinePatchSlices(\n margins: [number, number, number, number],\n size: { width: number; height: number } | undefined,\n): [number, number, number, number] {\n if (!size?.width || !size.height) {\n return margins;\n }\n const [top, right, bottom, left] = margins;\n const [clampedTop, clampedBottom] = clampSlicePair(top, bottom, size.height);\n const [clampedLeft, clampedRight] = clampSlicePair(left, right, size.width);\n if (\n clampedTop === top &&\n clampedRight === right &&\n clampedBottom === bottom &&\n clampedLeft === left\n ) {\n return margins;\n }\n return [clampedTop, clampedRight, clampedBottom, clampedLeft];\n}\n\nfunction clampSlicePair(a: number, b: number, dim: number): [number, number] {\n const total = a + b;\n const maxTotal = dim - 1; // leave >=1px center for the `fill` region\n if (total <= maxTotal || total <= 0) {\n return [a, b];\n }\n const scale = maxTotal / total;\n return [Math.floor(a * scale), Math.floor(b * scale)];\n}\n\nfunction assignNinePatchClipMaskStyles(\n // The element that hosts the node's children (the outer element); the alpha\n // mask is written here so it actually clips them.\n maskStyle: Record<string, string>,\n attributes: Record<string, string>,\n // The self-layer style, used only to read the node's box dimensions (it shares\n // the node rect with the outer element).\n boxStyle: Record<string, string>,\n props: Record<string, GodotVariant>,\n image: GodotResolvedResource,\n margins: [number, number, number, number],\n axisHorizontal: number | undefined,\n axisVertical: number | undefined,\n): void {\n maskStyle.overflow = \"hidden\";\n const maskUrl = ninePatchMaskDataUrl(\n boxStyle,\n props,\n image,\n margins,\n axisHorizontal,\n axisVertical,\n );\n if (!maskUrl) {\n attributes[\"data-godot-clip-mask\"] = \"missing-image-size\";\n return;\n }\n const imageValue = `url(\"${cssUrl(maskUrl)}\")`;\n attributes[\"data-godot-clip-mask\"] = \"nine-patch-alpha\";\n maskStyle[\"mask-image\"] = imageValue;\n maskStyle[\"mask-size\"] = \"100% 100%\";\n maskStyle[\"mask-repeat\"] = \"no-repeat\";\n maskStyle[\"mask-position\"] = \"0 0\";\n maskStyle[\"mask-mode\"] = \"alpha\";\n maskStyle[\"-webkit-mask-image\"] = imageValue;\n maskStyle[\"-webkit-mask-size\"] = maskStyle[\"mask-size\"];\n maskStyle[\"-webkit-mask-repeat\"] = maskStyle[\"mask-repeat\"];\n maskStyle[\"-webkit-mask-position\"] = maskStyle[\"mask-position\"];\n maskStyle[\"-webkit-mask-mode\"] = maskStyle[\"mask-mode\"];\n}\n\n// External-texture analogue of `assignNinePatchClipMaskStyles`: a `data:` SVG mask\n// can't load an external `<image href>` (sandbox), so clip the children with a NATIVE\n// nine-patch mask (`mask-border` / `-webkit-mask-box-image`) that references the URL\n// directly. Mirrors the border-image slice/width geometry (so the rounded capsule is\n// preserved), but masks — clips children, paints nothing — instead of drawing the\n// texture, so a CLIP_CHILDREN_ONLY node (e.g. the health-bar capsule `Mask`) clips its\n// fill to the rounded shape without rendering the white capsule itself.\nfunction assignNinePatchBorderMaskStyles(\n // The child-hosting (outer) element style/attributes — the mask must live here to\n // clip the children, which are siblings of the (empty) self-layer.\n maskStyle: Record<string, string>,\n attributes: Record<string, string>,\n image: GodotResolvedResource,\n margins: [number, number, number, number],\n axisHorizontal: number | undefined,\n axisVertical: number | undefined,\n): void {\n if (!image.url) {\n attributes[\"data-godot-clip-mask\"] = \"missing-image-size\";\n return;\n }\n maskStyle.overflow = \"hidden\";\n // Clamp the SOURCE slices like the border-image path so a pair that meets/overlaps\n // (margin_left + margin_right >= texture width — e.g. the 12px-wide capsule with 6+6\n // margins) keeps a >=1px `fill` center instead of collapsing it.\n const sliceMargins = clampNinePatchSlices(\n margins,\n image.atlas?.size ?? image.size,\n );\n const source = `url(\"${cssUrl(image.url)}\")`;\n const slice = `${sliceMargins.join(\" \")} fill`;\n const width = `${margins.join(\"px \")}px`;\n const repeat = `${axisStretchRepeat(axisHorizontal)} ${axisStretchRepeat(axisVertical)}`;\n attributes[\"data-godot-clip-mask\"] = \"nine-patch-border\";\n // `-webkit-mask-box-image` (Blink/WebKit, the renderer's targets — matching the\n // `-webkit-mask-*` already emitted above). Shorthand: source slice/width/outset repeat.\n maskStyle[\"-webkit-mask-box-image\"] =\n `${source} ${slice} / ${width} / 0 ${repeat}`;\n // Standard longhands for forward-compat (`mask-border-mode` defaults to `alpha`; the\n // capsule texture's alpha is the clip shape).\n maskStyle[\"mask-border-source\"] = source;\n maskStyle[\"mask-border-slice\"] = slice;\n maskStyle[\"mask-border-width\"] = width;\n maskStyle[\"mask-border-outset\"] = \"0\";\n maskStyle[\"mask-border-repeat\"] = repeat;\n maskStyle[\"mask-border-mode\"] = \"alpha\";\n}\n\nfunction assignTextureTintStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n resolved: GodotResolvedResource,\n tint: ColorMatrix | undefined,\n tintFilters: Map<string, string> | undefined,\n idPrefix: string,\n): void {\n if (!tint || !resolved.url) {\n return;\n }\n // External URLs can't be baked into an `<image>` SVG (see isEmbeddedAssetUrl);\n // the plain background-image is already set, so tint it via a CSS color-matrix\n // filter on the self layer instead.\n if (\n !isEmbeddedAssetUrl(resolved.url) &&\n applyTintFilterStyle(style, attributes, tintFilters, tint, idPrefix)\n ) {\n return;\n }\n // An AtlasTexture is pre-cropped into a standalone SVG (`imageResource`), so\n // routing it through `svgImageDataUrl` below would wrap that SVG inside another\n // SVG `<image>` — a nested SVG-data-URI that browsers refuse to rasterize as a\n // CSS background (the tinted sprite renders blank). Rebuild the crop and bake\n // the tint into ONE flat SVG instead (the `feColorMatrix` on the raster image,\n // exactly like the plain-texture path below), keeping the cropped intrinsic\n // size so the existing stretch background-size/position is unchanged.\n if (resolved.atlasCrop && resolved.atlas?.url && resolved.atlas.size) {\n const tinted = atlasTextureDataUrl(\n resolved.atlas.url,\n resolved.atlas.size,\n resolved.atlasCrop.region,\n resolved.atlasCrop.margin,\n tint,\n );\n style[\"background-image\"] = `url(\"${cssUrl(tinted)}\")`;\n attributes[\"data-godot-texture-tint\"] = \"svg-color-matrix\";\n return;\n }\n // Bake the color matrix into the image via SVG `feColorMatrix`. This\n // multiplies RGB per-pixel and PRESERVES alpha — matching Godot's shader\n // (`col.rgb *= v` before the texture alpha) and `modulate`. The\n // `background-color` + `background-blend-mode: multiply` + alpha-mask recipe is\n // NOT equivalent: its opaque tint fills the whole element and is only clipped\n // by the texture alpha, so anti-aliased edges bleed a gray/colored halo. The\n // matrix is per-pixel, so the existing background-size/position (region\n // cropping, stretch) still applies — the SVG keeps the same intrinsic size as\n // the original url (`resolved.size`; the raw-atlas fallback keeps a region and\n // draws the whole atlas, so use the atlas size there).\n const naturalSize = resolved.region\n ? (resolved.atlas?.size ?? resolved.size)\n : resolved.size;\n if (naturalSize?.width && naturalSize.height) {\n const tinted = svgImageDataUrl(\n resolved.url,\n naturalSize,\n { x: 0, y: 0, width: naturalSize.width, height: naturalSize.height },\n tint,\n );\n style[\"background-image\"] = `url(\"${cssUrl(tinted)}\")`;\n attributes[\"data-godot-texture-tint\"] = \"svg-color-matrix\";\n return;\n }\n // Fallback when the texture size is unknown (cannot build the SVG): a diagonal\n // tint can still be approximated with blend-multiply + alpha mask (a\n // non-diagonal matrix has no such fallback).\n if (!colorMatrixIsDiagonal(tint)) {\n attributes[\"data-godot-texture-tint\"] = \"missing-image-size\";\n return;\n }\n const image = `url(\"${cssUrl(resolved.url)}\")`;\n style[\"background-color\"] = colorMatrixDiagonalCss(tint);\n style[\"background-blend-mode\"] = \"multiply\";\n style[\"mask-image\"] = image;\n style[\"mask-size\"] = style[\"background-size\"] ?? \"auto\";\n style[\"mask-repeat\"] = style[\"background-repeat\"] ?? \"no-repeat\";\n style[\"mask-position\"] = style[\"background-position\"] ?? \"center\";\n style[\"-webkit-mask-image\"] = image;\n style[\"-webkit-mask-size\"] = style[\"mask-size\"];\n style[\"-webkit-mask-repeat\"] = style[\"mask-repeat\"];\n style[\"-webkit-mask-position\"] = style[\"mask-position\"];\n attributes[\"data-godot-texture-tint\"] = \"multiply\";\n}\n\n// Pure region→CSS math: paint a sub-rect of a STABLE atlas image by shifting the CSS viewport\n// (background-position/size) rather than swapping the image URL. Godot draws the `region` at `margin`'s\n// position inside a box of `region.size + margin.size`. With no `box`/`atlasSize` the image renders at native\n// pixels (`background-size: auto`); with both, it's scaled to the box per Godot's stretch mode. Exported so\n// consumers that own their own element styling (e.g. the live-tree mirror) reuse the exact same crop math\n// instead of re-deriving it — keeping atlas-animated sprites (intent icons) flicker-free with one URL.\nexport function regionBackgroundStyle(\n region: { x: number; y: number; width: number; height: number },\n options: {\n margin?: { x: number; y: number; width: number; height: number };\n atlasSize?: { width: number; height: number };\n box?: { width: number; height: number };\n stretchMode?: number;\n } = {},\n): { backgroundPosition: string; backgroundSize: string } {\n const { margin, atlasSize, box, stretchMode } = options;\n const texture = atlasTextureMetrics(region, margin);\n if (\n !atlasSize ||\n !box ||\n !box.width ||\n !box.height ||\n texture.width <= 0 ||\n texture.height <= 0\n ) {\n return {\n backgroundPosition: `${-(region.x - (margin?.x ?? 0))}px ${-(region.y - (margin?.y ?? 0))}px`,\n backgroundSize: \"auto\",\n };\n }\n const draw = textureDrawRect(box, texture, stretchMode);\n return {\n backgroundPosition: `${round(draw.x - (region.x - (margin?.x ?? 0)) * draw.scaleX)}px ${round(draw.y - (region.y - (margin?.y ?? 0)) * draw.scaleY)}px`,\n backgroundSize: `${round(atlasSize.width * draw.scaleX)}px ${round(atlasSize.height * draw.scaleY)}px`,\n };\n}\n\nfunction assignRegionBackgroundStyles(\n style: Record<string, string>,\n region: { x: number; y: number; width: number; height: number },\n atlasSize: { width: number; height: number } | undefined,\n stretchMode: number | undefined,\n margin?: { x: number; y: number; width: number; height: number },\n): void {\n const boxWidth = cssSize(style.width);\n const boxHeight = cssSize(style.height);\n const { backgroundPosition, backgroundSize } = regionBackgroundStyle(region, {\n margin,\n atlasSize,\n box: boxWidth && boxHeight ? { width: boxWidth, height: boxHeight } : undefined,\n stretchMode,\n });\n style[\"background-position\"] = backgroundPosition;\n style[\"background-size\"] = backgroundSize;\n}\n\nfunction textureDrawRect(\n box: { width: number; height: number },\n texture: { width: number; height: number },\n stretchMode: number | undefined,\n): { x: number; y: number; scaleX: number; scaleY: number } {\n if (stretchMode === 2 || stretchMode === 3) {\n return {\n x: stretchMode === 3 ? (box.width - texture.width) / 2 : 0,\n y: stretchMode === 3 ? (box.height - texture.height) / 2 : 0,\n scaleX: 1,\n scaleY: 1,\n };\n }\n if (stretchMode === 4 || stretchMode === 5) {\n const scale = Math.min(\n box.width / texture.width,\n box.height / texture.height,\n );\n return {\n x: stretchMode === 5 ? (box.width - texture.width * scale) / 2 : 0,\n y: stretchMode === 5 ? (box.height - texture.height * scale) / 2 : 0,\n scaleX: scale,\n scaleY: scale,\n };\n }\n return {\n x: 0,\n y: 0,\n scaleX: box.width / texture.width,\n scaleY: box.height / texture.height,\n };\n}\n\nfunction cssSize(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction ninePatchHtml(\n style: Record<string, string>,\n props: Record<string, GodotVariant>,\n image: GodotResolvedResource,\n margins: [number, number, number, number],\n axisHorizontal: number | undefined,\n axisVertical: number | undefined,\n tint: ColorMatrix | undefined,\n): string | undefined {\n const patch = ninePatchLayers(\n style,\n props,\n image,\n margins,\n axisHorizontal,\n axisVertical,\n );\n if (!patch || !image.url) {\n return undefined;\n }\n return patch.layers\n .map((layer) =>\n ninePatchLayerHtml({\n imageUrl: image.url ?? \"\",\n atlasSize: patch.textureSize,\n source: layer.source,\n dest: layer.dest,\n modeX: layer.modeX,\n modeY: layer.modeY,\n tint,\n }),\n )\n .join(\"\");\n}\n\nfunction ninePatchLayers(\n style: Record<string, string>,\n props: Record<string, GodotVariant>,\n image: GodotResolvedResource,\n margins: [number, number, number, number],\n axisHorizontal: number | undefined,\n axisVertical: number | undefined,\n):\n | {\n box: { width: number; height: number };\n textureSize: { width: number; height: number };\n layers: Array<{\n source: { x: number; y: number; width: number; height: number };\n dest: { x: number; y: number; width: number; height: number };\n modeX: number;\n modeY: number;\n }>;\n }\n | undefined {\n const boxWidth = cssSize(style.width);\n const boxHeight = cssSize(style.height);\n const textureSize = image.atlas?.size ?? image.size;\n if (!boxWidth || !boxHeight || !textureSize?.width || !textureSize.height) {\n return undefined;\n }\n const region = image.region ?? asRect2(props.region_rect);\n // The authored `region_rect` drives ALL nine-patch geometry — tile widths,\n // corner sizes, and dest positions — exactly as Godot does, even when the\n // region overflows the texture (e.g. a 116x85 region over a 114x82 image).\n // The texture-edge clamp for the overflow is applied per-slice below.\n const source =\n region && region.width > 0 && region.height > 0\n ? region\n : { x: 0, y: 0, width: textureSize.width, height: textureSize.height };\n const [top, right, bottom, left] = margins;\n const centerSourceWidth = Math.max(0, source.width - left - right);\n const centerSourceHeight = Math.max(0, source.height - top - bottom);\n const centerSourceColumn = centerPatchSourceSegment(\n source.x + left,\n centerSourceWidth,\n source.x,\n source.width,\n );\n const centerSourceRow = centerPatchSourceSegment(\n source.y + top,\n centerSourceHeight,\n source.y,\n source.height,\n );\n const centerDestWidth = Math.max(0, boxWidth - left - right);\n const centerDestHeight = Math.max(0, boxHeight - top - bottom);\n const columns = [\n {\n sourceStart: source.x,\n sourceSize: left,\n destStart: 0,\n destSize: left,\n mode: 0,\n },\n {\n sourceStart: centerSourceColumn.start,\n sourceSize: centerSourceColumn.size,\n destStart: left,\n destSize: centerDestWidth,\n mode: axisHorizontal ?? 0,\n },\n {\n sourceStart: source.x + source.width - right,\n sourceSize: right,\n destStart: boxWidth - right,\n destSize: right,\n mode: 0,\n },\n ];\n const rows = [\n {\n sourceStart: source.y,\n sourceSize: top,\n destStart: 0,\n destSize: top,\n mode: 0,\n },\n {\n sourceStart: centerSourceRow.start,\n sourceSize: centerSourceRow.size,\n destStart: top,\n destSize: centerDestHeight,\n mode: axisVertical ?? 0,\n },\n {\n sourceStart: source.y + source.height - bottom,\n sourceSize: bottom,\n destStart: boxHeight - bottom,\n destSize: bottom,\n mode: 0,\n },\n ];\n const drawCenter = asBoolean(props.draw_center) ?? true;\n const layers: Array<{\n source: { x: number; y: number; width: number; height: number };\n dest: { x: number; y: number; width: number; height: number };\n modeX: number;\n modeY: number;\n }> = [];\n for (let row = 0; row < rows.length; row += 1) {\n for (let column = 0; column < columns.length; column += 1) {\n if (!drawCenter && row === 1 && column === 1) {\n continue;\n }\n const x = columns[column];\n const y = rows[row];\n if (\n !x ||\n !y ||\n x.sourceSize <= 0 ||\n y.sourceSize <= 0 ||\n x.destSize <= 0 ||\n y.destSize <= 0\n ) {\n continue;\n }\n // Clamp ONLY this slice's source rect to the texture (Godot's\n // CLAMP_TO_EDGE). The dest is left at the authored-region position, so the\n // dest/source scale in `ninePatchLayerHtml` stretches the valid edge pixels\n // to fill it instead of leaving the 2-3px texture overflow transparent. A\n // slice that sits fully past the edge (a large region overflow) clamps to\n // the 1px boundary texel rather than collapsing to 0, so the trailing\n // caps/center keep drawing (never blank) and TILE tiling never divides by a\n // zero slice width. A no-op for in-bounds slices (the common case and the\n // center tile).\n const source = clampSliceSourceToTexture(\n {\n x: x.sourceStart,\n y: y.sourceStart,\n width: x.sourceSize,\n height: y.sourceSize,\n },\n textureSize,\n );\n layers.push({\n source,\n dest: {\n x: x.destStart,\n y: y.destStart,\n width: x.destSize,\n height: y.destSize,\n },\n modeX: x.mode,\n modeY: y.mode,\n });\n }\n }\n return {\n box: { width: boxWidth, height: boxHeight },\n textureSize,\n layers,\n };\n}\n\nfunction clampSliceSourceToTexture(\n source: { x: number; y: number; width: number; height: number },\n textureSize: { width: number; height: number },\n): { x: number; y: number; width: number; height: number } {\n // Intersect the slice's source rect with the texture, but never let it\n // collapse below 1px. A slice fully past the texture edge (a large region\n // overflow) clamps to the boundary texel — Godot's CLAMP_TO_EDGE — so it still\n // paints (stretched/tiled to its authored dest) instead of being dropped, and\n // the TILE `background-size` / axis scale never see a zero source width. A\n // no-op for the in-bounds case (`x0 === source.x`, `width` unchanged).\n const x0 = Math.min(\n Math.max(source.x, 0),\n Math.max(0, textureSize.width - 1),\n );\n const y0 = Math.min(\n Math.max(source.y, 0),\n Math.max(0, textureSize.height - 1),\n );\n const x1 = Math.min(source.x + source.width, textureSize.width);\n const y1 = Math.min(source.y + source.height, textureSize.height);\n return {\n x: x0,\n y: y0,\n width: Math.max(1, x1 - x0),\n height: Math.max(1, y1 - y0),\n };\n}\n\nfunction centerPatchSourceSegment(\n start: number,\n size: number,\n sourceStart: number,\n sourceSize: number,\n): { start: number; size: number } {\n if (size > 0) {\n return { start, size };\n }\n return {\n start: clamp(start, sourceStart, sourceStart + Math.max(0, sourceSize - 1)),\n size: 1,\n };\n}\n\nfunction ninePatchLayerHtml(options: {\n imageUrl: string;\n atlasSize: { width: number; height: number };\n source: { x: number; y: number; width: number; height: number };\n dest: { x: number; y: number; width: number; height: number };\n modeX: number;\n modeY: number;\n tint: ColorMatrix | undefined;\n}): string {\n const scaleX = ninePatchAxisScale(\n options.dest.width,\n options.source.width,\n options.modeX,\n );\n const scaleY = ninePatchAxisScale(\n options.dest.height,\n options.source.height,\n options.modeY,\n );\n const repeatX = options.modeX === 1 || options.modeX === 2;\n const repeatY = options.modeY === 1 || options.modeY === 2;\n const sliceUrl = svgSliceDataUrl(\n options.imageUrl,\n options.atlasSize,\n options.source,\n options.tint,\n );\n const repeat = `${repeatX ? \"repeat\" : \"no-repeat\"} ${repeatY ? \"repeat\" : \"no-repeat\"}`;\n const backgroundSize = `${round(options.source.width * scaleX)}px ${round(options.source.height * scaleY)}px`;\n const sliceImage = `url(\"${cssUrl(sliceUrl)}\")`;\n const layerStyle: Record<string, string> = {\n position: \"absolute\",\n left: `${round(options.dest.x)}px`,\n top: `${round(options.dest.y)}px`,\n width: `${round(options.dest.width)}px`,\n height: `${round(options.dest.height)}px`,\n overflow: \"hidden\",\n \"background-image\": sliceImage,\n \"background-repeat\": repeat,\n \"background-size\": backgroundSize,\n };\n return `<span aria-hidden=\"true\" data-godot-nine-patch-slice=\"true\" style=\"${escapeAttribute(styleAttribute(layerStyle))}\"></span>`;\n}\n\nfunction ninePatchAxisScale(\n destSize: number,\n sourceSize: number,\n mode: number,\n): number {\n if (sourceSize <= 0) {\n return 1;\n }\n if (mode === 1) {\n return 1;\n }\n if (mode === 2) {\n const count = Math.max(1, Math.round(destSize / sourceSize));\n return destSize / count / sourceSize;\n }\n return destSize / sourceSize;\n}\n\nfunction svgSliceDataUrl(\n imageUrl: string,\n atlasSize: { width: number; height: number },\n source: { x: number; y: number; width: number; height: number },\n tint: ColorMatrix | undefined,\n): string {\n return svgImageDataUrl(imageUrl, atlasSize, source, tint);\n}\n\nfunction ninePatchMaskDataUrl(\n style: Record<string, string>,\n props: Record<string, GodotVariant>,\n image: GodotResolvedResource,\n margins: [number, number, number, number],\n axisHorizontal: number | undefined,\n axisVertical: number | undefined,\n): string | undefined {\n if (!image.url) {\n return undefined;\n }\n const patch = ninePatchLayers(\n style,\n props,\n image,\n margins,\n axisHorizontal,\n axisVertical,\n );\n if (!patch) {\n return undefined;\n }\n const defs: string[] = [];\n const shapes = patch.layers\n .map((layer, index) =>\n ninePatchMaskLayerSvg({\n id: `godot-nine-patch-mask-${index}`,\n imageUrl: image.url ?? \"\",\n atlasSize: patch.textureSize,\n source: layer.source,\n dest: layer.dest,\n modeX: layer.modeX,\n modeY: layer.modeY,\n defs,\n }),\n )\n .join(\"\");\n const defsSvg = defs.length > 0 ? `<defs>${defs.join(\"\")}</defs>` : \"\";\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${round(patch.box.width)}\" height=\"${round(patch.box.height)}\" viewBox=\"0 0 ${round(patch.box.width)} ${round(patch.box.height)}\">${defsSvg}${shapes}</svg>`;\n return `data:image/svg+xml,${encodeURIComponent(svg)}`;\n}\n\nfunction ninePatchMaskLayerSvg(options: {\n id: string;\n imageUrl: string;\n atlasSize: { width: number; height: number };\n source: { x: number; y: number; width: number; height: number };\n dest: { x: number; y: number; width: number; height: number };\n modeX: number;\n modeY: number;\n defs: string[];\n}): string {\n const scaleX = ninePatchAxisScale(\n options.dest.width,\n options.source.width,\n options.modeX,\n );\n const scaleY = ninePatchAxisScale(\n options.dest.height,\n options.source.height,\n options.modeY,\n );\n const repeatX = options.modeX === 1 || options.modeX === 2;\n const repeatY = options.modeY === 1 || options.modeY === 2;\n if (repeatX || repeatY) {\n const width = repeatX\n ? round(options.source.width * scaleX)\n : round(options.dest.width);\n const height = repeatY\n ? round(options.source.height * scaleY)\n : round(options.dest.height);\n options.defs.push(\n `<pattern id=\"${options.id}\" patternUnits=\"userSpaceOnUse\" x=\"${round(options.dest.x)}\" y=\"${round(options.dest.y)}\" width=\"${width}\" height=\"${height}\"><svg width=\"${width}\" height=\"${height}\" viewBox=\"${round(options.source.x)} ${round(options.source.y)} ${round(options.source.width)} ${round(options.source.height)}\" preserveAspectRatio=\"none\"><image href=\"${escapeAttribute(options.imageUrl)}\" x=\"0\" y=\"0\" width=\"${round(options.atlasSize.width)}\" height=\"${round(options.atlasSize.height)}\"/></svg></pattern>`,\n );\n return `<rect x=\"${round(options.dest.x)}\" y=\"${round(options.dest.y)}\" width=\"${round(options.dest.width)}\" height=\"${round(options.dest.height)}\" fill=\"url(#${options.id})\"/>`;\n }\n return `<svg x=\"${round(options.dest.x)}\" y=\"${round(options.dest.y)}\" width=\"${round(options.dest.width)}\" height=\"${round(options.dest.height)}\" viewBox=\"${round(options.source.x)} ${round(options.source.y)} ${round(options.source.width)} ${round(options.source.height)}\" preserveAspectRatio=\"none\"><image href=\"${escapeAttribute(options.imageUrl)}\" x=\"0\" y=\"0\" width=\"${round(options.atlasSize.width)}\" height=\"${round(options.atlasSize.height)}\"/></svg>`;\n}\n\n// Memo for the SVG `<image>` crop/tint URLs (module-scoped LRU, mirroring `atlas.ts`'s). WHY:\n// the same handful of sprites re-serialize the same SVG + `encodeURIComponent` on every render;\n// this is one of the repeated tint-URL builds phone traces showed inside a play-a-card burst.\n// Pure string→string, so a hit is byte-identical to a fresh build.\nconst SVG_IMAGE_DATA_URL_CACHE_LIMIT = 200;\nconst svgImageDataUrlCache = createStringLru<string>(\n SVG_IMAGE_DATA_URL_CACHE_LIMIT,\n);\n\n/** TEST-ONLY: clear the SVG image data-URL memo so a test starts from an empty cache. */\nexport function __resetSvgImageDataUrlCacheForTest(): void {\n svgImageDataUrlCache.clear();\n}\n\nfunction svgImageDataUrl(\n imageUrl: string,\n atlasSize: { width: number; height: number },\n source: { x: number; y: number; width: number; height: number },\n tint: ColorMatrix | undefined,\n): string {\n // Fixed-arity numeric fields first, the arbitrary-content url last (see atlas.ts).\n const key =\n `${atlasSize.width},${atlasSize.height}` +\n `|${source.x},${source.y},${source.width},${source.height}` +\n `|${tint ? tint.rows.map((row) => row.join(\",\")).join(\";\") : \"\"}` +\n `|${imageUrl}`;\n const hit = svgImageDataUrlCache.get(key);\n if (hit !== undefined) {\n return hit;\n }\n const url = buildSvgImageDataUrl(imageUrl, atlasSize, source, tint);\n svgImageDataUrlCache.set(key, url);\n return url;\n}\n\nfunction buildSvgImageDataUrl(\n imageUrl: string,\n atlasSize: { width: number; height: number },\n source: { x: number; y: number; width: number; height: number },\n tint: ColorMatrix | undefined,\n): string {\n const filterId = \"godot-texture-tint\";\n const filter = tint\n ? `<filter id=\"${filterId}\" color-interpolation-filters=\"sRGB\"><feColorMatrix type=\"matrix\" values=\"${colorMatrixFeValues(tint)}\"/></filter>`\n : \"\";\n const defs = filter ? `<defs>${filter}</defs>` : \"\";\n const filterAttr = filter ? ` filter=\"url(#${filterId})\"` : \"\";\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${round(source.width)}\" height=\"${round(source.height)}\" viewBox=\"0 0 ${round(source.width)} ${round(source.height)}\">${defs}<image href=\"${escapeAttribute(imageUrl)}\" x=\"${round(-source.x)}\" y=\"${round(-source.y)}\" width=\"${round(atlasSize.width)}\" height=\"${round(atlasSize.height)}\"${filterAttr}/></svg>`;\n return `data:image/svg+xml,${encodeURIComponent(svg)}`;\n}\n\nfunction assignTextureMetadata(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n): void {\n const repeat = asNumber(props.texture_repeat);\n const filter = asNumber(props.texture_filter);\n const expandMode = asNumber(props.expand_mode);\n if (repeat !== undefined) {\n attributes[\"data-godot-texture-repeat\"] = String(repeat);\n }\n if (filter !== undefined) {\n attributes[\"data-godot-texture-filter\"] = String(filter);\n if (filter === 1) {\n style[\"image-rendering\"] = \"pixelated\";\n }\n }\n if (expandMode !== undefined) {\n attributes[\"data-godot-expand-mode\"] = String(expandMode);\n }\n}\n\nexport function assignAnimatedSpriteStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): void {\n attributes[\"data-godot-resource-kind\"] = \"AnimatedSprite2D\";\n const framesRef = asResourceRef(props.sprite_frames);\n if (!framesRef) {\n return;\n }\n const frames = normalizeResource(\n options.resolveResource?.(framesRef, source),\n );\n if (frames?.path) {\n attributes[\"data-godot-sprite-frames-path\"] = frames.path;\n }\n const selection = selectedSpriteFrame(frames?.document, props);\n if (!selection) {\n return;\n }\n attributes[\"data-godot-sprite-animation\"] = selection.animation;\n attributes[\"data-godot-sprite-frame\"] = String(selection.frame);\n attributes[\"data-godot-sprite-frame-count\"] = String(selection.frameCount);\n const textureRef = spriteFrameTextureRef(selection.value);\n if (!textureRef) {\n return;\n }\n const image = imageResource(\n normalizeResource(options.resolveResource?.(textureRef, source)),\n options,\n source,\n );\n if (image.path) {\n attributes[\"data-godot-resource-path\"] = image.path;\n }\n const size = animatedSpriteFrameSize(image);\n if (size) {\n const offset = asVector2(props.offset) ?? { x: 0, y: 0 };\n const centered = asBoolean(props.centered) ?? true;\n const left = cssSize(style.left) ?? 0;\n const top = cssSize(style.top) ?? 0;\n style.left = `${round(left + offset.x - (centered ? size.width / 2 : 0))}px`;\n style.top = `${round(top + offset.y - (centered ? size.height / 2 : 0))}px`;\n style.width = `${round(Math.max(1, size.width))}px`;\n style.height = `${round(Math.max(1, size.height))}px`;\n }\n if (!image.url) {\n return;\n }\n style[\"background-image\"] = `url(\"${cssUrl(image.url)}\")`;\n style[\"background-repeat\"] = \"no-repeat\";\n if (image.region) {\n const textureSize = image.atlas?.size ?? image.size;\n attributes[\"data-godot-atlas-region\"] =\n `${image.region.x},${image.region.y},${image.region.width},${image.region.height}`;\n style[\"background-position\"] =\n `${round(-image.region.x)}px ${round(-image.region.y)}px`;\n style[\"background-size\"] = textureSize\n ? `${round(textureSize.width)}px ${round(textureSize.height)}px`\n : \"auto\";\n } else {\n style[\"background-size\"] = \"100% 100%\";\n style[\"background-position\"] = \"center\";\n }\n}\n\nfunction selectedSpriteFrame(\n document: GodotResource | undefined,\n props: Record<string, GodotVariant>,\n):\n | {\n animation: string;\n frame: number;\n frameCount: number;\n value: GodotVariant | undefined;\n }\n | undefined {\n const animations = spriteAnimations(document);\n if (animations.length === 0) {\n return undefined;\n }\n const requestedAnimation = stringOrStringName(props.animation) ?? \"default\";\n const animation =\n animations.find((candidate) => candidate.name === requestedAnimation) ??\n animations[0];\n if (!animation) {\n return undefined;\n }\n const frameCount = animation.frames.length;\n const rawFrame = Math.floor(asNumber(props.frame) ?? 0);\n const frame = frameCount > 0 ? clamp(rawFrame, 0, frameCount - 1) : 0;\n return {\n animation: animation.name,\n frame,\n frameCount,\n value: animation.frames[frame],\n };\n}\n\nfunction spriteAnimations(\n document: GodotResource | undefined,\n): Array<{ name: string; frames: GodotVariant[] }> {\n const animations = document?.properties.animations;\n if (!Array.isArray(animations)) {\n return [];\n }\n return animations.flatMap((value) => {\n const animation = plainRecord(value);\n const name = stringOrStringName(animation?.name);\n const frames = animation?.frames;\n return name !== undefined && Array.isArray(frames)\n ? [{ name, frames }]\n : [];\n });\n}\n\nfunction spriteFrameTextureRef(\n value: GodotVariant | undefined,\n): GodotResourceRefValue | undefined {\n const directRef = asResourceRef(value);\n if (directRef) {\n return directRef;\n }\n const frame = plainRecord(value);\n return frame ? asResourceRef(frame.texture) : undefined;\n}\n\nfunction animatedSpriteFrameSize(\n image: GodotResolvedResource,\n): { width: number; height: number } | undefined {\n const size = image.region\n ? { width: image.region.width, height: image.region.height }\n : image.size;\n if (!size || size.width <= 0 || size.height <= 0) {\n return undefined;\n }\n return size;\n}\n\nfunction stringOrStringName(\n value: GodotVariant | undefined,\n): string | undefined {\n const string = asString(value);\n if (string !== undefined) {\n return string;\n }\n if (\n !value ||\n typeof value !== \"object\" ||\n Array.isArray(value) ||\n !(\"type\" in value)\n ) {\n return undefined;\n }\n const record = value as Record<string, unknown>;\n return record.type === \"StringName\" &&\n Array.isArray(record.args) &&\n typeof record.args[0] === \"string\"\n ? record.args[0]\n : undefined;\n}\n\nfunction plainRecord(\n value: GodotVariant | undefined,\n): Record<string, GodotVariant> | undefined {\n if (\n !value ||\n typeof value !== \"object\" ||\n Array.isArray(value) ||\n \"type\" in value\n ) {\n return undefined;\n }\n return value as Record<string, GodotVariant>;\n}\n\nfunction patchMargins(\n props: Record<string, GodotVariant>,\n): [number, number, number, number] {\n return [\n asNumber(props.patch_margin_top) ?? 0,\n asNumber(props.patch_margin_right) ?? 0,\n asNumber(props.patch_margin_bottom) ?? 0,\n asNumber(props.patch_margin_left) ?? 0,\n ];\n}\n\nfunction stretchModeBackgroundSize(value: number | undefined): string {\n // STRETCH_KEEP_ASPECT (4) and STRETCH_KEEP_ASPECT_CENTERED (5) both fit the\n // texture while preserving its aspect ratio (Godot differs only in alignment,\n // top-left vs centered; background-position handles that). Without 4 here a\n // KEEP_ASPECT TextureRect fell through to \"100% 100%\" and stretched to its box.\n if (value === 4 || value === 5) {\n return \"contain\";\n }\n if (value === 6) {\n return \"cover\";\n }\n return \"100% 100%\";\n}\n\nfunction textureRepeat(\n textureRepeatValue: number | undefined,\n stretchMode: number | undefined,\n): string {\n if (\n stretchMode === 1 ||\n textureRepeatValue === 1 ||\n textureRepeatValue === 2\n ) {\n return \"repeat\";\n }\n return \"no-repeat\";\n}\n\nfunction axisStretchRepeat(value: number | undefined): string {\n if (value === 1) {\n return \"repeat\";\n }\n if (value === 2) {\n return \"round\";\n }\n return \"stretch\";\n}\n","import {\n asBoolean,\n asNumber,\n asRect2,\n asResourceRef,\n asString,\n asVector2,\n type GodotCallVariant,\n type GodotNode,\n type GodotVariant,\n} from \"@godot-scene-web/core\";\nimport {\n linearizeParticleBaseColor,\n normalizeGodotRenderer,\n} from \"@godot-scene-web/effects/particles\";\nimport {\n clamp,\n colorCss,\n cssSize,\n cssUrl,\n escapeAttribute,\n round,\n styleAttribute,\n} from \"./css-values\";\nimport {\n isHiddenRawShaderFallbackMaterial,\n isWebglShaderMaterialNode,\n shaderIdListMatches,\n} from \"./material\";\nimport type { ParticleSpecConfig } from \"./particles/spec\";\nimport { imageResource, normalizeResource } from \"./resources\";\nimport type { GodotHtmlRenderOptions, GodotResolvedResource } from \"./types\";\nimport type { CurvePoint, GradientStop } from \"./webgl/bake-texture\";\n\nexport function assignSprite2DStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n nodePath?: string,\n): void {\n const image = resolveTextureImage(\n attributes,\n props,\n source,\n options,\n \"Sprite2D\",\n );\n assignTextureMetadata(style, attributes, props);\n assignNumberAttribute(attributes, props, \"hframes\", \"data-godot-hframes\");\n assignNumberAttribute(attributes, props, \"vframes\", \"data-godot-vframes\");\n assignNumberAttribute(attributes, props, \"frame\", \"data-godot-frame\");\n assignVectorAttribute(\n attributes,\n props,\n \"frame_coords\",\n \"data-godot-frame-coords\",\n );\n assignBooleanAttribute(\n attributes,\n props,\n \"region_enabled\",\n \"data-godot-region-enabled\",\n );\n assignRectAttribute(\n attributes,\n props,\n \"region_rect\",\n \"data-godot-region-rect\",\n );\n if (!image.url) {\n return;\n }\n // For a WebGL-eligible shader sprite, expose the RAW texture url the runtime\n // must bind as `TEXTURE` — the same contract `assignTextureStyles` publishes for\n // TextureRect/NinePatchRect. The runtime's fallback (reading the self-layer's\n // `background-image`) is NOT stable: mounting the shader canvas clears that\n // background, so a later reconcile re-read yields null and silently rebinds\n // TEXTURE to solid WHITE — which broke every texture-gated shader term (the Neow\n // `water_reflection` stepped-fire glow lost its light.png radial falloff and\n // flooded the whole box).\n if (isWebglShaderMaterialNode(props, source, options, nodePath)) {\n attributes[\"data-godot-shader-texture-url\"] = image.url;\n }\n const sourceRect = spriteSourceRect(props, image);\n const textureSize = image.atlas?.size ?? image.size;\n const width = sourceRect?.width ?? cssSize(style.width);\n const height = sourceRect?.height ?? cssSize(style.height);\n if (width && height) {\n const offset = asVector2(props.offset) ?? { x: 0, y: 0 };\n const centered = asBoolean(props.centered) ?? true;\n const left = cssSize(style.left) ?? 0;\n const top = cssSize(style.top) ?? 0;\n style.left = `${round(left + offset.x - (centered ? width / 2 : 0))}px`;\n style.top = `${round(top + offset.y - (centered ? height / 2 : 0))}px`;\n style.width = `${round(width)}px`;\n style.height = `${round(height)}px`;\n if (style.transform) {\n style[\"transform-origin\"] =\n `${round((centered ? width / 2 : 0) - offset.x)}px ` +\n `${round((centered ? height / 2 : 0) - offset.y)}px`;\n }\n }\n if (sourceRect && image.region) {\n attributes[\"data-godot-atlas-region\"] =\n `${image.region.x},${image.region.y},${image.region.width},${image.region.height}`;\n }\n if (sourceRect) {\n attributes[\"data-godot-source-rect\"] =\n `${sourceRect.x},${sourceRect.y},${sourceRect.width},${sourceRect.height}`;\n }\n // Honor the consumer's hidden-raw-fallback list exactly like the\n // TextureRect/NinePatchRect path (`assignTextureStyles`): a listed shader's raw\n // texture must NEVER paint. In Godot the texture is only an input the shader\n // gates/reshapes (e.g. light.png's radial falloff feeding the stepped-fire\n // water_reflection glow); painting it raw stretches the untransformed texture\n // over the node's full (often huge, rotated) quad — a hard-edged sheet that\n // shows both during the async WebGL takeover and permanently when the shader\n // can't run. Suppressing the paint degrades a non-running shader to the\n // consumer's documented hidden state; the WebGL canvas repaints the node when\n // it activates. The geometry/attrs above still apply (the runtime needs the\n // atlas region + `data-godot-shader-texture-url` to bind TEXTURE correctly).\n if (isHiddenRawShaderFallbackMaterial(props, source, options, nodePath)) {\n attributes[\"data-godot-shader-raw-fallback\"] = \"hidden\";\n return;\n }\n style[\"background-image\"] = `url(\"${cssUrl(image.url)}\")`;\n style[\"background-repeat\"] = textureRepeat(asNumber(props.texture_repeat));\n if (sourceRect) {\n style[\"background-position\"] =\n `${round(-sourceRect.x)}px ${round(-sourceRect.y)}px`;\n style[\"background-size\"] = textureSize\n ? `${round(textureSize.width)}px ${round(textureSize.height)}px`\n : \"auto\";\n } else {\n style[\"background-size\"] = \"100% 100%\";\n style[\"background-position\"] = \"center\";\n }\n}\n\nexport function assignLine2DStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): string | undefined {\n attributes[\"data-godot-resource-kind\"] = \"Line2D\";\n resolveTextureImage(attributes, props, source, options, \"Line2D\");\n assignTextureMetadata(style, attributes, props);\n assignNumberAttribute(\n attributes,\n props,\n \"texture_mode\",\n \"data-godot-texture-mode\",\n );\n assignNumberAttribute(\n attributes,\n props,\n \"joint_mode\",\n \"data-godot-joint-mode\",\n );\n assignNumberAttribute(\n attributes,\n props,\n \"begin_cap_mode\",\n \"data-godot-begin-cap-mode\",\n );\n assignNumberAttribute(\n attributes,\n props,\n \"end_cap_mode\",\n \"data-godot-end-cap-mode\",\n );\n assignNumberAttribute(\n attributes,\n props,\n \"sharp_limit\",\n \"data-godot-sharp-limit\",\n );\n assignNumberAttribute(\n attributes,\n props,\n \"round_precision\",\n \"data-godot-round-precision\",\n );\n assignBooleanAttribute(attributes, props, \"closed\", \"data-godot-closed\");\n assignBooleanAttribute(\n attributes,\n props,\n \"antialiased\",\n \"data-godot-antialiased\",\n );\n assignResourceRefAttributes(\n attributes,\n props.gradient,\n source,\n options,\n \"gradient\",\n );\n assignResourceRefAttributes(\n attributes,\n props.width_curve,\n source,\n options,\n \"width-curve\",\n );\n const points = vector2Points(props.points);\n if (points.length < 2) {\n return undefined;\n }\n const width = asNumber(props.width) ?? 10;\n const closed = asBoolean(props.closed) ?? false;\n const minX = Math.min(...points.map((point) => point.x));\n const minY = Math.min(...points.map((point) => point.y));\n const maxX = Math.max(...points.map((point) => point.x));\n const maxY = Math.max(...points.map((point) => point.y));\n const pad = Math.max(1, width);\n const left = cssSize(style.left) ?? 0;\n const top = cssSize(style.top) ?? 0;\n style.left = `${round(left + minX - pad / 2)}px`;\n style.top = `${round(top + minY - pad / 2)}px`;\n style.width = `${round(Math.max(1, maxX - minX + pad))}px`;\n style.height = `${round(Math.max(1, maxY - minY + pad))}px`;\n style.overflow = \"visible\";\n const color =\n colorCss(props.default_color) ??\n colorCss(props.modulate) ??\n \"rgba(102, 128, 255, 1)\";\n const gradient = lineGradient(props.gradient, source, options);\n const drawPoints = closed\n ? [...points, points[0]].filter(\n (point): point is { x: number; y: number } => Boolean(point),\n )\n : points;\n const svgPoints = drawPoints\n .map(\n (point) =>\n `${round(point.x - minX + pad / 2)},${round(point.y - minY + pad / 2)}`,\n )\n .join(\" \");\n const viewWidth = round(Math.max(1, maxX - minX + pad));\n const viewHeight = round(Math.max(1, maxY - minY + pad));\n const svgStyle = styleAttribute({\n position: \"absolute\",\n inset: \"0\",\n overflow: \"visible\",\n });\n const defs = gradient\n ? `<defs><linearGradient id=\"${gradient.id}\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">${gradient.stops}</linearGradient></defs>`\n : \"\";\n const stroke = gradient ? `url(#${gradient.id})` : color;\n return `<svg aria-hidden=\"true\" data-godot-line2d=\"true\" width=\"100%\" height=\"100%\" viewBox=\"0 0 ${escapeAttribute(String(viewWidth))} ${escapeAttribute(String(viewHeight))}\" style=\"${escapeAttribute(svgStyle)}\">${defs}<polyline points=\"${escapeAttribute(svgPoints)}\" fill=\"none\" stroke=\"${escapeAttribute(stroke)}\" stroke-width=\"${round(width)}\" stroke-linecap=\"${lineCap(props, closed)}\" stroke-linejoin=\"${lineJoin(props)}\"/></svg>`;\n}\n\nexport function assignParticle2DStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n kind: \"CPUParticles2D\" | \"GPUParticles2D\",\n nodePath: string,\n): string | undefined {\n attributes[\"data-godot-resource-kind\"] = kind;\n attributes[\"data-godot-static-preview\"] = \"true\";\n assignNumberAttribute(\n attributes,\n props,\n \"amount\",\n \"data-godot-particle-amount\",\n );\n assignNumberAttribute(\n attributes,\n props,\n \"amount_ratio\",\n \"data-godot-particle-amount-ratio\",\n );\n assignNumberAttribute(\n attributes,\n props,\n \"draw_order\",\n \"data-godot-particle-draw-order\",\n );\n assignBooleanAttribute(\n attributes,\n props,\n \"emitting\",\n \"data-godot-particle-emitting\",\n );\n assignParticleTimingMetadata(attributes, props);\n assignResourceRefAttributes(\n attributes,\n props.process_material,\n source,\n options,\n \"process-material\",\n );\n assignResourceRefAttributes(\n attributes,\n props.color_ramp,\n source,\n options,\n \"color-ramp\",\n );\n assignResourceRefAttributes(\n attributes,\n props.color_initial_ramp,\n source,\n options,\n \"color-initial-ramp\",\n );\n assignResourceRefAttributes(\n attributes,\n props.scale_amount_curve,\n source,\n options,\n \"scale-amount-curve\",\n );\n assignResourceRefAttributes(\n attributes,\n props.scale_curve_x,\n source,\n options,\n \"scale-curve-x\",\n );\n assignResourceRefAttributes(\n attributes,\n props.scale_curve_y,\n source,\n options,\n \"scale-curve-y\",\n );\n const processMaterial = resolvedResource(\n props.process_material,\n source,\n options,\n );\n const materialProps =\n processMaterial?.document?.properties ??\n (kind === \"CPUParticles2D\" ? props : undefined);\n assignParticleMaterialMetadata(\n attributes,\n materialProps,\n kind === \"CPUParticles2D\" ? \"particle\" : \"process-material\",\n );\n assignNestedResourceRefAttribute(\n attributes,\n processMaterial,\n \"color_ramp\",\n \"process-material-color-ramp\",\n );\n assignNestedResourceRefAttribute(\n attributes,\n processMaterial,\n \"color_initial_ramp\",\n \"process-material-color-initial-ramp\",\n );\n assignNestedResourceRefAttribute(\n attributes,\n processMaterial,\n \"emission_point_texture\",\n \"process-material-emission-point-texture\",\n );\n assignNestedResourceRefAttribute(\n attributes,\n processMaterial,\n \"emission_color_texture\",\n \"process-material-emission-color-texture\",\n );\n assignNestedResourceRefAttribute(\n attributes,\n processMaterial,\n \"emission_normal_texture\",\n \"process-material-emission-normal-texture\",\n );\n const image = resolveTextureImage(attributes, props, source, options, kind);\n assignTextureMetadata(style, attributes, props);\n const shape = particleShape(materialProps);\n assignParticleShapeMetadata(attributes, shape);\n const colorRamp =\n particleGradientStops(props.color_ramp, source, options) ??\n particleGradientStops(materialProps?.color_ramp, source, options);\n const colorInitialRamp =\n particleGradientStops(props.color_initial_ramp, source, options) ??\n particleGradientStops(materialProps?.color_initial_ramp, source, options);\n assignParticleRampMetadata(attributes, \"color-ramp\", colorRamp);\n assignParticleRampMetadata(\n attributes,\n \"color-initial-ramp\",\n colorInitialRamp,\n );\n const rect =\n asRect2(props.visibility_rect) ??\n asRect2(props.rect) ??\n particleFallbackRect(kind, image, shape);\n const left = cssSize(style.left) ?? 0;\n const top = cssSize(style.top) ?? 0;\n style.left = `${round(left + rect.x)}px`;\n style.top = `${round(top + rect.y)}px`;\n style.width = `${round(Math.max(1, rect.width))}px`;\n style.height = `${round(Math.max(1, rect.height))}px`;\n style.overflow = image.url ? \"visible\" : \"hidden\";\n const amount = Math.max(1, Math.round(asNumber(props.amount) ?? 8));\n const ratio = clamp(asNumber(props.amount_ratio) ?? 1, 0, 1);\n const count = Math.max(1, Math.min(64, Math.round(amount * ratio)));\n attributes[\"data-godot-particle-preview-count\"] = String(count);\n const minScale =\n asNumber(props.scale_amount_min) ?? asNumber(materialProps?.scale_min) ?? 1;\n const maxScale =\n asNumber(props.scale_amount_max) ??\n asNumber(materialProps?.scale_max) ??\n asNumber(props.scale_amount_max) ??\n minScale;\n attributes[\"data-godot-particle-scale-range\"] = `${minScale},${maxScale}`;\n const seed = particleSeed(props, attributes, kind);\n attributes[\"data-godot-particle-preview-seed\"] = String(seed.value);\n attributes[\"data-godot-particle-preview-seed-source\"] = seed.source;\n const materialColor = rgbaValue(materialProps?.color);\n const particleColor =\n materialColor ?? rgbaValue(props.color) ?? rgbaValue(props.modulate);\n // DELIBERATELY the raw sRGB value, NOT `baseColorRender`. `options.godotRenderer`'s\n // sRGB→linear correction is a RENDERED-PIXEL correction (see core's `particles/godot-renderer.ts`),\n // and this `color` — plus the `data-godot-*-color` attribute below — is the static `<span>`\n // preview and the value a consumer reads back. Both mirror what the Godot INSPECTOR shows for\n // `ParticleProcessMaterial.color`, which is the authored colour. Darkening them would make\n // the DOM lie about the scene, and would move goldens that have nothing to do with blending.\n const color = particleColor\n ? colorToCss(particleColor)\n : \"rgba(255, 255, 255, 1)\";\n if (materialColor) {\n attributes[\n `data-godot-${kind === \"CPUParticles2D\" ? \"particle\" : \"process-material\"}-color`\n ] = colorToCss(materialColor);\n }\n if (image.url && particleColor) {\n attributes[\"data-godot-particle-texture-tint\"] = \"multiply\";\n }\n // Additive particles (CanvasItemMaterial.blend_mode = BLEND_MODE_ADD) glow: the WebGL runtime\n // draws them additively, and the static <span> fallback must composite `plus-lighter` too, else a\n // white spark (base white, no ramp) previews as a flat white box instead of a glow.\n const canvasMaterial = resolvedResource(props.material, source, options);\n const canvasMaterialType =\n canvasMaterial?.type ??\n asString(canvasMaterial?.document?.header?.attributes.type);\n const additiveBlend =\n canvasMaterialType === \"CanvasItemMaterial\" &&\n Math.round(\n asNumber(canvasMaterial?.document?.properties?.blend_mode) ?? 0,\n ) === 1;\n // Live runtime opt-in: when enabled for this node, emit the marker + the full\n // serialized simulation config. Gated so the static html-string renderer (which\n // never sets `enableParticles`) keeps the byte-identical `<span>` preview below,\n // which also stays as the no-JS / no-GL fallback.\n if (\n isParticleRuntimeEnabled(\n options,\n nodePath,\n processMaterial?.path,\n image.path,\n )\n ) {\n attributes[\"data-godot-particle-runtime\"] = \"1\";\n attributes[\"data-godot-particle-specs\"] = JSON.stringify(\n serializeParticleConfig({\n kind,\n props,\n materialProps,\n image,\n shape,\n rect,\n colorRamp,\n colorInitialRamp,\n baseColor: particleColor,\n seed: seed.value,\n source,\n options,\n }),\n );\n }\n return particlePreviewHtml(\n count,\n rect,\n image,\n color,\n minScale,\n maxScale,\n shape,\n colorInitialRamp ?? colorRamp,\n seed.value,\n particleColor,\n additiveBlend,\n );\n}\n\nexport function assignPlaceholder2DStyles(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n kind: string,\n): void {\n attributes[\"data-godot-resource-kind\"] = kind;\n attributes[\"data-godot-placeholder\"] = \"true\";\n assignResourceRefAttributes(\n attributes,\n props.process_material,\n source,\n options,\n \"process-material\",\n );\n assignResourceRefAttributes(attributes, props.mesh, source, options, \"mesh\");\n const image = resolveTextureImage(attributes, props, source, options, kind);\n const rect = asRect2(props.visibility_rect) ?? asRect2(props.rect);\n if (rect) {\n const left = cssSize(style.left) ?? 0;\n const top = cssSize(style.top) ?? 0;\n style.left = `${round(left + rect.x)}px`;\n style.top = `${round(top + rect.y)}px`;\n style.width = `${round(Math.max(1, rect.width))}px`;\n style.height = `${round(Math.max(1, rect.height))}px`;\n } else if (image.size) {\n style.width = `${round(Math.max(1, image.size.width))}px`;\n style.height = `${round(Math.max(1, image.size.height))}px`;\n } else if (cssSize(style.width) === 0 && cssSize(style.height) === 0) {\n style.width = \"1px\";\n style.height = \"1px\";\n }\n}\n\nfunction spriteSourceRect(\n props: Record<string, GodotVariant>,\n image: GodotResolvedResource,\n): { x: number; y: number; width: number; height: number } | undefined {\n const regionEnabled = asBoolean(props.region_enabled) ?? false;\n const spriteRegion = regionEnabled ? asRect2(props.region_rect) : undefined;\n const baseX = image.region?.x ?? 0;\n const baseY = image.region?.y ?? 0;\n const baseWidth =\n spriteRegion?.width ?? image.region?.width ?? image.size?.width;\n const baseHeight =\n spriteRegion?.height ?? image.region?.height ?? image.size?.height;\n if (!baseWidth || !baseHeight) {\n return undefined;\n }\n const hframes = Math.max(1, Math.round(asNumber(props.hframes) ?? 1));\n const vframes = Math.max(1, Math.round(asNumber(props.vframes) ?? 1));\n const frame = spriteFrame(props, hframes, vframes);\n const frameWidth = baseWidth / hframes;\n const frameHeight = baseHeight / vframes;\n return {\n x: baseX + (spriteRegion?.x ?? 0) + (frame % hframes) * frameWidth,\n y:\n baseY +\n (spriteRegion?.y ?? 0) +\n Math.floor(frame / hframes) * frameHeight,\n width: frameWidth,\n height: frameHeight,\n };\n}\n\nfunction spriteFrame(\n props: Record<string, GodotVariant>,\n hframes: number,\n vframes: number,\n): number {\n const explicitFrame = asNumber(props.frame);\n if (explicitFrame !== undefined) {\n return Math.max(\n 0,\n Math.min(hframes * vframes - 1, Math.floor(explicitFrame)),\n );\n }\n const coords = asVector2(props.frame_coords);\n if (coords) {\n return Math.max(\n 0,\n Math.min(\n hframes * vframes - 1,\n Math.floor(coords.y) * hframes + Math.floor(coords.x),\n ),\n );\n }\n return 0;\n}\n\nfunction assignTextureMetadata(\n style: Record<string, string>,\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n): void {\n const repeat = asNumber(props.texture_repeat);\n const filter = asNumber(props.texture_filter);\n if (repeat !== undefined) {\n attributes[\"data-godot-texture-repeat\"] = String(repeat);\n }\n if (filter !== undefined) {\n attributes[\"data-godot-texture-filter\"] = String(filter);\n if (filter === 1) {\n style[\"image-rendering\"] = \"pixelated\";\n }\n }\n}\n\nfunction textureRepeat(value: number | undefined): string {\n return value === 1 || value === 2 ? \"repeat\" : \"no-repeat\";\n}\n\nfunction lineCap(\n props: Record<string, GodotVariant>,\n closed: boolean,\n): \"butt\" | \"round\" | \"square\" {\n if (closed) {\n return \"butt\";\n }\n const begin = asNumber(props.begin_cap_mode) ?? 0;\n const end = asNumber(props.end_cap_mode) ?? begin;\n if (begin === 2 || end === 2) {\n return \"round\";\n }\n if (begin === 1 || end === 1) {\n return \"square\";\n }\n return \"butt\";\n}\n\nfunction lineJoin(\n props: Record<string, GodotVariant>,\n): \"miter\" | \"bevel\" | \"round\" {\n const joint = asNumber(props.joint_mode) ?? 0;\n if (joint === 1) {\n return \"bevel\";\n }\n if (joint === 2) {\n return \"round\";\n }\n return \"miter\";\n}\n\nfunction lineGradient(\n value: GodotVariant | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): { id: string; stops: string } | undefined {\n const resource = resolvedResource(value, source, options);\n const stops = gradientStops(resource, source, options);\n if (stops.length === 0) {\n return undefined;\n }\n return {\n id: `godot-line-gradient-${Math.abs(hashString(JSON.stringify(stops)))}`,\n stops: stops\n .map(\n (stop) =>\n `<stop offset=\"${round(stop.offset * 100)}%\" stop-color=\"${escapeAttribute(stop.color)}\"/>`,\n )\n .join(\"\"),\n };\n}\n\nfunction gradientStops(\n resource: GodotResolvedResource | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): Array<{ offset: number; color: string }> {\n return gradientColorStops(resource, source, options).map((stop) => ({\n offset: stop.offset,\n color: colorToCss(stop.color),\n }));\n}\n\ntype ParticleKind = \"CPUParticles2D\" | \"GPUParticles2D\";\ntype Vector2 = { x: number; y: number };\ntype Vector3 = { x: number; y: number; z: number };\ntype Rgba = { r: number; g: number; b: number; a: number };\ntype GradientColorStop = { offset: number; color: Rgba };\ntype ParticleShape = {\n shape: number;\n name: string;\n offset: Vector2;\n scale: Vector2;\n boxExtents: Vector2;\n sphereRadius: number;\n ringRadius: number;\n ringInnerRadius: number;\n ringHeight: number;\n};\n\nfunction gradientColorStops(\n resource: GodotResolvedResource | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): GradientColorStop[] {\n const props = resource?.document?.properties;\n if (!props) {\n return [];\n }\n const type =\n resource.type ?? asString(resource.document?.header?.attributes.type);\n if (type === \"GradientTexture1D\" || type === \"GradientTexture2D\") {\n const gradientRef = asResourceRef(props.gradient);\n if (!gradientRef) {\n return [];\n }\n return gradientColorStops(\n normalizeResource(options.resolveResource?.(gradientRef, source)),\n source,\n options,\n );\n }\n const colors = packedColorValues(props.colors);\n if (colors.length === 0) {\n return [];\n }\n const offsets = packedNumberArray(props.offsets);\n return colors.map((color, index) => ({\n offset: clamp(\n offsets[index] ?? (colors.length === 1 ? 0 : index / (colors.length - 1)),\n 0,\n 1,\n ),\n color,\n }));\n}\n\nfunction particleFallbackRect(\n kind: ParticleKind,\n image: GodotResolvedResource,\n shape: ParticleShape,\n): { x: number; y: number; width: number; height: number } {\n const textureSize = image.region ?? image.size;\n const padX = Math.max(8, (textureSize?.width ?? 8) / 2);\n const padY = Math.max(8, (textureSize?.height ?? 8) / 2);\n const bounds = particleShapeBounds(shape);\n if (bounds) {\n return {\n x: bounds.x - padX,\n y: bounds.y - padY,\n width: Math.max(1, bounds.width + padX * 2),\n height: Math.max(1, bounds.height + padY * 2),\n };\n }\n const width = Math.max(\n 32,\n (image.size?.width ?? image.region?.width ?? 16) * 4,\n );\n const height = Math.max(\n 32,\n (image.size?.height ?? image.region?.height ?? 16) * 4,\n );\n if (kind === \"GPUParticles2D\") {\n return {\n x: -Math.max(100, width / 2),\n y: -Math.max(100, height / 2),\n width: Math.max(200, width),\n height: Math.max(200, height),\n };\n }\n return { x: -width / 2, y: -height / 2, width, height };\n}\n\nfunction particlePreviewHtml(\n count: number,\n rect: { x: number; y: number; width: number; height: number },\n image: GodotResolvedResource,\n color: string,\n minScale: number,\n maxScale: number,\n shape: ParticleShape,\n colorRamp: GradientColorStop[] | undefined,\n seed: number,\n textureTint: Rgba | undefined,\n additive: boolean,\n): string {\n const textureSize = image.region ?? image.size;\n const isTextured = Boolean(image.url);\n const baseWidth = image.url\n ? (textureSize?.width ?? 6)\n : Math.max(3, Math.min(24, textureSize?.width ?? 6));\n const baseHeight = image.url\n ? (textureSize?.height ?? 6)\n : Math.max(3, Math.min(24, textureSize?.height ?? 6));\n const particles: string[] = [];\n for (let index = 0; index < count; index += 1) {\n const sampled = sampleParticlePosition(shape, seed, index);\n const scale =\n minScale + (maxScale - minScale) * deterministicUnit(seed, index, 89);\n const width = Math.max(1, baseWidth * scale);\n const height = Math.max(1, baseHeight * scale);\n const left = sampled.x - rect.x - width / 2;\n const top = sampled.y - rect.y - height / 2;\n const previewOpacity = isTextured\n ? texturePreviewOpacity(textureTint)\n : round(0.55 + deterministicUnit(seed, index, 131) * 0.45);\n const particleStyle: Record<string, string> = {\n position: \"absolute\",\n left: `${round(isTextured ? left : clamp(left, 0, Math.max(0, rect.width - width)))}px`,\n top: `${round(isTextured ? top : clamp(top, 0, Math.max(0, rect.height - height)))}px`,\n width: `${round(width)}px`,\n height: `${round(height)}px`,\n opacity: `${previewOpacity}`,\n // Additive systems glow: composite the span onto the scene with `plus-lighter` (the CSS\n // analogue of BLEND_MODE_ADD) so bright sparks add light instead of painting flat over.\n ...(additive ? { \"mix-blend-mode\": \"plus-lighter\" } : {}),\n \"background-color\":\n colorRamp && colorRamp.length > 0\n ? sampleGradientCss(colorRamp, deterministicUnit(seed, index, 157))\n : color,\n \"border-radius\": \"999px\",\n };\n if (image.url) {\n particleStyle[\"background-image\"] = `url(\"${cssUrl(image.url)}\")`;\n particleStyle[\"background-size\"] = \"100% 100%\";\n particleStyle[\"background-repeat\"] = \"no-repeat\";\n particleStyle[\"border-radius\"] = \"0\";\n // The live particle color is `color_ramp(life) × modulate`; the texture only supplies the\n // shape/luminance. Fold the sampled ramp into the tint so a ramped ember (white modulate,\n // red→black ramp) previews red/black instead of a flat base color — matching what the WebGL\n // runtime draws. Without a ramp this reduces to the plain texture modulate.\n const rampSample =\n colorRamp && colorRamp.length > 0\n ? sampleGradientRgba(colorRamp, deterministicUnit(seed, index, 157))\n : undefined;\n const tint = rampSample\n ? textureTint\n ? {\n r: rampSample.r * textureTint.r,\n g: rampSample.g * textureTint.g,\n b: rampSample.b * textureTint.b,\n a: 1,\n }\n : rampSample\n : textureTint;\n if (tint) {\n particleStyle[\"background-color\"] = colorToCss(\n textureModulateTint(tint),\n );\n particleStyle[\"background-blend-mode\"] = \"multiply\";\n particleStyle[\"mask-image\"] = `url(\"${cssUrl(image.url)}\")`;\n particleStyle[\"mask-size\"] = \"100% 100%\";\n particleStyle[\"mask-repeat\"] = \"no-repeat\";\n particleStyle[\"-webkit-mask-image\"] = `url(\"${cssUrl(image.url)}\")`;\n particleStyle[\"-webkit-mask-size\"] = \"100% 100%\";\n particleStyle[\"-webkit-mask-repeat\"] = \"no-repeat\";\n } else {\n particleStyle[\"background-color\"] = \"transparent\";\n }\n }\n const overlay =\n image.url && textureTint\n ? `<span aria-hidden=\"true\" data-godot-particle-tint=\"multiply\" style=\"${escapeAttribute(\n styleAttribute({\n position: \"absolute\",\n inset: \"0\",\n \"background-color\": \"transparent\",\n opacity: \"1\",\n \"pointer-events\": \"none\",\n }),\n )}\"></span>`\n : \"\";\n particles.push(\n `<span aria-hidden=\"true\" data-godot-particle=\"true\" style=\"${escapeAttribute(styleAttribute(particleStyle))}\">${overlay}</span>`,\n );\n }\n return particles.join(\"\");\n}\n\nfunction textureModulateTint(color: Rgba): Rgba {\n return {\n r: color.r * color.r,\n g: color.g * color.g,\n b: color.b * color.b,\n a: 1,\n };\n}\n\nfunction texturePreviewOpacity(color: Rgba | undefined): number {\n return round(clamp(color?.a ?? 1, 0, 1) * 0.75);\n}\n\nfunction sampleParticlePosition(\n shape: ParticleShape,\n seed: number,\n index: number,\n): Vector2 {\n const a = deterministicUnit(seed, index, 17);\n const b = deterministicUnit(seed, index, 53);\n let point: Vector2;\n if (shape.shape === 0) {\n point = { x: 0, y: 0 };\n } else if (shape.shape === 1 || shape.shape === 2) {\n const angle = a * Math.PI * 2;\n const radius = shape.sphereRadius * (shape.shape === 2 ? 1 : Math.sqrt(b));\n point = { x: Math.cos(angle) * radius, y: Math.sin(angle) * radius };\n } else if (shape.shape === 3) {\n point = {\n x: (a * 2 - 1) * shape.boxExtents.x,\n y: (b * 2 - 1) * shape.boxExtents.y,\n };\n } else if (shape.shape === 6) {\n const angle = a * Math.PI * 2;\n const outer = Math.max(shape.ringRadius, shape.ringInnerRadius, 0.001);\n const inner = Math.max(0, Math.min(shape.ringInnerRadius, outer));\n const radius = Math.sqrt(\n b * (outer * outer - inner * inner) + inner * inner,\n );\n const y =\n ((deterministicUnit(seed, index, 71) * 2 - 1) * shape.ringHeight) / 2;\n point = { x: Math.cos(angle) * radius, y: Math.sin(angle) * radius + y };\n } else {\n point = {\n x:\n (a * 2 - 1) *\n Math.max(\n 16,\n shape.boxExtents.x || shape.sphereRadius || shape.ringRadius,\n ),\n y:\n (b * 2 - 1) *\n Math.max(\n 16,\n shape.boxExtents.y || shape.sphereRadius || shape.ringRadius,\n ),\n };\n }\n return {\n x: point.x * shape.scale.x + shape.offset.x,\n y: point.y * shape.scale.y + shape.offset.y,\n };\n}\n\nfunction deterministicUnit(seed: number, index: number, salt: number): number {\n let value = (seed ^ (salt * 374761393) ^ ((index + 1) * 668265263)) >>> 0;\n value = Math.imul(value ^ (value >>> 15), 2246822519) >>> 0;\n value = Math.imul(value ^ (value >>> 13), 3266489917) >>> 0;\n return ((value ^ (value >>> 16)) >>> 0) / 4294967296;\n}\n\nfunction assignParticleMaterialMetadata(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant> | undefined,\n prefix: string,\n): void {\n if (!props) {\n return;\n }\n for (const name of [\n \"scale_min\",\n \"scale_max\",\n \"scale_amount_min\",\n \"scale_amount_max\",\n \"emission_shape\",\n \"emission_sphere_radius\",\n \"emission_ring_radius\",\n \"emission_ring_inner_radius\",\n \"emission_ring_height\",\n \"initial_velocity_min\",\n \"initial_velocity_max\",\n \"spread\",\n ]) {\n const value = asNumber(props[name]);\n if (value !== undefined) {\n attributes[`data-godot-${prefix}-${name.replace(/_/g, \"-\")}`] =\n String(value);\n }\n }\n assignVectorValueAttribute(\n attributes,\n props,\n \"emission_shape_offset\",\n `data-godot-${prefix}-emission-shape-offset`,\n );\n assignVectorValueAttribute(\n attributes,\n props,\n \"emission_shape_scale\",\n `data-godot-${prefix}-emission-shape-scale`,\n );\n assignVectorValueAttribute(\n attributes,\n props,\n \"emission_box_extents\",\n `data-godot-${prefix}-emission-box-extents`,\n );\n assignVectorValueAttribute(\n attributes,\n props,\n \"emission_rect_extents\",\n `data-godot-${prefix}-emission-rect-extents`,\n );\n assignVectorValueAttribute(\n attributes,\n props,\n \"gravity\",\n `data-godot-${prefix}-gravity`,\n );\n for (const name of [\n \"particle_flag_align_y\",\n \"particle_flag_rotate_y\",\n \"particle_flag_disable_z\",\n \"particle_flag_damping_as_friction\",\n ]) {\n const value = asBoolean(props[name]);\n if (value !== undefined) {\n attributes[`data-godot-${prefix}-${name.replace(/_/g, \"-\")}`] =\n String(value);\n }\n }\n}\n\nfunction assignParticleTimingMetadata(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n): void {\n for (const name of [\n \"lifetime\",\n \"preprocess\",\n \"speed_scale\",\n \"explosiveness\",\n \"randomness\",\n \"fixed_fps\",\n \"seed\",\n \"trail_lifetime\",\n \"trail_sections\",\n \"trail_section_subdivisions\",\n ]) {\n assignNumberAttribute(\n attributes,\n props,\n name,\n `data-godot-particle-${name.replace(/_/g, \"-\")}`,\n );\n }\n for (const name of [\n \"one_shot\",\n \"local_coords\",\n \"fract_delta\",\n \"interpolate\",\n \"trail_enabled\",\n \"use_fixed_seed\",\n ]) {\n assignBooleanAttribute(\n attributes,\n props,\n name,\n `data-godot-particle-${name.replace(/_/g, \"-\")}`,\n );\n }\n}\n\nfunction particleShape(\n props: Record<string, GodotVariant> | undefined,\n): ParticleShape {\n const shape = Math.round(asNumber(props?.emission_shape) ?? 0);\n const offset = vector2FromAny(props?.emission_shape_offset) ?? { x: 0, y: 0 };\n const scale = vector2FromAny(props?.emission_shape_scale) ?? { x: 1, y: 1 };\n const boxExtents = vector2FromAny(props?.emission_box_extents) ??\n vector2FromAny(props?.emission_rect_extents) ?? { x: 0, y: 0 };\n const sphereRadius = Math.max(\n 0,\n asNumber(props?.emission_sphere_radius) ?? 0,\n );\n const ringRadius = Math.max(0, asNumber(props?.emission_ring_radius) ?? 0);\n const ringInnerRadius = Math.max(\n 0,\n asNumber(props?.emission_ring_inner_radius) ?? 0,\n );\n const ringHeight = Math.max(0, asNumber(props?.emission_ring_height) ?? 0);\n return {\n shape,\n name: particleShapeName(shape),\n offset,\n scale,\n boxExtents,\n sphereRadius,\n ringRadius,\n ringInnerRadius,\n ringHeight,\n };\n}\n\nfunction particleShapeName(shape: number): string {\n switch (shape) {\n case 0:\n return \"point\";\n case 1:\n return \"sphere\";\n case 2:\n return \"sphere-surface\";\n case 3:\n return \"box\";\n case 4:\n return \"points\";\n case 5:\n return \"directed-points\";\n case 6:\n return \"ring\";\n default:\n return \"unknown\";\n }\n}\n\nfunction assignParticleShapeMetadata(\n attributes: Record<string, string>,\n shape: ParticleShape,\n): void {\n attributes[\"data-godot-particle-emission-shape\"] = String(shape.shape);\n attributes[\"data-godot-particle-emission-shape-name\"] = shape.name;\n attributes[\"data-godot-particle-emission-shape-offset\"] =\n `${shape.offset.x},${shape.offset.y}`;\n attributes[\"data-godot-particle-emission-shape-scale\"] =\n `${shape.scale.x},${shape.scale.y}`;\n const bounds = particleShapeBounds(shape);\n if (bounds) {\n attributes[\"data-godot-particle-emission-shape-bounds\"] =\n `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;\n }\n}\n\nfunction particleShapeBounds(\n shape: ParticleShape,\n): { x: number; y: number; width: number; height: number } | undefined {\n if (shape.shape === 0) {\n return { x: shape.offset.x, y: shape.offset.y, width: 0, height: 0 };\n }\n if (shape.shape === 1 || shape.shape === 2) {\n const radiusX = shape.sphereRadius * Math.abs(shape.scale.x);\n const radiusY = shape.sphereRadius * Math.abs(shape.scale.y);\n return {\n x: shape.offset.x - radiusX,\n y: shape.offset.y - radiusY,\n width: radiusX * 2,\n height: radiusY * 2,\n };\n }\n if (\n shape.shape === 3 &&\n (shape.boxExtents.x !== 0 || shape.boxExtents.y !== 0)\n ) {\n const extentX = Math.abs(shape.boxExtents.x * shape.scale.x);\n const extentY = Math.abs(shape.boxExtents.y * shape.scale.y);\n return {\n x: shape.offset.x - extentX,\n y: shape.offset.y - extentY,\n width: extentX * 2,\n height: extentY * 2,\n };\n }\n if (shape.shape === 6) {\n const radiusX =\n Math.max(shape.ringRadius, shape.ringInnerRadius) *\n Math.abs(shape.scale.x);\n const radiusY =\n (Math.max(shape.ringRadius, shape.ringInnerRadius) +\n shape.ringHeight / 2) *\n Math.abs(shape.scale.y);\n return {\n x: shape.offset.x - radiusX,\n y: shape.offset.y - radiusY,\n width: radiusX * 2,\n height: radiusY * 2,\n };\n }\n return undefined;\n}\n\nfunction particleGradientStops(\n value: GodotVariant | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): GradientColorStop[] | undefined {\n const resource = resolvedResource(value, source, options);\n const stops = gradientColorStops(resource, source, options);\n return stops.length > 0 ? stops : undefined;\n}\n\nfunction assignParticleRampMetadata(\n attributes: Record<string, string>,\n name: string,\n stops: GradientColorStop[] | undefined,\n): void {\n if (!stops || stops.length === 0) {\n return;\n }\n attributes[`data-godot-particle-${name}-stops`] = stops\n .map((stop) => `${round(stop.offset)}:${colorToCss(stop.color)}`)\n .join(\"|\");\n}\n\nfunction particleSeed(\n props: Record<string, GodotVariant>,\n attributes: Record<string, string>,\n kind: ParticleKind,\n): { value: number; source: \"fixed\" | \"derived\" } {\n if (asBoolean(props.use_fixed_seed) === true) {\n return { value: Math.trunc(asNumber(props.seed) ?? 0), source: \"fixed\" };\n }\n const key = [\n attributes[\"data-godot-path\"],\n kind,\n attributes[\"data-godot-texture-ref\"],\n attributes[\"data-godot-process-material-ref\"],\n attributes[\"data-godot-color-ramp-ref\"],\n attributes[\"data-godot-color-initial-ramp-ref\"],\n ]\n .filter(Boolean)\n .join(\"|\");\n return { value: hashString(key || kind) >>> 0, source: \"derived\" };\n}\n\n// ---- runtime (live particle simulation) serialization ----------------------\n\nfunction isParticleRuntimeEnabled(\n options: GodotHtmlRenderOptions,\n nodePath: string,\n materialPath: string | undefined,\n texturePath: string | undefined,\n): boolean {\n if (!options.enableParticles) {\n return false;\n }\n if (nodePath && options.particleNodesByPath?.[nodePath]) {\n return true;\n }\n const ids = options.particleIds ?? [];\n if (ids.length === 0) {\n return false;\n }\n return (\n shaderIdListMatches(ids, materialPath, undefined) ||\n shaderIdListMatches(ids, texturePath, undefined)\n );\n}\n\n// Build the `data-godot-particle-specs` payload — the full simulation config from\n// the node + its ParticleProcessMaterial (`materialProps`, which is the process\n// material for GPU particles or the node itself for CPU particles), the resolved\n// texture, the CanvasItemMaterial blend/flipbook, and the decoded ramps/curves.\nfunction serializeParticleConfig(args: {\n kind: ParticleKind;\n props: Record<string, GodotVariant>;\n materialProps: Record<string, GodotVariant> | undefined;\n image: GodotResolvedResource;\n shape: ParticleShape;\n rect: { x: number; y: number; width: number; height: number };\n colorRamp: GradientColorStop[] | undefined;\n colorInitialRamp: GradientColorStop[] | undefined;\n baseColor: Rgba | undefined;\n seed: number;\n source: GodotNode;\n options: GodotHtmlRenderOptions;\n}): ParticleSpecConfig {\n const {\n kind,\n props,\n materialProps: m,\n image,\n shape,\n rect,\n colorRamp,\n colorInitialRamp,\n baseColor,\n seed,\n source,\n options,\n } = args;\n const material = resolvedResource(props.material, source, options);\n const materialType =\n material?.type ?? asString(material?.document?.header?.attributes.type);\n const canvasItem =\n materialType === \"CanvasItemMaterial\"\n ? material?.document?.properties\n : undefined;\n const animEnabled = asBoolean(canvasItem?.particles_animation) ?? false;\n const hframes = animEnabled\n ? Math.max(\n 1,\n Math.round(asNumber(canvasItem?.particles_anim_h_frames) ?? 1),\n )\n : 1;\n const vframes = animEnabled\n ? Math.max(\n 1,\n Math.round(asNumber(canvasItem?.particles_anim_v_frames) ?? 1),\n )\n : 1;\n const texSize = image.region ?? image.size;\n // The base colour goes into the blob BOTH as authored (`baseColor`, raw sRGB) and as the\n // target backend uploads it (`baseColorRender`). `normalizeParticleConfig` recomputes the\n // latter from the former on parse, so the blob cannot carry a stale or lying value.\n const godotRenderer = normalizeGodotRenderer(options.godotRenderer);\n const baseColorRgba: [number, number, number, number] = baseColor\n ? [baseColor.r, baseColor.g, baseColor.b, baseColor.a]\n : [1, 1, 1, 1];\n // Only a real `ParticleProcessMaterial.color` takes the RD linearization. `m` is the\n // process material for GPUParticles2D and the NODE for CPUParticles2D, so the kind check\n // is what separates `ParticleProcessMaterial.color` from `CPUParticles2D.color`; a\n // GPUParticles2D with no process material falls back to `modulate`, which Godot also\n // leaves in sRGB.\n const baseColorFromProcessMaterial =\n kind === \"GPUParticles2D\" && rgbaValue(m?.color) !== undefined;\n return {\n kind,\n godotRenderer,\n amount: Math.max(1, Math.round(asNumber(props.amount) ?? 8)),\n amountRatio: clamp(asNumber(props.amount_ratio) ?? 1, 0, 1),\n lifetime: Math.max(0.01, asNumber(props.lifetime) ?? 1),\n lifetimeRandomness: clamp(\n asNumber(m?.lifetime_randomness) ??\n asNumber(props.lifetime_randomness) ??\n 0,\n 0,\n 1,\n ),\n oneShot: asBoolean(props.one_shot) ?? false,\n emitting: asBoolean(props.emitting) ?? true,\n explosiveness: clamp(asNumber(props.explosiveness) ?? 0, 0, 1),\n randomness: clamp(asNumber(props.randomness) ?? 0, 0, 1),\n preprocess: Math.max(0, asNumber(props.preprocess) ?? 0),\n speedScale: asNumber(props.speed_scale) ?? 1,\n fixedFps: Math.max(0, Math.round(asNumber(props.fixed_fps) ?? 0)),\n localCoords: asBoolean(props.local_coords) ?? false,\n drawOrder: Math.round(asNumber(props.draw_order) ?? 0),\n seed,\n emissionShape: shape.shape,\n emissionOffset: [shape.offset.x, shape.offset.y],\n emissionScale: [shape.scale.x, shape.scale.y],\n emissionSphereRadius: shape.sphereRadius,\n emissionRingRadius: shape.ringRadius,\n emissionRingInnerRadius: shape.ringInnerRadius,\n emissionRingHeight: shape.ringHeight,\n emissionBoxExtents: [shape.boxExtents.x, shape.boxExtents.y],\n direction: vec2OrDefault(m?.direction, [1, 0]),\n spread: asNumber(m?.spread) ?? 45,\n initialVelocityMin: asNumber(m?.initial_velocity_min) ?? 0,\n initialVelocityMax: asNumber(m?.initial_velocity_max) ?? 0,\n angleMin: asNumber(m?.angle_min) ?? 0,\n angleMax: asNumber(m?.angle_max) ?? 0,\n angularVelocityMin: asNumber(m?.angular_velocity_min) ?? 0,\n angularVelocityMax: asNumber(m?.angular_velocity_max) ?? 0,\n gravity: vec2OrDefault(m?.gravity, [0, 980]),\n linearAccelMin: asNumber(m?.linear_accel_min) ?? 0,\n linearAccelMax: asNumber(m?.linear_accel_max) ?? 0,\n radialAccelMin: asNumber(m?.radial_accel_min) ?? 0,\n radialAccelMax: asNumber(m?.radial_accel_max) ?? 0,\n tangentialAccelMin: asNumber(m?.tangential_accel_min) ?? 0,\n tangentialAccelMax: asNumber(m?.tangential_accel_max) ?? 0,\n dampingMin: asNumber(m?.damping_min) ?? 0,\n dampingMax: asNumber(m?.damping_max) ?? 0,\n dampingAsFriction: asBoolean(m?.particle_flag_damping_as_friction) ?? false,\n orbitVelocityMin: asNumber(m?.orbit_velocity_min) ?? 0,\n orbitVelocityMax: asNumber(m?.orbit_velocity_max) ?? 0,\n scaleMin: asNumber(m?.scale_min) ?? asNumber(props.scale_amount_min) ?? 1,\n scaleMax:\n asNumber(m?.scale_max) ??\n asNumber(props.scale_amount_max) ??\n asNumber(m?.scale_min) ??\n 1,\n hueVariationMin: asNumber(m?.hue_variation_min) ?? 0,\n hueVariationMax: asNumber(m?.hue_variation_max) ?? 0,\n alignY: asBoolean(m?.particle_flag_align_y) ?? false,\n baseColor: baseColorRgba,\n baseColorFromProcessMaterial,\n baseColorRender: linearizeParticleBaseColor(\n baseColorRgba,\n godotRenderer,\n baseColorFromProcessMaterial,\n ),\n // Draw-space origin for the runtime: a particle at simulation (0,0) — the emitter /\n // node origin — lands at the node's visual origin (canvas pixel `pad`, since the overlay\n // canvas is positioned symmetrically at `-pad`). Kept at 0: the per-particle emission\n // spread is baked into the simulated positions, and coupling the DRAW origin to `-rect`\n // shifted a point-emission burst OUTSIDE the sprite-extent-sized canvas (clipping).\n originX: 0,\n originY: 0,\n // Screen offset of the overlay CANVAS (not the draw origin): the CSS-`<span>` fallback\n // renders each particle at `self-layer + (sampled - rect)`, so its emission center sits\n // at `-rect.(x,y)` from the node-box corner — near screen-center for a background\n // emitter. The WebGL canvas otherwise centers emission on the node-box corner (0,0) →\n // top-left. Shifting the whole canvas by `-rect.(x,y)` moves the WebGL emission center to\n // the SAME place as the spans, in both layout paths, with no clipping (the canvas moves\n // with its particles). `rect` = the emitter's visibility/emission box (top-left ≈ −half-extent).\n boxOffsetX: -rect.x,\n boxOffsetY: -rect.y,\n textureUrl: image.url ?? null,\n textureWidth: texSize?.width ?? 0,\n textureHeight: texSize?.height ?? 0,\n hframes,\n vframes,\n animLoop: asBoolean(canvasItem?.particles_anim_loop) ?? false,\n animSpeedMin: asNumber(m?.anim_speed_min) ?? 0,\n animSpeedMax: asNumber(m?.anim_speed_max) ?? 0,\n animOffsetMin: asNumber(m?.anim_offset_min) ?? 0,\n animOffsetMax: asNumber(m?.anim_offset_max) ?? 0,\n blendMode: Math.round(asNumber(canvasItem?.blend_mode) ?? 0),\n colorRamp: rampToSpec(colorRamp),\n colorInitialRamp: rampToSpec(colorInitialRamp),\n scaleCurve: curvePoints(\n m?.scale_curve ?? m?.scale_amount_curve,\n source,\n options,\n ),\n scaleCurveX: curvePoints(m?.scale_curve_x, source, options),\n scaleCurveY: curvePoints(m?.scale_curve_y, source, options),\n alphaCurve: curvePoints(m?.alpha_curve, source, options),\n hueCurve: curvePoints(m?.hue_variation_curve, source, options),\n };\n}\n\nfunction vec2OrDefault(\n value: GodotVariant | undefined,\n fallback: [number, number],\n): [number, number] {\n const vector = vector2FromAny(value);\n return vector ? [vector.x, vector.y] : fallback;\n}\n\nfunction rampToSpec(\n stops: GradientColorStop[] | undefined,\n): GradientStop[] | undefined {\n if (!stops || stops.length === 0) {\n return undefined;\n }\n return stops.map((stop) => ({\n offset: stop.offset,\n color: [stop.color.r, stop.color.g, stop.color.b, stop.color.a] as [\n number,\n number,\n number,\n number,\n ],\n }));\n}\n\n// Decode a Curve / CurveTexture / CurveXYZTexture resource to its control points.\n// Godot's `Curve._data` is a flat array of `[Vector2(x,y), left_tan, right_tan,\n// left_mode, right_mode]` per point; the Vector2 entries (the only Vector2s in the\n// array) are the points in order. Linear interpolation between them is the bar here.\nfunction curvePoints(\n value: GodotVariant | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): CurvePoint[] | undefined {\n const resource = resolvedResource(value, source, options);\n if (!resource) {\n return undefined;\n }\n const type =\n resource.type ?? asString(resource.document?.header?.attributes.type);\n let curveProps = resource.document?.properties;\n if (type === \"CurveTexture\") {\n curveProps =\n resolvedResource(curveProps?.curve, source, options)?.document\n ?.properties ?? curveProps;\n } else if (type === \"CurveXYZTexture\") {\n curveProps =\n resolvedResource(\n curveProps?.curve_x ?? curveProps?.curve_y ?? curveProps?.curve_z,\n source,\n options,\n )?.document?.properties ?? curveProps;\n }\n const points = extractCurvePoints(curveProps?._data);\n return points.length > 0 ? points : undefined;\n}\n\nfunction extractCurvePoints(value: GodotVariant | undefined): CurvePoint[] {\n const items = Array.isArray(value)\n ? value\n : value && isCallValue(value)\n ? value.args\n : [];\n const points: CurvePoint[] = [];\n for (const item of items) {\n const point = asVector2(item as GodotVariant);\n if (point) {\n points.push({ x: point.x, y: point.y });\n }\n }\n return points;\n}\n\nfunction sampleGradientRgba(stops: GradientColorStop[], offset: number): Rgba {\n const ordered = [...stops].sort((left, right) => left.offset - right.offset);\n if (ordered.length === 1 || offset <= ordered[0].offset) {\n return ordered[0].color;\n }\n for (let index = 1; index < ordered.length; index += 1) {\n const right = ordered[index];\n const left = ordered[index - 1];\n if (offset <= right.offset) {\n const span = Math.max(0.0001, right.offset - left.offset);\n const t = clamp((offset - left.offset) / span, 0, 1);\n return {\n r: left.color.r + (right.color.r - left.color.r) * t,\n g: left.color.g + (right.color.g - left.color.g) * t,\n b: left.color.b + (right.color.b - left.color.b) * t,\n a: left.color.a + (right.color.a - left.color.a) * t,\n };\n }\n }\n return ordered[ordered.length - 1].color;\n}\n\nfunction sampleGradientCss(stops: GradientColorStop[], offset: number): string {\n return colorToCss(sampleGradientRgba(stops, offset));\n}\n\nfunction colorToCss(color: Rgba): string {\n return `rgba(${Math.round(clamp(color.r, 0, 1) * 255)}, ${Math.round(clamp(color.g, 0, 1) * 255)}, ${Math.round(clamp(color.b, 0, 1) * 255)}, ${round(clamp(color.a, 0, 1))})`;\n}\n\nfunction vector2FromAny(value: GodotVariant | undefined): Vector2 | undefined {\n const vector2 = asVector2(value);\n if (vector2) {\n return vector2;\n }\n const vector3 = asVector3(value);\n return vector3 ? { x: vector3.x, y: vector3.y } : undefined;\n}\n\nfunction asVector3(value: GodotVariant | undefined): Vector3 | undefined {\n if (\n !value ||\n typeof value !== \"object\" ||\n Array.isArray(value) ||\n !(\"type\" in value) ||\n (value.type !== \"Vector3\" && value.type !== \"Vector3i\") ||\n !Array.isArray(value.args)\n ) {\n return undefined;\n }\n const [x, y, z] = value.args as unknown[];\n return typeof x === \"number\" &&\n typeof y === \"number\" &&\n typeof z === \"number\" &&\n Number.isFinite(x) &&\n Number.isFinite(y) &&\n Number.isFinite(z)\n ? { x, y, z }\n : undefined;\n}\n\nfunction assignVectorValueAttribute(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n property: string,\n attribute: string,\n): void {\n const vector = vector2FromAny(props[property]);\n if (vector) {\n attributes[attribute] = `${vector.x},${vector.y}`;\n }\n}\n\nfunction assignNestedResourceRefAttribute(\n attributes: Record<string, string>,\n resource: GodotResolvedResource | undefined,\n property: string,\n name: string,\n): void {\n const ref = asResourceRef(resource?.document?.properties[property]);\n if (ref) {\n attributes[`data-godot-${name}-ref`] = `${ref.type}:${ref.id ?? ref.path}`;\n }\n}\n\nfunction resolveTextureImage(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n kind: string,\n): GodotResolvedResource {\n attributes[\"data-godot-resource-kind\"] = kind;\n const texture = asResourceRef(props.texture);\n if (!texture) {\n return {};\n }\n attributes[\"data-godot-texture-ref\"] =\n `${texture.type}:${texture.id ?? texture.path}`;\n const image = imageResource(\n normalizeResource(options.resolveResource?.(texture, source)),\n options,\n source,\n );\n if (image.path) {\n attributes[\"data-godot-resource-path\"] = image.path;\n }\n return image;\n}\n\nfunction assignResourceRefAttributes(\n attributes: Record<string, string>,\n value: GodotVariant | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n name: string,\n): void {\n const ref = asResourceRef(value);\n if (!ref) {\n return;\n }\n attributes[`data-godot-${name}-ref`] = `${ref.type}:${ref.id ?? ref.path}`;\n const resource = normalizeResource(options.resolveResource?.(ref, source));\n const type =\n resource?.type ?? asString(resource?.document?.header?.attributes.type);\n if (type) {\n attributes[`data-godot-${name}-type`] = type;\n }\n if (resource?.path) {\n attributes[`data-godot-${name}-path`] = resource.path;\n }\n}\n\nfunction resolvedResource(\n value: GodotVariant | undefined,\n source: GodotNode,\n options: GodotHtmlRenderOptions,\n): GodotResolvedResource | undefined {\n const ref = asResourceRef(value);\n return ref\n ? normalizeResource(options.resolveResource?.(ref, source))\n : undefined;\n}\n\nfunction assignNumberAttribute(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n property: string,\n attribute: string,\n): void {\n const value = asNumber(props[property]);\n if (value !== undefined) {\n attributes[attribute] = String(value);\n }\n}\n\nfunction assignBooleanAttribute(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n property: string,\n attribute: string,\n): void {\n const value = asBoolean(props[property]);\n if (value !== undefined) {\n attributes[attribute] = String(value);\n }\n}\n\nfunction assignVectorAttribute(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n property: string,\n attribute: string,\n): void {\n const value = asVector2(props[property]);\n if (value) {\n attributes[attribute] = `${value.x},${value.y}`;\n }\n}\n\nfunction assignRectAttribute(\n attributes: Record<string, string>,\n props: Record<string, GodotVariant>,\n property: string,\n attribute: string,\n): void {\n const value = asRect2(props[property]);\n if (value) {\n attributes[attribute] =\n `${value.x},${value.y},${value.width},${value.height}`;\n }\n}\n\nfunction vector2Points(\n value: GodotVariant | undefined,\n): Array<{ x: number; y: number }> {\n if (!value) {\n return [];\n }\n if (Array.isArray(value)) {\n return value.flatMap((item) => {\n const point = asVector2(item);\n return point ? [point] : [];\n });\n }\n if (isCallValue(value) && value.type === \"PackedVector2Array\") {\n const points: Array<{ x: number; y: number }> = [];\n for (let index = 0; index + 1 < value.args.length; index += 2) {\n const x = value.args[index];\n const y = value.args[index + 1];\n if (typeof x === \"number\" && typeof y === \"number\") {\n points.push({ x, y });\n }\n }\n return points;\n }\n return [];\n}\n\nfunction packedNumberArray(value: GodotVariant | undefined): number[] {\n if (Array.isArray(value)) {\n return value.flatMap((item) => (typeof item === \"number\" ? [item] : []));\n }\n if (value && isCallValue(value)) {\n return value.args.flatMap((item) =>\n typeof item === \"number\" ? [item] : [],\n );\n }\n return [];\n}\n\nfunction packedColorValues(value: GodotVariant | undefined): Rgba[] {\n if (Array.isArray(value)) {\n return value.flatMap((item) => {\n const color = rgbaValue(item);\n return color ? [color] : [];\n });\n }\n if (value && isCallValue(value)) {\n const colors: Rgba[] = [];\n for (let index = 0; index + 3 < value.args.length; index += 4) {\n const color = rgbaValue({\n type: \"Color\",\n args: value.args\n .slice(index, index + 4)\n .filter((item): item is number => typeof item === \"number\"),\n });\n if (color) {\n colors.push(color);\n }\n }\n return colors;\n }\n return [];\n}\n\nfunction rgbaValue(value: GodotVariant | undefined): Rgba | undefined {\n if (\n !value ||\n typeof value !== \"object\" ||\n Array.isArray(value) ||\n !(\"type\" in value) ||\n value.type !== \"Color\" ||\n !Array.isArray(value.args)\n ) {\n return undefined;\n }\n const [r = 0, g = 0, b = 0, a = 1] = value.args;\n return typeof r === \"number\" &&\n typeof g === \"number\" &&\n typeof b === \"number\" &&\n typeof a === \"number\" &&\n Number.isFinite(r) &&\n Number.isFinite(g) &&\n Number.isFinite(b) &&\n Number.isFinite(a)\n ? { r, g, b, a }\n : undefined;\n}\n\nfunction hashString(value: string): number {\n let hash = 0;\n for (let index = 0; index < value.length; index += 1) {\n hash = ((hash << 5) - hash + value.charCodeAt(index)) | 0;\n }\n return hash;\n}\n\n// Variants whose `{ type, args }` shape is a known scalar — NOT an arbitrary\n// constructor. Excluding these preserves the old `kind === \"Call\"` semantics\n// (which only tagged unrecognized constructors like PackedVector2Array).\nconst SCALAR_VARIANT_TYPES = new Set([\n \"Vector2\",\n \"Vector2i\",\n \"Vector3\",\n \"Vector3i\",\n \"Vector4\",\n \"Vector4i\",\n \"Color\",\n \"Rect2\",\n \"Rect2i\",\n \"NodePath\",\n \"StringName\",\n \"ExtResource\",\n \"SubResource\",\n]);\n\nfunction isCallValue(value: GodotVariant): value is GodotCallVariant {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n \"type\" in value &&\n typeof value.type === \"string\" &&\n !SCALAR_VARIANT_TYPES.has(value.type) &&\n \"args\" in value &&\n Array.isArray((value as GodotCallVariant).args),\n );\n}\n","import {\n asBoolean,\n asString,\n type GodotNode,\n type GodotResourceRefValue,\n type GodotVariant,\n} from \"@godot-scene-web/core\";\nimport type {\n GodotRect,\n GodotSceneTree,\n GodotSceneTreeDiagnostic,\n GodotSceneTreeNode,\n} from \"@godot-scene-web/layout\";\nimport type {\n GodotResourceStatus,\n SceneGraph,\n SceneGraphNode,\n} from \"@godot-scene-web/scene-graph\";\nimport { godotSceneBaseCss } from \"./base-css\";\nimport { applyBrowserAnchorPositioning } from \"./browser-anchors\";\nimport {\n assignBrowserNativeLayout,\n assignBrowserNativeNodeLayout,\n type BrowserNativeParentContext,\n} from \"./browser-layout\";\nimport { assignContainerLayoutStyles } from \"./container-layout\";\nimport {\n type ResolvedContentScale,\n resolveContentScale,\n rewritePxLengths,\n scaleStyleRecord,\n} from \"./content-scale\";\nimport { round, safeClassSegment } from \"./css-values\";\nimport { assignMaterialAttributes, isShaderMaterialNode } from \"./material\";\nimport {\n assignBackgroundColor,\n assignDrawAttributes,\n assignOpacity,\n assignPointerEvents,\n assignPositionStyle,\n assignRangeStyles,\n assignSelfLayerFlip,\n assignTransform,\n assignZIndexStyle,\n} from \"./node-style\";\nimport {\n imageResource,\n normalizeResource,\n sourceNodeForLayout,\n uniqueFontFaces,\n} from \"./resources\";\nimport { assignInputStyleBoxStyles, assignPanelStyles } from \"./style-box\";\nimport { assignTextStyles, richTextLayeredHtml, textProp } from \"./text\";\nimport { resolveTextScale } from \"./text-scale\";\nimport { assignAnimatedSpriteStyles, assignTextureStyles } from \"./textures\";\nimport type {\n GodotHtmlFontFace,\n GodotHtmlModel,\n GodotHtmlNode,\n GodotHtmlRenderOptions,\n} from \"./types\";\nimport {\n assignLine2DStyles,\n assignParticle2DStyles,\n assignPlaceholder2DStyles,\n assignSprite2DStyles,\n} from \"./visual-2d\";\n\nconst RENDERABLE_TYPES = new Set([\n \"AnimatedSprite2D\",\n \"AnimationPlayer\",\n \"AspectRatioContainer\",\n \"AudioStreamPlayer\",\n \"BackBufferCopy\",\n \"Button\",\n \"CanvasGroup\",\n \"CanvasLayer\",\n \"BoxContainer\",\n \"Camera2D\",\n \"Camera3D\",\n \"CenterContainer\",\n \"ColorRect\",\n \"Container\",\n \"Control\",\n \"CPUParticles2D\",\n \"FmodBankLoader\",\n \"FmodListener2D\",\n \"FlowContainer\",\n \"GPUParticles2D\",\n \"GPUParticles3D\",\n \"GridContainer\",\n \"HBoxContainer\",\n \"HFlowContainer\",\n \"Label\",\n \"LineEdit\",\n \"Line2D\",\n \"LightOccluder2D\",\n \"MarginContainer\",\n \"Marker2D\",\n \"MeshInstance2D\",\n \"MeshInstance3D\",\n \"Node\",\n \"Node2D\",\n \"Node3D\",\n \"NinePatchRect\",\n \"Panel\",\n \"PanelContainer\",\n \"Path2D\",\n \"PathFollow2D\",\n \"Range\",\n \"RichTextLabel\",\n \"ScrollContainer\",\n \"Sprite2D\",\n \"SubViewport\",\n \"SubViewportContainer\",\n \"TextEdit\",\n \"TextureRect\",\n \"VBoxContainer\",\n \"VFlowContainer\",\n \"WorldEnvironment\",\n]);\n\nexport function renderSceneToHtmlModel(\n scene: GodotSceneTree,\n options: GodotHtmlRenderOptions = {},\n): GodotHtmlModel {\n const layout = scene;\n const resourceStatuses: GodotResourceStatus[] = [\n ...(layout.resourceStatuses ?? []),\n ];\n const renderOptions = withResourceStatusCollection(options, resourceStatuses);\n const classPrefix = options.classPrefix ?? \"godot\";\n const fontFaces: GodotHtmlFontFace[] = [];\n // Shared `<filter>` table (inner SVG markup -> id) collected while assigning\n // texture styles; emitted once and referenced via `filter: url(#id)` by\n // external color-matrix tints and consumer-supplied shader-fallback filters.\n const tintFilters = new Map<string, string>();\n const renderable = layout.nodes.filter(isRenderableNode);\n const layoutByPath = new Map(layout.nodes.map((node) => [node.path, node]));\n const renderablePaths = new Set(renderable.map((node) => node.path));\n const effectivelyVisible = effectiveVisibilityByPath(layoutByPath);\n const nodes: GodotHtmlNode[] = [];\n for (const node of renderable) {\n const parentPath = nearestRenderableParent(node, layout, renderablePaths);\n if (effectivelyVisible.get(node.path) ?? true) {\n nodes.push(\n htmlNodeFromLayoutNode(\n node,\n classPrefix,\n parentPath,\n parentPath ? layoutByPath.get(parentPath) : undefined,\n renderOptions,\n fontFaces,\n tintFilters,\n ),\n );\n } else if (\n parentPath === null ||\n (effectivelyVisible.get(parentPath) ?? true)\n ) {\n // Topmost hidden node of a pruned subtree (as seen in the rendered tree):\n // kept in position as a placeholder so every renderer can emit a comment\n // where the element would be. Deeper descendants are dropped entirely.\n nodes.push(hiddenPlaceholderNode(node, parentPath));\n }\n }\n const byPath = new Map(nodes.map((node) => [node.path, node]));\n for (const node of nodes) {\n if (node.parentPath) {\n byPath.get(node.parentPath)?.children.push(node.path);\n }\n }\n for (const node of nodes) {\n node.children.sort(\n (left, right) =>\n (layoutByPath.get(left)?.drawOrder ?? 0) -\n (layoutByPath.get(right)?.drawOrder ?? 0),\n );\n }\n assignContainerLayoutStyles(\n nodes.filter((node) => node.kind !== \"hidden-placeholder\"),\n layoutByPath,\n renderOptions,\n );\n const contentScale = resolveContentScale(\n options.contentScale,\n layout.viewport,\n );\n let css = godotSceneBaseCss;\n if (contentScale && contentScale.technique === \"container\") {\n // Express the whole stage subtree in container-query units so the scene fits\n // its frame, preserving aspect, with no JavaScript. Inline geometry lives in\n // `style`/`selfStyle`; rich-text `[font_size]`/`[img]` px live inside `html`.\n const { base } = contentScale;\n for (const node of nodes) {\n scaleStyleRecord(node.style, base);\n scaleStyleRecord(node.selfStyle, base);\n if (node.html !== null) {\n node.html = rewritePxLengths(node.html, base);\n }\n }\n css = rewritePxLengths(godotSceneBaseCss, base);\n }\n return {\n viewport: {\n width: layout.viewport.width,\n height: layout.viewport.height,\n },\n nodes,\n fontFaces: uniqueFontFaces(fontFaces),\n tintFilters: [...tintFilters].map(([markup, id]) => ({ id, markup })),\n diagnostics: layout.diagnostics,\n resourceStatuses,\n css,\n contentScale,\n };\n}\n\nconst SYNTHETIC_RECT: GodotRect = { x: 0, y: 0, width: 0, height: 0 };\nexport const DEFAULT_BROWSER_VIEWPORT = { width: 1280, height: 720 };\n\n/**\n * Browser-native HTML model from a `SceneGraph` (the `deriveSceneGraph` output):\n * the SAME `GodotHtmlModel` the computed renderer produces, but geometry is left\n * to the CSS engine — containers flex/grid, children flow, anchored Controls use\n * CSS insets, text sizes itself. Reuses the shared per-node builder\n * (`htmlNodeFromLayoutNode`) for all paint/text/resource work by feeding it a\n * placeholder rect, then replaces the rect-pinning container pass with\n * `assignBrowserNativeLayout`. Because the output model shape is identical, every\n * downstream consumer (fragment builder, content-scale observer, fonts) is shared.\n */\nexport function renderSceneGraphToHtmlModel(\n graph: SceneGraph,\n options: GodotHtmlRenderOptions & {\n viewport?: { width?: number; height?: number };\n } = {},\n): GodotHtmlModel {\n const resourceStatuses: GodotResourceStatus[] = [\n ...(graph.resourceStatuses ?? []),\n ];\n const renderOptions = withResourceStatusCollection(options, resourceStatuses);\n const classPrefix = options.classPrefix ?? \"godot\";\n const fontFaces: GodotHtmlFontFace[] = [];\n const tintFilters = new Map<string, string>();\n const viewport = {\n width: options.viewport?.width ?? DEFAULT_BROWSER_VIEWPORT.width,\n height: options.viewport?.height ?? DEFAULT_BROWSER_VIEWPORT.height,\n };\n // Wrap each graph node with a placeholder rect so the shared node builder runs;\n // `assignBrowserNativeLayout` overwrites all geometry afterward, so the rect\n // values themselves are never read.\n const layoutNodes: GodotSceneTreeNode[] = graph.nodes.map((node) => ({\n ...node,\n rect: { ...SYNTHETIC_RECT },\n renderedRect: { ...SYNTHETIC_RECT },\n }));\n const renderable = layoutNodes.filter(isRenderableNode);\n const layoutByPath = new Map(layoutNodes.map((node) => [node.path, node]));\n const renderablePaths = new Set(renderable.map((node) => node.path));\n const effectivelyVisible = effectiveVisibilityByPath(layoutByPath);\n const nodes: GodotHtmlNode[] = [];\n for (const node of renderable) {\n const parentPath = nearestRenderableParentPath(\n node,\n layoutByPath,\n renderablePaths,\n );\n if (effectivelyVisible.get(node.path) ?? true) {\n nodes.push(\n htmlNodeFromLayoutNode(\n node,\n classPrefix,\n parentPath,\n parentPath ? layoutByPath.get(parentPath) : undefined,\n renderOptions,\n fontFaces,\n tintFilters,\n ),\n );\n } else if (\n parentPath === null ||\n (effectivelyVisible.get(parentPath) ?? true)\n ) {\n nodes.push(hiddenPlaceholderNode(node, parentPath));\n }\n }\n const byPath = new Map(nodes.map((node) => [node.path, node]));\n for (const node of nodes) {\n if (node.parentPath) {\n byPath.get(node.parentPath)?.children.push(node.path);\n }\n }\n for (const node of nodes) {\n node.children.sort(\n (left, right) =>\n (layoutByPath.get(left)?.drawOrder ?? 0) -\n (layoutByPath.get(right)?.drawOrder ?? 0),\n );\n }\n assignBrowserNativeLayout(\n nodes.filter((node) => node.kind !== \"hidden-placeholder\"),\n layoutByPath,\n renderOptions,\n viewport,\n );\n const diagnostics: GodotSceneTreeDiagnostic[] = [];\n if (options.anchorsByPath && Object.keys(options.anchorsByPath).length > 0) {\n // Runs before the container-technique px rewrite below so anchor-offset px\n // inside the emitted calc() expressions scale with everything else.\n applyBrowserAnchorPositioning(\n byPath,\n layoutByPath,\n options.anchorsByPath,\n diagnostics,\n );\n }\n const contentScale = resolveContentScale(options.contentScale, viewport);\n let css = godotSceneBaseCss;\n if (contentScale && contentScale.technique === \"container\") {\n const { base } = contentScale;\n for (const node of nodes) {\n scaleStyleRecord(node.style, base);\n scaleStyleRecord(node.selfStyle, base);\n if (node.html !== null) {\n node.html = rewritePxLengths(node.html, base);\n }\n }\n css = rewritePxLengths(godotSceneBaseCss, base);\n }\n return {\n viewport,\n nodes,\n fontFaces: uniqueFontFaces(fontFaces),\n tintFilters: [...tintFilters].map(([markup, id]) => ({ id, markup })),\n diagnostics,\n resourceStatuses,\n css,\n contentScale,\n };\n}\n\n/**\n * Per-node browser-native HTML for ONE `SceneGraph` node — the same paint/text/\n * resource/layout work `renderSceneGraphToHtmlModel` does per node, but callable\n * in isolation so the Vue component renderer can build (and memoize) one node at\n * a time. Feeds `htmlNodeFromLayoutNode` a placeholder rect (overwritten by\n * `assignBrowserNativeNodeLayout`, exactly as the batch model does) and threads\n * the parent's container context for the flow pass. `tintFilters` is the caller's\n * shared, lifetime-stable filter table (a markup keeps its id), so a reused node's\n * baked `filter: url(#id)` stays valid; `fontFaces`/`resourceStatuses` are this\n * node's own (the caller merges them into the view's registry).\n */\nexport interface GraphNodeBuildResult {\n node: GodotHtmlNode;\n // The synthetic-rect layout node — pass it as `parentLayout` when building this\n // node's children (matches the batch's `layoutByPath.get(parentPath)`).\n layout: GodotSceneTreeNode;\n fontFaces: GodotHtmlFontFace[];\n resourceStatuses: GodotResourceStatus[];\n // The context THIS node hands to its children (its container type/axis, or the\n // root context when it is not a CSS container).\n childContext: BrowserNativeParentContext;\n}\n\nexport function buildGraphNodeHtml(\n graphNode: SceneGraphNode,\n parentLayout: GodotSceneTreeNode | undefined,\n parentPath: string | null,\n parentContext: BrowserNativeParentContext,\n options: GodotHtmlRenderOptions,\n tintFilters: Map<string, string>,\n viewport: { width: number; height: number },\n contentScale: ResolvedContentScale | null,\n): GraphNodeBuildResult {\n const classPrefix = options.classPrefix ?? \"godot\";\n const fontFaces: GodotHtmlFontFace[] = [];\n const resourceStatuses: GodotResourceStatus[] = [];\n const renderOptions = withResourceStatusCollection(options, resourceStatuses);\n // Placeholder rect, as the batch model uses — geometry is overwritten below.\n const layout: GodotSceneTreeNode = {\n ...graphNode,\n rect: { ...SYNTHETIC_RECT },\n renderedRect: { ...SYNTHETIC_RECT },\n };\n const node = htmlNodeFromLayoutNode(\n layout,\n classPrefix,\n parentPath,\n parentLayout,\n renderOptions,\n fontFaces,\n tintFilters,\n );\n const childContext = assignBrowserNativeNodeLayout(\n node,\n layout,\n parentContext,\n renderOptions,\n viewport,\n );\n // Container-technique content scale rewrites inline px per node (the batch does\n // this in one sweep over `nodes`; the css rewrite is the caller's, once).\n if (contentScale && contentScale.technique === \"container\") {\n scaleStyleRecord(node.style, contentScale.base);\n scaleStyleRecord(node.selfStyle, contentScale.base);\n if (node.html !== null) {\n node.html = rewritePxLengths(node.html, contentScale.base);\n }\n }\n return { node, layout, fontFaces, resourceStatuses, childContext };\n}\n\n// The comment-placeholder model node for an effectively-hidden `SceneGraph` node —\n// the component renderer emits it as `<!--godot:hidden …-->` (same as the batch),\n// keeping the node's behind/normal paint slot among its siblings.\nexport function buildHiddenGraphNode(\n graphNode: SceneGraphNode,\n parentPath: string | null,\n): GodotHtmlNode {\n return hiddenPlaceholderNode(graphNode, parentPath);\n}\n\n/**\n * The render STRUCTURE of a `SceneGraph` — which nodes render, and each renderable\n * parent's children split into the behind/normal paint slots (draw-order sorted),\n * flattening non-renderable nodes onto their nearest renderable ancestor. Pure and\n * visibility-agnostic: a hidden node still occupies its slot (the component renders\n * it as a comment); only the build skips DESCENDING into it. Mirrors the children-\n * wiring + draw-order sort + behind/normal partition `renderSceneGraphToHtmlModel`\n * does inline, so the component tree nests identically.\n */\nexport interface GraphSceneStructure {\n rootPaths: string[];\n nodesByPath: Map<string, SceneGraphNode>;\n childrenByPath: Map<string, { behind: string[]; normal: string[] }>;\n}\n\nexport function buildSceneStructure(graph: SceneGraph): GraphSceneStructure {\n const nodesByPath = new Map(graph.nodes.map((node) => [node.path, node]));\n const renderable = graph.nodes.filter(isRenderableNode);\n const renderablePaths = new Set(renderable.map((node) => node.path));\n const rootPaths: string[] = [];\n const childNodesByParent = new Map<string, SceneGraphNode[]>();\n for (const node of renderable) {\n const parentPath = nearestRenderableParentPath(\n node,\n nodesByPath,\n renderablePaths,\n );\n if (parentPath === null) {\n // Roots stay in graph (document) order — the batch never sorts them.\n rootPaths.push(node.path);\n continue;\n }\n const siblings = childNodesByParent.get(parentPath);\n if (siblings) {\n siblings.push(node);\n } else {\n childNodesByParent.set(parentPath, [node]);\n }\n }\n const childrenByPath = new Map<\n string,\n { behind: string[]; normal: string[] }\n >();\n for (const [parentPath, children] of childNodesByParent) {\n children.sort((left, right) => left.drawOrder - right.drawOrder);\n const behind: string[] = [];\n const normal: string[] = [];\n for (const child of children) {\n (child.showBehindParent ? behind : normal).push(child.path);\n }\n childrenByPath.set(parentPath, { behind, normal });\n }\n return { rootPaths, nodesByPath, childrenByPath };\n}\n\n/**\n * Effective visibility per path: a node renders only when its own `visible`\n * AND every ancestor's are true (Godot hides the whole subtree). Memoized\n * parent-chain walk; node `visible` is the node's OWN flag, not inherited.\n */\nfunction effectiveVisibilityByPath(\n layoutByPath: Map<string, GodotSceneTreeNode>,\n): Map<string, boolean> {\n const effective = new Map<string, boolean>();\n const resolve = (path: string): boolean => {\n const cached = effective.get(path);\n if (cached !== undefined) {\n return cached;\n }\n const node = layoutByPath.get(path);\n const visible =\n (node?.visible ?? true) &&\n (node?.parentPath ? resolve(node.parentPath) : true);\n effective.set(path, visible);\n return visible;\n };\n for (const path of layoutByPath.keys()) {\n resolve(path);\n }\n return effective;\n}\n\n/**\n * Minimal stand-in for the topmost node of an effectively-hidden subtree.\n * Renderers emit it as `<!--godot:hidden <path> (<Type>)-->` instead of an\n * element; it carries no styles/attributes except the mirrored\n * `data-godot-show-behind-parent` so it keeps the same behind/normal paint\n * slot among its siblings (stable child order and Vue keying across toggles).\n */\nfunction hiddenPlaceholderNode(\n node: { path: string; name: string; type: string; showBehindParent: boolean },\n parentPath: string | null,\n): GodotHtmlNode {\n const attributes: Record<string, string> = {};\n if (node.showBehindParent) {\n attributes[\"data-godot-show-behind-parent\"] = \"true\";\n }\n return {\n kind: \"hidden-placeholder\",\n path: node.path,\n name: node.name,\n type: node.type,\n parentPath,\n children: [],\n positioning: \"absolute\",\n containerLayout: null,\n attributes,\n className: \"\",\n style: {},\n selfAttributes: {},\n selfStyle: {},\n text: null,\n html: null,\n };\n}\n\nfunction nearestRenderableParentPath(\n node: { parentPath: string | null },\n layoutByPath: Map<string, { parentPath: string | null }>,\n renderablePaths: Set<string>,\n): string | null {\n let parentPath = node.parentPath;\n while (parentPath) {\n if (renderablePaths.has(parentPath)) {\n return parentPath;\n }\n parentPath = layoutByPath.get(parentPath)?.parentPath ?? null;\n }\n return null;\n}\n\nfunction withResourceStatusCollection(\n options: GodotHtmlRenderOptions,\n resourceStatuses: GodotResourceStatus[],\n): GodotHtmlRenderOptions {\n return {\n ...options,\n resolveResource: options.resolveResource\n ? (ref, node) => {\n const value = options.resolveResource?.(ref, node);\n recordResourceStatus(resourceStatuses, value, {\n kind: \"resource\",\n ref,\n node,\n });\n return value;\n }\n : undefined,\n resolveResourcePath: options.resolveResourcePath\n ? (path, node) => {\n const value = options.resolveResourcePath?.(path, node);\n recordResourceStatus(resourceStatuses, value, {\n kind: \"resource-path\",\n path,\n node,\n });\n return value;\n }\n : undefined,\n };\n}\n\nfunction recordResourceStatus(\n statuses: GodotResourceStatus[],\n value: unknown,\n context: {\n kind: \"resource\" | \"resource-path\";\n node: GodotNode;\n ref?: GodotResourceRefValue;\n path?: string;\n },\n): void {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return;\n }\n const status = (value as { status?: unknown }).status;\n if (status !== \"pending\" && status !== \"error\") {\n return;\n }\n statuses.push({\n kind: context.kind,\n status,\n nodePath: htmlResourceNodePath(context.node),\n path: asString((value as { path?: GodotVariant }).path) ?? context.path,\n ref: context.ref,\n message: asString((value as { message?: GodotVariant }).message),\n });\n}\n\nfunction htmlResourceNodePath(node: GodotNode): string {\n if (!node.parent) {\n return \".\";\n }\n return node.parent === \".\" ? node.name : `${node.parent}/${node.name}`;\n}\n\nfunction htmlNodeFromLayoutNode(\n node: GodotSceneTreeNode,\n classPrefix: string,\n parentPath: string | null,\n parentNode: GodotSceneTreeNode | undefined,\n options: GodotHtmlRenderOptions,\n fontFaces: GodotHtmlFontFace[],\n tintFilters: Map<string, string>,\n): GodotHtmlNode {\n const nodeOptions = options;\n const props = node.properties;\n const source = sourceNodeForLayout(node);\n // Whether this node's text tracks `var(--godot-text-scale, 1)`. Auto-fit text is\n // included by default; `exemptAutoFit` leaves it fitted to its box.\n const textScale = resolveTextScale(nodeOptions.textScale);\n const autoFitDirective = nodeOptions.textAutoFitByPath?.[node.path];\n const isAutoFitNode = Boolean(\n autoFitDirective &&\n (autoFitDirective.fitWidth || autoFitDirective.fitHeight),\n );\n const scaleText =\n textScale !== null && !(isAutoFitNode && textScale.exemptAutoFit);\n const style: Record<string, string> = {\n left: `${round(parentNode ? node.rect.x - parentNode.rect.x : node.rect.x)}px`,\n top: `${round(parentNode ? node.rect.y - parentNode.rect.y : node.rect.y)}px`,\n width: `${round(node.rect.width)}px`,\n height: `${round(node.rect.height)}px`,\n overflow: node.clipContents ? \"hidden\" : \"visible\",\n };\n const positioning = assignPositionStyle(style, node);\n assignZIndexStyle(style, node);\n const selfStyle: Record<string, string> = {\n position: \"absolute\",\n left: \"0\",\n top: \"0\",\n width: `${round(node.rect.width)}px`,\n height: `${round(node.rect.height)}px`,\n \"box-sizing\": \"border-box\",\n overflow: \"visible\",\n \"pointer-events\": \"none\",\n };\n const attributes: Record<string, string> = {\n \"data-godot-path\": node.path,\n \"data-godot-type\": node.type,\n \"data-godot-name\": node.name,\n \"data-godot-positioning\": positioning,\n };\n const selfAttributes: Record<string, string> = {\n \"data-godot-self-layer\": \"true\",\n };\n\n assignBackgroundColor(selfStyle, props, node.type);\n assignPointerEvents(style, props, node.type);\n assignOpacity(style, selfStyle, attributes, props);\n assignTransform(style, node, props);\n assignDrawAttributes(attributes, node, props);\n assignMaterialAttributes(\n attributes,\n style,\n props,\n source,\n nodeOptions,\n node.path,\n );\n if (\n nodeOptions.enableWebglShaders &&\n node.type === \"ColorRect\" &&\n props.color === undefined &&\n isShaderMaterialNode(props, source, nodeOptions)\n ) {\n delete selfStyle.background;\n selfAttributes[\"data-godot-shader-colorrect-fallback\"] = \"transparent\";\n }\n let html: string | null = null;\n if (\n node.type === \"Panel\" ||\n node.type === \"PanelContainer\" ||\n node.type === \"ScrollContainer\"\n ) {\n assignPanelStyles(selfStyle, selfAttributes, props, node, nodeOptions);\n }\n if (node.type === \"LineEdit\" || node.type === \"TextEdit\") {\n assignInputStyleBoxStyles(\n selfStyle,\n selfAttributes,\n props,\n node,\n nodeOptions,\n );\n }\n if (node.type === \"TextureRect\" || node.type === \"NinePatchRect\") {\n html =\n assignTextureStyles(\n selfStyle,\n selfAttributes,\n props,\n source,\n nodeOptions,\n node.type === \"NinePatchRect\",\n // A `clip_children` nine-patch must mask the node's children, which live\n // in the outer element alongside the self-layer — so its alpha mask is\n // applied to the outer `style`/`attributes`, not the self-layer.\n style,\n attributes,\n tintFilters,\n node.path,\n ) ?? html;\n }\n if (node.type === \"AnimatedSprite2D\") {\n assignAnimatedSpriteStyles(\n style,\n selfAttributes,\n props,\n source,\n nodeOptions,\n );\n movePaintStyles(style, selfStyle);\n syncSelfLayerBox(style, selfStyle);\n }\n if (node.type === \"Sprite2D\") {\n assignSprite2DStyles(\n style,\n selfAttributes,\n props,\n source,\n nodeOptions,\n node.path,\n );\n movePaintStyles(style, selfStyle);\n syncSelfLayerBox(style, selfStyle);\n }\n if (node.type === \"Line2D\") {\n html =\n assignLine2DStyles(style, selfAttributes, props, source, nodeOptions) ??\n html;\n syncSelfLayerBox(style, selfStyle);\n }\n if (node.type === \"CPUParticles2D\" || node.type === \"GPUParticles2D\") {\n html =\n assignParticle2DStyles(\n style,\n selfAttributes,\n props,\n source,\n nodeOptions,\n node.type,\n node.path,\n ) ?? html;\n syncSelfLayerBox(style, selfStyle);\n } else if (isPlaceholderNodeType(node.type)) {\n assignPlaceholder2DStyles(\n style,\n selfAttributes,\n props,\n source,\n nodeOptions,\n node.type,\n );\n syncSelfLayerBox(style, selfStyle);\n }\n if (node.type === \"Range\") {\n assignRangeStyles(selfStyle, selfAttributes, props);\n }\n if (isTextNodeType(node.type)) {\n assignTextStyles(\n selfStyle,\n selfAttributes,\n node,\n props,\n nodeOptions,\n fontFaces,\n scaleText,\n );\n assignTextAutoFitAttributes(attributes, node, nodeOptions);\n if (scaleText) {\n // Read by the runtime auto-fit pass so its font-size override also tracks\n // the text-scale var.\n attributes[\"data-godot-text-scale\"] = \"true\";\n }\n }\n\n const text =\n node.type === \"LineEdit\" || node.type === \"TextEdit\"\n ? (textProp(props.text) ?? textProp(props.placeholder_text))\n : textProp(props.text);\n if (\n (node.type === \"LineEdit\" || node.type === \"TextEdit\") &&\n typeof props.placeholder_text === \"string\"\n ) {\n attributes[\"data-godot-placeholder\"] = props.placeholder_text;\n }\n // Apply texture flips to the self-layer (after every type block has finished\n // assembling `selfStyle`) so a flipped TextureRect/Sprite mirrors only its own\n // texture, never its child nodes.\n assignSelfLayerFlip(selfStyle, props);\n assignShaderLoadingFallback(selfStyle, selfAttributes, node, nodeOptions);\n mirrorSelfMetadata(attributes, selfAttributes);\n return {\n path: node.path,\n name: node.name,\n type: node.type,\n parentPath,\n children: [],\n positioning,\n containerLayout: null,\n attributes,\n className: `godot-scene-node ${classPrefix}-type-${safeClassSegment(node.type)}`,\n style,\n selfAttributes,\n selfStyle,\n text,\n html:\n node.type === \"RichTextLabel\" &&\n text !== null &&\n asBoolean(props.bbcode_enabled) === true\n ? richTextLayeredHtml(text, {\n customTags: nodeOptions.bbcodeTags,\n resolveImage: (path) =>\n imageResource(\n normalizeResource(\n nodeOptions.resolveResourcePath?.(path, source),\n ),\n nodeOptions,\n source,\n ),\n textScale: scaleText,\n })\n : html,\n };\n}\n\nfunction assignShaderLoadingFallback(\n selfStyle: Record<string, string>,\n selfAttributes: Record<string, string>,\n node: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n): void {\n if (!options.enableWebglShaders) {\n return;\n }\n const fallback = options.shaderLoadingFallbacksByPath?.[node.path];\n if (\n !fallback ||\n typeof fallback.background !== \"string\" ||\n fallback.background === \"\"\n ) {\n return;\n }\n selfAttributes[\"data-godot-shader-loading-fallback\"] = \"1\";\n selfAttributes[\"data-godot-shader-loading\"] = \"1\";\n selfStyle.background = fallback.background;\n if (typeof fallback.clipPath === \"string\" && fallback.clipPath !== \"\") {\n selfStyle[\"clip-path\"] = fallback.clipPath;\n }\n if (\n typeof fallback.borderRadius === \"string\" &&\n fallback.borderRadius !== \"\"\n ) {\n selfStyle[\"border-radius\"] = fallback.borderRadius;\n }\n}\n\nfunction assignTextAutoFitAttributes(\n attributes: Record<string, string>,\n node: GodotSceneTreeNode,\n options: GodotHtmlRenderOptions,\n): void {\n const directive = options.textAutoFitByPath?.[node.path];\n if (!directive) {\n return;\n }\n attributes[\"data-godot-text-auto-fit\"] = \"true\";\n attributes[\"data-godot-text-auto-fit-min-font-size-px\"] = String(\n directive.minFontSizePx,\n );\n attributes[\"data-godot-text-auto-fit-max-font-size-px\"] = String(\n directive.maxFontSizePx,\n );\n if (directive.nominalFontSizePx !== undefined) {\n attributes[\"data-godot-text-auto-fit-nominal-font-size-px\"] = String(\n directive.nominalFontSizePx,\n );\n }\n if (directive.nominalMetrics) {\n attributes[\"data-godot-text-auto-fit-nominal-metrics\"] = JSON.stringify(\n directive.nominalMetrics,\n );\n }\n attributes[\"data-godot-text-auto-fit-width\"] = String(directive.fitWidth);\n attributes[\"data-godot-text-auto-fit-height\"] = String(directive.fitHeight);\n if (directive.wrapMode !== undefined) {\n attributes[\"data-godot-text-auto-fit-wrap-mode\"] = directive.wrapMode;\n }\n if (directive.textOverrunBehavior !== undefined) {\n attributes[\"data-godot-text-auto-fit-overrun-behavior\"] =\n directive.textOverrunBehavior;\n }\n}\n\nfunction mirrorSelfMetadata(\n attributes: Record<string, string>,\n selfAttributes: Record<string, string>,\n): void {\n for (const [name, value] of Object.entries(selfAttributes)) {\n if (name !== \"data-godot-self-layer\") {\n attributes[name] = value;\n }\n }\n}\n\nfunction syncSelfLayerBox(\n style: Record<string, string>,\n selfStyle: Record<string, string>,\n): void {\n selfStyle.width = style.width;\n selfStyle.height = style.height;\n}\n\nfunction movePaintStyles(\n style: Record<string, string>,\n selfStyle: Record<string, string>,\n): void {\n for (const property of [\n \"background-image\",\n \"background-repeat\",\n \"background-size\",\n \"background-position\",\n \"image-rendering\",\n ]) {\n const value = style[property];\n if (value !== undefined) {\n selfStyle[property] = value;\n delete style[property];\n }\n }\n}\n\nfunction isRenderableNode(node: { type: string }): boolean {\n return RENDERABLE_TYPES.has(node.type);\n}\n\nfunction isTextNodeType(type: string): boolean {\n return (\n type === \"Label\" ||\n type === \"RichTextLabel\" ||\n type === \"LineEdit\" ||\n type === \"TextEdit\" ||\n type === \"Button\"\n );\n}\n\nfunction isPlaceholderNodeType(type: string): boolean {\n return (\n type === \"AnimationPlayer\" ||\n type === \"AudioStreamPlayer\" ||\n type === \"BackBufferCopy\" ||\n type === \"Camera2D\" ||\n type === \"Camera3D\" ||\n type === \"FmodBankLoader\" ||\n type === \"FmodListener2D\" ||\n type === \"GPUParticles3D\" ||\n type === \"LightOccluder2D\" ||\n type === \"Marker2D\" ||\n type === \"MeshInstance2D\" ||\n type === \"MeshInstance3D\" ||\n type === \"Node\" ||\n type === \"Node3D\" ||\n type === \"Path2D\" ||\n type === \"PathFollow2D\" ||\n type === \"SubViewport\" ||\n type === \"WorldEnvironment\"\n );\n}\n\nfunction nearestRenderableParent(\n node: GodotSceneTreeNode,\n layout: GodotSceneTree,\n renderablePaths: Set<string>,\n): string | null {\n const byPath = new Map(\n layout.nodes.map((candidate) => [candidate.path, candidate]),\n );\n let parentPath = node.parentPath;\n while (parentPath) {\n if (renderablePaths.has(parentPath)) {\n return parentPath;\n }\n parentPath = byPath.get(parentPath)?.parentPath ?? null;\n }\n return null;\n}\n","import type { RenderElement } from \"./render-tree\";\n\n// Identity stabilization for successive `RenderElement` fragments.\n//\n// The model pipeline rebuilds the whole element tree on every change, so even a\n// one-node update hands a renderer all-new objects — an incremental target (the\n// Vue view's vnode cache) then has nothing to key reuse on. `stabilizeRenderElements`\n// walks the fresh fragment against the previous one and, wherever an element's\n// rendered content (tag/class/key/text/rawHtml/attributes/style) AND its entire\n// child subtree are unchanged, swaps the fresh object for the PREVIOUS one. After\n// the pass, `element === previousElement` ⟺ \"nothing in this subtree changed\",\n// which a renderer can use as a perfect memoization key. Unchanged subtrees keep\n// identity through arbitrarily many generations.\n//\n// `sourceNode` is deliberately EXCLUDED from the comparison: the model rebuild\n// churns its identity every cycle while the rendered output ignores it. The one\n// consumer of `sourceNode` (the Vue `#node` slot) must therefore not combine the\n// slot with stabilization-keyed caching — the Vue view disables its cache when\n// that slot is present.\nexport function stabilizeRenderElements(\n previous: RenderElement[] | undefined,\n next: RenderElement[],\n): RenderElement[] {\n if (!previous) {\n return next;\n }\n return stabilizeChildren(previous, next);\n}\n\nfunction stabilizeChildren(\n previous: RenderElement[],\n next: RenderElement[],\n): RenderElement[] {\n // Index-aligned fast path with a lazy key map for inserted/reordered keyed\n // elements (node elements are keyed by scene path).\n let byKey: Map<string, RenderElement> | undefined;\n return next.map((child, index) => {\n const indexMatch = previous[index];\n if (indexMatch && isSameElementType(indexMatch, child)) {\n return stabilizeElement(indexMatch, child);\n }\n if (child.key !== undefined) {\n byKey ??= keyMap(previous);\n const keyMatch = byKey.get(child.key);\n if (keyMatch && keyMatch.tag === child.tag) {\n return stabilizeElement(keyMatch, child);\n }\n }\n return child;\n });\n}\n\nfunction keyMap(elements: RenderElement[]): Map<string, RenderElement> {\n const map = new Map<string, RenderElement>();\n for (const element of elements) {\n if (element.key !== undefined && !map.has(element.key)) {\n map.set(element.key, element);\n }\n }\n return map;\n}\n\n// Mirrors vnode reconciliation: same position is only a candidate match when tag\n// and key agree (a key change means a different node landed here).\nfunction isSameElementType(a: RenderElement, b: RenderElement): boolean {\n return a.tag === b.tag && a.key === b.key;\n}\n\nfunction stabilizeElement(\n previous: RenderElement,\n next: RenderElement,\n): RenderElement {\n // Identity fast-path: when an upstream cross-render memo (the model build) already handed\n // back the SAME element object, the whole subtree is unchanged — skip the recursive deep\n // compare entirely. Harmless no-op until that memo exists (the references never match\n // today); collapses the per-render deep-compare once node identity flows through.\n if (previous === next) {\n return previous;\n }\n let childrenStable: boolean;\n if (next.children) {\n const stabilized = stabilizeChildren(\n previous.children ?? [],\n next.children,\n );\n // Fresh elements are throwaway per build; rewriting children in place keeps\n // the stabilized subtree without re-allocating the element.\n next.children = stabilized;\n childrenStable =\n previous.children !== undefined &&\n previous.children.length === stabilized.length &&\n stabilized.every((child, index) => child === previous.children?.[index]);\n } else {\n childrenStable = previous.children === undefined;\n }\n if (\n childrenStable &&\n previous.tag === next.tag &&\n previous.className === next.className &&\n previous.key === next.key &&\n previous.text === next.text &&\n previous.rawHtml === next.rawHtml &&\n recordsEqual(previous.attributes, next.attributes) &&\n recordsEqual(previous.style, next.style)\n ) {\n return previous;\n }\n return next;\n}\n\nfunction recordsEqual(\n a: Record<string, string> | undefined,\n b: Record<string, string> | undefined,\n): boolean {\n if (a === b) {\n return true;\n }\n if (!a || !b) {\n // Treat absent and empty as the same rendered output.\n return Object.keys(a ?? b ?? {}).length === 0;\n }\n const keys = Object.keys(a);\n if (keys.length !== Object.keys(b).length) {\n return false;\n }\n for (const key of keys) {\n if (a[key] !== b[key]) {\n return false;\n }\n }\n return true;\n}\n","import { round } from \"./css-values\";\nimport { renderRichTextFontSize } from \"./text\";\nimport { textScaleLength } from \"./text-scale\";\nimport type {\n GodotTextAutoFitDirective,\n GodotTextAutoFitNominalMetrics,\n} from \"./types\";\n\nconst EPSILON_PX = 0.5;\n\nconst RICH_TEXT_FONT_SIZE_VARS = [\n \"--godot-rich-normal-font-size\",\n \"--godot-rich-bold-font-size\",\n \"--godot-rich-italic-font-size\",\n \"--godot-rich-bold-italic-font-size\",\n] as const;\n\nexport function resolveTextAutoFitFontSize(\n directive: GodotTextAutoFitDirective,\n fits: (fontSizePx: number) => boolean,\n): number {\n const min = Math.ceil(directive.minFontSizePx);\n const max = Math.floor(directive.maxFontSizePx);\n if (!Number.isFinite(min) || !Number.isFinite(max) || min > max) {\n return min;\n }\n\n let low = min;\n let high = max;\n let best: number | undefined;\n while (low <= high) {\n const candidate = Math.floor((low + high) / 2);\n if (fits(candidate)) {\n best = candidate;\n low = candidate + 1;\n } else {\n high = candidate - 1;\n }\n }\n return best ?? min;\n}\n\nexport function applyTextAutoFit(stage: ParentNode): number {\n let applied = 0;\n for (const element of stage.querySelectorAll<HTMLElement>(\n \"[data-godot-text-auto-fit='true']\",\n )) {\n if (applyElementTextAutoFit(element)) {\n applied++;\n }\n }\n return applied;\n}\n\nfunction applyElementTextAutoFit(element: HTMLElement): boolean {\n const directive = directiveFromElement(element);\n if (!directive || (!directive.fitWidth && !directive.fitHeight)) {\n return false;\n }\n const selfLayer = element.querySelector<HTMLElement>(\n ':scope > [data-godot-self-layer=\"true\"]',\n );\n if (!selfLayer) {\n return false;\n }\n const measureTarget =\n element.dataset.godotType === \"RichTextLabel\"\n ? (selfLayer.querySelector<HTMLElement>(\n '[data-godot-rich-layer=\"fill\"]',\n ) ?? selfLayer)\n : selfLayer;\n const box = elementBox(element, selfLayer);\n if (\n (directive.fitWidth && !(box.width > 0)) ||\n (directive.fitHeight && !(box.height > 0))\n ) {\n return false;\n }\n\n // Prefer fitting from host-engine metrics; fall back to DOM measurement only when\n // metrics are unavailable (the DOM path mutates the font size while probing).\n const metricFits = metricFitPredicate(directive, box);\n const fits =\n metricFits ??\n ((candidate: number) => {\n assignAutoFitFontSize(element, selfLayer, candidate);\n const content = contentBox(measureTarget);\n return (\n (!directive.fitWidth || content.width <= box.width + EPSILON_PX) &&\n (!directive.fitHeight || content.height <= box.height + EPSILON_PX)\n );\n });\n const size = resolveTextAutoFitFontSize(directive, fits);\n assignAutoFitFontSize(element, selfLayer, size);\n return true;\n}\n\n/**\n * Build a pure `fits(candidate)` predicate from host-engine paragraph metrics\n * (measured at `nominalFontSizePx`): each candidate scales the nominal content box\n * by `candidate / nominalFontSizePx`, so width/height fits match the engine without\n * DOM measurement. Returns `null` when metrics or a positive nominal size are\n * unavailable, so the caller falls back to measuring the live DOM.\n */\nexport function metricFitPredicate(\n directive: GodotTextAutoFitDirective,\n box: { width: number; height: number },\n): ((candidate: number) => boolean) | null {\n const metrics: GodotTextAutoFitNominalMetrics | undefined =\n directive.nominalMetrics;\n const nominal = directive.nominalFontSizePx;\n if (!metrics || nominal === undefined || !(nominal > 0)) {\n return null;\n }\n const { contentWidthPx, contentHeightPx } = metrics;\n if (!(contentWidthPx > 0) || !(contentHeightPx > 0)) {\n return null;\n }\n return (candidate: number) => {\n const ratio = candidate / nominal;\n return (\n (!directive.fitWidth ||\n contentWidthPx * ratio <= box.width + EPSILON_PX) &&\n (!directive.fitHeight ||\n contentHeightPx * ratio <= box.height + EPSILON_PX)\n );\n };\n}\n\nfunction directiveFromElement(\n element: HTMLElement,\n): GodotTextAutoFitDirective | undefined {\n const minFontSizePx = numberData(element, \"godotTextAutoFitMinFontSizePx\");\n const maxFontSizePx = numberData(element, \"godotTextAutoFitMaxFontSizePx\");\n if (\n minFontSizePx === undefined ||\n maxFontSizePx === undefined ||\n minFontSizePx <= 0 ||\n maxFontSizePx <= 0 ||\n maxFontSizePx < minFontSizePx\n ) {\n return undefined;\n }\n return {\n minFontSizePx,\n maxFontSizePx,\n nominalFontSizePx: numberData(element, \"godotTextAutoFitNominalFontSizePx\"),\n nominalMetrics: nominalMetricsFromElement(element),\n fitWidth: element.dataset.godotTextAutoFitWidth === \"true\",\n fitHeight: element.dataset.godotTextAutoFitHeight === \"true\",\n wrapMode: element.dataset.godotTextAutoFitWrapMode,\n textOverrunBehavior: element.dataset.godotTextAutoFitOverrunBehavior,\n };\n}\n\nfunction nominalMetricsFromElement(\n element: HTMLElement,\n): GodotTextAutoFitNominalMetrics | undefined {\n const raw = element.dataset.godotTextAutoFitNominalMetrics;\n if (raw === undefined || raw.trim() === \"\") {\n return undefined;\n }\n try {\n const parsed = JSON.parse(raw) as unknown;\n return parsed && typeof parsed === \"object\"\n ? (parsed as GodotTextAutoFitNominalMetrics)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction numberData(\n element: HTMLElement,\n key: keyof HTMLElement[\"dataset\"],\n): number | undefined {\n const raw = element.dataset[key];\n if (raw === undefined || raw.trim() === \"\") {\n return undefined;\n }\n const value = Number(raw);\n return Number.isFinite(value) ? value : undefined;\n}\n\nfunction assignAutoFitFontSize(\n element: HTMLElement,\n selfLayer: HTMLElement,\n fontSizePx: number,\n): void {\n // When the node opted into text scaling, the fitted size must still track\n // `var(--godot-text-scale, 1)` so the player's slider keeps affecting it post-fit.\n const scaleText = element.dataset.godotTextScale === \"true\";\n if (element.dataset.godotType === \"RichTextLabel\") {\n // Godot scales every rich-text font role together; resizing only the normal\n // role would leave bold/italic runs at the authored size.\n const shouldScale = element.dataset.godotRichTextScaleFontSize !== \"false\";\n const renderedPx =\n renderRichTextFontSize(fontSizePx, shouldScale) ?? fontSizePx;\n for (const property of RICH_TEXT_FONT_SIZE_VARS) {\n selfLayer.style.setProperty(\n property,\n textScaleLength(renderedPx, scaleText),\n );\n }\n } else {\n selfLayer.style.fontSize = textScaleLength(fontSizePx, scaleText);\n }\n // Mirror assignTextStyles: line-height tracks the fitted logical size plus\n // line_separation, but only when the engine specified a separation (otherwise\n // leave it to the cascade rather than tightening Godot's font-metric spacing).\n const lineSeparation = numberData(element, \"godotLineSeparationPx\");\n if (lineSeparation !== undefined) {\n selfLayer.style.lineHeight = textScaleLength(\n Math.max(1, fontSizePx + lineSeparation),\n scaleText,\n );\n }\n}\n\nfunction elementBox(\n element: HTMLElement,\n selfLayer: HTMLElement,\n): { width: number; height: number } {\n // Prefer the engine-assigned logical size (style width/height) over\n // getBoundingClientRect: the stage is commonly wrapped in a `transform: scale()`\n // to fit the viewport, and getBoundingClientRect reports the *scaled* size, while\n // the fit inputs (nominalMetrics and scrollWidth/Height) are logical/unscaled.\n // Mixing them shrinks text on scaled pages. Fall back to measured rects only when\n // no logical size is set.\n const rect = element.getBoundingClientRect();\n const selfRect = selfLayer.getBoundingClientRect();\n return {\n width:\n cssSize(element.style.width) ??\n cssSize(selfLayer.style.width) ??\n positive(rect.width) ??\n positive(selfRect.width) ??\n 0,\n height:\n cssSize(element.style.height) ??\n cssSize(selfLayer.style.height) ??\n positive(rect.height) ??\n positive(selfRect.height) ??\n 0,\n };\n}\n\n// Caveat: the RichTextLabel content layer is now full-width (`.godot-rich-stack`\n// is `width: 100%`), so `scrollWidth` reports the box width rather than the text\n// width. That is harmless for the height-fit path used by every captured fixture\n// (those carry nominalMetrics, so metricFitPredicate runs and this is never\n// read), but a hypothetical width-fit-by-DOM RichTextLabel would mis-measure —\n// measure the widest line (getClientRects) instead if that case ever appears.\nfunction contentBox(element: HTMLElement): { width: number; height: number } {\n const rect = element.getBoundingClientRect();\n return {\n width:\n positive(element.scrollWidth) ??\n positive(rect.width) ??\n cssSize(element.style.width) ??\n 0,\n height:\n positive(element.scrollHeight) ??\n positive(rect.height) ??\n cssSize(element.style.height) ??\n 0,\n };\n}\n\nfunction positive(value: number): number | undefined {\n return Number.isFinite(value) && value > 0 ? value : undefined;\n}\n\nfunction cssSize(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number.parseFloat(value);\n return Number.isFinite(parsed) ? round(parsed) : undefined;\n}\n","// Post-mount pass that replaces `filter: url(#godot-tint-N)` texture tints with\n// the SAME color transform baked into the bitmap itself.\n//\n// Why: a CSS `filter` is a paint boundary — the browser rasterizes the filtered\n// layer axis-aligned and a ROTATED ancestor then resamples that raster, visibly\n// blurring the texture (the fanned combat-hand cards). Embedded (data-URI)\n// textures already avoid this by baking the matrix into an SVG `<image>` at\n// render time; EXTERNAL urls can't (SVG-as-CSS-background loads in secure static\n// mode, which refuses external references), so they fall back to the CSS filter\n// (`data-godot-texture-tint=\"css-filter\"`). This pass closes that gap in live\n// DOM hosts: it loads the external texture, applies the exposed color matrix\n// per-pixel on a canvas, swaps the painted url for the tinted data URL, and\n// strips the filter reference — pixel-identical output, no raster boundary.\n//\n// The html-string renderer never runs this (no DOM); it keeps the CSS filter.\n\nimport { clampNinePatchSlices } from \"./textures\";\n\nconst BAKED_CACHE = new Map<string, Promise<string | null>>();\nconst NATURAL_SIZE_CACHE = new Map<\n string,\n Promise<{ width: number; height: number } | null>\n>();\n\nexport type TintBakeImageLoader = (\n url: string,\n) => Promise<CanvasImageSource & { width: number; height: number }>;\n\nconst defaultLoadImage: TintBakeImageLoader = (url) =>\n new Promise((resolvePromise, rejectPromise) => {\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.onload = () => resolvePromise(image);\n image.onerror = () => rejectPromise(new Error(`image load failed: ${url}`));\n image.src = url;\n });\n\n/**\n * Apply a row-major 3×3 linear RGB transform to RGBA pixel bytes in place\n * (sRGB byte domain, alpha untouched) — the per-pixel equivalent of the\n * `feColorMatrix` emitted with `color-interpolation-filters=\"sRGB\"`.\n */\nexport function applyColorMatrixToPixels(\n pixels: Uint8ClampedArray,\n rows: readonly number[],\n): void {\n if (rows.length !== 9) {\n return;\n }\n const [r0, r1, r2, g0, g1, g2, b0, b1, b2] = rows;\n for (let i = 0; i < pixels.length; i += 4) {\n const r = pixels[i];\n const g = pixels[i + 1];\n const b = pixels[i + 2];\n pixels[i] = r0 * r + r1 * g + r2 * b;\n pixels[i + 1] = g0 * r + g1 * g + g2 * b;\n pixels[i + 2] = b0 * r + b1 * g + b2 * b;\n }\n}\n\nfunction parseMatrix(value: string | null): readonly number[] | undefined {\n if (!value) {\n return undefined;\n }\n const rows = value.trim().split(/\\s+/).map(Number);\n return rows.length === 9 && rows.every(Number.isFinite) ? rows : undefined;\n}\n\n// The painted url lives either in `background-image` (TextureRect) or\n// `border-image-source` (external NinePatchRect). Returns the style property\n// that carries it plus the bare url.\nfunction paintedUrl(\n element: HTMLElement,\n):\n | { property: \"background-image\" | \"border-image-source\"; url: string }\n | undefined {\n for (const property of [\"background-image\", \"border-image-source\"] as const) {\n const value = element.style.getPropertyValue(property);\n const match = /^url\\(([\"']?)(.*)\\1\\)$/.exec(value.trim());\n if (match?.[2] && !match[2].startsWith(\"data:\")) {\n return { property, url: match[2] };\n }\n }\n return undefined;\n}\n\nfunction bakedTintUrl(\n url: string,\n rows: readonly number[],\n loadImage: TintBakeImageLoader,\n): Promise<string | null> {\n const key = `${rows.join(\",\")}|${url}`;\n let pending = BAKED_CACHE.get(key);\n if (!pending) {\n pending = (async () => {\n const image = await loadImage(url);\n const width = Number(image.width);\n const height = Number(image.height);\n if (!width || !height) {\n return null;\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n const context = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!context) {\n return null;\n }\n context.drawImage(image, 0, 0);\n // Throws on a tainted canvas (cross-origin without CORS) — caught by the\n // caller, which keeps the CSS filter as the fallback.\n const imageData = context.getImageData(0, 0, width, height);\n applyColorMatrixToPixels(imageData.data, rows);\n context.putImageData(imageData, 0, 0);\n return canvas.toDataURL(\"image/png\");\n })().catch(() => null);\n BAKED_CACHE.set(key, pending);\n }\n return pending;\n}\n\n// Remove exactly this tint's `url(#id)` token from the inline filter (it may be\n// composed with other refs, and serializers may quote the fragment); drop the\n// property when nothing remains.\nfunction stripTintFilterRef(element: HTMLElement, filterId: string): void {\n const escaped = filterId.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const ref = new RegExp(`#${escaped}[\"')]`);\n const tokens = (element.style.filter ?? \"\")\n .split(/\\s+(?=url\\()/)\n .filter((token) => token.length > 0 && !ref.test(token));\n if (tokens.length) {\n element.style.filter = tokens.join(\" \");\n } else {\n element.style.removeProperty(\"filter\");\n }\n}\n\n/**\n * Upgrade every `data-godot-texture-tint=\"css-filter\"` element under `root` to\n * a baked tinted bitmap (see module comment). Idempotent: upgraded elements are\n * re-marked `baked-bitmap`; failures (image load, tainted canvas) keep the CSS\n * filter. Resolves once every candidate settled; returns the upgraded count.\n */\nexport async function bakeExternalTextureTints(\n root: ParentNode,\n loadImage: TintBakeImageLoader = defaultLoadImage,\n): Promise<number> {\n const candidates = [\n ...root.querySelectorAll<HTMLElement>(\n '[data-godot-texture-tint=\"css-filter\"][data-godot-tint-matrix]',\n ),\n ];\n const results = await Promise.all(\n candidates.map(async (element) => {\n const rows = parseMatrix(element.getAttribute(\"data-godot-tint-matrix\"));\n const filterId = element.getAttribute(\"data-godot-tint-filter-id\");\n const painted = paintedUrl(element);\n if (!rows || !filterId || !painted) {\n return false;\n }\n const baked = await bakedTintUrl(painted.url, rows, loadImage);\n // The element may have been re-rendered/replaced while the bitmap loaded.\n if (\n baked === null ||\n !element.isConnected ||\n element.getAttribute(\"data-godot-texture-tint\") !== \"css-filter\"\n ) {\n return false;\n }\n element.style.setProperty(painted.property, `url(\"${baked}\")`);\n stripTintFilterRef(element, filterId);\n element.setAttribute(\"data-godot-texture-tint\", \"baked-bitmap\");\n return true;\n }),\n );\n return results.filter(Boolean).length;\n}\n\n// Size-only loader: reading an image's NATURAL dimensions never needs a clean (CORS)\n// canvas (unlike the tint bake), so don't set `crossOrigin` — that would needlessly fail\n// the load for a cross-origin texture served without CORS headers, whose size is still\n// readable. (Same-origin `/res/` textures — the couch-coop case — load either way.)\nconst defaultSizeLoader: TintBakeImageLoader = (url) =>\n new Promise((resolvePromise, rejectPromise) => {\n const image = new Image();\n image.onload = () => resolvePromise(image);\n image.onerror = () => rejectPromise(new Error(`image load failed: ${url}`));\n image.src = url;\n });\n\nfunction naturalImageSize(\n url: string,\n loadImage: TintBakeImageLoader,\n): Promise<{ width: number; height: number } | null> {\n let pending = NATURAL_SIZE_CACHE.get(url);\n if (!pending) {\n pending = loadImage(url)\n .then((image) => {\n const width = Number(image.width);\n const height = Number(image.height);\n return width && height ? { width, height } : null;\n })\n .catch(() => null);\n NATURAL_SIZE_CACHE.set(url, pending);\n }\n return pending;\n}\n\n/**\n * Re-clamp external nine-patch `border-image-slice` once the texture's natural size is\n * known. The string renderer can't size an EXTERNAL texture, so it leaves the source slices\n * at the raw patch margins and marks the element `data-godot-nine-patch-unclamped` (carrying\n * those `top,right,bottom,left` margins). For a texture whose opposing margins meet/overlap\n * in the SOURCE, the browser drops the `border-image` `fill` center (the slanted end-caps\n * paint but the stretched middle does not — e.g. the HP-bar fill). Clamping the source slices\n * to keep a >=1px center restores it — the same fix `clampNinePatchSlices` applies inline when\n * the size IS known (embedded data-URI textures). Idempotent: an image-load failure leaves the\n * marker for a later pass; a successful pass clears it. Returns the count whose slices changed.\n */\nexport async function clampExternalNinePatchSlices(\n root: ParentNode,\n loadImage: TintBakeImageLoader = defaultSizeLoader,\n): Promise<number> {\n const candidates = [\n ...root.querySelectorAll<HTMLElement>(\"[data-godot-nine-patch-unclamped]\"),\n ];\n const results = await Promise.all(\n candidates.map(async (element) => {\n const raw = element.getAttribute(\"data-godot-nine-patch-unclamped\");\n const margins = raw?.split(\",\").map(Number);\n const painted = paintedUrl(element);\n if (\n margins?.length !== 4 ||\n margins.some((value) => !Number.isFinite(value)) ||\n !painted\n ) {\n return false;\n }\n const size = await naturalImageSize(painted.url, loadImage);\n // The element may have been re-rendered/replaced while the image loaded; a failed\n // load (null) keeps the marker so a later pass can retry.\n if (\n !size ||\n !element.isConnected ||\n !element.hasAttribute(\"data-godot-nine-patch-unclamped\")\n ) {\n return false;\n }\n const source = margins as [number, number, number, number];\n const clamped = clampNinePatchSlices(source, size);\n element.removeAttribute(\"data-godot-nine-patch-unclamped\");\n if (clamped === source) {\n return false; // margins fit the source — no center-drop to fix\n }\n element.style.setProperty(\n \"border-image-slice\",\n `${clamped.join(\" \")} fill`,\n );\n return true;\n }),\n );\n return results.filter(Boolean).length;\n}\n"],"mappings":"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"}