@almadar/ui 5.80.0 → 5.81.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.
@@ -8402,6 +8402,38 @@ var init_shared = __esm({
8402
8402
  init_canvasEffects();
8403
8403
  }
8404
8404
  });
8405
+ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
8406
+ const px = typeof size === "number" ? size : sizeMap[size];
8407
+ if (assetUrl?.url) {
8408
+ return /* @__PURE__ */ jsxRuntime.jsx(
8409
+ "img",
8410
+ {
8411
+ src: assetUrl.url,
8412
+ alt: alt ?? assetUrl.category ?? "",
8413
+ width: px,
8414
+ height: px,
8415
+ style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
8416
+ className: cn("flex-shrink-0", className)
8417
+ }
8418
+ );
8419
+ }
8420
+ const I = typeof icon === "string" ? resolveIcon(icon) : icon;
8421
+ return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
8422
+ }
8423
+ var sizeMap;
8424
+ var init_GameIcon = __esm({
8425
+ "components/game/2d/atoms/GameIcon.tsx"() {
8426
+ "use client";
8427
+ init_cn();
8428
+ init_Icon();
8429
+ sizeMap = {
8430
+ sm: 16,
8431
+ md: 24,
8432
+ lg: 32
8433
+ };
8434
+ GameIcon.displayName = "GameIcon";
8435
+ }
8436
+ });
8405
8437
  function GameCard({
8406
8438
  id,
8407
8439
  cost,
@@ -8424,9 +8456,9 @@ function GameCard({
8424
8456
  }, [disabled, id, onClick, clickEvent, eventBus]);
8425
8457
  const artPx = artPxMap[size];
8426
8458
  return /* @__PURE__ */ jsxRuntime.jsxs(
8427
- "button",
8459
+ Button,
8428
8460
  {
8429
- type: "button",
8461
+ variant: "ghost",
8430
8462
  onClick: handleClick,
8431
8463
  disabled,
8432
8464
  title: name,
@@ -8440,8 +8472,9 @@ function GameCard({
8440
8472
  ),
8441
8473
  children: [
8442
8474
  cost != null && /* @__PURE__ */ jsxRuntime.jsx(
8443
- "span",
8475
+ Typography,
8444
8476
  {
8477
+ as: "span",
8445
8478
  className: cn(
8446
8479
  "absolute -top-2 -left-2 flex items-center justify-center",
8447
8480
  "min-w-[22px] h-[22px] rounded-full px-1",
@@ -8450,17 +8483,7 @@ function GameCard({
8450
8483
  children: cost
8451
8484
  }
8452
8485
  ),
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 } }) }),
8486
+ /* @__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
8487
  name != null && /* @__PURE__ */ jsxRuntime.jsx(
8465
8488
  Typography,
8466
8489
  {
@@ -8470,8 +8493,8 @@ function GameCard({
8470
8493
  }
8471
8494
  ),
8472
8495
  (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}` : "" })
8496
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
8497
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
8475
8498
  ] })
8476
8499
  ]
8477
8500
  }
@@ -8484,7 +8507,9 @@ var init_GameCard = __esm({
8484
8507
  init_cn();
8485
8508
  init_useEventBus();
8486
8509
  init_Box();
8510
+ init_Button();
8487
8511
  init_Typography();
8512
+ init_GameIcon();
8488
8513
  cardSizeMap = {
8489
8514
  sm: "w-16 h-24",
8490
8515
  md: "w-20 h-28",
@@ -8507,12 +8532,13 @@ function HealthBar({
8507
8532
  frameAsset,
8508
8533
  fillAsset
8509
8534
  }) {
8510
- const sizes = sizeMap[size];
8535
+ const sizes = sizeMap2[size];
8511
8536
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
8512
8537
  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",
8538
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
8539
+ Box,
8515
8540
  {
8541
+ as: "span",
8516
8542
  className: cn(animated && "transition-transform hover:scale-110"),
8517
8543
  children: heartIcon(i < current, sizes.heart)
8518
8544
  },
@@ -8521,10 +8547,12 @@ function HealthBar({
8521
8547
  }
8522
8548
  if (format === "bar") {
8523
8549
  return /* @__PURE__ */ jsxRuntime.jsx(
8524
- "div",
8550
+ Box,
8525
8551
  {
8552
+ position: "relative",
8553
+ overflow: "hidden",
8526
8554
  className: cn(
8527
- "relative overflow-hidden rounded-full",
8555
+ "rounded-full",
8528
8556
  !frameAsset && "bg-muted",
8529
8557
  sizes.bar,
8530
8558
  "w-24",
@@ -8532,10 +8560,11 @@ function HealthBar({
8532
8560
  ),
8533
8561
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
8534
8562
  children: /* @__PURE__ */ jsxRuntime.jsx(
8535
- "div",
8563
+ Box,
8536
8564
  {
8565
+ position: "absolute",
8537
8566
  className: cn(
8538
- "absolute inset-y-0 left-0 rounded-full",
8567
+ "inset-y-0 left-0 rounded-full",
8539
8568
  !fillAsset && (percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error"),
8540
8569
  animated && "transition-all duration-300"
8541
8570
  ),
@@ -8549,10 +8578,11 @@ function HealthBar({
8549
8578
  );
8550
8579
  }
8551
8580
  if (format === "progress") {
8552
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), children: [
8581
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex items-center gap-2", className), children: [
8553
8582
  level != null && /* @__PURE__ */ jsxRuntime.jsxs(
8554
- "span",
8583
+ Typography,
8555
8584
  {
8585
+ as: "span",
8556
8586
  className: cn(
8557
8587
  "flex-shrink-0 rounded-interactive font-bold",
8558
8588
  "bg-accent text-accent-foreground border border-accent",
@@ -8564,21 +8594,23 @@ function HealthBar({
8564
8594
  ]
8565
8595
  }
8566
8596
  ),
8567
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [
8597
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 flex flex-col gap-0.5", children: [
8568
8598
  /* @__PURE__ */ jsxRuntime.jsx(
8569
- "div",
8599
+ Box,
8570
8600
  {
8601
+ position: "relative",
8571
8602
  className: cn(
8572
- "relative w-full overflow-hidden rounded-full",
8603
+ "w-full overflow-hidden rounded-full",
8573
8604
  !frameAsset && "bg-muted border border-muted",
8574
8605
  sizes.bar
8575
8606
  ),
8576
8607
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
8577
8608
  children: /* @__PURE__ */ jsxRuntime.jsx(
8578
- "div",
8609
+ Box,
8579
8610
  {
8611
+ position: "absolute",
8580
8612
  className: cn(
8581
- "absolute inset-y-0 left-0 rounded-full",
8613
+ "inset-y-0 left-0 rounded-full",
8582
8614
  !fillAsset && "bg-gradient-to-r from-accent to-info",
8583
8615
  animated && "transition-all duration-500 ease-out"
8584
8616
  ),
@@ -8590,7 +8622,7 @@ function HealthBar({
8590
8622
  )
8591
8623
  }
8592
8624
  ),
8593
- showLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
8625
+ showLabel && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
8594
8626
  current,
8595
8627
  " / ",
8596
8628
  max,
@@ -8599,16 +8631,18 @@ function HealthBar({
8599
8631
  ] })
8600
8632
  ] });
8601
8633
  }
8602
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
8634
+ return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-mono font-bold", sizes.text, className), children: [
8603
8635
  current,
8604
8636
  "/",
8605
8637
  max
8606
8638
  ] });
8607
8639
  }
8608
- var heartIcon, sizeMap;
8640
+ var heartIcon, sizeMap2;
8609
8641
  var init_HealthBar = __esm({
8610
8642
  "components/game/2d/atoms/HealthBar.tsx"() {
8611
8643
  init_cn();
8644
+ init_Box();
8645
+ init_Typography();
8612
8646
  heartIcon = (filled, size) => /* @__PURE__ */ jsxRuntime.jsx(
8613
8647
  "svg",
8614
8648
  {
@@ -8620,7 +8654,7 @@ var init_HealthBar = __esm({
8620
8654
  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
8655
  }
8622
8656
  );
8623
- sizeMap = {
8657
+ sizeMap2 = {
8624
8658
  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
8659
  md: { heart: "w-6 h-6", bar: "h-3", text: "text-base", label: "text-xs", badge: "text-xs px-2 py-0.5" },
8626
8660
  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 +8675,30 @@ function ScoreDisplay({
8641
8675
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
8642
8676
  const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
8643
8677
  return /* @__PURE__ */ jsxRuntime.jsxs(
8644
- "div",
8678
+ Box,
8645
8679
  {
8646
8680
  className: cn(
8647
8681
  "flex items-center gap-2 font-bold",
8648
- sizeMap2[size],
8682
+ sizeMap3[size],
8649
8683
  className
8650
8684
  ),
8651
8685
  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 })
8686
+ 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,
8687
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
8688
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "tabular-nums", children: formattedValue })
8665
8689
  ]
8666
8690
  }
8667
8691
  );
8668
8692
  }
8669
- var sizeMap2, DEFAULT_ASSET_URL;
8693
+ var sizeMap3, DEFAULT_ASSET_URL;
8670
8694
  var init_ScoreDisplay = __esm({
8671
8695
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
8672
8696
  init_cn();
8673
8697
  init_Icon();
8674
- sizeMap2 = {
8698
+ init_Box();
8699
+ init_Typography();
8700
+ init_GameIcon();
8701
+ sizeMap3 = {
8675
8702
  sm: "text-sm",
8676
8703
  md: "text-lg",
8677
8704
  lg: "text-2xl",
@@ -8734,9 +8761,9 @@ function ControlButton({
8734
8761
  [isPressed, releaseEvent, eventBus, onRelease]
8735
8762
  );
8736
8763
  return /* @__PURE__ */ jsxRuntime.jsx(
8737
- "button",
8764
+ Button,
8738
8765
  {
8739
- type: "button",
8766
+ variant,
8740
8767
  disabled,
8741
8768
  onPointerDown: handlePointerDown,
8742
8769
  onPointerUp: handlePointerUp,
@@ -8747,41 +8774,35 @@ function ControlButton({
8747
8774
  "select-none touch-none",
8748
8775
  "transition-all duration-100",
8749
8776
  "active:scale-95",
8750
- sizeMap3[size] ?? sizeMap3.md,
8777
+ sizeMap4[size] ?? sizeMap4.md,
8751
8778
  shapeMap[shape] ?? shapeMap.circle,
8752
8779
  variantMap[variant] ?? variantMap.secondary,
8753
8780
  actualPressed && "scale-95 brightness-110 border-foreground",
8754
8781
  disabled && "opacity-50 cursor-not-allowed",
8755
8782
  className
8756
8783
  ),
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) ? (() => {
8784
+ 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
8785
  const I = resolveIcon(icon);
8769
8786
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" }) : null;
8770
8787
  })() : icon : /* @__PURE__ */ (() => {
8771
8788
  const I = icon;
8772
8789
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" });
8773
- })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }) : null
8790
+ })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: label }) : null
8774
8791
  }
8775
8792
  );
8776
8793
  }
8777
- var sizeMap3, shapeMap, variantMap, DEFAULT_ASSET_URL2;
8794
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
8778
8795
  var init_ControlButton = __esm({
8779
8796
  "components/game/2d/atoms/ControlButton.tsx"() {
8780
8797
  "use client";
8781
8798
  init_cn();
8782
8799
  init_useEventBus();
8783
8800
  init_Icon();
8784
- sizeMap3 = {
8801
+ init_Button();
8802
+ init_Box();
8803
+ init_Typography();
8804
+ init_GameIcon();
8805
+ sizeMap4 = {
8785
8806
  sm: "w-10 h-10 text-sm",
8786
8807
  md: "w-14 h-14 text-base",
8787
8808
  lg: "w-18 h-18 text-lg",
@@ -8851,12 +8872,12 @@ function Sprite({
8851
8872
  onClick?.();
8852
8873
  };
8853
8874
  return /* @__PURE__ */ jsxRuntime.jsx(
8854
- "div",
8875
+ Box,
8855
8876
  {
8877
+ position: "absolute",
8856
8878
  className,
8857
8879
  onClick: action || onClick ? handleClick : void 0,
8858
8880
  style: {
8859
- position: "absolute",
8860
8881
  width: frameWidth,
8861
8882
  height: frameHeight,
8862
8883
  backgroundImage: `url(${spritesheet.url})`,
@@ -8877,6 +8898,7 @@ var init_Sprite = __esm({
8877
8898
  "components/game/2d/atoms/Sprite.tsx"() {
8878
8899
  "use client";
8879
8900
  init_useEventBus();
8901
+ init_Box();
8880
8902
  init_spriteAnimation();
8881
8903
  DEFAULT_SPRITESHEET = {
8882
8904
  url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
@@ -8913,17 +8935,7 @@ function StateIndicator({
8913
8935
  className
8914
8936
  ),
8915
8937
  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 }) }),
8938
+ /* @__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
8939
  /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: displayLabel })
8928
8940
  ]
8929
8941
  }
@@ -8935,6 +8947,7 @@ var init_StateIndicator = __esm({
8935
8947
  init_Box();
8936
8948
  init_Icon();
8937
8949
  init_cn();
8950
+ init_GameIcon();
8938
8951
  DEFAULT_ASSET_URL3 = {
8939
8952
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
8940
8953
  role: "ui",
@@ -8988,29 +9001,31 @@ function TimerDisplay({
8988
9001
  }) {
8989
9002
  const isLow = lowThreshold != null && seconds <= lowThreshold && seconds > 0;
8990
9003
  return /* @__PURE__ */ jsxRuntime.jsxs(
8991
- "div",
9004
+ Box,
8992
9005
  {
8993
9006
  className: cn(
8994
9007
  "inline-flex items-center gap-1 justify-center rounded-container",
8995
9008
  "bg-card/80 border border-muted font-mono font-bold tabular-nums",
8996
- sizeMap4[size],
9009
+ sizeMap5[size],
8997
9010
  running && "border-success/50",
8998
9011
  isLow && "text-error border-error/50 animate-pulse",
8999
9012
  !isLow && "text-foreground",
9000
9013
  className
9001
9014
  ),
9002
9015
  children: [
9003
- iconAsset && /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconAsset.url, alt: "", className: "w-4 h-4 object-contain flex-shrink-0" }),
9016
+ iconAsset && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: iconAsset, icon: "image", size: 16, className: "w-4 h-4 object-contain flex-shrink-0" }),
9004
9017
  formatTime(seconds, format)
9005
9018
  ]
9006
9019
  }
9007
9020
  );
9008
9021
  }
9009
- var sizeMap4;
9022
+ var sizeMap5;
9010
9023
  var init_TimerDisplay = __esm({
9011
9024
  "components/game/2d/atoms/TimerDisplay.tsx"() {
9012
9025
  init_cn();
9013
- sizeMap4 = {
9026
+ init_Box();
9027
+ init_GameIcon();
9028
+ sizeMap5 = {
9014
9029
  sm: "text-sm px-2 py-0.5",
9015
9030
  md: "text-lg px-3 py-1",
9016
9031
  lg: "text-2xl px-4 py-1.5"
@@ -9028,9 +9043,9 @@ function ResourceCounter({
9028
9043
  size = "md",
9029
9044
  className
9030
9045
  }) {
9031
- const sizes = sizeMap5[size];
9046
+ const sizes = sizeMap6[size];
9032
9047
  return /* @__PURE__ */ jsxRuntime.jsxs(
9033
- "div",
9048
+ Box,
9034
9049
  {
9035
9050
  className: cn(
9036
9051
  "inline-flex items-center rounded-container",
@@ -9039,21 +9054,11 @@ function ResourceCounter({
9039
9054
  className
9040
9055
  ),
9041
9056
  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: [
9057
+ 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,
9058
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
9059
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
9055
9060
  value,
9056
- max != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9061
+ max != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9057
9062
  "/",
9058
9063
  max
9059
9064
  ] })
@@ -9062,11 +9067,14 @@ function ResourceCounter({
9062
9067
  }
9063
9068
  );
9064
9069
  }
9065
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap5;
9070
+ var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
9066
9071
  var init_ResourceCounter = __esm({
9067
9072
  "components/game/2d/atoms/ResourceCounter.tsx"() {
9068
9073
  init_cn();
9069
9074
  init_Icon();
9075
+ init_Box();
9076
+ init_Typography();
9077
+ init_GameIcon();
9070
9078
  colorTokenClasses2 = {
9071
9079
  primary: "text-primary",
9072
9080
  secondary: "text-secondary",
@@ -9080,7 +9088,7 @@ var init_ResourceCounter = __esm({
9080
9088
  role: "ui",
9081
9089
  category: "coin"
9082
9090
  };
9083
- sizeMap5 = {
9091
+ sizeMap6 = {
9084
9092
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
9085
9093
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
9086
9094
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -9105,9 +9113,9 @@ function ItemSlot({
9105
9113
  const isClickable = onClick != null || action != null;
9106
9114
  const px = assetSizeMap[size];
9107
9115
  return /* @__PURE__ */ jsxRuntime.jsx(
9108
- "button",
9116
+ Button,
9109
9117
  {
9110
- type: "button",
9118
+ variant: "ghost",
9111
9119
  onClick: () => {
9112
9120
  if (action) eventBus.emit(`UI:${action}`, {});
9113
9121
  onClick?.();
@@ -9117,7 +9125,7 @@ function ItemSlot({
9117
9125
  className: cn(
9118
9126
  "relative flex items-center justify-center rounded-interactive border-2",
9119
9127
  "bg-card/80 transition-all duration-150",
9120
- sizeMap6[size],
9128
+ sizeMap7[size],
9121
9129
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
9122
9130
  !empty && rarityGlowMap[rarity],
9123
9131
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -9126,21 +9134,12 @@ function ItemSlot({
9126
9134
  !isClickable && "cursor-default",
9127
9135
  className
9128
9136
  ),
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,
9137
+ children: empty ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9138
+ 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
9139
  quantity != null && quantity > 1 && /* @__PURE__ */ jsxRuntime.jsx(
9142
- "span",
9140
+ Typography,
9143
9141
  {
9142
+ as: "span",
9144
9143
  className: cn(
9145
9144
  "absolute -bottom-1 -right-1 flex items-center justify-center",
9146
9145
  "min-w-[18px] h-[18px] rounded-full px-1",
@@ -9153,14 +9152,18 @@ function ItemSlot({
9153
9152
  }
9154
9153
  );
9155
9154
  }
9156
- var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9155
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9157
9156
  var init_ItemSlot = __esm({
9158
9157
  "components/game/2d/atoms/ItemSlot.tsx"() {
9159
9158
  "use client";
9160
9159
  init_cn();
9161
9160
  init_Icon();
9162
9161
  init_useEventBus();
9163
- sizeMap6 = {
9162
+ init_Button();
9163
+ init_Box();
9164
+ init_Typography();
9165
+ init_GameIcon();
9166
+ sizeMap7 = {
9164
9167
  sm: "w-10 h-10 text-lg",
9165
9168
  md: "w-14 h-14 text-2xl",
9166
9169
  lg: "w-18 h-18 text-3xl"
@@ -9201,9 +9204,9 @@ function TurnIndicator({
9201
9204
  size = "md",
9202
9205
  className
9203
9206
  }) {
9204
- const sizes = sizeMap7[size];
9207
+ const sizes = sizeMap8[size];
9205
9208
  return /* @__PURE__ */ jsxRuntime.jsxs(
9206
- "div",
9209
+ Box,
9207
9210
  {
9208
9211
  className: cn(
9209
9212
  "inline-flex items-center rounded-container",
@@ -9212,42 +9215,35 @@ function TurnIndicator({
9212
9215
  className
9213
9216
  ),
9214
9217
  children: [
9215
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold tabular-nums", children: [
9218
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "font-bold tabular-nums", children: [
9216
9219
  "Turn ",
9217
9220
  currentTurn,
9218
- maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9221
+ maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9219
9222
  "/",
9220
9223
  maxTurns
9221
9224
  ] })
9222
9225
  ] }),
9223
9226
  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 })
9227
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9228
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: phase })
9226
9229
  ] }),
9227
9230
  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 })
9231
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9232
+ 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) }),
9233
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-success", children: activeTeam })
9241
9234
  ] })
9242
9235
  ]
9243
9236
  }
9244
9237
  );
9245
9238
  }
9246
- var sizeMap7, DEFAULT_ASSET_URL6;
9239
+ var sizeMap8, DEFAULT_ASSET_URL6;
9247
9240
  var init_TurnIndicator = __esm({
9248
9241
  "components/game/2d/atoms/TurnIndicator.tsx"() {
9249
9242
  init_cn();
9250
- sizeMap7 = {
9243
+ init_Box();
9244
+ init_Typography();
9245
+ init_GameIcon();
9246
+ sizeMap8 = {
9251
9247
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
9252
9248
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
9253
9249
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
@@ -9279,10 +9275,10 @@ function ComboCounter({
9279
9275
  size = "md",
9280
9276
  className
9281
9277
  }) {
9282
- const sizes = sizeMap8[size];
9278
+ const sizes = sizeMap9[size];
9283
9279
  if (combo <= 0) return null;
9284
9280
  return /* @__PURE__ */ jsxRuntime.jsxs(
9285
- "div",
9281
+ Box,
9286
9282
  {
9287
9283
  className: cn(
9288
9284
  "inline-flex flex-col items-center justify-center",
@@ -9292,24 +9288,14 @@ function ComboCounter({
9292
9288
  className
9293
9289
  ),
9294
9290
  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: [
9291
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0 mb-0.5" }),
9292
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
9293
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
9294
+ multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
9309
9295
  "x",
9310
9296
  multiplier.toFixed(1)
9311
9297
  ] }),
9312
- streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9298
+ streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9313
9299
  streak,
9314
9300
  " streak"
9315
9301
  ] })
@@ -9317,16 +9303,19 @@ function ComboCounter({
9317
9303
  }
9318
9304
  );
9319
9305
  }
9320
- var DEFAULT_ASSET_URL7, sizeMap8;
9306
+ var DEFAULT_ASSET_URL7, sizeMap9;
9321
9307
  var init_ComboCounter = __esm({
9322
9308
  "components/game/2d/atoms/ComboCounter.tsx"() {
9323
9309
  init_cn();
9310
+ init_Box();
9311
+ init_Typography();
9312
+ init_GameIcon();
9324
9313
  DEFAULT_ASSET_URL7 = {
9325
9314
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
9326
9315
  role: "effect",
9327
9316
  category: "effect"
9328
9317
  };
9329
- sizeMap8 = {
9318
+ sizeMap9 = {
9330
9319
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
9331
9320
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
9332
9321
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -9343,54 +9332,48 @@ function WaypointMarker({
9343
9332
  size = "md",
9344
9333
  className
9345
9334
  }) {
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: [
9335
+ const sizes = sizeMap10[size];
9336
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col items-center", className), children: [
9337
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative flex items-center justify-center", children: [
9349
9338
  active && /* @__PURE__ */ jsxRuntime.jsx(
9350
- "div",
9339
+ Box,
9351
9340
  {
9341
+ position: "absolute",
9352
9342
  className: cn(
9353
- "absolute rounded-full border-2 border-info animate-ping opacity-50",
9343
+ "rounded-full border-2 border-info animate-ping opacity-50",
9354
9344
  sizes.ring
9355
9345
  )
9356
9346
  }
9357
9347
  ),
9358
9348
  active && /* @__PURE__ */ jsxRuntime.jsx(
9359
- "div",
9349
+ Box,
9360
9350
  {
9351
+ position: "absolute",
9361
9352
  className: cn(
9362
- "absolute rounded-full border-2 border-info",
9353
+ "rounded-full border-2 border-info",
9363
9354
  sizes.ring
9364
9355
  )
9365
9356
  }
9366
9357
  ),
9367
9358
  /* @__PURE__ */ jsxRuntime.jsx(
9368
- "div",
9359
+ Box,
9369
9360
  {
9361
+ position: "relative",
9370
9362
  className: cn(
9371
- "relative flex items-center justify-center rounded-full transition-all duration-200",
9363
+ "flex items-center justify-center rounded-full transition-all duration-200",
9372
9364
  sizes.dot,
9373
9365
  completed && "bg-success text-foreground",
9374
9366
  active && !completed && "bg-info text-foreground",
9375
9367
  !active && !completed && "bg-muted"
9376
9368
  ),
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
9369
+ 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
9370
  }
9389
9371
  )
9390
9372
  ] }),
9391
9373
  label && /* @__PURE__ */ jsxRuntime.jsx(
9392
- "span",
9374
+ Typography,
9393
9375
  {
9376
+ as: "span",
9394
9377
  className: cn(
9395
9378
  "text-center whitespace-nowrap",
9396
9379
  sizes.label,
@@ -9401,17 +9384,20 @@ function WaypointMarker({
9401
9384
  )
9402
9385
  ] });
9403
9386
  }
9404
- var DEFAULT_ASSET_URL8, sizeMap9, checkIcon;
9387
+ var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
9405
9388
  var init_WaypointMarker = __esm({
9406
9389
  "components/game/2d/atoms/WaypointMarker.tsx"() {
9407
9390
  init_cn();
9408
9391
  init_Icon();
9392
+ init_Box();
9393
+ init_Typography();
9394
+ init_GameIcon();
9409
9395
  DEFAULT_ASSET_URL8 = {
9410
9396
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
9411
9397
  role: "ui",
9412
9398
  category: "waypoint"
9413
9399
  };
9414
- sizeMap9 = {
9400
+ sizeMap10 = {
9415
9401
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
9416
9402
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
9417
9403
  lg: { dot: "w-8 h-8", ring: "w-10 h-10", label: "text-base mt-2", img: 24 }
@@ -9436,32 +9422,24 @@ function StatusEffect({
9436
9422
  size = "md",
9437
9423
  className
9438
9424
  }) {
9439
- const sizes = sizeMap10[size];
9440
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
9425
+ const sizes = sizeMap11[size];
9426
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn("inline-flex flex-col items-center", className), children: [
9441
9427
  /* @__PURE__ */ jsxRuntime.jsxs(
9442
- "div",
9428
+ Box,
9443
9429
  {
9430
+ position: "relative",
9444
9431
  className: cn(
9445
- "relative flex items-center justify-center rounded-interactive border-2",
9432
+ "flex items-center justify-center rounded-interactive border-2",
9446
9433
  sizes.container,
9447
9434
  variantStyles7[variant]
9448
9435
  ),
9449
9436
  title: label,
9450
9437
  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 }),
9438
+ /* @__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
9439
  duration !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
9463
- "span",
9440
+ Typography,
9464
9441
  {
9442
+ as: "span",
9465
9443
  className: cn(
9466
9444
  "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
9467
9445
  sizes.timer
@@ -9473,8 +9451,9 @@ function StatusEffect({
9473
9451
  }
9474
9452
  ),
9475
9453
  stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsxRuntime.jsx(
9476
- "span",
9454
+ Typography,
9477
9455
  {
9456
+ as: "span",
9478
9457
  className: cn(
9479
9458
  "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
9480
9459
  sizes.badge
@@ -9482,20 +9461,23 @@ function StatusEffect({
9482
9461
  children: stacks
9483
9462
  }
9484
9463
  ),
9485
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
9464
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
9486
9465
  ] });
9487
9466
  }
9488
- var DEFAULT_ASSET_URL9, sizeMap10, variantStyles7;
9467
+ var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
9489
9468
  var init_StatusEffect = __esm({
9490
9469
  "components/game/2d/atoms/StatusEffect.tsx"() {
9491
9470
  init_cn();
9492
9471
  init_Icon();
9472
+ init_Box();
9473
+ init_Typography();
9474
+ init_GameIcon();
9493
9475
  DEFAULT_ASSET_URL9 = {
9494
9476
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
9495
9477
  role: "ui",
9496
9478
  category: "effect"
9497
9479
  };
9498
- sizeMap10 = {
9480
+ sizeMap11 = {
9499
9481
  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
9482
  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
9483
  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 +9501,31 @@ function DamageNumber({
9519
9501
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9520
9502
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: floatKeyframes }),
9521
9503
  /* @__PURE__ */ jsxRuntime.jsxs(
9522
- "span",
9504
+ Typography,
9523
9505
  {
9506
+ as: "span",
9524
9507
  className: cn(
9525
9508
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
9526
- sizeMap11[size],
9509
+ sizeMap12[size],
9527
9510
  typeStyles[type],
9528
9511
  className
9529
9512
  ),
9530
9513
  style: { animation: "damageFloat 1s ease-out forwards" },
9531
9514
  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
- ),
9515
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 14, className: "flex-shrink-0" }),
9543
9516
  displayText
9544
9517
  ]
9545
9518
  }
9546
9519
  )
9547
9520
  ] });
9548
9521
  }
9549
- var sizeMap11, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
9522
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
9550
9523
  var init_DamageNumber = __esm({
9551
9524
  "components/game/2d/atoms/DamageNumber.tsx"() {
9552
9525
  init_cn();
9553
- sizeMap11 = {
9526
+ init_Typography();
9527
+ init_GameIcon();
9528
+ sizeMap12 = {
9554
9529
  sm: "text-sm",
9555
9530
  md: "text-lg",
9556
9531
  lg: "text-2xl"
@@ -9584,7 +9559,7 @@ function DialogueBubble({
9584
9559
  className
9585
9560
  }) {
9586
9561
  return /* @__PURE__ */ jsxRuntime.jsxs(
9587
- "div",
9562
+ Box,
9588
9563
  {
9589
9564
  className: cn(
9590
9565
  "flex items-start gap-3 rounded-container bg-background/80 backdrop-blur-sm px-4 py-3 border border-border/10",
@@ -9592,17 +9567,10 @@ function DialogueBubble({
9592
9567
  className
9593
9568
  ),
9594
9569
  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 })
9570
+ 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" }) }),
9571
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-1 min-w-0", children: [
9572
+ speaker && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm font-bold text-warning", children: speaker }),
9573
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm text-foreground leading-relaxed", children: text })
9606
9574
  ] })
9607
9575
  ]
9608
9576
  }
@@ -9612,6 +9580,9 @@ var DEFAULT_PORTRAIT;
9612
9580
  var init_DialogueBubble = __esm({
9613
9581
  "components/game/2d/atoms/DialogueBubble.tsx"() {
9614
9582
  init_cn();
9583
+ init_Box();
9584
+ init_Typography();
9585
+ init_GameIcon();
9615
9586
  DEFAULT_PORTRAIT = {
9616
9587
  url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
9617
9588
  role: "effect",
@@ -9633,11 +9604,11 @@ function ChoiceButton({
9633
9604
  }) {
9634
9605
  const eventBus = useEventBus();
9635
9606
  return /* @__PURE__ */ jsxRuntime.jsxs(
9636
- "button",
9607
+ Button,
9637
9608
  {
9638
- type: "button",
9609
+ variant: "ghost",
9639
9610
  disabled,
9640
- onClick: (e) => {
9611
+ onClick: () => {
9641
9612
  if (action) eventBus.emit(`UI:${action}`, {});
9642
9613
  onClick?.();
9643
9614
  },
@@ -9650,8 +9621,9 @@ function ChoiceButton({
9650
9621
  ),
9651
9622
  children: [
9652
9623
  index !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(
9653
- "span",
9624
+ Typography,
9654
9625
  {
9626
+ as: "span",
9655
9627
  className: cn(
9656
9628
  "flex-shrink-0 font-mono font-bold text-sm",
9657
9629
  selected ? "text-accent" : "text-muted-foreground"
@@ -9662,24 +9634,14 @@ function ChoiceButton({
9662
9634
  ]
9663
9635
  }
9664
9636
  ),
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" ? (() => {
9637
+ 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
9638
  const I = resolveIcon(icon);
9677
9639
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
9678
9640
  })() : /* @__PURE__ */ (() => {
9679
9641
  const I = icon;
9680
9642
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
9681
9643
  })() }) : null,
9682
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-snug", children: text })
9644
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm leading-snug", children: text })
9683
9645
  ]
9684
9646
  }
9685
9647
  );
@@ -9689,6 +9651,10 @@ var init_ChoiceButton = __esm({
9689
9651
  init_cn();
9690
9652
  init_Icon();
9691
9653
  init_useEventBus();
9654
+ init_Button();
9655
+ init_Box();
9656
+ init_Typography();
9657
+ init_GameIcon();
9692
9658
  ChoiceButton.displayName = "ChoiceButton";
9693
9659
  }
9694
9660
  });
@@ -9706,16 +9672,16 @@ function ActionButton({
9706
9672
  className
9707
9673
  }) {
9708
9674
  const eventBus = useEventBus();
9709
- const sizes = sizeMap12[size];
9675
+ const sizes = sizeMap13[size];
9710
9676
  const onCooldown = cooldown > 0;
9711
9677
  const isDisabled = disabled || onCooldown;
9712
9678
  const cooldownDeg = Math.round(cooldown * 360);
9713
9679
  return /* @__PURE__ */ jsxRuntime.jsxs(
9714
- "button",
9680
+ Button,
9715
9681
  {
9716
- type: "button",
9682
+ variant: variant === "danger" ? "danger" : variant === "secondary" ? "secondary" : "primary",
9717
9683
  disabled: isDisabled,
9718
- onClick: (e) => {
9684
+ onClick: () => {
9719
9685
  if (action) eventBus.emit(`UI:${action}`, {});
9720
9686
  onClick?.();
9721
9687
  },
@@ -9728,9 +9694,10 @@ function ActionButton({
9728
9694
  ),
9729
9695
  children: [
9730
9696
  onCooldown && /* @__PURE__ */ jsxRuntime.jsx(
9731
- "div",
9697
+ Box,
9732
9698
  {
9733
- className: "absolute inset-0 bg-foreground/40 pointer-events-none",
9699
+ position: "absolute",
9700
+ className: "inset-0 bg-foreground/40 pointer-events-none",
9734
9701
  style: {
9735
9702
  clipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
9736
9703
  WebkitClipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
@@ -9738,27 +9705,18 @@ function ActionButton({
9738
9705
  }
9739
9706
  }
9740
9707
  ),
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" ? (() => {
9708
+ 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
9709
  const I = resolveIcon(icon);
9753
9710
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
9754
9711
  })() : /* @__PURE__ */ (() => {
9755
9712
  const I = icon;
9756
9713
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
9757
9714
  })() }) : null,
9758
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10", children: label }),
9715
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "relative z-10", children: label }),
9759
9716
  hotkey && /* @__PURE__ */ jsxRuntime.jsx(
9760
- "span",
9717
+ Typography,
9761
9718
  {
9719
+ as: "span",
9762
9720
  className: cn(
9763
9721
  "absolute top-0.5 right-0.5 bg-foreground/30 text-primary-foreground rounded font-mono leading-tight",
9764
9722
  sizes.hotkey
@@ -9770,13 +9728,17 @@ function ActionButton({
9770
9728
  }
9771
9729
  );
9772
9730
  }
9773
- var sizeMap12, variantStyles8, DEFAULT_ASSET_URL11;
9731
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
9774
9732
  var init_ActionButton = __esm({
9775
9733
  "components/game/2d/atoms/ActionButton.tsx"() {
9776
9734
  init_cn();
9777
9735
  init_Icon();
9778
9736
  init_useEventBus();
9779
- sizeMap12 = {
9737
+ init_Button();
9738
+ init_Box();
9739
+ init_Typography();
9740
+ init_GameIcon();
9741
+ sizeMap13 = {
9780
9742
  sm: { button: "h-button-sm px-3 text-xs", hotkey: "text-[9px] px-1", icon: "text-xs" },
9781
9743
  md: { button: "h-button-md px-4 text-sm", hotkey: "text-xs px-1.5", icon: "text-sm" },
9782
9744
  lg: { button: "h-button-lg px-5 text-base", hotkey: "text-xs px-2", icon: "text-base" }
@@ -9878,10 +9840,12 @@ function MiniMap({
9878
9840
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9879
9841
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes minimap-blink{0%,49%{opacity:1}50%,100%{opacity:0}}` }),
9880
9842
  /* @__PURE__ */ jsxRuntime.jsxs(
9881
- "div",
9843
+ Box,
9882
9844
  {
9845
+ position: "relative",
9846
+ display: "inline-block",
9883
9847
  className: cn(
9884
- "relative inline-block border border-border/20 rounded-container",
9848
+ "border border-border/20 rounded-container",
9885
9849
  className
9886
9850
  ),
9887
9851
  children: [
@@ -9896,10 +9860,10 @@ function MiniMap({
9896
9860
  }
9897
9861
  ),
9898
9862
  playerLeft !== null && playerTop !== null && /* @__PURE__ */ jsxRuntime.jsx(
9899
- "div",
9863
+ Box,
9900
9864
  {
9865
+ position: "absolute",
9901
9866
  style: {
9902
- position: "absolute",
9903
9867
  left: playerLeft,
9904
9868
  top: playerTop,
9905
9869
  width: 3,
@@ -9920,6 +9884,7 @@ var init_MiniMap = __esm({
9920
9884
  "components/game/2d/atoms/MiniMap.tsx"() {
9921
9885
  "use client";
9922
9886
  init_cn();
9887
+ init_Box();
9923
9888
  DEFAULT_TILES = [
9924
9889
  { x: 10, y: 10, color: "#4ade80" },
9925
9890
  { x: 20, y: 15, color: "#4ade80" },
@@ -9937,38 +9902,6 @@ var init_MiniMap = __esm({
9937
9902
  MiniMap.displayName = "MiniMap";
9938
9903
  }
9939
9904
  });
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
9905
  function ControlGrid({
9973
9906
  kind,
9974
9907
  buttons = DEFAULT_BUTTONS,
@@ -10029,22 +9962,22 @@ function ControlGrid({
10029
9962
  },
10030
9963
  d
10031
9964
  );
10032
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
10033
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9965
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
9966
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10034
9967
  dir("up"),
10035
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9968
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10036
9969
  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" }) }),
9970
+ /* @__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
9971
  dir("right"),
10039
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9972
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10040
9973
  dir("down"),
10041
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
9974
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10042
9975
  ] });
10043
9976
  }
10044
9977
  if (layout === "diamond" && buttons.length === 4) {
10045
9978
  const [top, right, bottom, left] = buttons;
10046
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(layoutClass.diamond, className), children: [
10047
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9979
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(layoutClass.diamond, className), children: [
9980
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10048
9981
  /* @__PURE__ */ jsxRuntime.jsx(
10049
9982
  ControlButton,
10050
9983
  {
@@ -10059,7 +9992,7 @@ function ControlGrid({
10059
9992
  disabled
10060
9993
  }
10061
9994
  ),
10062
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
9995
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10063
9996
  /* @__PURE__ */ jsxRuntime.jsx(
10064
9997
  ControlButton,
10065
9998
  {
@@ -10074,7 +10007,7 @@ function ControlGrid({
10074
10007
  disabled
10075
10008
  }
10076
10009
  ),
10077
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10010
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10078
10011
  /* @__PURE__ */ jsxRuntime.jsx(
10079
10012
  ControlButton,
10080
10013
  {
@@ -10089,7 +10022,7 @@ function ControlGrid({
10089
10022
  disabled
10090
10023
  }
10091
10024
  ),
10092
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10025
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10093
10026
  /* @__PURE__ */ jsxRuntime.jsx(
10094
10027
  ControlButton,
10095
10028
  {
@@ -10104,10 +10037,10 @@ function ControlGrid({
10104
10037
  disabled
10105
10038
  }
10106
10039
  ),
10107
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10040
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10108
10041
  ] });
10109
10042
  }
10110
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10043
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10111
10044
  ControlButton,
10112
10045
  {
10113
10046
  icon: button.icon,
@@ -10129,6 +10062,7 @@ var init_ControlGrid = __esm({
10129
10062
  "use client";
10130
10063
  init_cn();
10131
10064
  init_useEventBus();
10065
+ init_Box();
10132
10066
  init_ControlButton();
10133
10067
  sizeKey = { sm: "sm", md: "md", lg: "lg" };
10134
10068
  layoutClass = {
@@ -10173,7 +10107,7 @@ function StatBadge({
10173
10107
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
10174
10108
  const resolvedAsset = iconUrl ?? assetUrl;
10175
10109
  return /* @__PURE__ */ jsxRuntime.jsxs(
10176
- "div",
10110
+ Box,
10177
10111
  {
10178
10112
  className: cn(
10179
10113
  "inline-flex items-center gap-2 rounded-container border backdrop-blur-sm",
@@ -10182,18 +10116,8 @@ function StatBadge({
10182
10116
  className
10183
10117
  ),
10184
10118
  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 }),
10119
+ 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,
10120
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
10197
10121
  format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
10198
10122
  HealthBar,
10199
10123
  {
@@ -10219,7 +10143,7 @@ function StatBadge({
10219
10143
  size: size === "lg" ? "md" : "sm"
10220
10144
  }
10221
10145
  ),
10222
- format === "text" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-foreground", children: value })
10146
+ format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
10223
10147
  ]
10224
10148
  }
10225
10149
  );
@@ -10229,6 +10153,9 @@ var init_StatBadge = __esm({
10229
10153
  "components/game/2d/molecules/StatBadge.tsx"() {
10230
10154
  init_cn();
10231
10155
  init_Icon();
10156
+ init_Box();
10157
+ init_Typography();
10158
+ init_GameIcon();
10232
10159
  init_HealthBar();
10233
10160
  init_ScoreDisplay();
10234
10161
  sizeMap14 = {
@@ -10406,9 +10333,9 @@ function GameHud({
10406
10333
  if (position === "corners") {
10407
10334
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
10408
10335
  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)) })
10336
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn(positionMap[position], className), children: [
10337
+ /* @__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)) }),
10338
+ /* @__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
10339
  ] });
10413
10340
  }
10414
10341
  if (position === "top" || position === "bottom") {
@@ -10417,7 +10344,7 @@ function GameHud({
10417
10344
  const rightStats = stats.slice(mid);
10418
10345
  const isTop = position === "top";
10419
10346
  return /* @__PURE__ */ jsxRuntime.jsxs(
10420
- "div",
10347
+ Box,
10421
10348
  {
10422
10349
  className: cn(
10423
10350
  "flex items-center justify-between w-full",
@@ -10427,17 +10354,18 @@ function GameHud({
10427
10354
  className
10428
10355
  ),
10429
10356
  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)) })
10357
+ /* @__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)) }),
10358
+ 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
10359
  ]
10433
10360
  }
10434
10361
  );
10435
10362
  }
10436
10363
  return /* @__PURE__ */ jsxRuntime.jsx(
10437
- "div",
10364
+ Box,
10438
10365
  {
10366
+ position: "relative",
10439
10367
  className: cn(
10440
- "relative z-10 flex items-center gap-4 px-4 py-2",
10368
+ "z-10 flex items-center gap-4 px-4 py-2",
10441
10369
  transparent ? "bg-black/30 backdrop-blur-sm" : "bg-surface/90 backdrop-blur-sm",
10442
10370
  className
10443
10371
  ),
@@ -10449,6 +10377,7 @@ var positionMap, DEFAULT_HUD_STATS;
10449
10377
  var init_GameHud = __esm({
10450
10378
  "components/game/2d/molecules/GameHud.tsx"() {
10451
10379
  init_cn();
10380
+ init_Box();
10452
10381
  init_StatBadge();
10453
10382
  positionMap = {
10454
10383
  corners: "inset-0 pointer-events-none"
@@ -10489,7 +10418,7 @@ function GameMenu({
10489
10418
  [eventBus, onSelect]
10490
10419
  );
10491
10420
  return /* @__PURE__ */ jsxRuntime.jsxs(
10492
- "div",
10421
+ Box,
10493
10422
  {
10494
10423
  className: cn(
10495
10424
  "min-h-screen w-full flex flex-col items-center justify-center p-8",
@@ -10499,18 +10428,12 @@ function GameMenu({
10499
10428
  background: background ?? "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0e17 100%)"
10500
10429
  },
10501
10430
  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
- ),
10431
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "text-center mb-12 animate-fade-in", children: [
10432
+ 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
10433
  /* @__PURE__ */ jsxRuntime.jsx(
10512
- "h1",
10434
+ Typography,
10513
10435
  {
10436
+ variant: "h1",
10514
10437
  className: "text-5xl md:text-7xl font-bold text-[var(--color-foreground)] tracking-tight",
10515
10438
  style: {
10516
10439
  textShadow: "0 4px 12px rgba(0,0,0,0.5)"
@@ -10518,9 +10441,9 @@ function GameMenu({
10518
10441
  children: title
10519
10442
  }
10520
10443
  ),
10521
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
10444
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
10522
10445
  ] }),
10523
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
10446
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
10524
10447
  ChoiceButton,
10525
10448
  {
10526
10449
  text: option.label,
@@ -10531,9 +10454,9 @@ function GameMenu({
10531
10454
  },
10532
10455
  index
10533
10456
  )) }),
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" })
10457
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "absolute", className: "inset-0 pointer-events-none overflow-hidden", children: [
10458
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
10459
+ /* @__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
10460
  ] })
10538
10461
  ]
10539
10462
  }
@@ -10545,6 +10468,9 @@ var init_GameMenu = __esm({
10545
10468
  "use client";
10546
10469
  init_cn();
10547
10470
  init_useEventBus();
10471
+ init_Box();
10472
+ init_Typography();
10473
+ init_GameIcon();
10548
10474
  init_ChoiceButton();
10549
10475
  DEFAULT_MENU_OPTIONS = [
10550
10476
  { label: "New Game", event: "NEW_GAME", variant: "primary" },
@@ -11964,10 +11890,11 @@ function Canvas2D({
11964
11890
  }
11965
11891
  }
11966
11892
  ),
11967
- process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
11893
+ process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
11968
11894
  tileClickEvent && /* @__PURE__ */ jsxRuntime.jsx(
11969
- "button",
11895
+ Button,
11970
11896
  {
11897
+ variant: "ghost",
11971
11898
  "data-event": tileClickEvent,
11972
11899
  "data-x": "0",
11973
11900
  "data-y": "0",
@@ -11976,8 +11903,9 @@ function Canvas2D({
11976
11903
  }
11977
11904
  ),
11978
11905
  unitClickEvent && units && units.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
11979
- "button",
11906
+ Button,
11980
11907
  {
11908
+ variant: "ghost",
11981
11909
  "data-event": unitClickEvent,
11982
11910
  "data-unit-id": units[0].id,
11983
11911
  onClick: () => eventBus.emit(`UI:${unitClickEvent}`, { unitId: units[0].id }),
@@ -11986,15 +11914,17 @@ function Canvas2D({
11986
11914
  )
11987
11915
  ] }),
11988
11916
  unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxRuntime.jsxs(
11989
- "div",
11917
+ Box,
11990
11918
  {
11991
- className: "absolute pointer-events-none",
11919
+ position: "absolute",
11920
+ className: "pointer-events-none",
11992
11921
  style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
11993
11922
  children: [
11994
11923
  unit.name && /* @__PURE__ */ jsxRuntime.jsx(
11995
- "div",
11924
+ Typography,
11996
11925
  {
11997
- className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
11926
+ as: "span",
11927
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
11998
11928
  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
11929
  children: unit.name
12000
11930
  }
@@ -12004,7 +11934,7 @@ function Canvas2D({
12004
11934
  },
12005
11935
  unit.id
12006
11936
  )),
12007
- showMinimap && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
11937
+ showMinimap && /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
12008
11938
  MiniMap,
12009
11939
  {
12010
11940
  tiles: miniMapTiles,
@@ -12026,6 +11956,7 @@ var init_Canvas2D = __esm({
12026
11956
  init_cn();
12027
11957
  init_useEventBus();
12028
11958
  init_Box();
11959
+ init_Button();
12029
11960
  init_Stack();
12030
11961
  init_Icon();
12031
11962
  init_Typography();
@@ -12357,7 +12288,7 @@ function GameAudioToggle({
12357
12288
  onClick: handleToggle,
12358
12289
  className: cn("text-lg leading-none px-2", className),
12359
12290
  "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}"
12291
+ 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
12292
  }
12362
12293
  );
12363
12294
  }
@@ -12367,6 +12298,7 @@ var init_GameAudioToggle = __esm({
12367
12298
  init_atoms();
12368
12299
  init_cn();
12369
12300
  init_GameAudioProvider();
12301
+ init_GameIcon();
12370
12302
  GameAudioToggle.displayName = "GameAudioToggle";
12371
12303
  }
12372
12304
  });