@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.
package/dist/avl/index.js CHANGED
@@ -5384,6 +5384,7 @@ var init_Button = __esm({
5384
5384
  rightIcon,
5385
5385
  icon: iconProp,
5386
5386
  iconRight: iconRightProp,
5387
+ iconAsset,
5387
5388
  action,
5388
5389
  actionPayload,
5389
5390
  label,
@@ -5395,7 +5396,8 @@ var init_Button = __esm({
5395
5396
  const eventBus = useEventBus();
5396
5397
  const leftIconValue = leftIcon || iconProp;
5397
5398
  const rightIconValue = rightIcon || iconRightProp;
5398
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
5399
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
5400
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ jsx("img", { src: iconAsset.url, alt: iconAsset.name ?? iconAsset.category ?? "", width: px, height: px, style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px }, className: "flex-shrink-0" }) : resolveIconProp(leftIconValue, iconSizeStyles[size]);
5399
5401
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
5400
5402
  const handleClick = (e) => {
5401
5403
  if (action) {
@@ -5935,13 +5937,14 @@ var init_Badge = __esm({
5935
5937
  lg: "px-3 py-1.5 text-base"
5936
5938
  };
5937
5939
  Badge = React112__default.forwardRef(
5938
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
5940
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
5939
5941
  const iconSizes3 = {
5940
5942
  sm: "h-icon-default w-icon-default",
5941
5943
  md: "h-icon-default w-icon-default",
5942
5944
  lg: "h-icon-default w-icon-default"
5943
5945
  };
5944
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
5946
+ const iconPx = size === "lg" ? 20 : 16;
5947
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ jsx("img", { src: iconAsset.url, alt: iconAsset.name ?? iconAsset.category ?? "", width: iconPx, height: iconPx, style: { imageRendering: "pixelated", objectFit: "contain", width: iconPx, height: iconPx }, className: "flex-shrink-0" }) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
5945
5948
  return /* @__PURE__ */ jsxs(
5946
5949
  "span",
5947
5950
  {
@@ -12111,10 +12114,43 @@ var init_shared = __esm({
12111
12114
  init_canvasEffects();
12112
12115
  }
12113
12116
  });
12117
+ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
12118
+ const px = typeof size === "number" ? size : sizeMap[size];
12119
+ if (assetUrl?.url) {
12120
+ return /* @__PURE__ */ jsx(
12121
+ "img",
12122
+ {
12123
+ src: assetUrl.url,
12124
+ alt: alt ?? assetUrl.category ?? "",
12125
+ width: px,
12126
+ height: px,
12127
+ style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
12128
+ className: cn("flex-shrink-0", className)
12129
+ }
12130
+ );
12131
+ }
12132
+ const I = typeof icon === "string" ? resolveIcon(icon) : icon;
12133
+ return /* @__PURE__ */ jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
12134
+ }
12135
+ var sizeMap;
12136
+ var init_GameIcon = __esm({
12137
+ "components/game/2d/atoms/GameIcon.tsx"() {
12138
+ "use client";
12139
+ init_cn();
12140
+ init_Icon();
12141
+ sizeMap = {
12142
+ sm: 16,
12143
+ md: 24,
12144
+ lg: 32
12145
+ };
12146
+ GameIcon.displayName = "GameIcon";
12147
+ }
12148
+ });
12114
12149
  function GameCard({
12115
12150
  id,
12116
12151
  cost,
12117
12152
  art,
12153
+ frameAsset,
12118
12154
  attack,
12119
12155
  defense,
12120
12156
  name,
@@ -12132,16 +12168,19 @@ function GameCard({
12132
12168
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
12133
12169
  }, [disabled, id, onClick, clickEvent, eventBus]);
12134
12170
  const artPx = artPxMap[size];
12171
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
12135
12172
  return /* @__PURE__ */ jsxs(
12136
- "button",
12173
+ Button,
12137
12174
  {
12138
- type: "button",
12175
+ variant: "ghost",
12139
12176
  onClick: handleClick,
12140
12177
  disabled,
12141
12178
  title: name,
12179
+ style: frameStyle,
12142
12180
  className: cn(
12143
- "relative flex flex-col items-center rounded-interactive border-2",
12181
+ "relative flex flex-col items-center rounded-interactive",
12144
12182
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
12183
+ frameAsset?.url ? "border-0" : "border-2",
12145
12184
  cardSizeMap[size],
12146
12185
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
12147
12186
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -12149,8 +12188,9 @@ function GameCard({
12149
12188
  ),
12150
12189
  children: [
12151
12190
  cost != null && /* @__PURE__ */ jsx(
12152
- "span",
12191
+ Typography,
12153
12192
  {
12193
+ as: "span",
12154
12194
  className: cn(
12155
12195
  "absolute -top-2 -left-2 flex items-center justify-center",
12156
12196
  "min-w-[22px] h-[22px] rounded-full px-1",
@@ -12159,17 +12199,7 @@ function GameCard({
12159
12199
  children: cost
12160
12200
  }
12161
12201
  ),
12162
- /* @__PURE__ */ jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsx(
12163
- "img",
12164
- {
12165
- src: art.url,
12166
- alt: name ?? id,
12167
- width: artPx,
12168
- height: artPx,
12169
- style: { imageRendering: "pixelated", objectFit: "contain" },
12170
- className: "flex-shrink-0"
12171
- }
12172
- ) : /* @__PURE__ */ jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
12202
+ /* @__PURE__ */ jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsx(GameIcon, { assetUrl: art, icon: "image", size: artPx, alt: name ?? id, className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
12173
12203
  name != null && /* @__PURE__ */ jsx(
12174
12204
  Typography,
12175
12205
  {
@@ -12179,8 +12209,8 @@ function GameCard({
12179
12209
  }
12180
12210
  ),
12181
12211
  (attack != null || defense != null) && /* @__PURE__ */ jsxs(Box, { className: "flex w-full items-center justify-between px-0.5 text-[10px] font-bold leading-none", children: [
12182
- /* @__PURE__ */ jsx("span", { className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
12183
- /* @__PURE__ */ jsx("span", { className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
12212
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
12213
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
12184
12214
  ] })
12185
12215
  ]
12186
12216
  }
@@ -12193,7 +12223,9 @@ var init_GameCard = __esm({
12193
12223
  init_cn();
12194
12224
  init_useEventBus();
12195
12225
  init_Box();
12226
+ init_Button();
12196
12227
  init_Typography();
12228
+ init_GameIcon();
12197
12229
  cardSizeMap = {
12198
12230
  sm: "w-16 h-24",
12199
12231
  md: "w-20 h-28",
@@ -12216,12 +12248,13 @@ function HealthBar({
12216
12248
  frameAsset,
12217
12249
  fillAsset
12218
12250
  }) {
12219
- const sizes = sizeMap[size];
12251
+ const sizes = sizeMap2[size];
12220
12252
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
12221
12253
  if (format === "hearts") {
12222
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx(
12223
- "span",
12254
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx(
12255
+ Box,
12224
12256
  {
12257
+ as: "span",
12225
12258
  className: cn(animated && "transition-transform hover:scale-110"),
12226
12259
  children: heartIcon(i < current, sizes.heart)
12227
12260
  },
@@ -12230,10 +12263,12 @@ function HealthBar({
12230
12263
  }
12231
12264
  if (format === "bar") {
12232
12265
  return /* @__PURE__ */ jsx(
12233
- "div",
12266
+ Box,
12234
12267
  {
12268
+ position: "relative",
12269
+ overflow: "hidden",
12235
12270
  className: cn(
12236
- "relative overflow-hidden rounded-full",
12271
+ "rounded-full",
12237
12272
  !frameAsset && "bg-muted",
12238
12273
  sizes.bar,
12239
12274
  "w-24",
@@ -12241,10 +12276,11 @@ function HealthBar({
12241
12276
  ),
12242
12277
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
12243
12278
  children: /* @__PURE__ */ jsx(
12244
- "div",
12279
+ Box,
12245
12280
  {
12281
+ position: "absolute",
12246
12282
  className: cn(
12247
- "absolute inset-y-0 left-0 rounded-full",
12283
+ "inset-y-0 left-0 rounded-full",
12248
12284
  !fillAsset && (percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error"),
12249
12285
  animated && "transition-all duration-300"
12250
12286
  ),
@@ -12258,10 +12294,11 @@ function HealthBar({
12258
12294
  );
12259
12295
  }
12260
12296
  if (format === "progress") {
12261
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
12297
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex items-center gap-2", className), children: [
12262
12298
  level != null && /* @__PURE__ */ jsxs(
12263
- "span",
12299
+ Typography,
12264
12300
  {
12301
+ as: "span",
12265
12302
  className: cn(
12266
12303
  "flex-shrink-0 rounded-interactive font-bold",
12267
12304
  "bg-accent text-accent-foreground border border-accent",
@@ -12273,21 +12310,23 @@ function HealthBar({
12273
12310
  ]
12274
12311
  }
12275
12312
  ),
12276
- /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [
12313
+ /* @__PURE__ */ jsxs(Box, { className: "flex-1 flex flex-col gap-0.5", children: [
12277
12314
  /* @__PURE__ */ jsx(
12278
- "div",
12315
+ Box,
12279
12316
  {
12317
+ position: "relative",
12280
12318
  className: cn(
12281
- "relative w-full overflow-hidden rounded-full",
12319
+ "w-full overflow-hidden rounded-full",
12282
12320
  !frameAsset && "bg-muted border border-muted",
12283
12321
  sizes.bar
12284
12322
  ),
12285
12323
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
12286
12324
  children: /* @__PURE__ */ jsx(
12287
- "div",
12325
+ Box,
12288
12326
  {
12327
+ position: "absolute",
12289
12328
  className: cn(
12290
- "absolute inset-y-0 left-0 rounded-full",
12329
+ "inset-y-0 left-0 rounded-full",
12291
12330
  !fillAsset && "bg-gradient-to-r from-accent to-info",
12292
12331
  animated && "transition-all duration-500 ease-out"
12293
12332
  ),
@@ -12299,7 +12338,7 @@ function HealthBar({
12299
12338
  )
12300
12339
  }
12301
12340
  ),
12302
- showLabel && /* @__PURE__ */ jsxs("span", { className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
12341
+ showLabel && /* @__PURE__ */ jsxs(Typography, { as: "span", className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
12303
12342
  current,
12304
12343
  " / ",
12305
12344
  max,
@@ -12308,16 +12347,18 @@ function HealthBar({
12308
12347
  ] })
12309
12348
  ] });
12310
12349
  }
12311
- return /* @__PURE__ */ jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
12350
+ return /* @__PURE__ */ jsxs(Typography, { as: "span", className: cn("font-mono font-bold", sizes.text, className), children: [
12312
12351
  current,
12313
12352
  "/",
12314
12353
  max
12315
12354
  ] });
12316
12355
  }
12317
- var heartIcon, sizeMap;
12356
+ var heartIcon, sizeMap2;
12318
12357
  var init_HealthBar = __esm({
12319
12358
  "components/game/2d/atoms/HealthBar.tsx"() {
12320
12359
  init_cn();
12360
+ init_Box();
12361
+ init_Typography();
12321
12362
  heartIcon = (filled, size) => /* @__PURE__ */ jsx(
12322
12363
  "svg",
12323
12364
  {
@@ -12329,7 +12370,7 @@ var init_HealthBar = __esm({
12329
12370
  children: /* @__PURE__ */ 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" })
12330
12371
  }
12331
12372
  );
12332
- sizeMap = {
12373
+ sizeMap2 = {
12333
12374
  sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm", label: "text-xs", badge: "text-xs px-1.5 py-0.5" },
12334
12375
  md: { heart: "w-6 h-6", bar: "h-3", text: "text-base", label: "text-xs", badge: "text-xs px-2 py-0.5" },
12335
12376
  lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg", label: "text-sm", badge: "text-sm px-2.5 py-1" }
@@ -12350,37 +12391,30 @@ function ScoreDisplay({
12350
12391
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
12351
12392
  const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
12352
12393
  return /* @__PURE__ */ jsxs(
12353
- "div",
12394
+ Box,
12354
12395
  {
12355
12396
  className: cn(
12356
12397
  "flex items-center gap-2 font-bold",
12357
- sizeMap2[size],
12398
+ sizeMap3[size],
12358
12399
  className
12359
12400
  ),
12360
12401
  children: [
12361
- assetUrl ? /* @__PURE__ */ jsx(
12362
- "img",
12363
- {
12364
- src: assetUrl.url,
12365
- alt: "",
12366
- width: 20,
12367
- height: 20,
12368
- style: { imageRendering: "pixelated", objectFit: "contain" },
12369
- className: "flex-shrink-0"
12370
- }
12371
- ) : icon ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) }) : null,
12372
- label && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
12373
- /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formattedValue })
12402
+ assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: 20, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) }) : null,
12403
+ label && /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
12404
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "tabular-nums", children: formattedValue })
12374
12405
  ]
12375
12406
  }
12376
12407
  );
12377
12408
  }
12378
- var sizeMap2, DEFAULT_ASSET_URL;
12409
+ var sizeMap3, DEFAULT_ASSET_URL;
12379
12410
  var init_ScoreDisplay = __esm({
12380
12411
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
12381
12412
  init_cn();
12382
12413
  init_Icon();
12383
- sizeMap2 = {
12414
+ init_Box();
12415
+ init_Typography();
12416
+ init_GameIcon();
12417
+ sizeMap3 = {
12384
12418
  sm: "text-sm",
12385
12419
  md: "text-lg",
12386
12420
  lg: "text-2xl",
@@ -12443,9 +12477,9 @@ function ControlButton({
12443
12477
  [isPressed, releaseEvent, eventBus, onRelease]
12444
12478
  );
12445
12479
  return /* @__PURE__ */ jsx(
12446
- "button",
12480
+ Button,
12447
12481
  {
12448
- type: "button",
12482
+ variant,
12449
12483
  disabled,
12450
12484
  onPointerDown: handlePointerDown,
12451
12485
  onPointerUp: handlePointerUp,
@@ -12456,41 +12490,35 @@ function ControlButton({
12456
12490
  "select-none touch-none",
12457
12491
  "transition-all duration-100",
12458
12492
  "active:scale-95",
12459
- sizeMap3[size] ?? sizeMap3.md,
12493
+ sizeMap4[size] ?? sizeMap4.md,
12460
12494
  shapeMap[shape] ?? shapeMap.circle,
12461
12495
  variantMap[variant] ?? variantMap.secondary,
12462
12496
  actualPressed && "scale-95 brightness-110 border-foreground",
12463
12497
  disabled && "opacity-50 cursor-not-allowed",
12464
12498
  className
12465
12499
  ),
12466
- children: assetUrl ? /* @__PURE__ */ jsx(
12467
- "img",
12468
- {
12469
- src: assetUrl.url,
12470
- alt: "",
12471
- width: 24,
12472
- height: 24,
12473
- style: { imageRendering: "pixelated", objectFit: "contain" },
12474
- className: "flex-shrink-0"
12475
- }
12476
- ) : icon ? /* @__PURE__ */ jsx("span", { className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
12500
+ children: assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
12477
12501
  const I = resolveIcon(icon);
12478
12502
  return I ? /* @__PURE__ */ jsx(I, { className: "w-6 h-6" }) : null;
12479
12503
  })() : icon : /* @__PURE__ */ (() => {
12480
12504
  const I = icon;
12481
12505
  return /* @__PURE__ */ jsx(I, { className: "w-6 h-6" });
12482
- })() }) : label ? /* @__PURE__ */ jsx("span", { children: label }) : null
12506
+ })() }) : label ? /* @__PURE__ */ jsx(Typography, { as: "span", children: label }) : null
12483
12507
  }
12484
12508
  );
12485
12509
  }
12486
- var sizeMap3, shapeMap, variantMap, DEFAULT_ASSET_URL2;
12510
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
12487
12511
  var init_ControlButton = __esm({
12488
12512
  "components/game/2d/atoms/ControlButton.tsx"() {
12489
12513
  "use client";
12490
12514
  init_cn();
12491
12515
  init_useEventBus();
12492
12516
  init_Icon();
12493
- sizeMap3 = {
12517
+ init_Button();
12518
+ init_Box();
12519
+ init_Typography();
12520
+ init_GameIcon();
12521
+ sizeMap4 = {
12494
12522
  sm: "w-10 h-10 text-sm",
12495
12523
  md: "w-14 h-14 text-base",
12496
12524
  lg: "w-18 h-18 text-lg",
@@ -12560,12 +12588,12 @@ function Sprite({
12560
12588
  onClick?.();
12561
12589
  };
12562
12590
  return /* @__PURE__ */ jsx(
12563
- "div",
12591
+ Box,
12564
12592
  {
12593
+ position: "absolute",
12565
12594
  className,
12566
12595
  onClick: action || onClick ? handleClick : void 0,
12567
12596
  style: {
12568
- position: "absolute",
12569
12597
  width: frameWidth,
12570
12598
  height: frameHeight,
12571
12599
  backgroundImage: `url(${spritesheet.url})`,
@@ -12586,6 +12614,7 @@ var init_Sprite = __esm({
12586
12614
  "components/game/2d/atoms/Sprite.tsx"() {
12587
12615
  "use client";
12588
12616
  init_useEventBus();
12617
+ init_Box();
12589
12618
  init_spriteAnimation();
12590
12619
  DEFAULT_SPRITESHEET = {
12591
12620
  url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
@@ -12622,17 +12651,7 @@ function StateIndicator({
12622
12651
  className
12623
12652
  ),
12624
12653
  children: [
12625
- /* @__PURE__ */ jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsx(
12626
- "img",
12627
- {
12628
- src: assetUrl.url,
12629
- alt: displayLabel,
12630
- width: 16,
12631
- height: 16,
12632
- style: { imageRendering: "pixelated", objectFit: "contain" },
12633
- className: "flex-shrink-0"
12634
- }
12635
- ) : typeof config.icon === "string" ? /^[a-zA-Z0-9-]+$/.test(config.icon) ? /* @__PURE__ */ jsx(Icon, { name: config.icon }) : config.icon : /* @__PURE__ */ jsx(Icon, { icon: config.icon }) }),
12654
+ /* @__PURE__ */ jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: config.icon }) : config.icon : /* @__PURE__ */ jsx(Icon, { icon: config.icon }) }),
12636
12655
  /* @__PURE__ */ jsx(Box, { as: "span", children: displayLabel })
12637
12656
  ]
12638
12657
  }
@@ -12644,6 +12663,7 @@ var init_StateIndicator = __esm({
12644
12663
  init_Box();
12645
12664
  init_Icon();
12646
12665
  init_cn();
12666
+ init_GameIcon();
12647
12667
  DEFAULT_ASSET_URL3 = {
12648
12668
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
12649
12669
  role: "ui",
@@ -12697,29 +12717,31 @@ function TimerDisplay({
12697
12717
  }) {
12698
12718
  const isLow = lowThreshold != null && seconds <= lowThreshold && seconds > 0;
12699
12719
  return /* @__PURE__ */ jsxs(
12700
- "div",
12720
+ Box,
12701
12721
  {
12702
12722
  className: cn(
12703
12723
  "inline-flex items-center gap-1 justify-center rounded-container",
12704
12724
  "bg-card/80 border border-muted font-mono font-bold tabular-nums",
12705
- sizeMap4[size],
12725
+ sizeMap5[size],
12706
12726
  running && "border-success/50",
12707
12727
  isLow && "text-error border-error/50 animate-pulse",
12708
12728
  !isLow && "text-foreground",
12709
12729
  className
12710
12730
  ),
12711
12731
  children: [
12712
- iconAsset && /* @__PURE__ */ jsx("img", { src: iconAsset.url, alt: "", className: "w-4 h-4 object-contain flex-shrink-0" }),
12732
+ iconAsset && /* @__PURE__ */ jsx(GameIcon, { assetUrl: iconAsset, icon: "image", size: 16, className: "w-4 h-4 object-contain flex-shrink-0" }),
12713
12733
  formatTime(seconds, format)
12714
12734
  ]
12715
12735
  }
12716
12736
  );
12717
12737
  }
12718
- var sizeMap4;
12738
+ var sizeMap5;
12719
12739
  var init_TimerDisplay = __esm({
12720
12740
  "components/game/2d/atoms/TimerDisplay.tsx"() {
12721
12741
  init_cn();
12722
- sizeMap4 = {
12742
+ init_Box();
12743
+ init_GameIcon();
12744
+ sizeMap5 = {
12723
12745
  sm: "text-sm px-2 py-0.5",
12724
12746
  md: "text-lg px-3 py-1",
12725
12747
  lg: "text-2xl px-4 py-1.5"
@@ -12737,9 +12759,9 @@ function ResourceCounter({
12737
12759
  size = "md",
12738
12760
  className
12739
12761
  }) {
12740
- const sizes = sizeMap5[size];
12762
+ const sizes = sizeMap6[size];
12741
12763
  return /* @__PURE__ */ jsxs(
12742
- "div",
12764
+ Box,
12743
12765
  {
12744
12766
  className: cn(
12745
12767
  "inline-flex items-center rounded-container",
@@ -12748,21 +12770,11 @@ function ResourceCounter({
12748
12770
  className
12749
12771
  ),
12750
12772
  children: [
12751
- assetUrl ? /* @__PURE__ */ jsx(
12752
- "img",
12753
- {
12754
- src: assetUrl.url,
12755
- alt: label,
12756
- width: sizes.img,
12757
- height: sizes.img,
12758
- style: { imageRendering: "pixelated", objectFit: "contain" },
12759
- className: "flex-shrink-0"
12760
- }
12761
- ) : icon ? /* @__PURE__ */ jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) }) : null,
12762
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
12763
- /* @__PURE__ */ jsxs("span", { className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
12773
+ assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) }) : null,
12774
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
12775
+ /* @__PURE__ */ jsxs(Typography, { as: "span", className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
12764
12776
  value,
12765
- max != null && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
12777
+ max != null && /* @__PURE__ */ jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
12766
12778
  "/",
12767
12779
  max
12768
12780
  ] })
@@ -12771,11 +12783,14 @@ function ResourceCounter({
12771
12783
  }
12772
12784
  );
12773
12785
  }
12774
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap5;
12786
+ var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
12775
12787
  var init_ResourceCounter = __esm({
12776
12788
  "components/game/2d/atoms/ResourceCounter.tsx"() {
12777
12789
  init_cn();
12778
12790
  init_Icon();
12791
+ init_Box();
12792
+ init_Typography();
12793
+ init_GameIcon();
12779
12794
  colorTokenClasses2 = {
12780
12795
  primary: "text-primary",
12781
12796
  secondary: "text-secondary",
@@ -12789,7 +12804,7 @@ var init_ResourceCounter = __esm({
12789
12804
  role: "ui",
12790
12805
  category: "coin"
12791
12806
  };
12792
- sizeMap5 = {
12807
+ sizeMap6 = {
12793
12808
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
12794
12809
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
12795
12810
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -12814,9 +12829,9 @@ function ItemSlot({
12814
12829
  const isClickable = onClick != null || action != null;
12815
12830
  const px = assetSizeMap[size];
12816
12831
  return /* @__PURE__ */ jsx(
12817
- "button",
12832
+ Button,
12818
12833
  {
12819
- type: "button",
12834
+ variant: "ghost",
12820
12835
  onClick: () => {
12821
12836
  if (action) eventBus.emit(`UI:${action}`, {});
12822
12837
  onClick?.();
@@ -12826,7 +12841,7 @@ function ItemSlot({
12826
12841
  className: cn(
12827
12842
  "relative flex items-center justify-center rounded-interactive border-2",
12828
12843
  "bg-card/80 transition-all duration-150",
12829
- sizeMap6[size],
12844
+ sizeMap7[size],
12830
12845
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
12831
12846
  !empty && rarityGlowMap[rarity],
12832
12847
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -12835,21 +12850,12 @@ function ItemSlot({
12835
12850
  !isClickable && "cursor-default",
12836
12851
  className
12837
12852
  ),
12838
- children: empty ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
12839
- assetUrl ? /* @__PURE__ */ jsx(
12840
- "img",
12841
- {
12842
- src: assetUrl?.url,
12843
- alt: label,
12844
- width: px,
12845
- height: px,
12846
- style: { imageRendering: "pixelated", objectFit: "contain" },
12847
- className: "flex-shrink-0"
12848
- }
12849
- ) : icon ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) }) : null,
12853
+ children: empty ? /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
12854
+ assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: px, alt: label, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) }) : null,
12850
12855
  quantity != null && quantity > 1 && /* @__PURE__ */ jsx(
12851
- "span",
12856
+ Typography,
12852
12857
  {
12858
+ as: "span",
12853
12859
  className: cn(
12854
12860
  "absolute -bottom-1 -right-1 flex items-center justify-center",
12855
12861
  "min-w-[18px] h-[18px] rounded-full px-1",
@@ -12862,14 +12868,18 @@ function ItemSlot({
12862
12868
  }
12863
12869
  );
12864
12870
  }
12865
- var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
12871
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
12866
12872
  var init_ItemSlot = __esm({
12867
12873
  "components/game/2d/atoms/ItemSlot.tsx"() {
12868
12874
  "use client";
12869
12875
  init_cn();
12870
12876
  init_Icon();
12871
12877
  init_useEventBus();
12872
- sizeMap6 = {
12878
+ init_Button();
12879
+ init_Box();
12880
+ init_Typography();
12881
+ init_GameIcon();
12882
+ sizeMap7 = {
12873
12883
  sm: "w-10 h-10 text-lg",
12874
12884
  md: "w-14 h-14 text-2xl",
12875
12885
  lg: "w-18 h-18 text-3xl"
@@ -12910,9 +12920,9 @@ function TurnIndicator({
12910
12920
  size = "md",
12911
12921
  className
12912
12922
  }) {
12913
- const sizes = sizeMap7[size];
12923
+ const sizes = sizeMap8[size];
12914
12924
  return /* @__PURE__ */ jsxs(
12915
- "div",
12925
+ Box,
12916
12926
  {
12917
12927
  className: cn(
12918
12928
  "inline-flex items-center rounded-container",
@@ -12921,42 +12931,35 @@ function TurnIndicator({
12921
12931
  className
12922
12932
  ),
12923
12933
  children: [
12924
- /* @__PURE__ */ jsxs("span", { className: "font-bold tabular-nums", children: [
12934
+ /* @__PURE__ */ jsxs(Typography, { as: "span", className: "font-bold tabular-nums", children: [
12925
12935
  "Turn ",
12926
12936
  currentTurn,
12927
- maxTurns != null && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
12937
+ maxTurns != null && /* @__PURE__ */ jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
12928
12938
  "/",
12929
12939
  maxTurns
12930
12940
  ] })
12931
12941
  ] }),
12932
12942
  phase && /* @__PURE__ */ jsxs(Fragment, { children: [
12933
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "|" }),
12934
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: phase })
12943
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
12944
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground", children: phase })
12935
12945
  ] }),
12936
12946
  activeTeam && /* @__PURE__ */ jsxs(Fragment, { children: [
12937
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "|" }),
12938
- assetUrl ? /* @__PURE__ */ jsx(
12939
- "img",
12940
- {
12941
- src: assetUrl.url,
12942
- alt: "",
12943
- width: 12,
12944
- height: 12,
12945
- style: { imageRendering: "pixelated", objectFit: "contain" },
12946
- className: "flex-shrink-0"
12947
- }
12948
- ) : /* @__PURE__ */ jsx("span", { className: cn("rounded-full bg-success/20", sizes.dot) }),
12949
- /* @__PURE__ */ jsx("span", { className: "text-success", children: activeTeam })
12947
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
12948
+ assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: 12, className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Box, { as: "span", className: cn("rounded-full bg-success/20", sizes.dot) }),
12949
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-success", children: activeTeam })
12950
12950
  ] })
12951
12951
  ]
12952
12952
  }
12953
12953
  );
12954
12954
  }
12955
- var sizeMap7, DEFAULT_ASSET_URL6;
12955
+ var sizeMap8, DEFAULT_ASSET_URL6;
12956
12956
  var init_TurnIndicator = __esm({
12957
12957
  "components/game/2d/atoms/TurnIndicator.tsx"() {
12958
12958
  init_cn();
12959
- sizeMap7 = {
12959
+ init_Box();
12960
+ init_Typography();
12961
+ init_GameIcon();
12962
+ sizeMap8 = {
12960
12963
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
12961
12964
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
12962
12965
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
@@ -12988,10 +12991,10 @@ function ComboCounter({
12988
12991
  size = "md",
12989
12992
  className
12990
12993
  }) {
12991
- const sizes = sizeMap8[size];
12994
+ const sizes = sizeMap9[size];
12992
12995
  if (combo <= 0) return null;
12993
12996
  return /* @__PURE__ */ jsxs(
12994
- "div",
12997
+ Box,
12995
12998
  {
12996
12999
  className: cn(
12997
13000
  "inline-flex flex-col items-center justify-center",
@@ -13001,24 +13004,14 @@ function ComboCounter({
13001
13004
  className
13002
13005
  ),
13003
13006
  children: [
13004
- assetUrl && /* @__PURE__ */ jsx(
13005
- "img",
13006
- {
13007
- src: assetUrl.url,
13008
- alt: "combo",
13009
- width: 24,
13010
- height: 24,
13011
- style: { imageRendering: "pixelated", objectFit: "contain" },
13012
- className: "flex-shrink-0 mb-0.5"
13013
- }
13014
- ),
13015
- /* @__PURE__ */ jsx("span", { className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
13016
- /* @__PURE__ */ jsx("span", { className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
13017
- multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxs("span", { className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
13007
+ assetUrl && /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0 mb-0.5" }),
13008
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
13009
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
13010
+ multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxs(Typography, { as: "span", className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
13018
13011
  "x",
13019
13012
  multiplier.toFixed(1)
13020
13013
  ] }),
13021
- streak != null && streak > 0 && /* @__PURE__ */ jsxs("span", { className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
13014
+ streak != null && streak > 0 && /* @__PURE__ */ jsxs(Typography, { as: "span", className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
13022
13015
  streak,
13023
13016
  " streak"
13024
13017
  ] })
@@ -13026,16 +13019,19 @@ function ComboCounter({
13026
13019
  }
13027
13020
  );
13028
13021
  }
13029
- var DEFAULT_ASSET_URL7, sizeMap8;
13022
+ var DEFAULT_ASSET_URL7, sizeMap9;
13030
13023
  var init_ComboCounter = __esm({
13031
13024
  "components/game/2d/atoms/ComboCounter.tsx"() {
13032
13025
  init_cn();
13026
+ init_Box();
13027
+ init_Typography();
13028
+ init_GameIcon();
13033
13029
  DEFAULT_ASSET_URL7 = {
13034
13030
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
13035
13031
  role: "effect",
13036
13032
  category: "effect"
13037
13033
  };
13038
- sizeMap8 = {
13034
+ sizeMap9 = {
13039
13035
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
13040
13036
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
13041
13037
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -13052,54 +13048,48 @@ function WaypointMarker({
13052
13048
  size = "md",
13053
13049
  className
13054
13050
  }) {
13055
- const sizes = sizeMap9[size];
13056
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center", className), children: [
13057
- /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
13051
+ const sizes = sizeMap10[size];
13052
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col items-center", className), children: [
13053
+ /* @__PURE__ */ jsxs(Box, { className: "relative flex items-center justify-center", children: [
13058
13054
  active && /* @__PURE__ */ jsx(
13059
- "div",
13055
+ Box,
13060
13056
  {
13057
+ position: "absolute",
13061
13058
  className: cn(
13062
- "absolute rounded-full border-2 border-info animate-ping opacity-50",
13059
+ "rounded-full border-2 border-info animate-ping opacity-50",
13063
13060
  sizes.ring
13064
13061
  )
13065
13062
  }
13066
13063
  ),
13067
13064
  active && /* @__PURE__ */ jsx(
13068
- "div",
13065
+ Box,
13069
13066
  {
13067
+ position: "absolute",
13070
13068
  className: cn(
13071
- "absolute rounded-full border-2 border-info",
13069
+ "rounded-full border-2 border-info",
13072
13070
  sizes.ring
13073
13071
  )
13074
13072
  }
13075
13073
  ),
13076
13074
  /* @__PURE__ */ jsx(
13077
- "div",
13075
+ Box,
13078
13076
  {
13077
+ position: "relative",
13079
13078
  className: cn(
13080
- "relative flex items-center justify-center rounded-full transition-all duration-200",
13079
+ "flex items-center justify-center rounded-full transition-all duration-200",
13081
13080
  sizes.dot,
13082
13081
  completed && "bg-success text-foreground",
13083
13082
  active && !completed && "bg-info text-foreground",
13084
13083
  !active && !completed && "bg-muted"
13085
13084
  ),
13086
- children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsx(
13087
- "img",
13088
- {
13089
- src: assetUrl.url,
13090
- alt: label,
13091
- width: sizes.img,
13092
- height: sizes.img,
13093
- style: { imageRendering: "pixelated", objectFit: "contain" },
13094
- className: "flex-shrink-0"
13095
- }
13096
- ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) : null
13085
+ children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon }) : /* @__PURE__ */ jsx(Icon, { icon }) : null
13097
13086
  }
13098
13087
  )
13099
13088
  ] }),
13100
13089
  label && /* @__PURE__ */ jsx(
13101
- "span",
13090
+ Typography,
13102
13091
  {
13092
+ as: "span",
13103
13093
  className: cn(
13104
13094
  "text-center whitespace-nowrap",
13105
13095
  sizes.label,
@@ -13110,17 +13100,20 @@ function WaypointMarker({
13110
13100
  )
13111
13101
  ] });
13112
13102
  }
13113
- var DEFAULT_ASSET_URL8, sizeMap9, checkIcon;
13103
+ var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
13114
13104
  var init_WaypointMarker = __esm({
13115
13105
  "components/game/2d/atoms/WaypointMarker.tsx"() {
13116
13106
  init_cn();
13117
13107
  init_Icon();
13108
+ init_Box();
13109
+ init_Typography();
13110
+ init_GameIcon();
13118
13111
  DEFAULT_ASSET_URL8 = {
13119
13112
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
13120
13113
  role: "ui",
13121
13114
  category: "waypoint"
13122
13115
  };
13123
- sizeMap9 = {
13116
+ sizeMap10 = {
13124
13117
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
13125
13118
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
13126
13119
  lg: { dot: "w-8 h-8", ring: "w-10 h-10", label: "text-base mt-2", img: 24 }
@@ -13145,32 +13138,24 @@ function StatusEffect({
13145
13138
  size = "md",
13146
13139
  className
13147
13140
  }) {
13148
- const sizes = sizeMap10[size];
13149
- return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
13141
+ const sizes = sizeMap11[size];
13142
+ return /* @__PURE__ */ jsxs(Box, { position: "relative", className: cn("inline-flex flex-col items-center", className), children: [
13150
13143
  /* @__PURE__ */ jsxs(
13151
- "div",
13144
+ Box,
13152
13145
  {
13146
+ position: "relative",
13153
13147
  className: cn(
13154
- "relative flex items-center justify-center rounded-interactive border-2",
13148
+ "flex items-center justify-center rounded-interactive border-2",
13155
13149
  sizes.container,
13156
13150
  variantStyles7[variant]
13157
13151
  ),
13158
13152
  title: label,
13159
13153
  children: [
13160
- /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
13161
- "img",
13162
- {
13163
- src: assetUrl.url,
13164
- alt: label,
13165
- width: sizes.img,
13166
- height: sizes.img,
13167
- style: { imageRendering: "pixelated", objectFit: "contain" },
13168
- className: "flex-shrink-0"
13169
- }
13170
- ) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsx(Icon, { icon, size: "sm" }) : null }),
13154
+ /* @__PURE__ */ jsx(Box, { as: "span", className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsx(Icon, { icon, size: "sm" }) : null }),
13171
13155
  duration !== void 0 && /* @__PURE__ */ jsx(
13172
- "span",
13156
+ Typography,
13173
13157
  {
13158
+ as: "span",
13174
13159
  className: cn(
13175
13160
  "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
13176
13161
  sizes.timer
@@ -13182,8 +13167,9 @@ function StatusEffect({
13182
13167
  }
13183
13168
  ),
13184
13169
  stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsx(
13185
- "span",
13170
+ Typography,
13186
13171
  {
13172
+ as: "span",
13187
13173
  className: cn(
13188
13174
  "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
13189
13175
  sizes.badge
@@ -13191,20 +13177,23 @@ function StatusEffect({
13191
13177
  children: stacks
13192
13178
  }
13193
13179
  ),
13194
- label && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
13180
+ label && /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
13195
13181
  ] });
13196
13182
  }
13197
- var DEFAULT_ASSET_URL9, sizeMap10, variantStyles7;
13183
+ var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
13198
13184
  var init_StatusEffect = __esm({
13199
13185
  "components/game/2d/atoms/StatusEffect.tsx"() {
13200
13186
  init_cn();
13201
13187
  init_Icon();
13188
+ init_Box();
13189
+ init_Typography();
13190
+ init_GameIcon();
13202
13191
  DEFAULT_ASSET_URL9 = {
13203
13192
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
13204
13193
  role: "ui",
13205
13194
  category: "effect"
13206
13195
  };
13207
- sizeMap10 = {
13196
+ sizeMap11 = {
13208
13197
  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 },
13209
13198
  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 },
13210
13199
  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 }
@@ -13228,38 +13217,31 @@ function DamageNumber({
13228
13217
  return /* @__PURE__ */ jsxs(Fragment, { children: [
13229
13218
  /* @__PURE__ */ jsx("style", { children: floatKeyframes }),
13230
13219
  /* @__PURE__ */ jsxs(
13231
- "span",
13220
+ Typography,
13232
13221
  {
13222
+ as: "span",
13233
13223
  className: cn(
13234
13224
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
13235
- sizeMap11[size],
13225
+ sizeMap12[size],
13236
13226
  typeStyles[type],
13237
13227
  className
13238
13228
  ),
13239
13229
  style: { animation: "damageFloat 1s ease-out forwards" },
13240
13230
  children: [
13241
- assetUrl && /* @__PURE__ */ jsx(
13242
- "img",
13243
- {
13244
- src: assetUrl.url,
13245
- alt: "",
13246
- width: 14,
13247
- height: 14,
13248
- style: { imageRendering: "pixelated", objectFit: "contain" },
13249
- className: "flex-shrink-0"
13250
- }
13251
- ),
13231
+ assetUrl && /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: 14, className: "flex-shrink-0" }),
13252
13232
  displayText
13253
13233
  ]
13254
13234
  }
13255
13235
  )
13256
13236
  ] });
13257
13237
  }
13258
- var sizeMap11, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
13238
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
13259
13239
  var init_DamageNumber = __esm({
13260
13240
  "components/game/2d/atoms/DamageNumber.tsx"() {
13261
13241
  init_cn();
13262
- sizeMap11 = {
13242
+ init_Typography();
13243
+ init_GameIcon();
13244
+ sizeMap12 = {
13263
13245
  sm: "text-sm",
13264
13246
  md: "text-lg",
13265
13247
  lg: "text-2xl"
@@ -13293,7 +13275,7 @@ function DialogueBubble({
13293
13275
  className
13294
13276
  }) {
13295
13277
  return /* @__PURE__ */ jsxs(
13296
- "div",
13278
+ Box,
13297
13279
  {
13298
13280
  className: cn(
13299
13281
  "flex items-start gap-3 rounded-container bg-background/80 backdrop-blur-sm px-4 py-3 border border-border/10",
@@ -13301,17 +13283,10 @@ function DialogueBubble({
13301
13283
  className
13302
13284
  ),
13303
13285
  children: [
13304
- portrait && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsx(
13305
- "img",
13306
- {
13307
- src: portrait?.url,
13308
- alt: speaker ?? "speaker",
13309
- className: "w-full h-full object-cover"
13310
- }
13311
- ) }),
13312
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [
13313
- speaker && /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-warning", children: speaker }),
13314
- /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground leading-relaxed", children: text })
13286
+ portrait && /* @__PURE__ */ jsx(Box, { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsx(GameIcon, { assetUrl: portrait, icon: "image", size: 48, alt: speaker ?? "speaker", className: "w-full h-full object-cover" }) }),
13287
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-col gap-1 min-w-0", children: [
13288
+ speaker && /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-sm font-bold text-warning", children: speaker }),
13289
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-sm text-foreground leading-relaxed", children: text })
13315
13290
  ] })
13316
13291
  ]
13317
13292
  }
@@ -13321,6 +13296,9 @@ var DEFAULT_PORTRAIT;
13321
13296
  var init_DialogueBubble = __esm({
13322
13297
  "components/game/2d/atoms/DialogueBubble.tsx"() {
13323
13298
  init_cn();
13299
+ init_Box();
13300
+ init_Typography();
13301
+ init_GameIcon();
13324
13302
  DEFAULT_PORTRAIT = {
13325
13303
  url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
13326
13304
  role: "effect",
@@ -13342,11 +13320,11 @@ function ChoiceButton({
13342
13320
  }) {
13343
13321
  const eventBus = useEventBus();
13344
13322
  return /* @__PURE__ */ jsxs(
13345
- "button",
13323
+ Button,
13346
13324
  {
13347
- type: "button",
13325
+ variant: "ghost",
13348
13326
  disabled,
13349
- onClick: (e) => {
13327
+ onClick: () => {
13350
13328
  if (action) eventBus.emit(`UI:${action}`, {});
13351
13329
  onClick?.();
13352
13330
  },
@@ -13359,8 +13337,9 @@ function ChoiceButton({
13359
13337
  ),
13360
13338
  children: [
13361
13339
  index !== void 0 && /* @__PURE__ */ jsxs(
13362
- "span",
13340
+ Typography,
13363
13341
  {
13342
+ as: "span",
13364
13343
  className: cn(
13365
13344
  "flex-shrink-0 font-mono font-bold text-sm",
13366
13345
  selected ? "text-accent" : "text-muted-foreground"
@@ -13371,24 +13350,14 @@ function ChoiceButton({
13371
13350
  ]
13372
13351
  }
13373
13352
  ),
13374
- assetUrl ? /* @__PURE__ */ jsx(
13375
- "img",
13376
- {
13377
- src: assetUrl.url,
13378
- alt: "",
13379
- width: 16,
13380
- height: 16,
13381
- style: { imageRendering: "pixelated", objectFit: "contain" },
13382
- className: "flex-shrink-0"
13383
- }
13384
- ) : icon ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
13353
+ assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
13385
13354
  const I = resolveIcon(icon);
13386
13355
  return I ? /* @__PURE__ */ jsx(I, { className: "w-4 h-4" }) : null;
13387
13356
  })() : /* @__PURE__ */ (() => {
13388
13357
  const I = icon;
13389
13358
  return /* @__PURE__ */ jsx(I, { className: "w-4 h-4" });
13390
13359
  })() }) : null,
13391
- /* @__PURE__ */ jsx("span", { className: "text-sm leading-snug", children: text })
13360
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-sm leading-snug", children: text })
13392
13361
  ]
13393
13362
  }
13394
13363
  );
@@ -13398,6 +13367,10 @@ var init_ChoiceButton = __esm({
13398
13367
  init_cn();
13399
13368
  init_Icon();
13400
13369
  init_useEventBus();
13370
+ init_Button();
13371
+ init_Box();
13372
+ init_Typography();
13373
+ init_GameIcon();
13401
13374
  ChoiceButton.displayName = "ChoiceButton";
13402
13375
  }
13403
13376
  });
@@ -13415,16 +13388,16 @@ function ActionButton({
13415
13388
  className
13416
13389
  }) {
13417
13390
  const eventBus = useEventBus();
13418
- const sizes = sizeMap12[size];
13391
+ const sizes = sizeMap13[size];
13419
13392
  const onCooldown = cooldown > 0;
13420
13393
  const isDisabled = disabled || onCooldown;
13421
13394
  const cooldownDeg = Math.round(cooldown * 360);
13422
13395
  return /* @__PURE__ */ jsxs(
13423
- "button",
13396
+ Button,
13424
13397
  {
13425
- type: "button",
13398
+ variant: variant === "danger" ? "danger" : variant === "secondary" ? "secondary" : "primary",
13426
13399
  disabled: isDisabled,
13427
- onClick: (e) => {
13400
+ onClick: () => {
13428
13401
  if (action) eventBus.emit(`UI:${action}`, {});
13429
13402
  onClick?.();
13430
13403
  },
@@ -13437,9 +13410,10 @@ function ActionButton({
13437
13410
  ),
13438
13411
  children: [
13439
13412
  onCooldown && /* @__PURE__ */ jsx(
13440
- "div",
13413
+ Box,
13441
13414
  {
13442
- className: "absolute inset-0 bg-foreground/40 pointer-events-none",
13415
+ position: "absolute",
13416
+ className: "inset-0 bg-foreground/40 pointer-events-none",
13443
13417
  style: {
13444
13418
  clipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
13445
13419
  WebkitClipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
@@ -13447,27 +13421,18 @@ function ActionButton({
13447
13421
  }
13448
13422
  }
13449
13423
  ),
13450
- assetUrl ? /* @__PURE__ */ jsx(
13451
- "img",
13452
- {
13453
- src: assetUrl.url,
13454
- alt: "",
13455
- width: 16,
13456
- height: 16,
13457
- style: { imageRendering: "pixelated", objectFit: "contain" },
13458
- className: cn("flex-shrink-0", sizes.icon)
13459
- }
13460
- ) : icon ? /* @__PURE__ */ jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
13424
+ assetUrl ? /* @__PURE__ */ jsx(GameIcon, { assetUrl, icon: "image", size: 16, className: cn("flex-shrink-0", sizes.icon) }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
13461
13425
  const I = resolveIcon(icon);
13462
13426
  return I ? /* @__PURE__ */ jsx(I, { className: "w-4 h-4" }) : null;
13463
13427
  })() : /* @__PURE__ */ (() => {
13464
13428
  const I = icon;
13465
13429
  return /* @__PURE__ */ jsx(I, { className: "w-4 h-4" });
13466
13430
  })() }) : null,
13467
- /* @__PURE__ */ jsx("span", { className: "relative z-10", children: label }),
13431
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "relative z-10", children: label }),
13468
13432
  hotkey && /* @__PURE__ */ jsx(
13469
- "span",
13433
+ Typography,
13470
13434
  {
13435
+ as: "span",
13471
13436
  className: cn(
13472
13437
  "absolute top-0.5 right-0.5 bg-foreground/30 text-primary-foreground rounded font-mono leading-tight",
13473
13438
  sizes.hotkey
@@ -13479,13 +13444,17 @@ function ActionButton({
13479
13444
  }
13480
13445
  );
13481
13446
  }
13482
- var sizeMap12, variantStyles8, DEFAULT_ASSET_URL11;
13447
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
13483
13448
  var init_ActionButton = __esm({
13484
13449
  "components/game/2d/atoms/ActionButton.tsx"() {
13485
13450
  init_cn();
13486
13451
  init_Icon();
13487
13452
  init_useEventBus();
13488
- sizeMap12 = {
13453
+ init_Button();
13454
+ init_Box();
13455
+ init_Typography();
13456
+ init_GameIcon();
13457
+ sizeMap13 = {
13489
13458
  sm: { button: "h-button-sm px-3 text-xs", hotkey: "text-[9px] px-1", icon: "text-xs" },
13490
13459
  md: { button: "h-button-md px-4 text-sm", hotkey: "text-xs px-1.5", icon: "text-sm" },
13491
13460
  lg: { button: "h-button-lg px-5 text-base", hotkey: "text-xs px-2", icon: "text-base" }
@@ -13587,10 +13556,12 @@ function MiniMap({
13587
13556
  return /* @__PURE__ */ jsxs(Fragment, { children: [
13588
13557
  /* @__PURE__ */ jsx("style", { children: `@keyframes minimap-blink{0%,49%{opacity:1}50%,100%{opacity:0}}` }),
13589
13558
  /* @__PURE__ */ jsxs(
13590
- "div",
13559
+ Box,
13591
13560
  {
13561
+ position: "relative",
13562
+ display: "inline-block",
13592
13563
  className: cn(
13593
- "relative inline-block border border-border/20 rounded-container",
13564
+ "border border-border/20 rounded-container",
13594
13565
  className
13595
13566
  ),
13596
13567
  children: [
@@ -13605,10 +13576,10 @@ function MiniMap({
13605
13576
  }
13606
13577
  ),
13607
13578
  playerLeft !== null && playerTop !== null && /* @__PURE__ */ jsx(
13608
- "div",
13579
+ Box,
13609
13580
  {
13581
+ position: "absolute",
13610
13582
  style: {
13611
- position: "absolute",
13612
13583
  left: playerLeft,
13613
13584
  top: playerTop,
13614
13585
  width: 3,
@@ -13629,6 +13600,7 @@ var init_MiniMap = __esm({
13629
13600
  "components/game/2d/atoms/MiniMap.tsx"() {
13630
13601
  "use client";
13631
13602
  init_cn();
13603
+ init_Box();
13632
13604
  DEFAULT_TILES = [
13633
13605
  { x: 10, y: 10, color: "#4ade80" },
13634
13606
  { x: 20, y: 15, color: "#4ade80" },
@@ -13646,38 +13618,6 @@ var init_MiniMap = __esm({
13646
13618
  MiniMap.displayName = "MiniMap";
13647
13619
  }
13648
13620
  });
13649
- function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
13650
- const px = typeof size === "number" ? size : sizeMap13[size];
13651
- if (assetUrl?.url) {
13652
- return /* @__PURE__ */ jsx(
13653
- "img",
13654
- {
13655
- src: assetUrl.url,
13656
- alt: alt ?? assetUrl.category ?? "",
13657
- width: px,
13658
- height: px,
13659
- style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
13660
- className: cn("flex-shrink-0", className)
13661
- }
13662
- );
13663
- }
13664
- const I = typeof icon === "string" ? resolveIcon(icon) : icon;
13665
- return /* @__PURE__ */ jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
13666
- }
13667
- var sizeMap13;
13668
- var init_GameIcon = __esm({
13669
- "components/game/2d/atoms/GameIcon.tsx"() {
13670
- "use client";
13671
- init_cn();
13672
- init_Icon();
13673
- sizeMap13 = {
13674
- sm: 16,
13675
- md: 24,
13676
- lg: 32
13677
- };
13678
- GameIcon.displayName = "GameIcon";
13679
- }
13680
- });
13681
13621
  function ControlGrid({
13682
13622
  kind,
13683
13623
  buttons = DEFAULT_BUTTONS,
@@ -13738,22 +13678,22 @@ function ControlGrid({
13738
13678
  },
13739
13679
  d
13740
13680
  );
13741
- return /* @__PURE__ */ jsxs("div", { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
13742
- /* @__PURE__ */ jsx("div", {}),
13681
+ return /* @__PURE__ */ jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
13682
+ /* @__PURE__ */ jsx(Box, {}),
13743
13683
  dir("up"),
13744
- /* @__PURE__ */ jsx("div", {}),
13684
+ /* @__PURE__ */ jsx(Box, {}),
13745
13685
  dir("left"),
13746
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
13686
+ /* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(Box, { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
13747
13687
  dir("right"),
13748
- /* @__PURE__ */ jsx("div", {}),
13688
+ /* @__PURE__ */ jsx(Box, {}),
13749
13689
  dir("down"),
13750
- /* @__PURE__ */ jsx("div", {})
13690
+ /* @__PURE__ */ jsx(Box, {})
13751
13691
  ] });
13752
13692
  }
13753
13693
  if (layout === "diamond" && buttons.length === 4) {
13754
13694
  const [top, right, bottom, left] = buttons;
13755
- return /* @__PURE__ */ jsxs("div", { className: cn(layoutClass.diamond, className), children: [
13756
- /* @__PURE__ */ jsx("div", {}),
13695
+ return /* @__PURE__ */ jsxs(Box, { className: cn(layoutClass.diamond, className), children: [
13696
+ /* @__PURE__ */ jsx(Box, {}),
13757
13697
  /* @__PURE__ */ jsx(
13758
13698
  ControlButton,
13759
13699
  {
@@ -13768,7 +13708,7 @@ function ControlGrid({
13768
13708
  disabled
13769
13709
  }
13770
13710
  ),
13771
- /* @__PURE__ */ jsx("div", {}),
13711
+ /* @__PURE__ */ jsx(Box, {}),
13772
13712
  /* @__PURE__ */ jsx(
13773
13713
  ControlButton,
13774
13714
  {
@@ -13783,7 +13723,7 @@ function ControlGrid({
13783
13723
  disabled
13784
13724
  }
13785
13725
  ),
13786
- /* @__PURE__ */ jsx("div", {}),
13726
+ /* @__PURE__ */ jsx(Box, {}),
13787
13727
  /* @__PURE__ */ jsx(
13788
13728
  ControlButton,
13789
13729
  {
@@ -13798,7 +13738,7 @@ function ControlGrid({
13798
13738
  disabled
13799
13739
  }
13800
13740
  ),
13801
- /* @__PURE__ */ jsx("div", {}),
13741
+ /* @__PURE__ */ jsx(Box, {}),
13802
13742
  /* @__PURE__ */ jsx(
13803
13743
  ControlButton,
13804
13744
  {
@@ -13813,10 +13753,10 @@ function ControlGrid({
13813
13753
  disabled
13814
13754
  }
13815
13755
  ),
13816
- /* @__PURE__ */ jsx("div", {})
13756
+ /* @__PURE__ */ jsx(Box, {})
13817
13757
  ] });
13818
13758
  }
13819
- return /* @__PURE__ */ jsx("div", { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsx(
13759
+ return /* @__PURE__ */ jsx(Box, { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsx(
13820
13760
  ControlButton,
13821
13761
  {
13822
13762
  icon: button.icon,
@@ -13838,6 +13778,7 @@ var init_ControlGrid = __esm({
13838
13778
  "use client";
13839
13779
  init_cn();
13840
13780
  init_useEventBus();
13781
+ init_Box();
13841
13782
  init_ControlButton();
13842
13783
  sizeKey = { sm: "sm", md: "md", lg: "lg" };
13843
13784
  layoutClass = {
@@ -13882,7 +13823,7 @@ function StatBadge({
13882
13823
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
13883
13824
  const resolvedAsset = iconUrl ?? assetUrl;
13884
13825
  return /* @__PURE__ */ jsxs(
13885
- "div",
13826
+ Box,
13886
13827
  {
13887
13828
  className: cn(
13888
13829
  "inline-flex items-center gap-2 rounded-container border backdrop-blur-sm",
@@ -13891,18 +13832,8 @@ function StatBadge({
13891
13832
  className
13892
13833
  ),
13893
13834
  children: [
13894
- resolvedAsset ? /* @__PURE__ */ jsx(
13895
- "img",
13896
- {
13897
- src: resolvedAsset.url,
13898
- alt: "",
13899
- width: 16,
13900
- height: 16,
13901
- style: { imageRendering: "pixelated", objectFit: "contain" },
13902
- className: "flex-shrink-0"
13903
- }
13904
- ) : icon ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
13905
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground font-medium", children: label }),
13835
+ resolvedAsset ? /* @__PURE__ */ jsx(GameIcon, { assetUrl: resolvedAsset, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsx(Box, { as: "span", className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
13836
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
13906
13837
  format === "hearts" && max && /* @__PURE__ */ jsx(
13907
13838
  HealthBar,
13908
13839
  {
@@ -13928,7 +13859,7 @@ function StatBadge({
13928
13859
  size: size === "lg" ? "md" : "sm"
13929
13860
  }
13930
13861
  ),
13931
- format === "text" && /* @__PURE__ */ jsx("span", { className: "font-bold text-foreground", children: value })
13862
+ format === "text" && /* @__PURE__ */ jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
13932
13863
  ]
13933
13864
  }
13934
13865
  );
@@ -13938,6 +13869,9 @@ var init_StatBadge = __esm({
13938
13869
  "components/game/2d/molecules/StatBadge.tsx"() {
13939
13870
  init_cn();
13940
13871
  init_Icon();
13872
+ init_Box();
13873
+ init_Typography();
13874
+ init_GameIcon();
13941
13875
  init_HealthBar();
13942
13876
  init_ScoreDisplay();
13943
13877
  sizeMap14 = {
@@ -14115,9 +14049,9 @@ function GameHud({
14115
14049
  if (position === "corners") {
14116
14050
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
14117
14051
  const rightStats = stats.slice(Math.ceil(stats.length / 2));
14118
- return /* @__PURE__ */ jsxs("div", { className: cn("relative", positionMap[position], className), children: [
14119
- /* @__PURE__ */ jsx("div", { className: "absolute top-4 left-4 flex flex-col gap-2 pointer-events-auto", children: leftStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) }),
14120
- /* @__PURE__ */ jsx("div", { className: "absolute top-4 right-4 flex flex-col gap-2 items-end pointer-events-auto", children: rightStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) })
14052
+ return /* @__PURE__ */ jsxs(Box, { position: "relative", className: cn(positionMap[position], className), children: [
14053
+ /* @__PURE__ */ jsx(Box, { position: "absolute", className: "top-4 left-4 flex flex-col gap-2 pointer-events-auto", children: leftStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) }),
14054
+ /* @__PURE__ */ 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__ */ jsx(StatBadge, { ...stat, size }, i)) })
14121
14055
  ] });
14122
14056
  }
14123
14057
  if (position === "top" || position === "bottom") {
@@ -14126,7 +14060,7 @@ function GameHud({
14126
14060
  const rightStats = stats.slice(mid);
14127
14061
  const isTop = position === "top";
14128
14062
  return /* @__PURE__ */ jsxs(
14129
- "div",
14063
+ Box,
14130
14064
  {
14131
14065
  className: cn(
14132
14066
  "flex items-center justify-between w-full",
@@ -14136,17 +14070,18 @@ function GameHud({
14136
14070
  className
14137
14071
  ),
14138
14072
  children: [
14139
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 flex-shrink-0", children: leftStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) }),
14140
- rightStats.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 flex-shrink-0", children: rightStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) })
14073
+ /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-3 flex-shrink-0", children: leftStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) }),
14074
+ rightStats.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-3 flex-shrink-0", children: rightStats.map((stat, i) => /* @__PURE__ */ jsx(StatBadge, { ...stat, size }, i)) })
14141
14075
  ]
14142
14076
  }
14143
14077
  );
14144
14078
  }
14145
14079
  return /* @__PURE__ */ jsx(
14146
- "div",
14080
+ Box,
14147
14081
  {
14082
+ position: "relative",
14148
14083
  className: cn(
14149
- "relative z-10 flex items-center gap-4 px-4 py-2",
14084
+ "z-10 flex items-center gap-4 px-4 py-2",
14150
14085
  transparent ? "bg-black/30 backdrop-blur-sm" : "bg-surface/90 backdrop-blur-sm",
14151
14086
  className
14152
14087
  ),
@@ -14158,6 +14093,7 @@ var positionMap, DEFAULT_HUD_STATS;
14158
14093
  var init_GameHud = __esm({
14159
14094
  "components/game/2d/molecules/GameHud.tsx"() {
14160
14095
  init_cn();
14096
+ init_Box();
14161
14097
  init_StatBadge();
14162
14098
  positionMap = {
14163
14099
  corners: "inset-0 pointer-events-none"
@@ -14198,7 +14134,7 @@ function GameMenu({
14198
14134
  [eventBus, onSelect]
14199
14135
  );
14200
14136
  return /* @__PURE__ */ jsxs(
14201
- "div",
14137
+ Box,
14202
14138
  {
14203
14139
  className: cn(
14204
14140
  "min-h-screen w-full flex flex-col items-center justify-center p-8",
@@ -14208,18 +14144,12 @@ function GameMenu({
14208
14144
  background: background ?? "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0e17 100%)"
14209
14145
  },
14210
14146
  children: [
14211
- /* @__PURE__ */ jsxs("div", { className: "text-center mb-12 animate-fade-in", children: [
14212
- logo && /* @__PURE__ */ jsx(
14213
- "img",
14214
- {
14215
- src: logo.url,
14216
- alt: title,
14217
- className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl"
14218
- }
14219
- ),
14147
+ /* @__PURE__ */ jsxs(Box, { className: "text-center mb-12 animate-fade-in", children: [
14148
+ logo && /* @__PURE__ */ jsx(GameIcon, { assetUrl: logo, icon: "image", size: 96, alt: title, className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl" }),
14220
14149
  /* @__PURE__ */ jsx(
14221
- "h1",
14150
+ Typography,
14222
14151
  {
14152
+ variant: "h1",
14223
14153
  className: "text-5xl md:text-7xl font-bold text-[var(--color-foreground)] tracking-tight",
14224
14154
  style: {
14225
14155
  textShadow: "0 4px 12px rgba(0,0,0,0.5)"
@@ -14227,9 +14157,9 @@ function GameMenu({
14227
14157
  children: title
14228
14158
  }
14229
14159
  ),
14230
- subtitle && /* @__PURE__ */ jsx("p", { className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
14160
+ subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
14231
14161
  ] }),
14232
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsx(
14162
+ /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsx(
14233
14163
  ChoiceButton,
14234
14164
  {
14235
14165
  text: option.label,
@@ -14240,9 +14170,9 @@ function GameMenu({
14240
14170
  },
14241
14171
  index
14242
14172
  )) }),
14243
- /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 pointer-events-none overflow-hidden", children: [
14244
- /* @__PURE__ */ jsx("div", { className: "absolute top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
14245
- /* @__PURE__ */ jsx("div", { className: "absolute bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
14173
+ /* @__PURE__ */ jsxs(Box, { position: "absolute", className: "inset-0 pointer-events-none overflow-hidden", children: [
14174
+ /* @__PURE__ */ jsx(Box, { position: "absolute", className: "top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
14175
+ /* @__PURE__ */ jsx(Box, { position: "absolute", className: "bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
14246
14176
  ] })
14247
14177
  ]
14248
14178
  }
@@ -14254,6 +14184,9 @@ var init_GameMenu = __esm({
14254
14184
  "use client";
14255
14185
  init_cn();
14256
14186
  init_useEventBus();
14187
+ init_Box();
14188
+ init_Typography();
14189
+ init_GameIcon();
14257
14190
  init_ChoiceButton();
14258
14191
  DEFAULT_MENU_OPTIONS = [
14259
14192
  { label: "New Game", event: "NEW_GAME", variant: "primary" },
@@ -15673,10 +15606,11 @@ function Canvas2D({
15673
15606
  }
15674
15607
  }
15675
15608
  ),
15676
- process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxs("div", { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
15609
+ process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxs(Box, { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
15677
15610
  tileClickEvent && /* @__PURE__ */ jsx(
15678
- "button",
15611
+ Button,
15679
15612
  {
15613
+ variant: "ghost",
15680
15614
  "data-event": tileClickEvent,
15681
15615
  "data-x": "0",
15682
15616
  "data-y": "0",
@@ -15685,8 +15619,9 @@ function Canvas2D({
15685
15619
  }
15686
15620
  ),
15687
15621
  unitClickEvent && units && units.length > 0 && /* @__PURE__ */ jsx(
15688
- "button",
15622
+ Button,
15689
15623
  {
15624
+ variant: "ghost",
15690
15625
  "data-event": unitClickEvent,
15691
15626
  "data-unit-id": units[0].id,
15692
15627
  onClick: () => eventBus.emit(`UI:${unitClickEvent}`, { unitId: units[0].id }),
@@ -15695,15 +15630,17 @@ function Canvas2D({
15695
15630
  )
15696
15631
  ] }),
15697
15632
  unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxs(
15698
- "div",
15633
+ Box,
15699
15634
  {
15700
- className: "absolute pointer-events-none",
15635
+ position: "absolute",
15636
+ className: "pointer-events-none",
15701
15637
  style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
15702
15638
  children: [
15703
15639
  unit.name && /* @__PURE__ */ jsx(
15704
- "div",
15640
+ Typography,
15705
15641
  {
15706
- className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
15642
+ as: "span",
15643
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
15707
15644
  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)" },
15708
15645
  children: unit.name
15709
15646
  }
@@ -15713,7 +15650,7 @@ function Canvas2D({
15713
15650
  },
15714
15651
  unit.id
15715
15652
  )),
15716
- showMinimap && /* @__PURE__ */ jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsx(
15653
+ showMinimap && /* @__PURE__ */ jsx(Box, { position: "absolute", className: "bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsx(
15717
15654
  MiniMap,
15718
15655
  {
15719
15656
  tiles: miniMapTiles,
@@ -15735,6 +15672,7 @@ var init_Canvas2D = __esm({
15735
15672
  init_cn();
15736
15673
  init_useEventBus();
15737
15674
  init_Box();
15675
+ init_Button();
15738
15676
  init_Stack();
15739
15677
  init_Icon();
15740
15678
  init_Typography();
@@ -16066,7 +16004,7 @@ function GameAudioToggle({
16066
16004
  onClick: handleToggle,
16067
16005
  className: cn("text-lg leading-none px-2", className),
16068
16006
  "aria-pressed": muted,
16069
- children: activeAsset ? /* @__PURE__ */ jsx("img", { src: activeAsset.url, alt: muted ? "Muted" : "Sound on", className: "w-5 h-5 object-contain" }) : muted ? "\u{1F507}" : "\u{1F50A}"
16007
+ children: activeAsset ? /* @__PURE__ */ 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}"
16070
16008
  }
16071
16009
  );
16072
16010
  }
@@ -16076,6 +16014,7 @@ var init_GameAudioToggle = __esm({
16076
16014
  init_atoms();
16077
16015
  init_cn();
16078
16016
  init_GameAudioProvider();
16017
+ init_GameIcon();
16079
16018
  GameAudioToggle.displayName = "GameAudioToggle";
16080
16019
  }
16081
16020
  });
@@ -25836,7 +25775,7 @@ var init_Tabs = __esm({
25836
25775
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
25837
25776
  ),
25838
25777
  children: [
25839
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
25778
+ item.iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
25840
25779
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
25841
25780
  item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge })
25842
25781
  ]