@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.
@@ -8928,6 +8928,38 @@ var init_shared = __esm({
8928
8928
  init_canvasEffects();
8929
8929
  }
8930
8930
  });
8931
+ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
8932
+ const px = typeof size === "number" ? size : sizeMap[size];
8933
+ if (assetUrl?.url) {
8934
+ return /* @__PURE__ */ jsxRuntime.jsx(
8935
+ "img",
8936
+ {
8937
+ src: assetUrl.url,
8938
+ alt: alt ?? assetUrl.category ?? "",
8939
+ width: px,
8940
+ height: px,
8941
+ style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
8942
+ className: cn("flex-shrink-0", className)
8943
+ }
8944
+ );
8945
+ }
8946
+ const I = typeof icon === "string" ? resolveIcon(icon) : icon;
8947
+ return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
8948
+ }
8949
+ var sizeMap;
8950
+ var init_GameIcon = __esm({
8951
+ "components/game/2d/atoms/GameIcon.tsx"() {
8952
+ "use client";
8953
+ init_cn();
8954
+ init_Icon();
8955
+ sizeMap = {
8956
+ sm: 16,
8957
+ md: 24,
8958
+ lg: 32
8959
+ };
8960
+ GameIcon.displayName = "GameIcon";
8961
+ }
8962
+ });
8931
8963
  function GameCard({
8932
8964
  id,
8933
8965
  cost,
@@ -8950,9 +8982,9 @@ function GameCard({
8950
8982
  }, [disabled, id, onClick, clickEvent, eventBus]);
8951
8983
  const artPx = artPxMap[size];
8952
8984
  return /* @__PURE__ */ jsxRuntime.jsxs(
8953
- "button",
8985
+ Button,
8954
8986
  {
8955
- type: "button",
8987
+ variant: "ghost",
8956
8988
  onClick: handleClick,
8957
8989
  disabled,
8958
8990
  title: name,
@@ -8966,8 +8998,9 @@ function GameCard({
8966
8998
  ),
8967
8999
  children: [
8968
9000
  cost != null && /* @__PURE__ */ jsxRuntime.jsx(
8969
- "span",
9001
+ Typography,
8970
9002
  {
9003
+ as: "span",
8971
9004
  className: cn(
8972
9005
  "absolute -top-2 -left-2 flex items-center justify-center",
8973
9006
  "min-w-[22px] h-[22px] rounded-full px-1",
@@ -8976,17 +9009,7 @@ function GameCard({
8976
9009
  children: cost
8977
9010
  }
8978
9011
  ),
8979
- /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsxRuntime.jsx(
8980
- "img",
8981
- {
8982
- src: art.url,
8983
- alt: name ?? id,
8984
- width: artPx,
8985
- height: artPx,
8986
- style: { imageRendering: "pixelated", objectFit: "contain" },
8987
- className: "flex-shrink-0"
8988
- }
8989
- ) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
9012
+ /* @__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 } }) }),
8990
9013
  name != null && /* @__PURE__ */ jsxRuntime.jsx(
8991
9014
  Typography,
8992
9015
  {
@@ -8996,8 +9019,8 @@ function GameCard({
8996
9019
  }
8997
9020
  ),
8998
9021
  (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: [
8999
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
9000
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
9022
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
9023
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
9001
9024
  ] })
9002
9025
  ]
9003
9026
  }
@@ -9010,7 +9033,9 @@ var init_GameCard = __esm({
9010
9033
  init_cn();
9011
9034
  init_useEventBus();
9012
9035
  init_Box();
9036
+ init_Button();
9013
9037
  init_Typography();
9038
+ init_GameIcon();
9014
9039
  cardSizeMap = {
9015
9040
  sm: "w-16 h-24",
9016
9041
  md: "w-20 h-28",
@@ -9033,12 +9058,13 @@ function HealthBar({
9033
9058
  frameAsset,
9034
9059
  fillAsset
9035
9060
  }) {
9036
- const sizes = sizeMap[size];
9061
+ const sizes = sizeMap2[size];
9037
9062
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
9038
9063
  if (format === "hearts") {
9039
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
9040
- "span",
9064
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
9065
+ Box,
9041
9066
  {
9067
+ as: "span",
9042
9068
  className: cn(animated && "transition-transform hover:scale-110"),
9043
9069
  children: heartIcon(i < current, sizes.heart)
9044
9070
  },
@@ -9047,10 +9073,12 @@ function HealthBar({
9047
9073
  }
9048
9074
  if (format === "bar") {
9049
9075
  return /* @__PURE__ */ jsxRuntime.jsx(
9050
- "div",
9076
+ Box,
9051
9077
  {
9078
+ position: "relative",
9079
+ overflow: "hidden",
9052
9080
  className: cn(
9053
- "relative overflow-hidden rounded-full",
9081
+ "rounded-full",
9054
9082
  !frameAsset && "bg-muted",
9055
9083
  sizes.bar,
9056
9084
  "w-24",
@@ -9058,10 +9086,11 @@ function HealthBar({
9058
9086
  ),
9059
9087
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
9060
9088
  children: /* @__PURE__ */ jsxRuntime.jsx(
9061
- "div",
9089
+ Box,
9062
9090
  {
9091
+ position: "absolute",
9063
9092
  className: cn(
9064
- "absolute inset-y-0 left-0 rounded-full",
9093
+ "inset-y-0 left-0 rounded-full",
9065
9094
  !fillAsset && (percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error"),
9066
9095
  animated && "transition-all duration-300"
9067
9096
  ),
@@ -9075,10 +9104,11 @@ function HealthBar({
9075
9104
  );
9076
9105
  }
9077
9106
  if (format === "progress") {
9078
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), children: [
9107
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex items-center gap-2", className), children: [
9079
9108
  level != null && /* @__PURE__ */ jsxRuntime.jsxs(
9080
- "span",
9109
+ Typography,
9081
9110
  {
9111
+ as: "span",
9082
9112
  className: cn(
9083
9113
  "flex-shrink-0 rounded-interactive font-bold",
9084
9114
  "bg-accent text-accent-foreground border border-accent",
@@ -9090,21 +9120,23 @@ function HealthBar({
9090
9120
  ]
9091
9121
  }
9092
9122
  ),
9093
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [
9123
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 flex flex-col gap-0.5", children: [
9094
9124
  /* @__PURE__ */ jsxRuntime.jsx(
9095
- "div",
9125
+ Box,
9096
9126
  {
9127
+ position: "relative",
9097
9128
  className: cn(
9098
- "relative w-full overflow-hidden rounded-full",
9129
+ "w-full overflow-hidden rounded-full",
9099
9130
  !frameAsset && "bg-muted border border-muted",
9100
9131
  sizes.bar
9101
9132
  ),
9102
9133
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
9103
9134
  children: /* @__PURE__ */ jsxRuntime.jsx(
9104
- "div",
9135
+ Box,
9105
9136
  {
9137
+ position: "absolute",
9106
9138
  className: cn(
9107
- "absolute inset-y-0 left-0 rounded-full",
9139
+ "inset-y-0 left-0 rounded-full",
9108
9140
  !fillAsset && "bg-gradient-to-r from-accent to-info",
9109
9141
  animated && "transition-all duration-500 ease-out"
9110
9142
  ),
@@ -9116,7 +9148,7 @@ function HealthBar({
9116
9148
  )
9117
9149
  }
9118
9150
  ),
9119
- showLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
9151
+ showLabel && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
9120
9152
  current,
9121
9153
  " / ",
9122
9154
  max,
@@ -9125,16 +9157,18 @@ function HealthBar({
9125
9157
  ] })
9126
9158
  ] });
9127
9159
  }
9128
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
9160
+ return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-mono font-bold", sizes.text, className), children: [
9129
9161
  current,
9130
9162
  "/",
9131
9163
  max
9132
9164
  ] });
9133
9165
  }
9134
- var heartIcon, sizeMap;
9166
+ var heartIcon, sizeMap2;
9135
9167
  var init_HealthBar = __esm({
9136
9168
  "components/game/2d/atoms/HealthBar.tsx"() {
9137
9169
  init_cn();
9170
+ init_Box();
9171
+ init_Typography();
9138
9172
  heartIcon = (filled, size) => /* @__PURE__ */ jsxRuntime.jsx(
9139
9173
  "svg",
9140
9174
  {
@@ -9146,7 +9180,7 @@ var init_HealthBar = __esm({
9146
9180
  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" })
9147
9181
  }
9148
9182
  );
9149
- sizeMap = {
9183
+ sizeMap2 = {
9150
9184
  sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm", label: "text-xs", badge: "text-xs px-1.5 py-0.5" },
9151
9185
  md: { heart: "w-6 h-6", bar: "h-3", text: "text-base", label: "text-xs", badge: "text-xs px-2 py-0.5" },
9152
9186
  lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg", label: "text-sm", badge: "text-sm px-2.5 py-1" }
@@ -9167,37 +9201,30 @@ function ScoreDisplay({
9167
9201
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
9168
9202
  const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
9169
9203
  return /* @__PURE__ */ jsxRuntime.jsxs(
9170
- "div",
9204
+ Box,
9171
9205
  {
9172
9206
  className: cn(
9173
9207
  "flex items-center gap-2 font-bold",
9174
- sizeMap2[size],
9208
+ sizeMap3[size],
9175
9209
  className
9176
9210
  ),
9177
9211
  children: [
9178
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9179
- "img",
9180
- {
9181
- src: assetUrl.url,
9182
- alt: "",
9183
- width: 20,
9184
- height: 20,
9185
- style: { imageRendering: "pixelated", objectFit: "contain" },
9186
- className: "flex-shrink-0"
9187
- }
9188
- ) : 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,
9189
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
9190
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: formattedValue })
9212
+ 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,
9213
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
9214
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "tabular-nums", children: formattedValue })
9191
9215
  ]
9192
9216
  }
9193
9217
  );
9194
9218
  }
9195
- var sizeMap2, DEFAULT_ASSET_URL;
9219
+ var sizeMap3, DEFAULT_ASSET_URL;
9196
9220
  var init_ScoreDisplay = __esm({
9197
9221
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
9198
9222
  init_cn();
9199
9223
  init_Icon();
9200
- sizeMap2 = {
9224
+ init_Box();
9225
+ init_Typography();
9226
+ init_GameIcon();
9227
+ sizeMap3 = {
9201
9228
  sm: "text-sm",
9202
9229
  md: "text-lg",
9203
9230
  lg: "text-2xl",
@@ -9260,9 +9287,9 @@ function ControlButton({
9260
9287
  [isPressed, releaseEvent, eventBus, onRelease]
9261
9288
  );
9262
9289
  return /* @__PURE__ */ jsxRuntime.jsx(
9263
- "button",
9290
+ Button,
9264
9291
  {
9265
- type: "button",
9292
+ variant,
9266
9293
  disabled,
9267
9294
  onPointerDown: handlePointerDown,
9268
9295
  onPointerUp: handlePointerUp,
@@ -9273,41 +9300,35 @@ function ControlButton({
9273
9300
  "select-none touch-none",
9274
9301
  "transition-all duration-100",
9275
9302
  "active:scale-95",
9276
- sizeMap3[size] ?? sizeMap3.md,
9303
+ sizeMap4[size] ?? sizeMap4.md,
9277
9304
  shapeMap[shape] ?? shapeMap.circle,
9278
9305
  variantMap[variant] ?? variantMap.secondary,
9279
9306
  actualPressed && "scale-95 brightness-110 border-foreground",
9280
9307
  disabled && "opacity-50 cursor-not-allowed",
9281
9308
  className
9282
9309
  ),
9283
- children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9284
- "img",
9285
- {
9286
- src: assetUrl.url,
9287
- alt: "",
9288
- width: 24,
9289
- height: 24,
9290
- style: { imageRendering: "pixelated", objectFit: "contain" },
9291
- className: "flex-shrink-0"
9292
- }
9293
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
9310
+ 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) ? (() => {
9294
9311
  const I = resolveIcon(icon);
9295
9312
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" }) : null;
9296
9313
  })() : icon : /* @__PURE__ */ (() => {
9297
9314
  const I = icon;
9298
9315
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" });
9299
- })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }) : null
9316
+ })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: label }) : null
9300
9317
  }
9301
9318
  );
9302
9319
  }
9303
- var sizeMap3, shapeMap, variantMap, DEFAULT_ASSET_URL2;
9320
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
9304
9321
  var init_ControlButton = __esm({
9305
9322
  "components/game/2d/atoms/ControlButton.tsx"() {
9306
9323
  "use client";
9307
9324
  init_cn();
9308
9325
  init_useEventBus();
9309
9326
  init_Icon();
9310
- sizeMap3 = {
9327
+ init_Button();
9328
+ init_Box();
9329
+ init_Typography();
9330
+ init_GameIcon();
9331
+ sizeMap4 = {
9311
9332
  sm: "w-10 h-10 text-sm",
9312
9333
  md: "w-14 h-14 text-base",
9313
9334
  lg: "w-18 h-18 text-lg",
@@ -9377,12 +9398,12 @@ function Sprite({
9377
9398
  onClick?.();
9378
9399
  };
9379
9400
  return /* @__PURE__ */ jsxRuntime.jsx(
9380
- "div",
9401
+ Box,
9381
9402
  {
9403
+ position: "absolute",
9382
9404
  className,
9383
9405
  onClick: action || onClick ? handleClick : void 0,
9384
9406
  style: {
9385
- position: "absolute",
9386
9407
  width: frameWidth,
9387
9408
  height: frameHeight,
9388
9409
  backgroundImage: `url(${spritesheet.url})`,
@@ -9403,6 +9424,7 @@ var init_Sprite = __esm({
9403
9424
  "components/game/2d/atoms/Sprite.tsx"() {
9404
9425
  "use client";
9405
9426
  init_useEventBus();
9427
+ init_Box();
9406
9428
  init_spriteAnimation();
9407
9429
  DEFAULT_SPRITESHEET = {
9408
9430
  url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
@@ -9439,17 +9461,7 @@ function StateIndicator({
9439
9461
  className
9440
9462
  ),
9441
9463
  children: [
9442
- /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9443
- "img",
9444
- {
9445
- src: assetUrl.url,
9446
- alt: displayLabel,
9447
- width: 16,
9448
- height: 16,
9449
- style: { imageRendering: "pixelated", objectFit: "contain" },
9450
- className: "flex-shrink-0"
9451
- }
9452
- ) : 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 }) }),
9464
+ /* @__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 }) }),
9453
9465
  /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: displayLabel })
9454
9466
  ]
9455
9467
  }
@@ -9461,6 +9473,7 @@ var init_StateIndicator = __esm({
9461
9473
  init_Box();
9462
9474
  init_Icon();
9463
9475
  init_cn();
9476
+ init_GameIcon();
9464
9477
  DEFAULT_ASSET_URL3 = {
9465
9478
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
9466
9479
  role: "ui",
@@ -9514,29 +9527,31 @@ function TimerDisplay({
9514
9527
  }) {
9515
9528
  const isLow = lowThreshold != null && seconds <= lowThreshold && seconds > 0;
9516
9529
  return /* @__PURE__ */ jsxRuntime.jsxs(
9517
- "div",
9530
+ Box,
9518
9531
  {
9519
9532
  className: cn(
9520
9533
  "inline-flex items-center gap-1 justify-center rounded-container",
9521
9534
  "bg-card/80 border border-muted font-mono font-bold tabular-nums",
9522
- sizeMap4[size],
9535
+ sizeMap5[size],
9523
9536
  running && "border-success/50",
9524
9537
  isLow && "text-error border-error/50 animate-pulse",
9525
9538
  !isLow && "text-foreground",
9526
9539
  className
9527
9540
  ),
9528
9541
  children: [
9529
- iconAsset && /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconAsset.url, alt: "", className: "w-4 h-4 object-contain flex-shrink-0" }),
9542
+ iconAsset && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: iconAsset, icon: "image", size: 16, className: "w-4 h-4 object-contain flex-shrink-0" }),
9530
9543
  formatTime(seconds, format)
9531
9544
  ]
9532
9545
  }
9533
9546
  );
9534
9547
  }
9535
- var sizeMap4;
9548
+ var sizeMap5;
9536
9549
  var init_TimerDisplay = __esm({
9537
9550
  "components/game/2d/atoms/TimerDisplay.tsx"() {
9538
9551
  init_cn();
9539
- sizeMap4 = {
9552
+ init_Box();
9553
+ init_GameIcon();
9554
+ sizeMap5 = {
9540
9555
  sm: "text-sm px-2 py-0.5",
9541
9556
  md: "text-lg px-3 py-1",
9542
9557
  lg: "text-2xl px-4 py-1.5"
@@ -9554,9 +9569,9 @@ function ResourceCounter({
9554
9569
  size = "md",
9555
9570
  className
9556
9571
  }) {
9557
- const sizes = sizeMap5[size];
9572
+ const sizes = sizeMap6[size];
9558
9573
  return /* @__PURE__ */ jsxRuntime.jsxs(
9559
- "div",
9574
+ Box,
9560
9575
  {
9561
9576
  className: cn(
9562
9577
  "inline-flex items-center rounded-container",
@@ -9565,21 +9580,11 @@ function ResourceCounter({
9565
9580
  className
9566
9581
  ),
9567
9582
  children: [
9568
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9569
- "img",
9570
- {
9571
- src: assetUrl.url,
9572
- alt: label,
9573
- width: sizes.img,
9574
- height: sizes.img,
9575
- style: { imageRendering: "pixelated", objectFit: "contain" },
9576
- className: "flex-shrink-0"
9577
- }
9578
- ) : 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,
9579
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
9580
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
9583
+ 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,
9584
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
9585
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
9581
9586
  value,
9582
- max != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9587
+ max != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9583
9588
  "/",
9584
9589
  max
9585
9590
  ] })
@@ -9588,11 +9593,14 @@ function ResourceCounter({
9588
9593
  }
9589
9594
  );
9590
9595
  }
9591
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap5;
9596
+ var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
9592
9597
  var init_ResourceCounter = __esm({
9593
9598
  "components/game/2d/atoms/ResourceCounter.tsx"() {
9594
9599
  init_cn();
9595
9600
  init_Icon();
9601
+ init_Box();
9602
+ init_Typography();
9603
+ init_GameIcon();
9596
9604
  colorTokenClasses2 = {
9597
9605
  primary: "text-primary",
9598
9606
  secondary: "text-secondary",
@@ -9606,7 +9614,7 @@ var init_ResourceCounter = __esm({
9606
9614
  role: "ui",
9607
9615
  category: "coin"
9608
9616
  };
9609
- sizeMap5 = {
9617
+ sizeMap6 = {
9610
9618
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
9611
9619
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
9612
9620
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -9631,9 +9639,9 @@ function ItemSlot({
9631
9639
  const isClickable = onClick != null || action != null;
9632
9640
  const px = assetSizeMap[size];
9633
9641
  return /* @__PURE__ */ jsxRuntime.jsx(
9634
- "button",
9642
+ Button,
9635
9643
  {
9636
- type: "button",
9644
+ variant: "ghost",
9637
9645
  onClick: () => {
9638
9646
  if (action) eventBus.emit(`UI:${action}`, {});
9639
9647
  onClick?.();
@@ -9643,7 +9651,7 @@ function ItemSlot({
9643
9651
  className: cn(
9644
9652
  "relative flex items-center justify-center rounded-interactive border-2",
9645
9653
  "bg-card/80 transition-all duration-150",
9646
- sizeMap6[size],
9654
+ sizeMap7[size],
9647
9655
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
9648
9656
  !empty && rarityGlowMap[rarity],
9649
9657
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -9652,21 +9660,12 @@ function ItemSlot({
9652
9660
  !isClickable && "cursor-default",
9653
9661
  className
9654
9662
  ),
9655
- children: empty ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9656
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9657
- "img",
9658
- {
9659
- src: assetUrl?.url,
9660
- alt: label,
9661
- width: px,
9662
- height: px,
9663
- style: { imageRendering: "pixelated", objectFit: "contain" },
9664
- className: "flex-shrink-0"
9665
- }
9666
- ) : 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,
9663
+ children: empty ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9664
+ 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,
9667
9665
  quantity != null && quantity > 1 && /* @__PURE__ */ jsxRuntime.jsx(
9668
- "span",
9666
+ Typography,
9669
9667
  {
9668
+ as: "span",
9670
9669
  className: cn(
9671
9670
  "absolute -bottom-1 -right-1 flex items-center justify-center",
9672
9671
  "min-w-[18px] h-[18px] rounded-full px-1",
@@ -9679,14 +9678,18 @@ function ItemSlot({
9679
9678
  }
9680
9679
  );
9681
9680
  }
9682
- var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9681
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9683
9682
  var init_ItemSlot = __esm({
9684
9683
  "components/game/2d/atoms/ItemSlot.tsx"() {
9685
9684
  "use client";
9686
9685
  init_cn();
9687
9686
  init_Icon();
9688
9687
  init_useEventBus();
9689
- sizeMap6 = {
9688
+ init_Button();
9689
+ init_Box();
9690
+ init_Typography();
9691
+ init_GameIcon();
9692
+ sizeMap7 = {
9690
9693
  sm: "w-10 h-10 text-lg",
9691
9694
  md: "w-14 h-14 text-2xl",
9692
9695
  lg: "w-18 h-18 text-3xl"
@@ -9727,9 +9730,9 @@ function TurnIndicator({
9727
9730
  size = "md",
9728
9731
  className
9729
9732
  }) {
9730
- const sizes = sizeMap7[size];
9733
+ const sizes = sizeMap8[size];
9731
9734
  return /* @__PURE__ */ jsxRuntime.jsxs(
9732
- "div",
9735
+ Box,
9733
9736
  {
9734
9737
  className: cn(
9735
9738
  "inline-flex items-center rounded-container",
@@ -9738,42 +9741,35 @@ function TurnIndicator({
9738
9741
  className
9739
9742
  ),
9740
9743
  children: [
9741
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold tabular-nums", children: [
9744
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "font-bold tabular-nums", children: [
9742
9745
  "Turn ",
9743
9746
  currentTurn,
9744
- maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9747
+ maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9745
9748
  "/",
9746
9749
  maxTurns
9747
9750
  ] })
9748
9751
  ] }),
9749
9752
  phase && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9750
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
9751
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: phase })
9753
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9754
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: phase })
9752
9755
  ] }),
9753
9756
  activeTeam && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9754
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
9755
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9756
- "img",
9757
- {
9758
- src: assetUrl.url,
9759
- alt: "",
9760
- width: 12,
9761
- height: 12,
9762
- style: { imageRendering: "pixelated", objectFit: "contain" },
9763
- className: "flex-shrink-0"
9764
- }
9765
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full bg-success/20", sizes.dot) }),
9766
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-success", children: activeTeam })
9757
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9758
+ 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) }),
9759
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-success", children: activeTeam })
9767
9760
  ] })
9768
9761
  ]
9769
9762
  }
9770
9763
  );
9771
9764
  }
9772
- var sizeMap7, DEFAULT_ASSET_URL6;
9765
+ var sizeMap8, DEFAULT_ASSET_URL6;
9773
9766
  var init_TurnIndicator = __esm({
9774
9767
  "components/game/2d/atoms/TurnIndicator.tsx"() {
9775
9768
  init_cn();
9776
- sizeMap7 = {
9769
+ init_Box();
9770
+ init_Typography();
9771
+ init_GameIcon();
9772
+ sizeMap8 = {
9777
9773
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
9778
9774
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
9779
9775
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
@@ -9805,10 +9801,10 @@ function ComboCounter({
9805
9801
  size = "md",
9806
9802
  className
9807
9803
  }) {
9808
- const sizes = sizeMap8[size];
9804
+ const sizes = sizeMap9[size];
9809
9805
  if (combo <= 0) return null;
9810
9806
  return /* @__PURE__ */ jsxRuntime.jsxs(
9811
- "div",
9807
+ Box,
9812
9808
  {
9813
9809
  className: cn(
9814
9810
  "inline-flex flex-col items-center justify-center",
@@ -9818,24 +9814,14 @@ function ComboCounter({
9818
9814
  className
9819
9815
  ),
9820
9816
  children: [
9821
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
9822
- "img",
9823
- {
9824
- src: assetUrl.url,
9825
- alt: "combo",
9826
- width: 24,
9827
- height: 24,
9828
- style: { imageRendering: "pixelated", objectFit: "contain" },
9829
- className: "flex-shrink-0 mb-0.5"
9830
- }
9831
- ),
9832
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
9833
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
9834
- multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
9817
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0 mb-0.5" }),
9818
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
9819
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
9820
+ multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
9835
9821
  "x",
9836
9822
  multiplier.toFixed(1)
9837
9823
  ] }),
9838
- streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9824
+ streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9839
9825
  streak,
9840
9826
  " streak"
9841
9827
  ] })
@@ -9843,16 +9829,19 @@ function ComboCounter({
9843
9829
  }
9844
9830
  );
9845
9831
  }
9846
- var DEFAULT_ASSET_URL7, sizeMap8;
9832
+ var DEFAULT_ASSET_URL7, sizeMap9;
9847
9833
  var init_ComboCounter = __esm({
9848
9834
  "components/game/2d/atoms/ComboCounter.tsx"() {
9849
9835
  init_cn();
9836
+ init_Box();
9837
+ init_Typography();
9838
+ init_GameIcon();
9850
9839
  DEFAULT_ASSET_URL7 = {
9851
9840
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
9852
9841
  role: "effect",
9853
9842
  category: "effect"
9854
9843
  };
9855
- sizeMap8 = {
9844
+ sizeMap9 = {
9856
9845
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
9857
9846
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
9858
9847
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -9869,54 +9858,48 @@ function WaypointMarker({
9869
9858
  size = "md",
9870
9859
  className
9871
9860
  }) {
9872
- const sizes = sizeMap9[size];
9873
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center", className), children: [
9874
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
9861
+ const sizes = sizeMap10[size];
9862
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col items-center", className), children: [
9863
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative flex items-center justify-center", children: [
9875
9864
  active && /* @__PURE__ */ jsxRuntime.jsx(
9876
- "div",
9865
+ Box,
9877
9866
  {
9867
+ position: "absolute",
9878
9868
  className: cn(
9879
- "absolute rounded-full border-2 border-info animate-ping opacity-50",
9869
+ "rounded-full border-2 border-info animate-ping opacity-50",
9880
9870
  sizes.ring
9881
9871
  )
9882
9872
  }
9883
9873
  ),
9884
9874
  active && /* @__PURE__ */ jsxRuntime.jsx(
9885
- "div",
9875
+ Box,
9886
9876
  {
9877
+ position: "absolute",
9887
9878
  className: cn(
9888
- "absolute rounded-full border-2 border-info",
9879
+ "rounded-full border-2 border-info",
9889
9880
  sizes.ring
9890
9881
  )
9891
9882
  }
9892
9883
  ),
9893
9884
  /* @__PURE__ */ jsxRuntime.jsx(
9894
- "div",
9885
+ Box,
9895
9886
  {
9887
+ position: "relative",
9896
9888
  className: cn(
9897
- "relative flex items-center justify-center rounded-full transition-all duration-200",
9889
+ "flex items-center justify-center rounded-full transition-all duration-200",
9898
9890
  sizes.dot,
9899
9891
  completed && "bg-success text-foreground",
9900
9892
  active && !completed && "bg-info text-foreground",
9901
9893
  !active && !completed && "bg-muted"
9902
9894
  ),
9903
- children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9904
- "img",
9905
- {
9906
- src: assetUrl.url,
9907
- alt: label,
9908
- width: sizes.img,
9909
- height: sizes.img,
9910
- style: { imageRendering: "pixelated", objectFit: "contain" },
9911
- className: "flex-shrink-0"
9912
- }
9913
- ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) : null
9895
+ 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
9914
9896
  }
9915
9897
  )
9916
9898
  ] }),
9917
9899
  label && /* @__PURE__ */ jsxRuntime.jsx(
9918
- "span",
9900
+ Typography,
9919
9901
  {
9902
+ as: "span",
9920
9903
  className: cn(
9921
9904
  "text-center whitespace-nowrap",
9922
9905
  sizes.label,
@@ -9927,17 +9910,20 @@ function WaypointMarker({
9927
9910
  )
9928
9911
  ] });
9929
9912
  }
9930
- var DEFAULT_ASSET_URL8, sizeMap9, checkIcon;
9913
+ var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
9931
9914
  var init_WaypointMarker = __esm({
9932
9915
  "components/game/2d/atoms/WaypointMarker.tsx"() {
9933
9916
  init_cn();
9934
9917
  init_Icon();
9918
+ init_Box();
9919
+ init_Typography();
9920
+ init_GameIcon();
9935
9921
  DEFAULT_ASSET_URL8 = {
9936
9922
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
9937
9923
  role: "ui",
9938
9924
  category: "waypoint"
9939
9925
  };
9940
- sizeMap9 = {
9926
+ sizeMap10 = {
9941
9927
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
9942
9928
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
9943
9929
  lg: { dot: "w-8 h-8", ring: "w-10 h-10", label: "text-base mt-2", img: 24 }
@@ -9962,32 +9948,24 @@ function StatusEffect({
9962
9948
  size = "md",
9963
9949
  className
9964
9950
  }) {
9965
- const sizes = sizeMap10[size];
9966
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
9951
+ const sizes = sizeMap11[size];
9952
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn("inline-flex flex-col items-center", className), children: [
9967
9953
  /* @__PURE__ */ jsxRuntime.jsxs(
9968
- "div",
9954
+ Box,
9969
9955
  {
9956
+ position: "relative",
9970
9957
  className: cn(
9971
- "relative flex items-center justify-center rounded-interactive border-2",
9958
+ "flex items-center justify-center rounded-interactive border-2",
9972
9959
  sizes.container,
9973
9960
  variantStyles7[variant]
9974
9961
  ),
9975
9962
  title: label,
9976
9963
  children: [
9977
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9978
- "img",
9979
- {
9980
- src: assetUrl.url,
9981
- alt: label,
9982
- width: sizes.img,
9983
- height: sizes.img,
9984
- style: { imageRendering: "pixelated", objectFit: "contain" },
9985
- className: "flex-shrink-0"
9986
- }
9987
- ) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, size: "sm" }) : null }),
9964
+ /* @__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 }),
9988
9965
  duration !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
9989
- "span",
9966
+ Typography,
9990
9967
  {
9968
+ as: "span",
9991
9969
  className: cn(
9992
9970
  "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
9993
9971
  sizes.timer
@@ -9999,8 +9977,9 @@ function StatusEffect({
9999
9977
  }
10000
9978
  ),
10001
9979
  stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsxRuntime.jsx(
10002
- "span",
9980
+ Typography,
10003
9981
  {
9982
+ as: "span",
10004
9983
  className: cn(
10005
9984
  "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
10006
9985
  sizes.badge
@@ -10008,20 +9987,23 @@ function StatusEffect({
10008
9987
  children: stacks
10009
9988
  }
10010
9989
  ),
10011
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
9990
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
10012
9991
  ] });
10013
9992
  }
10014
- var DEFAULT_ASSET_URL9, sizeMap10, variantStyles7;
9993
+ var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
10015
9994
  var init_StatusEffect = __esm({
10016
9995
  "components/game/2d/atoms/StatusEffect.tsx"() {
10017
9996
  init_cn();
10018
9997
  init_Icon();
9998
+ init_Box();
9999
+ init_Typography();
10000
+ init_GameIcon();
10019
10001
  DEFAULT_ASSET_URL9 = {
10020
10002
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
10021
10003
  role: "ui",
10022
10004
  category: "effect"
10023
10005
  };
10024
- sizeMap10 = {
10006
+ sizeMap11 = {
10025
10007
  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 },
10026
10008
  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 },
10027
10009
  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 }
@@ -10045,38 +10027,31 @@ function DamageNumber({
10045
10027
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10046
10028
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: floatKeyframes }),
10047
10029
  /* @__PURE__ */ jsxRuntime.jsxs(
10048
- "span",
10030
+ Typography,
10049
10031
  {
10032
+ as: "span",
10050
10033
  className: cn(
10051
10034
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
10052
- sizeMap11[size],
10035
+ sizeMap12[size],
10053
10036
  typeStyles[type],
10054
10037
  className
10055
10038
  ),
10056
10039
  style: { animation: "damageFloat 1s ease-out forwards" },
10057
10040
  children: [
10058
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
10059
- "img",
10060
- {
10061
- src: assetUrl.url,
10062
- alt: "",
10063
- width: 14,
10064
- height: 14,
10065
- style: { imageRendering: "pixelated", objectFit: "contain" },
10066
- className: "flex-shrink-0"
10067
- }
10068
- ),
10041
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 14, className: "flex-shrink-0" }),
10069
10042
  displayText
10070
10043
  ]
10071
10044
  }
10072
10045
  )
10073
10046
  ] });
10074
10047
  }
10075
- var sizeMap11, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
10048
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
10076
10049
  var init_DamageNumber = __esm({
10077
10050
  "components/game/2d/atoms/DamageNumber.tsx"() {
10078
10051
  init_cn();
10079
- sizeMap11 = {
10052
+ init_Typography();
10053
+ init_GameIcon();
10054
+ sizeMap12 = {
10080
10055
  sm: "text-sm",
10081
10056
  md: "text-lg",
10082
10057
  lg: "text-2xl"
@@ -10110,7 +10085,7 @@ function DialogueBubble({
10110
10085
  className
10111
10086
  }) {
10112
10087
  return /* @__PURE__ */ jsxRuntime.jsxs(
10113
- "div",
10088
+ Box,
10114
10089
  {
10115
10090
  className: cn(
10116
10091
  "flex items-start gap-3 rounded-container bg-background/80 backdrop-blur-sm px-4 py-3 border border-border/10",
@@ -10118,17 +10093,10 @@ function DialogueBubble({
10118
10093
  className
10119
10094
  ),
10120
10095
  children: [
10121
- 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(
10122
- "img",
10123
- {
10124
- src: portrait?.url,
10125
- alt: speaker ?? "speaker",
10126
- className: "w-full h-full object-cover"
10127
- }
10128
- ) }),
10129
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [
10130
- speaker && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold text-warning", children: speaker }),
10131
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground leading-relaxed", children: text })
10096
+ 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" }) }),
10097
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-1 min-w-0", children: [
10098
+ speaker && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm font-bold text-warning", children: speaker }),
10099
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm text-foreground leading-relaxed", children: text })
10132
10100
  ] })
10133
10101
  ]
10134
10102
  }
@@ -10138,6 +10106,9 @@ var DEFAULT_PORTRAIT;
10138
10106
  var init_DialogueBubble = __esm({
10139
10107
  "components/game/2d/atoms/DialogueBubble.tsx"() {
10140
10108
  init_cn();
10109
+ init_Box();
10110
+ init_Typography();
10111
+ init_GameIcon();
10141
10112
  DEFAULT_PORTRAIT = {
10142
10113
  url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
10143
10114
  role: "effect",
@@ -10159,11 +10130,11 @@ function ChoiceButton({
10159
10130
  }) {
10160
10131
  const eventBus = useEventBus();
10161
10132
  return /* @__PURE__ */ jsxRuntime.jsxs(
10162
- "button",
10133
+ Button,
10163
10134
  {
10164
- type: "button",
10135
+ variant: "ghost",
10165
10136
  disabled,
10166
- onClick: (e) => {
10137
+ onClick: () => {
10167
10138
  if (action) eventBus.emit(`UI:${action}`, {});
10168
10139
  onClick?.();
10169
10140
  },
@@ -10176,8 +10147,9 @@ function ChoiceButton({
10176
10147
  ),
10177
10148
  children: [
10178
10149
  index !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(
10179
- "span",
10150
+ Typography,
10180
10151
  {
10152
+ as: "span",
10181
10153
  className: cn(
10182
10154
  "flex-shrink-0 font-mono font-bold text-sm",
10183
10155
  selected ? "text-accent" : "text-muted-foreground"
@@ -10188,24 +10160,14 @@ function ChoiceButton({
10188
10160
  ]
10189
10161
  }
10190
10162
  ),
10191
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
10192
- "img",
10193
- {
10194
- src: assetUrl.url,
10195
- alt: "",
10196
- width: 16,
10197
- height: 16,
10198
- style: { imageRendering: "pixelated", objectFit: "contain" },
10199
- className: "flex-shrink-0"
10200
- }
10201
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
10163
+ 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" ? (() => {
10202
10164
  const I = resolveIcon(icon);
10203
10165
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
10204
10166
  })() : /* @__PURE__ */ (() => {
10205
10167
  const I = icon;
10206
10168
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
10207
10169
  })() }) : null,
10208
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-snug", children: text })
10170
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm leading-snug", children: text })
10209
10171
  ]
10210
10172
  }
10211
10173
  );
@@ -10215,6 +10177,10 @@ var init_ChoiceButton = __esm({
10215
10177
  init_cn();
10216
10178
  init_Icon();
10217
10179
  init_useEventBus();
10180
+ init_Button();
10181
+ init_Box();
10182
+ init_Typography();
10183
+ init_GameIcon();
10218
10184
  ChoiceButton.displayName = "ChoiceButton";
10219
10185
  }
10220
10186
  });
@@ -10232,16 +10198,16 @@ function ActionButton({
10232
10198
  className
10233
10199
  }) {
10234
10200
  const eventBus = useEventBus();
10235
- const sizes = sizeMap12[size];
10201
+ const sizes = sizeMap13[size];
10236
10202
  const onCooldown = cooldown > 0;
10237
10203
  const isDisabled = disabled || onCooldown;
10238
10204
  const cooldownDeg = Math.round(cooldown * 360);
10239
10205
  return /* @__PURE__ */ jsxRuntime.jsxs(
10240
- "button",
10206
+ Button,
10241
10207
  {
10242
- type: "button",
10208
+ variant: variant === "danger" ? "danger" : variant === "secondary" ? "secondary" : "primary",
10243
10209
  disabled: isDisabled,
10244
- onClick: (e) => {
10210
+ onClick: () => {
10245
10211
  if (action) eventBus.emit(`UI:${action}`, {});
10246
10212
  onClick?.();
10247
10213
  },
@@ -10254,9 +10220,10 @@ function ActionButton({
10254
10220
  ),
10255
10221
  children: [
10256
10222
  onCooldown && /* @__PURE__ */ jsxRuntime.jsx(
10257
- "div",
10223
+ Box,
10258
10224
  {
10259
- className: "absolute inset-0 bg-foreground/40 pointer-events-none",
10225
+ position: "absolute",
10226
+ className: "inset-0 bg-foreground/40 pointer-events-none",
10260
10227
  style: {
10261
10228
  clipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
10262
10229
  WebkitClipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
@@ -10264,27 +10231,18 @@ function ActionButton({
10264
10231
  }
10265
10232
  }
10266
10233
  ),
10267
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
10268
- "img",
10269
- {
10270
- src: assetUrl.url,
10271
- alt: "",
10272
- width: 16,
10273
- height: 16,
10274
- style: { imageRendering: "pixelated", objectFit: "contain" },
10275
- className: cn("flex-shrink-0", sizes.icon)
10276
- }
10277
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
10234
+ 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" ? (() => {
10278
10235
  const I = resolveIcon(icon);
10279
10236
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
10280
10237
  })() : /* @__PURE__ */ (() => {
10281
10238
  const I = icon;
10282
10239
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
10283
10240
  })() }) : null,
10284
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10", children: label }),
10241
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "relative z-10", children: label }),
10285
10242
  hotkey && /* @__PURE__ */ jsxRuntime.jsx(
10286
- "span",
10243
+ Typography,
10287
10244
  {
10245
+ as: "span",
10288
10246
  className: cn(
10289
10247
  "absolute top-0.5 right-0.5 bg-foreground/30 text-primary-foreground rounded font-mono leading-tight",
10290
10248
  sizes.hotkey
@@ -10296,13 +10254,17 @@ function ActionButton({
10296
10254
  }
10297
10255
  );
10298
10256
  }
10299
- var sizeMap12, variantStyles8, DEFAULT_ASSET_URL11;
10257
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
10300
10258
  var init_ActionButton = __esm({
10301
10259
  "components/game/2d/atoms/ActionButton.tsx"() {
10302
10260
  init_cn();
10303
10261
  init_Icon();
10304
10262
  init_useEventBus();
10305
- sizeMap12 = {
10263
+ init_Button();
10264
+ init_Box();
10265
+ init_Typography();
10266
+ init_GameIcon();
10267
+ sizeMap13 = {
10306
10268
  sm: { button: "h-button-sm px-3 text-xs", hotkey: "text-[9px] px-1", icon: "text-xs" },
10307
10269
  md: { button: "h-button-md px-4 text-sm", hotkey: "text-xs px-1.5", icon: "text-sm" },
10308
10270
  lg: { button: "h-button-lg px-5 text-base", hotkey: "text-xs px-2", icon: "text-base" }
@@ -10404,10 +10366,12 @@ function MiniMap({
10404
10366
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10405
10367
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes minimap-blink{0%,49%{opacity:1}50%,100%{opacity:0}}` }),
10406
10368
  /* @__PURE__ */ jsxRuntime.jsxs(
10407
- "div",
10369
+ Box,
10408
10370
  {
10371
+ position: "relative",
10372
+ display: "inline-block",
10409
10373
  className: cn(
10410
- "relative inline-block border border-border/20 rounded-container",
10374
+ "border border-border/20 rounded-container",
10411
10375
  className
10412
10376
  ),
10413
10377
  children: [
@@ -10422,10 +10386,10 @@ function MiniMap({
10422
10386
  }
10423
10387
  ),
10424
10388
  playerLeft !== null && playerTop !== null && /* @__PURE__ */ jsxRuntime.jsx(
10425
- "div",
10389
+ Box,
10426
10390
  {
10391
+ position: "absolute",
10427
10392
  style: {
10428
- position: "absolute",
10429
10393
  left: playerLeft,
10430
10394
  top: playerTop,
10431
10395
  width: 3,
@@ -10446,6 +10410,7 @@ var init_MiniMap = __esm({
10446
10410
  "components/game/2d/atoms/MiniMap.tsx"() {
10447
10411
  "use client";
10448
10412
  init_cn();
10413
+ init_Box();
10449
10414
  DEFAULT_TILES = [
10450
10415
  { x: 10, y: 10, color: "#4ade80" },
10451
10416
  { x: 20, y: 15, color: "#4ade80" },
@@ -10463,38 +10428,6 @@ var init_MiniMap = __esm({
10463
10428
  MiniMap.displayName = "MiniMap";
10464
10429
  }
10465
10430
  });
10466
- function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
10467
- const px = typeof size === "number" ? size : sizeMap13[size];
10468
- if (assetUrl?.url) {
10469
- return /* @__PURE__ */ jsxRuntime.jsx(
10470
- "img",
10471
- {
10472
- src: assetUrl.url,
10473
- alt: alt ?? assetUrl.category ?? "",
10474
- width: px,
10475
- height: px,
10476
- style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
10477
- className: cn("flex-shrink-0", className)
10478
- }
10479
- );
10480
- }
10481
- const I = typeof icon === "string" ? resolveIcon(icon) : icon;
10482
- return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
10483
- }
10484
- var sizeMap13;
10485
- var init_GameIcon = __esm({
10486
- "components/game/2d/atoms/GameIcon.tsx"() {
10487
- "use client";
10488
- init_cn();
10489
- init_Icon();
10490
- sizeMap13 = {
10491
- sm: 16,
10492
- md: 24,
10493
- lg: 32
10494
- };
10495
- GameIcon.displayName = "GameIcon";
10496
- }
10497
- });
10498
10431
  function ControlGrid({
10499
10432
  kind,
10500
10433
  buttons = DEFAULT_BUTTONS,
@@ -10555,22 +10488,22 @@ function ControlGrid({
10555
10488
  },
10556
10489
  d
10557
10490
  );
10558
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
10559
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10491
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
10492
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10560
10493
  dir("up"),
10561
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10494
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10562
10495
  dir("left"),
10563
- /* @__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" }) }),
10496
+ /* @__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" }) }),
10564
10497
  dir("right"),
10565
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10498
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10566
10499
  dir("down"),
10567
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10500
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10568
10501
  ] });
10569
10502
  }
10570
10503
  if (layout === "diamond" && buttons.length === 4) {
10571
10504
  const [top, right, bottom, left] = buttons;
10572
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(layoutClass.diamond, className), children: [
10573
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10505
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(layoutClass.diamond, className), children: [
10506
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10574
10507
  /* @__PURE__ */ jsxRuntime.jsx(
10575
10508
  ControlButton,
10576
10509
  {
@@ -10585,7 +10518,7 @@ function ControlGrid({
10585
10518
  disabled
10586
10519
  }
10587
10520
  ),
10588
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10521
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10589
10522
  /* @__PURE__ */ jsxRuntime.jsx(
10590
10523
  ControlButton,
10591
10524
  {
@@ -10600,7 +10533,7 @@ function ControlGrid({
10600
10533
  disabled
10601
10534
  }
10602
10535
  ),
10603
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10536
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10604
10537
  /* @__PURE__ */ jsxRuntime.jsx(
10605
10538
  ControlButton,
10606
10539
  {
@@ -10615,7 +10548,7 @@ function ControlGrid({
10615
10548
  disabled
10616
10549
  }
10617
10550
  ),
10618
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10551
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10619
10552
  /* @__PURE__ */ jsxRuntime.jsx(
10620
10553
  ControlButton,
10621
10554
  {
@@ -10630,10 +10563,10 @@ function ControlGrid({
10630
10563
  disabled
10631
10564
  }
10632
10565
  ),
10633
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10566
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10634
10567
  ] });
10635
10568
  }
10636
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10569
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10637
10570
  ControlButton,
10638
10571
  {
10639
10572
  icon: button.icon,
@@ -10655,6 +10588,7 @@ var init_ControlGrid = __esm({
10655
10588
  "use client";
10656
10589
  init_cn();
10657
10590
  init_useEventBus();
10591
+ init_Box();
10658
10592
  init_ControlButton();
10659
10593
  sizeKey = { sm: "sm", md: "md", lg: "lg" };
10660
10594
  layoutClass = {
@@ -10699,7 +10633,7 @@ function StatBadge({
10699
10633
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
10700
10634
  const resolvedAsset = iconUrl ?? assetUrl;
10701
10635
  return /* @__PURE__ */ jsxRuntime.jsxs(
10702
- "div",
10636
+ Box,
10703
10637
  {
10704
10638
  className: cn(
10705
10639
  "inline-flex items-center gap-2 rounded-container border backdrop-blur-sm",
@@ -10708,18 +10642,8 @@ function StatBadge({
10708
10642
  className
10709
10643
  ),
10710
10644
  children: [
10711
- resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(
10712
- "img",
10713
- {
10714
- src: resolvedAsset.url,
10715
- alt: "",
10716
- width: 16,
10717
- height: 16,
10718
- style: { imageRendering: "pixelated", objectFit: "contain" },
10719
- className: "flex-shrink-0"
10720
- }
10721
- ) : 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,
10722
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground font-medium", children: label }),
10645
+ 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,
10646
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
10723
10647
  format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
10724
10648
  HealthBar,
10725
10649
  {
@@ -10745,7 +10669,7 @@ function StatBadge({
10745
10669
  size: size === "lg" ? "md" : "sm"
10746
10670
  }
10747
10671
  ),
10748
- format === "text" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-foreground", children: value })
10672
+ format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
10749
10673
  ]
10750
10674
  }
10751
10675
  );
@@ -10755,6 +10679,9 @@ var init_StatBadge = __esm({
10755
10679
  "components/game/2d/molecules/StatBadge.tsx"() {
10756
10680
  init_cn();
10757
10681
  init_Icon();
10682
+ init_Box();
10683
+ init_Typography();
10684
+ init_GameIcon();
10758
10685
  init_HealthBar();
10759
10686
  init_ScoreDisplay();
10760
10687
  sizeMap14 = {
@@ -10932,9 +10859,9 @@ function GameHud({
10932
10859
  if (position === "corners") {
10933
10860
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
10934
10861
  const rightStats = stats.slice(Math.ceil(stats.length / 2));
10935
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", positionMap[position], className), children: [
10936
- /* @__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)) }),
10937
- /* @__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)) })
10862
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn(positionMap[position], className), children: [
10863
+ /* @__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)) }),
10864
+ /* @__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)) })
10938
10865
  ] });
10939
10866
  }
10940
10867
  if (position === "top" || position === "bottom") {
@@ -10943,7 +10870,7 @@ function GameHud({
10943
10870
  const rightStats = stats.slice(mid);
10944
10871
  const isTop = position === "top";
10945
10872
  return /* @__PURE__ */ jsxRuntime.jsxs(
10946
- "div",
10873
+ Box,
10947
10874
  {
10948
10875
  className: cn(
10949
10876
  "flex items-center justify-between w-full",
@@ -10953,17 +10880,18 @@ function GameHud({
10953
10880
  className
10954
10881
  ),
10955
10882
  children: [
10956
- /* @__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)) }),
10957
- 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)) })
10883
+ /* @__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)) }),
10884
+ 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)) })
10958
10885
  ]
10959
10886
  }
10960
10887
  );
10961
10888
  }
10962
10889
  return /* @__PURE__ */ jsxRuntime.jsx(
10963
- "div",
10890
+ Box,
10964
10891
  {
10892
+ position: "relative",
10965
10893
  className: cn(
10966
- "relative z-10 flex items-center gap-4 px-4 py-2",
10894
+ "z-10 flex items-center gap-4 px-4 py-2",
10967
10895
  transparent ? "bg-black/30 backdrop-blur-sm" : "bg-surface/90 backdrop-blur-sm",
10968
10896
  className
10969
10897
  ),
@@ -10975,6 +10903,7 @@ var positionMap, DEFAULT_HUD_STATS;
10975
10903
  var init_GameHud = __esm({
10976
10904
  "components/game/2d/molecules/GameHud.tsx"() {
10977
10905
  init_cn();
10906
+ init_Box();
10978
10907
  init_StatBadge();
10979
10908
  positionMap = {
10980
10909
  corners: "inset-0 pointer-events-none"
@@ -11015,7 +10944,7 @@ function GameMenu({
11015
10944
  [eventBus, onSelect]
11016
10945
  );
11017
10946
  return /* @__PURE__ */ jsxRuntime.jsxs(
11018
- "div",
10947
+ Box,
11019
10948
  {
11020
10949
  className: cn(
11021
10950
  "min-h-screen w-full flex flex-col items-center justify-center p-8",
@@ -11025,18 +10954,12 @@ function GameMenu({
11025
10954
  background: background ?? "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0e17 100%)"
11026
10955
  },
11027
10956
  children: [
11028
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-12 animate-fade-in", children: [
11029
- logo && /* @__PURE__ */ jsxRuntime.jsx(
11030
- "img",
11031
- {
11032
- src: logo.url,
11033
- alt: title,
11034
- className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl"
11035
- }
11036
- ),
10957
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "text-center mb-12 animate-fade-in", children: [
10958
+ 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" }),
11037
10959
  /* @__PURE__ */ jsxRuntime.jsx(
11038
- "h1",
10960
+ Typography,
11039
10961
  {
10962
+ variant: "h1",
11040
10963
  className: "text-5xl md:text-7xl font-bold text-[var(--color-foreground)] tracking-tight",
11041
10964
  style: {
11042
10965
  textShadow: "0 4px 12px rgba(0,0,0,0.5)"
@@ -11044,9 +10967,9 @@ function GameMenu({
11044
10967
  children: title
11045
10968
  }
11046
10969
  ),
11047
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
10970
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
11048
10971
  ] }),
11049
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
10972
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
11050
10973
  ChoiceButton,
11051
10974
  {
11052
10975
  text: option.label,
@@ -11057,9 +10980,9 @@ function GameMenu({
11057
10980
  },
11058
10981
  index
11059
10982
  )) }),
11060
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none overflow-hidden", children: [
11061
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
11062
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
10983
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "absolute", className: "inset-0 pointer-events-none overflow-hidden", children: [
10984
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
10985
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
11063
10986
  ] })
11064
10987
  ]
11065
10988
  }
@@ -11071,6 +10994,9 @@ var init_GameMenu = __esm({
11071
10994
  "use client";
11072
10995
  init_cn();
11073
10996
  init_useEventBus();
10997
+ init_Box();
10998
+ init_Typography();
10999
+ init_GameIcon();
11074
11000
  init_ChoiceButton();
11075
11001
  DEFAULT_MENU_OPTIONS = [
11076
11002
  { label: "New Game", event: "NEW_GAME", variant: "primary" },
@@ -12311,10 +12237,11 @@ function Canvas2D({
12311
12237
  }
12312
12238
  }
12313
12239
  ),
12314
- process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
12240
+ process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
12315
12241
  tileClickEvent && /* @__PURE__ */ jsxRuntime.jsx(
12316
- "button",
12242
+ Button,
12317
12243
  {
12244
+ variant: "ghost",
12318
12245
  "data-event": tileClickEvent,
12319
12246
  "data-x": "0",
12320
12247
  "data-y": "0",
@@ -12323,8 +12250,9 @@ function Canvas2D({
12323
12250
  }
12324
12251
  ),
12325
12252
  unitClickEvent && units && units.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
12326
- "button",
12253
+ Button,
12327
12254
  {
12255
+ variant: "ghost",
12328
12256
  "data-event": unitClickEvent,
12329
12257
  "data-unit-id": units[0].id,
12330
12258
  onClick: () => eventBus.emit(`UI:${unitClickEvent}`, { unitId: units[0].id }),
@@ -12333,15 +12261,17 @@ function Canvas2D({
12333
12261
  )
12334
12262
  ] }),
12335
12263
  unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxRuntime.jsxs(
12336
- "div",
12264
+ Box,
12337
12265
  {
12338
- className: "absolute pointer-events-none",
12266
+ position: "absolute",
12267
+ className: "pointer-events-none",
12339
12268
  style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
12340
12269
  children: [
12341
12270
  unit.name && /* @__PURE__ */ jsxRuntime.jsx(
12342
- "div",
12271
+ Typography,
12343
12272
  {
12344
- className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
12273
+ as: "span",
12274
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
12345
12275
  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)" },
12346
12276
  children: unit.name
12347
12277
  }
@@ -12351,7 +12281,7 @@ function Canvas2D({
12351
12281
  },
12352
12282
  unit.id
12353
12283
  )),
12354
- showMinimap && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
12284
+ showMinimap && /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
12355
12285
  MiniMap,
12356
12286
  {
12357
12287
  tiles: miniMapTiles,
@@ -12373,6 +12303,7 @@ var init_Canvas2D = __esm({
12373
12303
  init_cn();
12374
12304
  init_useEventBus();
12375
12305
  init_Box();
12306
+ init_Button();
12376
12307
  init_Stack();
12377
12308
  init_Icon();
12378
12309
  init_Typography();
@@ -12704,7 +12635,7 @@ function GameAudioToggle({
12704
12635
  onClick: handleToggle,
12705
12636
  className: cn("text-lg leading-none px-2", className),
12706
12637
  "aria-pressed": muted,
12707
- 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}"
12638
+ 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}"
12708
12639
  }
12709
12640
  );
12710
12641
  }
@@ -12714,6 +12645,7 @@ var init_GameAudioToggle = __esm({
12714
12645
  init_atoms();
12715
12646
  init_cn();
12716
12647
  init_GameAudioProvider();
12648
+ init_GameIcon();
12717
12649
  GameAudioToggle.displayName = "GameAudioToggle";
12718
12650
  }
12719
12651
  });