@almadar/ui 5.80.0 → 5.82.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.
@@ -1484,6 +1484,7 @@ var init_Button = __esm({
1484
1484
  rightIcon,
1485
1485
  icon: iconProp,
1486
1486
  iconRight: iconRightProp,
1487
+ iconAsset,
1487
1488
  action,
1488
1489
  actionPayload,
1489
1490
  label,
@@ -1495,7 +1496,8 @@ var init_Button = __esm({
1495
1496
  const eventBus = useEventBus();
1496
1497
  const leftIconValue = leftIcon || iconProp;
1497
1498
  const rightIconValue = rightIcon || iconRightProp;
1498
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
1499
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
1500
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ jsxRuntime.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]);
1499
1501
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
1500
1502
  const handleClick = (e) => {
1501
1503
  if (action) {
@@ -2153,13 +2155,14 @@ var init_Badge = __esm({
2153
2155
  lg: "px-3 py-1.5 text-base"
2154
2156
  };
2155
2157
  Badge = React105__namespace.default.forwardRef(
2156
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2158
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2157
2159
  const iconSizes3 = {
2158
2160
  sm: "h-icon-default w-icon-default",
2159
2161
  md: "h-icon-default w-icon-default",
2160
2162
  lg: "h-icon-default w-icon-default"
2161
2163
  };
2162
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2164
+ const iconPx = size === "lg" ? 20 : 16;
2165
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2163
2166
  return /* @__PURE__ */ jsxRuntime.jsxs(
2164
2167
  "span",
2165
2168
  {
@@ -8402,10 +8405,43 @@ var init_shared = __esm({
8402
8405
  init_canvasEffects();
8403
8406
  }
8404
8407
  });
8408
+ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
8409
+ const px = typeof size === "number" ? size : sizeMap[size];
8410
+ if (assetUrl?.url) {
8411
+ return /* @__PURE__ */ jsxRuntime.jsx(
8412
+ "img",
8413
+ {
8414
+ src: assetUrl.url,
8415
+ alt: alt ?? assetUrl.category ?? "",
8416
+ width: px,
8417
+ height: px,
8418
+ style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
8419
+ className: cn("flex-shrink-0", className)
8420
+ }
8421
+ );
8422
+ }
8423
+ const I = typeof icon === "string" ? resolveIcon(icon) : icon;
8424
+ return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
8425
+ }
8426
+ var sizeMap;
8427
+ var init_GameIcon = __esm({
8428
+ "components/game/2d/atoms/GameIcon.tsx"() {
8429
+ "use client";
8430
+ init_cn();
8431
+ init_Icon();
8432
+ sizeMap = {
8433
+ sm: 16,
8434
+ md: 24,
8435
+ lg: 32
8436
+ };
8437
+ GameIcon.displayName = "GameIcon";
8438
+ }
8439
+ });
8405
8440
  function GameCard({
8406
8441
  id,
8407
8442
  cost,
8408
8443
  art,
8444
+ frameAsset,
8409
8445
  attack,
8410
8446
  defense,
8411
8447
  name,
@@ -8423,16 +8459,19 @@ function GameCard({
8423
8459
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
8424
8460
  }, [disabled, id, onClick, clickEvent, eventBus]);
8425
8461
  const artPx = artPxMap[size];
8462
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
8426
8463
  return /* @__PURE__ */ jsxRuntime.jsxs(
8427
- "button",
8464
+ Button,
8428
8465
  {
8429
- type: "button",
8466
+ variant: "ghost",
8430
8467
  onClick: handleClick,
8431
8468
  disabled,
8432
8469
  title: name,
8470
+ style: frameStyle,
8433
8471
  className: cn(
8434
- "relative flex flex-col items-center rounded-interactive border-2",
8472
+ "relative flex flex-col items-center rounded-interactive",
8435
8473
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
8474
+ frameAsset?.url ? "border-0" : "border-2",
8436
8475
  cardSizeMap[size],
8437
8476
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
8438
8477
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -8440,8 +8479,9 @@ function GameCard({
8440
8479
  ),
8441
8480
  children: [
8442
8481
  cost != null && /* @__PURE__ */ jsxRuntime.jsx(
8443
- "span",
8482
+ Typography,
8444
8483
  {
8484
+ as: "span",
8445
8485
  className: cn(
8446
8486
  "absolute -top-2 -left-2 flex items-center justify-center",
8447
8487
  "min-w-[22px] h-[22px] rounded-full px-1",
@@ -8450,17 +8490,7 @@ function GameCard({
8450
8490
  children: cost
8451
8491
  }
8452
8492
  ),
8453
- /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsxRuntime.jsx(
8454
- "img",
8455
- {
8456
- src: art.url,
8457
- alt: name ?? id,
8458
- width: artPx,
8459
- height: artPx,
8460
- style: { imageRendering: "pixelated", objectFit: "contain" },
8461
- className: "flex-shrink-0"
8462
- }
8463
- ) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
8493
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: art, icon: "image", size: artPx, alt: name ?? id, className: "flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
8464
8494
  name != null && /* @__PURE__ */ jsxRuntime.jsx(
8465
8495
  Typography,
8466
8496
  {
@@ -8470,8 +8500,8 @@ function GameCard({
8470
8500
  }
8471
8501
  ),
8472
8502
  (attack != null || defense != null) && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex w-full items-center justify-between px-0.5 text-[10px] font-bold leading-none", children: [
8473
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
8474
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
8503
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
8504
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
8475
8505
  ] })
8476
8506
  ]
8477
8507
  }
@@ -8484,7 +8514,9 @@ var init_GameCard = __esm({
8484
8514
  init_cn();
8485
8515
  init_useEventBus();
8486
8516
  init_Box();
8517
+ init_Button();
8487
8518
  init_Typography();
8519
+ init_GameIcon();
8488
8520
  cardSizeMap = {
8489
8521
  sm: "w-16 h-24",
8490
8522
  md: "w-20 h-28",
@@ -8507,12 +8539,13 @@ function HealthBar({
8507
8539
  frameAsset,
8508
8540
  fillAsset
8509
8541
  }) {
8510
- const sizes = sizeMap[size];
8542
+ const sizes = sizeMap2[size];
8511
8543
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
8512
8544
  if (format === "hearts") {
8513
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
8514
- "span",
8545
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
8546
+ Box,
8515
8547
  {
8548
+ as: "span",
8516
8549
  className: cn(animated && "transition-transform hover:scale-110"),
8517
8550
  children: heartIcon(i < current, sizes.heart)
8518
8551
  },
@@ -8521,10 +8554,12 @@ function HealthBar({
8521
8554
  }
8522
8555
  if (format === "bar") {
8523
8556
  return /* @__PURE__ */ jsxRuntime.jsx(
8524
- "div",
8557
+ Box,
8525
8558
  {
8559
+ position: "relative",
8560
+ overflow: "hidden",
8526
8561
  className: cn(
8527
- "relative overflow-hidden rounded-full",
8562
+ "rounded-full",
8528
8563
  !frameAsset && "bg-muted",
8529
8564
  sizes.bar,
8530
8565
  "w-24",
@@ -8532,10 +8567,11 @@ function HealthBar({
8532
8567
  ),
8533
8568
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
8534
8569
  children: /* @__PURE__ */ jsxRuntime.jsx(
8535
- "div",
8570
+ Box,
8536
8571
  {
8572
+ position: "absolute",
8537
8573
  className: cn(
8538
- "absolute inset-y-0 left-0 rounded-full",
8574
+ "inset-y-0 left-0 rounded-full",
8539
8575
  !fillAsset && (percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error"),
8540
8576
  animated && "transition-all duration-300"
8541
8577
  ),
@@ -8549,10 +8585,11 @@ function HealthBar({
8549
8585
  );
8550
8586
  }
8551
8587
  if (format === "progress") {
8552
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), children: [
8588
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex items-center gap-2", className), children: [
8553
8589
  level != null && /* @__PURE__ */ jsxRuntime.jsxs(
8554
- "span",
8590
+ Typography,
8555
8591
  {
8592
+ as: "span",
8556
8593
  className: cn(
8557
8594
  "flex-shrink-0 rounded-interactive font-bold",
8558
8595
  "bg-accent text-accent-foreground border border-accent",
@@ -8564,21 +8601,23 @@ function HealthBar({
8564
8601
  ]
8565
8602
  }
8566
8603
  ),
8567
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [
8604
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 flex flex-col gap-0.5", children: [
8568
8605
  /* @__PURE__ */ jsxRuntime.jsx(
8569
- "div",
8606
+ Box,
8570
8607
  {
8608
+ position: "relative",
8571
8609
  className: cn(
8572
- "relative w-full overflow-hidden rounded-full",
8610
+ "w-full overflow-hidden rounded-full",
8573
8611
  !frameAsset && "bg-muted border border-muted",
8574
8612
  sizes.bar
8575
8613
  ),
8576
8614
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
8577
8615
  children: /* @__PURE__ */ jsxRuntime.jsx(
8578
- "div",
8616
+ Box,
8579
8617
  {
8618
+ position: "absolute",
8580
8619
  className: cn(
8581
- "absolute inset-y-0 left-0 rounded-full",
8620
+ "inset-y-0 left-0 rounded-full",
8582
8621
  !fillAsset && "bg-gradient-to-r from-accent to-info",
8583
8622
  animated && "transition-all duration-500 ease-out"
8584
8623
  ),
@@ -8590,7 +8629,7 @@ function HealthBar({
8590
8629
  )
8591
8630
  }
8592
8631
  ),
8593
- showLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
8632
+ showLabel && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
8594
8633
  current,
8595
8634
  " / ",
8596
8635
  max,
@@ -8599,16 +8638,18 @@ function HealthBar({
8599
8638
  ] })
8600
8639
  ] });
8601
8640
  }
8602
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
8641
+ return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-mono font-bold", sizes.text, className), children: [
8603
8642
  current,
8604
8643
  "/",
8605
8644
  max
8606
8645
  ] });
8607
8646
  }
8608
- var heartIcon, sizeMap;
8647
+ var heartIcon, sizeMap2;
8609
8648
  var init_HealthBar = __esm({
8610
8649
  "components/game/2d/atoms/HealthBar.tsx"() {
8611
8650
  init_cn();
8651
+ init_Box();
8652
+ init_Typography();
8612
8653
  heartIcon = (filled, size) => /* @__PURE__ */ jsxRuntime.jsx(
8613
8654
  "svg",
8614
8655
  {
@@ -8620,7 +8661,7 @@ var init_HealthBar = __esm({
8620
8661
  children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" })
8621
8662
  }
8622
8663
  );
8623
- sizeMap = {
8664
+ sizeMap2 = {
8624
8665
  sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm", label: "text-xs", badge: "text-xs px-1.5 py-0.5" },
8625
8666
  md: { heart: "w-6 h-6", bar: "h-3", text: "text-base", label: "text-xs", badge: "text-xs px-2 py-0.5" },
8626
8667
  lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg", label: "text-sm", badge: "text-sm px-2.5 py-1" }
@@ -8641,37 +8682,30 @@ function ScoreDisplay({
8641
8682
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
8642
8683
  const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
8643
8684
  return /* @__PURE__ */ jsxRuntime.jsxs(
8644
- "div",
8685
+ Box,
8645
8686
  {
8646
8687
  className: cn(
8647
8688
  "flex items-center gap-2 font-bold",
8648
- sizeMap2[size],
8689
+ sizeMap3[size],
8649
8690
  className
8650
8691
  ),
8651
8692
  children: [
8652
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
8653
- "img",
8654
- {
8655
- src: assetUrl.url,
8656
- alt: "",
8657
- width: 20,
8658
- height: 20,
8659
- style: { imageRendering: "pixelated", objectFit: "contain" },
8660
- className: "flex-shrink-0"
8661
- }
8662
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
8663
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
8664
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: formattedValue })
8693
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 20, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
8694
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
8695
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "tabular-nums", children: formattedValue })
8665
8696
  ]
8666
8697
  }
8667
8698
  );
8668
8699
  }
8669
- var sizeMap2, DEFAULT_ASSET_URL;
8700
+ var sizeMap3, DEFAULT_ASSET_URL;
8670
8701
  var init_ScoreDisplay = __esm({
8671
8702
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
8672
8703
  init_cn();
8673
8704
  init_Icon();
8674
- sizeMap2 = {
8705
+ init_Box();
8706
+ init_Typography();
8707
+ init_GameIcon();
8708
+ sizeMap3 = {
8675
8709
  sm: "text-sm",
8676
8710
  md: "text-lg",
8677
8711
  lg: "text-2xl",
@@ -8734,9 +8768,9 @@ function ControlButton({
8734
8768
  [isPressed, releaseEvent, eventBus, onRelease]
8735
8769
  );
8736
8770
  return /* @__PURE__ */ jsxRuntime.jsx(
8737
- "button",
8771
+ Button,
8738
8772
  {
8739
- type: "button",
8773
+ variant,
8740
8774
  disabled,
8741
8775
  onPointerDown: handlePointerDown,
8742
8776
  onPointerUp: handlePointerUp,
@@ -8747,41 +8781,35 @@ function ControlButton({
8747
8781
  "select-none touch-none",
8748
8782
  "transition-all duration-100",
8749
8783
  "active:scale-95",
8750
- sizeMap3[size] ?? sizeMap3.md,
8784
+ sizeMap4[size] ?? sizeMap4.md,
8751
8785
  shapeMap[shape] ?? shapeMap.circle,
8752
8786
  variantMap[variant] ?? variantMap.secondary,
8753
8787
  actualPressed && "scale-95 brightness-110 border-foreground",
8754
8788
  disabled && "opacity-50 cursor-not-allowed",
8755
8789
  className
8756
8790
  ),
8757
- children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
8758
- "img",
8759
- {
8760
- src: assetUrl.url,
8761
- alt: "",
8762
- width: 24,
8763
- height: 24,
8764
- style: { imageRendering: "pixelated", objectFit: "contain" },
8765
- className: "flex-shrink-0"
8766
- }
8767
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
8791
+ children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
8768
8792
  const I = resolveIcon(icon);
8769
8793
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" }) : null;
8770
8794
  })() : icon : /* @__PURE__ */ (() => {
8771
8795
  const I = icon;
8772
8796
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" });
8773
- })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }) : null
8797
+ })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: label }) : null
8774
8798
  }
8775
8799
  );
8776
8800
  }
8777
- var sizeMap3, shapeMap, variantMap, DEFAULT_ASSET_URL2;
8801
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
8778
8802
  var init_ControlButton = __esm({
8779
8803
  "components/game/2d/atoms/ControlButton.tsx"() {
8780
8804
  "use client";
8781
8805
  init_cn();
8782
8806
  init_useEventBus();
8783
8807
  init_Icon();
8784
- sizeMap3 = {
8808
+ init_Button();
8809
+ init_Box();
8810
+ init_Typography();
8811
+ init_GameIcon();
8812
+ sizeMap4 = {
8785
8813
  sm: "w-10 h-10 text-sm",
8786
8814
  md: "w-14 h-14 text-base",
8787
8815
  lg: "w-18 h-18 text-lg",
@@ -8851,12 +8879,12 @@ function Sprite({
8851
8879
  onClick?.();
8852
8880
  };
8853
8881
  return /* @__PURE__ */ jsxRuntime.jsx(
8854
- "div",
8882
+ Box,
8855
8883
  {
8884
+ position: "absolute",
8856
8885
  className,
8857
8886
  onClick: action || onClick ? handleClick : void 0,
8858
8887
  style: {
8859
- position: "absolute",
8860
8888
  width: frameWidth,
8861
8889
  height: frameHeight,
8862
8890
  backgroundImage: `url(${spritesheet.url})`,
@@ -8877,6 +8905,7 @@ var init_Sprite = __esm({
8877
8905
  "components/game/2d/atoms/Sprite.tsx"() {
8878
8906
  "use client";
8879
8907
  init_useEventBus();
8908
+ init_Box();
8880
8909
  init_spriteAnimation();
8881
8910
  DEFAULT_SPRITESHEET = {
8882
8911
  url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
@@ -8913,17 +8942,7 @@ function StateIndicator({
8913
8942
  className
8914
8943
  ),
8915
8944
  children: [
8916
- /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
8917
- "img",
8918
- {
8919
- src: assetUrl.url,
8920
- alt: displayLabel,
8921
- width: 16,
8922
- height: 16,
8923
- style: { imageRendering: "pixelated", objectFit: "contain" },
8924
- className: "flex-shrink-0"
8925
- }
8926
- ) : typeof config.icon === "string" ? /^[a-zA-Z0-9-]+$/.test(config.icon) ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: config.icon }) : config.icon : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: config.icon }) }),
8945
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 16, alt: displayLabel, className: "flex-shrink-0" }) : typeof config.icon === "string" ? /^[a-zA-Z0-9-]+$/.test(config.icon) ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: config.icon }) : config.icon : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: config.icon }) }),
8927
8946
  /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: displayLabel })
8928
8947
  ]
8929
8948
  }
@@ -8935,6 +8954,7 @@ var init_StateIndicator = __esm({
8935
8954
  init_Box();
8936
8955
  init_Icon();
8937
8956
  init_cn();
8957
+ init_GameIcon();
8938
8958
  DEFAULT_ASSET_URL3 = {
8939
8959
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
8940
8960
  role: "ui",
@@ -8988,29 +9008,31 @@ function TimerDisplay({
8988
9008
  }) {
8989
9009
  const isLow = lowThreshold != null && seconds <= lowThreshold && seconds > 0;
8990
9010
  return /* @__PURE__ */ jsxRuntime.jsxs(
8991
- "div",
9011
+ Box,
8992
9012
  {
8993
9013
  className: cn(
8994
9014
  "inline-flex items-center gap-1 justify-center rounded-container",
8995
9015
  "bg-card/80 border border-muted font-mono font-bold tabular-nums",
8996
- sizeMap4[size],
9016
+ sizeMap5[size],
8997
9017
  running && "border-success/50",
8998
9018
  isLow && "text-error border-error/50 animate-pulse",
8999
9019
  !isLow && "text-foreground",
9000
9020
  className
9001
9021
  ),
9002
9022
  children: [
9003
- iconAsset && /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconAsset.url, alt: "", className: "w-4 h-4 object-contain flex-shrink-0" }),
9023
+ iconAsset && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: iconAsset, icon: "image", size: 16, className: "w-4 h-4 object-contain flex-shrink-0" }),
9004
9024
  formatTime(seconds, format)
9005
9025
  ]
9006
9026
  }
9007
9027
  );
9008
9028
  }
9009
- var sizeMap4;
9029
+ var sizeMap5;
9010
9030
  var init_TimerDisplay = __esm({
9011
9031
  "components/game/2d/atoms/TimerDisplay.tsx"() {
9012
9032
  init_cn();
9013
- sizeMap4 = {
9033
+ init_Box();
9034
+ init_GameIcon();
9035
+ sizeMap5 = {
9014
9036
  sm: "text-sm px-2 py-0.5",
9015
9037
  md: "text-lg px-3 py-1",
9016
9038
  lg: "text-2xl px-4 py-1.5"
@@ -9028,9 +9050,9 @@ function ResourceCounter({
9028
9050
  size = "md",
9029
9051
  className
9030
9052
  }) {
9031
- const sizes = sizeMap5[size];
9053
+ const sizes = sizeMap6[size];
9032
9054
  return /* @__PURE__ */ jsxRuntime.jsxs(
9033
- "div",
9055
+ Box,
9034
9056
  {
9035
9057
  className: cn(
9036
9058
  "inline-flex items-center rounded-container",
@@ -9039,21 +9061,11 @@ function ResourceCounter({
9039
9061
  className
9040
9062
  ),
9041
9063
  children: [
9042
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9043
- "img",
9044
- {
9045
- src: assetUrl.url,
9046
- alt: label,
9047
- width: sizes.img,
9048
- height: sizes.img,
9049
- style: { imageRendering: "pixelated", objectFit: "contain" },
9050
- className: "flex-shrink-0"
9051
- }
9052
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9053
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
9054
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
9064
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9065
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
9066
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
9055
9067
  value,
9056
- max != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9068
+ max != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9057
9069
  "/",
9058
9070
  max
9059
9071
  ] })
@@ -9062,11 +9074,14 @@ function ResourceCounter({
9062
9074
  }
9063
9075
  );
9064
9076
  }
9065
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap5;
9077
+ var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
9066
9078
  var init_ResourceCounter = __esm({
9067
9079
  "components/game/2d/atoms/ResourceCounter.tsx"() {
9068
9080
  init_cn();
9069
9081
  init_Icon();
9082
+ init_Box();
9083
+ init_Typography();
9084
+ init_GameIcon();
9070
9085
  colorTokenClasses2 = {
9071
9086
  primary: "text-primary",
9072
9087
  secondary: "text-secondary",
@@ -9080,7 +9095,7 @@ var init_ResourceCounter = __esm({
9080
9095
  role: "ui",
9081
9096
  category: "coin"
9082
9097
  };
9083
- sizeMap5 = {
9098
+ sizeMap6 = {
9084
9099
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
9085
9100
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
9086
9101
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -9105,9 +9120,9 @@ function ItemSlot({
9105
9120
  const isClickable = onClick != null || action != null;
9106
9121
  const px = assetSizeMap[size];
9107
9122
  return /* @__PURE__ */ jsxRuntime.jsx(
9108
- "button",
9123
+ Button,
9109
9124
  {
9110
- type: "button",
9125
+ variant: "ghost",
9111
9126
  onClick: () => {
9112
9127
  if (action) eventBus.emit(`UI:${action}`, {});
9113
9128
  onClick?.();
@@ -9117,7 +9132,7 @@ function ItemSlot({
9117
9132
  className: cn(
9118
9133
  "relative flex items-center justify-center rounded-interactive border-2",
9119
9134
  "bg-card/80 transition-all duration-150",
9120
- sizeMap6[size],
9135
+ sizeMap7[size],
9121
9136
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
9122
9137
  !empty && rarityGlowMap[rarity],
9123
9138
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -9126,21 +9141,12 @@ function ItemSlot({
9126
9141
  !isClickable && "cursor-default",
9127
9142
  className
9128
9143
  ),
9129
- children: empty ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9130
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9131
- "img",
9132
- {
9133
- src: assetUrl?.url,
9134
- alt: label,
9135
- width: px,
9136
- height: px,
9137
- style: { imageRendering: "pixelated", objectFit: "contain" },
9138
- className: "flex-shrink-0"
9139
- }
9140
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9144
+ children: empty ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9145
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: px, alt: label, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9141
9146
  quantity != null && quantity > 1 && /* @__PURE__ */ jsxRuntime.jsx(
9142
- "span",
9147
+ Typography,
9143
9148
  {
9149
+ as: "span",
9144
9150
  className: cn(
9145
9151
  "absolute -bottom-1 -right-1 flex items-center justify-center",
9146
9152
  "min-w-[18px] h-[18px] rounded-full px-1",
@@ -9153,14 +9159,18 @@ function ItemSlot({
9153
9159
  }
9154
9160
  );
9155
9161
  }
9156
- var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9162
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9157
9163
  var init_ItemSlot = __esm({
9158
9164
  "components/game/2d/atoms/ItemSlot.tsx"() {
9159
9165
  "use client";
9160
9166
  init_cn();
9161
9167
  init_Icon();
9162
9168
  init_useEventBus();
9163
- sizeMap6 = {
9169
+ init_Button();
9170
+ init_Box();
9171
+ init_Typography();
9172
+ init_GameIcon();
9173
+ sizeMap7 = {
9164
9174
  sm: "w-10 h-10 text-lg",
9165
9175
  md: "w-14 h-14 text-2xl",
9166
9176
  lg: "w-18 h-18 text-3xl"
@@ -9201,9 +9211,9 @@ function TurnIndicator({
9201
9211
  size = "md",
9202
9212
  className
9203
9213
  }) {
9204
- const sizes = sizeMap7[size];
9214
+ const sizes = sizeMap8[size];
9205
9215
  return /* @__PURE__ */ jsxRuntime.jsxs(
9206
- "div",
9216
+ Box,
9207
9217
  {
9208
9218
  className: cn(
9209
9219
  "inline-flex items-center rounded-container",
@@ -9212,42 +9222,35 @@ function TurnIndicator({
9212
9222
  className
9213
9223
  ),
9214
9224
  children: [
9215
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold tabular-nums", children: [
9225
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "font-bold tabular-nums", children: [
9216
9226
  "Turn ",
9217
9227
  currentTurn,
9218
- maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9228
+ maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9219
9229
  "/",
9220
9230
  maxTurns
9221
9231
  ] })
9222
9232
  ] }),
9223
9233
  phase && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9224
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
9225
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: phase })
9234
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9235
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: phase })
9226
9236
  ] }),
9227
9237
  activeTeam && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9228
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
9229
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9230
- "img",
9231
- {
9232
- src: assetUrl.url,
9233
- alt: "",
9234
- width: 12,
9235
- height: 12,
9236
- style: { imageRendering: "pixelated", objectFit: "contain" },
9237
- className: "flex-shrink-0"
9238
- }
9239
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full bg-success/20", sizes.dot) }),
9240
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-success", children: activeTeam })
9238
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9239
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 12, className: "flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("rounded-full bg-success/20", sizes.dot) }),
9240
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-success", children: activeTeam })
9241
9241
  ] })
9242
9242
  ]
9243
9243
  }
9244
9244
  );
9245
9245
  }
9246
- var sizeMap7, DEFAULT_ASSET_URL6;
9246
+ var sizeMap8, DEFAULT_ASSET_URL6;
9247
9247
  var init_TurnIndicator = __esm({
9248
9248
  "components/game/2d/atoms/TurnIndicator.tsx"() {
9249
9249
  init_cn();
9250
- sizeMap7 = {
9250
+ init_Box();
9251
+ init_Typography();
9252
+ init_GameIcon();
9253
+ sizeMap8 = {
9251
9254
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
9252
9255
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
9253
9256
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
@@ -9279,10 +9282,10 @@ function ComboCounter({
9279
9282
  size = "md",
9280
9283
  className
9281
9284
  }) {
9282
- const sizes = sizeMap8[size];
9285
+ const sizes = sizeMap9[size];
9283
9286
  if (combo <= 0) return null;
9284
9287
  return /* @__PURE__ */ jsxRuntime.jsxs(
9285
- "div",
9288
+ Box,
9286
9289
  {
9287
9290
  className: cn(
9288
9291
  "inline-flex flex-col items-center justify-center",
@@ -9292,24 +9295,14 @@ function ComboCounter({
9292
9295
  className
9293
9296
  ),
9294
9297
  children: [
9295
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
9296
- "img",
9297
- {
9298
- src: assetUrl.url,
9299
- alt: "combo",
9300
- width: 24,
9301
- height: 24,
9302
- style: { imageRendering: "pixelated", objectFit: "contain" },
9303
- className: "flex-shrink-0 mb-0.5"
9304
- }
9305
- ),
9306
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
9307
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
9308
- multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
9298
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0 mb-0.5" }),
9299
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
9300
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
9301
+ multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
9309
9302
  "x",
9310
9303
  multiplier.toFixed(1)
9311
9304
  ] }),
9312
- streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9305
+ streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9313
9306
  streak,
9314
9307
  " streak"
9315
9308
  ] })
@@ -9317,16 +9310,19 @@ function ComboCounter({
9317
9310
  }
9318
9311
  );
9319
9312
  }
9320
- var DEFAULT_ASSET_URL7, sizeMap8;
9313
+ var DEFAULT_ASSET_URL7, sizeMap9;
9321
9314
  var init_ComboCounter = __esm({
9322
9315
  "components/game/2d/atoms/ComboCounter.tsx"() {
9323
9316
  init_cn();
9317
+ init_Box();
9318
+ init_Typography();
9319
+ init_GameIcon();
9324
9320
  DEFAULT_ASSET_URL7 = {
9325
9321
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
9326
9322
  role: "effect",
9327
9323
  category: "effect"
9328
9324
  };
9329
- sizeMap8 = {
9325
+ sizeMap9 = {
9330
9326
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
9331
9327
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
9332
9328
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -9343,54 +9339,48 @@ function WaypointMarker({
9343
9339
  size = "md",
9344
9340
  className
9345
9341
  }) {
9346
- const sizes = sizeMap9[size];
9347
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center", className), children: [
9348
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
9342
+ const sizes = sizeMap10[size];
9343
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col items-center", className), children: [
9344
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative flex items-center justify-center", children: [
9349
9345
  active && /* @__PURE__ */ jsxRuntime.jsx(
9350
- "div",
9346
+ Box,
9351
9347
  {
9348
+ position: "absolute",
9352
9349
  className: cn(
9353
- "absolute rounded-full border-2 border-info animate-ping opacity-50",
9350
+ "rounded-full border-2 border-info animate-ping opacity-50",
9354
9351
  sizes.ring
9355
9352
  )
9356
9353
  }
9357
9354
  ),
9358
9355
  active && /* @__PURE__ */ jsxRuntime.jsx(
9359
- "div",
9356
+ Box,
9360
9357
  {
9358
+ position: "absolute",
9361
9359
  className: cn(
9362
- "absolute rounded-full border-2 border-info",
9360
+ "rounded-full border-2 border-info",
9363
9361
  sizes.ring
9364
9362
  )
9365
9363
  }
9366
9364
  ),
9367
9365
  /* @__PURE__ */ jsxRuntime.jsx(
9368
- "div",
9366
+ Box,
9369
9367
  {
9368
+ position: "relative",
9370
9369
  className: cn(
9371
- "relative flex items-center justify-center rounded-full transition-all duration-200",
9370
+ "flex items-center justify-center rounded-full transition-all duration-200",
9372
9371
  sizes.dot,
9373
9372
  completed && "bg-success text-foreground",
9374
9373
  active && !completed && "bg-info text-foreground",
9375
9374
  !active && !completed && "bg-muted"
9376
9375
  ),
9377
- children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9378
- "img",
9379
- {
9380
- src: assetUrl.url,
9381
- alt: label,
9382
- width: sizes.img,
9383
- height: sizes.img,
9384
- style: { imageRendering: "pixelated", objectFit: "contain" },
9385
- className: "flex-shrink-0"
9386
- }
9387
- ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) : null
9376
+ children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) : null
9388
9377
  }
9389
9378
  )
9390
9379
  ] }),
9391
9380
  label && /* @__PURE__ */ jsxRuntime.jsx(
9392
- "span",
9381
+ Typography,
9393
9382
  {
9383
+ as: "span",
9394
9384
  className: cn(
9395
9385
  "text-center whitespace-nowrap",
9396
9386
  sizes.label,
@@ -9401,17 +9391,20 @@ function WaypointMarker({
9401
9391
  )
9402
9392
  ] });
9403
9393
  }
9404
- var DEFAULT_ASSET_URL8, sizeMap9, checkIcon;
9394
+ var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
9405
9395
  var init_WaypointMarker = __esm({
9406
9396
  "components/game/2d/atoms/WaypointMarker.tsx"() {
9407
9397
  init_cn();
9408
9398
  init_Icon();
9399
+ init_Box();
9400
+ init_Typography();
9401
+ init_GameIcon();
9409
9402
  DEFAULT_ASSET_URL8 = {
9410
9403
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
9411
9404
  role: "ui",
9412
9405
  category: "waypoint"
9413
9406
  };
9414
- sizeMap9 = {
9407
+ sizeMap10 = {
9415
9408
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
9416
9409
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
9417
9410
  lg: { dot: "w-8 h-8", ring: "w-10 h-10", label: "text-base mt-2", img: 24 }
@@ -9436,32 +9429,24 @@ function StatusEffect({
9436
9429
  size = "md",
9437
9430
  className
9438
9431
  }) {
9439
- const sizes = sizeMap10[size];
9440
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
9432
+ const sizes = sizeMap11[size];
9433
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn("inline-flex flex-col items-center", className), children: [
9441
9434
  /* @__PURE__ */ jsxRuntime.jsxs(
9442
- "div",
9435
+ Box,
9443
9436
  {
9437
+ position: "relative",
9444
9438
  className: cn(
9445
- "relative flex items-center justify-center rounded-interactive border-2",
9439
+ "flex items-center justify-center rounded-interactive border-2",
9446
9440
  sizes.container,
9447
9441
  variantStyles7[variant]
9448
9442
  ),
9449
9443
  title: label,
9450
9444
  children: [
9451
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9452
- "img",
9453
- {
9454
- src: assetUrl.url,
9455
- alt: label,
9456
- width: sizes.img,
9457
- height: sizes.img,
9458
- style: { imageRendering: "pixelated", objectFit: "contain" },
9459
- className: "flex-shrink-0"
9460
- }
9461
- ) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, size: "sm" }) : null }),
9445
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, size: "sm" }) : null }),
9462
9446
  duration !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
9463
- "span",
9447
+ Typography,
9464
9448
  {
9449
+ as: "span",
9465
9450
  className: cn(
9466
9451
  "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
9467
9452
  sizes.timer
@@ -9473,8 +9458,9 @@ function StatusEffect({
9473
9458
  }
9474
9459
  ),
9475
9460
  stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsxRuntime.jsx(
9476
- "span",
9461
+ Typography,
9477
9462
  {
9463
+ as: "span",
9478
9464
  className: cn(
9479
9465
  "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
9480
9466
  sizes.badge
@@ -9482,20 +9468,23 @@ function StatusEffect({
9482
9468
  children: stacks
9483
9469
  }
9484
9470
  ),
9485
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
9471
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
9486
9472
  ] });
9487
9473
  }
9488
- var DEFAULT_ASSET_URL9, sizeMap10, variantStyles7;
9474
+ var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
9489
9475
  var init_StatusEffect = __esm({
9490
9476
  "components/game/2d/atoms/StatusEffect.tsx"() {
9491
9477
  init_cn();
9492
9478
  init_Icon();
9479
+ init_Box();
9480
+ init_Typography();
9481
+ init_GameIcon();
9493
9482
  DEFAULT_ASSET_URL9 = {
9494
9483
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
9495
9484
  role: "ui",
9496
9485
  category: "effect"
9497
9486
  };
9498
- sizeMap10 = {
9487
+ sizeMap11 = {
9499
9488
  sm: { container: "w-8 h-8", icon: "text-sm", badge: "text-xs -top-1 -right-1 w-4 h-4", timer: "text-[9px]", img: 20 },
9500
9489
  md: { container: "w-10 h-10", icon: "text-base", badge: "text-xs -top-1 -right-1 w-5 h-5", timer: "text-xs", img: 28 },
9501
9490
  lg: { container: "w-12 h-12", icon: "text-lg", badge: "text-sm -top-1.5 -right-1.5 w-6 h-6", timer: "text-xs", img: 36 }
@@ -9519,38 +9508,31 @@ function DamageNumber({
9519
9508
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9520
9509
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: floatKeyframes }),
9521
9510
  /* @__PURE__ */ jsxRuntime.jsxs(
9522
- "span",
9511
+ Typography,
9523
9512
  {
9513
+ as: "span",
9524
9514
  className: cn(
9525
9515
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
9526
- sizeMap11[size],
9516
+ sizeMap12[size],
9527
9517
  typeStyles[type],
9528
9518
  className
9529
9519
  ),
9530
9520
  style: { animation: "damageFloat 1s ease-out forwards" },
9531
9521
  children: [
9532
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
9533
- "img",
9534
- {
9535
- src: assetUrl.url,
9536
- alt: "",
9537
- width: 14,
9538
- height: 14,
9539
- style: { imageRendering: "pixelated", objectFit: "contain" },
9540
- className: "flex-shrink-0"
9541
- }
9542
- ),
9522
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 14, className: "flex-shrink-0" }),
9543
9523
  displayText
9544
9524
  ]
9545
9525
  }
9546
9526
  )
9547
9527
  ] });
9548
9528
  }
9549
- var sizeMap11, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
9529
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
9550
9530
  var init_DamageNumber = __esm({
9551
9531
  "components/game/2d/atoms/DamageNumber.tsx"() {
9552
9532
  init_cn();
9553
- sizeMap11 = {
9533
+ init_Typography();
9534
+ init_GameIcon();
9535
+ sizeMap12 = {
9554
9536
  sm: "text-sm",
9555
9537
  md: "text-lg",
9556
9538
  lg: "text-2xl"
@@ -9584,7 +9566,7 @@ function DialogueBubble({
9584
9566
  className
9585
9567
  }) {
9586
9568
  return /* @__PURE__ */ jsxRuntime.jsxs(
9587
- "div",
9569
+ Box,
9588
9570
  {
9589
9571
  className: cn(
9590
9572
  "flex items-start gap-3 rounded-container bg-background/80 backdrop-blur-sm px-4 py-3 border border-border/10",
@@ -9592,17 +9574,10 @@ function DialogueBubble({
9592
9574
  className
9593
9575
  ),
9594
9576
  children: [
9595
- portrait && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsxRuntime.jsx(
9596
- "img",
9597
- {
9598
- src: portrait?.url,
9599
- alt: speaker ?? "speaker",
9600
- className: "w-full h-full object-cover"
9601
- }
9602
- ) }),
9603
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [
9604
- speaker && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold text-warning", children: speaker }),
9605
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground leading-relaxed", children: text })
9577
+ portrait && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: portrait, icon: "image", size: 48, alt: speaker ?? "speaker", className: "w-full h-full object-cover" }) }),
9578
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-1 min-w-0", children: [
9579
+ speaker && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm font-bold text-warning", children: speaker }),
9580
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm text-foreground leading-relaxed", children: text })
9606
9581
  ] })
9607
9582
  ]
9608
9583
  }
@@ -9612,6 +9587,9 @@ var DEFAULT_PORTRAIT;
9612
9587
  var init_DialogueBubble = __esm({
9613
9588
  "components/game/2d/atoms/DialogueBubble.tsx"() {
9614
9589
  init_cn();
9590
+ init_Box();
9591
+ init_Typography();
9592
+ init_GameIcon();
9615
9593
  DEFAULT_PORTRAIT = {
9616
9594
  url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
9617
9595
  role: "effect",
@@ -9633,11 +9611,11 @@ function ChoiceButton({
9633
9611
  }) {
9634
9612
  const eventBus = useEventBus();
9635
9613
  return /* @__PURE__ */ jsxRuntime.jsxs(
9636
- "button",
9614
+ Button,
9637
9615
  {
9638
- type: "button",
9616
+ variant: "ghost",
9639
9617
  disabled,
9640
- onClick: (e) => {
9618
+ onClick: () => {
9641
9619
  if (action) eventBus.emit(`UI:${action}`, {});
9642
9620
  onClick?.();
9643
9621
  },
@@ -9650,8 +9628,9 @@ function ChoiceButton({
9650
9628
  ),
9651
9629
  children: [
9652
9630
  index !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(
9653
- "span",
9631
+ Typography,
9654
9632
  {
9633
+ as: "span",
9655
9634
  className: cn(
9656
9635
  "flex-shrink-0 font-mono font-bold text-sm",
9657
9636
  selected ? "text-accent" : "text-muted-foreground"
@@ -9662,24 +9641,14 @@ function ChoiceButton({
9662
9641
  ]
9663
9642
  }
9664
9643
  ),
9665
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9666
- "img",
9667
- {
9668
- src: assetUrl.url,
9669
- alt: "",
9670
- width: 16,
9671
- height: 16,
9672
- style: { imageRendering: "pixelated", objectFit: "contain" },
9673
- className: "flex-shrink-0"
9674
- }
9675
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
9644
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
9676
9645
  const I = resolveIcon(icon);
9677
9646
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
9678
9647
  })() : /* @__PURE__ */ (() => {
9679
9648
  const I = icon;
9680
9649
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
9681
9650
  })() }) : null,
9682
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-snug", children: text })
9651
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm leading-snug", children: text })
9683
9652
  ]
9684
9653
  }
9685
9654
  );
@@ -9689,6 +9658,10 @@ var init_ChoiceButton = __esm({
9689
9658
  init_cn();
9690
9659
  init_Icon();
9691
9660
  init_useEventBus();
9661
+ init_Button();
9662
+ init_Box();
9663
+ init_Typography();
9664
+ init_GameIcon();
9692
9665
  ChoiceButton.displayName = "ChoiceButton";
9693
9666
  }
9694
9667
  });
@@ -9706,16 +9679,16 @@ function ActionButton({
9706
9679
  className
9707
9680
  }) {
9708
9681
  const eventBus = useEventBus();
9709
- const sizes = sizeMap12[size];
9682
+ const sizes = sizeMap13[size];
9710
9683
  const onCooldown = cooldown > 0;
9711
9684
  const isDisabled = disabled || onCooldown;
9712
9685
  const cooldownDeg = Math.round(cooldown * 360);
9713
9686
  return /* @__PURE__ */ jsxRuntime.jsxs(
9714
- "button",
9687
+ Button,
9715
9688
  {
9716
- type: "button",
9689
+ variant: variant === "danger" ? "danger" : variant === "secondary" ? "secondary" : "primary",
9717
9690
  disabled: isDisabled,
9718
- onClick: (e) => {
9691
+ onClick: () => {
9719
9692
  if (action) eventBus.emit(`UI:${action}`, {});
9720
9693
  onClick?.();
9721
9694
  },
@@ -9728,9 +9701,10 @@ function ActionButton({
9728
9701
  ),
9729
9702
  children: [
9730
9703
  onCooldown && /* @__PURE__ */ jsxRuntime.jsx(
9731
- "div",
9704
+ Box,
9732
9705
  {
9733
- className: "absolute inset-0 bg-foreground/40 pointer-events-none",
9706
+ position: "absolute",
9707
+ className: "inset-0 bg-foreground/40 pointer-events-none",
9734
9708
  style: {
9735
9709
  clipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
9736
9710
  WebkitClipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
@@ -9738,27 +9712,18 @@ function ActionButton({
9738
9712
  }
9739
9713
  }
9740
9714
  ),
9741
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9742
- "img",
9743
- {
9744
- src: assetUrl.url,
9745
- alt: "",
9746
- width: 16,
9747
- height: 16,
9748
- style: { imageRendering: "pixelated", objectFit: "contain" },
9749
- className: cn("flex-shrink-0", sizes.icon)
9750
- }
9751
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
9715
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 16, className: cn("flex-shrink-0", sizes.icon) }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
9752
9716
  const I = resolveIcon(icon);
9753
9717
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
9754
9718
  })() : /* @__PURE__ */ (() => {
9755
9719
  const I = icon;
9756
9720
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
9757
9721
  })() }) : null,
9758
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10", children: label }),
9722
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "relative z-10", children: label }),
9759
9723
  hotkey && /* @__PURE__ */ jsxRuntime.jsx(
9760
- "span",
9724
+ Typography,
9761
9725
  {
9726
+ as: "span",
9762
9727
  className: cn(
9763
9728
  "absolute top-0.5 right-0.5 bg-foreground/30 text-primary-foreground rounded font-mono leading-tight",
9764
9729
  sizes.hotkey
@@ -9770,13 +9735,17 @@ function ActionButton({
9770
9735
  }
9771
9736
  );
9772
9737
  }
9773
- var sizeMap12, variantStyles8, DEFAULT_ASSET_URL11;
9738
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
9774
9739
  var init_ActionButton = __esm({
9775
9740
  "components/game/2d/atoms/ActionButton.tsx"() {
9776
9741
  init_cn();
9777
9742
  init_Icon();
9778
9743
  init_useEventBus();
9779
- sizeMap12 = {
9744
+ init_Button();
9745
+ init_Box();
9746
+ init_Typography();
9747
+ init_GameIcon();
9748
+ sizeMap13 = {
9780
9749
  sm: { button: "h-button-sm px-3 text-xs", hotkey: "text-[9px] px-1", icon: "text-xs" },
9781
9750
  md: { button: "h-button-md px-4 text-sm", hotkey: "text-xs px-1.5", icon: "text-sm" },
9782
9751
  lg: { button: "h-button-lg px-5 text-base", hotkey: "text-xs px-2", icon: "text-base" }
@@ -9878,10 +9847,12 @@ function MiniMap({
9878
9847
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9879
9848
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes minimap-blink{0%,49%{opacity:1}50%,100%{opacity:0}}` }),
9880
9849
  /* @__PURE__ */ jsxRuntime.jsxs(
9881
- "div",
9850
+ Box,
9882
9851
  {
9852
+ position: "relative",
9853
+ display: "inline-block",
9883
9854
  className: cn(
9884
- "relative inline-block border border-border/20 rounded-container",
9855
+ "border border-border/20 rounded-container",
9885
9856
  className
9886
9857
  ),
9887
9858
  children: [
@@ -9896,10 +9867,10 @@ function MiniMap({
9896
9867
  }
9897
9868
  ),
9898
9869
  playerLeft !== null && playerTop !== null && /* @__PURE__ */ jsxRuntime.jsx(
9899
- "div",
9870
+ Box,
9900
9871
  {
9872
+ position: "absolute",
9901
9873
  style: {
9902
- position: "absolute",
9903
9874
  left: playerLeft,
9904
9875
  top: playerTop,
9905
9876
  width: 3,
@@ -9920,6 +9891,7 @@ var init_MiniMap = __esm({
9920
9891
  "components/game/2d/atoms/MiniMap.tsx"() {
9921
9892
  "use client";
9922
9893
  init_cn();
9894
+ init_Box();
9923
9895
  DEFAULT_TILES = [
9924
9896
  { x: 10, y: 10, color: "#4ade80" },
9925
9897
  { x: 20, y: 15, color: "#4ade80" },
@@ -9937,38 +9909,6 @@ var init_MiniMap = __esm({
9937
9909
  MiniMap.displayName = "MiniMap";
9938
9910
  }
9939
9911
  });
9940
- function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
9941
- const px = typeof size === "number" ? size : sizeMap13[size];
9942
- if (assetUrl?.url) {
9943
- return /* @__PURE__ */ jsxRuntime.jsx(
9944
- "img",
9945
- {
9946
- src: assetUrl.url,
9947
- alt: alt ?? assetUrl.category ?? "",
9948
- width: px,
9949
- height: px,
9950
- style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
9951
- className: cn("flex-shrink-0", className)
9952
- }
9953
- );
9954
- }
9955
- const I = typeof icon === "string" ? resolveIcon(icon) : icon;
9956
- return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
9957
- }
9958
- var sizeMap13;
9959
- var init_GameIcon = __esm({
9960
- "components/game/2d/atoms/GameIcon.tsx"() {
9961
- "use client";
9962
- init_cn();
9963
- init_Icon();
9964
- sizeMap13 = {
9965
- sm: 16,
9966
- md: 24,
9967
- lg: 32
9968
- };
9969
- GameIcon.displayName = "GameIcon";
9970
- }
9971
- });
9972
9912
  function ControlGrid({
9973
9913
  kind,
9974
9914
  buttons = DEFAULT_BUTTONS,
@@ -10029,22 +9969,22 @@ function ControlGrid({
10029
9969
  },
10030
9970
  d
10031
9971
  );
10032
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
10033
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9972
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
9973
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10034
9974
  dir("up"),
10035
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9975
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10036
9976
  dir("left"),
10037
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
9977
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
10038
9978
  dir("right"),
10039
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9979
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10040
9980
  dir("down"),
10041
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
9981
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10042
9982
  ] });
10043
9983
  }
10044
9984
  if (layout === "diamond" && buttons.length === 4) {
10045
9985
  const [top, right, bottom, left] = buttons;
10046
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(layoutClass.diamond, className), children: [
10047
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9986
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(layoutClass.diamond, className), children: [
9987
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10048
9988
  /* @__PURE__ */ jsxRuntime.jsx(
10049
9989
  ControlButton,
10050
9990
  {
@@ -10059,7 +9999,7 @@ function ControlGrid({
10059
9999
  disabled
10060
10000
  }
10061
10001
  ),
10062
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10002
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10063
10003
  /* @__PURE__ */ jsxRuntime.jsx(
10064
10004
  ControlButton,
10065
10005
  {
@@ -10074,7 +10014,7 @@ function ControlGrid({
10074
10014
  disabled
10075
10015
  }
10076
10016
  ),
10077
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10017
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10078
10018
  /* @__PURE__ */ jsxRuntime.jsx(
10079
10019
  ControlButton,
10080
10020
  {
@@ -10089,7 +10029,7 @@ function ControlGrid({
10089
10029
  disabled
10090
10030
  }
10091
10031
  ),
10092
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10032
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10093
10033
  /* @__PURE__ */ jsxRuntime.jsx(
10094
10034
  ControlButton,
10095
10035
  {
@@ -10104,10 +10044,10 @@ function ControlGrid({
10104
10044
  disabled
10105
10045
  }
10106
10046
  ),
10107
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10047
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10108
10048
  ] });
10109
10049
  }
10110
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10050
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10111
10051
  ControlButton,
10112
10052
  {
10113
10053
  icon: button.icon,
@@ -10129,6 +10069,7 @@ var init_ControlGrid = __esm({
10129
10069
  "use client";
10130
10070
  init_cn();
10131
10071
  init_useEventBus();
10072
+ init_Box();
10132
10073
  init_ControlButton();
10133
10074
  sizeKey = { sm: "sm", md: "md", lg: "lg" };
10134
10075
  layoutClass = {
@@ -10173,7 +10114,7 @@ function StatBadge({
10173
10114
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
10174
10115
  const resolvedAsset = iconUrl ?? assetUrl;
10175
10116
  return /* @__PURE__ */ jsxRuntime.jsxs(
10176
- "div",
10117
+ Box,
10177
10118
  {
10178
10119
  className: cn(
10179
10120
  "inline-flex items-center gap-2 rounded-container border backdrop-blur-sm",
@@ -10182,18 +10123,8 @@ function StatBadge({
10182
10123
  className
10183
10124
  ),
10184
10125
  children: [
10185
- resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(
10186
- "img",
10187
- {
10188
- src: resolvedAsset.url,
10189
- alt: "",
10190
- width: 16,
10191
- height: 16,
10192
- style: { imageRendering: "pixelated", objectFit: "contain" },
10193
- className: "flex-shrink-0"
10194
- }
10195
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
10196
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground font-medium", children: label }),
10126
+ resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: resolvedAsset, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
10127
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
10197
10128
  format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
10198
10129
  HealthBar,
10199
10130
  {
@@ -10219,7 +10150,7 @@ function StatBadge({
10219
10150
  size: size === "lg" ? "md" : "sm"
10220
10151
  }
10221
10152
  ),
10222
- format === "text" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-foreground", children: value })
10153
+ format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
10223
10154
  ]
10224
10155
  }
10225
10156
  );
@@ -10229,6 +10160,9 @@ var init_StatBadge = __esm({
10229
10160
  "components/game/2d/molecules/StatBadge.tsx"() {
10230
10161
  init_cn();
10231
10162
  init_Icon();
10163
+ init_Box();
10164
+ init_Typography();
10165
+ init_GameIcon();
10232
10166
  init_HealthBar();
10233
10167
  init_ScoreDisplay();
10234
10168
  sizeMap14 = {
@@ -10406,9 +10340,9 @@ function GameHud({
10406
10340
  if (position === "corners") {
10407
10341
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
10408
10342
  const rightStats = stats.slice(Math.ceil(stats.length / 2));
10409
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", positionMap[position], className), children: [
10410
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 left-4 flex flex-col gap-2 pointer-events-auto", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10411
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 right-4 flex flex-col gap-2 items-end pointer-events-auto", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10343
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn(positionMap[position], className), children: [
10344
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-4 left-4 flex flex-col gap-2 pointer-events-auto", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10345
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-4 right-4 flex flex-col gap-2 items-end pointer-events-auto", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10412
10346
  ] });
10413
10347
  }
10414
10348
  if (position === "top" || position === "bottom") {
@@ -10417,7 +10351,7 @@ function GameHud({
10417
10351
  const rightStats = stats.slice(mid);
10418
10352
  const isTop = position === "top";
10419
10353
  return /* @__PURE__ */ jsxRuntime.jsxs(
10420
- "div",
10354
+ Box,
10421
10355
  {
10422
10356
  className: cn(
10423
10357
  "flex items-center justify-between w-full",
@@ -10427,17 +10361,18 @@ function GameHud({
10427
10361
  className
10428
10362
  ),
10429
10363
  children: [
10430
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 flex-shrink-0", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10431
- rightStats.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 flex-shrink-0", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10364
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center gap-3 flex-shrink-0", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10365
+ rightStats.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center gap-3 flex-shrink-0", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10432
10366
  ]
10433
10367
  }
10434
10368
  );
10435
10369
  }
10436
10370
  return /* @__PURE__ */ jsxRuntime.jsx(
10437
- "div",
10371
+ Box,
10438
10372
  {
10373
+ position: "relative",
10439
10374
  className: cn(
10440
- "relative z-10 flex items-center gap-4 px-4 py-2",
10375
+ "z-10 flex items-center gap-4 px-4 py-2",
10441
10376
  transparent ? "bg-black/30 backdrop-blur-sm" : "bg-surface/90 backdrop-blur-sm",
10442
10377
  className
10443
10378
  ),
@@ -10449,6 +10384,7 @@ var positionMap, DEFAULT_HUD_STATS;
10449
10384
  var init_GameHud = __esm({
10450
10385
  "components/game/2d/molecules/GameHud.tsx"() {
10451
10386
  init_cn();
10387
+ init_Box();
10452
10388
  init_StatBadge();
10453
10389
  positionMap = {
10454
10390
  corners: "inset-0 pointer-events-none"
@@ -10489,7 +10425,7 @@ function GameMenu({
10489
10425
  [eventBus, onSelect]
10490
10426
  );
10491
10427
  return /* @__PURE__ */ jsxRuntime.jsxs(
10492
- "div",
10428
+ Box,
10493
10429
  {
10494
10430
  className: cn(
10495
10431
  "min-h-screen w-full flex flex-col items-center justify-center p-8",
@@ -10499,18 +10435,12 @@ function GameMenu({
10499
10435
  background: background ?? "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0e17 100%)"
10500
10436
  },
10501
10437
  children: [
10502
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-12 animate-fade-in", children: [
10503
- logo && /* @__PURE__ */ jsxRuntime.jsx(
10504
- "img",
10505
- {
10506
- src: logo.url,
10507
- alt: title,
10508
- className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl"
10509
- }
10510
- ),
10438
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "text-center mb-12 animate-fade-in", children: [
10439
+ logo && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: logo, icon: "image", size: 96, alt: title, className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl" }),
10511
10440
  /* @__PURE__ */ jsxRuntime.jsx(
10512
- "h1",
10441
+ Typography,
10513
10442
  {
10443
+ variant: "h1",
10514
10444
  className: "text-5xl md:text-7xl font-bold text-[var(--color-foreground)] tracking-tight",
10515
10445
  style: {
10516
10446
  textShadow: "0 4px 12px rgba(0,0,0,0.5)"
@@ -10518,9 +10448,9 @@ function GameMenu({
10518
10448
  children: title
10519
10449
  }
10520
10450
  ),
10521
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
10451
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
10522
10452
  ] }),
10523
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
10453
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
10524
10454
  ChoiceButton,
10525
10455
  {
10526
10456
  text: option.label,
@@ -10531,9 +10461,9 @@ function GameMenu({
10531
10461
  },
10532
10462
  index
10533
10463
  )) }),
10534
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none overflow-hidden", children: [
10535
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
10536
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
10464
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "absolute", className: "inset-0 pointer-events-none overflow-hidden", children: [
10465
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
10466
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
10537
10467
  ] })
10538
10468
  ]
10539
10469
  }
@@ -10545,6 +10475,9 @@ var init_GameMenu = __esm({
10545
10475
  "use client";
10546
10476
  init_cn();
10547
10477
  init_useEventBus();
10478
+ init_Box();
10479
+ init_Typography();
10480
+ init_GameIcon();
10548
10481
  init_ChoiceButton();
10549
10482
  DEFAULT_MENU_OPTIONS = [
10550
10483
  { label: "New Game", event: "NEW_GAME", variant: "primary" },
@@ -11964,10 +11897,11 @@ function Canvas2D({
11964
11897
  }
11965
11898
  }
11966
11899
  ),
11967
- process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
11900
+ process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
11968
11901
  tileClickEvent && /* @__PURE__ */ jsxRuntime.jsx(
11969
- "button",
11902
+ Button,
11970
11903
  {
11904
+ variant: "ghost",
11971
11905
  "data-event": tileClickEvent,
11972
11906
  "data-x": "0",
11973
11907
  "data-y": "0",
@@ -11976,8 +11910,9 @@ function Canvas2D({
11976
11910
  }
11977
11911
  ),
11978
11912
  unitClickEvent && units && units.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
11979
- "button",
11913
+ Button,
11980
11914
  {
11915
+ variant: "ghost",
11981
11916
  "data-event": unitClickEvent,
11982
11917
  "data-unit-id": units[0].id,
11983
11918
  onClick: () => eventBus.emit(`UI:${unitClickEvent}`, { unitId: units[0].id }),
@@ -11986,15 +11921,17 @@ function Canvas2D({
11986
11921
  )
11987
11922
  ] }),
11988
11923
  unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxRuntime.jsxs(
11989
- "div",
11924
+ Box,
11990
11925
  {
11991
- className: "absolute pointer-events-none",
11926
+ position: "absolute",
11927
+ className: "pointer-events-none",
11992
11928
  style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
11993
11929
  children: [
11994
11930
  unit.name && /* @__PURE__ */ jsxRuntime.jsx(
11995
- "div",
11931
+ Typography,
11996
11932
  {
11997
- className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
11933
+ as: "span",
11934
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
11998
11935
  style: { background: unit.team === "player" ? "rgba(59,130,246,0.9)" : unit.team === "enemy" ? "rgba(239,68,68,0.9)" : "rgba(107,114,128,0.9)" },
11999
11936
  children: unit.name
12000
11937
  }
@@ -12004,7 +11941,7 @@ function Canvas2D({
12004
11941
  },
12005
11942
  unit.id
12006
11943
  )),
12007
- showMinimap && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
11944
+ showMinimap && /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
12008
11945
  MiniMap,
12009
11946
  {
12010
11947
  tiles: miniMapTiles,
@@ -12026,6 +11963,7 @@ var init_Canvas2D = __esm({
12026
11963
  init_cn();
12027
11964
  init_useEventBus();
12028
11965
  init_Box();
11966
+ init_Button();
12029
11967
  init_Stack();
12030
11968
  init_Icon();
12031
11969
  init_Typography();
@@ -12357,7 +12295,7 @@ function GameAudioToggle({
12357
12295
  onClick: handleToggle,
12358
12296
  className: cn("text-lg leading-none px-2", className),
12359
12297
  "aria-pressed": muted,
12360
- children: activeAsset ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: activeAsset.url, alt: muted ? "Muted" : "Sound on", className: "w-5 h-5 object-contain" }) : muted ? "\u{1F507}" : "\u{1F50A}"
12298
+ children: activeAsset ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: activeAsset, icon: "image", size: 20, alt: muted ? "Muted" : "Sound on", className: "w-5 h-5 object-contain" }) : muted ? "\u{1F507}" : "\u{1F50A}"
12361
12299
  }
12362
12300
  );
12363
12301
  }
@@ -12367,6 +12305,7 @@ var init_GameAudioToggle = __esm({
12367
12305
  init_atoms();
12368
12306
  init_cn();
12369
12307
  init_GameAudioProvider();
12308
+ init_GameIcon();
12370
12309
  GameAudioToggle.displayName = "GameAudioToggle";
12371
12310
  }
12372
12311
  });
@@ -23337,7 +23276,7 @@ var init_Tabs = __esm({
23337
23276
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
23338
23277
  ),
23339
23278
  children: [
23340
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: item.icon, size: "sm" })),
23279
+ item.iconAsset?.url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: item.iconAsset.url, alt: item.iconAsset.name ?? item.iconAsset.category ?? "", width: 16, height: 16, style: { imageRendering: "pixelated", objectFit: "contain", width: 16, height: 16 }, className: "flex-shrink-0" }) : item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: item.icon, size: "sm" })),
23341
23280
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
23342
23281
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: item.badge })
23343
23282
  ]