@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 React97 from 'react';
2
- import React97__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useLayoutEffect, lazy, useId, useSyncExternalStore } from 'react';
1
+ import * as React98 from 'react';
2
+ import React98__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useLayoutEffect, lazy, useId, useSyncExternalStore } from 'react';
3
3
  import { EventBusContext, useTraitScope, useEntitySchemaOptional, TraitScopeProvider, useCurrentPagePath } from '@almadar/ui/providers';
4
4
  import { createLogger, isLogLevelEnabled } from '@almadar/logger';
5
5
  import { clsx } from 'clsx';
@@ -388,7 +388,7 @@ var init_Box = __esm({
388
388
  fixed: "fixed",
389
389
  sticky: "sticky"
390
390
  };
391
- Box = React97__default.forwardRef(
391
+ Box = React98__default.forwardRef(
392
392
  ({
393
393
  padding,
394
394
  paddingX,
@@ -453,7 +453,7 @@ var init_Box = __esm({
453
453
  onPointerDown?.(e);
454
454
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
455
455
  const isClickable = action || onClick;
456
- return React97__default.createElement(
456
+ return React98__default.createElement(
457
457
  Component,
458
458
  {
459
459
  ref,
@@ -549,7 +549,7 @@ function loadLib(key, importer) {
549
549
  return p;
550
550
  }
551
551
  function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
552
- const Lazy = React97__default.lazy(async () => {
552
+ const Lazy = React98__default.lazy(async () => {
553
553
  const lib = await loadLib(libKey, importer);
554
554
  const Comp = pick(lib);
555
555
  if (!Comp) {
@@ -559,7 +559,7 @@ function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
559
559
  return { default: Comp };
560
560
  });
561
561
  const Wrapped = (props) => /* @__PURE__ */ jsx(
562
- React97__default.Suspense,
562
+ React98__default.Suspense,
563
563
  {
564
564
  fallback: /* @__PURE__ */ jsx(
565
565
  "span",
@@ -1290,7 +1290,7 @@ var init_Icon = __esm({
1290
1290
  const directIcon = typeof icon === "string" ? void 0 : icon;
1291
1291
  const effectiveName = typeof icon === "string" ? icon : name;
1292
1292
  const family = useIconFamily();
1293
- const RenderedComponent = React97__default.useMemo(() => {
1293
+ const RenderedComponent = React98__default.useMemo(() => {
1294
1294
  if (directIcon) return null;
1295
1295
  return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1296
1296
  }, [directIcon, effectiveName, family]);
@@ -1340,6 +1340,210 @@ var init_Icon = __esm({
1340
1340
  Icon.displayName = "Icon";
1341
1341
  }
1342
1342
  });
1343
+
1344
+ // lib/atlasSlice.ts
1345
+ function isTilesheet(a) {
1346
+ return typeof a.tileWidth === "number";
1347
+ }
1348
+ function getAtlas(url, onReady) {
1349
+ if (atlasCache.has(url)) return atlasCache.get(url) ?? void 0;
1350
+ atlasCache.set(url, void 0);
1351
+ fetch(url).then((r) => r.json()).then((json) => {
1352
+ atlasCache.set(url, json);
1353
+ onReady();
1354
+ }).catch(() => {
1355
+ atlasCache.set(url, null);
1356
+ });
1357
+ return void 0;
1358
+ }
1359
+ function subRectFor(atlas, sprite) {
1360
+ if (isTilesheet(atlas)) {
1361
+ let col;
1362
+ let row;
1363
+ if (sprite.includes(",")) {
1364
+ const [c, r] = sprite.split(",").map((n) => Number(n.trim()));
1365
+ col = c;
1366
+ row = r;
1367
+ } else {
1368
+ const i = Number(sprite);
1369
+ if (!Number.isFinite(i)) return null;
1370
+ col = i % atlas.columns;
1371
+ row = Math.floor(i / atlas.columns);
1372
+ }
1373
+ if (!Number.isFinite(col) || !Number.isFinite(row) || col < 0 || row < 0 || col >= atlas.columns || row >= atlas.rows) return null;
1374
+ const margin = atlas.margin ?? 0;
1375
+ const spacing = atlas.spacing ?? 0;
1376
+ return {
1377
+ sx: margin + col * (atlas.tileWidth + spacing),
1378
+ sy: margin + row * (atlas.tileHeight + spacing),
1379
+ sw: atlas.tileWidth,
1380
+ sh: atlas.tileHeight
1381
+ };
1382
+ }
1383
+ const st = atlas.subTextures[sprite];
1384
+ if (!st) return null;
1385
+ return { sx: st.x, sy: st.y, sw: st.width, sh: st.height };
1386
+ }
1387
+ function isAtlasAsset(asset) {
1388
+ return !!asset && typeof asset.atlas === "string" && typeof asset.sprite === "string";
1389
+ }
1390
+ function resolveAssetSource(img, asset, onReady) {
1391
+ if (isAtlasAsset(asset)) {
1392
+ const atlas = getAtlas(asset.atlas, onReady);
1393
+ if (!atlas) return null;
1394
+ const rect = subRectFor(atlas, asset.sprite);
1395
+ if (!rect) return null;
1396
+ return { img, rect, aspect: rect.sw / rect.sh };
1397
+ }
1398
+ const natW = img.naturalWidth || 1;
1399
+ const natH = img.naturalHeight || 1;
1400
+ return { img, rect: null, aspect: natW / natH };
1401
+ }
1402
+ function blit(ctx, src, dx, dy, dw, dh) {
1403
+ if (src.rect) ctx.drawImage(src.img, src.rect.sx, src.rect.sy, src.rect.sw, src.rect.sh, dx, dy, dw, dh);
1404
+ else ctx.drawImage(src.img, dx, dy, dw, dh);
1405
+ }
1406
+ var atlasCache;
1407
+ var init_atlasSlice = __esm({
1408
+ "lib/atlasSlice.ts"() {
1409
+ "use client";
1410
+ atlasCache = /* @__PURE__ */ new Map();
1411
+ }
1412
+ });
1413
+ function useAtlasSliceDataUrl(asset) {
1414
+ const [, bump] = React98.useReducer((x) => x + 1, 0);
1415
+ if (!isAtlasAsset(asset)) return void 0;
1416
+ const key = `${asset.atlas}#${asset.sprite}`;
1417
+ const cached = sliceDataUrlCache.get(key);
1418
+ if (cached) return cached;
1419
+ const atlas = getAtlas(asset.atlas, bump);
1420
+ const img = asset?.url ? getSheetImage(asset.url, bump) : null;
1421
+ if (!atlas || !img) return void 0;
1422
+ const rect = subRectFor(atlas, asset.sprite);
1423
+ if (!rect) return void 0;
1424
+ const canvas = document.createElement("canvas");
1425
+ canvas.width = rect.sw;
1426
+ canvas.height = rect.sh;
1427
+ const ctx = canvas.getContext("2d");
1428
+ if (!ctx) return void 0;
1429
+ ctx.imageSmoothingEnabled = false;
1430
+ ctx.drawImage(img, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
1431
+ const url = canvas.toDataURL();
1432
+ sliceDataUrlCache.set(key, url);
1433
+ return url;
1434
+ }
1435
+ function AtlasPanel({ asset, borderSlice = 16, borderWidth = 16, mode = "nineSlice", className, style, children, "aria-hidden": ariaHidden }) {
1436
+ const dataUrl = useAtlasSliceDataUrl(asset);
1437
+ const skin = !dataUrl ? {} : mode === "repeat" ? { backgroundImage: `url(${dataUrl})`, backgroundRepeat: "repeat" } : {
1438
+ borderStyle: "solid",
1439
+ borderWidth,
1440
+ borderImageSource: `url(${dataUrl})`,
1441
+ borderImageSlice: `${borderSlice} fill`,
1442
+ borderImageWidth: borderWidth,
1443
+ borderImageRepeat: "stretch",
1444
+ imageRendering: "pixelated"
1445
+ };
1446
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": ariaHidden, className: cn("inline-block", className), style: { ...skin, ...style }, children });
1447
+ }
1448
+ function getSheetImage(url, onReady) {
1449
+ const cached = imageCache.get(url);
1450
+ if (cached) return cached;
1451
+ (imageWaiters.get(url) ?? imageWaiters.set(url, /* @__PURE__ */ new Set()).get(url)).add(onReady);
1452
+ if (!imageCache.has(url)) {
1453
+ imageCache.set(url, null);
1454
+ const img = new Image();
1455
+ img.crossOrigin = "anonymous";
1456
+ img.onload = () => {
1457
+ imageCache.set(url, img);
1458
+ imageWaiters.get(url)?.forEach((fn) => fn());
1459
+ imageWaiters.delete(url);
1460
+ };
1461
+ img.src = url;
1462
+ }
1463
+ return null;
1464
+ }
1465
+ function AtlasImage({
1466
+ asset,
1467
+ size,
1468
+ width,
1469
+ height,
1470
+ fill = false,
1471
+ fit = "contain",
1472
+ alt,
1473
+ className,
1474
+ style,
1475
+ "aria-hidden": ariaHidden
1476
+ }) {
1477
+ const [, bump] = React98.useReducer((x) => x + 1, 0);
1478
+ const canvasRef = React98.useRef(null);
1479
+ const sliced = isAtlasAsset(asset);
1480
+ const atlas = sliced ? getAtlas(asset.atlas, bump) : void 0;
1481
+ const img = sliced && asset?.url ? getSheetImage(asset.url, bump) : null;
1482
+ const rect = sliced && atlas ? subRectFor(atlas, asset.sprite) : null;
1483
+ React98.useEffect(() => {
1484
+ const canvas = canvasRef.current;
1485
+ if (!canvas || !img || !rect) return;
1486
+ canvas.width = rect.sw;
1487
+ canvas.height = rect.sh;
1488
+ const ctx = canvas.getContext("2d");
1489
+ if (!ctx) return;
1490
+ ctx.imageSmoothingEnabled = false;
1491
+ ctx.clearRect(0, 0, rect.sw, rect.sh);
1492
+ ctx.drawImage(img, rect.sx, rect.sy, rect.sw, rect.sh, 0, 0, rect.sw, rect.sh);
1493
+ }, [img, rect?.sx, rect?.sy, rect?.sw, rect?.sh]);
1494
+ const w = fill ? "100%" : width ?? size;
1495
+ const h = fill ? "100%" : height ?? size;
1496
+ const boxStyle = {
1497
+ ...fill ? { position: "absolute", inset: 0 } : {},
1498
+ width: w,
1499
+ height: h,
1500
+ objectFit: fit,
1501
+ imageRendering: "pixelated",
1502
+ ...style
1503
+ };
1504
+ if (!asset?.url) return null;
1505
+ if (sliced) {
1506
+ if (!rect || !img) {
1507
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("inline-block flex-shrink-0", className), style: { ...boxStyle, objectFit: void 0 } });
1508
+ }
1509
+ return /* @__PURE__ */ jsx(
1510
+ "canvas",
1511
+ {
1512
+ ref: canvasRef,
1513
+ role: ariaHidden ? void 0 : "img",
1514
+ "aria-hidden": ariaHidden,
1515
+ "aria-label": ariaHidden ? void 0 : alt ?? asset.name ?? asset.category ?? "",
1516
+ className: cn("flex-shrink-0", className),
1517
+ style: boxStyle
1518
+ }
1519
+ );
1520
+ }
1521
+ return /* @__PURE__ */ jsx(
1522
+ "img",
1523
+ {
1524
+ src: asset.url,
1525
+ alt: alt ?? asset.name ?? asset.category ?? "",
1526
+ "aria-hidden": ariaHidden,
1527
+ ...typeof w === "number" ? { width: w } : {},
1528
+ ...typeof h === "number" ? { height: h } : {},
1529
+ className: cn("flex-shrink-0", className),
1530
+ style: boxStyle
1531
+ }
1532
+ );
1533
+ }
1534
+ var sliceDataUrlCache, imageCache, imageWaiters;
1535
+ var init_AtlasImage = __esm({
1536
+ "components/core/atoms/AtlasImage.tsx"() {
1537
+ "use client";
1538
+ init_atlasSlice();
1539
+ init_cn();
1540
+ sliceDataUrlCache = /* @__PURE__ */ new Map();
1541
+ AtlasPanel.displayName = "AtlasPanel";
1542
+ imageCache = /* @__PURE__ */ new Map();
1543
+ imageWaiters = /* @__PURE__ */ new Map();
1544
+ AtlasImage.displayName = "AtlasImage";
1545
+ }
1546
+ });
1343
1547
  function isIconLike(v) {
1344
1548
  return typeof v.render === "function";
1345
1549
  }
@@ -1352,7 +1556,7 @@ function resolveIconProp(value, sizeClass) {
1352
1556
  const IconComp = value;
1353
1557
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
1354
1558
  }
1355
- if (React97__default.isValidElement(value)) {
1559
+ if (React98__default.isValidElement(value)) {
1356
1560
  return value;
1357
1561
  }
1358
1562
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -1368,6 +1572,7 @@ var init_Button = __esm({
1368
1572
  init_cn();
1369
1573
  init_useEventBus();
1370
1574
  init_Icon();
1575
+ init_AtlasImage();
1371
1576
  variantStyles = {
1372
1577
  primary: [
1373
1578
  "bg-primary text-primary-foreground",
@@ -1428,7 +1633,7 @@ var init_Button = __esm({
1428
1633
  md: "h-icon-default w-icon-default",
1429
1634
  lg: "h-icon-default w-icon-default"
1430
1635
  };
1431
- Button = React97__default.forwardRef(
1636
+ Button = React98__default.forwardRef(
1432
1637
  ({
1433
1638
  className,
1434
1639
  variant = "primary",
@@ -1452,7 +1657,7 @@ var init_Button = __esm({
1452
1657
  const leftIconValue = leftIcon || iconProp;
1453
1658
  const rightIconValue = rightIcon || iconRightProp;
1454
1659
  const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
1455
- 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]);
1660
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ jsx(AtlasImage, { asset: iconAsset, size: px, alt: iconAsset.name ?? iconAsset.category ?? "", className: "flex-shrink-0" }) : resolveIconProp(leftIconValue, iconSizeStyles[size]);
1456
1661
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
1457
1662
  const handleClick = (e) => {
1458
1663
  if (action) {
@@ -1496,7 +1701,7 @@ var Dialog;
1496
1701
  var init_Dialog = __esm({
1497
1702
  "components/core/atoms/Dialog.tsx"() {
1498
1703
  init_cn();
1499
- Dialog = React97__default.forwardRef(
1704
+ Dialog = React98__default.forwardRef(
1500
1705
  ({
1501
1706
  role = "dialog",
1502
1707
  "aria-modal": ariaModal = true,
@@ -1614,7 +1819,7 @@ var init_Typography = __esm({
1614
1819
  }) => {
1615
1820
  const variant = variantProp ?? (level ? `h${level}` : "body1");
1616
1821
  const Component = as || defaultElements[variant];
1617
- return React97__default.createElement(
1822
+ return React98__default.createElement(
1618
1823
  Component,
1619
1824
  {
1620
1825
  id,
@@ -2072,6 +2277,7 @@ var init_Badge = __esm({
2072
2277
  "components/core/atoms/Badge.tsx"() {
2073
2278
  init_cn();
2074
2279
  init_Icon();
2280
+ init_AtlasImage();
2075
2281
  variantStyles3 = {
2076
2282
  default: [
2077
2283
  "bg-muted text-foreground",
@@ -2109,7 +2315,7 @@ var init_Badge = __esm({
2109
2315
  md: "px-2.5 py-1 text-sm",
2110
2316
  lg: "px-3 py-1.5 text-base"
2111
2317
  };
2112
- Badge = React97__default.forwardRef(
2318
+ Badge = React98__default.forwardRef(
2113
2319
  ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2114
2320
  const iconSizes3 = {
2115
2321
  sm: "h-icon-default w-icon-default",
@@ -2117,7 +2323,7 @@ var init_Badge = __esm({
2117
2323
  lg: "h-icon-default w-icon-default"
2118
2324
  };
2119
2325
  const iconPx = size === "lg" ? 20 : 16;
2120
- 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;
2326
+ 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;
2121
2327
  return /* @__PURE__ */ jsxs(
2122
2328
  "span",
2123
2329
  {
@@ -2446,7 +2652,7 @@ var init_SvgFlow = __esm({
2446
2652
  width = 100,
2447
2653
  height = 100
2448
2654
  }) => {
2449
- const markerId = React97__default.useMemo(() => {
2655
+ const markerId = React98__default.useMemo(() => {
2450
2656
  flowIdCounter += 1;
2451
2657
  return `almadar-flow-arrow-${flowIdCounter}`;
2452
2658
  }, []);
@@ -3039,7 +3245,7 @@ var init_SvgRing = __esm({
3039
3245
  width = 100,
3040
3246
  height = 100
3041
3247
  }) => {
3042
- const gradientId = React97__default.useMemo(() => {
3248
+ const gradientId = React98__default.useMemo(() => {
3043
3249
  ringIdCounter += 1;
3044
3250
  return `almadar-ring-glow-${ringIdCounter}`;
3045
3251
  }, []);
@@ -3220,7 +3426,7 @@ var init_Input = __esm({
3220
3426
  init_cn();
3221
3427
  init_Icon();
3222
3428
  init_useEventBus();
3223
- Input = React97__default.forwardRef(
3429
+ Input = React98__default.forwardRef(
3224
3430
  ({
3225
3431
  className,
3226
3432
  inputType,
@@ -3380,7 +3586,7 @@ var Label;
3380
3586
  var init_Label = __esm({
3381
3587
  "components/core/atoms/Label.tsx"() {
3382
3588
  init_cn();
3383
- Label = React97__default.forwardRef(
3589
+ Label = React98__default.forwardRef(
3384
3590
  ({ className, required, children, ...props }, ref) => {
3385
3591
  return /* @__PURE__ */ jsxs(
3386
3592
  "label",
@@ -3407,7 +3613,7 @@ var init_Textarea = __esm({
3407
3613
  "components/core/atoms/Textarea.tsx"() {
3408
3614
  init_cn();
3409
3615
  init_useEventBus();
3410
- Textarea = React97__default.forwardRef(
3616
+ Textarea = React98__default.forwardRef(
3411
3617
  ({ className, error, onChange, ...props }, ref) => {
3412
3618
  const eventBus = useEventBus();
3413
3619
  const handleChange = (e) => {
@@ -3646,7 +3852,7 @@ var init_Select = __esm({
3646
3852
  init_cn();
3647
3853
  init_Icon();
3648
3854
  init_useEventBus();
3649
- Select = React97__default.forwardRef(
3855
+ Select = React98__default.forwardRef(
3650
3856
  (props, _ref) => {
3651
3857
  const { multiple, searchable, clearable } = props;
3652
3858
  if (multiple || searchable || clearable) {
@@ -3663,7 +3869,7 @@ var init_Checkbox = __esm({
3663
3869
  "components/core/atoms/Checkbox.tsx"() {
3664
3870
  init_cn();
3665
3871
  init_useEventBus();
3666
- Checkbox = React97__default.forwardRef(
3872
+ Checkbox = React98__default.forwardRef(
3667
3873
  ({ className, label, id, onChange, ...props }, ref) => {
3668
3874
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
3669
3875
  const eventBus = useEventBus();
@@ -3717,7 +3923,7 @@ var init_Spinner = __esm({
3717
3923
  md: "h-6 w-6",
3718
3924
  lg: "h-8 w-8"
3719
3925
  };
3720
- Spinner = React97__default.forwardRef(
3926
+ Spinner = React98__default.forwardRef(
3721
3927
  ({ className, size = "md", overlay, ...props }, ref) => {
3722
3928
  if (overlay) {
3723
3929
  return /* @__PURE__ */ jsx(
@@ -3807,7 +4013,7 @@ var init_Card = __esm({
3807
4013
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
3808
4014
  "tile-image-first": "p-0 overflow-hidden"
3809
4015
  };
3810
- Card = React97__default.forwardRef(
4016
+ Card = React98__default.forwardRef(
3811
4017
  ({
3812
4018
  className,
3813
4019
  variant = "bordered",
@@ -3855,9 +4061,9 @@ var init_Card = __esm({
3855
4061
  }
3856
4062
  );
3857
4063
  Card.displayName = "Card";
3858
- CardHeader = React97__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
4064
+ CardHeader = React98__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
3859
4065
  CardHeader.displayName = "CardHeader";
3860
- CardTitle = React97__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4066
+ CardTitle = React98__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3861
4067
  "h3",
3862
4068
  {
3863
4069
  ref,
@@ -3870,11 +4076,11 @@ var init_Card = __esm({
3870
4076
  }
3871
4077
  ));
3872
4078
  CardTitle.displayName = "CardTitle";
3873
- CardContent = React97__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
4079
+ CardContent = React98__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
3874
4080
  CardContent.displayName = "CardContent";
3875
4081
  CardBody = CardContent;
3876
4082
  CardBody.displayName = "CardBody";
3877
- CardFooter = React97__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4083
+ CardFooter = React98__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3878
4084
  "div",
3879
4085
  {
3880
4086
  ref,
@@ -3929,7 +4135,7 @@ var init_FilterPill = __esm({
3929
4135
  md: "w-3.5 h-3.5",
3930
4136
  lg: "w-4 h-4"
3931
4137
  };
3932
- FilterPill = React97__default.forwardRef(
4138
+ FilterPill = React98__default.forwardRef(
3933
4139
  ({
3934
4140
  className,
3935
4141
  variant = "default",
@@ -4058,8 +4264,8 @@ var init_Avatar = __esm({
4058
4264
  actionPayload
4059
4265
  }) => {
4060
4266
  const eventBus = useEventBus();
4061
- const [imgFailed, setImgFailed] = React97__default.useState(false);
4062
- React97__default.useEffect(() => {
4267
+ const [imgFailed, setImgFailed] = React98__default.useState(false);
4268
+ React98__default.useEffect(() => {
4063
4269
  setImgFailed(false);
4064
4270
  }, [src]);
4065
4271
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -4172,7 +4378,7 @@ var init_Center = __esm({
4172
4378
  as: Component = "div"
4173
4379
  }) => {
4174
4380
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
4175
- return React97__default.createElement(Component, {
4381
+ return React98__default.createElement(Component, {
4176
4382
  className: cn(
4177
4383
  inline ? "inline-flex" : "flex",
4178
4384
  horizontal && "justify-center",
@@ -4440,7 +4646,7 @@ var init_Radio = __esm({
4440
4646
  md: "w-2.5 h-2.5",
4441
4647
  lg: "w-3 h-3"
4442
4648
  };
4443
- Radio = React97__default.forwardRef(
4649
+ Radio = React98__default.forwardRef(
4444
4650
  ({
4445
4651
  label,
4446
4652
  helperText,
@@ -4457,12 +4663,12 @@ var init_Radio = __esm({
4457
4663
  onChange,
4458
4664
  ...props
4459
4665
  }, ref) => {
4460
- const reactId = React97__default.useId();
4666
+ const reactId = React98__default.useId();
4461
4667
  const baseId = id || `radio-${reactId}`;
4462
4668
  const hasError = !!error;
4463
4669
  const eventBus = useEventBus();
4464
- const [selected, setSelected] = React97__default.useState(value);
4465
- React97__default.useEffect(() => {
4670
+ const [selected, setSelected] = React98__default.useState(value);
4671
+ React98__default.useEffect(() => {
4466
4672
  if (value !== void 0) setSelected(value);
4467
4673
  }, [value]);
4468
4674
  const pick = (next, e) => {
@@ -4644,7 +4850,7 @@ var init_Switch = __esm({
4644
4850
  "components/core/atoms/Switch.tsx"() {
4645
4851
  "use client";
4646
4852
  init_cn();
4647
- Switch = React97.forwardRef(
4853
+ Switch = React98.forwardRef(
4648
4854
  ({
4649
4855
  checked,
4650
4856
  defaultChecked = false,
@@ -4655,10 +4861,10 @@ var init_Switch = __esm({
4655
4861
  name,
4656
4862
  className
4657
4863
  }, ref) => {
4658
- const [isChecked, setIsChecked] = React97.useState(
4864
+ const [isChecked, setIsChecked] = React98.useState(
4659
4865
  checked !== void 0 ? checked : defaultChecked
4660
4866
  );
4661
- React97.useEffect(() => {
4867
+ React98.useEffect(() => {
4662
4868
  if (checked !== void 0) {
4663
4869
  setIsChecked(checked);
4664
4870
  }
@@ -4821,7 +5027,7 @@ var init_Stack = __esm({
4821
5027
  };
4822
5028
  const isHorizontal = direction === "horizontal";
4823
5029
  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";
4824
- return React97__default.createElement(
5030
+ return React98__default.createElement(
4825
5031
  Component,
4826
5032
  {
4827
5033
  className: cn(
@@ -5021,7 +5227,7 @@ var Aside;
5021
5227
  var init_Aside = __esm({
5022
5228
  "components/core/atoms/Aside.tsx"() {
5023
5229
  init_cn();
5024
- Aside = React97__default.forwardRef(
5230
+ Aside = React98__default.forwardRef(
5025
5231
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
5026
5232
  );
5027
5233
  Aside.displayName = "Aside";
@@ -5100,9 +5306,9 @@ var init_LawReferenceTooltip = __esm({
5100
5306
  className
5101
5307
  }) => {
5102
5308
  const { t } = useTranslate();
5103
- const [isVisible, setIsVisible] = React97__default.useState(false);
5104
- const timeoutRef = React97__default.useRef(null);
5105
- const triggerRef = React97__default.useRef(null);
5309
+ const [isVisible, setIsVisible] = React98__default.useState(false);
5310
+ const timeoutRef = React98__default.useRef(null);
5311
+ const triggerRef = React98__default.useRef(null);
5106
5312
  const handleMouseEnter = () => {
5107
5313
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5108
5314
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -5113,7 +5319,7 @@ var init_LawReferenceTooltip = __esm({
5113
5319
  };
5114
5320
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
5115
5321
  const open = isVisible || revealed;
5116
- React97__default.useEffect(() => {
5322
+ React98__default.useEffect(() => {
5117
5323
  return () => {
5118
5324
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5119
5325
  };
@@ -5323,7 +5529,7 @@ var init_StatusDot = __esm({
5323
5529
  md: "w-2.5 h-2.5",
5324
5530
  lg: "w-3 h-3"
5325
5531
  };
5326
- StatusDot = React97__default.forwardRef(
5532
+ StatusDot = React98__default.forwardRef(
5327
5533
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
5328
5534
  return /* @__PURE__ */ jsx(
5329
5535
  "span",
@@ -5377,7 +5583,7 @@ var init_TrendIndicator = __esm({
5377
5583
  down: "trending-down",
5378
5584
  flat: "arrow-right"
5379
5585
  };
5380
- TrendIndicator = React97__default.forwardRef(
5586
+ TrendIndicator = React98__default.forwardRef(
5381
5587
  ({
5382
5588
  className,
5383
5589
  value,
@@ -5444,7 +5650,7 @@ var init_RangeSlider = __esm({
5444
5650
  md: "w-4 h-4",
5445
5651
  lg: "w-5 h-5"
5446
5652
  };
5447
- RangeSlider = React97__default.forwardRef(
5653
+ RangeSlider = React98__default.forwardRef(
5448
5654
  ({
5449
5655
  className,
5450
5656
  min = 0,
@@ -6038,7 +6244,7 @@ var init_ContentSection = __esm({
6038
6244
  md: "py-16",
6039
6245
  lg: "py-24"
6040
6246
  };
6041
- ContentSection = React97__default.forwardRef(
6247
+ ContentSection = React98__default.forwardRef(
6042
6248
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
6043
6249
  return /* @__PURE__ */ jsx(
6044
6250
  Box,
@@ -6572,7 +6778,7 @@ var init_AnimatedReveal = __esm({
6572
6778
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
6573
6779
  "none": {}
6574
6780
  };
6575
- AnimatedReveal = React97__default.forwardRef(
6781
+ AnimatedReveal = React98__default.forwardRef(
6576
6782
  ({
6577
6783
  trigger = "scroll",
6578
6784
  animation = "fade-up",
@@ -6732,7 +6938,7 @@ var init_AnimatedGraphic = __esm({
6732
6938
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
6733
6939
  "use client";
6734
6940
  init_cn();
6735
- AnimatedGraphic = React97__default.forwardRef(
6941
+ AnimatedGraphic = React98__default.forwardRef(
6736
6942
  ({
6737
6943
  src,
6738
6944
  svgContent,
@@ -6755,7 +6961,7 @@ var init_AnimatedGraphic = __esm({
6755
6961
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
6756
6962
  const resolvedSvg = svgContent ?? fetchedSvg;
6757
6963
  const prevAnimateRef = useRef(animate);
6758
- const setRef = React97__default.useCallback(
6964
+ const setRef = React98__default.useCallback(
6759
6965
  (node) => {
6760
6966
  containerRef.current = node;
6761
6967
  if (typeof ref === "function") ref(node);
@@ -7215,7 +7421,7 @@ function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
7215
7421
  }
7216
7422
  if (layout === "flat") {
7217
7423
  const screenX2 = tileX * scaledTileWidth + baseOffsetX;
7218
- const screenY2 = tileY * scaledFloorHeight;
7424
+ const screenY2 = tileY * scaledTileWidth;
7219
7425
  return { x: screenX2, y: screenY2 };
7220
7426
  }
7221
7427
  const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
@@ -7232,7 +7438,7 @@ function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric")
7232
7438
  }
7233
7439
  if (layout === "flat") {
7234
7440
  const col = Math.round((screenX - baseOffsetX) / scaledTileWidth);
7235
- const row = Math.round(screenY / scaledFloorHeight);
7441
+ const row = Math.round(screenY / scaledTileWidth);
7236
7442
  return { x: col, y: row };
7237
7443
  }
7238
7444
  const adjustedX = screenX - baseOffsetX;
@@ -7306,13 +7512,11 @@ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
7306
7512
  const px = typeof size === "number" ? size : sizeMap[size];
7307
7513
  if (assetUrl?.url) {
7308
7514
  return /* @__PURE__ */ jsx(
7309
- "img",
7515
+ AtlasImage,
7310
7516
  {
7311
- src: assetUrl.url,
7517
+ asset: assetUrl,
7518
+ size: px,
7312
7519
  alt: alt ?? assetUrl.category ?? "",
7313
- width: px,
7314
- height: px,
7315
- style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
7316
7520
  className: cn("flex-shrink-0", className)
7317
7521
  }
7318
7522
  );
@@ -7326,6 +7530,7 @@ var init_GameIcon = __esm({
7326
7530
  "use client";
7327
7531
  init_cn();
7328
7532
  init_Icon();
7533
+ init_AtlasImage();
7329
7534
  sizeMap = {
7330
7535
  sm: 16,
7331
7536
  md: 24,
@@ -7351,13 +7556,12 @@ function GameCard({
7351
7556
  className
7352
7557
  }) {
7353
7558
  const eventBus = useEventBus();
7354
- const handleClick = React97.useCallback(() => {
7559
+ const handleClick = React98.useCallback(() => {
7355
7560
  if (disabled) return;
7356
7561
  onClick?.(id);
7357
7562
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
7358
7563
  }, [disabled, id, onClick, clickEvent, eventBus]);
7359
7564
  const artPx = artPxMap[size];
7360
- const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
7361
7565
  return /* @__PURE__ */ jsxs(
7362
7566
  Button,
7363
7567
  {
@@ -7365,11 +7569,10 @@ function GameCard({
7365
7569
  onClick: handleClick,
7366
7570
  disabled,
7367
7571
  title: name,
7368
- style: frameStyle,
7369
7572
  className: cn(
7370
- "relative flex flex-col items-center rounded-interactive",
7371
- "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
7372
- frameAsset?.url ? "border-0" : "border-2",
7573
+ "relative isolate flex flex-col items-center rounded-interactive",
7574
+ "px-1.5 pt-1.5 pb-1 transition-all duration-150",
7575
+ frameAsset?.url ? "border-0" : "border-2 bg-card/90",
7373
7576
  cardSizeMap[size],
7374
7577
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
7375
7578
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -7377,6 +7580,7 @@ function GameCard({
7377
7580
  className
7378
7581
  ),
7379
7582
  children: [
7583
+ frameAsset?.url && /* @__PURE__ */ jsx(AtlasImage, { asset: frameAsset, fill: true, fit: "fill", "aria-hidden": true, style: { zIndex: -1 } }),
7380
7584
  cost != null && /* @__PURE__ */ jsx(
7381
7585
  Typography,
7382
7586
  {
@@ -7415,6 +7619,7 @@ var init_GameCard = __esm({
7415
7619
  init_Box();
7416
7620
  init_Button();
7417
7621
  init_Typography();
7622
+ init_AtlasImage();
7418
7623
  init_GameIcon();
7419
7624
  cardSizeMap = {
7420
7625
  sm: "w-16 h-24",
@@ -7575,7 +7780,7 @@ var init_HealthBar = __esm({
7575
7780
  }
7576
7781
  });
7577
7782
  function ScoreDisplay({
7578
- assetUrl = DEFAULT_ASSET_URL,
7783
+ assetUrl,
7579
7784
  value,
7580
7785
  score,
7581
7786
  label,
@@ -7602,7 +7807,7 @@ function ScoreDisplay({
7602
7807
  }
7603
7808
  );
7604
7809
  }
7605
- var sizeMap3, DEFAULT_ASSET_URL;
7810
+ var sizeMap3;
7606
7811
  var init_ScoreDisplay = __esm({
7607
7812
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
7608
7813
  init_cn();
@@ -7616,16 +7821,11 @@ var init_ScoreDisplay = __esm({
7616
7821
  lg: "text-2xl",
7617
7822
  xl: "text-4xl"
7618
7823
  };
7619
- DEFAULT_ASSET_URL = {
7620
- url: "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png",
7621
- role: "effect",
7622
- category: "effect"
7623
- };
7624
7824
  ScoreDisplay.displayName = "ScoreDisplay";
7625
7825
  }
7626
7826
  });
7627
7827
  function ControlButton({
7628
- assetUrl = DEFAULT_ASSET_URL2,
7828
+ assetUrl = DEFAULT_ASSET_URL,
7629
7829
  label,
7630
7830
  icon,
7631
7831
  size = "md",
@@ -7640,9 +7840,9 @@ function ControlButton({
7640
7840
  className
7641
7841
  }) {
7642
7842
  const eventBus = useEventBus();
7643
- const [isPressed, setIsPressed] = React97.useState(false);
7843
+ const [isPressed, setIsPressed] = React98.useState(false);
7644
7844
  const actualPressed = pressed ?? isPressed;
7645
- const handlePointerDown = React97.useCallback(
7845
+ const handlePointerDown = React98.useCallback(
7646
7846
  (e) => {
7647
7847
  e.preventDefault();
7648
7848
  if (disabled) return;
@@ -7652,7 +7852,7 @@ function ControlButton({
7652
7852
  },
7653
7853
  [disabled, pressEvent, eventBus, onPress]
7654
7854
  );
7655
- const handlePointerUp = React97.useCallback(
7855
+ const handlePointerUp = React98.useCallback(
7656
7856
  (e) => {
7657
7857
  e.preventDefault();
7658
7858
  if (disabled) return;
@@ -7662,7 +7862,7 @@ function ControlButton({
7662
7862
  },
7663
7863
  [disabled, releaseEvent, eventBus, onRelease]
7664
7864
  );
7665
- const handlePointerLeave = React97.useCallback(
7865
+ const handlePointerLeave = React98.useCallback(
7666
7866
  (e) => {
7667
7867
  if (isPressed) {
7668
7868
  setIsPressed(false);
@@ -7703,7 +7903,7 @@ function ControlButton({
7703
7903
  }
7704
7904
  );
7705
7905
  }
7706
- var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
7906
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL;
7707
7907
  var init_ControlButton = __esm({
7708
7908
  "components/game/2d/atoms/ControlButton.tsx"() {
7709
7909
  "use client";
@@ -7730,7 +7930,7 @@ var init_ControlButton = __esm({
7730
7930
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
7731
7931
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
7732
7932
  };
7733
- DEFAULT_ASSET_URL2 = {
7933
+ DEFAULT_ASSET_URL = {
7734
7934
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
7735
7935
  role: "ui",
7736
7936
  category: "control"
@@ -7823,7 +8023,7 @@ function isKnownState(s) {
7823
8023
  return s in DEFAULT_STATE_STYLES;
7824
8024
  }
7825
8025
  function StateIndicator({
7826
- assetUrl = DEFAULT_ASSET_URL3,
8026
+ assetUrl = DEFAULT_ASSET_URL2,
7827
8027
  state = "idle",
7828
8028
  label,
7829
8029
  size = "md",
@@ -7853,14 +8053,14 @@ function StateIndicator({
7853
8053
  }
7854
8054
  );
7855
8055
  }
7856
- var DEFAULT_ASSET_URL3, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
8056
+ var DEFAULT_ASSET_URL2, DEFAULT_STATE_STYLES, DEFAULT_STYLE, STATIC_STATES, SIZE_CLASSES;
7857
8057
  var init_StateIndicator = __esm({
7858
8058
  "components/game/2d/atoms/StateIndicator.tsx"() {
7859
8059
  init_Box();
7860
8060
  init_Icon();
7861
8061
  init_cn();
7862
8062
  init_GameIcon();
7863
- DEFAULT_ASSET_URL3 = {
8063
+ DEFAULT_ASSET_URL2 = {
7864
8064
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7865
8065
  role: "ui",
7866
8066
  category: "state"
@@ -7946,7 +8146,7 @@ var init_TimerDisplay = __esm({
7946
8146
  }
7947
8147
  });
7948
8148
  function ResourceCounter({
7949
- assetUrl = DEFAULT_ASSET_URL4,
8149
+ assetUrl = DEFAULT_ASSET_URL3,
7950
8150
  icon,
7951
8151
  label = "Gold",
7952
8152
  value = 250,
@@ -7979,7 +8179,7 @@ function ResourceCounter({
7979
8179
  }
7980
8180
  );
7981
8181
  }
7982
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
8182
+ var colorTokenClasses2, DEFAULT_ASSET_URL3, sizeMap6;
7983
8183
  var init_ResourceCounter = __esm({
7984
8184
  "components/game/2d/atoms/ResourceCounter.tsx"() {
7985
8185
  init_cn();
@@ -7995,7 +8195,7 @@ var init_ResourceCounter = __esm({
7995
8195
  error: "text-error",
7996
8196
  muted: "text-muted-foreground"
7997
8197
  };
7998
- DEFAULT_ASSET_URL4 = {
8198
+ DEFAULT_ASSET_URL3 = {
7999
8199
  url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
8000
8200
  role: "ui",
8001
8201
  category: "coin"
@@ -8009,7 +8209,7 @@ var init_ResourceCounter = __esm({
8009
8209
  }
8010
8210
  });
8011
8211
  function ItemSlot({
8012
- assetUrl = DEFAULT_ASSET_URL5,
8212
+ assetUrl = DEFAULT_ASSET_URL4,
8013
8213
  icon = "sword",
8014
8214
  label = "Iron Sword",
8015
8215
  quantity,
@@ -8064,7 +8264,7 @@ function ItemSlot({
8064
8264
  }
8065
8265
  );
8066
8266
  }
8067
- var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
8267
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
8068
8268
  var init_ItemSlot = __esm({
8069
8269
  "components/game/2d/atoms/ItemSlot.tsx"() {
8070
8270
  "use client";
@@ -8094,7 +8294,7 @@ var init_ItemSlot = __esm({
8094
8294
  epic: "shadow-lg",
8095
8295
  legendary: "shadow-lg"
8096
8296
  };
8097
- DEFAULT_ASSET_URL5 = {
8297
+ DEFAULT_ASSET_URL4 = {
8098
8298
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
8099
8299
  role: "item",
8100
8300
  category: "item"
@@ -8108,7 +8308,7 @@ var init_ItemSlot = __esm({
8108
8308
  }
8109
8309
  });
8110
8310
  function TurnIndicator({
8111
- assetUrl = DEFAULT_ASSET_URL6,
8311
+ assetUrl = DEFAULT_ASSET_URL5,
8112
8312
  currentTurn = 1,
8113
8313
  maxTurns,
8114
8314
  activeTeam,
@@ -8148,7 +8348,7 @@ function TurnIndicator({
8148
8348
  }
8149
8349
  );
8150
8350
  }
8151
- var sizeMap8, DEFAULT_ASSET_URL6;
8351
+ var sizeMap8, DEFAULT_ASSET_URL5;
8152
8352
  var init_TurnIndicator = __esm({
8153
8353
  "components/game/2d/atoms/TurnIndicator.tsx"() {
8154
8354
  init_cn();
@@ -8160,7 +8360,7 @@ var init_TurnIndicator = __esm({
8160
8360
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
8161
8361
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
8162
8362
  };
8163
- DEFAULT_ASSET_URL6 = {
8363
+ DEFAULT_ASSET_URL5 = {
8164
8364
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
8165
8365
  role: "ui",
8166
8366
  category: "turn"
@@ -8180,7 +8380,7 @@ function getComboScale(combo) {
8180
8380
  return "";
8181
8381
  }
8182
8382
  function ComboCounter({
8183
- assetUrl = DEFAULT_ASSET_URL7,
8383
+ assetUrl = DEFAULT_ASSET_URL6,
8184
8384
  combo = 5,
8185
8385
  multiplier,
8186
8386
  streak,
@@ -8215,14 +8415,14 @@ function ComboCounter({
8215
8415
  }
8216
8416
  );
8217
8417
  }
8218
- var DEFAULT_ASSET_URL7, sizeMap9;
8418
+ var DEFAULT_ASSET_URL6, sizeMap9;
8219
8419
  var init_ComboCounter = __esm({
8220
8420
  "components/game/2d/atoms/ComboCounter.tsx"() {
8221
8421
  init_cn();
8222
8422
  init_Box();
8223
8423
  init_Typography();
8224
8424
  init_GameIcon();
8225
- DEFAULT_ASSET_URL7 = {
8425
+ DEFAULT_ASSET_URL6 = {
8226
8426
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
8227
8427
  role: "effect",
8228
8428
  category: "effect"
@@ -8236,7 +8436,7 @@ var init_ComboCounter = __esm({
8236
8436
  }
8237
8437
  });
8238
8438
  function WaypointMarker({
8239
- assetUrl = DEFAULT_ASSET_URL8,
8439
+ assetUrl = DEFAULT_ASSET_URL7,
8240
8440
  label,
8241
8441
  icon,
8242
8442
  active = true,
@@ -8296,7 +8496,7 @@ function WaypointMarker({
8296
8496
  )
8297
8497
  ] });
8298
8498
  }
8299
- var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
8499
+ var DEFAULT_ASSET_URL7, sizeMap10, checkIcon;
8300
8500
  var init_WaypointMarker = __esm({
8301
8501
  "components/game/2d/atoms/WaypointMarker.tsx"() {
8302
8502
  init_cn();
@@ -8304,7 +8504,7 @@ var init_WaypointMarker = __esm({
8304
8504
  init_Box();
8305
8505
  init_Typography();
8306
8506
  init_GameIcon();
8307
- DEFAULT_ASSET_URL8 = {
8507
+ DEFAULT_ASSET_URL7 = {
8308
8508
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
8309
8509
  role: "ui",
8310
8510
  category: "waypoint"
@@ -8325,7 +8525,7 @@ function formatDuration(seconds) {
8325
8525
  return `${Math.round(seconds)}s`;
8326
8526
  }
8327
8527
  function StatusEffect({
8328
- assetUrl = DEFAULT_ASSET_URL9,
8528
+ assetUrl = DEFAULT_ASSET_URL8,
8329
8529
  icon,
8330
8530
  label = "Shield",
8331
8531
  duration = 30,
@@ -8376,7 +8576,7 @@ function StatusEffect({
8376
8576
  label && /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
8377
8577
  ] });
8378
8578
  }
8379
- var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
8579
+ var DEFAULT_ASSET_URL8, sizeMap11, variantStyles7;
8380
8580
  var init_StatusEffect = __esm({
8381
8581
  "components/game/2d/atoms/StatusEffect.tsx"() {
8382
8582
  init_cn();
@@ -8384,7 +8584,7 @@ var init_StatusEffect = __esm({
8384
8584
  init_Box();
8385
8585
  init_Typography();
8386
8586
  init_GameIcon();
8387
- DEFAULT_ASSET_URL9 = {
8587
+ DEFAULT_ASSET_URL8 = {
8388
8588
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
8389
8589
  role: "ui",
8390
8590
  category: "effect"
@@ -8403,7 +8603,7 @@ var init_StatusEffect = __esm({
8403
8603
  }
8404
8604
  });
8405
8605
  function DamageNumber({
8406
- assetUrl = DEFAULT_ASSET_URL10,
8606
+ assetUrl = DEFAULT_ASSET_URL9,
8407
8607
  value = 42,
8408
8608
  type = "damage",
8409
8609
  size = "md",
@@ -8431,7 +8631,7 @@ function DamageNumber({
8431
8631
  )
8432
8632
  ] });
8433
8633
  }
8434
- var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
8634
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL9;
8435
8635
  var init_DamageNumber = __esm({
8436
8636
  "components/game/2d/atoms/DamageNumber.tsx"() {
8437
8637
  init_cn();
@@ -8455,7 +8655,7 @@ var init_DamageNumber = __esm({
8455
8655
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
8456
8656
  }
8457
8657
  `;
8458
- DEFAULT_ASSET_URL10 = {
8658
+ DEFAULT_ASSET_URL9 = {
8459
8659
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
8460
8660
  role: "effect",
8461
8661
  category: "effect"
@@ -8581,7 +8781,7 @@ var init_ChoiceButton = __esm({
8581
8781
  }
8582
8782
  });
8583
8783
  function ActionButton({
8584
- assetUrl = DEFAULT_ASSET_URL11,
8784
+ assetUrl = DEFAULT_ASSET_URL10,
8585
8785
  label = "Attack",
8586
8786
  icon,
8587
8787
  cooldown = 0,
@@ -8650,7 +8850,7 @@ function ActionButton({
8650
8850
  }
8651
8851
  );
8652
8852
  }
8653
- var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
8853
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL10;
8654
8854
  var init_ActionButton = __esm({
8655
8855
  "components/game/2d/atoms/ActionButton.tsx"() {
8656
8856
  init_cn();
@@ -8670,7 +8870,7 @@ var init_ActionButton = __esm({
8670
8870
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
8671
8871
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
8672
8872
  };
8673
- DEFAULT_ASSET_URL11 = {
8873
+ DEFAULT_ASSET_URL10 = {
8674
8874
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
8675
8875
  role: "ui",
8676
8876
  category: "action"
@@ -8690,8 +8890,8 @@ function MiniMap({
8690
8890
  tileAssets,
8691
8891
  unitAssets
8692
8892
  }) {
8693
- const canvasRef = React97.useRef(null);
8694
- const imgCacheRef = React97.useRef(/* @__PURE__ */ new Map());
8893
+ const canvasRef = React98.useRef(null);
8894
+ const imgCacheRef = React98.useRef(/* @__PURE__ */ new Map());
8695
8895
  function loadImg(url) {
8696
8896
  const cached = imgCacheRef.current.get(url);
8697
8897
  if (cached) return cached.complete ? cached : null;
@@ -8706,7 +8906,7 @@ function MiniMap({
8706
8906
  imgCacheRef.current.set(url, img);
8707
8907
  return null;
8708
8908
  }
8709
- React97.useEffect(() => {
8909
+ React98.useEffect(() => {
8710
8910
  const canvas = canvasRef.current;
8711
8911
  if (!canvas) return;
8712
8912
  const ctx = canvas.getContext("2d");
@@ -8841,8 +9041,8 @@ function ControlGrid({
8841
9041
  className
8842
9042
  }) {
8843
9043
  const eventBus = useEventBus();
8844
- const [active, setActive] = React97.useState(/* @__PURE__ */ new Set());
8845
- const handlePress = React97.useCallback(
9044
+ const [active, setActive] = React98.useState(/* @__PURE__ */ new Set());
9045
+ const handlePress = React98.useCallback(
8846
9046
  (id) => {
8847
9047
  setActive((prev) => new Set(prev).add(id));
8848
9048
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -8856,7 +9056,7 @@ function ControlGrid({
8856
9056
  },
8857
9057
  [kind, actionEvent, directionEvent, directionEvents, eventBus, onAction, onDirection]
8858
9058
  );
8859
- const handleRelease = React97.useCallback(
9059
+ const handleRelease = React98.useCallback(
8860
9060
  (id) => {
8861
9061
  setActive((prev) => {
8862
9062
  const next = new Set(prev);
@@ -9114,7 +9314,7 @@ function InventoryGrid({
9114
9314
  const eventBus = useEventBus();
9115
9315
  const slotCount = totalSlots ?? items.length;
9116
9316
  const emptySlotCount = Math.max(0, slotCount - items.length);
9117
- const handleSelect = React97.useCallback(
9317
+ const handleSelect = React98.useCallback(
9118
9318
  (id) => {
9119
9319
  onSelect?.(id);
9120
9320
  if (selectEvent) {
@@ -9331,7 +9531,7 @@ function GameMenu({
9331
9531
  }) {
9332
9532
  const resolvedOptions = options ?? menuItems ?? DEFAULT_MENU_OPTIONS;
9333
9533
  const eventBus = useEventBus();
9334
- const handleOptionClick = React97.useCallback(
9534
+ const handleOptionClick = React98.useCallback(
9335
9535
  (option) => {
9336
9536
  if (option.event) {
9337
9537
  eventBus.emit(`UI:${option.event}`, { option });
@@ -9557,7 +9757,7 @@ function StateGraph({
9557
9757
  }) {
9558
9758
  const eventBus = useEventBus();
9559
9759
  const nodes = states ?? [];
9560
- const positions = React97.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
9760
+ const positions = React98.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
9561
9761
  return /* @__PURE__ */ jsxs(
9562
9762
  Box,
9563
9763
  {
@@ -10023,11 +10223,11 @@ function SideView({
10023
10223
  const canvasRef = useRef(null);
10024
10224
  const eventBus = useEventBus();
10025
10225
  const keysRef = useRef(/* @__PURE__ */ new Set());
10026
- const imageCache = useRef(/* @__PURE__ */ new Map());
10226
+ const imageCache2 = useRef(/* @__PURE__ */ new Map());
10027
10227
  const [loadedImages, setLoadedImages] = useState(/* @__PURE__ */ new Set());
10028
10228
  const loadImage = useCallback((url) => {
10029
10229
  if (!url) return null;
10030
- const cached = imageCache.current.get(url);
10230
+ const cached = imageCache2.current.get(url);
10031
10231
  if (cached?.complete && cached.naturalWidth > 0) {
10032
10232
  if (!loadedImages.has(url)) setLoadedImages((prev) => new Set(prev).add(url));
10033
10233
  return cached;
@@ -10037,7 +10237,7 @@ function SideView({
10037
10237
  img.crossOrigin = "anonymous";
10038
10238
  img.src = url;
10039
10239
  img.onload = () => setLoadedImages((prev) => new Set(prev).add(url));
10040
- imageCache.current.set(url, img);
10240
+ imageCache2.current.set(url, img);
10041
10241
  }
10042
10242
  return null;
10043
10243
  }, [loadedImages]);
@@ -10154,7 +10354,10 @@ function SideView({
10154
10354
  camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
10155
10355
  }
10156
10356
  const bgImage = bgImg ? loadImage(bgImg.url) : null;
10157
- if (bgImage) {
10357
+ const bgSrc = bgImage ? resolveAssetSource(bgImage, bgImg, NOOP) : null;
10358
+ if (bgSrc) {
10359
+ blit(ctx, bgSrc, 0, 0, cw, ch);
10360
+ } else if (bgImage) {
10158
10361
  ctx.drawImage(bgImage, 0, 0, cw, ch);
10159
10362
  } else if (bg) {
10160
10363
  ctx.fillStyle = bg;
@@ -10187,15 +10390,18 @@ function SideView({
10187
10390
  const platType = plat.type ?? "ground";
10188
10391
  const spriteAsset = tSprites?.[platType];
10189
10392
  const tileImg = spriteAsset ? loadImage(spriteAsset.url) : null;
10190
- if (tileImg) {
10191
- const tileW = tileImg.naturalWidth;
10192
- const tileH = tileImg.naturalHeight;
10393
+ const tileSrc = tileImg ? resolveAssetSource(tileImg, spriteAsset, NOOP) : null;
10394
+ if (tileSrc) {
10395
+ const originX = tileSrc.rect ? tileSrc.rect.sx : 0;
10396
+ const originY = tileSrc.rect ? tileSrc.rect.sy : 0;
10397
+ const tileW = tileSrc.rect ? tileSrc.rect.sw : tileImg.naturalWidth;
10398
+ const tileH = tileSrc.rect ? tileSrc.rect.sh : tileImg.naturalHeight;
10193
10399
  const scaleH = plat.height / tileH;
10194
10400
  const scaledW = tileW * scaleH;
10195
10401
  for (let tx = 0; tx < plat.width; tx += scaledW) {
10196
10402
  const drawW = Math.min(scaledW, plat.width - tx);
10197
10403
  const srcW = drawW / scaleH;
10198
- ctx.drawImage(tileImg, 0, 0, srcW, tileH, platX + tx, platY, drawW, plat.height);
10404
+ ctx.drawImage(tileImg, originX, originY, srcW, tileH, platX + tx, platY, drawW, plat.height);
10199
10405
  }
10200
10406
  } else {
10201
10407
  const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
@@ -10229,14 +10435,15 @@ function SideView({
10229
10435
  const ppy = py - camY;
10230
10436
  const facingRight = auth.facingRight ?? true;
10231
10437
  const playerImg = pSprite ? loadImage(pSprite.url) : null;
10232
- if (playerImg) {
10438
+ const playerSrc = playerImg ? resolveAssetSource(playerImg, pSprite, NOOP) : null;
10439
+ if (playerSrc) {
10233
10440
  ctx.save();
10234
10441
  if (!facingRight) {
10235
10442
  ctx.translate(ppx + pw, ppy);
10236
10443
  ctx.scale(-1, 1);
10237
- ctx.drawImage(playerImg, 0, 0, pw, ph);
10444
+ blit(ctx, playerSrc, 0, 0, pw, ph);
10238
10445
  } else {
10239
- ctx.drawImage(playerImg, ppx, ppy, pw, ph);
10446
+ blit(ctx, playerSrc, ppx, ppy, pw, ph);
10240
10447
  }
10241
10448
  ctx.restore();
10242
10449
  } else {
@@ -10348,6 +10555,7 @@ function Canvas2D({
10348
10555
  const isSide = projection === "side";
10349
10556
  const isFree = projection === "free";
10350
10557
  const flatLike = projection === "hex" || projection === "flat" || isFree;
10558
+ const squareGrid = projection === "flat";
10351
10559
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
10352
10560
  const unitsProp = Array.isArray(_unitsPropRaw) ? _unitsPropRaw : [];
10353
10561
  const featuresProp = Array.isArray(_featuresPropRaw) ? _featuresPropRaw : [];
@@ -10430,17 +10638,18 @@ function Canvas2D({
10430
10638
  const effectiveDiamondTopY = diamondTopYProp ?? DIAMOND_TOP_Y;
10431
10639
  const scaledDiamondTopY = effectiveDiamondTopY * scale;
10432
10640
  const baseOffsetX = useMemo(() => {
10433
- if (isFree) return 0;
10641
+ if (isFree || projection === "flat") return 0;
10434
10642
  return (gridHeight - 1) * (scaledTileWidth / 2);
10435
- }, [isFree, gridHeight, scaledTileWidth]);
10643
+ }, [isFree, projection, gridHeight, scaledTileWidth]);
10436
10644
  const validMoveSet = useMemo(() => new Set(validMoves.map((p) => `${p.x},${p.y}`)), [validMoves]);
10437
10645
  const attackTargetSet = useMemo(() => new Set(attackTargets.map((p) => `${p.x},${p.y}`)), [attackTargets]);
10438
10646
  const spriteUrls = useMemo(() => {
10439
10647
  const urls = [];
10648
+ const toUrl = (x) => typeof x === "string" ? x : x?.url;
10440
10649
  for (const tile of sortedTiles) {
10441
10650
  if (tile.terrainSprite) urls.push(tile.terrainSprite.url);
10442
10651
  else if (getTerrainSprite) {
10443
- const url = getTerrainSprite(tile.terrain ?? "");
10652
+ const url = toUrl(getTerrainSprite(tile.terrain ?? ""));
10444
10653
  if (url) urls.push(url);
10445
10654
  } else {
10446
10655
  const url = assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
@@ -10450,7 +10659,7 @@ function Canvas2D({
10450
10659
  for (const feature of features) {
10451
10660
  if (feature.sprite) urls.push(feature.sprite.url);
10452
10661
  else if (getFeatureSprite) {
10453
- const url = getFeatureSprite(feature.type);
10662
+ const url = toUrl(getFeatureSprite(feature.type));
10454
10663
  if (url) urls.push(url);
10455
10664
  } else {
10456
10665
  const url = assetManifest?.features?.[feature.type]?.url;
@@ -10460,7 +10669,7 @@ function Canvas2D({
10460
10669
  for (const unit of units) {
10461
10670
  if (unit.sprite) urls.push(unit.sprite.url);
10462
10671
  else if (getUnitSprite) {
10463
- const url = getUnitSprite(unit);
10672
+ const url = toUrl(getUnitSprite(unit));
10464
10673
  if (url) urls.push(url);
10465
10674
  } else if (unit.unitType) {
10466
10675
  const url = assetManifest?.units?.[unit.unitType]?.url;
@@ -10501,14 +10710,25 @@ function Canvas2D({
10501
10710
  screenToWorld,
10502
10711
  lerpToTarget
10503
10712
  } = useCamera();
10504
- const resolveTerrainSpriteUrl = useCallback((tile) => {
10505
- return tile.terrainSprite?.url || getTerrainSprite?.(tile.terrain ?? "") || assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
10713
+ const [, setAtlasVersion] = useState(0);
10714
+ const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
10715
+ const resolveTerrainAsset = useCallback((tile) => {
10716
+ if (tile.terrainSprite) return tile.terrainSprite;
10717
+ const s = getTerrainSprite?.(tile.terrain ?? "");
10718
+ if (s) return typeof s === "string" ? { url: s } : s;
10719
+ return assetManifest?.terrains?.[tile.terrain ?? ""];
10506
10720
  }, [getTerrainSprite, assetManifest]);
10507
- const resolveFeatureSpriteUrl = useCallback((featureType) => {
10508
- return getFeatureSprite?.(featureType) || assetManifest?.features?.[featureType]?.url;
10721
+ const resolveFeatureAsset = useCallback((feature) => {
10722
+ if (feature.sprite) return feature.sprite;
10723
+ const s = getFeatureSprite?.(feature.type);
10724
+ if (s) return typeof s === "string" ? { url: s } : s;
10725
+ return assetManifest?.features?.[feature.type];
10509
10726
  }, [getFeatureSprite, assetManifest]);
10510
- const resolveUnitSpriteUrl = useCallback((unit) => {
10511
- return unit.sprite?.url || getUnitSprite?.(unit) || (unit.unitType ? assetManifest?.units?.[unit.unitType]?.url : void 0);
10727
+ const resolveUnitAsset = useCallback((unit) => {
10728
+ if (unit.sprite) return unit.sprite;
10729
+ const s = getUnitSprite?.(unit);
10730
+ if (s) return typeof s === "string" ? { url: s } : s;
10731
+ return unit.unitType ? assetManifest?.units?.[unit.unitType] : void 0;
10512
10732
  }, [getUnitSprite, assetManifest]);
10513
10733
  const miniMapTiles = useMemo(() => {
10514
10734
  if (!showMinimap) return [];
@@ -10541,7 +10761,13 @@ function Canvas2D({
10541
10761
  ctx.clearRect(0, 0, viewportSize.width, viewportSize.height);
10542
10762
  if (backgroundImage) {
10543
10763
  const bgImg = getImage(backgroundImage.url);
10544
- if (bgImg) {
10764
+ const bgSrc = bgImg ? resolveAssetSource(bgImg, backgroundImage, bumpAtlas) : null;
10765
+ if (bgSrc?.rect) {
10766
+ const k = Math.max(viewportSize.width / bgSrc.rect.sw, viewportSize.height / bgSrc.rect.sh);
10767
+ const dw = bgSrc.rect.sw * k;
10768
+ const dh = bgSrc.rect.sh * k;
10769
+ blit(ctx, bgSrc, (viewportSize.width - dw) / 2, (viewportSize.height - dh) / 2, dw, dh);
10770
+ } else if (bgImg) {
10545
10771
  const cam2 = cameraRef.current;
10546
10772
  const patW = bgImg.naturalWidth;
10547
10773
  const patH = bgImg.naturalHeight;
@@ -10572,18 +10798,23 @@ function Canvas2D({
10572
10798
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
10573
10799
  continue;
10574
10800
  }
10575
- const spriteUrl = resolveTerrainSpriteUrl(tile);
10576
- const img = spriteUrl ? getImage(spriteUrl) : null;
10577
- if (img) {
10578
- if (img.naturalWidth === 0) {
10579
- ctx.drawImage(img, pos.x, pos.y, scaledTileWidth, scaledTileHeight);
10580
- } else {
10581
- const drawW = scaledTileWidth;
10582
- const drawH = scaledTileWidth * (img.naturalHeight / img.naturalWidth);
10583
- const drawX = pos.x;
10584
- const drawY = flatLike ? pos.y : pos.y + scaledTileHeight - drawH;
10585
- ctx.drawImage(img, drawX, drawY, drawW, drawH);
10586
- }
10801
+ const terrainAsset = resolveTerrainAsset(tile);
10802
+ const img = terrainAsset?.url ? getImage(terrainAsset.url) : null;
10803
+ const src = img ? resolveAssetSource(img, terrainAsset, bumpAtlas) : null;
10804
+ if (src) {
10805
+ const drawW = scaledTileWidth;
10806
+ const drawH = squareGrid ? scaledTileWidth : scaledTileWidth / src.aspect;
10807
+ const drawX = pos.x;
10808
+ const drawY = flatLike ? pos.y : pos.y + scaledTileHeight - drawH;
10809
+ blit(ctx, src, drawX, drawY, drawW, drawH);
10810
+ } else if (img && img.naturalWidth === 0) {
10811
+ ctx.drawImage(img, pos.x, pos.y, scaledTileWidth, scaledTileHeight);
10812
+ } else if (squareGrid) {
10813
+ ctx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : tile.terrain === "stone" ? "#9ca3af" : "#4ade80";
10814
+ ctx.fillRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
10815
+ ctx.strokeStyle = "rgba(0,0,0,0.2)";
10816
+ ctx.lineWidth = 1;
10817
+ ctx.strokeRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
10587
10818
  } else {
10588
10819
  const centerX = pos.x + scaledTileWidth / 2;
10589
10820
  const topY = pos.y + scaledDiamondTopY;
@@ -10600,9 +10831,13 @@ function Canvas2D({
10600
10831
  ctx.stroke();
10601
10832
  }
10602
10833
  const drawHighlight = (color) => {
10834
+ ctx.fillStyle = color;
10835
+ if (squareGrid) {
10836
+ ctx.fillRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
10837
+ return;
10838
+ }
10603
10839
  const centerX = pos.x + scaledTileWidth / 2;
10604
10840
  const topY = pos.y + scaledDiamondTopY;
10605
- ctx.fillStyle = color;
10606
10841
  ctx.beginPath();
10607
10842
  ctx.moveTo(centerX, topY);
10608
10843
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -10619,7 +10854,7 @@ function Canvas2D({
10619
10854
  if (attackTargetSet.has(tileKey)) drawHighlight("rgba(239, 68, 68, 0.35)");
10620
10855
  if (debug2) {
10621
10856
  const centerX = pos.x + scaledTileWidth / 2;
10622
- const centerY = pos.y + scaledFloorHeight / 2 + scaledDiamondTopY;
10857
+ const centerY = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledFloorHeight / 2 + scaledDiamondTopY;
10623
10858
  ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
10624
10859
  ctx.font = `${12 * scale * 2}px monospace`;
10625
10860
  ctx.textAlign = "center";
@@ -10637,15 +10872,16 @@ function Canvas2D({
10637
10872
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
10638
10873
  continue;
10639
10874
  }
10640
- const spriteUrl = feature.sprite?.url || resolveFeatureSpriteUrl(feature.type);
10641
- const img = spriteUrl ? getImage(spriteUrl) : null;
10875
+ const featureAsset = resolveFeatureAsset(feature);
10876
+ const img = featureAsset?.url ? getImage(featureAsset.url) : null;
10877
+ const src = img ? resolveAssetSource(img, featureAsset, bumpAtlas) : null;
10642
10878
  const centerX = pos.x + scaledTileWidth / 2;
10643
- const featureGroundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10879
+ const featureGroundY = squareGrid ? pos.y + scaledTileWidth * 0.92 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10644
10880
  const isCastle = feature.type === "castle";
10645
- const featureDrawH = isCastle ? scaledFloorHeight * 3.5 : scaledFloorHeight * 1.6;
10881
+ const featureDrawH = squareGrid ? isCastle ? scaledTileWidth * 1.4 : scaledTileWidth * 0.8 : isCastle ? scaledFloorHeight * 3.5 : scaledFloorHeight * 1.6;
10646
10882
  const maxFeatureW = isCastle ? scaledTileWidth * 1.8 : scaledTileWidth * 0.7;
10647
- if (img) {
10648
- const ar = img.naturalWidth / img.naturalHeight;
10883
+ if (src) {
10884
+ const ar = src.aspect;
10649
10885
  let drawH = featureDrawH;
10650
10886
  let drawW = featureDrawH * ar;
10651
10887
  if (drawW > maxFeatureW) {
@@ -10654,7 +10890,7 @@ function Canvas2D({
10654
10890
  }
10655
10891
  const drawX = centerX - drawW / 2;
10656
10892
  const drawY = featureGroundY - drawH;
10657
- ctx.drawImage(img, drawX, drawY, drawW, drawH);
10893
+ blit(ctx, src, drawX, drawY, drawW, drawH);
10658
10894
  } else {
10659
10895
  const color = FEATURE_COLORS[feature.type] || FEATURE_COLORS.default;
10660
10896
  ctx.beginPath();
@@ -10681,19 +10917,20 @@ function Canvas2D({
10681
10917
  }
10682
10918
  const isSelected = unit.id === selectedUnitId;
10683
10919
  const centerX = pos.x + scaledTileWidth / 2;
10684
- const groundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10920
+ const groundY = squareGrid ? pos.y + scaledTileWidth * 0.92 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10685
10921
  const breatheOffset = 0;
10686
- const unitSpriteUrl = resolveUnitSpriteUrl(unit);
10687
- const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
10688
- const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
10922
+ const unitAsset = resolveUnitAsset(unit);
10923
+ const img = unitAsset?.url ? getImage(unitAsset.url) : null;
10924
+ const unitDrawH = squareGrid ? scaledTileWidth * 0.55 * spriteHeightRatio * unitScale : scaledFloorHeight * spriteHeightRatio * unitScale;
10689
10925
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
10690
10926
  const unitIsSheet = unit.spriteSheet?.url !== void 0;
10927
+ const unitSrc = img && !unitIsSheet ? resolveAssetSource(img, unitAsset, bumpAtlas) : null;
10691
10928
  const SHEET_ROWS = 5;
10692
10929
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
10693
10930
  const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
10694
10931
  const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
10695
10932
  const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
10696
- const ar = frameW / (frameH || 1);
10933
+ const ar = unitIsSheet ? sheetFrameW / (sheetFrameH || 1) : unitSrc ? unitSrc.aspect : frameW / (frameH || 1);
10697
10934
  let drawH = unitDrawH;
10698
10935
  let drawW = unitDrawH * ar;
10699
10936
  if (drawW > maxUnitW) {
@@ -10703,12 +10940,14 @@ function Canvas2D({
10703
10940
  if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
10704
10941
  const ghostPos = project(unit.previousPosition.x, unit.previousPosition.y, baseOffsetX);
10705
10942
  const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
10706
- const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10943
+ const ghostGroundY = squareGrid ? ghostPos.y + scaledTileWidth * 0.92 : ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10707
10944
  ctx.save();
10708
10945
  ctx.globalAlpha = 0.25;
10709
10946
  if (img) {
10710
10947
  if (unitIsSheet) {
10711
10948
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
10949
+ } else if (unitSrc) {
10950
+ blit(ctx, unitSrc, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
10712
10951
  } else {
10713
10952
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
10714
10953
  }
@@ -10757,6 +10996,8 @@ function Canvas2D({
10757
10996
  const drawUnit = (x) => {
10758
10997
  if (unitIsSheet) {
10759
10998
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
10999
+ } else if (unitSrc) {
11000
+ blit(ctx, unitSrc, x, spriteY, drawW, drawH);
10760
11001
  } else {
10761
11002
  ctx.drawImage(img, x, spriteY, drawW, drawH);
10762
11003
  }
@@ -10782,17 +11023,24 @@ function Canvas2D({
10782
11023
  }
10783
11024
  }
10784
11025
  for (const fx of effects) {
10785
- const spriteUrl = assetManifest?.effects?.[fx.key]?.url;
10786
- if (!spriteUrl) continue;
10787
- const img = getImage(spriteUrl);
11026
+ const fxAsset = assetManifest?.effects?.[fx.key];
11027
+ if (!fxAsset?.url) continue;
11028
+ const img = getImage(fxAsset.url);
10788
11029
  if (!img) continue;
11030
+ const src = resolveAssetSource(img, fxAsset, bumpAtlas);
10789
11031
  const pos = project(fx.x, fx.y, baseOffsetX);
10790
11032
  const cx = pos.x + scaledTileWidth / 2;
10791
- const cy = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11033
+ const cy = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10792
11034
  const alpha = Math.min(1, fx.ttl / 4);
10793
11035
  const prev = ctx.globalAlpha;
10794
11036
  ctx.globalAlpha = alpha;
10795
- ctx.drawImage(img, cx - img.naturalWidth / 2, cy - img.naturalHeight / 2);
11037
+ if (src?.rect) {
11038
+ const dw = scaledTileWidth;
11039
+ const dh = dw / src.aspect;
11040
+ blit(ctx, src, cx - dw / 2, cy - dh / 2, dw, dh);
11041
+ } else {
11042
+ ctx.drawImage(img, cx - img.naturalWidth / 2, cy - img.naturalHeight / 2);
11043
+ }
10796
11044
  ctx.globalAlpha = prev;
10797
11045
  }
10798
11046
  onDrawEffects?.(ctx, 0, getImage);
@@ -10805,13 +11053,15 @@ function Canvas2D({
10805
11053
  effects,
10806
11054
  project,
10807
11055
  flatLike,
11056
+ squareGrid,
10808
11057
  scale,
10809
11058
  debug2,
10810
- resolveTerrainSpriteUrl,
10811
- resolveFeatureSpriteUrl,
10812
- resolveUnitSpriteUrl,
11059
+ resolveTerrainAsset,
11060
+ resolveFeatureAsset,
11061
+ resolveUnitAsset,
10813
11062
  resolveFrameForUnit,
10814
11063
  getImage,
11064
+ bumpAtlas,
10815
11065
  baseOffsetX,
10816
11066
  scaledTileWidth,
10817
11067
  scaledTileHeight,
@@ -10837,12 +11087,12 @@ function Canvas2D({
10837
11087
  if (!unit?.position) return;
10838
11088
  const pos = project(unit.position.x, unit.position.y, baseOffsetX);
10839
11089
  const centerX = pos.x + scaledTileWidth / 2;
10840
- const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
11090
+ const centerY = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
10841
11091
  targetCameraRef.current = {
10842
11092
  x: centerX - viewportSize.width / 2,
10843
11093
  y: centerY - viewportSize.height / 2
10844
11094
  };
10845
- }, [camera, selectedUnitId, units, project, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
11095
+ }, [camera, selectedUnitId, units, project, baseOffsetX, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
10846
11096
  useEffect(() => {
10847
11097
  if (isSide || !interpolateUnits) return;
10848
11098
  unitInterp.onSnapshot(
@@ -10913,11 +11163,11 @@ function Canvas2D({
10913
11163
  if (!tileHoverEvent || !canvasRef.current) return;
10914
11164
  const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
10915
11165
  const adjustedX = world.x - scaledTileWidth / 2;
10916
- const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
11166
+ const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
10917
11167
  const isoPos = unproject(adjustedX, adjustedY, baseOffsetX);
10918
11168
  const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
10919
11169
  if (tileExists) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
10920
- }, [screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
11170
+ }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
10921
11171
  const handleCanvasPointerUp = useCallback((e) => {
10922
11172
  singlePointerActiveRef.current = false;
10923
11173
  if (enableCamera) handlePointerUp();
@@ -10925,7 +11175,7 @@ function Canvas2D({
10925
11175
  if (!canvasRef.current) return;
10926
11176
  const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
10927
11177
  const adjustedX = world.x - scaledTileWidth / 2;
10928
- const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
11178
+ const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
10929
11179
  const isoPos = unproject(adjustedX, adjustedY, baseOffsetX);
10930
11180
  const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
10931
11181
  if (clickedUnit && unitClickEvent) {
@@ -10934,7 +11184,7 @@ function Canvas2D({
10934
11184
  const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
10935
11185
  if (tileExists) eventBus.emit(`UI:${tileClickEvent}`, { x: isoPos.x, y: isoPos.y });
10936
11186
  }
10937
- }, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, units, tilesProp, unitClickEvent, tileClickEvent, eventBus]);
11187
+ }, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, baseOffsetX, units, tilesProp, unitClickEvent, tileClickEvent, eventBus]);
10938
11188
  const handleCanvasPointerLeave = useCallback(() => {
10939
11189
  handleMouseLeave();
10940
11190
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
@@ -10984,11 +11234,12 @@ function Canvas2D({
10984
11234
  return units.filter((u) => !!u.position).map((u) => {
10985
11235
  const pos = project(u.position.x, u.position.y, baseOffsetX);
10986
11236
  const cam = cameraRef.current;
11237
+ const anchorY = squareGrid ? pos.y + scaledTileWidth * 0.92 : pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10987
11238
  const screenX = (pos.x + scaledTileWidth / 2 - (cam.x + viewportSize.width / 2)) * cam.zoom + viewportSize.width / 2;
10988
- const screenY = (pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5 - (cam.y + viewportSize.height / 2)) * cam.zoom + viewportSize.height / 2;
11239
+ const screenY = (anchorY - (cam.y + viewportSize.height / 2)) * cam.zoom + viewportSize.height / 2;
10989
11240
  return { unit: u, screenX, screenY };
10990
11241
  });
10991
- }, [units, project, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, cameraRef]);
11242
+ }, [units, project, baseOffsetX, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, viewportSize, cameraRef]);
10992
11243
  if (error) {
10993
11244
  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: [
10994
11245
  /* @__PURE__ */ jsx(Icon, { name: "alert-circle", size: "xl" }),
@@ -11125,7 +11376,7 @@ function Canvas2D({
11125
11376
  }
11126
11377
  );
11127
11378
  }
11128
- var PLATFORM_COLORS, PLAYER_COLOR, PLAYER_EYE_COLOR, SKY_GRADIENT_TOP, SKY_GRADIENT_BOTTOM, GRID_COLOR, DEFAULT_PLATFORMS;
11379
+ var PLATFORM_COLORS, NOOP, PLAYER_COLOR, PLAYER_EYE_COLOR, SKY_GRADIENT_TOP, SKY_GRADIENT_BOTTOM, GRID_COLOR, DEFAULT_PLATFORMS;
11129
11380
  var init_Canvas2D = __esm({
11130
11381
  "components/game/2d/molecules/Canvas2D.tsx"() {
11131
11382
  "use client";
@@ -11139,6 +11390,7 @@ var init_Canvas2D = __esm({
11139
11390
  init_MiniMap();
11140
11391
  init_HealthBar();
11141
11392
  init_useImageCache();
11393
+ init_atlasSlice();
11142
11394
  init_useCamera();
11143
11395
  init_useCanvasGestures();
11144
11396
  init_useRenderInterpolation();
@@ -11152,6 +11404,8 @@ var init_Canvas2D = __esm({
11152
11404
  hazard: "#c0392b",
11153
11405
  goal: "#f1c40f"
11154
11406
  };
11407
+ NOOP = () => {
11408
+ };
11155
11409
  PLAYER_COLOR = "#3498db";
11156
11410
  PLAYER_EYE_COLOR = "#ffffff";
11157
11411
  SKY_GRADIENT_TOP = "#1a1a2e";
@@ -11231,7 +11485,7 @@ function LinearView({
11231
11485
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
11232
11486
  const isDone = i < currentIdx;
11233
11487
  const isCurrent = i === currentIdx;
11234
- return /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
11488
+ return /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
11235
11489
  i > 0 && /* @__PURE__ */ jsx(
11236
11490
  Typography,
11237
11491
  {
@@ -11766,7 +12020,7 @@ function SequenceBar({
11766
12020
  else onSlotRemove?.(index);
11767
12021
  }, [emit, slotRemoveEvent, onSlotRemove, playing]);
11768
12022
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
11769
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
12023
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
11770
12024
  i > 0 && /* @__PURE__ */ jsx(
11771
12025
  Typography,
11772
12026
  {
@@ -13923,82 +14177,167 @@ var init_GameTemplate = __esm({
13923
14177
  GameTemplate.displayName = "GameTemplate";
13924
14178
  }
13925
14179
  });
13926
- var GameShell;
14180
+ var FONT_BASE, GAME_FONTS, FONT_FACES, GameShell;
13927
14181
  var init_GameShell = __esm({
13928
14182
  "components/game/2d/templates/GameShell.tsx"() {
13929
14183
  init_cn();
13930
14184
  init_Box();
13931
- init_Stack();
13932
14185
  init_Typography();
14186
+ init_AtlasImage();
14187
+ FONT_BASE = "https://almadar-kflow-assets.web.app/shared/_shared/kenney-fonts/fonts";
14188
+ GAME_FONTS = {
14189
+ future: "Kenney Future",
14190
+ "future-narrow": "Kenney Future Narrow",
14191
+ pixel: "Kenney Pixel",
14192
+ blocks: "Kenney Blocks",
14193
+ mini: "Kenney Mini"
14194
+ };
14195
+ FONT_FACES = `
14196
+ @font-face { font-family: 'Kenney Future'; src: url('${FONT_BASE}/Kenney%20Future.ttf') format('truetype'); font-display: swap; }
14197
+ @font-face { font-family: 'Kenney Future Narrow'; src: url('${FONT_BASE}/Kenney%20Future%20Narrow.ttf') format('truetype'); font-display: swap; }
14198
+ @font-face { font-family: 'Kenney Pixel'; src: url('${FONT_BASE}/Kenney%20Pixel.ttf') format('truetype'); font-display: swap; }
14199
+ @font-face { font-family: 'Kenney Blocks'; src: url('${FONT_BASE}/Kenney%20Blocks.ttf') format('truetype'); font-display: swap; }
14200
+ @font-face { font-family: 'Kenney Mini'; src: url('${FONT_BASE}/Kenney%20Mini.ttf') format('truetype'); font-display: swap; }
14201
+ .game-shell, .game-shell * { font-family: inherit; }
14202
+ `;
13933
14203
  GameShell = ({
13934
14204
  appName = "Game",
13935
14205
  hud,
14206
+ addons,
14207
+ controls,
14208
+ overlay,
13936
14209
  className,
13937
14210
  showTopBar = true,
13938
14211
  children,
13939
14212
  backgroundAsset,
13940
- hudBackgroundAsset
14213
+ hudBackgroundAsset,
14214
+ fontFamily = "future"
13941
14215
  }) => {
14216
+ const font = GAME_FONTS[fontFamily] ?? fontFamily;
13942
14217
  return /* @__PURE__ */ jsxs(
13943
14218
  Box,
13944
14219
  {
13945
- display: "flex",
13946
- className: cn(
13947
- "game-shell",
13948
- "flex-col w-full h-screen overflow-hidden",
13949
- className
13950
- ),
14220
+ className: cn("game-shell", className),
13951
14221
  style: {
14222
+ position: "relative",
13952
14223
  width: "100vw",
13953
14224
  height: "100vh",
13954
14225
  overflow: "hidden",
13955
- background: backgroundAsset ? `url(${backgroundAsset.url}) center/cover no-repeat` : "var(--color-background, #0a0a0f)",
13956
- color: "var(--color-text, #e0e0e0)"
14226
+ background: "var(--color-background, #0a0a0f)",
14227
+ color: "var(--color-text, #e0e0e0)",
14228
+ fontFamily: `'${font}', system-ui, sans-serif`
13957
14229
  },
13958
14230
  children: [
13959
- showTopBar && /* @__PURE__ */ jsxs(
14231
+ /* @__PURE__ */ jsx("style", { children: FONT_FACES }),
14232
+ backgroundAsset && /* @__PURE__ */ jsx(
14233
+ AtlasPanel,
14234
+ {
14235
+ asset: backgroundAsset,
14236
+ mode: "repeat",
14237
+ "aria-hidden": true,
14238
+ className: "game-shell__bg",
14239
+ style: { position: "absolute", inset: 0, opacity: 0.18, zIndex: 0, display: "block" }
14240
+ }
14241
+ ),
14242
+ /* @__PURE__ */ jsx(Box, { className: "game-shell__content", style: { position: "absolute", inset: 0, zIndex: 1 }, children }),
14243
+ (showTopBar || hud) && /* @__PURE__ */ jsxs(
13960
14244
  Box,
13961
14245
  {
13962
- className: "game-shell__header",
14246
+ className: "game-shell__top pointer-events-none",
13963
14247
  style: {
13964
- flexShrink: 0,
13965
- background: hudBackgroundAsset ? `url(${hudBackgroundAsset.url}) center/cover no-repeat` : "var(--color-surface, #12121f)",
13966
- borderBottom: "1px solid var(--color-border, #2a2a3a)"
14248
+ position: "absolute",
14249
+ top: 12,
14250
+ left: 12,
14251
+ right: 12,
14252
+ zIndex: 2,
14253
+ display: "flex",
14254
+ alignItems: "flex-start",
14255
+ gap: 12
13967
14256
  },
13968
14257
  children: [
13969
- /* @__PURE__ */ jsx(
13970
- HStack,
14258
+ showTopBar && /* @__PURE__ */ jsx(
14259
+ AtlasPanel,
13971
14260
  {
13972
- align: "center",
13973
- justify: "between",
13974
- style: { padding: "0.375rem 1rem" },
14261
+ asset: hudBackgroundAsset,
14262
+ borderSlice: 12,
14263
+ borderWidth: 10,
14264
+ className: "game-shell__title pointer-events-auto",
14265
+ style: {
14266
+ padding: "6px 16px",
14267
+ background: hudBackgroundAsset ? void 0 : "rgba(18, 18, 31, 0.85)",
14268
+ borderRadius: hudBackgroundAsset ? void 0 : 10,
14269
+ boxShadow: "0 4px 14px rgba(0,0,0,0.45)",
14270
+ flexShrink: 0
14271
+ },
13975
14272
  children: /* @__PURE__ */ jsx(
13976
14273
  Typography,
13977
14274
  {
13978
- variant: "h6",
14275
+ as: "span",
13979
14276
  style: {
13980
14277
  fontWeight: 700,
13981
- letterSpacing: "0.02em"
14278
+ fontSize: "1.05rem",
14279
+ letterSpacing: "0.06em",
14280
+ textShadow: "0 2px 0 rgba(0,0,0,0.5)",
14281
+ whiteSpace: "nowrap"
13982
14282
  },
13983
14283
  children: appName
13984
14284
  }
13985
14285
  )
13986
14286
  }
13987
14287
  ),
13988
- hud && /* @__PURE__ */ jsx(Box, { className: "game-shell__hud", style: { width: "100%" }, children: hud })
14288
+ hud && /* @__PURE__ */ jsx(Box, { className: "game-shell__hud pointer-events-auto", style: { flex: 1, minWidth: 0 }, children: hud })
13989
14289
  ]
13990
14290
  }
13991
14291
  ),
13992
- /* @__PURE__ */ jsx(
14292
+ controls && /* @__PURE__ */ jsx(
13993
14293
  Box,
13994
14294
  {
13995
- className: "game-shell__content",
14295
+ className: "game-shell__controls pointer-events-auto",
13996
14296
  style: {
13997
- flex: 1,
13998
- overflow: "hidden",
13999
- position: "relative"
14297
+ position: "absolute",
14298
+ left: 16,
14299
+ bottom: 16,
14300
+ zIndex: 2,
14301
+ display: "flex",
14302
+ flexDirection: "column",
14303
+ alignItems: "flex-start",
14304
+ gap: 10,
14305
+ filter: "drop-shadow(0 6px 12px rgba(0,0,0,0.5))"
14000
14306
  },
14001
- children
14307
+ children: controls
14308
+ }
14309
+ ),
14310
+ addons && /* @__PURE__ */ jsx(
14311
+ Box,
14312
+ {
14313
+ className: "game-shell__actions pointer-events-auto",
14314
+ style: {
14315
+ position: "absolute",
14316
+ right: 16,
14317
+ bottom: 16,
14318
+ zIndex: 2,
14319
+ display: "flex",
14320
+ flexDirection: "column",
14321
+ alignItems: "flex-end",
14322
+ gap: 10,
14323
+ filter: "drop-shadow(0 6px 12px rgba(0,0,0,0.5))"
14324
+ },
14325
+ children: addons
14326
+ }
14327
+ ),
14328
+ overlay && /* @__PURE__ */ jsx(
14329
+ Box,
14330
+ {
14331
+ className: "game-shell__overlay pointer-events-none",
14332
+ style: {
14333
+ position: "absolute",
14334
+ inset: 0,
14335
+ zIndex: 3,
14336
+ display: "flex",
14337
+ alignItems: "center",
14338
+ justifyContent: "center"
14339
+ },
14340
+ children: /* @__PURE__ */ jsx(Box, { className: "pointer-events-auto", children: overlay })
14002
14341
  }
14003
14342
  )
14004
14343
  ]
@@ -14412,7 +14751,7 @@ var init_ErrorBoundary = __esm({
14412
14751
  }
14413
14752
  );
14414
14753
  };
14415
- ErrorBoundary = class extends React97__default.Component {
14754
+ ErrorBoundary = class extends React98__default.Component {
14416
14755
  constructor(props) {
14417
14756
  super(props);
14418
14757
  __publicField(this, "reset", () => {
@@ -15077,7 +15416,7 @@ var init_Container = __esm({
15077
15416
  as: Component = "div"
15078
15417
  }) => {
15079
15418
  const resolvedSize = maxWidth ?? size ?? "lg";
15080
- return React97__default.createElement(
15419
+ return React98__default.createElement(
15081
15420
  Component,
15082
15421
  {
15083
15422
  className: cn(
@@ -16193,6 +16532,153 @@ var init_ComponentPatterns = __esm({
16193
16532
  AlertPattern.displayName = "AlertPattern";
16194
16533
  }
16195
16534
  });
16535
+ var DEFAULT_BAR_COLOR, DEFAULT_CELL_COLOR, DEFAULT_POINTER_COLOR, POINTER_BAND, TOP_PAD, AlgorithmCanvas;
16536
+ var init_AlgorithmCanvas = __esm({
16537
+ "components/learning/molecules/AlgorithmCanvas.tsx"() {
16538
+ "use client";
16539
+ init_atoms();
16540
+ init_Stack();
16541
+ init_LearningCanvas();
16542
+ DEFAULT_BAR_COLOR = "#3b82f6";
16543
+ DEFAULT_CELL_COLOR = "#e5e7eb";
16544
+ DEFAULT_POINTER_COLOR = "#dc2626";
16545
+ POINTER_BAND = 34;
16546
+ TOP_PAD = 12;
16547
+ AlgorithmCanvas = ({
16548
+ className,
16549
+ width = 600,
16550
+ height = 400,
16551
+ title,
16552
+ backgroundColor,
16553
+ bars = [],
16554
+ cells = [],
16555
+ pointers = [],
16556
+ shapes = [],
16557
+ interactive = false,
16558
+ animate = false,
16559
+ onShapeClick,
16560
+ isLoading,
16561
+ error
16562
+ }) => {
16563
+ const derivedShapes = useMemo(() => {
16564
+ const out = [];
16565
+ if (bars.length > 0) {
16566
+ const slot = width / bars.length;
16567
+ const barW = slot * 0.8;
16568
+ const gap = slot * 0.1;
16569
+ const baseline = height - POINTER_BAND;
16570
+ const usableH = baseline - TOP_PAD;
16571
+ const maxV = Math.max(1, ...bars.map((b) => Number.isFinite(b.value) ? b.value : 0));
16572
+ bars.forEach((bar, i) => {
16573
+ const v = Number.isFinite(bar.value) ? bar.value : 0;
16574
+ const bh = Math.max(0, v / maxV * usableH);
16575
+ const x = i * slot + gap;
16576
+ const color = bar.color ?? DEFAULT_BAR_COLOR;
16577
+ out.push({
16578
+ type: "rect",
16579
+ id: `bar-${i}`,
16580
+ x,
16581
+ y: baseline - bh,
16582
+ width: barW,
16583
+ height: bh,
16584
+ color,
16585
+ fill: color
16586
+ });
16587
+ const label = bar.label ?? (bars.length <= 24 ? String(v) : void 0);
16588
+ if (label) {
16589
+ out.push({
16590
+ type: "text",
16591
+ x: x + barW / 2,
16592
+ y: baseline - bh - 8,
16593
+ text: label,
16594
+ color: "#374151",
16595
+ fontSize: 11,
16596
+ align: "center"
16597
+ });
16598
+ }
16599
+ });
16600
+ pointers.forEach((p) => {
16601
+ if (p.index < 0 || p.index >= bars.length) return;
16602
+ const cx = p.index * slot + slot / 2;
16603
+ const color = p.color ?? DEFAULT_POINTER_COLOR;
16604
+ out.push({
16605
+ type: "arrow",
16606
+ x1: cx,
16607
+ y1: height - 6,
16608
+ x2: cx,
16609
+ y2: baseline + 4,
16610
+ color,
16611
+ lineWidth: 2
16612
+ });
16613
+ if (p.label) {
16614
+ out.push({
16615
+ type: "text",
16616
+ x: cx,
16617
+ y: height - 22,
16618
+ text: p.label,
16619
+ color,
16620
+ fontSize: 11,
16621
+ align: "center"
16622
+ });
16623
+ }
16624
+ });
16625
+ }
16626
+ if (cells.length > 0) {
16627
+ const maxCol = Math.max(0, ...cells.map((c) => c.col)) + 1;
16628
+ const maxRow = Math.max(0, ...cells.map((c) => c.row)) + 1;
16629
+ const cw = width / maxCol;
16630
+ const ch = height / maxRow;
16631
+ cells.forEach((c, i) => {
16632
+ const x = c.col * cw;
16633
+ const y = c.row * ch;
16634
+ const color = c.color ?? DEFAULT_CELL_COLOR;
16635
+ out.push({
16636
+ type: "rect",
16637
+ id: `cell-${i}`,
16638
+ x: x + 1,
16639
+ y: y + 1,
16640
+ width: cw - 2,
16641
+ height: ch - 2,
16642
+ color: "#9ca3af",
16643
+ fill: color
16644
+ });
16645
+ const label = c.label ?? (c.value != null ? String(c.value) : void 0);
16646
+ if (label && cw >= 18 && ch >= 14) {
16647
+ out.push({
16648
+ type: "text",
16649
+ x: x + cw / 2,
16650
+ y: y + ch / 2,
16651
+ text: label,
16652
+ color: "#111827",
16653
+ fontSize: 12,
16654
+ align: "center"
16655
+ });
16656
+ }
16657
+ });
16658
+ }
16659
+ out.push(...shapes);
16660
+ return out;
16661
+ }, [bars, cells, pointers, shapes, width, height]);
16662
+ return /* @__PURE__ */ jsx(Card, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
16663
+ title ? /* @__PURE__ */ jsx(Typography, { variant: "h4", children: title }) : null,
16664
+ /* @__PURE__ */ jsx(
16665
+ LearningCanvas,
16666
+ {
16667
+ width,
16668
+ height,
16669
+ backgroundColor,
16670
+ shapes: derivedShapes,
16671
+ interactive,
16672
+ animate,
16673
+ onShapeClick,
16674
+ isLoading,
16675
+ error
16676
+ }
16677
+ )
16678
+ ] }) });
16679
+ };
16680
+ }
16681
+ });
16196
16682
  var AuthLayout;
16197
16683
  var init_AuthLayout = __esm({
16198
16684
  "components/marketing/templates/AuthLayout.tsx"() {
@@ -17745,7 +18231,7 @@ var init_CodeBlock = __esm({
17745
18231
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
17746
18232
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
17747
18233
  HIDDEN_LINE_NUMBERS = { display: "none" };
17748
- CodeBlock = React97__default.memo(
18234
+ CodeBlock = React98__default.memo(
17749
18235
  ({
17750
18236
  code: rawCode,
17751
18237
  language = "text",
@@ -18332,7 +18818,7 @@ var init_MarkdownContent = __esm({
18332
18818
  init_Box();
18333
18819
  init_CodeBlock();
18334
18820
  init_cn();
18335
- MarkdownContent = React97__default.memo(
18821
+ MarkdownContent = React98__default.memo(
18336
18822
  ({ content, direction = "ltr", className }) => {
18337
18823
  const { t: _t } = useTranslate();
18338
18824
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -19659,7 +20145,7 @@ var init_StateMachineView = __esm({
19659
20145
  style: { top: title ? 30 : 0 },
19660
20146
  children: [
19661
20147
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
19662
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React97__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
20148
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React98__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
19663
20149
  StateNode2,
19664
20150
  {
19665
20151
  state,
@@ -25297,8 +25783,8 @@ var init_Menu = __esm({
25297
25783
  "bottom-end": "bottom-start"
25298
25784
  };
25299
25785
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
25300
- const triggerChild = React97__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
25301
- const triggerElement = React97__default.cloneElement(
25786
+ const triggerChild = React98__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
25787
+ const triggerElement = React98__default.cloneElement(
25302
25788
  triggerChild,
25303
25789
  {
25304
25790
  ref: triggerRef,
@@ -25393,14 +25879,14 @@ function useDataDnd(args) {
25393
25879
  const isZone = Boolean(dragGroup || accepts || sortable);
25394
25880
  const enabled = isZone || Boolean(dndRoot);
25395
25881
  const eventBus = useEventBus();
25396
- const parentRoot = React97__default.useContext(RootCtx);
25882
+ const parentRoot = React98__default.useContext(RootCtx);
25397
25883
  const isRoot = enabled && parentRoot === null;
25398
- const zoneId = React97__default.useId();
25884
+ const zoneId = React98__default.useId();
25399
25885
  const ownGroup = dragGroup ?? accepts ?? zoneId;
25400
- const [optimisticOrders, setOptimisticOrders] = React97__default.useState(() => /* @__PURE__ */ new Map());
25401
- const optimisticOrdersRef = React97__default.useRef(optimisticOrders);
25886
+ const [optimisticOrders, setOptimisticOrders] = React98__default.useState(() => /* @__PURE__ */ new Map());
25887
+ const optimisticOrdersRef = React98__default.useRef(optimisticOrders);
25402
25888
  optimisticOrdersRef.current = optimisticOrders;
25403
- const clearOptimisticOrder = React97__default.useCallback((group) => {
25889
+ const clearOptimisticOrder = React98__default.useCallback((group) => {
25404
25890
  setOptimisticOrders((prev) => {
25405
25891
  if (!prev.has(group)) return prev;
25406
25892
  const next = new Map(prev);
@@ -25425,7 +25911,7 @@ function useDataDnd(args) {
25425
25911
  const raw = it[dndItemIdField];
25426
25912
  return raw != null ? String(raw) : `__idx_${idx}`;
25427
25913
  }).join("|");
25428
- const itemIds = React97__default.useMemo(
25914
+ const itemIds = React98__default.useMemo(
25429
25915
  () => orderedItems.map((it, idx) => {
25430
25916
  const raw = it[dndItemIdField];
25431
25917
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -25436,7 +25922,7 @@ function useDataDnd(args) {
25436
25922
  const raw = it[dndItemIdField];
25437
25923
  return raw != null ? String(raw) : `__${idx}`;
25438
25924
  }).join("|");
25439
- React97__default.useEffect(() => {
25925
+ React98__default.useEffect(() => {
25440
25926
  const root = isRoot ? null : parentRoot;
25441
25927
  if (root) {
25442
25928
  root.clearOptimisticOrder(ownGroup);
@@ -25444,20 +25930,20 @@ function useDataDnd(args) {
25444
25930
  clearOptimisticOrder(ownGroup);
25445
25931
  }
25446
25932
  }, [itemsContentSig, ownGroup]);
25447
- const zonesRef = React97__default.useRef(/* @__PURE__ */ new Map());
25448
- const registerZone = React97__default.useCallback((zoneId2, meta2) => {
25933
+ const zonesRef = React98__default.useRef(/* @__PURE__ */ new Map());
25934
+ const registerZone = React98__default.useCallback((zoneId2, meta2) => {
25449
25935
  zonesRef.current.set(zoneId2, meta2);
25450
25936
  }, []);
25451
- const unregisterZone = React97__default.useCallback((zoneId2) => {
25937
+ const unregisterZone = React98__default.useCallback((zoneId2) => {
25452
25938
  zonesRef.current.delete(zoneId2);
25453
25939
  }, []);
25454
- const [activeDrag, setActiveDrag] = React97__default.useState(null);
25455
- const [overZoneGroup, setOverZoneGroup] = React97__default.useState(null);
25456
- const meta = React97__default.useMemo(
25940
+ const [activeDrag, setActiveDrag] = React98__default.useState(null);
25941
+ const [overZoneGroup, setOverZoneGroup] = React98__default.useState(null);
25942
+ const meta = React98__default.useMemo(
25457
25943
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
25458
25944
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
25459
25945
  );
25460
- React97__default.useEffect(() => {
25946
+ React98__default.useEffect(() => {
25461
25947
  const target = isRoot ? null : parentRoot;
25462
25948
  if (!target) {
25463
25949
  zonesRef.current.set(zoneId, meta);
@@ -25476,7 +25962,7 @@ function useDataDnd(args) {
25476
25962
  }, [parentRoot, isRoot, zoneId, meta]);
25477
25963
  const sensors = useAlmadarDndSensors(true);
25478
25964
  const collisionDetection = almadarDndCollisionDetection;
25479
- const findZoneByItem = React97__default.useCallback(
25965
+ const findZoneByItem = React98__default.useCallback(
25480
25966
  (id) => {
25481
25967
  for (const z of zonesRef.current.values()) {
25482
25968
  if (z.itemIds.includes(id)) return z;
@@ -25485,7 +25971,7 @@ function useDataDnd(args) {
25485
25971
  },
25486
25972
  []
25487
25973
  );
25488
- React97__default.useCallback(
25974
+ React98__default.useCallback(
25489
25975
  (group) => {
25490
25976
  for (const z of zonesRef.current.values()) {
25491
25977
  if (z.group === group) return z;
@@ -25494,7 +25980,7 @@ function useDataDnd(args) {
25494
25980
  },
25495
25981
  []
25496
25982
  );
25497
- const handleDragEnd = React97__default.useCallback(
25983
+ const handleDragEnd = React98__default.useCallback(
25498
25984
  (event) => {
25499
25985
  const { active, over } = event;
25500
25986
  const activeIdStr = String(active.id);
@@ -25585,8 +26071,8 @@ function useDataDnd(args) {
25585
26071
  },
25586
26072
  [eventBus]
25587
26073
  );
25588
- const sortableData = React97__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25589
- const SortableItem = React97__default.useCallback(
26074
+ const sortableData = React98__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
26075
+ const SortableItem = React98__default.useCallback(
25590
26076
  ({ id, children }) => {
25591
26077
  const {
25592
26078
  attributes,
@@ -25626,7 +26112,7 @@ function useDataDnd(args) {
25626
26112
  id: droppableId,
25627
26113
  data: sortableData
25628
26114
  });
25629
- const ctx = React97__default.useContext(RootCtx);
26115
+ const ctx = React98__default.useContext(RootCtx);
25630
26116
  const activeDrag2 = ctx?.activeDrag ?? null;
25631
26117
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
25632
26118
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -25641,7 +26127,7 @@ function useDataDnd(args) {
25641
26127
  showForeignPlaceholder,
25642
26128
  ctxAvailable: ctx != null
25643
26129
  });
25644
- React97__default.useEffect(() => {
26130
+ React98__default.useEffect(() => {
25645
26131
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25646
26132
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25647
26133
  return /* @__PURE__ */ jsx(
@@ -25655,11 +26141,11 @@ function useDataDnd(args) {
25655
26141
  }
25656
26142
  );
25657
26143
  };
25658
- const rootContextValue = React97__default.useMemo(
26144
+ const rootContextValue = React98__default.useMemo(
25659
26145
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
25660
26146
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
25661
26147
  );
25662
- const handleDragStart = React97__default.useCallback((event) => {
26148
+ const handleDragStart = React98__default.useCallback((event) => {
25663
26149
  const sourceZone = findZoneByItem(event.active.id);
25664
26150
  const rect = event.active.rect.current.initial;
25665
26151
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -25678,7 +26164,7 @@ function useDataDnd(args) {
25678
26164
  isRoot
25679
26165
  });
25680
26166
  }, [findZoneByItem, isRoot, zoneId]);
25681
- const handleDragOver = React97__default.useCallback((event) => {
26167
+ const handleDragOver = React98__default.useCallback((event) => {
25682
26168
  const { active, over } = event;
25683
26169
  const overData = over?.data?.current;
25684
26170
  const overGroup = overData?.dndGroup ?? null;
@@ -25748,7 +26234,7 @@ function useDataDnd(args) {
25748
26234
  return next;
25749
26235
  });
25750
26236
  }, []);
25751
- const handleDragCancel = React97__default.useCallback((event) => {
26237
+ const handleDragCancel = React98__default.useCallback((event) => {
25752
26238
  setActiveDrag(null);
25753
26239
  setOverZoneGroup(null);
25754
26240
  dndLog.warn("dragCancel", {
@@ -25756,12 +26242,12 @@ function useDataDnd(args) {
25756
26242
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
25757
26243
  });
25758
26244
  }, []);
25759
- const handleDragEndWithCleanup = React97__default.useCallback((event) => {
26245
+ const handleDragEndWithCleanup = React98__default.useCallback((event) => {
25760
26246
  handleDragEnd(event);
25761
26247
  setActiveDrag(null);
25762
26248
  setOverZoneGroup(null);
25763
26249
  }, [handleDragEnd]);
25764
- const wrapContainer = React97__default.useCallback(
26250
+ const wrapContainer = React98__default.useCallback(
25765
26251
  (children) => {
25766
26252
  if (!enabled) return children;
25767
26253
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -25815,7 +26301,7 @@ var init_useDataDnd = __esm({
25815
26301
  init_useAlmadarDndCollision();
25816
26302
  init_Box();
25817
26303
  dndLog = createLogger("almadar:ui:dnd");
25818
- RootCtx = React97__default.createContext(null);
26304
+ RootCtx = React98__default.createContext(null);
25819
26305
  }
25820
26306
  });
25821
26307
  function renderIconInput(icon, props) {
@@ -26341,7 +26827,7 @@ function DataList({
26341
26827
  }) {
26342
26828
  const eventBus = useEventBus();
26343
26829
  const { t } = useTranslate();
26344
- const [visibleCount, setVisibleCount] = React97__default.useState(pageSize || Infinity);
26830
+ const [visibleCount, setVisibleCount] = React98__default.useState(pageSize || Infinity);
26345
26831
  const fieldDefs = fields ?? columns ?? [];
26346
26832
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
26347
26833
  const dnd = useDataDnd({
@@ -26360,7 +26846,7 @@ function DataList({
26360
26846
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
26361
26847
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
26362
26848
  const hasRenderProp = typeof children === "function";
26363
- React97__default.useEffect(() => {
26849
+ React98__default.useEffect(() => {
26364
26850
  const renderItemTypeOf = typeof schemaRenderItem;
26365
26851
  const childrenTypeOf = typeof children;
26366
26852
  if (data.length > 0 && !hasRenderProp) {
@@ -26464,7 +26950,7 @@ function DataList({
26464
26950
  const items2 = [...data];
26465
26951
  const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
26466
26952
  const contentField = titleField?.name ?? fieldDefs[0]?.name ?? "";
26467
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
26953
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
26468
26954
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
26469
26955
  group.items.map((itemData, index) => {
26470
26956
  const id = itemData.id || `${gi}-${index}`;
@@ -26605,7 +27091,7 @@ function DataList({
26605
27091
  className
26606
27092
  ),
26607
27093
  children: [
26608
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
27094
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
26609
27095
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
26610
27096
  group.items.map(
26611
27097
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -26690,7 +27176,7 @@ var init_FormSection = __esm({
26690
27176
  columns = 1,
26691
27177
  className
26692
27178
  }) => {
26693
- const [collapsed, setCollapsed] = React97__default.useState(defaultCollapsed);
27179
+ const [collapsed, setCollapsed] = React98__default.useState(defaultCollapsed);
26694
27180
  const { t } = useTranslate();
26695
27181
  const eventBus = useEventBus();
26696
27182
  const gridClass = {
@@ -26698,7 +27184,7 @@ var init_FormSection = __esm({
26698
27184
  2: "grid-cols-1 md:grid-cols-2",
26699
27185
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
26700
27186
  }[columns];
26701
- React97__default.useCallback(() => {
27187
+ React98__default.useCallback(() => {
26702
27188
  if (collapsible) {
26703
27189
  setCollapsed((prev) => !prev);
26704
27190
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -27648,7 +28134,7 @@ var init_Flex = __esm({
27648
28134
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
27649
28135
  }
27650
28136
  }
27651
- return React97__default.createElement(Component, {
28137
+ return React98__default.createElement(Component, {
27652
28138
  className: cn(
27653
28139
  inline ? "inline-flex" : "flex",
27654
28140
  directionStyles[direction],
@@ -27767,7 +28253,7 @@ var init_Grid = __esm({
27767
28253
  as: Component = "div"
27768
28254
  }) => {
27769
28255
  const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
27770
- return React97__default.createElement(
28256
+ return React98__default.createElement(
27771
28257
  Component,
27772
28258
  {
27773
28259
  className: cn(
@@ -27963,9 +28449,9 @@ var init_Popover = __esm({
27963
28449
  onMouseLeave: handleClose,
27964
28450
  onPointerDown: tapTriggerProps.onPointerDown
27965
28451
  };
27966
- const childElement = React97__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28452
+ const childElement = React98__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27967
28453
  const childPointerDown = childElement.props.onPointerDown;
27968
- const triggerElement = React97__default.cloneElement(
28454
+ const triggerElement = React98__default.cloneElement(
27969
28455
  childElement,
27970
28456
  {
27971
28457
  ref: triggerRef,
@@ -28567,9 +29053,9 @@ var init_Tooltip = __esm({
28567
29053
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
28568
29054
  };
28569
29055
  }, []);
28570
- const triggerElement = React97__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
29056
+ const triggerElement = React98__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28571
29057
  const childPointerDown = triggerElement.props.onPointerDown;
28572
- const trigger = React97__default.cloneElement(triggerElement, {
29058
+ const trigger = React98__default.cloneElement(triggerElement, {
28573
29059
  ref: triggerRef,
28574
29060
  onMouseEnter: handleMouseEnter,
28575
29061
  onMouseLeave: handleMouseLeave,
@@ -28659,7 +29145,7 @@ var init_WizardProgress = __esm({
28659
29145
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
28660
29146
  const isActive = index === currentStep;
28661
29147
  const isCompleted = index < currentStep;
28662
- return /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
29148
+ return /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
28663
29149
  /* @__PURE__ */ jsx(
28664
29150
  "button",
28665
29151
  {
@@ -30219,13 +30705,13 @@ var init_MapView = __esm({
30219
30705
  shadowSize: [41, 41]
30220
30706
  });
30221
30707
  L.Marker.prototype.options.icon = defaultIcon;
30222
- const { useEffect: useEffect67, useRef: useRef64, useCallback: useCallback103, useState: useState98 } = React97__default;
30708
+ const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback103, useState: useState98 } = React98__default;
30223
30709
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
30224
30710
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
30225
30711
  function MapUpdater({ centerLat, centerLng, zoom }) {
30226
30712
  const map = useMap();
30227
- const prevRef = useRef64({ centerLat, centerLng, zoom });
30228
- useEffect67(() => {
30713
+ const prevRef = useRef65({ centerLat, centerLng, zoom });
30714
+ useEffect68(() => {
30229
30715
  const prev = prevRef.current;
30230
30716
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
30231
30717
  map.setView([centerLat, centerLng], zoom);
@@ -30236,7 +30722,7 @@ var init_MapView = __esm({
30236
30722
  }
30237
30723
  function MapClickHandler({ onMapClick }) {
30238
30724
  const map = useMap();
30239
- useEffect67(() => {
30725
+ useEffect68(() => {
30240
30726
  if (!onMapClick) return;
30241
30727
  const handler = (e) => {
30242
30728
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -31134,8 +31620,8 @@ function TableView({
31134
31620
  }) {
31135
31621
  const eventBus = useEventBus();
31136
31622
  const { t } = useTranslate();
31137
- const [visibleCount, setVisibleCount] = React97__default.useState(pageSize > 0 ? pageSize : Infinity);
31138
- const [localSelected, setLocalSelected] = React97__default.useState(/* @__PURE__ */ new Set());
31623
+ const [visibleCount, setVisibleCount] = React98__default.useState(pageSize > 0 ? pageSize : Infinity);
31624
+ const [localSelected, setLocalSelected] = React98__default.useState(/* @__PURE__ */ new Set());
31139
31625
  const colDefs = columns ?? fields ?? [];
31140
31626
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
31141
31627
  const dnd = useDataDnd({
@@ -31330,12 +31816,12 @@ function TableView({
31330
31816
  ]
31331
31817
  }
31332
31818
  );
31333
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React97__default.Fragment, { children: rowInner }, id);
31819
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React98__default.Fragment, { children: rowInner }, id);
31334
31820
  };
31335
31821
  const items = Array.from(data);
31336
31822
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
31337
31823
  let runningIndex = 0;
31338
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
31824
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
31339
31825
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
31340
31826
  group.items.map((row) => renderRow(row, runningIndex++))
31341
31827
  ] }, gi)) });
@@ -32692,7 +33178,7 @@ var init_StepFlow = __esm({
32692
33178
  className
32693
33179
  }) => {
32694
33180
  if (orientation === "vertical") {
32695
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React97__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
33181
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React98__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
32696
33182
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
32697
33183
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32698
33184
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -32703,7 +33189,7 @@ var init_StepFlow = __esm({
32703
33189
  ] })
32704
33190
  ] }) }, index)) });
32705
33191
  }
32706
- 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(React97__default.Fragment, { children: [
33192
+ 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(React98__default.Fragment, { children: [
32707
33193
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
32708
33194
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32709
33195
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -33688,7 +34174,7 @@ var init_LikertScale = __esm({
33688
34174
  md: "text-base",
33689
34175
  lg: "text-lg"
33690
34176
  };
33691
- LikertScale = React97__default.forwardRef(
34177
+ LikertScale = React98__default.forwardRef(
33692
34178
  ({
33693
34179
  question,
33694
34180
  options = DEFAULT_LIKERT_OPTIONS,
@@ -33700,7 +34186,7 @@ var init_LikertScale = __esm({
33700
34186
  variant = "radios",
33701
34187
  className
33702
34188
  }, ref) => {
33703
- const groupId = React97__default.useId();
34189
+ const groupId = React98__default.useId();
33704
34190
  const eventBus = useEventBus();
33705
34191
  const handleSelect = useCallback(
33706
34192
  (next) => {
@@ -35982,7 +36468,7 @@ var init_DocBreadcrumb = __esm({
35982
36468
  "aria-label": t("aria.breadcrumb"),
35983
36469
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
35984
36470
  const isLast = idx === items.length - 1;
35985
- return /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
36471
+ return /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
35986
36472
  idx > 0 && /* @__PURE__ */ jsx(
35987
36473
  Icon,
35988
36474
  {
@@ -36851,7 +37337,7 @@ var init_MiniStateMachine = __esm({
36851
37337
  const x = 2 + i * (NODE_W + GAP + ARROW_W + GAP);
36852
37338
  const tc = transitionCounts[s.name] ?? 0;
36853
37339
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
36854
- return /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
37340
+ return /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
36855
37341
  /* @__PURE__ */ jsx(
36856
37342
  AvlState,
36857
37343
  {
@@ -37055,7 +37541,7 @@ var init_PageHeader = __esm({
37055
37541
  info: "bg-info/10 text-info"
37056
37542
  };
37057
37543
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
37058
- 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(React97__default.Fragment, { children: [
37544
+ 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(React98__default.Fragment, { children: [
37059
37545
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
37060
37546
  crumb.href ? /* @__PURE__ */ jsx(
37061
37547
  "a",
@@ -37413,7 +37899,7 @@ var init_Section = __esm({
37413
37899
  as: Component = "section"
37414
37900
  }) => {
37415
37901
  const hasHeader = title || description || action;
37416
- return React97__default.createElement(
37902
+ return React98__default.createElement(
37417
37903
  Component,
37418
37904
  {
37419
37905
  className: cn(
@@ -37787,7 +38273,7 @@ var init_WizardContainer = __esm({
37787
38273
  const isCompleted = index < currentStep;
37788
38274
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
37789
38275
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
37790
- return /* @__PURE__ */ jsxs(React97__default.Fragment, { children: [
38276
+ return /* @__PURE__ */ jsxs(React98__default.Fragment, { children: [
37791
38277
  /* @__PURE__ */ jsx(
37792
38278
  Button,
37793
38279
  {
@@ -40220,7 +40706,7 @@ var init_DetailPanel = __esm({
40220
40706
  }
40221
40707
  });
40222
40708
  function extractTitle(children) {
40223
- if (!React97__default.isValidElement(children)) return void 0;
40709
+ if (!React98__default.isValidElement(children)) return void 0;
40224
40710
  const props = children.props;
40225
40711
  if (typeof props.title === "string") {
40226
40712
  return props.title;
@@ -40570,12 +41056,12 @@ var init_Form = __esm({
40570
41056
  const isSchemaEntity = isOrbitalEntitySchema(entity);
40571
41057
  const resolvedEntity = isSchemaEntity ? entity : void 0;
40572
41058
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
40573
- const normalizedInitialData = React97__default.useMemo(() => {
41059
+ const normalizedInitialData = React98__default.useMemo(() => {
40574
41060
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
40575
41061
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
40576
41062
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
40577
41063
  }, [entity, initialData]);
40578
- const entityDerivedFields = React97__default.useMemo(() => {
41064
+ const entityDerivedFields = React98__default.useMemo(() => {
40579
41065
  if (fields && fields.length > 0) return void 0;
40580
41066
  if (!resolvedEntity) return void 0;
40581
41067
  return resolvedEntity.fields.map(
@@ -40596,16 +41082,16 @@ var init_Form = __esm({
40596
41082
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
40597
41083
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
40598
41084
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
40599
- const [formData, setFormData] = React97__default.useState(
41085
+ const [formData, setFormData] = React98__default.useState(
40600
41086
  normalizedInitialData
40601
41087
  );
40602
- const [collapsedSections, setCollapsedSections] = React97__default.useState(
41088
+ const [collapsedSections, setCollapsedSections] = React98__default.useState(
40603
41089
  /* @__PURE__ */ new Set()
40604
41090
  );
40605
- const [submitError, setSubmitError] = React97__default.useState(null);
40606
- const formRef = React97__default.useRef(null);
41091
+ const [submitError, setSubmitError] = React98__default.useState(null);
41092
+ const formRef = React98__default.useRef(null);
40607
41093
  const formMode = props.mode;
40608
- const mountedRef = React97__default.useRef(false);
41094
+ const mountedRef = React98__default.useRef(false);
40609
41095
  if (!mountedRef.current) {
40610
41096
  mountedRef.current = true;
40611
41097
  debug("forms", "mount", {
@@ -40618,7 +41104,7 @@ var init_Form = __esm({
40618
41104
  });
40619
41105
  }
40620
41106
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
40621
- const evalContext = React97__default.useMemo(
41107
+ const evalContext = React98__default.useMemo(
40622
41108
  () => ({
40623
41109
  formValues: formData,
40624
41110
  globalVariables: externalContext?.globalVariables ?? {},
@@ -40627,7 +41113,7 @@ var init_Form = __esm({
40627
41113
  }),
40628
41114
  [formData, externalContext]
40629
41115
  );
40630
- React97__default.useEffect(() => {
41116
+ React98__default.useEffect(() => {
40631
41117
  debug("forms", "initialData-sync", {
40632
41118
  mode: formMode,
40633
41119
  normalizedInitialData,
@@ -40638,7 +41124,7 @@ var init_Form = __esm({
40638
41124
  setFormData(normalizedInitialData);
40639
41125
  }
40640
41126
  }, [normalizedInitialData]);
40641
- const processCalculations = React97__default.useCallback(
41127
+ const processCalculations = React98__default.useCallback(
40642
41128
  (changedFieldId, newFormData) => {
40643
41129
  if (!hiddenCalculations.length) return;
40644
41130
  const context = {
@@ -40663,7 +41149,7 @@ var init_Form = __esm({
40663
41149
  },
40664
41150
  [hiddenCalculations, externalContext, eventBus]
40665
41151
  );
40666
- const checkViolations = React97__default.useCallback(
41152
+ const checkViolations = React98__default.useCallback(
40667
41153
  (changedFieldId, newFormData) => {
40668
41154
  if (!violationTriggers.length) return;
40669
41155
  const context = {
@@ -40701,7 +41187,7 @@ var init_Form = __esm({
40701
41187
  processCalculations(name, newFormData);
40702
41188
  checkViolations(name, newFormData);
40703
41189
  };
40704
- const isFieldVisible = React97__default.useCallback(
41190
+ const isFieldVisible = React98__default.useCallback(
40705
41191
  (fieldName) => {
40706
41192
  const condition = conditionalFields[fieldName];
40707
41193
  if (!condition) return true;
@@ -40709,7 +41195,7 @@ var init_Form = __esm({
40709
41195
  },
40710
41196
  [conditionalFields, evalContext]
40711
41197
  );
40712
- const isSectionVisible = React97__default.useCallback(
41198
+ const isSectionVisible = React98__default.useCallback(
40713
41199
  (section) => {
40714
41200
  if (!section.condition) return true;
40715
41201
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -40785,7 +41271,7 @@ var init_Form = __esm({
40785
41271
  eventBus.emit(`UI:${onCancel}`);
40786
41272
  }
40787
41273
  };
40788
- const renderField = React97__default.useCallback(
41274
+ const renderField = React98__default.useCallback(
40789
41275
  (field) => {
40790
41276
  const fieldName = field.name || field.field;
40791
41277
  if (!fieldName) return null;
@@ -40806,7 +41292,7 @@ var init_Form = __esm({
40806
41292
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
40807
41293
  );
40808
41294
  const effectiveFields = entityDerivedFields ?? fields;
40809
- const normalizedFields = React97__default.useMemo(() => {
41295
+ const normalizedFields = React98__default.useMemo(() => {
40810
41296
  if (!effectiveFields || effectiveFields.length === 0) return [];
40811
41297
  return effectiveFields.map((field) => {
40812
41298
  if (typeof field === "string") {
@@ -40830,7 +41316,7 @@ var init_Form = __esm({
40830
41316
  return field;
40831
41317
  });
40832
41318
  }, [effectiveFields, resolvedEntity]);
40833
- const schemaFields = React97__default.useMemo(() => {
41319
+ const schemaFields = React98__default.useMemo(() => {
40834
41320
  if (normalizedFields.length === 0) return null;
40835
41321
  if (isDebugEnabled()) {
40836
41322
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -40840,7 +41326,7 @@ var init_Form = __esm({
40840
41326
  }
40841
41327
  return normalizedFields.map(renderField).filter(Boolean);
40842
41328
  }, [normalizedFields, renderField, entityName, conditionalFields]);
40843
- const sectionElements = React97__default.useMemo(() => {
41329
+ const sectionElements = React98__default.useMemo(() => {
40844
41330
  if (!sections || sections.length === 0) return null;
40845
41331
  return sections.map((section) => {
40846
41332
  if (!isSectionVisible(section)) {
@@ -41565,7 +42051,7 @@ var init_List = __esm({
41565
42051
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
41566
42052
  return [];
41567
42053
  }, [entity]);
41568
- const getItemActions = React97__default.useCallback(
42054
+ const getItemActions = React98__default.useCallback(
41569
42055
  (item) => {
41570
42056
  if (!itemActions) return [];
41571
42057
  if (typeof itemActions === "function") {
@@ -42040,7 +42526,7 @@ var init_MediaGallery = __esm({
42040
42526
  [selectable, selectedItems, selectionEvent, eventBus]
42041
42527
  );
42042
42528
  const entityData = Array.isArray(entity) ? entity : [];
42043
- const items = React97__default.useMemo(() => {
42529
+ const items = React98__default.useMemo(() => {
42044
42530
  if (propItems) return propItems;
42045
42531
  if (entityData.length === 0) return [];
42046
42532
  return entityData.map((record, idx) => {
@@ -42203,7 +42689,7 @@ var init_MediaGallery = __esm({
42203
42689
  }
42204
42690
  });
42205
42691
  function extractTitle2(children) {
42206
- if (!React97__default.isValidElement(children)) return void 0;
42692
+ if (!React98__default.isValidElement(children)) return void 0;
42207
42693
  const props = children.props;
42208
42694
  if (typeof props.title === "string") {
42209
42695
  return props.title;
@@ -42458,7 +42944,7 @@ var init_debugRegistry = __esm({
42458
42944
  }
42459
42945
  });
42460
42946
  function useDebugData() {
42461
- const [data, setData] = React97.useState(() => ({
42947
+ const [data, setData] = React98.useState(() => ({
42462
42948
  traits: [],
42463
42949
  ticks: [],
42464
42950
  guards: [],
@@ -42472,7 +42958,7 @@ function useDebugData() {
42472
42958
  },
42473
42959
  lastUpdate: Date.now()
42474
42960
  }));
42475
- React97.useEffect(() => {
42961
+ React98.useEffect(() => {
42476
42962
  const updateData = () => {
42477
42963
  setData({
42478
42964
  traits: getAllTraits(),
@@ -42581,12 +43067,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
42581
43067
  return positions;
42582
43068
  }
42583
43069
  function WalkMinimap() {
42584
- const [walkStep, setWalkStep] = React97.useState(null);
42585
- const [traits2, setTraits] = React97.useState([]);
42586
- const [coveredEdges, setCoveredEdges] = React97.useState([]);
42587
- const [completedTraits, setCompletedTraits] = React97.useState(/* @__PURE__ */ new Set());
42588
- const prevTraitRef = React97.useRef(null);
42589
- React97.useEffect(() => {
43070
+ const [walkStep, setWalkStep] = React98.useState(null);
43071
+ const [traits2, setTraits] = React98.useState([]);
43072
+ const [coveredEdges, setCoveredEdges] = React98.useState([]);
43073
+ const [completedTraits, setCompletedTraits] = React98.useState(/* @__PURE__ */ new Set());
43074
+ const prevTraitRef = React98.useRef(null);
43075
+ React98.useEffect(() => {
42590
43076
  const interval = setInterval(() => {
42591
43077
  const w = window;
42592
43078
  const step = w.__orbitalWalkStep;
@@ -43022,15 +43508,15 @@ var init_EntitiesTab = __esm({
43022
43508
  });
43023
43509
  function EventFlowTab({ events: events2 }) {
43024
43510
  const { t } = useTranslate();
43025
- const [filter, setFilter] = React97.useState("all");
43026
- const containerRef = React97.useRef(null);
43027
- const [autoScroll, setAutoScroll] = React97.useState(true);
43028
- React97.useEffect(() => {
43511
+ const [filter, setFilter] = React98.useState("all");
43512
+ const containerRef = React98.useRef(null);
43513
+ const [autoScroll, setAutoScroll] = React98.useState(true);
43514
+ React98.useEffect(() => {
43029
43515
  if (autoScroll && containerRef.current) {
43030
43516
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
43031
43517
  }
43032
43518
  }, [events2.length, autoScroll]);
43033
- const filteredEvents = React97.useMemo(() => {
43519
+ const filteredEvents = React98.useMemo(() => {
43034
43520
  if (filter === "all") return events2;
43035
43521
  return events2.filter((e) => e.type === filter);
43036
43522
  }, [events2, filter]);
@@ -43146,7 +43632,7 @@ var init_EventFlowTab = __esm({
43146
43632
  });
43147
43633
  function GuardsPanel({ guards }) {
43148
43634
  const { t } = useTranslate();
43149
- const [filter, setFilter] = React97.useState("all");
43635
+ const [filter, setFilter] = React98.useState("all");
43150
43636
  if (guards.length === 0) {
43151
43637
  return /* @__PURE__ */ jsx(
43152
43638
  EmptyState,
@@ -43159,7 +43645,7 @@ function GuardsPanel({ guards }) {
43159
43645
  }
43160
43646
  const passedCount = guards.filter((g) => g.result).length;
43161
43647
  const failedCount = guards.length - passedCount;
43162
- const filteredGuards = React97.useMemo(() => {
43648
+ const filteredGuards = React98.useMemo(() => {
43163
43649
  if (filter === "all") return guards;
43164
43650
  if (filter === "passed") return guards.filter((g) => g.result);
43165
43651
  return guards.filter((g) => !g.result);
@@ -43322,10 +43808,10 @@ function EffectBadge({ effect }) {
43322
43808
  }
43323
43809
  function TransitionTimeline({ transitions }) {
43324
43810
  const { t } = useTranslate();
43325
- const containerRef = React97.useRef(null);
43326
- const [autoScroll, setAutoScroll] = React97.useState(true);
43327
- const [expandedId, setExpandedId] = React97.useState(null);
43328
- React97.useEffect(() => {
43811
+ const containerRef = React98.useRef(null);
43812
+ const [autoScroll, setAutoScroll] = React98.useState(true);
43813
+ const [expandedId, setExpandedId] = React98.useState(null);
43814
+ React98.useEffect(() => {
43329
43815
  if (autoScroll && containerRef.current) {
43330
43816
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
43331
43817
  }
@@ -43605,9 +44091,9 @@ function getAllEvents(traits2) {
43605
44091
  function EventDispatcherTab({ traits: traits2, schema }) {
43606
44092
  const eventBus = useEventBus();
43607
44093
  const { t } = useTranslate();
43608
- const [log13, setLog] = React97.useState([]);
43609
- const prevStatesRef = React97.useRef(/* @__PURE__ */ new Map());
43610
- React97.useEffect(() => {
44094
+ const [log13, setLog] = React98.useState([]);
44095
+ const prevStatesRef = React98.useRef(/* @__PURE__ */ new Map());
44096
+ React98.useEffect(() => {
43611
44097
  for (const trait of traits2) {
43612
44098
  const prev = prevStatesRef.current.get(trait.id);
43613
44099
  if (prev && prev !== trait.currentState) {
@@ -43776,10 +44262,10 @@ function VerifyModePanel({
43776
44262
  localCount
43777
44263
  }) {
43778
44264
  const { t } = useTranslate();
43779
- const [expanded, setExpanded] = React97.useState(true);
43780
- const scrollRef = React97.useRef(null);
43781
- const prevCountRef = React97.useRef(0);
43782
- React97.useEffect(() => {
44265
+ const [expanded, setExpanded] = React98.useState(true);
44266
+ const scrollRef = React98.useRef(null);
44267
+ const prevCountRef = React98.useRef(0);
44268
+ React98.useEffect(() => {
43783
44269
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
43784
44270
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
43785
44271
  }
@@ -43836,10 +44322,10 @@ function RuntimeDebugger({
43836
44322
  schema
43837
44323
  }) {
43838
44324
  const { t } = useTranslate();
43839
- const [isCollapsed, setIsCollapsed] = React97.useState(mode === "verify" ? true : defaultCollapsed);
43840
- const [isVisible, setIsVisible] = React97.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
44325
+ const [isCollapsed, setIsCollapsed] = React98.useState(mode === "verify" ? true : defaultCollapsed);
44326
+ const [isVisible, setIsVisible] = React98.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
43841
44327
  const debugData = useDebugData();
43842
- React97.useEffect(() => {
44328
+ React98.useEffect(() => {
43843
44329
  if (mode === "inline") return;
43844
44330
  return onDebugToggle((enabled) => {
43845
44331
  setIsVisible(enabled);
@@ -43848,7 +44334,7 @@ function RuntimeDebugger({
43848
44334
  }
43849
44335
  });
43850
44336
  }, [mode]);
43851
- React97.useEffect(() => {
44337
+ React98.useEffect(() => {
43852
44338
  if (mode === "inline") return;
43853
44339
  const handleKeyDown = (e) => {
43854
44340
  if (e.key === "`" && isVisible) {
@@ -44368,7 +44854,7 @@ var init_StatCard = __esm({
44368
44854
  const labelToUse = propLabel ?? propTitle;
44369
44855
  const eventBus = useEventBus();
44370
44856
  const { t } = useTranslate();
44371
- const handleActionClick = React97__default.useCallback(() => {
44857
+ const handleActionClick = React98__default.useCallback(() => {
44372
44858
  if (action?.event) {
44373
44859
  eventBus.emit(`UI:${action.event}`, {});
44374
44860
  }
@@ -44379,7 +44865,7 @@ var init_StatCard = __esm({
44379
44865
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
44380
44866
  const isLoading = externalLoading ?? false;
44381
44867
  const error = externalError;
44382
- const computeMetricValue = React97__default.useCallback(
44868
+ const computeMetricValue = React98__default.useCallback(
44383
44869
  (metric, items) => {
44384
44870
  if (metric.value !== void 0) {
44385
44871
  return metric.value;
@@ -44418,7 +44904,7 @@ var init_StatCard = __esm({
44418
44904
  },
44419
44905
  []
44420
44906
  );
44421
- const schemaStats = React97__default.useMemo(() => {
44907
+ const schemaStats = React98__default.useMemo(() => {
44422
44908
  if (!metrics || metrics.length === 0) return null;
44423
44909
  return metrics.map((metric) => ({
44424
44910
  label: metric.label,
@@ -44426,7 +44912,7 @@ var init_StatCard = __esm({
44426
44912
  format: metric.format
44427
44913
  }));
44428
44914
  }, [metrics, data, computeMetricValue]);
44429
- const calculatedTrend = React97__default.useMemo(() => {
44915
+ const calculatedTrend = React98__default.useMemo(() => {
44430
44916
  if (manualTrend !== void 0) return manualTrend;
44431
44917
  if (previousValue === void 0 || currentValue === void 0)
44432
44918
  return void 0;
@@ -45066,8 +45552,8 @@ var init_SubagentTracePanel = __esm({
45066
45552
  ] });
45067
45553
  };
45068
45554
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
45069
- const endRef = React97__default.useRef(null);
45070
- React97__default.useEffect(() => {
45555
+ const endRef = React98__default.useRef(null);
45556
+ React98__default.useEffect(() => {
45071
45557
  if (!autoScroll) return;
45072
45558
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
45073
45559
  }, [activities.length, autoScroll]);
@@ -45161,7 +45647,7 @@ var init_SubagentTracePanel = __esm({
45161
45647
  };
45162
45648
  SubagentRichCard = ({ subagent }) => {
45163
45649
  const { t } = useTranslate();
45164
- const activities = React97__default.useMemo(
45650
+ const activities = React98__default.useMemo(
45165
45651
  () => subagentMessagesToActivities(subagent.messages),
45166
45652
  [subagent.messages]
45167
45653
  );
@@ -45238,8 +45724,8 @@ var init_SubagentTracePanel = __esm({
45238
45724
  ] });
45239
45725
  };
45240
45726
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
45241
- const endRef = React97__default.useRef(null);
45242
- React97__default.useEffect(() => {
45727
+ const endRef = React98__default.useRef(null);
45728
+ React98__default.useEffect(() => {
45243
45729
  if (!autoScroll) return;
45244
45730
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
45245
45731
  }, [messages.length, autoScroll]);
@@ -45669,7 +46155,7 @@ var init_Timeline = __esm({
45669
46155
  }) => {
45670
46156
  const { t } = useTranslate();
45671
46157
  const entityData = entity ?? [];
45672
- const items = React97__default.useMemo(() => {
46158
+ const items = React98__default.useMemo(() => {
45673
46159
  if (propItems) return propItems;
45674
46160
  if (entityData.length === 0) return [];
45675
46161
  return entityData.map((record, idx) => {
@@ -45771,7 +46257,7 @@ var init_Timeline = __esm({
45771
46257
  }
45772
46258
  });
45773
46259
  function extractToastProps(children) {
45774
- if (!React97__default.isValidElement(children)) {
46260
+ if (!React98__default.isValidElement(children)) {
45775
46261
  if (typeof children === "string") {
45776
46262
  return { message: children };
45777
46263
  }
@@ -45813,7 +46299,7 @@ var init_ToastSlot = __esm({
45813
46299
  eventBus.emit(`${prefix}CLOSE`);
45814
46300
  };
45815
46301
  if (!isVisible) return null;
45816
- const isCustomContent = React97__default.isValidElement(children) && !message;
46302
+ const isCustomContent = React98__default.isValidElement(children) && !message;
45817
46303
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
45818
46304
  Toast,
45819
46305
  {
@@ -45830,7 +46316,7 @@ var init_ToastSlot = __esm({
45830
46316
  }
45831
46317
  });
45832
46318
  function lazyThree(name, loader) {
45833
- const Lazy = React97__default.lazy(
46319
+ const Lazy = React98__default.lazy(
45834
46320
  () => loader().then((m) => {
45835
46321
  const Resolved = m[name];
45836
46322
  if (!Resolved) {
@@ -45842,13 +46328,13 @@ function lazyThree(name, loader) {
45842
46328
  })
45843
46329
  );
45844
46330
  function ThreeWrapper(props) {
45845
- return React97__default.createElement(
46331
+ return React98__default.createElement(
45846
46332
  ThreeBoundary,
45847
46333
  { name },
45848
- React97__default.createElement(
45849
- React97__default.Suspense,
46334
+ React98__default.createElement(
46335
+ React98__default.Suspense,
45850
46336
  { fallback: null },
45851
- React97__default.createElement(Lazy, props)
46337
+ React98__default.createElement(Lazy, props)
45852
46338
  )
45853
46339
  );
45854
46340
  }
@@ -45865,11 +46351,13 @@ var init_component_registry_generated = __esm({
45865
46351
  init_ActionTile();
45866
46352
  init_ActivationBlock();
45867
46353
  init_ComponentPatterns();
46354
+ init_AlgorithmCanvas();
45868
46355
  init_AnimatedCounter();
45869
46356
  init_AnimatedGraphic();
45870
46357
  init_AnimatedReveal();
45871
46358
  init_ArticleSection();
45872
46359
  init_Aside();
46360
+ init_AtlasImage();
45873
46361
  init_AuthLayout();
45874
46362
  init_Avatar();
45875
46363
  init_Badge();
@@ -46127,7 +46615,7 @@ var init_component_registry_generated = __esm({
46127
46615
  init_WizardContainer();
46128
46616
  init_WizardNavigation();
46129
46617
  init_WizardProgress();
46130
- ThreeBoundary = class extends React97__default.Component {
46618
+ ThreeBoundary = class extends React98__default.Component {
46131
46619
  constructor() {
46132
46620
  super(...arguments);
46133
46621
  __publicField(this, "state", { failed: false });
@@ -46137,7 +46625,7 @@ var init_component_registry_generated = __esm({
46137
46625
  }
46138
46626
  render() {
46139
46627
  if (this.state.failed) {
46140
- return React97__default.createElement(
46628
+ return React98__default.createElement(
46141
46629
  "div",
46142
46630
  {
46143
46631
  "data-testid": "three-unavailable",
@@ -46163,11 +46651,14 @@ var init_component_registry_generated = __esm({
46163
46651
  "ActivationBlock": ActivationBlock,
46164
46652
  "Alert": AlertPattern,
46165
46653
  "AlertPattern": AlertPattern,
46654
+ "AlgorithmCanvas": AlgorithmCanvas,
46166
46655
  "AnimatedCounter": AnimatedCounter,
46167
46656
  "AnimatedGraphic": AnimatedGraphic,
46168
46657
  "AnimatedReveal": AnimatedReveal,
46169
46658
  "ArticleSection": ArticleSection,
46170
46659
  "Aside": Aside,
46660
+ "AtlasImage": AtlasImage,
46661
+ "AtlasPanel": AtlasPanel,
46171
46662
  "AuthLayout": AuthLayout,
46172
46663
  "Avatar": Avatar,
46173
46664
  "Badge": Badge,
@@ -46460,7 +46951,7 @@ function SuspenseConfigProvider({
46460
46951
  config,
46461
46952
  children
46462
46953
  }) {
46463
- return React97__default.createElement(
46954
+ return React98__default.createElement(
46464
46955
  SuspenseConfigContext.Provider,
46465
46956
  { value: config },
46466
46957
  children
@@ -46502,7 +46993,7 @@ function enrichFormFields(fields, entityDef) {
46502
46993
  }
46503
46994
  return { name: field, label: field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase()) };
46504
46995
  }
46505
- if (field && typeof field === "object" && !Array.isArray(field) && !React97__default.isValidElement(field) && !(field instanceof Date)) {
46996
+ if (field && typeof field === "object" && !Array.isArray(field) && !React98__default.isValidElement(field) && !(field instanceof Date)) {
46506
46997
  const obj = field;
46507
46998
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
46508
46999
  if (!fieldName) return field;
@@ -46955,7 +47446,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
46955
47446
  const key = `${parentId}-${index}-trait:${traitName}`;
46956
47447
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
46957
47448
  }
46958
- return /* @__PURE__ */ jsx(React97__default.Fragment, { children: child }, `${parentId}-${index}`);
47449
+ return /* @__PURE__ */ jsx(React98__default.Fragment, { children: child }, `${parentId}-${index}`);
46959
47450
  }
46960
47451
  if (!child || typeof child !== "object") return null;
46961
47452
  const childId = `${parentId}-${index}`;
@@ -46995,14 +47486,14 @@ function isPatternConfig(value) {
46995
47486
  if (value === null || value === void 0) return false;
46996
47487
  if (typeof value !== "object") return false;
46997
47488
  if (Array.isArray(value)) return false;
46998
- if (React97__default.isValidElement(value)) return false;
47489
+ if (React98__default.isValidElement(value)) return false;
46999
47490
  if (value instanceof Date) return false;
47000
47491
  if (typeof value === "function") return false;
47001
47492
  const record = value;
47002
47493
  return "type" in record && typeof record.type === "string" && getComponentForPattern$1(record.type) !== null;
47003
47494
  }
47004
47495
  function isPlainConfigObject(value) {
47005
- if (React97__default.isValidElement(value)) return false;
47496
+ if (React98__default.isValidElement(value)) return false;
47006
47497
  if (value instanceof Date) return false;
47007
47498
  const proto = Object.getPrototypeOf(value);
47008
47499
  return proto === Object.prototype || proto === null;
@@ -47128,7 +47619,7 @@ function SlotContentRenderer({
47128
47619
  for (const slotKey of CONTENT_NODE_SLOTS) {
47129
47620
  const slotVal = restProps[slotKey];
47130
47621
  if (slotVal === void 0 || slotVal === null) continue;
47131
- if (React97__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
47622
+ if (React98__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
47132
47623
  if (Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
47133
47624
  nodeSlotOverrides[slotKey] = renderPatternChildren(
47134
47625
  slotVal,
@@ -47177,7 +47668,7 @@ function SlotContentRenderer({
47177
47668
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
47178
47669
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
47179
47670
  const sample = resolvedItems[0];
47180
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React97__default.isValidElement(sample) && !(sample instanceof Date)) {
47671
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React98__default.isValidElement(sample) && !(sample instanceof Date)) {
47181
47672
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
47182
47673
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
47183
47674
  }
@@ -47338,7 +47829,9 @@ var init_UISlotRenderer = __esm({
47338
47829
  "content",
47339
47830
  "addons",
47340
47831
  "hud",
47341
- "fallback"
47832
+ "fallback",
47833
+ "controls",
47834
+ "overlay"
47342
47835
  ]);
47343
47836
  PATTERNS_WITH_CHILDREN = /* @__PURE__ */ new Set([
47344
47837
  "stack",