diff --git a/package-lock.json b/package-lock.json
index b146856c..6208e36e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18534,6 +18534,7 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
diff --git a/src/components/MobileNavButton.tsx b/src/components/MobileNavButton.tsx
new file mode 100644
index 00000000..f8502bf4
--- /dev/null
+++ b/src/components/MobileNavButton.tsx
@@ -0,0 +1,35 @@
+import Link from 'next/link';
+import React from 'react';
+
+interface MobileNavButtonProps {
+ href: string;
+ icon: React.ReactNode;
+ label: string;
+ active?: boolean;
+}
+
+export function MobileNavButton({
+ href,
+ icon,
+ label,
+ active = false,
+}: MobileNavButtonProps) {
+ return (
+
+ {icon}
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/analytics/AnalyticsTableShimmer.tsx b/src/components/analytics/AnalyticsTableShimmer.tsx
new file mode 100644
index 00000000..fc948fa9
--- /dev/null
+++ b/src/components/analytics/AnalyticsTableShimmer.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+
+interface AnalyticsTableShimmerProps {
+ rows?: number;
+}
+
+export function AnalyticsTableShimmer({
+ rows = 6,
+}: AnalyticsTableShimmerProps) {
+ return (
+
+
+ {Array.from({ length: rows }).map((_, index) => (
+
+ ))}
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/eslint/deep-import-rules.js b/src/components/eslint/deep-import-rules.js
new file mode 100644
index 00000000..39f9a01a
--- /dev/null
+++ b/src/components/eslint/deep-import-rules.js
@@ -0,0 +1,34 @@
+/**
+ * Enforce deep imports across components.
+ *
+ * Prevents importing from barrel files such as:
+ * import { Button } from "@/components";
+ *
+ * Encourages:
+ * import Button from "@/components/ui/Button";
+ */
+
+export const deepImportRules = {
+ "no-restricted-imports": [
+ "warn",
+ {
+ paths: [
+ {
+ name: "@/components",
+ message:
+ "Use deep imports instead of barrel imports for better code-splitting.",
+ },
+ ],
+ patterns: [
+ {
+ group: [
+ "@/components/index",
+ "@/components/**/index",
+ ],
+ message:
+ "Import components directly from their source file instead of a barrel export.",
+ },
+ ],
+ },
+ ],
+};
\ No newline at end of file
diff --git a/src/hooks/usePropertyCardData.ts b/src/hooks/usePropertyCardData.ts
new file mode 100644
index 00000000..e9345b40
--- /dev/null
+++ b/src/hooks/usePropertyCardData.ts
@@ -0,0 +1,63 @@
+import { useMemo } from 'react';
+
+import type { Property } from '@/types/property';
+import { useComparisonStore } from '@/store/comparisonStore';
+import { useCompareStore } from '@/store/compareStore';
+import { useFavoritesStore } from '@/store/favoritesStore';
+
+import {
+ formatPrice,
+ formatNumber,
+ formatROI,
+ getBlockchainColor,
+} from '@/utils/searchUtils';
+
+export function usePropertyCardData(property: Property) {
+ const { isPropertySelected } = useComparisonStore();
+
+ const selectedIds = useCompareStore((state) => state.selectedIds);
+
+ const { isFavorite } = useFavoritesStore();
+
+ return useMemo(() => {
+ const isCompared = selectedIds.includes(property.id);
+
+ return {
+ isSelectedForComparison: isPropertySelected(property.id),
+
+ isCompared,
+
+ compareLimitReached:
+ selectedIds.length >= 3 && !isCompared,
+
+ isFavorite: isFavorite(property.id),
+
+ formattedROI: formatROI(property.metrics.roi),
+
+ formattedSquareFeet: formatNumber(
+ property.details.squareFeet,
+ ),
+
+ formattedAvailableTokens: formatNumber(
+ property.tokenInfo.available,
+ ),
+
+ formattedTotalSupply: formatNumber(
+ property.tokenInfo.totalSupply,
+ ),
+
+ formattedTokenPrice: formatPrice(
+ property.price.perToken,
+ ),
+
+ blockchainColor: getBlockchainColor(
+ property.blockchain,
+ ),
+ };
+ }, [
+ property,
+ selectedIds,
+ isPropertySelected,
+ isFavorite,
+ ]);
+}
\ No newline at end of file