@almadar/ui 5.94.1 → 5.96.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.
@@ -1,5 +1,5 @@
1
- import * as React95 from 'react';
2
- import React95__default, { useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, createContext, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
1
+ import * as React96 from 'react';
2
+ import React96__default, { useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, createContext, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
3
3
  import { EventBusContext, useTraitScope, useEntitySchemaOptional, useEntitySchema, getAllPages, OrbitalProvider, TraitScopeProvider, ServerBridgeProvider, useCurrentPagePath, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge } from '@almadar/ui/providers';
4
4
  export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider, useEntitySchema, useEntitySchemaOptional, useServerBridge, useTrait, useTraitContext } from '@almadar/ui/providers';
5
5
  import { createLogger, isLogLevelEnabled } from '@almadar/logger';
@@ -937,7 +937,7 @@ var init_Box = __esm({
937
937
  fixed: "fixed",
938
938
  sticky: "sticky"
939
939
  };
940
- Box = React95__default.forwardRef(
940
+ Box = React96__default.forwardRef(
941
941
  ({
942
942
  padding,
943
943
  paddingX,
@@ -1002,7 +1002,7 @@ var init_Box = __esm({
1002
1002
  onPointerDown?.(e);
1003
1003
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
1004
1004
  const isClickable = action || onClick;
1005
- return React95__default.createElement(
1005
+ return React96__default.createElement(
1006
1006
  Component,
1007
1007
  {
1008
1008
  ref,
@@ -1098,7 +1098,7 @@ function loadLib(key, importer) {
1098
1098
  return p;
1099
1099
  }
1100
1100
  function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1101
- const Lazy = React95__default.lazy(async () => {
1101
+ const Lazy = React96__default.lazy(async () => {
1102
1102
  const lib = await loadLib(libKey, importer);
1103
1103
  const Comp = pick(lib);
1104
1104
  if (!Comp) {
@@ -1108,7 +1108,7 @@ function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1108
1108
  return { default: Comp };
1109
1109
  });
1110
1110
  const Wrapped = (props) => /* @__PURE__ */ jsx(
1111
- React95__default.Suspense,
1111
+ React96__default.Suspense,
1112
1112
  {
1113
1113
  fallback: /* @__PURE__ */ jsx(
1114
1114
  "span",
@@ -1839,7 +1839,7 @@ var init_Icon = __esm({
1839
1839
  const directIcon = typeof icon === "string" ? void 0 : icon;
1840
1840
  const effectiveName = typeof icon === "string" ? icon : name;
1841
1841
  const family = useIconFamily();
1842
- const RenderedComponent = React95__default.useMemo(() => {
1842
+ const RenderedComponent = React96__default.useMemo(() => {
1843
1843
  if (directIcon) return null;
1844
1844
  return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1845
1845
  }, [directIcon, effectiveName, family]);
@@ -1889,6 +1889,210 @@ var init_Icon = __esm({
1889
1889
  Icon.displayName = "Icon";
1890
1890
  }
1891
1891
  });
1892
+
1893
+ // lib/atlasSlice.ts
1894
+ function isTilesheet(a) {
1895
+ return typeof a.tileWidth === "number";
1896
+ }
1897
+ function getAtlas(url, onReady) {
1898
+ if (atlasCache.has(url)) return atlasCache.get(url) ?? void 0;
1899
+ atlasCache.set(url, void 0);
1900
+ fetch(url).then((r) => r.json()).then((json) => {
1901
+ atlasCache.set(url, json);
1902
+ onReady();
1903
+ }).catch(() => {
1904
+ atlasCache.set(url, null);
1905
+ });
1906
+ return void 0;
1907
+ }
1908
+ function subRectFor(atlas, sprite) {
1909
+ if (isTilesheet(atlas)) {
1910
+ let col;
1911
+ let row;
1912
+ if (sprite.includes(",")) {
1913
+ const [c, r] = sprite.split(",").map((n) => Number(n.trim()));
1914
+ col = c;
1915
+ row = r;
1916
+ } else {
1917
+ const i = Number(sprite);
1918
+ if (!Number.isFinite(i)) return null;
1919
+ col = i % atlas.columns;
1920
+ row = Math.floor(i / atlas.columns);
1921
+ }
1922
+ if (!Number.isFinite(col) || !Number.isFinite(row) || col < 0 || row < 0 || col >= atlas.columns || row >= atlas.rows) return null;
1923
+ const margin = atlas.margin ?? 0;
1924
+ const spacing = atlas.spacing ?? 0;
1925
+ return {
1926
+ sx: margin + col * (atlas.tileWidth + spacing),
1927
+ sy: margin + row * (atlas.tileHeight + spacing),
1928
+ sw: atlas.tileWidth,
1929
+ sh: atlas.tileHeight
1930
+ };
1931
+ }
1932
+ const st = atlas.subTextures[sprite];
1933
+ if (!st) return null;
1934
+ return { sx: st.x, sy: st.y, sw: st.width, sh: st.height };
1935
+ }
1936
+ function isAtlasAsset(asset) {
1937
+ return !!asset && typeof asset.atlas === "string" && typeof asset.sprite === "string";
1938
+ }
1939
+ function resolveAssetSource(img, asset, onReady) {
1940
+ if (isAtlasAsset(asset)) {
1941
+ const atlas = getAtlas(asset.atlas, onReady);
1942
+ if (!atlas) return null;
1943
+ const rect = subRectFor(atlas, asset.sprite);
1944
+ if (!rect) return null;
1945
+ return { img, rect, aspect: rect.sw / rect.sh };
1946
+ }
1947
+ const natW = img.naturalWidth || 1;
1948
+ const natH = img.naturalHeight || 1;
1949
+ return { img, rect: null, aspect: natW / natH };
1950
+ }
1951
+ function blit(ctx, src, dx, dy, dw, dh) {
1952
+ if (src.rect) ctx.drawImage(src.img, src.rect.sx, src.rect.sy, src.rect.sw, src.rect.sh, dx, dy, dw, dh);
1953
+ else ctx.drawImage(src.img, dx, dy, dw, dh);
1954
+ }
1955
+ var atlasCache;
1956
+ var init_atlasSlice = __esm({
1957
+ "lib/atlasSlice.ts"() {
1958
+ "use client";
1959
+ atlasCache = /* @__PURE__ */ new Map();
1960
+ }
1961
+ });
1962
+ function useAtlasSliceDataUrl(asset) {
1963
+ const [, bump] = React96.useReducer((x) => x + 1, 0);
1964
+ if (!isAtlasAsset(asset)) return void 0;
1965
+ const key = `${asset.atlas}#${asset.sprite}`;
1966
+ const cached = sliceDataUrlCache.get(key);
1967
+ if (cached) return cached;
1968
+ const atlas = getAtlas(asset.atlas, bump);
1969
+ const img = asset?.url ? getSheetImage(asset.url, bump) : null;
1970
+ if (!atlas || !img) return void 0;
1971
+ const rect = subRectFor(atlas, asset.sprite);
1972
+ if (!rect) return void 0;
1973
+ const canvas = document.createElement("canvas");
1974
+ canvas.width = rect.sw;
1975
+ canvas.height = rect.sh;
1976
+ const ctx = canvas.getContext("2d");
1977
+ if (!ctx) return void 0;
1978
+ ctx.imageSmoothingEnabled = false;
1979
+ ctx.drawImage(img, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
1980
+ const url = canvas.toDataURL();
1981
+ sliceDataUrlCache.set(key, url);
1982
+ return url;
1983
+ }
1984
+ function AtlasPanel({ asset, borderSlice = 16, borderWidth = 16, mode = "nineSlice", className, style, children, "aria-hidden": ariaHidden }) {
1985
+ const dataUrl = useAtlasSliceDataUrl(asset);
1986
+ const skin = !dataUrl ? {} : mode === "repeat" ? { backgroundImage: `url(${dataUrl})`, backgroundRepeat: "repeat" } : {
1987
+ borderStyle: "solid",
1988
+ borderWidth,
1989
+ borderImageSource: `url(${dataUrl})`,
1990
+ borderImageSlice: `${borderSlice} fill`,
1991
+ borderImageWidth: borderWidth,
1992
+ borderImageRepeat: "stretch",
1993
+ imageRendering: "pixelated"
1994
+ };
1995
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": ariaHidden, className: cn("inline-block", className), style: { ...skin, ...style }, children });
1996
+ }
1997
+ function getSheetImage(url, onReady) {
1998
+ const cached = imageCache.get(url);
1999
+ if (cached) return cached;
2000
+ (imageWaiters.get(url) ?? imageWaiters.set(url, /* @__PURE__ */ new Set()).get(url)).add(onReady);
2001
+ if (!imageCache.has(url)) {
2002
+ imageCache.set(url, null);
2003
+ const img = new Image();
2004
+ img.crossOrigin = "anonymous";
2005
+ img.onload = () => {
2006
+ imageCache.set(url, img);
2007
+ imageWaiters.get(url)?.forEach((fn) => fn());
2008
+ imageWaiters.delete(url);
2009
+ };
2010
+ img.src = url;
2011
+ }
2012
+ return null;
2013
+ }
2014
+ function AtlasImage({
2015
+ asset,
2016
+ size,
2017
+ width,
2018
+ height,
2019
+ fill = false,
2020
+ fit = "contain",
2021
+ alt,
2022
+ className,
2023
+ style,
2024
+ "aria-hidden": ariaHidden
2025
+ }) {
2026
+ const [, bump] = React96.useReducer((x) => x + 1, 0);
2027
+ const canvasRef = React96.useRef(null);
2028
+ const sliced = isAtlasAsset(asset);
2029
+ const atlas = sliced ? getAtlas(asset.atlas, bump) : void 0;
2030
+ const img = sliced && asset?.url ? getSheetImage(asset.url, bump) : null;
2031
+ const rect = sliced && atlas ? subRectFor(atlas, asset.sprite) : null;
2032
+ React96.useEffect(() => {
2033
+ const canvas = canvasRef.current;
2034
+ if (!canvas || !img || !rect) return;
2035
+ canvas.width = rect.sw;
2036
+ canvas.height = rect.sh;
2037
+ const ctx = canvas.getContext("2d");
2038
+ if (!ctx) return;
2039
+ ctx.imageSmoothingEnabled = false;
2040
+ ctx.clearRect(0, 0, rect.sw, rect.sh);
2041
+ ctx.drawImage(img, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
2042
+ }, [img, rect?.sx, rect?.sy, rect?.sw, rect?.sh]);
2043
+ const w = fill ? "100%" : width ?? size;
2044
+ const h = fill ? "100%" : height ?? size;
2045
+ const boxStyle = {
2046
+ ...fill ? { position: "absolute", inset: 0 } : {},
2047
+ width: w,
2048
+ height: h,
2049
+ objectFit: fit,
2050
+ imageRendering: "pixelated",
2051
+ ...style
2052
+ };
2053
+ if (!asset?.url) return null;
2054
+ if (sliced) {
2055
+ if (!rect || !img) {
2056
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("inline-block flex-shrink-0", className), style: { ...boxStyle, objectFit: void 0 } });
2057
+ }
2058
+ return /* @__PURE__ */ jsx(
2059
+ "canvas",
2060
+ {
2061
+ ref: canvasRef,
2062
+ role: ariaHidden ? void 0 : "img",
2063
+ "aria-hidden": ariaHidden,
2064
+ "aria-label": ariaHidden ? void 0 : alt ?? asset.name ?? asset.category ?? "",
2065
+ className: cn("flex-shrink-0", className),
2066
+ style: boxStyle
2067
+ }
2068
+ );
2069
+ }
2070
+ return /* @__PURE__ */ jsx(
2071
+ "img",
2072
+ {
2073
+ src: asset.url,
2074
+ alt: alt ?? asset.name ?? asset.category ?? "",
2075
+ "aria-hidden": ariaHidden,
2076
+ ...typeof w === "number" ? { width: w } : {},
2077
+ ...typeof h === "number" ? { height: h } : {},
2078
+ className: cn("flex-shrink-0", className),
2079
+ style: boxStyle
2080
+ }
2081
+ );
2082
+ }
2083
+ var sliceDataUrlCache, imageCache, imageWaiters;
2084
+ var init_AtlasImage = __esm({
2085
+ "components/core/atoms/AtlasImage.tsx"() {
2086
+ "use client";
2087
+ init_atlasSlice();
2088
+ init_cn();
2089
+ sliceDataUrlCache = /* @__PURE__ */ new Map();
2090
+ AtlasPanel.displayName = "AtlasPanel";
2091
+ imageCache = /* @__PURE__ */ new Map();
2092
+ imageWaiters = /* @__PURE__ */ new Map();
2093
+ AtlasImage.displayName = "AtlasImage";
2094
+ }
2095
+ });
1892
2096
  function isIconLike(v) {
1893
2097
  return typeof v.render === "function";
1894
2098
  }
@@ -1901,7 +2105,7 @@ function resolveIconProp(value, sizeClass) {
1901
2105
  const IconComp = value;
1902
2106
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
1903
2107
  }
1904
- if (React95__default.isValidElement(value)) {
2108
+ if (React96__default.isValidElement(value)) {
1905
2109
  return value;
1906
2110
  }
1907
2111
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -1917,6 +2121,7 @@ var init_Button = __esm({
1917
2121
  init_cn();
1918
2122
  init_useEventBus();
1919
2123
  init_Icon();
2124
+ init_AtlasImage();
1920
2125
  variantStyles = {
1921
2126
  primary: [
1922
2127
  "bg-primary text-primary-foreground",
@@ -1977,7 +2182,7 @@ var init_Button = __esm({
1977
2182
  md: "h-icon-default w-icon-default",
1978
2183
  lg: "h-icon-default w-icon-default"
1979
2184
  };
1980
- Button = React95__default.forwardRef(
2185
+ Button = React96__default.forwardRef(
1981
2186
  ({
1982
2187
  className,
1983
2188
  variant = "primary",
@@ -2001,7 +2206,7 @@ var init_Button = __esm({
2001
2206
  const leftIconValue = leftIcon || iconProp;
2002
2207
  const rightIconValue = rightIcon || iconRightProp;
2003
2208
  const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
2004
- const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ jsx("img", { src: iconAsset.url, alt: iconAsset.name ?? iconAsset.category ?? "", width: px, height: px, style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px }, className: "flex-shrink-0" }) : resolveIconProp(leftIconValue, iconSizeStyles[size]);
2209
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ jsx(AtlasImage, { asset: iconAsset, size: px, alt: iconAsset.name ?? iconAsset.category ?? "", className: "flex-shrink-0" }) : resolveIconProp(leftIconValue, iconSizeStyles[size]);
2005
2210
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
2006
2211
  const handleClick = (e) => {
2007
2212
  if (action) {
@@ -2045,7 +2250,7 @@ var Dialog;
2045
2250
  var init_Dialog = __esm({
2046
2251
  "components/core/atoms/Dialog.tsx"() {
2047
2252
  init_cn();
2048
- Dialog = React95__default.forwardRef(
2253
+ Dialog = React96__default.forwardRef(
2049
2254
  ({
2050
2255
  role = "dialog",
2051
2256
  "aria-modal": ariaModal = true,
@@ -2163,7 +2368,7 @@ var init_Typography = __esm({
2163
2368
  }) => {
2164
2369
  const variant = variantProp ?? (level ? `h${level}` : "body1");
2165
2370
  const Component = as || defaultElements[variant];
2166
- return React95__default.createElement(
2371
+ return React96__default.createElement(
2167
2372
  Component,
2168
2373
  {
2169
2374
  id,
@@ -2621,6 +2826,7 @@ var init_Badge = __esm({
2621
2826
  "components/core/atoms/Badge.tsx"() {
2622
2827
  init_cn();
2623
2828
  init_Icon();
2829
+ init_AtlasImage();
2624
2830
  variantStyles3 = {
2625
2831
  default: [
2626
2832
  "bg-muted text-foreground",
@@ -2658,7 +2864,7 @@ var init_Badge = __esm({
2658
2864
  md: "px-2.5 py-1 text-sm",
2659
2865
  lg: "px-3 py-1.5 text-base"
2660
2866
  };
2661
- Badge = React95__default.forwardRef(
2867
+ Badge = React96__default.forwardRef(
2662
2868
  ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2663
2869
  const iconSizes3 = {
2664
2870
  sm: "h-icon-default w-icon-default",
@@ -2666,7 +2872,7 @@ var init_Badge = __esm({
2666
2872
  lg: "h-icon-default w-icon-default"
2667
2873
  };
2668
2874
  const iconPx = size === "lg" ? 20 : 16;
2669
- const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ jsx("img", { src: iconAsset.url, alt: iconAsset.name ?? iconAsset.category ?? "", width: iconPx, height: iconPx, style: { imageRendering: "pixelated", objectFit: "contain", width: iconPx, height: iconPx }, className: "flex-shrink-0" }) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2875
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ jsx(AtlasImage, { asset: iconAsset, size: iconPx, alt: iconAsset.name ?? iconAsset.category ?? "", className: "flex-shrink-0" }) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2670
2876
  return /* @__PURE__ */ jsxs(
2671
2877
  "span",
2672
2878
  {
@@ -2995,7 +3201,7 @@ var init_SvgFlow = __esm({
2995
3201
  width = 100,
2996
3202
  height = 100
2997
3203
  }) => {
2998
- const markerId = React95__default.useMemo(() => {
3204
+ const markerId = React96__default.useMemo(() => {
2999
3205
  flowIdCounter += 1;
3000
3206
  return `almadar-flow-arrow-${flowIdCounter}`;
3001
3207
  }, []);
@@ -3588,7 +3794,7 @@ var init_SvgRing = __esm({
3588
3794
  width = 100,
3589
3795
  height = 100
3590
3796
  }) => {
3591
- const gradientId = React95__default.useMemo(() => {
3797
+ const gradientId = React96__default.useMemo(() => {
3592
3798
  ringIdCounter += 1;
3593
3799
  return `almadar-ring-glow-${ringIdCounter}`;
3594
3800
  }, []);
@@ -3769,7 +3975,7 @@ var init_Input = __esm({
3769
3975
  init_cn();
3770
3976
  init_Icon();
3771
3977
  init_useEventBus();
3772
- Input = React95__default.forwardRef(
3978
+ Input = React96__default.forwardRef(
3773
3979
  ({
3774
3980
  className,
3775
3981
  inputType,
@@ -3929,7 +4135,7 @@ var Label;
3929
4135
  var init_Label = __esm({
3930
4136
  "components/core/atoms/Label.tsx"() {
3931
4137
  init_cn();
3932
- Label = React95__default.forwardRef(
4138
+ Label = React96__default.forwardRef(
3933
4139
  ({ className, required, children, ...props }, ref) => {
3934
4140
  return /* @__PURE__ */ jsxs(
3935
4141
  "label",
@@ -3956,7 +4162,7 @@ var init_Textarea = __esm({
3956
4162
  "components/core/atoms/Textarea.tsx"() {
3957
4163
  init_cn();
3958
4164
  init_useEventBus();
3959
- Textarea = React95__default.forwardRef(
4165
+ Textarea = React96__default.forwardRef(
3960
4166
  ({ className, error, onChange, ...props }, ref) => {
3961
4167
  const eventBus = useEventBus();
3962
4168
  const handleChange = (e) => {
@@ -4195,7 +4401,7 @@ var init_Select = __esm({
4195
4401
  init_cn();
4196
4402
  init_Icon();
4197
4403
  init_useEventBus();
4198
- Select = React95__default.forwardRef(
4404
+ Select = React96__default.forwardRef(
4199
4405
  (props, _ref) => {
4200
4406
  const { multiple, searchable, clearable } = props;
4201
4407
  if (multiple || searchable || clearable) {
@@ -4212,7 +4418,7 @@ var init_Checkbox = __esm({
4212
4418
  "components/core/atoms/Checkbox.tsx"() {
4213
4419
  init_cn();
4214
4420
  init_useEventBus();
4215
- Checkbox = React95__default.forwardRef(
4421
+ Checkbox = React96__default.forwardRef(
4216
4422
  ({ className, label, id, onChange, ...props }, ref) => {
4217
4423
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
4218
4424
  const eventBus = useEventBus();
@@ -4266,7 +4472,7 @@ var init_Spinner = __esm({
4266
4472
  md: "h-6 w-6",
4267
4473
  lg: "h-8 w-8"
4268
4474
  };
4269
- Spinner = React95__default.forwardRef(
4475
+ Spinner = React96__default.forwardRef(
4270
4476
  ({ className, size = "md", overlay, ...props }, ref) => {
4271
4477
  if (overlay) {
4272
4478
  return /* @__PURE__ */ jsx(
@@ -4356,7 +4562,7 @@ var init_Card = __esm({
4356
4562
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
4357
4563
  "tile-image-first": "p-0 overflow-hidden"
4358
4564
  };
4359
- Card = React95__default.forwardRef(
4565
+ Card = React96__default.forwardRef(
4360
4566
  ({
4361
4567
  className,
4362
4568
  variant = "bordered",
@@ -4404,9 +4610,9 @@ var init_Card = __esm({
4404
4610
  }
4405
4611
  );
4406
4612
  Card.displayName = "Card";
4407
- CardHeader = React95__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
4613
+ CardHeader = React96__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
4408
4614
  CardHeader.displayName = "CardHeader";
4409
- CardTitle = React95__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4615
+ CardTitle = React96__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4410
4616
  "h3",
4411
4617
  {
4412
4618
  ref,
@@ -4419,11 +4625,11 @@ var init_Card = __esm({
4419
4625
  }
4420
4626
  ));
4421
4627
  CardTitle.displayName = "CardTitle";
4422
- CardContent = React95__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
4628
+ CardContent = React96__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
4423
4629
  CardContent.displayName = "CardContent";
4424
4630
  CardBody = CardContent;
4425
4631
  CardBody.displayName = "CardBody";
4426
- CardFooter = React95__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4632
+ CardFooter = React96__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4427
4633
  "div",
4428
4634
  {
4429
4635
  ref,
@@ -4478,7 +4684,7 @@ var init_FilterPill = __esm({
4478
4684
  md: "w-3.5 h-3.5",
4479
4685
  lg: "w-4 h-4"
4480
4686
  };
4481
- FilterPill = React95__default.forwardRef(
4687
+ FilterPill = React96__default.forwardRef(
4482
4688
  ({
4483
4689
  className,
4484
4690
  variant = "default",
@@ -4607,8 +4813,8 @@ var init_Avatar = __esm({
4607
4813
  actionPayload
4608
4814
  }) => {
4609
4815
  const eventBus = useEventBus();
4610
- const [imgFailed, setImgFailed] = React95__default.useState(false);
4611
- React95__default.useEffect(() => {
4816
+ const [imgFailed, setImgFailed] = React96__default.useState(false);
4817
+ React96__default.useEffect(() => {
4612
4818
  setImgFailed(false);
4613
4819
  }, [src]);
4614
4820
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -4721,7 +4927,7 @@ var init_Center = __esm({
4721
4927
  as: Component = "div"
4722
4928
  }) => {
4723
4929
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
4724
- return React95__default.createElement(Component, {
4930
+ return React96__default.createElement(Component, {
4725
4931
  className: cn(
4726
4932
  inline ? "inline-flex" : "flex",
4727
4933
  horizontal && "justify-center",
@@ -4989,7 +5195,7 @@ var init_Radio = __esm({
4989
5195
  md: "w-2.5 h-2.5",
4990
5196
  lg: "w-3 h-3"
4991
5197
  };
4992
- Radio = React95__default.forwardRef(
5198
+ Radio = React96__default.forwardRef(
4993
5199
  ({
4994
5200
  label,
4995
5201
  helperText,
@@ -5006,12 +5212,12 @@ var init_Radio = __esm({
5006
5212
  onChange,
5007
5213
  ...props
5008
5214
  }, ref) => {
5009
- const reactId = React95__default.useId();
5215
+ const reactId = React96__default.useId();
5010
5216
  const baseId = id || `radio-${reactId}`;
5011
5217
  const hasError = !!error;
5012
5218
  const eventBus = useEventBus();
5013
- const [selected, setSelected] = React95__default.useState(value);
5014
- React95__default.useEffect(() => {
5219
+ const [selected, setSelected] = React96__default.useState(value);
5220
+ React96__default.useEffect(() => {
5015
5221
  if (value !== void 0) setSelected(value);
5016
5222
  }, [value]);
5017
5223
  const pick = (next, e) => {
@@ -5193,7 +5399,7 @@ var init_Switch = __esm({
5193
5399
  "components/core/atoms/Switch.tsx"() {
5194
5400
  "use client";
5195
5401
  init_cn();
5196
- Switch = React95.forwardRef(
5402
+ Switch = React96.forwardRef(
5197
5403
  ({
5198
5404
  checked,
5199
5405
  defaultChecked = false,
@@ -5204,10 +5410,10 @@ var init_Switch = __esm({
5204
5410
  name,
5205
5411
  className
5206
5412
  }, ref) => {
5207
- const [isChecked, setIsChecked] = React95.useState(
5413
+ const [isChecked, setIsChecked] = React96.useState(
5208
5414
  checked !== void 0 ? checked : defaultChecked
5209
5415
  );
5210
- React95.useEffect(() => {
5416
+ React96.useEffect(() => {
5211
5417
  if (checked !== void 0) {
5212
5418
  setIsChecked(checked);
5213
5419
  }
@@ -5370,7 +5576,7 @@ var init_Stack = __esm({
5370
5576
  };
5371
5577
  const isHorizontal = direction === "horizontal";
5372
5578
  const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
5373
- return React95__default.createElement(
5579
+ return React96__default.createElement(
5374
5580
  Component,
5375
5581
  {
5376
5582
  className: cn(
@@ -5570,7 +5776,7 @@ var Aside;
5570
5776
  var init_Aside = __esm({
5571
5777
  "components/core/atoms/Aside.tsx"() {
5572
5778
  init_cn();
5573
- Aside = React95__default.forwardRef(
5779
+ Aside = React96__default.forwardRef(
5574
5780
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
5575
5781
  );
5576
5782
  Aside.displayName = "Aside";
@@ -5649,9 +5855,9 @@ var init_LawReferenceTooltip = __esm({
5649
5855
  className
5650
5856
  }) => {
5651
5857
  const { t } = useTranslate();
5652
- const [isVisible, setIsVisible] = React95__default.useState(false);
5653
- const timeoutRef = React95__default.useRef(null);
5654
- const triggerRef = React95__default.useRef(null);
5858
+ const [isVisible, setIsVisible] = React96__default.useState(false);
5859
+ const timeoutRef = React96__default.useRef(null);
5860
+ const triggerRef = React96__default.useRef(null);
5655
5861
  const handleMouseEnter = () => {
5656
5862
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5657
5863
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -5662,7 +5868,7 @@ var init_LawReferenceTooltip = __esm({
5662
5868
  };
5663
5869
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
5664
5870
  const open = isVisible || revealed;
5665
- React95__default.useEffect(() => {
5871
+ React96__default.useEffect(() => {
5666
5872
  return () => {
5667
5873
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5668
5874
  };
@@ -5872,7 +6078,7 @@ var init_StatusDot = __esm({
5872
6078
  md: "w-2.5 h-2.5",
5873
6079
  lg: "w-3 h-3"
5874
6080
  };
5875
- StatusDot = React95__default.forwardRef(
6081
+ StatusDot = React96__default.forwardRef(
5876
6082
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
5877
6083
  return /* @__PURE__ */ jsx(
5878
6084
  "span",
@@ -5926,7 +6132,7 @@ var init_TrendIndicator = __esm({
5926
6132
  down: "trending-down",
5927
6133
  flat: "arrow-right"
5928
6134
  };
5929
- TrendIndicator = React95__default.forwardRef(
6135
+ TrendIndicator = React96__default.forwardRef(
5930
6136
  ({
5931
6137
  className,
5932
6138
  value,
@@ -5993,7 +6199,7 @@ var init_RangeSlider = __esm({
5993
6199
  md: "w-4 h-4",
5994
6200
  lg: "w-5 h-5"
5995
6201
  };
5996
- RangeSlider = React95__default.forwardRef(
6202
+ RangeSlider = React96__default.forwardRef(
5997
6203
  ({
5998
6204
  className,
5999
6205
  min = 0,
@@ -6552,7 +6758,7 @@ var init_ContentSection = __esm({
6552
6758
  md: "py-16",
6553
6759
  lg: "py-24"
6554
6760
  };
6555
- ContentSection = React95__default.forwardRef(
6761
+ ContentSection = React96__default.forwardRef(
6556
6762
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
6557
6763
  return /* @__PURE__ */ jsx(
6558
6764
  Box,
@@ -7086,7 +7292,7 @@ var init_AnimatedReveal = __esm({
7086
7292
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
7087
7293
  "none": {}
7088
7294
  };
7089
- AnimatedReveal = React95__default.forwardRef(
7295
+ AnimatedReveal = React96__default.forwardRef(
7090
7296
  ({
7091
7297
  trigger = "scroll",
7092
7298
  animation = "fade-up",
@@ -7246,7 +7452,7 @@ var init_AnimatedGraphic = __esm({
7246
7452
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
7247
7453
  "use client";
7248
7454
  init_cn();
7249
- AnimatedGraphic = React95__default.forwardRef(
7455
+ AnimatedGraphic = React96__default.forwardRef(
7250
7456
  ({
7251
7457
  src,
7252
7458
  svgContent,
@@ -7269,7 +7475,7 @@ var init_AnimatedGraphic = __esm({
7269
7475
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
7270
7476
  const resolvedSvg = svgContent ?? fetchedSvg;
7271
7477
  const prevAnimateRef = useRef(animate);
7272
- const setRef = React95__default.useCallback(
7478
+ const setRef = React96__default.useCallback(
7273
7479
  (node) => {
7274
7480
  containerRef.current = node;
7275
7481
  if (typeof ref === "function") ref(node);
@@ -7741,7 +7947,7 @@ function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
7741
7947
  }
7742
7948
  if (layout === "flat") {
7743
7949
  const screenX2 = tileX * scaledTileWidth + baseOffsetX;
7744
- const screenY2 = tileY * scaledFloorHeight;
7950
+ const screenY2 = tileY * scaledTileWidth;
7745
7951
  return { x: screenX2, y: screenY2 };
7746
7952
  }
7747
7953
  const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
@@ -7758,7 +7964,7 @@ function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric")
7758
7964
  }
7759
7965
  if (layout === "flat") {
7760
7966
  const col = Math.round((screenX - baseOffsetX) / scaledTileWidth);
7761
- const row = Math.round(screenY / scaledFloorHeight);
7967
+ const row = Math.round(screenY / scaledTileWidth);
7762
7968
  return { x: col, y: row };
7763
7969
  }
7764
7970
  const adjustedX = screenX - baseOffsetX;
@@ -7832,13 +8038,11 @@ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
7832
8038
  const px = typeof size === "number" ? size : sizeMap[size];
7833
8039
  if (assetUrl?.url) {
7834
8040
  return /* @__PURE__ */ jsx(
7835
- "img",
8041
+ AtlasImage,
7836
8042
  {
7837
- src: assetUrl.url,
8043
+ asset: assetUrl,
8044
+ size: px,
7838
8045
  alt: alt ?? assetUrl.category ?? "",
7839
- width: px,
7840
- height: px,
7841
- style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
7842
8046
  className: cn("flex-shrink-0", className)
7843
8047
  }
7844
8048
  );
@@ -7852,6 +8056,7 @@ var init_GameIcon = __esm({
7852
8056
  "use client";
7853
8057
  init_cn();
7854
8058
  init_Icon();
8059
+ init_AtlasImage();
7855
8060
  sizeMap = {
7856
8061
  sm: 16,
7857
8062
  md: 24,
@@ -7877,13 +8082,12 @@ function GameCard({
7877
8082
  className
7878
8083
  }) {
7879
8084
  const eventBus = useEventBus();
7880
- const handleClick = React95.useCallback(() => {
8085
+ const handleClick = React96.useCallback(() => {
7881
8086
  if (disabled) return;
7882
8087
  onClick?.(id);
7883
8088
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
7884
8089
  }, [disabled, id, onClick, clickEvent, eventBus]);
7885
8090
  const artPx = artPxMap[size];
7886
- const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
7887
8091
  return /* @__PURE__ */ jsxs(
7888
8092
  Button,
7889
8093
  {
@@ -7891,11 +8095,10 @@ function GameCard({
7891
8095
  onClick: handleClick,
7892
8096
  disabled,
7893
8097
  title: name,
7894
- style: frameStyle,
7895
8098
  className: cn(
7896
- "relative flex flex-col items-center rounded-interactive",
7897
- "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
7898
- frameAsset?.url ? "border-0" : "border-2",
8099
+ "relative isolate flex flex-col items-center rounded-interactive",
8100
+ "px-1.5 pt-1.5 pb-1 transition-all duration-150",
8101
+ frameAsset?.url ? "border-0" : "border-2 bg-card/90",
7899
8102
  cardSizeMap[size],
7900
8103
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
7901
8104
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -7903,6 +8106,7 @@ function GameCard({
7903
8106
  className
7904
8107
  ),
7905
8108
  children: [
8109
+ frameAsset?.url && /* @__PURE__ */ jsx(AtlasImage, { asset: frameAsset, fill: true, fit: "fill", "aria-hidden": true, style: { zIndex: -1 } }),
7906
8110
  cost != null && /* @__PURE__ */ jsx(
7907
8111
  Typography,
7908
8112
  {
@@ -7941,6 +8145,7 @@ var init_GameCard = __esm({
7941
8145
  init_Box();
7942
8146
  init_Button();
7943
8147
  init_Typography();
8148
+ init_AtlasImage();
7944
8149
  init_GameIcon();
7945
8150
  cardSizeMap = {
7946
8151
  sm: "w-16 h-24",
@@ -8101,7 +8306,7 @@ var init_HealthBar = __esm({
8101
8306
  }
8102
8307
  });
8103
8308
  function ScoreDisplay({
8104
- assetUrl = DEFAULT_ASSET_URL,
8309
+ assetUrl,
8105
8310
  value,
8106
8311
  score,
8107
8312
  label,
@@ -8128,7 +8333,7 @@ function ScoreDisplay({
8128
8333
  }
8129
8334
  );
8130
8335
  }
8131
- var sizeMap3, DEFAULT_ASSET_URL;
8336
+ var sizeMap3;
8132
8337
  var init_ScoreDisplay = __esm({
8133
8338
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
8134
8339
  init_cn();
@@ -8142,16 +8347,11 @@ var init_ScoreDisplay = __esm({
8142
8347
  lg: "text-2xl",
8143
8348
  xl: "text-4xl"
8144
8349
  };
8145
- DEFAULT_ASSET_URL = {
8146
- url: "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png",
8147
- role: "effect",
8148
- category: "effect"
8149
- };
8150
8350
  ScoreDisplay.displayName = "ScoreDisplay";
8151
8351
  }
8152
8352
  });
8153
8353
  function ControlButton({
8154
- assetUrl = DEFAULT_ASSET_URL2,
8354
+ assetUrl = DEFAULT_ASSET_URL,
8155
8355
  label,
8156
8356
  icon,
8157
8357
  size = "md",
@@ -8166,9 +8366,9 @@ function ControlButton({
8166
8366
  className
8167
8367
  }) {
8168
8368
  const eventBus = useEventBus();
8169
- const [isPressed, setIsPressed] = React95.useState(false);
8369
+ const [isPressed, setIsPressed] = React96.useState(false);
8170
8370
  const actualPressed = pressed ?? isPressed;
8171
- const handlePointerDown = React95.useCallback(
8371
+ const handlePointerDown = React96.useCallback(
8172
8372
  (e) => {
8173
8373
  e.preventDefault();
8174
8374
  if (disabled) return;
@@ -8178,7 +8378,7 @@ function ControlButton({
8178
8378
  },
8179
8379
  [disabled, pressEvent, eventBus, onPress]
8180
8380
  );
8181
- const handlePointerUp = React95.useCallback(
8381
+ const handlePointerUp = React96.useCallback(
8182
8382
  (e) => {
8183
8383
  e.preventDefault();
8184
8384
  if (disabled) return;
@@ -8188,7 +8388,7 @@ function ControlButton({
8188
8388
  },
8189
8389
  [disabled, releaseEvent, eventBus, onRelease]
8190
8390
  );
8191
- const handlePointerLeave = React95.useCallback(
8391
+ const handlePointerLeave = React96.useCallback(
8192
8392
  (e) => {
8193
8393
  if (isPressed) {
8194
8394
  setIsPressed(false);
@@ -8229,7 +8429,7 @@ function ControlButton({
8229
8429
  }
8230
8430
  );
8231
8431
  }
8232
- var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
8432
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL;
8233
8433
  var init_ControlButton = __esm({
8234
8434
  "components/game/2d/atoms/ControlButton.tsx"() {
8235
8435
  "use client";
@@ -8256,7 +8456,7 @@ var init_ControlButton = __esm({
8256
8456
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
8257
8457
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
8258
8458
  };
8259
- DEFAULT_ASSET_URL2 = {
8459
+ DEFAULT_ASSET_URL = {
8260
8460
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
8261
8461
  role: "ui",
8262
8462
  category: "control"
@@ -8349,7 +8549,7 @@ function isKnownState(s) {
8349
8549
  return s in DEFAULT_STATE_STYLES;
8350
8550
  }
8351
8551
  function StateIndicator({
8352
- assetUrl = DEFAULT_ASSET_URL3,
8552
+ assetUrl = DEFAULT_ASSET_URL2,
8353
8553
  state = "idle",
8354
8554
  label,
8355
8555
  size = "md",
@@ -8379,14 +8579,14 @@ function StateIndicator({
8379
8579
  }
8380
8580
  );
8381
8581
  }
8382
- var DEFAULT_ASSET_URL3, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
8582
+ var DEFAULT_ASSET_URL2, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
8383
8583
  var init_StateIndicator = __esm({
8384
8584
  "components/game/2d/atoms/StateIndicator.tsx"() {
8385
8585
  init_Box();
8386
8586
  init_Icon();
8387
8587
  init_cn();
8388
8588
  init_GameIcon();
8389
- DEFAULT_ASSET_URL3 = {
8589
+ DEFAULT_ASSET_URL2 = {
8390
8590
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
8391
8591
  role: "ui",
8392
8592
  category: "state"
@@ -8472,7 +8672,7 @@ var init_TimerDisplay = __esm({
8472
8672
  }
8473
8673
  });
8474
8674
  function ResourceCounter({
8475
- assetUrl = DEFAULT_ASSET_URL4,
8675
+ assetUrl = DEFAULT_ASSET_URL3,
8476
8676
  icon,
8477
8677
  label = "Gold",
8478
8678
  value = 250,
@@ -8505,7 +8705,7 @@ function ResourceCounter({
8505
8705
  }
8506
8706
  );
8507
8707
  }
8508
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
8708
+ var colorTokenClasses2, DEFAULT_ASSET_URL3, sizeMap6;
8509
8709
  var init_ResourceCounter = __esm({
8510
8710
  "components/game/2d/atoms/ResourceCounter.tsx"() {
8511
8711
  init_cn();
@@ -8521,7 +8721,7 @@ var init_ResourceCounter = __esm({
8521
8721
  error: "text-error",
8522
8722
  muted: "text-muted-foreground"
8523
8723
  };
8524
- DEFAULT_ASSET_URL4 = {
8724
+ DEFAULT_ASSET_URL3 = {
8525
8725
  url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
8526
8726
  role: "ui",
8527
8727
  category: "coin"
@@ -8535,7 +8735,7 @@ var init_ResourceCounter = __esm({
8535
8735
  }
8536
8736
  });
8537
8737
  function ItemSlot({
8538
- assetUrl = DEFAULT_ASSET_URL5,
8738
+ assetUrl = DEFAULT_ASSET_URL4,
8539
8739
  icon = "sword",
8540
8740
  label = "Iron Sword",
8541
8741
  quantity,
@@ -8590,7 +8790,7 @@ function ItemSlot({
8590
8790
  }
8591
8791
  );
8592
8792
  }
8593
- var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
8793
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
8594
8794
  var init_ItemSlot = __esm({
8595
8795
  "components/game/2d/atoms/ItemSlot.tsx"() {
8596
8796
  "use client";
@@ -8620,7 +8820,7 @@ var init_ItemSlot = __esm({
8620
8820
  epic: "shadow-lg",
8621
8821
  legendary: "shadow-lg"
8622
8822
  };
8623
- DEFAULT_ASSET_URL5 = {
8823
+ DEFAULT_ASSET_URL4 = {
8624
8824
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
8625
8825
  role: "item",
8626
8826
  category: "item"
@@ -8634,7 +8834,7 @@ var init_ItemSlot = __esm({
8634
8834
  }
8635
8835
  });
8636
8836
  function TurnIndicator({
8637
- assetUrl = DEFAULT_ASSET_URL6,
8837
+ assetUrl = DEFAULT_ASSET_URL5,
8638
8838
  currentTurn = 1,
8639
8839
  maxTurns,
8640
8840
  activeTeam,
@@ -8674,7 +8874,7 @@ function TurnIndicator({
8674
8874
  }
8675
8875
  );
8676
8876
  }
8677
- var sizeMap8, DEFAULT_ASSET_URL6;
8877
+ var sizeMap8, DEFAULT_ASSET_URL5;
8678
8878
  var init_TurnIndicator = __esm({
8679
8879
  "components/game/2d/atoms/TurnIndicator.tsx"() {
8680
8880
  init_cn();
@@ -8686,7 +8886,7 @@ var init_TurnIndicator = __esm({
8686
8886
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
8687
8887
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
8688
8888
  };
8689
- DEFAULT_ASSET_URL6 = {
8889
+ DEFAULT_ASSET_URL5 = {
8690
8890
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
8691
8891
  role: "ui",
8692
8892
  category: "turn"
@@ -8706,7 +8906,7 @@ function getComboScale(combo) {
8706
8906
  return "";
8707
8907
  }
8708
8908
  function ComboCounter({
8709
- assetUrl = DEFAULT_ASSET_URL7,
8909
+ assetUrl = DEFAULT_ASSET_URL6,
8710
8910
  combo = 5,
8711
8911
  multiplier,
8712
8912
  streak,
@@ -8741,14 +8941,14 @@ function ComboCounter({
8741
8941
  }
8742
8942
  );
8743
8943
  }
8744
- var DEFAULT_ASSET_URL7, sizeMap9;
8944
+ var DEFAULT_ASSET_URL6, sizeMap9;
8745
8945
  var init_ComboCounter = __esm({
8746
8946
  "components/game/2d/atoms/ComboCounter.tsx"() {
8747
8947
  init_cn();
8748
8948
  init_Box();
8749
8949
  init_Typography();
8750
8950
  init_GameIcon();
8751
- DEFAULT_ASSET_URL7 = {
8951
+ DEFAULT_ASSET_URL6 = {
8752
8952
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
8753
8953
  role: "effect",
8754
8954
  category: "effect"
@@ -8762,7 +8962,7 @@ var init_ComboCounter = __esm({
8762
8962
  }
8763
8963
  });
8764
8964
  function WaypointMarker({
8765
- assetUrl = DEFAULT_ASSET_URL8,
8965
+ assetUrl = DEFAULT_ASSET_URL7,
8766
8966
  label,
8767
8967
  icon,
8768
8968
  active = true,
@@ -8822,7 +9022,7 @@ function WaypointMarker({
8822
9022
  )
8823
9023
  ] });
8824
9024
  }
8825
- var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
9025
+ var DEFAULT_ASSET_URL7, sizeMap10, checkIcon;
8826
9026
  var init_WaypointMarker = __esm({
8827
9027
  "components/game/2d/atoms/WaypointMarker.tsx"() {
8828
9028
  init_cn();
@@ -8830,7 +9030,7 @@ var init_WaypointMarker = __esm({
8830
9030
  init_Box();
8831
9031
  init_Typography();
8832
9032
  init_GameIcon();
8833
- DEFAULT_ASSET_URL8 = {
9033
+ DEFAULT_ASSET_URL7 = {
8834
9034
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
8835
9035
  role: "ui",
8836
9036
  category: "waypoint"
@@ -8851,7 +9051,7 @@ function formatDuration(seconds) {
8851
9051
  return `${Math.round(seconds)}s`;
8852
9052
  }
8853
9053
  function StatusEffect({
8854
- assetUrl = DEFAULT_ASSET_URL9,
9054
+ assetUrl = DEFAULT_ASSET_URL8,
8855
9055
  icon,
8856
9056
  label = "Shield",
8857
9057
  duration = 30,
@@ -8902,7 +9102,7 @@ function StatusEffect({
8902
9102
  label && /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
8903
9103
  ] });
8904
9104
  }
8905
- var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
9105
+ var DEFAULT_ASSET_URL8, sizeMap11, variantStyles7;
8906
9106
  var init_StatusEffect = __esm({
8907
9107
  "components/game/2d/atoms/StatusEffect.tsx"() {
8908
9108
  init_cn();
@@ -8910,7 +9110,7 @@ var init_StatusEffect = __esm({
8910
9110
  init_Box();
8911
9111
  init_Typography();
8912
9112
  init_GameIcon();
8913
- DEFAULT_ASSET_URL9 = {
9113
+ DEFAULT_ASSET_URL8 = {
8914
9114
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
8915
9115
  role: "ui",
8916
9116
  category: "effect"
@@ -8929,7 +9129,7 @@ var init_StatusEffect = __esm({
8929
9129
  }
8930
9130
  });
8931
9131
  function DamageNumber({
8932
- assetUrl = DEFAULT_ASSET_URL10,
9132
+ assetUrl = DEFAULT_ASSET_URL9,
8933
9133
  value = 42,
8934
9134
  type = "damage",
8935
9135
  size = "md",
@@ -8957,7 +9157,7 @@ function DamageNumber({
8957
9157
  )
8958
9158
  ] });
8959
9159
  }
8960
- var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
9160
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL9;
8961
9161
  var init_DamageNumber = __esm({
8962
9162
  "components/game/2d/atoms/DamageNumber.tsx"() {
8963
9163
  init_cn();
@@ -8981,7 +9181,7 @@ var init_DamageNumber = __esm({
8981
9181
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
8982
9182
  }
8983
9183
  `;
8984
- DEFAULT_ASSET_URL10 = {
9184
+ DEFAULT_ASSET_URL9 = {
8985
9185
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
8986
9186
  role: "effect",
8987
9187
  category: "effect"
@@ -9107,7 +9307,7 @@ var init_ChoiceButton = __esm({
9107
9307
  }
9108
9308
  });
9109
9309
  function ActionButton({
9110
- assetUrl = DEFAULT_ASSET_URL11,
9310
+ assetUrl = DEFAULT_ASSET_URL10,
9111
9311
  label = "Attack",
9112
9312
  icon,
9113
9313
  cooldown = 0,
@@ -9176,7 +9376,7 @@ function ActionButton({
9176
9376
  }
9177
9377
  );
9178
9378
  }
9179
- var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
9379
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL10;
9180
9380
  var init_ActionButton = __esm({
9181
9381
  "components/game/2d/atoms/ActionButton.tsx"() {
9182
9382
  init_cn();
@@ -9196,7 +9396,7 @@ var init_ActionButton = __esm({
9196
9396
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
9197
9397
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
9198
9398
  };
9199
- DEFAULT_ASSET_URL11 = {
9399
+ DEFAULT_ASSET_URL10 = {
9200
9400
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
9201
9401
  role: "ui",
9202
9402
  category: "action"
@@ -9216,8 +9416,8 @@ function MiniMap({
9216
9416
  tileAssets,
9217
9417
  unitAssets
9218
9418
  }) {
9219
- const canvasRef = React95.useRef(null);
9220
- const imgCacheRef = React95.useRef(/* @__PURE__ */ new Map());
9419
+ const canvasRef = React96.useRef(null);
9420
+ const imgCacheRef = React96.useRef(/* @__PURE__ */ new Map());
9221
9421
  function loadImg(url) {
9222
9422
  const cached = imgCacheRef.current.get(url);
9223
9423
  if (cached) return cached.complete ? cached : null;
@@ -9232,7 +9432,7 @@ function MiniMap({
9232
9432
  imgCacheRef.current.set(url, img);
9233
9433
  return null;
9234
9434
  }
9235
- React95.useEffect(() => {
9435
+ React96.useEffect(() => {
9236
9436
  const canvas = canvasRef.current;
9237
9437
  if (!canvas) return;
9238
9438
  const ctx = canvas.getContext("2d");
@@ -9367,8 +9567,8 @@ function ControlGrid({
9367
9567
  className
9368
9568
  }) {
9369
9569
  const eventBus = useEventBus();
9370
- const [active, setActive] = React95.useState(/* @__PURE__ */ new Set());
9371
- const handlePress = React95.useCallback(
9570
+ const [active, setActive] = React96.useState(/* @__PURE__ */ new Set());
9571
+ const handlePress = React96.useCallback(
9372
9572
  (id) => {
9373
9573
  setActive((prev) => new Set(prev).add(id));
9374
9574
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -9382,7 +9582,7 @@ function ControlGrid({
9382
9582
  },
9383
9583
  [kind, actionEvent, directionEvent, directionEvents, eventBus, onAction, onDirection]
9384
9584
  );
9385
- const handleRelease = React95.useCallback(
9585
+ const handleRelease = React96.useCallback(
9386
9586
  (id) => {
9387
9587
  setActive((prev) => {
9388
9588
  const next = new Set(prev);
@@ -9640,7 +9840,7 @@ function InventoryGrid({
9640
9840
  const eventBus = useEventBus();
9641
9841
  const slotCount = totalSlots ?? items.length;
9642
9842
  const emptySlotCount = Math.max(0, slotCount - items.length);
9643
- const handleSelect = React95.useCallback(
9843
+ const handleSelect = React96.useCallback(
9644
9844
  (id) => {
9645
9845
  onSelect?.(id);
9646
9846
  if (selectEvent) {
@@ -9857,7 +10057,7 @@ function GameMenu({
9857
10057
  }) {
9858
10058
  const resolvedOptions = options ?? menuItems ?? DEFAULT_MENU_OPTIONS;
9859
10059
  const eventBus = useEventBus();
9860
- const handleOptionClick = React95.useCallback(
10060
+ const handleOptionClick = React96.useCallback(
9861
10061
  (option) => {
9862
10062
  if (option.event) {
9863
10063
  eventBus.emit(`UI:${option.event}`, { option });
@@ -10083,7 +10283,7 @@ function StateGraph({
10083
10283
  }) {
10084
10284
  const eventBus = useEventBus();
10085
10285
  const nodes = states ?? [];
10086
- const positions = React95.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
10286
+ const positions = React96.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
10087
10287
  return /* @__PURE__ */ jsxs(
10088
10288
  Box,
10089
10289
  {
@@ -10370,11 +10570,11 @@ function SideView({
10370
10570
  const canvasRef = useRef(null);
10371
10571
  const eventBus = useEventBus();
10372
10572
  const keysRef = useRef(/* @__PURE__ */ new Set());
10373
- const imageCache = useRef(/* @__PURE__ */ new Map());
10573
+ const imageCache2 = useRef(/* @__PURE__ */ new Map());
10374
10574
  const [loadedImages, setLoadedImages] = useState(/* @__PURE__ */ new Set());
10375
10575
  const loadImage = useCallback((url) => {
10376
10576
  if (!url) return null;
10377
- const cached = imageCache.current.get(url);
10577
+ const cached = imageCache2.current.get(url);
10378
10578
  if (cached?.complete && cached.naturalWidth > 0) {
10379
10579
  if (!loadedImages.has(url)) setLoadedImages((prev) => new Set(prev).add(url));
10380
10580
  return cached;
@@ -10384,7 +10584,7 @@ function SideView({
10384
10584
  img.crossOrigin = "anonymous";
10385
10585
  img.src = url;
10386
10586
  img.onload = () => setLoadedImages((prev) => new Set(prev).add(url));
10387
- imageCache.current.set(url, img);
10587
+ imageCache2.current.set(url, img);
10388
10588
  }
10389
10589
  return null;
10390
10590
  }, [loadedImages]);
@@ -10501,7 +10701,10 @@ function SideView({
10501
10701
  camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
10502
10702
  }
10503
10703
  const bgImage = bgImg ? loadImage(bgImg.url) : null;
10504
- if (bgImage) {
10704
+ const bgSrc = bgImage ? resolveAssetSource(bgImage, bgImg, NOOP) : null;
10705
+ if (bgSrc) {
10706
+ blit(ctx, bgSrc, 0, 0, cw, ch);
10707
+ } else if (bgImage) {
10505
10708
  ctx.drawImage(bgImage, 0, 0, cw, ch);
10506
10709
  } else if (bg) {
10507
10710
  ctx.fillStyle = bg;
@@ -10534,15 +10737,18 @@ function SideView({
10534
10737
  const platType = plat.type ?? "ground";
10535
10738
  const spriteAsset = tSprites?.[platType];
10536
10739
  const tileImg = spriteAsset ? loadImage(spriteAsset.url) : null;
10537
- if (tileImg) {
10538
- const tileW = tileImg.naturalWidth;
10539
- const tileH = tileImg.naturalHeight;
10740
+ const tileSrc = tileImg ? resolveAssetSource(tileImg, spriteAsset, NOOP) : null;
10741
+ if (tileSrc) {
10742
+ const originX = tileSrc.rect ? tileSrc.rect.sx : 0;
10743
+ const originY = tileSrc.rect ? tileSrc.rect.sy : 0;
10744
+ const tileW = tileSrc.rect ? tileSrc.rect.sw : tileImg.naturalWidth;
10745
+ const tileH = tileSrc.rect ? tileSrc.rect.sh : tileImg.naturalHeight;
10540
10746
  const scaleH = plat.height / tileH;
10541
10747
  const scaledW = tileW * scaleH;
10542
10748
  for (let tx = 0; tx < plat.width; tx += scaledW) {
10543
10749
  const drawW = Math.min(scaledW, plat.width - tx);
10544
10750
  const srcW = drawW / scaleH;
10545
- ctx.drawImage(tileImg, 0, 0, srcW, tileH, platX + tx, platY, drawW, plat.height);
10751
+ ctx.drawImage(tileImg, originX, originY, srcW, tileH, platX + tx, platY, drawW, plat.height);
10546
10752
  }
10547
10753
  } else {
10548
10754
  const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
@@ -10576,14 +10782,15 @@ function SideView({
10576
10782
  const ppy = py - camY;
10577
10783
  const facingRight = auth.facingRight ?? true;
10578
10784
  const playerImg = pSprite ? loadImage(pSprite.url) : null;
10579
- if (playerImg) {
10785
+ const playerSrc = playerImg ? resolveAssetSource(playerImg, pSprite, NOOP) : null;
10786
+ if (playerSrc) {
10580
10787
  ctx.save();
10581
10788
  if (!facingRight) {
10582
10789
  ctx.translate(ppx + pw, ppy);
10583
10790
  ctx.scale(-1, 1);
10584
- ctx.drawImage(playerImg, 0, 0, pw, ph);
10791
+ blit(ctx, playerSrc, 0, 0, pw, ph);
10585
10792
  } else {
10586
- ctx.drawImage(playerImg, ppx, ppy, pw, ph);
10793
+ blit(ctx, playerSrc, ppx, ppy, pw, ph);
10587
10794
  }
10588
10795
  ctx.restore();
10589
10796
  } else {
@@ -10695,6 +10902,7 @@ function Canvas2D({
10695
10902
  const isSide = projection === "side";
10696
10903
  const isFree = projection === "free";
10697
10904
  const flatLike = projection === "hex" || projection === "flat" || isFree;
10905
+ const squareGrid = projection === "flat";
10698
10906
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
10699
10907
  const unitsProp = Array.isArray(_unitsPropRaw) ? _unitsPropRaw : [];
10700
10908
  const featuresProp = Array.isArray(_featuresPropRaw) ? _featuresPropRaw : [];
@@ -10777,17 +10985,18 @@ function Canvas2D({
10777
10985
  const effectiveDiamondTopY = diamondTopYProp ?? DIAMOND_TOP_Y;
10778
10986
  const scaledDiamondTopY = effectiveDiamondTopY * scale;
10779
10987
  const baseOffsetX = useMemo(() => {
10780
- if (isFree) return 0;
10988
+ if (isFree || projection === "flat") return 0;
10781
10989
  return (gridHeight - 1) * (scaledTileWidth / 2);
10782
- }, [isFree, gridHeight, scaledTileWidth]);
10990
+ }, [isFree, projection, gridHeight, scaledTileWidth]);
10783
10991
  const validMoveSet = useMemo(() => new Set(validMoves.map((p) => `${p.x},${p.y}`)), [validMoves]);
10784
10992
  const attackTargetSet = useMemo(() => new Set(attackTargets.map((p) => `${p.x},${p.y}`)), [attackTargets]);
10785
10993
  const spriteUrls = useMemo(() => {
10786
10994
  const urls = [];
10995
+ const toUrl = (x) => typeof x === "string" ? x : x?.url;
10787
10996
  for (const tile of sortedTiles) {
10788
10997
  if (tile.terrainSprite) urls.push(tile.terrainSprite.url);
10789
10998
  else if (getTerrainSprite) {
10790
- const url = getTerrainSprite(tile.terrain ?? "");
10999
+ const url = toUrl(getTerrainSprite(tile.terrain ?? ""));
10791
11000
  if (url) urls.push(url);
10792
11001
  } else {
10793
11002
  const url = assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
@@ -10797,7 +11006,7 @@ function Canvas2D({
10797
11006
  for (const feature of features) {
10798
11007
  if (feature.sprite) urls.push(feature.sprite.url);
10799
11008
  else if (getFeatureSprite) {
10800
- const url = getFeatureSprite(feature.type);
11009
+ const url = toUrl(getFeatureSprite(feature.type));
10801
11010
  if (url) urls.push(url);
10802
11011
  } else {
10803
11012
  const url = assetManifest?.features?.[feature.type]?.url;
@@ -10807,7 +11016,7 @@ function Canvas2D({
10807
11016
  for (const unit of units) {
10808
11017
  if (unit.sprite) urls.push(unit.sprite.url);
10809
11018
  else if (getUnitSprite) {
10810
- const url = getUnitSprite(unit);
11019
+ const url = toUrl(getUnitSprite(unit));
10811
11020
  if (url) urls.push(url);
10812
11021
  } else if (unit.unitType) {
10813
11022
  const url = assetManifest?.units?.[unit.unitType]?.url;
@@ -10848,14 +11057,25 @@ function Canvas2D({
10848
11057
  screenToWorld,
10849
11058
  lerpToTarget
10850
11059
  } = useCamera();
10851
- const resolveTerrainSpriteUrl = useCallback((tile) => {
10852
- return tile.terrainSprite?.url || getTerrainSprite?.(tile.terrain ?? "") || assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11060
+ const [, setAtlasVersion] = useState(0);
11061
+ const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
11062
+ const resolveTerrainAsset = useCallback((tile) => {
11063
+ if (tile.terrainSprite) return tile.terrainSprite;
11064
+ const s = getTerrainSprite?.(tile.terrain ?? "");
11065
+ if (s) return typeof s === "string" ? { url: s } : s;
11066
+ return assetManifest?.terrains?.[tile.terrain ?? ""];
10853
11067
  }, [getTerrainSprite, assetManifest]);
10854
- const resolveFeatureSpriteUrl = useCallback((featureType) => {
10855
- return getFeatureSprite?.(featureType) || assetManifest?.features?.[featureType]?.url;
11068
+ const resolveFeatureAsset = useCallback((feature) => {
11069
+ if (feature.sprite) return feature.sprite;
11070
+ const s = getFeatureSprite?.(feature.type);
11071
+ if (s) return typeof s === "string" ? { url: s } : s;
11072
+ return assetManifest?.features?.[feature.type];
10856
11073
  }, [getFeatureSprite, assetManifest]);
10857
- const resolveUnitSpriteUrl = useCallback((unit) => {
10858
- return unit.sprite?.url || getUnitSprite?.(unit) || (unit.unitType ? assetManifest?.units?.[unit.unitType]?.url : void 0);
11074
+ const resolveUnitAsset = useCallback((unit) => {
11075
+ if (unit.sprite) return unit.sprite;
11076
+ const s = getUnitSprite?.(unit);
11077
+ if (s) return typeof s === "string" ? { url: s } : s;
11078
+ return unit.unitType ? assetManifest?.units?.[unit.unitType] : void 0;
10859
11079
  }, [getUnitSprite, assetManifest]);
10860
11080
  const miniMapTiles = useMemo(() => {
10861
11081
  if (!showMinimap) return [];
@@ -10888,7 +11108,13 @@ function Canvas2D({
10888
11108
  ctx.clearRect(0, 0, viewportSize.width, viewportSize.height);
10889
11109
  if (backgroundImage) {
10890
11110
  const bgImg = getImage(backgroundImage.url);
10891
- if (bgImg) {
11111
+ const bgSrc = bgImg ? resolveAssetSource(bgImg, backgroundImage, bumpAtlas) : null;
11112
+ if (bgSrc?.rect) {
11113
+ const k = Math.max(viewportSize.width / bgSrc.rect.sw, viewportSize.height / bgSrc.rect.sh);
11114
+ const dw = bgSrc.rect.sw * k;
11115
+ const dh = bgSrc.rect.sh * k;
11116
+ blit(ctx, bgSrc, (viewportSize.width - dw) / 2, (viewportSize.height - dh) / 2, dw, dh);
11117
+ } else if (bgImg) {
10892
11118
  const cam2 = cameraRef.current;
10893
11119
  const patW = bgImg.naturalWidth;
10894
11120
  const patH = bgImg.naturalHeight;
@@ -10919,18 +11145,23 @@ function Canvas2D({
10919
11145
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
10920
11146
  continue;
10921
11147
  }
10922
- const spriteUrl = resolveTerrainSpriteUrl(tile);
10923
- const img = spriteUrl ? getImage(spriteUrl) : null;
10924
- if (img) {
10925
- if (img.naturalWidth === 0) {
10926
- ctx.drawImage(img, pos.x, pos.y, scaledTileWidth, scaledTileHeight);
10927
- } else {
10928
- const drawW = scaledTileWidth;
10929
- const drawH = scaledTileWidth * (img.naturalHeight / img.naturalWidth);
10930
- const drawX = pos.x;
10931
- const drawY = flatLike ? pos.y : pos.y + scaledTileHeight - drawH;
10932
- ctx.drawImage(img, drawX, drawY, drawW, drawH);
10933
- }
11148
+ const terrainAsset = resolveTerrainAsset(tile);
11149
+ const img = terrainAsset?.url ? getImage(terrainAsset.url) : null;
11150
+ const src = img ? resolveAssetSource(img, terrainAsset, bumpAtlas) : null;
11151
+ if (src) {
11152
+ const drawW = scaledTileWidth;
11153
+ const drawH = squareGrid ? scaledTileWidth : scaledTileWidth / src.aspect;
11154
+ const drawX = pos.x;
11155
+ const drawY = flatLike ? pos.y : pos.y + scaledTileHeight - drawH;
11156
+ blit(ctx, src, drawX, drawY, drawW, drawH);
11157
+ } else if (img && img.naturalWidth === 0) {
11158
+ ctx.drawImage(img, pos.x, pos.y, scaledTileWidth, scaledTileHeight);
11159
+ } else if (squareGrid) {
11160
+ ctx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : tile.terrain === "stone" ? "#9ca3af" : "#4ade80";
11161
+ ctx.fillRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
11162
+ ctx.strokeStyle = "rgba(0,0,0,0.2)";
11163
+ ctx.lineWidth = 1;
11164
+ ctx.strokeRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
10934
11165
  } else {
10935
11166
  const centerX = pos.x + scaledTileWidth / 2;
10936
11167
  const topY = pos.y + scaledDiamondTopY;
@@ -10947,9 +11178,13 @@ function Canvas2D({
10947
11178
  ctx.stroke();
10948
11179
  }
10949
11180
  const drawHighlight = (color) => {
11181
+ ctx.fillStyle = color;
11182
+ if (squareGrid) {
11183
+ ctx.fillRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
11184
+ return;
11185
+ }
10950
11186
  const centerX = pos.x + scaledTileWidth / 2;
10951
11187
  const topY = pos.y + scaledDiamondTopY;
10952
- ctx.fillStyle = color;
10953
11188
  ctx.beginPath();
10954
11189
  ctx.moveTo(centerX, topY);
10955
11190
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -10966,7 +11201,7 @@ function Canvas2D({
10966
11201
  if (attackTargetSet.has(tileKey)) drawHighlight("rgba(239, 68, 68, 0.35)");
10967
11202
  if (debug2) {
10968
11203
  const centerX = pos.x + scaledTileWidth / 2;
10969
- const centerY = pos.y + scaledFloorHeight / 2 + scaledDiamondTopY;
11204
+ const centerY = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledFloorHeight / 2 + scaledDiamondTopY;
10970
11205
  ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
10971
11206
  ctx.font = `${12 * scale * 2}px monospace`;
10972
11207
  ctx.textAlign = "center";
@@ -10984,15 +11219,16 @@ function Canvas2D({
10984
11219
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
10985
11220
  continue;
10986
11221
  }
10987
- const spriteUrl = feature.sprite?.url || resolveFeatureSpriteUrl(feature.type);
10988
- const img = spriteUrl ? getImage(spriteUrl) : null;
11222
+ const featureAsset = resolveFeatureAsset(feature);
11223
+ const img = featureAsset?.url ? getImage(featureAsset.url) : null;
11224
+ const src = img ? resolveAssetSource(img, featureAsset, bumpAtlas) : null;
10989
11225
  const centerX = pos.x + scaledTileWidth / 2;
10990
- const featureGroundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11226
+ const featureGroundY = squareGrid ? pos.y + scaledTileWidth * 0.92 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10991
11227
  const isCastle = feature.type === "castle";
10992
- const featureDrawH = isCastle ? scaledFloorHeight * 3.5 : scaledFloorHeight * 1.6;
11228
+ const featureDrawH = squareGrid ? isCastle ? scaledTileWidth * 1.4 : scaledTileWidth * 0.8 : isCastle ? scaledFloorHeight * 3.5 : scaledFloorHeight * 1.6;
10993
11229
  const maxFeatureW = isCastle ? scaledTileWidth * 1.8 : scaledTileWidth * 0.7;
10994
- if (img) {
10995
- const ar = img.naturalWidth / img.naturalHeight;
11230
+ if (src) {
11231
+ const ar = src.aspect;
10996
11232
  let drawH = featureDrawH;
10997
11233
  let drawW = featureDrawH * ar;
10998
11234
  if (drawW > maxFeatureW) {
@@ -11001,7 +11237,7 @@ function Canvas2D({
11001
11237
  }
11002
11238
  const drawX = centerX - drawW / 2;
11003
11239
  const drawY = featureGroundY - drawH;
11004
- ctx.drawImage(img, drawX, drawY, drawW, drawH);
11240
+ blit(ctx, src, drawX, drawY, drawW, drawH);
11005
11241
  } else {
11006
11242
  const color = FEATURE_COLORS[feature.type] || FEATURE_COLORS.default;
11007
11243
  ctx.beginPath();
@@ -11028,19 +11264,20 @@ function Canvas2D({
11028
11264
  }
11029
11265
  const isSelected = unit.id === selectedUnitId;
11030
11266
  const centerX = pos.x + scaledTileWidth / 2;
11031
- const groundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11267
+ const groundY = squareGrid ? pos.y + scaledTileWidth * 0.92 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11032
11268
  const breatheOffset = 0;
11033
- const unitSpriteUrl = resolveUnitSpriteUrl(unit);
11034
- const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11035
- const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11269
+ const unitAsset = resolveUnitAsset(unit);
11270
+ const img = unitAsset?.url ? getImage(unitAsset.url) : null;
11271
+ const unitDrawH = squareGrid ? scaledTileWidth * 0.55 * spriteHeightRatio * unitScale : scaledFloorHeight * spriteHeightRatio * unitScale;
11036
11272
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11037
11273
  const unitIsSheet = unit.spriteSheet?.url !== void 0;
11274
+ const unitSrc = img && !unitIsSheet ? resolveAssetSource(img, unitAsset, bumpAtlas) : null;
11038
11275
  const SHEET_ROWS = 5;
11039
11276
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
11040
11277
  const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
11041
11278
  const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11042
11279
  const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11043
- const ar = frameW / (frameH || 1);
11280
+ const ar = unitIsSheet ? sheetFrameW / (sheetFrameH || 1) : unitSrc ? unitSrc.aspect : frameW / (frameH || 1);
11044
11281
  let drawH = unitDrawH;
11045
11282
  let drawW = unitDrawH * ar;
11046
11283
  if (drawW > maxUnitW) {
@@ -11050,12 +11287,14 @@ function Canvas2D({
11050
11287
  if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
11051
11288
  const ghostPos = project(unit.previousPosition.x, unit.previousPosition.y, baseOffsetX);
11052
11289
  const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
11053
- const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11290
+ const ghostGroundY = squareGrid ? ghostPos.y + scaledTileWidth * 0.92 : ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11054
11291
  ctx.save();
11055
11292
  ctx.globalAlpha = 0.25;
11056
11293
  if (img) {
11057
11294
  if (unitIsSheet) {
11058
11295
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11296
+ } else if (unitSrc) {
11297
+ blit(ctx, unitSrc, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11059
11298
  } else {
11060
11299
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11061
11300
  }
@@ -11104,6 +11343,8 @@ function Canvas2D({
11104
11343
  const drawUnit = (x) => {
11105
11344
  if (unitIsSheet) {
11106
11345
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
11346
+ } else if (unitSrc) {
11347
+ blit(ctx, unitSrc, x, spriteY, drawW, drawH);
11107
11348
  } else {
11108
11349
  ctx.drawImage(img, x, spriteY, drawW, drawH);
11109
11350
  }
@@ -11129,17 +11370,24 @@ function Canvas2D({
11129
11370
  }
11130
11371
  }
11131
11372
  for (const fx of effects) {
11132
- const spriteUrl = assetManifest?.effects?.[fx.key]?.url;
11133
- if (!spriteUrl) continue;
11134
- const img = getImage(spriteUrl);
11373
+ const fxAsset = assetManifest?.effects?.[fx.key];
11374
+ if (!fxAsset?.url) continue;
11375
+ const img = getImage(fxAsset.url);
11135
11376
  if (!img) continue;
11377
+ const src = resolveAssetSource(img, fxAsset, bumpAtlas);
11136
11378
  const pos = project(fx.x, fx.y, baseOffsetX);
11137
11379
  const cx = pos.x + scaledTileWidth / 2;
11138
- const cy = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11380
+ const cy = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11139
11381
  const alpha = Math.min(1, fx.ttl / 4);
11140
11382
  const prev = ctx.globalAlpha;
11141
11383
  ctx.globalAlpha = alpha;
11142
- ctx.drawImage(img, cx - img.naturalWidth / 2, cy - img.naturalHeight / 2);
11384
+ if (src?.rect) {
11385
+ const dw = scaledTileWidth;
11386
+ const dh = dw / src.aspect;
11387
+ blit(ctx, src, cx - dw / 2, cy - dh / 2, dw, dh);
11388
+ } else {
11389
+ ctx.drawImage(img, cx - img.naturalWidth / 2, cy - img.naturalHeight / 2);
11390
+ }
11143
11391
  ctx.globalAlpha = prev;
11144
11392
  }
11145
11393
  onDrawEffects?.(ctx, 0, getImage);
@@ -11152,13 +11400,15 @@ function Canvas2D({
11152
11400
  effects,
11153
11401
  project,
11154
11402
  flatLike,
11403
+ squareGrid,
11155
11404
  scale,
11156
11405
  debug2,
11157
- resolveTerrainSpriteUrl,
11158
- resolveFeatureSpriteUrl,
11159
- resolveUnitSpriteUrl,
11406
+ resolveTerrainAsset,
11407
+ resolveFeatureAsset,
11408
+ resolveUnitAsset,
11160
11409
  resolveFrameForUnit,
11161
11410
  getImage,
11411
+ bumpAtlas,
11162
11412
  baseOffsetX,
11163
11413
  scaledTileWidth,
11164
11414
  scaledTileHeight,
@@ -11184,12 +11434,12 @@ function Canvas2D({
11184
11434
  if (!unit?.position) return;
11185
11435
  const pos = project(unit.position.x, unit.position.y, baseOffsetX);
11186
11436
  const centerX = pos.x + scaledTileWidth / 2;
11187
- const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
11437
+ const centerY = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
11188
11438
  targetCameraRef.current = {
11189
11439
  x: centerX - viewportSize.width / 2,
11190
11440
  y: centerY - viewportSize.height / 2
11191
11441
  };
11192
- }, [camera, selectedUnitId, units, project, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
11442
+ }, [camera, selectedUnitId, units, project, baseOffsetX, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
11193
11443
  useEffect(() => {
11194
11444
  if (isSide || !interpolateUnits) return;
11195
11445
  unitInterp.onSnapshot(
@@ -11260,11 +11510,11 @@ function Canvas2D({
11260
11510
  if (!tileHoverEvent || !canvasRef.current) return;
11261
11511
  const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
11262
11512
  const adjustedX = world.x - scaledTileWidth / 2;
11263
- const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
11513
+ const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
11264
11514
  const isoPos = unproject(adjustedX, adjustedY, baseOffsetX);
11265
11515
  const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
11266
11516
  if (tileExists) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
11267
- }, [screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
11517
+ }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
11268
11518
  const handleCanvasPointerUp = useCallback((e) => {
11269
11519
  singlePointerActiveRef.current = false;
11270
11520
  if (enableCamera) handlePointerUp();
@@ -11272,7 +11522,7 @@ function Canvas2D({
11272
11522
  if (!canvasRef.current) return;
11273
11523
  const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
11274
11524
  const adjustedX = world.x - scaledTileWidth / 2;
11275
- const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
11525
+ const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
11276
11526
  const isoPos = unproject(adjustedX, adjustedY, baseOffsetX);
11277
11527
  const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
11278
11528
  if (clickedUnit && unitClickEvent) {
@@ -11281,7 +11531,7 @@ function Canvas2D({
11281
11531
  const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
11282
11532
  if (tileExists) eventBus.emit(`UI:${tileClickEvent}`, { x: isoPos.x, y: isoPos.y });
11283
11533
  }
11284
- }, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, units, tilesProp, unitClickEvent, tileClickEvent, eventBus]);
11534
+ }, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, units, tilesProp, unitClickEvent, tileClickEvent, eventBus]);
11285
11535
  const handleCanvasPointerLeave = useCallback(() => {
11286
11536
  handleMouseLeave();
11287
11537
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
@@ -11331,11 +11581,12 @@ function Canvas2D({
11331
11581
  return units.filter((u) => !!u.position).map((u) => {
11332
11582
  const pos = project(u.position.x, u.position.y, baseOffsetX);
11333
11583
  const cam = cameraRef.current;
11584
+ const anchorY = squareGrid ? pos.y + scaledTileWidth * 0.92 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11334
11585
  const screenX = (pos.x + scaledTileWidth / 2 - (cam.x + viewportSize.width / 2)) * cam.zoom + viewportSize.width / 2;
11335
- const screenY = (pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5 - (cam.y + viewportSize.height / 2)) * cam.zoom + viewportSize.height / 2;
11586
+ const screenY = (anchorY - (cam.y + viewportSize.height / 2)) * cam.zoom + viewportSize.height / 2;
11336
11587
  return { unit: u, screenX, screenY };
11337
11588
  });
11338
- }, [units, project, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, cameraRef]);
11589
+ }, [units, project, baseOffsetX, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, viewportSize, cameraRef]);
11339
11590
  if (error) {
11340
11591
  return /* @__PURE__ */ jsx(Box, { className: cn("flex items-center justify-center w-full h-full bg-[var(--color-card)] rounded-container", className), children: /* @__PURE__ */ jsxs(Stack, { direction: "vertical", gap: "md", align: "center", children: [
11341
11592
  /* @__PURE__ */ jsx(Icon, { name: "alert-circle", size: "xl" }),
@@ -11472,7 +11723,7 @@ function Canvas2D({
11472
11723
  }
11473
11724
  );
11474
11725
  }
11475
- var PLATFORM_COLORS, PLAYER_COLOR, PLAYER_EYE_COLOR, SKY_GRADIENT_TOP, SKY_GRADIENT_BOTTOM, GRID_COLOR, DEFAULT_PLATFORMS;
11726
+ var PLATFORM_COLORS, NOOP, PLAYER_COLOR, PLAYER_EYE_COLOR, SKY_GRADIENT_TOP, SKY_GRADIENT_BOTTOM, GRID_COLOR, DEFAULT_PLATFORMS;
11476
11727
  var init_Canvas2D = __esm({
11477
11728
  "components/game/2d/molecules/Canvas2D.tsx"() {
11478
11729
  "use client";
@@ -11486,6 +11737,7 @@ var init_Canvas2D = __esm({
11486
11737
  init_MiniMap();
11487
11738
  init_HealthBar();
11488
11739
  init_useImageCache();
11740
+ init_atlasSlice();
11489
11741
  init_useCamera();
11490
11742
  init_useCanvasGestures();
11491
11743
  init_useRenderInterpolation();
@@ -11499,6 +11751,8 @@ var init_Canvas2D = __esm({
11499
11751
  hazard: "#c0392b",
11500
11752
  goal: "#f1c40f"
11501
11753
  };
11754
+ NOOP = () => {
11755
+ };
11502
11756
  PLAYER_COLOR = "#3498db";
11503
11757
  PLAYER_EYE_COLOR = "#ffffff";
11504
11758
  SKY_GRADIENT_TOP = "#1a1a2e";
@@ -11578,7 +11832,7 @@ function LinearView({
11578
11832
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
11579
11833
  const isDone = i < currentIdx;
11580
11834
  const isCurrent = i === currentIdx;
11581
- return /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
11835
+ return /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
11582
11836
  i > 0 && /* @__PURE__ */ jsx(
11583
11837
  Typography,
11584
11838
  {
@@ -12113,7 +12367,7 @@ function SequenceBar({
12113
12367
  else onSlotRemove?.(index);
12114
12368
  }, [emit, slotRemoveEvent, onSlotRemove, playing]);
12115
12369
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
12116
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
12370
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
12117
12371
  i > 0 && /* @__PURE__ */ jsx(
12118
12372
  Typography,
12119
12373
  {
@@ -14270,82 +14524,167 @@ var init_GameTemplate = __esm({
14270
14524
  GameTemplate.displayName = "GameTemplate";
14271
14525
  }
14272
14526
  });
14273
- var GameShell;
14527
+ var FONT_BASE, GAME_FONTS, FONT_FACES, GameShell;
14274
14528
  var init_GameShell = __esm({
14275
14529
  "components/game/2d/templates/GameShell.tsx"() {
14276
14530
  init_cn();
14277
14531
  init_Box();
14278
- init_Stack();
14279
14532
  init_Typography();
14533
+ init_AtlasImage();
14534
+ FONT_BASE = "https://almadar-kflow-assets.web.app/shared/_shared/kenney-fonts/fonts";
14535
+ GAME_FONTS = {
14536
+ future: "Kenney Future",
14537
+ "future-narrow": "Kenney Future Narrow",
14538
+ pixel: "Kenney Pixel",
14539
+ blocks: "Kenney Blocks",
14540
+ mini: "Kenney Mini"
14541
+ };
14542
+ FONT_FACES = `
14543
+ @font-face { font-family: 'Kenney Future'; src: url('${FONT_BASE}/Kenney%20Future.ttf') format('truetype'); font-display: swap; }
14544
+ @font-face { font-family: 'Kenney Future Narrow'; src: url('${FONT_BASE}/Kenney%20Future%20Narrow.ttf') format('truetype'); font-display: swap; }
14545
+ @font-face { font-family: 'Kenney Pixel'; src: url('${FONT_BASE}/Kenney%20Pixel.ttf') format('truetype'); font-display: swap; }
14546
+ @font-face { font-family: 'Kenney Blocks'; src: url('${FONT_BASE}/Kenney%20Blocks.ttf') format('truetype'); font-display: swap; }
14547
+ @font-face { font-family: 'Kenney Mini'; src: url('${FONT_BASE}/Kenney%20Mini.ttf') format('truetype'); font-display: swap; }
14548
+ .game-shell, .game-shell * { font-family: inherit; }
14549
+ `;
14280
14550
  GameShell = ({
14281
14551
  appName = "Game",
14282
14552
  hud,
14553
+ addons,
14554
+ controls,
14555
+ overlay,
14283
14556
  className,
14284
14557
  showTopBar = true,
14285
14558
  children,
14286
14559
  backgroundAsset,
14287
- hudBackgroundAsset
14560
+ hudBackgroundAsset,
14561
+ fontFamily = "future"
14288
14562
  }) => {
14563
+ const font = GAME_FONTS[fontFamily] ?? fontFamily;
14289
14564
  return /* @__PURE__ */ jsxs(
14290
14565
  Box,
14291
14566
  {
14292
- display: "flex",
14293
- className: cn(
14294
- "game-shell",
14295
- "flex-col w-full h-screen overflow-hidden",
14296
- className
14297
- ),
14567
+ className: cn("game-shell", className),
14298
14568
  style: {
14569
+ position: "relative",
14299
14570
  width: "100vw",
14300
14571
  height: "100vh",
14301
14572
  overflow: "hidden",
14302
- background: backgroundAsset ? `url(${backgroundAsset.url}) center/cover no-repeat` : "var(--color-background, #0a0a0f)",
14303
- color: "var(--color-text, #e0e0e0)"
14573
+ background: "var(--color-background, #0a0a0f)",
14574
+ color: "var(--color-text, #e0e0e0)",
14575
+ fontFamily: `'${font}', system-ui, sans-serif`
14304
14576
  },
14305
14577
  children: [
14306
- showTopBar && /* @__PURE__ */ jsxs(
14578
+ /* @__PURE__ */ jsx("style", { children: FONT_FACES }),
14579
+ backgroundAsset && /* @__PURE__ */ jsx(
14580
+ AtlasPanel,
14581
+ {
14582
+ asset: backgroundAsset,
14583
+ mode: "repeat",
14584
+ "aria-hidden": true,
14585
+ className: "game-shell__bg",
14586
+ style: { position: "absolute", inset: 0, opacity: 0.18, zIndex: 0, display: "block" }
14587
+ }
14588
+ ),
14589
+ /* @__PURE__ */ jsx(Box, { className: "game-shell__content", style: { position: "absolute", inset: 0, zIndex: 1 }, children }),
14590
+ (showTopBar || hud) && /* @__PURE__ */ jsxs(
14307
14591
  Box,
14308
14592
  {
14309
- className: "game-shell__header",
14593
+ className: "game-shell__top pointer-events-none",
14310
14594
  style: {
14311
- flexShrink: 0,
14312
- background: hudBackgroundAsset ? `url(${hudBackgroundAsset.url}) center/cover no-repeat` : "var(--color-surface, #12121f)",
14313
- borderBottom: "1px solid var(--color-border, #2a2a3a)"
14595
+ position: "absolute",
14596
+ top: 12,
14597
+ left: 12,
14598
+ right: 12,
14599
+ zIndex: 2,
14600
+ display: "flex",
14601
+ alignItems: "flex-start",
14602
+ gap: 12
14314
14603
  },
14315
14604
  children: [
14316
- /* @__PURE__ */ jsx(
14317
- HStack,
14605
+ showTopBar && /* @__PURE__ */ jsx(
14606
+ AtlasPanel,
14318
14607
  {
14319
- align: "center",
14320
- justify: "between",
14321
- style: { padding: "0.375rem 1rem" },
14608
+ asset: hudBackgroundAsset,
14609
+ borderSlice: 12,
14610
+ borderWidth: 10,
14611
+ className: "game-shell__title pointer-events-auto",
14612
+ style: {
14613
+ padding: "6px 16px",
14614
+ background: hudBackgroundAsset ? void 0 : "rgba(18, 18, 31, 0.85)",
14615
+ borderRadius: hudBackgroundAsset ? void 0 : 10,
14616
+ boxShadow: "0 4px 14px rgba(0,0,0,0.45)",
14617
+ flexShrink: 0
14618
+ },
14322
14619
  children: /* @__PURE__ */ jsx(
14323
14620
  Typography,
14324
14621
  {
14325
- variant: "h6",
14622
+ as: "span",
14326
14623
  style: {
14327
14624
  fontWeight: 700,
14328
- letterSpacing: "0.02em"
14625
+ fontSize: "1.05rem",
14626
+ letterSpacing: "0.06em",
14627
+ textShadow: "0 2px 0 rgba(0,0,0,0.5)",
14628
+ whiteSpace: "nowrap"
14329
14629
  },
14330
14630
  children: appName
14331
14631
  }
14332
14632
  )
14333
14633
  }
14334
14634
  ),
14335
- hud && /* @__PURE__ */ jsx(Box, { className: "game-shell__hud", style: { width: "100%" }, children: hud })
14635
+ hud && /* @__PURE__ */ jsx(Box, { className: "game-shell__hud pointer-events-auto", style: { flex: 1, minWidth: 0 }, children: hud })
14336
14636
  ]
14337
14637
  }
14338
14638
  ),
14339
- /* @__PURE__ */ jsx(
14639
+ controls && /* @__PURE__ */ jsx(
14340
14640
  Box,
14341
14641
  {
14342
- className: "game-shell__content",
14642
+ className: "game-shell__controls pointer-events-auto",
14343
14643
  style: {
14344
- flex: 1,
14345
- overflow: "hidden",
14346
- position: "relative"
14644
+ position: "absolute",
14645
+ left: 16,
14646
+ bottom: 16,
14647
+ zIndex: 2,
14648
+ display: "flex",
14649
+ flexDirection: "column",
14650
+ alignItems: "flex-start",
14651
+ gap: 10,
14652
+ filter: "drop-shadow(0 6px 12px rgba(0,0,0,0.5))"
14347
14653
  },
14348
- children
14654
+ children: controls
14655
+ }
14656
+ ),
14657
+ addons && /* @__PURE__ */ jsx(
14658
+ Box,
14659
+ {
14660
+ className: "game-shell__actions pointer-events-auto",
14661
+ style: {
14662
+ position: "absolute",
14663
+ right: 16,
14664
+ bottom: 16,
14665
+ zIndex: 2,
14666
+ display: "flex",
14667
+ flexDirection: "column",
14668
+ alignItems: "flex-end",
14669
+ gap: 10,
14670
+ filter: "drop-shadow(0 6px 12px rgba(0,0,0,0.5))"
14671
+ },
14672
+ children: addons
14673
+ }
14674
+ ),
14675
+ overlay && /* @__PURE__ */ jsx(
14676
+ Box,
14677
+ {
14678
+ className: "game-shell__overlay pointer-events-none",
14679
+ style: {
14680
+ position: "absolute",
14681
+ inset: 0,
14682
+ zIndex: 3,
14683
+ display: "flex",
14684
+ alignItems: "center",
14685
+ justifyContent: "center"
14686
+ },
14687
+ children: /* @__PURE__ */ jsx(Box, { className: "pointer-events-auto", children: overlay })
14349
14688
  }
14350
14689
  )
14351
14690
  ]
@@ -14759,7 +15098,7 @@ var init_ErrorBoundary = __esm({
14759
15098
  }
14760
15099
  );
14761
15100
  };
14762
- ErrorBoundary = class extends React95__default.Component {
15101
+ ErrorBoundary = class extends React96__default.Component {
14763
15102
  constructor(props) {
14764
15103
  super(props);
14765
15104
  __publicField(this, "reset", () => {
@@ -15041,7 +15380,7 @@ var init_Container = __esm({
15041
15380
  as: Component = "div"
15042
15381
  }) => {
15043
15382
  const resolvedSize = maxWidth ?? size ?? "lg";
15044
- return React95__default.createElement(
15383
+ return React96__default.createElement(
15045
15384
  Component,
15046
15385
  {
15047
15386
  className: cn(
@@ -16157,6 +16496,153 @@ var init_ComponentPatterns = __esm({
16157
16496
  AlertPattern.displayName = "AlertPattern";
16158
16497
  }
16159
16498
  });
16499
+ var DEFAULT_BAR_COLOR, DEFAULT_CELL_COLOR, DEFAULT_POINTER_COLOR, POINTER_BAND, TOP_PAD, AlgorithmCanvas;
16500
+ var init_AlgorithmCanvas = __esm({
16501
+ "components/learning/molecules/AlgorithmCanvas.tsx"() {
16502
+ "use client";
16503
+ init_atoms();
16504
+ init_Stack();
16505
+ init_LearningCanvas();
16506
+ DEFAULT_BAR_COLOR = "#3b82f6";
16507
+ DEFAULT_CELL_COLOR = "#e5e7eb";
16508
+ DEFAULT_POINTER_COLOR = "#dc2626";
16509
+ POINTER_BAND = 34;
16510
+ TOP_PAD = 12;
16511
+ AlgorithmCanvas = ({
16512
+ className,
16513
+ width = 600,
16514
+ height = 400,
16515
+ title,
16516
+ backgroundColor,
16517
+ bars = [],
16518
+ cells = [],
16519
+ pointers = [],
16520
+ shapes = [],
16521
+ interactive = false,
16522
+ animate = false,
16523
+ onShapeClick,
16524
+ isLoading,
16525
+ error
16526
+ }) => {
16527
+ const derivedShapes = useMemo(() => {
16528
+ const out = [];
16529
+ if (bars.length > 0) {
16530
+ const slot = width / bars.length;
16531
+ const barW = slot * 0.8;
16532
+ const gap = slot * 0.1;
16533
+ const baseline = height - POINTER_BAND;
16534
+ const usableH = baseline - TOP_PAD;
16535
+ const maxV = Math.max(1, ...bars.map((b) => Number.isFinite(b.value) ? b.value : 0));
16536
+ bars.forEach((bar, i) => {
16537
+ const v = Number.isFinite(bar.value) ? bar.value : 0;
16538
+ const bh = Math.max(0, v / maxV * usableH);
16539
+ const x = i * slot + gap;
16540
+ const color = bar.color ?? DEFAULT_BAR_COLOR;
16541
+ out.push({
16542
+ type: "rect",
16543
+ id: `bar-${i}`,
16544
+ x,
16545
+ y: baseline - bh,
16546
+ width: barW,
16547
+ height: bh,
16548
+ color,
16549
+ fill: color
16550
+ });
16551
+ const label = bar.label ?? (bars.length <= 24 ? String(v) : void 0);
16552
+ if (label) {
16553
+ out.push({
16554
+ type: "text",
16555
+ x: x + barW / 2,
16556
+ y: baseline - bh - 8,
16557
+ text: label,
16558
+ color: "#374151",
16559
+ fontSize: 11,
16560
+ align: "center"
16561
+ });
16562
+ }
16563
+ });
16564
+ pointers.forEach((p) => {
16565
+ if (p.index < 0 || p.index >= bars.length) return;
16566
+ const cx = p.index * slot + slot / 2;
16567
+ const color = p.color ?? DEFAULT_POINTER_COLOR;
16568
+ out.push({
16569
+ type: "arrow",
16570
+ x1: cx,
16571
+ y1: height - 6,
16572
+ x2: cx,
16573
+ y2: baseline + 4,
16574
+ color,
16575
+ lineWidth: 2
16576
+ });
16577
+ if (p.label) {
16578
+ out.push({
16579
+ type: "text",
16580
+ x: cx,
16581
+ y: height - 22,
16582
+ text: p.label,
16583
+ color,
16584
+ fontSize: 11,
16585
+ align: "center"
16586
+ });
16587
+ }
16588
+ });
16589
+ }
16590
+ if (cells.length > 0) {
16591
+ const maxCol = Math.max(0, ...cells.map((c) => c.col)) + 1;
16592
+ const maxRow = Math.max(0, ...cells.map((c) => c.row)) + 1;
16593
+ const cw = width / maxCol;
16594
+ const ch = height / maxRow;
16595
+ cells.forEach((c, i) => {
16596
+ const x = c.col * cw;
16597
+ const y = c.row * ch;
16598
+ const color = c.color ?? DEFAULT_CELL_COLOR;
16599
+ out.push({
16600
+ type: "rect",
16601
+ id: `cell-${i}`,
16602
+ x: x + 1,
16603
+ y: y + 1,
16604
+ width: cw - 2,
16605
+ height: ch - 2,
16606
+ color: "#9ca3af",
16607
+ fill: color
16608
+ });
16609
+ const label = c.label ?? (c.value != null ? String(c.value) : void 0);
16610
+ if (label && cw >= 18 && ch >= 14) {
16611
+ out.push({
16612
+ type: "text",
16613
+ x: x + cw / 2,
16614
+ y: y + ch / 2,
16615
+ text: label,
16616
+ color: "#111827",
16617
+ fontSize: 12,
16618
+ align: "center"
16619
+ });
16620
+ }
16621
+ });
16622
+ }
16623
+ out.push(...shapes);
16624
+ return out;
16625
+ }, [bars, cells, pointers, shapes, width, height]);
16626
+ return /* @__PURE__ */ jsx(Card, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
16627
+ title ? /* @__PURE__ */ jsx(Typography, { variant: "h4", children: title }) : null,
16628
+ /* @__PURE__ */ jsx(
16629
+ LearningCanvas,
16630
+ {
16631
+ width,
16632
+ height,
16633
+ backgroundColor,
16634
+ shapes: derivedShapes,
16635
+ interactive,
16636
+ animate,
16637
+ onShapeClick,
16638
+ isLoading,
16639
+ error
16640
+ }
16641
+ )
16642
+ ] }) });
16643
+ };
16644
+ }
16645
+ });
16160
16646
  var AuthLayout;
16161
16647
  var init_AuthLayout = __esm({
16162
16648
  "components/marketing/templates/AuthLayout.tsx"() {
@@ -17709,7 +18195,7 @@ var init_CodeBlock = __esm({
17709
18195
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
17710
18196
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
17711
18197
  HIDDEN_LINE_NUMBERS = { display: "none" };
17712
- CodeBlock = React95__default.memo(
18198
+ CodeBlock = React96__default.memo(
17713
18199
  ({
17714
18200
  code: rawCode,
17715
18201
  language = "text",
@@ -18296,7 +18782,7 @@ var init_MarkdownContent = __esm({
18296
18782
  init_Box();
18297
18783
  init_CodeBlock();
18298
18784
  init_cn();
18299
- MarkdownContent = React95__default.memo(
18785
+ MarkdownContent = React96__default.memo(
18300
18786
  ({ content, direction = "ltr", className }) => {
18301
18787
  const { t: _t } = useTranslate();
18302
18788
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -19573,7 +20059,7 @@ var init_StateMachineView = __esm({
19573
20059
  style: { top: title ? 30 : 0 },
19574
20060
  children: [
19575
20061
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
19576
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React95__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
20062
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React96__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
19577
20063
  StateNode2,
19578
20064
  {
19579
20065
  state,
@@ -25130,8 +25616,8 @@ var init_Menu = __esm({
25130
25616
  "bottom-end": "bottom-start"
25131
25617
  };
25132
25618
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
25133
- const triggerChild = React95__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
25134
- const triggerElement = React95__default.cloneElement(
25619
+ const triggerChild = React96__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
25620
+ const triggerElement = React96__default.cloneElement(
25135
25621
  triggerChild,
25136
25622
  {
25137
25623
  ref: triggerRef,
@@ -25226,14 +25712,14 @@ function useDataDnd(args) {
25226
25712
  const isZone = Boolean(dragGroup || accepts || sortable);
25227
25713
  const enabled = isZone || Boolean(dndRoot);
25228
25714
  const eventBus = useEventBus();
25229
- const parentRoot = React95__default.useContext(RootCtx);
25715
+ const parentRoot = React96__default.useContext(RootCtx);
25230
25716
  const isRoot = enabled && parentRoot === null;
25231
- const zoneId = React95__default.useId();
25717
+ const zoneId = React96__default.useId();
25232
25718
  const ownGroup = dragGroup ?? accepts ?? zoneId;
25233
- const [optimisticOrders, setOptimisticOrders] = React95__default.useState(() => /* @__PURE__ */ new Map());
25234
- const optimisticOrdersRef = React95__default.useRef(optimisticOrders);
25719
+ const [optimisticOrders, setOptimisticOrders] = React96__default.useState(() => /* @__PURE__ */ new Map());
25720
+ const optimisticOrdersRef = React96__default.useRef(optimisticOrders);
25235
25721
  optimisticOrdersRef.current = optimisticOrders;
25236
- const clearOptimisticOrder = React95__default.useCallback((group) => {
25722
+ const clearOptimisticOrder = React96__default.useCallback((group) => {
25237
25723
  setOptimisticOrders((prev) => {
25238
25724
  if (!prev.has(group)) return prev;
25239
25725
  const next = new Map(prev);
@@ -25258,7 +25744,7 @@ function useDataDnd(args) {
25258
25744
  const raw = it[dndItemIdField];
25259
25745
  return raw != null ? String(raw) : `__idx_${idx}`;
25260
25746
  }).join("|");
25261
- const itemIds = React95__default.useMemo(
25747
+ const itemIds = React96__default.useMemo(
25262
25748
  () => orderedItems.map((it, idx) => {
25263
25749
  const raw = it[dndItemIdField];
25264
25750
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -25269,7 +25755,7 @@ function useDataDnd(args) {
25269
25755
  const raw = it[dndItemIdField];
25270
25756
  return raw != null ? String(raw) : `__${idx}`;
25271
25757
  }).join("|");
25272
- React95__default.useEffect(() => {
25758
+ React96__default.useEffect(() => {
25273
25759
  const root = isRoot ? null : parentRoot;
25274
25760
  if (root) {
25275
25761
  root.clearOptimisticOrder(ownGroup);
@@ -25277,20 +25763,20 @@ function useDataDnd(args) {
25277
25763
  clearOptimisticOrder(ownGroup);
25278
25764
  }
25279
25765
  }, [itemsContentSig, ownGroup]);
25280
- const zonesRef = React95__default.useRef(/* @__PURE__ */ new Map());
25281
- const registerZone = React95__default.useCallback((zoneId2, meta2) => {
25766
+ const zonesRef = React96__default.useRef(/* @__PURE__ */ new Map());
25767
+ const registerZone = React96__default.useCallback((zoneId2, meta2) => {
25282
25768
  zonesRef.current.set(zoneId2, meta2);
25283
25769
  }, []);
25284
- const unregisterZone = React95__default.useCallback((zoneId2) => {
25770
+ const unregisterZone = React96__default.useCallback((zoneId2) => {
25285
25771
  zonesRef.current.delete(zoneId2);
25286
25772
  }, []);
25287
- const [activeDrag, setActiveDrag] = React95__default.useState(null);
25288
- const [overZoneGroup, setOverZoneGroup] = React95__default.useState(null);
25289
- const meta = React95__default.useMemo(
25773
+ const [activeDrag, setActiveDrag] = React96__default.useState(null);
25774
+ const [overZoneGroup, setOverZoneGroup] = React96__default.useState(null);
25775
+ const meta = React96__default.useMemo(
25290
25776
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
25291
25777
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
25292
25778
  );
25293
- React95__default.useEffect(() => {
25779
+ React96__default.useEffect(() => {
25294
25780
  const target = isRoot ? null : parentRoot;
25295
25781
  if (!target) {
25296
25782
  zonesRef.current.set(zoneId, meta);
@@ -25309,7 +25795,7 @@ function useDataDnd(args) {
25309
25795
  }, [parentRoot, isRoot, zoneId, meta]);
25310
25796
  const sensors = useAlmadarDndSensors(true);
25311
25797
  const collisionDetection = almadarDndCollisionDetection;
25312
- const findZoneByItem = React95__default.useCallback(
25798
+ const findZoneByItem = React96__default.useCallback(
25313
25799
  (id) => {
25314
25800
  for (const z of zonesRef.current.values()) {
25315
25801
  if (z.itemIds.includes(id)) return z;
@@ -25318,7 +25804,7 @@ function useDataDnd(args) {
25318
25804
  },
25319
25805
  []
25320
25806
  );
25321
- React95__default.useCallback(
25807
+ React96__default.useCallback(
25322
25808
  (group) => {
25323
25809
  for (const z of zonesRef.current.values()) {
25324
25810
  if (z.group === group) return z;
@@ -25327,7 +25813,7 @@ function useDataDnd(args) {
25327
25813
  },
25328
25814
  []
25329
25815
  );
25330
- const handleDragEnd = React95__default.useCallback(
25816
+ const handleDragEnd = React96__default.useCallback(
25331
25817
  (event) => {
25332
25818
  const { active, over } = event;
25333
25819
  const activeIdStr = String(active.id);
@@ -25418,8 +25904,8 @@ function useDataDnd(args) {
25418
25904
  },
25419
25905
  [eventBus]
25420
25906
  );
25421
- const sortableData = React95__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25422
- const SortableItem = React95__default.useCallback(
25907
+ const sortableData = React96__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25908
+ const SortableItem = React96__default.useCallback(
25423
25909
  ({ id, children }) => {
25424
25910
  const {
25425
25911
  attributes,
@@ -25459,7 +25945,7 @@ function useDataDnd(args) {
25459
25945
  id: droppableId,
25460
25946
  data: sortableData
25461
25947
  });
25462
- const ctx = React95__default.useContext(RootCtx);
25948
+ const ctx = React96__default.useContext(RootCtx);
25463
25949
  const activeDrag2 = ctx?.activeDrag ?? null;
25464
25950
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
25465
25951
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -25474,7 +25960,7 @@ function useDataDnd(args) {
25474
25960
  showForeignPlaceholder,
25475
25961
  ctxAvailable: ctx != null
25476
25962
  });
25477
- React95__default.useEffect(() => {
25963
+ React96__default.useEffect(() => {
25478
25964
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25479
25965
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25480
25966
  return /* @__PURE__ */ jsx(
@@ -25488,11 +25974,11 @@ function useDataDnd(args) {
25488
25974
  }
25489
25975
  );
25490
25976
  };
25491
- const rootContextValue = React95__default.useMemo(
25977
+ const rootContextValue = React96__default.useMemo(
25492
25978
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
25493
25979
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
25494
25980
  );
25495
- const handleDragStart = React95__default.useCallback((event) => {
25981
+ const handleDragStart = React96__default.useCallback((event) => {
25496
25982
  const sourceZone = findZoneByItem(event.active.id);
25497
25983
  const rect = event.active.rect.current.initial;
25498
25984
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -25511,7 +25997,7 @@ function useDataDnd(args) {
25511
25997
  isRoot
25512
25998
  });
25513
25999
  }, [findZoneByItem, isRoot, zoneId]);
25514
- const handleDragOver = React95__default.useCallback((event) => {
26000
+ const handleDragOver = React96__default.useCallback((event) => {
25515
26001
  const { active, over } = event;
25516
26002
  const overData = over?.data?.current;
25517
26003
  const overGroup = overData?.dndGroup ?? null;
@@ -25581,7 +26067,7 @@ function useDataDnd(args) {
25581
26067
  return next;
25582
26068
  });
25583
26069
  }, []);
25584
- const handleDragCancel = React95__default.useCallback((event) => {
26070
+ const handleDragCancel = React96__default.useCallback((event) => {
25585
26071
  setActiveDrag(null);
25586
26072
  setOverZoneGroup(null);
25587
26073
  dndLog.warn("dragCancel", {
@@ -25589,12 +26075,12 @@ function useDataDnd(args) {
25589
26075
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
25590
26076
  });
25591
26077
  }, []);
25592
- const handleDragEndWithCleanup = React95__default.useCallback((event) => {
26078
+ const handleDragEndWithCleanup = React96__default.useCallback((event) => {
25593
26079
  handleDragEnd(event);
25594
26080
  setActiveDrag(null);
25595
26081
  setOverZoneGroup(null);
25596
26082
  }, [handleDragEnd]);
25597
- const wrapContainer = React95__default.useCallback(
26083
+ const wrapContainer = React96__default.useCallback(
25598
26084
  (children) => {
25599
26085
  if (!enabled) return children;
25600
26086
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -25648,7 +26134,7 @@ var init_useDataDnd = __esm({
25648
26134
  init_useAlmadarDndCollision();
25649
26135
  init_Box();
25650
26136
  dndLog = createLogger("almadar:ui:dnd");
25651
- RootCtx = React95__default.createContext(null);
26137
+ RootCtx = React96__default.createContext(null);
25652
26138
  }
25653
26139
  });
25654
26140
  function renderIconInput(icon, props) {
@@ -26174,7 +26660,7 @@ function DataList({
26174
26660
  }) {
26175
26661
  const eventBus = useEventBus();
26176
26662
  const { t } = useTranslate();
26177
- const [visibleCount, setVisibleCount] = React95__default.useState(pageSize || Infinity);
26663
+ const [visibleCount, setVisibleCount] = React96__default.useState(pageSize || Infinity);
26178
26664
  const fieldDefs = fields ?? columns ?? [];
26179
26665
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
26180
26666
  const dnd = useDataDnd({
@@ -26193,7 +26679,7 @@ function DataList({
26193
26679
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
26194
26680
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
26195
26681
  const hasRenderProp = typeof children === "function";
26196
- React95__default.useEffect(() => {
26682
+ React96__default.useEffect(() => {
26197
26683
  const renderItemTypeOf = typeof schemaRenderItem;
26198
26684
  const childrenTypeOf = typeof children;
26199
26685
  if (data.length > 0 && !hasRenderProp) {
@@ -26297,7 +26783,7 @@ function DataList({
26297
26783
  const items2 = [...data];
26298
26784
  const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
26299
26785
  const contentField = titleField?.name ?? fieldDefs[0]?.name ?? "";
26300
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
26786
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
26301
26787
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
26302
26788
  group.items.map((itemData, index) => {
26303
26789
  const id = itemData.id || `${gi}-${index}`;
@@ -26438,7 +26924,7 @@ function DataList({
26438
26924
  className
26439
26925
  ),
26440
26926
  children: [
26441
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
26927
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
26442
26928
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
26443
26929
  group.items.map(
26444
26930
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -26523,7 +27009,7 @@ var init_FormSection = __esm({
26523
27009
  columns = 1,
26524
27010
  className
26525
27011
  }) => {
26526
- const [collapsed, setCollapsed] = React95__default.useState(defaultCollapsed);
27012
+ const [collapsed, setCollapsed] = React96__default.useState(defaultCollapsed);
26527
27013
  const { t } = useTranslate();
26528
27014
  const eventBus = useEventBus();
26529
27015
  const gridClass = {
@@ -26531,7 +27017,7 @@ var init_FormSection = __esm({
26531
27017
  2: "grid-cols-1 md:grid-cols-2",
26532
27018
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
26533
27019
  }[columns];
26534
- React95__default.useCallback(() => {
27020
+ React96__default.useCallback(() => {
26535
27021
  if (collapsible) {
26536
27022
  setCollapsed((prev) => !prev);
26537
27023
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -27417,7 +27903,7 @@ var init_Flex = __esm({
27417
27903
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
27418
27904
  }
27419
27905
  }
27420
- return React95__default.createElement(Component, {
27906
+ return React96__default.createElement(Component, {
27421
27907
  className: cn(
27422
27908
  inline ? "inline-flex" : "flex",
27423
27909
  directionStyles[direction],
@@ -27536,7 +28022,7 @@ var init_Grid = __esm({
27536
28022
  as: Component = "div"
27537
28023
  }) => {
27538
28024
  const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
27539
- return React95__default.createElement(
28025
+ return React96__default.createElement(
27540
28026
  Component,
27541
28027
  {
27542
28028
  className: cn(
@@ -27732,9 +28218,9 @@ var init_Popover = __esm({
27732
28218
  onMouseLeave: handleClose,
27733
28219
  onPointerDown: tapTriggerProps.onPointerDown
27734
28220
  };
27735
- const childElement = React95__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28221
+ const childElement = React96__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27736
28222
  const childPointerDown = childElement.props.onPointerDown;
27737
- const triggerElement = React95__default.cloneElement(
28223
+ const triggerElement = React96__default.cloneElement(
27738
28224
  childElement,
27739
28225
  {
27740
28226
  ref: triggerRef,
@@ -28336,9 +28822,9 @@ var init_Tooltip = __esm({
28336
28822
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
28337
28823
  };
28338
28824
  }, []);
28339
- const triggerElement = React95__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28825
+ const triggerElement = React96__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28340
28826
  const childPointerDown = triggerElement.props.onPointerDown;
28341
- const trigger = React95__default.cloneElement(triggerElement, {
28827
+ const trigger = React96__default.cloneElement(triggerElement, {
28342
28828
  ref: triggerRef,
28343
28829
  onMouseEnter: handleMouseEnter,
28344
28830
  onMouseLeave: handleMouseLeave,
@@ -28428,7 +28914,7 @@ var init_WizardProgress = __esm({
28428
28914
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
28429
28915
  const isActive = index === currentStep;
28430
28916
  const isCompleted = index < currentStep;
28431
- return /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
28917
+ return /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
28432
28918
  /* @__PURE__ */ jsx(
28433
28919
  "button",
28434
28920
  {
@@ -29988,13 +30474,13 @@ var init_MapView = __esm({
29988
30474
  shadowSize: [41, 41]
29989
30475
  });
29990
30476
  L.Marker.prototype.options.icon = defaultIcon;
29991
- const { useEffect: useEffect66, useRef: useRef64, useCallback: useCallback98, useState: useState97 } = React95__default;
30477
+ const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback98, useState: useState97 } = React96__default;
29992
30478
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29993
30479
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29994
30480
  function MapUpdater({ centerLat, centerLng, zoom }) {
29995
30481
  const map = useMap();
29996
- const prevRef = useRef64({ centerLat, centerLng, zoom });
29997
- useEffect66(() => {
30482
+ const prevRef = useRef65({ centerLat, centerLng, zoom });
30483
+ useEffect67(() => {
29998
30484
  const prev = prevRef.current;
29999
30485
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
30000
30486
  map.setView([centerLat, centerLng], zoom);
@@ -30005,7 +30491,7 @@ var init_MapView = __esm({
30005
30491
  }
30006
30492
  function MapClickHandler({ onMapClick }) {
30007
30493
  const map = useMap();
30008
- useEffect66(() => {
30494
+ useEffect67(() => {
30009
30495
  if (!onMapClick) return;
30010
30496
  const handler = (e) => {
30011
30497
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -30903,8 +31389,8 @@ function TableView({
30903
31389
  }) {
30904
31390
  const eventBus = useEventBus();
30905
31391
  const { t } = useTranslate();
30906
- const [visibleCount, setVisibleCount] = React95__default.useState(pageSize > 0 ? pageSize : Infinity);
30907
- const [localSelected, setLocalSelected] = React95__default.useState(/* @__PURE__ */ new Set());
31392
+ const [visibleCount, setVisibleCount] = React96__default.useState(pageSize > 0 ? pageSize : Infinity);
31393
+ const [localSelected, setLocalSelected] = React96__default.useState(/* @__PURE__ */ new Set());
30908
31394
  const colDefs = columns ?? fields ?? [];
30909
31395
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
30910
31396
  const dnd = useDataDnd({
@@ -31099,12 +31585,12 @@ function TableView({
31099
31585
  ]
31100
31586
  }
31101
31587
  );
31102
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React95__default.Fragment, { children: rowInner }, id);
31588
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React96__default.Fragment, { children: rowInner }, id);
31103
31589
  };
31104
31590
  const items = Array.from(data);
31105
31591
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
31106
31592
  let runningIndex = 0;
31107
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
31593
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
31108
31594
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
31109
31595
  group.items.map((row) => renderRow(row, runningIndex++))
31110
31596
  ] }, gi)) });
@@ -32323,7 +32809,7 @@ var init_StepFlow = __esm({
32323
32809
  className
32324
32810
  }) => {
32325
32811
  if (orientation === "vertical") {
32326
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React95__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
32812
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React96__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
32327
32813
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
32328
32814
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32329
32815
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -32334,7 +32820,7 @@ var init_StepFlow = __esm({
32334
32820
  ] })
32335
32821
  ] }) }, index)) });
32336
32822
  }
32337
- return /* @__PURE__ */ jsx(Box, { className: cn("w-full flex flex-col md:flex-row items-start gap-0", className), children: steps.map((step, index) => /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
32823
+ return /* @__PURE__ */ jsx(Box, { className: cn("w-full flex flex-col md:flex-row items-start gap-0", className), children: steps.map((step, index) => /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
32338
32824
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
32339
32825
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32340
32826
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -33319,7 +33805,7 @@ var init_LikertScale = __esm({
33319
33805
  md: "text-base",
33320
33806
  lg: "text-lg"
33321
33807
  };
33322
- LikertScale = React95__default.forwardRef(
33808
+ LikertScale = React96__default.forwardRef(
33323
33809
  ({
33324
33810
  question,
33325
33811
  options = DEFAULT_LIKERT_OPTIONS,
@@ -33331,7 +33817,7 @@ var init_LikertScale = __esm({
33331
33817
  variant = "radios",
33332
33818
  className
33333
33819
  }, ref) => {
33334
- const groupId = React95__default.useId();
33820
+ const groupId = React96__default.useId();
33335
33821
  const eventBus = useEventBus();
33336
33822
  const handleSelect = useCallback(
33337
33823
  (next) => {
@@ -35613,7 +36099,7 @@ var init_DocBreadcrumb = __esm({
35613
36099
  "aria-label": t("aria.breadcrumb"),
35614
36100
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
35615
36101
  const isLast = idx === items.length - 1;
35616
- return /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
36102
+ return /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
35617
36103
  idx > 0 && /* @__PURE__ */ jsx(
35618
36104
  Icon,
35619
36105
  {
@@ -36482,7 +36968,7 @@ var init_MiniStateMachine = __esm({
36482
36968
  const x = 2 + i * (NODE_W + GAP + ARROW_W + GAP);
36483
36969
  const tc = transitionCounts[s.name] ?? 0;
36484
36970
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
36485
- return /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
36971
+ return /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
36486
36972
  /* @__PURE__ */ jsx(
36487
36973
  AvlState,
36488
36974
  {
@@ -36686,7 +37172,7 @@ var init_PageHeader = __esm({
36686
37172
  info: "bg-info/10 text-info"
36687
37173
  };
36688
37174
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
36689
- breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
37175
+ breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
36690
37176
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
36691
37177
  crumb.href ? /* @__PURE__ */ jsx(
36692
37178
  "a",
@@ -37044,7 +37530,7 @@ var init_Section = __esm({
37044
37530
  as: Component = "section"
37045
37531
  }) => {
37046
37532
  const hasHeader = title || description || action;
37047
- return React95__default.createElement(
37533
+ return React96__default.createElement(
37048
37534
  Component,
37049
37535
  {
37050
37536
  className: cn(
@@ -37418,7 +37904,7 @@ var init_WizardContainer = __esm({
37418
37904
  const isCompleted = index < currentStep;
37419
37905
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
37420
37906
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
37421
- return /* @__PURE__ */ jsxs(React95__default.Fragment, { children: [
37907
+ return /* @__PURE__ */ jsxs(React96__default.Fragment, { children: [
37422
37908
  /* @__PURE__ */ jsx(
37423
37909
  Button,
37424
37910
  {
@@ -39851,7 +40337,7 @@ var init_DetailPanel = __esm({
39851
40337
  }
39852
40338
  });
39853
40339
  function extractTitle(children) {
39854
- if (!React95__default.isValidElement(children)) return void 0;
40340
+ if (!React96__default.isValidElement(children)) return void 0;
39855
40341
  const props = children.props;
39856
40342
  if (typeof props.title === "string") {
39857
40343
  return props.title;
@@ -40201,12 +40687,12 @@ var init_Form = __esm({
40201
40687
  const isSchemaEntity = isOrbitalEntitySchema(entity);
40202
40688
  const resolvedEntity = isSchemaEntity ? entity : void 0;
40203
40689
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
40204
- const normalizedInitialData = React95__default.useMemo(() => {
40690
+ const normalizedInitialData = React96__default.useMemo(() => {
40205
40691
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
40206
40692
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
40207
40693
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
40208
40694
  }, [entity, initialData]);
40209
- const entityDerivedFields = React95__default.useMemo(() => {
40695
+ const entityDerivedFields = React96__default.useMemo(() => {
40210
40696
  if (fields && fields.length > 0) return void 0;
40211
40697
  if (!resolvedEntity) return void 0;
40212
40698
  return resolvedEntity.fields.map(
@@ -40227,16 +40713,16 @@ var init_Form = __esm({
40227
40713
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
40228
40714
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
40229
40715
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
40230
- const [formData, setFormData] = React95__default.useState(
40716
+ const [formData, setFormData] = React96__default.useState(
40231
40717
  normalizedInitialData
40232
40718
  );
40233
- const [collapsedSections, setCollapsedSections] = React95__default.useState(
40719
+ const [collapsedSections, setCollapsedSections] = React96__default.useState(
40234
40720
  /* @__PURE__ */ new Set()
40235
40721
  );
40236
- const [submitError, setSubmitError] = React95__default.useState(null);
40237
- const formRef = React95__default.useRef(null);
40722
+ const [submitError, setSubmitError] = React96__default.useState(null);
40723
+ const formRef = React96__default.useRef(null);
40238
40724
  const formMode = props.mode;
40239
- const mountedRef = React95__default.useRef(false);
40725
+ const mountedRef = React96__default.useRef(false);
40240
40726
  if (!mountedRef.current) {
40241
40727
  mountedRef.current = true;
40242
40728
  debug("forms", "mount", {
@@ -40249,7 +40735,7 @@ var init_Form = __esm({
40249
40735
  });
40250
40736
  }
40251
40737
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
40252
- const evalContext = React95__default.useMemo(
40738
+ const evalContext = React96__default.useMemo(
40253
40739
  () => ({
40254
40740
  formValues: formData,
40255
40741
  globalVariables: externalContext?.globalVariables ?? {},
@@ -40258,7 +40744,7 @@ var init_Form = __esm({
40258
40744
  }),
40259
40745
  [formData, externalContext]
40260
40746
  );
40261
- React95__default.useEffect(() => {
40747
+ React96__default.useEffect(() => {
40262
40748
  debug("forms", "initialData-sync", {
40263
40749
  mode: formMode,
40264
40750
  normalizedInitialData,
@@ -40269,7 +40755,7 @@ var init_Form = __esm({
40269
40755
  setFormData(normalizedInitialData);
40270
40756
  }
40271
40757
  }, [normalizedInitialData]);
40272
- const processCalculations = React95__default.useCallback(
40758
+ const processCalculations = React96__default.useCallback(
40273
40759
  (changedFieldId, newFormData) => {
40274
40760
  if (!hiddenCalculations.length) return;
40275
40761
  const context = {
@@ -40294,7 +40780,7 @@ var init_Form = __esm({
40294
40780
  },
40295
40781
  [hiddenCalculations, externalContext, eventBus]
40296
40782
  );
40297
- const checkViolations = React95__default.useCallback(
40783
+ const checkViolations = React96__default.useCallback(
40298
40784
  (changedFieldId, newFormData) => {
40299
40785
  if (!violationTriggers.length) return;
40300
40786
  const context = {
@@ -40332,7 +40818,7 @@ var init_Form = __esm({
40332
40818
  processCalculations(name, newFormData);
40333
40819
  checkViolations(name, newFormData);
40334
40820
  };
40335
- const isFieldVisible = React95__default.useCallback(
40821
+ const isFieldVisible = React96__default.useCallback(
40336
40822
  (fieldName) => {
40337
40823
  const condition = conditionalFields[fieldName];
40338
40824
  if (!condition) return true;
@@ -40340,7 +40826,7 @@ var init_Form = __esm({
40340
40826
  },
40341
40827
  [conditionalFields, evalContext]
40342
40828
  );
40343
- const isSectionVisible = React95__default.useCallback(
40829
+ const isSectionVisible = React96__default.useCallback(
40344
40830
  (section) => {
40345
40831
  if (!section.condition) return true;
40346
40832
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -40416,7 +40902,7 @@ var init_Form = __esm({
40416
40902
  eventBus.emit(`UI:${onCancel}`);
40417
40903
  }
40418
40904
  };
40419
- const renderField = React95__default.useCallback(
40905
+ const renderField = React96__default.useCallback(
40420
40906
  (field) => {
40421
40907
  const fieldName = field.name || field.field;
40422
40908
  if (!fieldName) return null;
@@ -40437,7 +40923,7 @@ var init_Form = __esm({
40437
40923
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
40438
40924
  );
40439
40925
  const effectiveFields = entityDerivedFields ?? fields;
40440
- const normalizedFields = React95__default.useMemo(() => {
40926
+ const normalizedFields = React96__default.useMemo(() => {
40441
40927
  if (!effectiveFields || effectiveFields.length === 0) return [];
40442
40928
  return effectiveFields.map((field) => {
40443
40929
  if (typeof field === "string") {
@@ -40461,7 +40947,7 @@ var init_Form = __esm({
40461
40947
  return field;
40462
40948
  });
40463
40949
  }, [effectiveFields, resolvedEntity]);
40464
- const schemaFields = React95__default.useMemo(() => {
40950
+ const schemaFields = React96__default.useMemo(() => {
40465
40951
  if (normalizedFields.length === 0) return null;
40466
40952
  if (isDebugEnabled()) {
40467
40953
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -40471,7 +40957,7 @@ var init_Form = __esm({
40471
40957
  }
40472
40958
  return normalizedFields.map(renderField).filter(Boolean);
40473
40959
  }, [normalizedFields, renderField, entityName, conditionalFields]);
40474
- const sectionElements = React95__default.useMemo(() => {
40960
+ const sectionElements = React96__default.useMemo(() => {
40475
40961
  if (!sections || sections.length === 0) return null;
40476
40962
  return sections.map((section) => {
40477
40963
  if (!isSectionVisible(section)) {
@@ -41196,7 +41682,7 @@ var init_List = __esm({
41196
41682
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
41197
41683
  return [];
41198
41684
  }, [entity]);
41199
- const getItemActions = React95__default.useCallback(
41685
+ const getItemActions = React96__default.useCallback(
41200
41686
  (item) => {
41201
41687
  if (!itemActions) return [];
41202
41688
  if (typeof itemActions === "function") {
@@ -41671,7 +42157,7 @@ var init_MediaGallery = __esm({
41671
42157
  [selectable, selectedItems, selectionEvent, eventBus]
41672
42158
  );
41673
42159
  const entityData = Array.isArray(entity) ? entity : [];
41674
- const items = React95__default.useMemo(() => {
42160
+ const items = React96__default.useMemo(() => {
41675
42161
  if (propItems) return propItems;
41676
42162
  if (entityData.length === 0) return [];
41677
42163
  return entityData.map((record, idx) => {
@@ -41834,7 +42320,7 @@ var init_MediaGallery = __esm({
41834
42320
  }
41835
42321
  });
41836
42322
  function extractTitle2(children) {
41837
- if (!React95__default.isValidElement(children)) return void 0;
42323
+ if (!React96__default.isValidElement(children)) return void 0;
41838
42324
  const props = children.props;
41839
42325
  if (typeof props.title === "string") {
41840
42326
  return props.title;
@@ -42108,7 +42594,7 @@ var init_debugRegistry = __esm({
42108
42594
  }
42109
42595
  });
42110
42596
  function useDebugData() {
42111
- const [data, setData] = React95.useState(() => ({
42597
+ const [data, setData] = React96.useState(() => ({
42112
42598
  traits: [],
42113
42599
  ticks: [],
42114
42600
  guards: [],
@@ -42122,7 +42608,7 @@ function useDebugData() {
42122
42608
  },
42123
42609
  lastUpdate: Date.now()
42124
42610
  }));
42125
- React95.useEffect(() => {
42611
+ React96.useEffect(() => {
42126
42612
  const updateData = () => {
42127
42613
  setData({
42128
42614
  traits: getAllTraits(),
@@ -42231,12 +42717,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
42231
42717
  return positions;
42232
42718
  }
42233
42719
  function WalkMinimap() {
42234
- const [walkStep, setWalkStep] = React95.useState(null);
42235
- const [traits2, setTraits] = React95.useState([]);
42236
- const [coveredEdges, setCoveredEdges] = React95.useState([]);
42237
- const [completedTraits, setCompletedTraits] = React95.useState(/* @__PURE__ */ new Set());
42238
- const prevTraitRef = React95.useRef(null);
42239
- React95.useEffect(() => {
42720
+ const [walkStep, setWalkStep] = React96.useState(null);
42721
+ const [traits2, setTraits] = React96.useState([]);
42722
+ const [coveredEdges, setCoveredEdges] = React96.useState([]);
42723
+ const [completedTraits, setCompletedTraits] = React96.useState(/* @__PURE__ */ new Set());
42724
+ const prevTraitRef = React96.useRef(null);
42725
+ React96.useEffect(() => {
42240
42726
  const interval = setInterval(() => {
42241
42727
  const w = window;
42242
42728
  const step = w.__orbitalWalkStep;
@@ -42672,15 +43158,15 @@ var init_EntitiesTab = __esm({
42672
43158
  });
42673
43159
  function EventFlowTab({ events: events2 }) {
42674
43160
  const { t } = useTranslate();
42675
- const [filter, setFilter] = React95.useState("all");
42676
- const containerRef = React95.useRef(null);
42677
- const [autoScroll, setAutoScroll] = React95.useState(true);
42678
- React95.useEffect(() => {
43161
+ const [filter, setFilter] = React96.useState("all");
43162
+ const containerRef = React96.useRef(null);
43163
+ const [autoScroll, setAutoScroll] = React96.useState(true);
43164
+ React96.useEffect(() => {
42679
43165
  if (autoScroll && containerRef.current) {
42680
43166
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
42681
43167
  }
42682
43168
  }, [events2.length, autoScroll]);
42683
- const filteredEvents = React95.useMemo(() => {
43169
+ const filteredEvents = React96.useMemo(() => {
42684
43170
  if (filter === "all") return events2;
42685
43171
  return events2.filter((e) => e.type === filter);
42686
43172
  }, [events2, filter]);
@@ -42796,7 +43282,7 @@ var init_EventFlowTab = __esm({
42796
43282
  });
42797
43283
  function GuardsPanel({ guards }) {
42798
43284
  const { t } = useTranslate();
42799
- const [filter, setFilter] = React95.useState("all");
43285
+ const [filter, setFilter] = React96.useState("all");
42800
43286
  if (guards.length === 0) {
42801
43287
  return /* @__PURE__ */ jsx(
42802
43288
  EmptyState,
@@ -42809,7 +43295,7 @@ function GuardsPanel({ guards }) {
42809
43295
  }
42810
43296
  const passedCount = guards.filter((g) => g.result).length;
42811
43297
  const failedCount = guards.length - passedCount;
42812
- const filteredGuards = React95.useMemo(() => {
43298
+ const filteredGuards = React96.useMemo(() => {
42813
43299
  if (filter === "all") return guards;
42814
43300
  if (filter === "passed") return guards.filter((g) => g.result);
42815
43301
  return guards.filter((g) => !g.result);
@@ -42972,10 +43458,10 @@ function EffectBadge({ effect }) {
42972
43458
  }
42973
43459
  function TransitionTimeline({ transitions }) {
42974
43460
  const { t } = useTranslate();
42975
- const containerRef = React95.useRef(null);
42976
- const [autoScroll, setAutoScroll] = React95.useState(true);
42977
- const [expandedId, setExpandedId] = React95.useState(null);
42978
- React95.useEffect(() => {
43461
+ const containerRef = React96.useRef(null);
43462
+ const [autoScroll, setAutoScroll] = React96.useState(true);
43463
+ const [expandedId, setExpandedId] = React96.useState(null);
43464
+ React96.useEffect(() => {
42979
43465
  if (autoScroll && containerRef.current) {
42980
43466
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
42981
43467
  }
@@ -43255,9 +43741,9 @@ function getAllEvents(traits2) {
43255
43741
  function EventDispatcherTab({ traits: traits2, schema }) {
43256
43742
  const eventBus = useEventBus();
43257
43743
  const { t } = useTranslate();
43258
- const [log9, setLog] = React95.useState([]);
43259
- const prevStatesRef = React95.useRef(/* @__PURE__ */ new Map());
43260
- React95.useEffect(() => {
43744
+ const [log9, setLog] = React96.useState([]);
43745
+ const prevStatesRef = React96.useRef(/* @__PURE__ */ new Map());
43746
+ React96.useEffect(() => {
43261
43747
  for (const trait of traits2) {
43262
43748
  const prev = prevStatesRef.current.get(trait.id);
43263
43749
  if (prev && prev !== trait.currentState) {
@@ -43426,10 +43912,10 @@ function VerifyModePanel({
43426
43912
  localCount
43427
43913
  }) {
43428
43914
  const { t } = useTranslate();
43429
- const [expanded, setExpanded] = React95.useState(true);
43430
- const scrollRef = React95.useRef(null);
43431
- const prevCountRef = React95.useRef(0);
43432
- React95.useEffect(() => {
43915
+ const [expanded, setExpanded] = React96.useState(true);
43916
+ const scrollRef = React96.useRef(null);
43917
+ const prevCountRef = React96.useRef(0);
43918
+ React96.useEffect(() => {
43433
43919
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
43434
43920
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
43435
43921
  }
@@ -43486,10 +43972,10 @@ function RuntimeDebugger({
43486
43972
  schema
43487
43973
  }) {
43488
43974
  const { t } = useTranslate();
43489
- const [isCollapsed, setIsCollapsed] = React95.useState(mode === "verify" ? true : defaultCollapsed);
43490
- const [isVisible, setIsVisible] = React95.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
43975
+ const [isCollapsed, setIsCollapsed] = React96.useState(mode === "verify" ? true : defaultCollapsed);
43976
+ const [isVisible, setIsVisible] = React96.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
43491
43977
  const debugData = useDebugData();
43492
- React95.useEffect(() => {
43978
+ React96.useEffect(() => {
43493
43979
  if (mode === "inline") return;
43494
43980
  return onDebugToggle((enabled) => {
43495
43981
  setIsVisible(enabled);
@@ -43498,7 +43984,7 @@ function RuntimeDebugger({
43498
43984
  }
43499
43985
  });
43500
43986
  }, [mode]);
43501
- React95.useEffect(() => {
43987
+ React96.useEffect(() => {
43502
43988
  if (mode === "inline") return;
43503
43989
  const handleKeyDown = (e) => {
43504
43990
  if (e.key === "`" && isVisible) {
@@ -44018,7 +44504,7 @@ var init_StatCard = __esm({
44018
44504
  const labelToUse = propLabel ?? propTitle;
44019
44505
  const eventBus = useEventBus();
44020
44506
  const { t } = useTranslate();
44021
- const handleActionClick = React95__default.useCallback(() => {
44507
+ const handleActionClick = React96__default.useCallback(() => {
44022
44508
  if (action?.event) {
44023
44509
  eventBus.emit(`UI:${action.event}`, {});
44024
44510
  }
@@ -44029,7 +44515,7 @@ var init_StatCard = __esm({
44029
44515
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
44030
44516
  const isLoading = externalLoading ?? false;
44031
44517
  const error = externalError;
44032
- const computeMetricValue = React95__default.useCallback(
44518
+ const computeMetricValue = React96__default.useCallback(
44033
44519
  (metric, items) => {
44034
44520
  if (metric.value !== void 0) {
44035
44521
  return metric.value;
@@ -44068,7 +44554,7 @@ var init_StatCard = __esm({
44068
44554
  },
44069
44555
  []
44070
44556
  );
44071
- const schemaStats = React95__default.useMemo(() => {
44557
+ const schemaStats = React96__default.useMemo(() => {
44072
44558
  if (!metrics || metrics.length === 0) return null;
44073
44559
  return metrics.map((metric) => ({
44074
44560
  label: metric.label,
@@ -44076,7 +44562,7 @@ var init_StatCard = __esm({
44076
44562
  format: metric.format
44077
44563
  }));
44078
44564
  }, [metrics, data, computeMetricValue]);
44079
- const calculatedTrend = React95__default.useMemo(() => {
44565
+ const calculatedTrend = React96__default.useMemo(() => {
44080
44566
  if (manualTrend !== void 0) return manualTrend;
44081
44567
  if (previousValue === void 0 || currentValue === void 0)
44082
44568
  return void 0;
@@ -44716,8 +45202,8 @@ var init_SubagentTracePanel = __esm({
44716
45202
  ] });
44717
45203
  };
44718
45204
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
44719
- const endRef = React95__default.useRef(null);
44720
- React95__default.useEffect(() => {
45205
+ const endRef = React96__default.useRef(null);
45206
+ React96__default.useEffect(() => {
44721
45207
  if (!autoScroll) return;
44722
45208
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
44723
45209
  }, [activities.length, autoScroll]);
@@ -44811,7 +45297,7 @@ var init_SubagentTracePanel = __esm({
44811
45297
  };
44812
45298
  SubagentRichCard = ({ subagent }) => {
44813
45299
  const { t } = useTranslate();
44814
- const activities = React95__default.useMemo(
45300
+ const activities = React96__default.useMemo(
44815
45301
  () => subagentMessagesToActivities(subagent.messages),
44816
45302
  [subagent.messages]
44817
45303
  );
@@ -44888,8 +45374,8 @@ var init_SubagentTracePanel = __esm({
44888
45374
  ] });
44889
45375
  };
44890
45376
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
44891
- const endRef = React95__default.useRef(null);
44892
- React95__default.useEffect(() => {
45377
+ const endRef = React96__default.useRef(null);
45378
+ React96__default.useEffect(() => {
44893
45379
  if (!autoScroll) return;
44894
45380
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
44895
45381
  }, [messages.length, autoScroll]);
@@ -45319,7 +45805,7 @@ var init_Timeline = __esm({
45319
45805
  }) => {
45320
45806
  const { t } = useTranslate();
45321
45807
  const entityData = entity ?? [];
45322
- const items = React95__default.useMemo(() => {
45808
+ const items = React96__default.useMemo(() => {
45323
45809
  if (propItems) return propItems;
45324
45810
  if (entityData.length === 0) return [];
45325
45811
  return entityData.map((record, idx) => {
@@ -45421,7 +45907,7 @@ var init_Timeline = __esm({
45421
45907
  }
45422
45908
  });
45423
45909
  function extractToastProps(children) {
45424
- if (!React95__default.isValidElement(children)) {
45910
+ if (!React96__default.isValidElement(children)) {
45425
45911
  if (typeof children === "string") {
45426
45912
  return { message: children };
45427
45913
  }
@@ -45463,7 +45949,7 @@ var init_ToastSlot = __esm({
45463
45949
  eventBus.emit(`${prefix}CLOSE`);
45464
45950
  };
45465
45951
  if (!isVisible) return null;
45466
- const isCustomContent = React95__default.isValidElement(children) && !message;
45952
+ const isCustomContent = React96__default.isValidElement(children) && !message;
45467
45953
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
45468
45954
  Toast,
45469
45955
  {
@@ -45480,7 +45966,7 @@ var init_ToastSlot = __esm({
45480
45966
  }
45481
45967
  });
45482
45968
  function lazyThree(name, loader) {
45483
- const Lazy = React95__default.lazy(
45969
+ const Lazy = React96__default.lazy(
45484
45970
  () => loader().then((m) => {
45485
45971
  const Resolved = m[name];
45486
45972
  if (!Resolved) {
@@ -45492,13 +45978,13 @@ function lazyThree(name, loader) {
45492
45978
  })
45493
45979
  );
45494
45980
  function ThreeWrapper(props) {
45495
- return React95__default.createElement(
45981
+ return React96__default.createElement(
45496
45982
  ThreeBoundary,
45497
45983
  { name },
45498
- React95__default.createElement(
45499
- React95__default.Suspense,
45984
+ React96__default.createElement(
45985
+ React96__default.Suspense,
45500
45986
  { fallback: null },
45501
- React95__default.createElement(Lazy, props)
45987
+ React96__default.createElement(Lazy, props)
45502
45988
  )
45503
45989
  );
45504
45990
  }
@@ -45515,11 +46001,13 @@ var init_component_registry_generated = __esm({
45515
46001
  init_ActionTile();
45516
46002
  init_ActivationBlock();
45517
46003
  init_ComponentPatterns();
46004
+ init_AlgorithmCanvas();
45518
46005
  init_AnimatedCounter();
45519
46006
  init_AnimatedGraphic();
45520
46007
  init_AnimatedReveal();
45521
46008
  init_ArticleSection();
45522
46009
  init_Aside();
46010
+ init_AtlasImage();
45523
46011
  init_AuthLayout();
45524
46012
  init_Avatar();
45525
46013
  init_Badge();
@@ -45777,7 +46265,7 @@ var init_component_registry_generated = __esm({
45777
46265
  init_WizardContainer();
45778
46266
  init_WizardNavigation();
45779
46267
  init_WizardProgress();
45780
- ThreeBoundary = class extends React95__default.Component {
46268
+ ThreeBoundary = class extends React96__default.Component {
45781
46269
  constructor() {
45782
46270
  super(...arguments);
45783
46271
  __publicField(this, "state", { failed: false });
@@ -45787,7 +46275,7 @@ var init_component_registry_generated = __esm({
45787
46275
  }
45788
46276
  render() {
45789
46277
  if (this.state.failed) {
45790
- return React95__default.createElement(
46278
+ return React96__default.createElement(
45791
46279
  "div",
45792
46280
  {
45793
46281
  "data-testid": "three-unavailable",
@@ -45813,11 +46301,14 @@ var init_component_registry_generated = __esm({
45813
46301
  "ActivationBlock": ActivationBlock,
45814
46302
  "Alert": AlertPattern,
45815
46303
  "AlertPattern": AlertPattern,
46304
+ "AlgorithmCanvas": AlgorithmCanvas,
45816
46305
  "AnimatedCounter": AnimatedCounter,
45817
46306
  "AnimatedGraphic": AnimatedGraphic,
45818
46307
  "AnimatedReveal": AnimatedReveal,
45819
46308
  "ArticleSection": ArticleSection,
45820
46309
  "Aside": Aside,
46310
+ "AtlasImage": AtlasImage,
46311
+ "AtlasPanel": AtlasPanel,
45821
46312
  "AuthLayout": AuthLayout,
45822
46313
  "Avatar": Avatar,
45823
46314
  "Badge": Badge,
@@ -46110,7 +46601,7 @@ function SuspenseConfigProvider({
46110
46601
  config,
46111
46602
  children
46112
46603
  }) {
46113
- return React95__default.createElement(
46604
+ return React96__default.createElement(
46114
46605
  SuspenseConfigContext.Provider,
46115
46606
  { value: config },
46116
46607
  children
@@ -46152,7 +46643,7 @@ function enrichFormFields(fields, entityDef) {
46152
46643
  }
46153
46644
  return { name: field, label: field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase()) };
46154
46645
  }
46155
- if (field && typeof field === "object" && !Array.isArray(field) && !React95__default.isValidElement(field) && !(field instanceof Date)) {
46646
+ if (field && typeof field === "object" && !Array.isArray(field) && !React96__default.isValidElement(field) && !(field instanceof Date)) {
46156
46647
  const obj = field;
46157
46648
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
46158
46649
  if (!fieldName) return field;
@@ -46605,7 +47096,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
46605
47096
  const key = `${parentId}-${index}-trait:${traitName}`;
46606
47097
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
46607
47098
  }
46608
- return /* @__PURE__ */ jsx(React95__default.Fragment, { children: child }, `${parentId}-${index}`);
47099
+ return /* @__PURE__ */ jsx(React96__default.Fragment, { children: child }, `${parentId}-${index}`);
46609
47100
  }
46610
47101
  if (!child || typeof child !== "object") return null;
46611
47102
  const childId = `${parentId}-${index}`;
@@ -46645,14 +47136,14 @@ function isPatternConfig(value) {
46645
47136
  if (value === null || value === void 0) return false;
46646
47137
  if (typeof value !== "object") return false;
46647
47138
  if (Array.isArray(value)) return false;
46648
- if (React95__default.isValidElement(value)) return false;
47139
+ if (React96__default.isValidElement(value)) return false;
46649
47140
  if (value instanceof Date) return false;
46650
47141
  if (typeof value === "function") return false;
46651
47142
  const record = value;
46652
47143
  return "type" in record && typeof record.type === "string" && getComponentForPattern$1(record.type) !== null;
46653
47144
  }
46654
47145
  function isPlainConfigObject(value) {
46655
- if (React95__default.isValidElement(value)) return false;
47146
+ if (React96__default.isValidElement(value)) return false;
46656
47147
  if (value instanceof Date) return false;
46657
47148
  const proto = Object.getPrototypeOf(value);
46658
47149
  return proto === Object.prototype || proto === null;
@@ -46778,7 +47269,7 @@ function SlotContentRenderer({
46778
47269
  for (const slotKey of CONTENT_NODE_SLOTS) {
46779
47270
  const slotVal = restProps[slotKey];
46780
47271
  if (slotVal === void 0 || slotVal === null) continue;
46781
- if (React95__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
47272
+ if (React96__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
46782
47273
  if (Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
46783
47274
  nodeSlotOverrides[slotKey] = renderPatternChildren(
46784
47275
  slotVal,
@@ -46827,7 +47318,7 @@ function SlotContentRenderer({
46827
47318
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
46828
47319
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
46829
47320
  const sample = resolvedItems[0];
46830
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React95__default.isValidElement(sample) && !(sample instanceof Date)) {
47321
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React96__default.isValidElement(sample) && !(sample instanceof Date)) {
46831
47322
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
46832
47323
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
46833
47324
  }
@@ -46988,7 +47479,9 @@ var init_UISlotRenderer = __esm({
46988
47479
  "content",
46989
47480
  "addons",
46990
47481
  "hud",
46991
- "fallback"
47482
+ "fallback",
47483
+ "controls",
47484
+ "overlay"
46992
47485
  ]);
46993
47486
  PATTERNS_WITH_CHILDREN = /* @__PURE__ */ new Set([
46994
47487
  "stack",
@@ -47119,7 +47612,7 @@ function resolveLambdaBindings(body, params, item, index) {
47119
47612
  if (Array.isArray(body)) {
47120
47613
  return body.map((b) => recur(b));
47121
47614
  }
47122
- if (body !== null && typeof body === "object" && !React95__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
47615
+ if (body !== null && typeof body === "object" && !React96__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
47123
47616
  const out = {};
47124
47617
  for (const [k, v] of Object.entries(body)) {
47125
47618
  out[k] = recur(v);
@@ -47138,7 +47631,7 @@ function getSlotContentRenderer2() {
47138
47631
  function makeLambdaFn(params, lambdaBody, callerKey) {
47139
47632
  return (item, index) => {
47140
47633
  const resolvedBody = resolveLambdaBindings(lambdaBody, params, item, index);
47141
- if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React95__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
47634
+ if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React96__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
47142
47635
  return null;
47143
47636
  }
47144
47637
  const record = resolvedBody;
@@ -47157,7 +47650,7 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
47157
47650
  props: childProps,
47158
47651
  priority: 0
47159
47652
  };
47160
- return React95__default.createElement(SlotContentRenderer2, { content: childContent });
47653
+ return React96__default.createElement(SlotContentRenderer2, { content: childContent });
47161
47654
  };
47162
47655
  }
47163
47656
  function convertNode(node, callerKey) {
@@ -47176,7 +47669,7 @@ function convertNode(node, callerKey) {
47176
47669
  });
47177
47670
  return anyChanged ? mapped : node;
47178
47671
  }
47179
- if (typeof node === "object" && !React95__default.isValidElement(node) && !(node instanceof Date)) {
47672
+ if (typeof node === "object" && !React96__default.isValidElement(node) && !(node instanceof Date)) {
47180
47673
  return convertObjectProps(node);
47181
47674
  }
47182
47675
  return node;