diff --git a/frontend/src/lib/ui/Badge.svelte b/frontend/src/lib/ui/Badge.svelte
new file mode 100644
index 00000000..17c80d71
--- /dev/null
+++ b/frontend/src/lib/ui/Badge.svelte
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if dot}
+
+ {/if}
+
+ {@render children?.()}
+
+
+
diff --git a/frontend/src/lib/ui/index.ts b/frontend/src/lib/ui/index.ts
index 94a63c6b..6bb71f1a 100644
--- a/frontend/src/lib/ui/index.ts
+++ b/frontend/src/lib/ui/index.ts
@@ -16,6 +16,7 @@ export { default as EmptyState } from './EmptyState.svelte';
export { default as LanguageSwitcher } from './LanguageSwitcher.svelte';
export { default as Icon } from './Icon.svelte';
export { default as HelpTooltip } from './HelpTooltip.svelte';
+export { default as Badge } from './Badge.svelte';
// [/SECTION: EXPORTS]
// #endregion ui:Module
\ No newline at end of file
diff --git a/frontend/src/lib/utils/dateFormat.ts b/frontend/src/lib/utils/dateFormat.ts
new file mode 100644
index 00000000..c2c1a307
--- /dev/null
+++ b/frontend/src/lib/utils/dateFormat.ts
@@ -0,0 +1,72 @@
+// #region Utils.DateFormat [C:2] [TYPE Module] [SEMANTICS date,format,utility,helper]
+// @ingroup Utils
+// @BRIEF Centralized date/time formatting utilities. Replaces 6+ local formatDate definitions.
+// @LAYER Infra
+// @RATIONALE 6 files defined independent formatDate functions and 20+ files use inline new Date().toLocaleDateString().
+// Consolidating into one module ensures consistent locale-aware formatting and reduces duplication.
+
+// #region formatDate:Function [TYPE Function]
+// @BRIEF Format ISO date string to localized short date (e.g. "15 Jan 2025").
+export function formatDate(value: string | Date | null | undefined): string {
+ if (!value) return "";
+ const d = typeof value === "string" ? new Date(value) : value;
+ if (isNaN(d.getTime())) return "";
+ return d.toLocaleDateString(undefined, {
+ year: "numeric",
+ month: "short",
+ day: "numeric",
+ });
+}
+// #endregion formatDate:Function
+
+// #region formatDateTime:Function [TYPE Function]
+// @BRIEF Format ISO date string to localized date+time (e.g. "15 Jan 2025, 14:30").
+export function formatDateTime(value: string | Date | null | undefined): string {
+ if (!value) return "";
+ const d = typeof value === "string" ? new Date(value) : value;
+ if (isNaN(d.getTime())) return "";
+ return d.toLocaleDateString(undefined, {
+ year: "numeric",
+ month: "short",
+ day: "numeric",
+ hour: "2-digit",
+ minute: "2-digit",
+ });
+}
+// #endregion formatDateTime:Function
+
+// #region formatRelativeTime:Function [TYPE Function]
+// @BRIEF Format date to relative time string (e.g. "2 hours ago", "just now").
+export function formatRelativeTime(value: string | Date | null | undefined): string {
+ if (!value) return "";
+ const d = typeof value === "string" ? new Date(value) : value;
+ if (isNaN(d.getTime())) return "";
+
+ const now = Date.now();
+ const diffMs = now - d.getTime();
+ const diffSec = Math.floor(diffMs / 1000);
+ const diffMin = Math.floor(diffSec / 60);
+ const diffHour = Math.floor(diffMin / 60);
+ const diffDay = Math.floor(diffHour / 24);
+
+ if (diffSec < 60) return "just now";
+ if (diffMin < 60) return `${diffMin}m ago`;
+ if (diffHour < 24) return `${diffHour}h ago`;
+ if (diffDay < 30) return `${diffDay}d ago`;
+ return formatDate(d);
+}
+// #endregion formatRelativeTime:Function
+
+// #region formatFileSize:Function [TYPE Function]
+// @BRIEF Format bytes to human-readable size (e.g. "1.5 MB").
+export function formatFileSize(bytes: number | null | undefined): string {
+ if (bytes == null || bytes < 0) return "";
+ if (bytes === 0) return "0 B";
+ const units = ["B", "KB", "MB", "GB", "TB"];
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
+ const val = bytes / Math.pow(1024, i);
+ return `${val.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
+}
+// #endregion formatFileSize:Function
+
+// #endregion Utils.DateFormat