diff --git a/app-9xzmfic2e4g1/src/components/planner/BudgetSelector.tsx b/app-9xzmfic2e4g1/src/components/planner/BudgetSelector.tsx
new file mode 100644
index 0000000..8d09834
--- /dev/null
+++ b/app-9xzmfic2e4g1/src/components/planner/BudgetSelector.tsx
@@ -0,0 +1,106 @@
+import { memo } from 'react';
+import { BUDGET_OPTIONS } from '@/constants/planner';
+import { cn } from '@/lib/utils';
+import { motion } from 'framer-motion';
+
+interface BudgetSelectorProps {
+ selectedId: string;
+ onSelect: (id: string) => void;
+}
+
+export const BudgetSelector = memo(({ selectedId, onSelect }: BudgetSelectorProps) => {
+ const selectedIndex = BUDGET_OPTIONS.findIndex(o => o.id === selectedId);
+
+ return (
+
+ {/* Visual tier bar */}
+
+ {BUDGET_OPTIONS.map((option, i) => (
+
+ ))}
+
+
+
+ {BUDGET_OPTIONS.map((option, index) => {
+ const Icon = option.icon;
+ const isSelected = selectedId === option.id;
+
+ return (
+
onSelect(option.id)}
+ className={cn(
+ 'relative group flex items-center gap-4 px-5 py-4 rounded-2xl border-2 text-left transition-all duration-200 w-full overflow-hidden',
+ isSelected
+ ? `${option.activeBorder} ${option.activeBg} shadow-md`
+ : 'border-gray-100 bg-gray-50/60 hover:border-gray-200 hover:bg-white hover:shadow-sm'
+ )}
+ >
+ {/* Tier dots */}
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+ ))}
+
+
+ {/* Icon */}
+
+
+
+
+ {/* Text */}
+
+
+ {option.label}
+
+
+ {option.description}
+
+
+
+ {/* Price range */}
+
+ {option.range}
+
+
+ );
+ })}
+
+
+ );
+});
+
+BudgetSelector.displayName = 'BudgetSelector';
\ No newline at end of file