import{useState,useEffect,useCallback}from "react"; import{Upload,Save,Trash2,Plus,X,Eye,Package,Palette,Settings,Check,AlertCircle,}from "lucide-react"; import{supabase,type PodProduct,type PodColor}from "../lib/supabase"; import TShirtMockup from "./TShirtMockup"; import ProductImageManager from "./ProductImageManager"; import OrderManager from "./OrderManager"; import "./AdminPanel.css"; const DEFAULT_SIZES = ["S","M","L","XL","XXL","XXXL"]; type ProductType = "tshirt" | "panjabi" | "beauty"; const PRODUCT_TYPES:{value:ProductType;label:string}[] = [{value: "tshirt",label: "T-Shirt",},{value: "panjabi",label: "Hand Painted Panjabi",},{value: "beauty",label: "Beauty Accessories",},]; const CATEGORY_OPTIONS: Record<ProductType,string[]> ={tshirt:["POD T-Shirt","Casual T-Shirt","Oversize T-Shirt","Polo T-Shirt","Free Size T-Shirt","Hand Design Custom T-Shirt",],panjabi: ["Hand Painted Panjabi","Classic Panjabi","Embroidery Panjabi","Design Panjabi",],beauty: ["Junk Jewellery","Hand Bags","Dolls & Soft Toys","Fashion Accessories","Gift & Lifestyle",],}; const SHOWS_GARMENT_MOCKUP = (type: ProductType) => type === "tshirt" || type === "panjabi"; interface ProductForm{product_type:ProductType;name:string;description:string;base_price:number;category:string;available_sizes:string[];design_front_url:string | null;design_back_url:string | null;has_back_design:boolean;print_position_x:number;print_position_y:number;print_size_width:number;print_size_height:number;selected_color_ids:string[];beauty_size:string;beauty_color:string;beauty_material:string;beauty_weight:string;beauty_stock:number;main_image_url:string | null;image_2_url:string | null;image_3_url:string | null;image_4_url:string | null;detail_image_url:string | null;is_active:boolean}const DEFAULT_FORM: ProductForm ={product_type:"tshirt",name: "",description: "Premium quality t-shirt crafted from 100% combed cotton. Soft, breathable fabric with a relaxed fit.",base_price: 650,category: "POD T-Shirt",available_sizes: DEFAULT_SIZES,design_front_url: null,design_back_url: null,has_back_design: false,print_position_x: 50,print_position_y: 40,print_size_width: 35,print_size_height: 35,selected_color_ids: [],beauty_size: "",beauty_color: "",beauty_material: "",beauty_weight: "",beauty_stock: 0,main_image_url: null,image_2_url: null,image_3_url: null,image_4_url: null,detail_image_url: null,is_active: true,}; export default function AdminPanel(){const [products,setProducts] = useState<PodProduct[]>([]);const [colors,setColors] = useState<PodColor[]>([]);const [selectedProductId,setSelectedProductId] = useState<string | null>(null);const [listFilter,setListFilter] = useState<"all" | ProductType>("all");const [view,setView] = useState<"products" | "orders">("products");const [loading,setLoading] = useState(true);const [uploading,setUploading] = useState(false);const [saving,setSaving] = useState(false);const [message,setMessage] = useState<{type:"success" | "error";text:string}| null>(null);const [form,setForm] = useState<ProductForm>(DEFAULT_FORM);const loadData = useCallback(async () => {setLoading(true); const {data: prods,error: productError} = await supabase .from("pod_products") .select("*") .order("created_at",{ascending: false,}); const {data: cols,error: colorError} = await supabase .from("pod_colors") .select("*") .eq("is_active",true) .order("sort_order"); if (!productError && prods) {setProducts(prods);} if (!colorError && cols) {setColors(cols);} setLoading(false);},[]);useEffect(() => {loadData();},[loadData]);const showMessage = (type: "success" | "error",text: string) =>{setMessage({type,text,});setTimeout(() => {setMessage(null);},3000)}const loadProduct = (p: PodProduct) =>{const product = p as any;const options = product.product_options ||{}const images = product.product_images ||{}setSelectedProductId(p.id);setForm({product_type: product.product_type || "tshirt",name: product.name || "",description: product.description || "",base_price: Number(product.base_price || 0),category: product.category || CATEGORY_OPTIONS[product.product_type || "tshirt"][0],available_sizes: product.available_sizes || [],design_front_url: product.design_front_url || null,design_back_url: product.design_back_url || null,has_back_design: Boolean(product.has_back_design),print_position_x: Number(product.print_position?.x ?? 50),print_position_y: Number(product.print_position?.y ?? 40),print_size_width: Number(product.print_size?.width ?? 35),print_size_height: Number(product.print_size?.height ?? 35),selected_color_ids: [],beauty_size: options.size || "",beauty_color: options.color || "",beauty_material: options.material || "",beauty_weight: options.weight || "",beauty_stock: Number(options.stock || 0),main_image_url: images.main || null,image_2_url: images.image2 || null,image_3_url: images.image3 || null,image_4_url: images.image4 || null,detail_image_url: images.detail || null,is_active: product.is_active !== false,});loadProductColors(p.id)}const loadProductColors = async (productId: string) =>{const{data}= await supabase .from("pod_product_colors") .select("color_id") .eq("product_id",productId);if (data){setForm((current) => ({...current,selected_color_ids: data.map((item: {color_id: string}) => item.color_id),}))}}const uploadDesign = async (file: File,side: "front" | "back") =>{setUploading(true);const ext = file.name.split(".").pop() || "png";const fileName = `design-${Date.now()}-${side}.${ext}`;const{error}= await supabase.storage .from("pod-designs") .upload(fileName,file);if (error){showMessage("error",`Upload failed: ${error.message}`);setUploading(false);return}const{data:urlData}= supabase.storage .from("pod-designs") .getPublicUrl(fileName);if (side === "front"){setForm((current) => ({...current,design_front_url: urlData.publicUrl,}))}else{setForm((current) => ({...current,design_back_url: urlData.publicUrl,has_back_design: true,}))}setUploading(false);showMessage("success","Design uploaded successfully")}const uploadBeautyImage = async (file: File,field: "main" | "image2" | "image3" | "image4" | "detail") =>{setUploading(true);const ext = file.name.split(".").pop() || "jpg";const fileName = `beauty-${Date.now()}-${field}.${ext}`;const{error}= await supabase.storage .from("pod-designs") .upload(fileName,file);if (error){showMessage("error",`Image upload failed: ${error.message}`);setUploading(false);return}const{data}= supabase.storage .from("pod-designs") .getPublicUrl(fileName);const url = data.publicUrl;setForm((current) => {if (field === "main") {return {...current,main_image_url: url,};} if (field === "image2") {return {...current,image_2_url: url,};} if (field === "image3") {return {...current,image_3_url: url,};} if (field === "image4") {return {...current,image_4_url: url,};} return {...current,detail_image_url: url,};});setUploading(false);showMessage("success",`${field === "main" ? "Main" : "Product"} image uploaded`)}const handleSave = async () =>{if (!form.name.trim()){showMessage("error","Please enter Product Name");return}setSaving(true);const productOptions = form.product_type === "beauty" ?{size:form.beauty_size.trim() || null,color: form.beauty_color.trim() || null,material: form.beauty_material.trim() || null,weight: form.beauty_weight.trim() || null,stock: Number(form.beauty_stock || 0),}const productImages = form.product_type === "beauty" ?{main:form.main_image_url || null,image2: form.image_2_url || null,image3: form.image_3_url || null,image4: form.image_4_url || null,detail: form.detail_image_url || null,}: null;const payload ={product_type: form.product_type,name: form.name.trim(),description: form.description,base_price: Number(form.base_price || 0),category: form.category,available_sizes: form.product_type === "beauty" ? [] : form.available_sizes,product_options: productOptions,product_images: productImages,design_front_url: form.design_front_url,design_back_url: form.design_back_url,has_back_design: form.has_back_design,print_position:{x:form.print_position_x,y: form.print_position_y,},print_size:{width:form.print_size_width,height: form.print_size_height,},is_active: form.is_active,}if (selectedProductId){const{data,error}= await supabase .from("pod_products") .update(payload) .eq("id",selectedProductId) .select();if (error){showMessage("error",error.message);setSaving(false);return}if (!data || data.length === 0){showMessage("error","Update blocked (0 rows changed) — likely a Supabase RLS policy issue on pod_products.");setSaving(false);return}await syncProductColors(selectedProductId)}else{const{data,error}= await supabase .from("pod_products") .insert(payload) .select() .single();if (error){showMessage("error",error.message);setSaving(false);return}if (data){setSelectedProductId(data.id);await syncProductColors(data.id)}}setSaving(false);showMessage("success","Product saved successfully");await loadData()}const syncProductColors = async (productId: string) =>{await supabase .from("pod_product_colors") .delete() .eq("product_id",productId);if (form.selected_color_ids.length === 0){return}const rows = form.selected_color_ids.map((colorId) => ({product_id: productId,color_id: colorId,}));await supabase.from("pod_product_colors").insert(rows)}const deleteProduct = async (id: string) =>{const confirmed = window.confirm("Are you sure you want to delete this product?");if (!confirmed){return}const{error}= await supabase.from("pod_products").delete().eq("id",id);if (error){showMessage("error",error.message);return}if (selectedProductId === id){resetForm("tshirt")}await loadData();showMessage("success","Product deleted")}const resetForm = (type: ProductType = "tshirt") =>{const formData: ProductForm ={...DEFAULT_FORM,product_type: type,name: "",description: type === "tshirt" ? "Premium quality t-shirt crafted from 100% combed cotton. Soft, breathable fabric with a relaxed fit." : type === "panjabi" ? "Hand painted premium panjabi, crafted with care and attention to detail." : "Premium quality beauty accessory crafted for your everyday lifestyle.",base_price: type === "tshirt" ? 650 : type === "panjabi" ? 1000 : 500,category: CATEGORY_OPTIONS[type][0],available_sizes: type === "beauty" ? [] : DEFAULT_SIZES,}setForm(formData);setSelectedProductId(null)}const changeProductType = (newType: ProductType) =>{setForm((current) => ({...current,product_type: newType,category: CATEGORY_OPTIONS[newType][0],available_sizes: newType === "beauty" ? [] : DEFAULT_SIZES,description: newType === "tshirt" ? "Premium quality t-shirt crafted from 100% combed cotton. Soft, breathable fabric with a relaxed fit." : newType === "panjabi" ? "Hand painted premium panjabi, crafted with care and attention to detail." : "Premium quality beauty accessory crafted for your everyday lifestyle.",}))}const toggleColor = (colorId: string) =>{setForm((current) => ({...current,selected_color_ids: current.selected_color_ids.includes(colorId) ? current.selected_color_ids.filter((id) => id !== colorId) : [...current.selected_color_ids,colorId],}))}const toggleSize = (size: string) =>{setForm((current) => ({...current,available_sizes: current.available_sizes.includes(size) ? current.available_sizes.filter((s) => s !== size) : [...current.available_sizes,size],}))}const previewColor: PodColor = colors[0] ||{id:"preview",name: "Black",hex: "#1a1a1a",is_active: true,sort_order: 0,}const filteredProducts = listFilter === "all" ? products : products.filter((product) => ((product as any).product_type || "tshirt") === listFilter);return (<div className="admin-panel"> {} <div className="admin-header"> <div> <h1 className="admin-title"> <Settings size={24} /> Admin Panel </h1> <p className="admin-subtitle"> Manage T-Shirt,Panjabi,and Beauty Accessories products </p> </div> <div style={{display: "flex",gap: 10,flexWrap: "wrap",}} > <button className={`filter-chip ${view === "products" ? "active" : ""}`} onClick={() => setView("products")} > Products </button> <button className={`filter-chip ${view === "orders" ? "active" : ""}`} onClick={() => setView("orders")} > Orders </button> {view === "products" && (<button className="btn btn-primary" onClick={() => resetForm("tshirt")} > <Plus size={18} /> New Product </button>)} </div> </div> {} {message && (<div className={`admin-message ${message.type}`}> {message.type === "success" ? (<Check size={18} />) : (<AlertCircle size={18} />)} {message.text} </div>)} {} {view === "orders" ? (<div className="admin-body" style={{display: "block",}} > <OrderManager /> </div>) : (<div className="admin-body"> {} <div className="admin-sidebar"> <h3 className="admin-sidebar-title"> <Package size={18} /> Products ({filteredProducts.length}) </h3> {} <div style={{display: "flex",gap: 6,flexWrap: "wrap",marginBottom: 12,}} > {(["all","tshirt","panjabi","beauty"] as const).map((type) => (<button key={type} onClick={() => setListFilter(type)} className={`filter-chip ${listFilter === type ? "active" : ""}`} style={{fontSize: 12,padding: "4px 10px",}} > {type === "all" ? "All" : PRODUCT_TYPES.find((item) => item.value === type)?.label} </button>))} </div> {} <div className="admin-product-list"> {loading && <p className="admin-loading">Loading...</p>} {!loading && filteredProducts.length === 0 && (<p className="admin-empty">No products yet. Create one!</p>)} {filteredProducts.map((product) => (<button key={product.id} className={`admin-product-item ${selectedProductId === product.id ? "active" : ""}`} onClick={() => loadProduct(product)} style={{display: "flex",flexDirection: "column",alignItems: "flex-start",gap: 4,width: "100%",textAlign: "left",}} > <span className="admin-product-name" style={{display: "block",width: "100%"}} > {product.name || "Untitled Product"} </span> <span className="admin-product-cat" style={{display: "block",width: "100%"}} > {PRODUCT_TYPES.find((item) => item.value === ((product as any).product_type || "tshirt"))?.label} {" · "} {product.category} {" · ₹"} {product.base_price} </span> </button>))} </div> {} <h3 className="admin-sidebar-title" style={{marginTop: 24,}} > <Palette size={18} /> Color Options ({colors.length}) </h3> <ColorManager colors={colors} onRefresh={loadData} /> </div> {} <div className="admin-editor"> <div className="admin-editor-grid"> {} <div className="admin-preview-section"> <h3 className="admin-section-title"> <Eye size={18} /> Live Preview </h3> {SHOWS_GARMENT_MOCKUP(form.product_type) ? (<> <div className="admin-preview-wrap"> <TShirtMockup color={previewColor} designUrl={form.design_front_url} backDesignUrl={form.design_back_url} printPosition={{x: form.print_position_x,y: form.print_position_y,}} printSize={{width: form.print_size_width,height: form.print_size_height,}} view="front" hasBackDesign={form.has_back_design} size="lg" /> </div> <div className="admin-preview-colors"> {colors.slice(0,6).map((color) => (<button key={color.id} className="admin-preview-color-btn" style={{background: color.hex,}} title={color.name} />))} </div> </>) : (<div className="admin-hint" style={{padding: 20,}} > <strong>👜 Beauty & Accessories</strong> <br /> এখানে garment mockup নেই। <br /> নিচে সরাসরি product photos upload করুন। </div>)} </div> {} <div className="admin-form-section"> <h3 className="admin-section-title">Product Details</h3> {} <div className="admin-form-group"> <label>Product Type</label> <select className="form-input" value={form.product_type} onChange={(event) => changeProductType(event.target.value as ProductType)} > {PRODUCT_TYPES.map((type) => (<option key={type.value} value={type.value}> {type.label} </option>))} </select> </div> {} <div className="admin-form-group"> <label>Product Name</label> <input className="form-input" value={form.name} onChange={(event) => setForm((current) => ({...current,name: event.target.value,}))} placeholder="Enter product name" /> </div> {} <div className="admin-form-row"> <div className="admin-form-group"> <label>Price (₹)</label> <input type="number" min="0" className="form-input" value={form.base_price} onChange={(event) => setForm((current) => ({...current,base_price: Number(event.target.value),}))} /> </div> <div className="admin-form-group"> <label>Category</label> <select className="form-input" value={form.category} onChange={(event) => setForm((current) => ({...current,category: event.target.value,}))} > {CATEGORY_OPTIONS[form.product_type].map((category) => (<option key={category} value={category}> {category} </option>))} </select> </div> </div> {} <div className="admin-form-group"> <label>Description</label> <textarea className="form-input admin-textarea" value={form.description} onChange={(event) => setForm((current) => ({...current,description: event.target.value,}))} rows={4} /> </div> {} {form.product_type === "beauty" && (<> <h3 className="admin-section-title" style={{marginTop: 24,}} > 👜 Beauty & Accessories </h3> <p className="admin-hint"> Junk Jewellery,Hand Bags,Dolls & Soft Toys,Fashion Accessories এবং Gift & Lifestyle products এখান থেকে manage করুন। </p> {} <h3 className="admin-section-title" style={{marginTop: 20,}} > Product Options </h3> <div className="admin-form-row"> <div className="admin-form-group"> <label>Size — Optional</label> <input className="form-input" value={form.beauty_size} onChange={(event) => setForm((current) => ({...current,beauty_size: event.target.value,}))} placeholder="e.g. Medium" /> </div> <div className="admin-form-group"> <label>Color — Optional</label> <input className="form-input" value={form.beauty_color} onChange={(event) => setForm((current) => ({...current,beauty_color: event.target.value,}))} placeholder="e.g. Black" /> </div> </div> <div className="admin-form-row"> <div className="admin-form-group"> <label>Material — Optional</label> <input className="form-input" value={form.beauty_material} onChange={(event) => setForm((current) => ({...current,beauty_material: event.target.value,}))} placeholder="e.g. PU Leather" /> </div> <div className="admin-form-group"> <label>Weight — Optional</label> <input className="form-input" value={form.beauty_weight} onChange={(event) => setForm((current) => ({...current,beauty_weight: event.target.value,}))} placeholder="e.g. 450g" /> </div> </div> <div className="admin-form-group"> <label>Stock — Optional</label> <input type="number" min="0" className="form-input" value={form.beauty_stock} onChange={(event) => setForm((current) => ({...current,beauty_stock: Number(event.target.value),}))} placeholder="e.g. 10" /> </div> {} <div className="admin-form-group"> <label>Product Status</label> <select className="form-input" value={form.is_active ? "active" : "inactive"} onChange={(event) => setForm((current) => ({...current,is_active: event.target.value === "active",}))} > <option value="active">Active</option> <option value="inactive">Inactive</option> </select> </div> {} <h3 className="admin-section-title" style={{marginTop: 24,}} > 📸 Product Images </h3> <p className="admin-hint"> Main Image অবশ্যই দিন। অন্য ছবিগুলো optional। </p> <BeautyImageBox label="Main Image" value={form.main_image_url} uploading={uploading} onUpload={(file) => uploadBeautyImage(file,"main")} onRemove={() => setForm((current) => ({...current,main_image_url: null,}))} /> <BeautyImageBox label="Image 2" value={form.image_2_url} uploading={uploading} onUpload={(file) => uploadBeautyImage(file,"image2")} onRemove={() => setForm((current) => ({...current,image_2_url: null,}))} /> <BeautyImageBox label="Image 3" value={form.image_3_url} uploading={uploading} onUpload={(file) => uploadBeautyImage(file,"image3")} onRemove={() => setForm((current) => ({...current,image_3_url: null,}))} /> <BeautyImageBox label="Image 4" value={form.image_4_url} uploading={uploading} onUpload={(file) => uploadBeautyImage(file,"image4")} onRemove={() => setForm((current) => ({...current,image_4_url: null,}))} /> <BeautyImageBox label="Detail Image" value={form.detail_image_url} uploading={uploading} onUpload={(file) => uploadBeautyImage(file,"detail")} onRemove={() => setForm((current) => ({...current,detail_image_url: null,}))} /> </>)} {} {SHOWS_GARMENT_MOCKUP(form.product_type) && (<> <h3 className="admin-section-title" style={{marginTop: 24,}} > <Upload size={18} /> Design Upload </h3> <p className="admin-hint"> Upload transparent PNG artwork. </p> <div className="admin-upload-row"> {} <div className="admin-upload-box"> <label className="admin-upload-label"> <input type="file" accept="image/png,image/jpeg,image/webp" hidden onChange={(event) => {const file = event.target.files?.[0]; if (file) {uploadDesign(file,"front");}}} /> <Upload size={24} /> <span> {uploading ? "Uploading..." : "Upload Front Design"} </span> </label> {form.design_front_url && (<div className="admin-upload-preview"> <img src={form.design_front_url} alt="Front design" /> <button type="button" onClick={() => setForm((current) => ({...current,design_front_url: null,}))} > <X size={14} /> </button> </div>)} </div> {} <div className="admin-upload-box"> <label className="admin-upload-label"> <input type="file" accept="image/png,image/jpeg,image/webp" hidden onChange={(event) => {const file = event.target.files?.[0]; if (file) {uploadDesign(file,"back");}}} /> <Upload size={24} /> <span> {uploading ? "Uploading..." : "Upload Back Design"} </span> </label> {form.design_back_url && (<div className="admin-upload-preview"> <img src={form.design_back_url} alt="Back design" /> <button type="button" onClick={() => setForm((current) => ({...current,design_back_url: null,has_back_design: false,}))} > <X size={14} /> </button> </div>)} </div> </div> {} <h3 className="admin-section-title" style={{marginTop: 24,}} > Print Settings </h3> <div className="admin-form-row"> <RangeField label="Print Position X (%)" value={form.print_position_x} min={10} max={90} onChange={(value) => setForm((current) => ({...current,print_position_x: value,}))} /> <RangeField label="Print Position Y (%)" value={form.print_position_y} min={15} max={75} onChange={(value) => setForm((current) => ({...current,print_position_y: value,}))} /> </div> <div className="admin-form-row"> <RangeField label="Print Width (%)" value={form.print_size_width} min={10} max={70} onChange={(value) => setForm((current) => ({...current,print_size_width: value,}))} /> <RangeField label="Print Height (%)" value={form.print_size_height} min={10} max={70} onChange={(value) => setForm((current) => ({...current,print_size_height: value,}))} /> </div> {} <h3 className="admin-section-title" style={{marginTop: 24,}} > Available Sizes </h3> <div className="admin-sizes"> {["XS","S","M","L","XL","XXL","XXXL"].map((size) => (<button key={size} type="button" className={`admin-size-btn ${form.available_sizes.includes(size) ? "active" : ""}`} onClick={() => toggleSize(size)} > {size} </button>))} </div> {} <h3 className="admin-section-title" style={{marginTop: 24,}} > Available Colors </h3> <div className="admin-color-grid"> {colors.map((color) => (<button key={color.id} type="button" className={`admin-color-chip ${form.selected_color_ids.includes(color.id) ? "active" : ""}`} onClick={() => toggleColor(color.id)} > <span className="admin-color-swatch" style={{background: color.hex,}} /> <span className="admin-color-name">{color.name}</span> {form.selected_color_ids.includes(color.id) && (<Check size={14} className="admin-color-check" />)} </button>))} </div> {} {selectedProductId && (<> <h3 className="admin-section-title" style={{marginTop: 24,}} > Product Images (Per Color) </h3> <p className="admin-hint"> প্রতিটি selected color-এর Front,Back,Close-up এবং Detail image manage করুন। </p> <ProductImageManager productId={selectedProductId} colors={colors.filter((color) => form.selected_color_ids.includes(color.id))} /> </>)} </>)} {} <div className="admin-actions" style={{marginTop: 30,}} > <button className="btn btn-primary" onClick={handleSave} disabled={saving} > <Save size={18} /> {saving ? "Saving..." : "Save Product"} </button> {selectedProductId && (<button className="btn btn-danger" onClick={() => deleteProduct(selectedProductId)} > <Trash2 size={18} /> Delete </button>)} </div> </div> </div> </div> </div>)} </div>)}function BeautyImageBox({label,value,uploading,onUpload,onRemove,}: {label: string; value: string | null; uploading: boolean; onUpload: (file: File) => void; onRemove: () => void;}){return (<div className="admin-upload-box" style={{marginBottom: 14,}} > <label className="admin-upload-label"> <input type="file" accept="image/png,image/jpeg,image/webp" hidden onChange={(event) => {const file = event.target.files?.[0]; if (file) {onUpload(file);} event.currentTarget.value = "";}} /> <Upload size={22} /> <span>{uploading ? "Uploading..." : `Upload ${label}`}</span> </label> {value && (<div className="admin-upload-preview"> <img src={value} alt={label} /> <button type="button" onClick={onRemove}> <X size={14} /> </button> </div>)} </div>)}function RangeField({label,value,min,max,onChange,}: {label: string; value: number; min: number; max: number; onChange: (value: number) => void;}){return (<div className="admin-form-group"> <label>{label}</label> <input type="range" min={min} max={max} value={value} onChange={(event) => onChange(Number(event.target.value))} /> <span className="admin-range-val">{value}%</span> </div>)}function ColorManager({colors,onRefresh,}: {colors: PodColor[]; onRefresh: () => void;}){const [newName,setNewName] = useState("");const [newHex,setNewHex] = useState("#000000");const [adding,setAdding] = useState(false);const addColor = async () =>{if (!newName.trim() || !newHex){return}setAdding(true);const{error}= await supabase.from("pod_colors").insert({name: newName.trim(),hex: newHex,is_active: true,sort_order: colors.length + 1,});if (error){alert(error.message)}setNewName("");setNewHex("#000000");setAdding(false);onRefresh()}const toggleColor = async (color: PodColor) =>{await supabase .from("pod_colors") .update({is_active: !color.is_active,}) .eq("id",color.id);onRefresh()}const deleteColor = async (id: string) =>{const confirmed = window.confirm("Delete this color?");if (!confirmed){return}await supabase.from("pod_colors").delete().eq("id",id);onRefresh()}return (<div className="color-manager"> <div className="color-manager-add"> <input className="form-input color-manager-name" placeholder="Color name" value={newName} onChange={(event) => setNewName(event.target.value)} /> <input type="color" className="color-manager-picker" value={newHex} onChange={(event) => setNewHex(event.target.value)} /> <button className="btn btn-primary btn-sm" onClick={addColor} disabled={adding || !newName.trim()} > <Plus size={16} /> </button> </div> <div className="color-manager-list"> {colors.map((color) => (<div key={color.id} className={`color-manager-item ${!color.is_active ? "inactive" : ""}`} > <span className="color-manager-swatch" style={{background: color.hex,}} /> <span className="color-manager-label">{color.name}</span> <button onClick={() => toggleColor(color)} className="color-manager-toggle" title={color.is_active ? "Disable" : "Enable"} > {color.is_active ? <Check size={14} /> : <X size={14} />} </button> <button onClick={() => deleteColor(color.id)} className="color-manager-delete" title="Delete" > <Trash2 size={14} /> </button> </div>))} </div> </div>)}:root{--font-body: "Inter", system-ui, sans-serif;--font-display: "Playfair Display", Georgia, serif;--bg: #0a0a0b;--bg-elev: #131315;--bg-elev-2: #1c1c1f;--border: #2a2a2e;--border-soft: #1f1f23;--text: #f5f5f4;--text-muted: #a1a1aa;--text-dim: #71717a;--primary: #d4a574;--primary-dark: #b8895a;--primary-soft: rgba(212, 165, 116, .12);--accent: #4ade80;--success: #22c55e;--warning: #f59e0b;--error: #ef4444;--radius: 14px;--radius-sm: 8px;--radius-lg: 22px;--shadow-sm: 0 1px 2px rgba(0,0,0,.4);--shadow: 0 8px 24px rgba(0,0,0,.4);--shadow-lg: 0 24px 60px rgba(0,0,0,.5);--transition: .28s cubic-bezier(.4, 0, .2, 1);--transition-fast: .16s cubic-bezier(.4, 0, .2, 1)}*{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth}body{font-family:var(--font-body);background:var(--bg);color:var(--text);line-height:1.5;-webkit-font-smoothing:antialiased;overflow-x:hidden}a{color:inherit;text-decoration:none}button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}img{display:block;max-width:100%}ul{list-style:none}.container{max-width:1320px;margin:0 auto;padding:0 24px}@media (max-width: 768px){.container{padding:0 16px}}::selection{background:var(--primary);color:#0a0a0b}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:var(--border);border-radius:10px}::-webkit-scrollbar-thumb:hover{background:#3a3a40}@keyframes fadeInUp{0%{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes scaleIn{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes shimmer{0%{background-position:-1000px 0}to{background-position:1000px 0}}@keyframes float{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}.fade-up{animation:fadeInUp .7s var(--transition) both}.fade-in{animation:fadeIn .5s ease both}.header{position:fixed;top:0;left:0;right:0;z-index:100;padding:18px 0;background:transparent;transition:background var(--transition),padding var(--transition),border-color var(--transition);border-bottom:1px solid transparent}.header.scrolled{background:#0a0a0bd9;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);padding:12px 0;border-bottom-color:var(--border-soft)}.header-inner{display:flex;align-items:center;justify-content:space-between;gap:32px}.logo{display:flex;align-items:baseline;gap:8px;font-family:var(--font-display);font-weight:800;letter-spacing:.02em}.logo-mark{font-size:28px;color:var(--primary)}.logo-text{font-size:18px;letter-spacing:.3em;color:var(--text)}.header-nav{display:flex;gap:28px}.header-link{font-size:14px;font-weight:500;color:var(--text-muted);position:relative;padding:4px 0;transition:color var(--transition-fast)}.header-link:after{content:"";position:absolute;left:0;bottom:0;width:0;height:1px;background:var(--primary);transition:width var(--transition)}.header-link:hover{color:var(--text)}.header-link:hover:after{width:100%}.header-link.sale{color:var(--error);font-weight:600}.header-link.active{color:var(--primary)}.header-link.active:after{width:100%;background:var(--primary)}.header-actions{display:flex;gap:6px;align-items:center}.icon-btn{position:relative;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:50%;color:var(--text-muted);transition:background var(--transition-fast),color var(--transition-fast)}.icon-btn:hover{background:var(--bg-elev);color:var(--text)}.cart-count{position:absolute;top:4px;right:4px;background:var(--primary);color:#0a0a0b;font-size:10px;font-weight:700;min-width:16px;height:16px;border-radius:8px;display:flex;align-items:center;justify-content:center;padding:0 4px}.header-mobile-toggle{display:none;width:40px;height:40px;align-items:center;justify-content:center;color:var(--text)}@media (max-width: 880px){.header-mobile-toggle{display:flex}.header-nav{position:fixed;top:64px;left:0;right:0;background:var(--bg-elev);flex-direction:column;padding:24px;gap:16px;border-bottom:1px solid var(--border);transform:translateY(-120%);transition:transform var(--transition)}.header-nav.open{transform:translateY(0)}.logo-text{display:none}}.search-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:300;background:#000000b3;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);display:flex;align-items:flex-start;justify-content:center;padding:100px 24px 24px;animation:fadeIn .2s ease both}.search-panel{width:100%;max-width:560px;background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);padding:16px;animation:scaleIn .25s ease both}.search-input-row{display:flex;align-items:center;gap:12px;padding:10px 14px;background:var(--bg);border:1px solid var(--border-soft);border-radius:var(--radius);color:var(--text-muted)}.search-input{flex:1;background:transparent;border:none;outline:none;color:var(--text);font-size:15px;font-family:inherit}.search-input::placeholder{color:var(--text-dim)}.search-results{margin-top:14px;display:flex;flex-direction:column;gap:6px;max-height:400px;overflow-y:auto}.search-result-item{display:flex;align-items:center;gap:12px;padding:8px;border-radius:var(--radius-sm);text-align:left;transition:background var(--transition-fast);width:100%}.search-result-item:hover{background:var(--bg-elev-2)}.search-result-image{width:48px;height:60px;object-fit:cover;border-radius:var(--radius-sm);background:var(--bg-elev-2);flex-shrink:0}.search-result-info{display:flex;flex-direction:column;gap:2px}.search-result-name{font-size:14px;font-weight:600;color:var(--text)}.search-result-price{font-size:13px;color:var(--text-muted)}.search-result-meta{font-size:12px;color:var(--text-dim);text-transform:capitalize}.hero{position:relative;height:100vh;min-height:640px;overflow:hidden;background:var(--bg-elev)}.hero-track{position:absolute;top:0;right:0;bottom:0;left:0}.hero-slide{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .9s cubic-bezier(.4,0,.2,1)}.hero-slide.active{opacity:1}.hero-image-wrap{position:relative;width:100%;height:100%;overflow:hidden}.hero-image{width:100%;height:100%;object-fit:cover;transform:scale(1.08);transition:transform 8s ease-out}.hero-slide.active .hero-image{transform:scale(1)}.hero-overlay{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(180deg,#0a0a0b73,#0a0a0b40 40%,#0a0a0bbf)}.hero-content{position:relative;z-index:2;height:100%;display:flex;align-items:center}.hero-text{position:relative;display:flex;max-width:620px;min-height:280px}.hero-copy{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;gap:18px;opacity:0;transition:opacity .7s cubic-bezier(.4,0,.2,1);pointer-events:none}.hero-copy.show{opacity:1;pointer-events:auto}.hero-badge{display:inline-flex;align-self:flex-start;align-items:center;gap:6px;padding:6px 14px;background:var(--primary-soft);border:1px solid rgba(212,165,116,.3);color:var(--primary);font-size:12px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;border-radius:100px}.hero-title{font-family:var(--font-display);font-size:clamp(40px,6vw,76px);font-weight:700;line-height:1.05;letter-spacing:-.02em;color:#fff}.hero-subtitle{font-size:18px;line-height:1.6;color:#ffffffd1;max-width:480px}.hero-actions{display:flex;gap:14px;margin-top:8px;flex-wrap:wrap}.btn{display:inline-flex;align-items:center;gap:8px;padding:14px 28px;font-size:14px;font-weight:600;letter-spacing:.02em;border-radius:100px;transition:all var(--transition);white-space:nowrap}.btn-primary{background:var(--primary);color:#0a0a0b}.btn-primary:hover{background:var(--primary-dark);transform:translateY(-2px);box-shadow:0 12px 32px #d4a57459}.btn-ghost{background:#ffffff14;color:#fff;border:1px solid rgba(255,255,255,.2);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.btn-ghost:hover{background:#ffffff26;border-color:#fff6}.hero-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:3;width:48px;height:48px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:#ffffff1a;border:1px solid rgba(255,255,255,.15);color:#fff;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all var(--transition)}.hero-nav:hover{background:#fff3;transform:translateY(-50%) scale(1.08)}.hero-nav-prev{left:32px}.hero-nav-next{right:32px}@media (max-width: 768px){.hero-nav{display:none}}.hero-dots{position:absolute;bottom:48px;left:50%;transform:translate(-50%);z-index:3;display:flex;gap:10px}.hero-dot{width:10px;height:10px;border-radius:50%;background:#ffffff4d;transition:all var(--transition)}.hero-dot.active{width:32px;border-radius:5px;background:var(--primary)}.hero-progress{position:absolute;bottom:0;left:0;right:0;height:3px;background:#ffffff1a;z-index:3}.hero-progress-bar{height:100%;background:var(--primary);transition:width .6s linear}.features-section{padding:56px 0;border-bottom:1px solid var(--border-soft)}.features-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:24px}.feature-card{display:flex;align-items:center;gap:16px;padding:20px;border-radius:var(--radius);background:var(--bg-elev);border:1px solid var(--border-soft);transition:all var(--transition)}.feature-card:hover{border-color:var(--border);transform:translateY(-2px)}.feature-icon{flex-shrink:0;width:48px;height:48px;display:flex;align-items:center;justify-content:center;border-radius:12px;background:var(--primary-soft);color:var(--primary)}.feature-title{font-size:15px;font-weight:600;margin-bottom:2px}.feature-desc{font-size:13px;color:var(--text-dim)}@media (max-width: 880px){.features-grid{grid-template-columns:repeat(2,1fr)}}@media (max-width: 480px){.features-grid{grid-template-columns:1fr}}.section-head{display:flex;align-items:flex-end;justify-content:space-between;margin-bottom:36px;gap:20px}.eyebrow{display:block;font-size:12px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--primary);margin-bottom:8px}.eyebrow-light{color:#d4a574e6}.section-title{font-family:var(--font-display);font-size:clamp(28px,4vw,44px);font-weight:700;letter-spacing:-.02em}.section-link{font-size:14px;font-weight:600;color:var(--text-muted);transition:color var(--transition-fast)}.section-link:hover{color:var(--primary)}.category-banner{padding:140px 0 48px;text-align:center;border-bottom:1px solid var(--border-soft)}.category-banner-title{font-family:var(--font-display);font-size:clamp(32px,5vw,52px);font-weight:700;margin:12px 0 10px}.category-banner-subtitle{color:var(--text-muted);font-size:16px;max-width:560px;margin:0 auto}@media (max-width: 640px){.category-banner{padding:110px 0 36px}}.categories-section{padding:80px 0}.category-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}.category-card{position:relative;aspect-ratio:3/4;border-radius:var(--radius);overflow:hidden;display:block}.category-image{width:100%;height:100%;object-fit:cover;transition:transform .7s ease}.category-card:hover .category-image{transform:scale(1.08)}.category-overlay{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(180deg,transparent 40%,rgba(10,10,11,.85) 100%)}.category-info{position:absolute;bottom:0;left:0;right:0;padding:20px;display:flex;align-items:flex-end;justify-content:space-between;z-index:2}.category-name{font-family:var(--font-display);font-size:22px;font-weight:700;color:#fff}.category-count{font-size:13px;color:#ffffffb3}.category-arrow{width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:#ffffff26;color:#fff;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:all var(--transition)}.category-card:hover .category-arrow{background:var(--primary);color:#0a0a0b;transform:rotate(0) scale(1.1)}@media (max-width: 880px){.category-grid{grid-template-columns:repeat(2,1fr)}}.category-grid-3{grid-template-columns:repeat(3,1fr)}.category-image-placeholder{width:100%;height:100%;background:linear-gradient(135deg,var(--bg-elev-2),var(--bg-elev))}@media (max-width: 880px){.category-grid-3{grid-template-columns:1fr}}.products-section{padding:80px 0;background:var(--bg-elev);border-top:1px solid var(--border-soft);border-bottom:1px solid var(--border-soft)}.product-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:24px}.product-card{background:var(--bg);border-radius:var(--radius);overflow:hidden;border:1px solid var(--border-soft);transition:all var(--transition)}.product-card:hover{border-color:var(--border);transform:translateY(-4px);box-shadow:var(--shadow)}.product-image-wrap{position:relative;aspect-ratio:3/4;overflow:hidden;background:var(--bg-elev-2)}.product-image{width:100%;height:100%;object-fit:cover;transition:transform .7s ease}.product-card:hover .product-image{transform:scale(1.06)}.product-tag{position:absolute;top:12px;left:12px;padding:4px 10px;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;border-radius:6px;z-index:2}.tag-sale{background:var(--error);color:#fff}.tag-new{background:var(--accent);color:#0a0a0b}.tag-bestseller{background:var(--primary);color:#0a0a0b}.tag-premium{background:#fff;color:#0a0a0b}.product-wishlist{position:absolute;top:12px;right:12px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:#ffffffe6;color:#0a0a0b;z-index:2;opacity:0;transform:translateY(-8px);transition:all var(--transition)}.product-card:hover .product-wishlist{opacity:1;transform:translateY(0)}.product-wishlist:hover{background:#fff;color:var(--error)}.product-quick-add{position:absolute;bottom:12px;left:12px;right:12px;display:flex;align-items:center;justify-content:center;gap:8px;padding:12px;border-radius:var(--radius-sm);background:#0a0a0be6;color:#fff;font-size:13px;font-weight:600;z-index:2;opacity:0;transform:translateY(12px);transition:all var(--transition);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.product-card:hover .product-quick-add{opacity:1;transform:translateY(0)}.product-quick-add:hover{background:var(--primary);color:#0a0a0b}.product-action-row{position:absolute;bottom:12px;left:12px;right:12px;display:flex;gap:8px;z-index:2;opacity:0;transform:translateY(12px);transition:all var(--transition)}.product-card:hover .product-action-row{opacity:1;transform:translateY(0)}.product-action-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:10px 8px;border-radius:var(--radius-sm);font-size:12px;font-weight:600;border:none;cursor:pointer;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:all var(--transition)}.product-action-btn.add-cart{background:#0a0a0be6;color:#fff}.product-action-btn.add-cart:hover{background:var(--primary);color:#0a0a0b}.product-action-btn.order-now{background:var(--accent);color:#0a0a0b}.product-action-btn.order-now:hover{filter:brightness(1.08)}.product-info{padding:16px}.product-category{font-size:11px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--text-dim);margin-bottom:4px}.product-name{font-size:15px;font-weight:600;margin-bottom:8px}.product-rating{display:flex;align-items:center;gap:4px;font-size:13px;color:var(--text-muted);margin-bottom:12px}.star{fill:var(--primary);color:var(--primary)}.product-reviews{color:var(--text-dim)}.product-bottom{display:flex;align-items:center;justify-content:space-between}.product-price{display:flex;align-items:baseline;gap:8px}.price-now{font-size:17px;font-weight:700;color:var(--text)}.price-was{font-size:14px;color:var(--text-dim);text-decoration:line-through}.product-colors{display:flex;gap:5px}.color-dot{width:16px;height:16px;border-radius:50%;border:1px solid rgba(255,255,255,.15);padding:0;cursor:pointer;box-sizing:border-box;transition:transform .15s ease,box-shadow .15s ease}.color-dot:hover{transform:scale(1.15)}.color-dot.active{box-shadow:0 0 0 2px var(--bg, #0a0a0a),0 0 0 4px currentColor;transform:scale(1.1)}@media (max-width: 1080px){.product-grid{grid-template-columns:repeat(3,1fr)}}@media (max-width: 880px){.product-grid{grid-template-columns:repeat(2,1fr)}}@media (max-width: 480px){.product-grid{grid-template-columns:1fr}}.newsletter-section{padding:80px 0}.newsletter-card{display:flex;align-items:center;justify-content:space-between;gap:48px;padding:56px;border-radius:var(--radius-lg);background:linear-gradient(135deg,var(--bg-elev) 0%,var(--bg-elev-2) 100%);border:1px solid var(--border);position:relative;overflow:hidden}.newsletter-card:before{content:"";position:absolute;top:-50%;right:-10%;width:400px;height:400px;background:radial-gradient(circle,var(--primary-soft) 0%,transparent 70%);border-radius:50%}.newsletter-content{position:relative;z-index:2;max-width:480px}.newsletter-title{font-family:var(--font-display);font-size:clamp(28px,4vw,40px);font-weight:700;margin:8px 0 12px;letter-spacing:-.02em}.newsletter-text{font-size:16px;color:var(--text-muted);line-height:1.6}.newsletter-form{position:relative;z-index:2;display:flex;gap:10px;min-width:380px}.newsletter-input{flex:1;padding:14px 20px;background:var(--bg);border:1px solid var(--border);border-radius:100px;color:var(--text);font-size:14px;font-family:inherit;outline:none;transition:border-color var(--transition)}.newsletter-input:focus{border-color:var(--primary)}.newsletter-input::placeholder{color:var(--text-dim)}@media (max-width: 880px){.newsletter-card{flex-direction:column;padding:36px;gap:28px}.newsletter-form{min-width:unset;width:100%}}.footer{padding:64px 0 32px;border-top:1px solid var(--border-soft);background:var(--bg-elev)}.footer-top{display:flex;justify-content:space-between;gap:64px;margin-bottom:48px}.footer-brand{max-width:320px}.footer-tagline{margin:16px 0 20px;font-size:14px;color:var(--text-muted);line-height:1.6}.footer-socials{display:flex;gap:10px}.footer-socials a{width:38px;height:38px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--bg-elev-2);border:1px solid var(--border-soft);color:var(--text-muted);transition:all var(--transition)}.footer-socials a:hover{background:var(--primary);color:#0a0a0b;border-color:var(--primary);transform:translateY(-2px)}.footer-cols{display:grid;grid-template-columns:repeat(3,1fr);gap:48px}.footer-col-title{font-size:14px;font-weight:600;margin-bottom:16px;letter-spacing:.02em}.footer-col ul{display:flex;flex-direction:column;gap:10px}.footer-col a{font-size:14px;color:var(--text-muted);transition:color var(--transition-fast)}.footer-col a:hover{color:var(--primary)}.footer-bottom{display:flex;justify-content:space-between;align-items:center;padding-top:24px;border-top:1px solid var(--border-soft);font-size:13px;color:var(--text-dim)}.footer-legal{display:flex;gap:24px}.footer-legal a{transition:color var(--transition-fast)}.footer-legal a:hover{color:var(--text)}@media (max-width: 768px){.footer-top{flex-direction:column;gap:36px}.footer-cols{grid-template-columns:repeat(2,1fr);gap:32px}.footer-bottom{flex-direction:column;gap:12px;text-align:center}}.filter-bar{display:flex;gap:10px;margin-bottom:32px;flex-wrap:wrap}.filter-chip{padding:8px 18px;font-size:13px;font-weight:600;border-radius:100px;background:var(--bg-elev-2);color:var(--text-muted);border:1px solid var(--border-soft);transition:all var(--transition)}.filter-chip:hover{color:var(--text);border-color:var(--border)}.filter-chip.active{background:var(--primary);color:#0a0a0b;border-color:var(--primary)}.modal-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:200;background:#000000b3;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;padding:24px;animation:fadeIn .25s ease both}.modal-close{position:absolute;top:16px;right:16px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--bg-elev-2);color:var(--text-muted);transition:all var(--transition-fast);z-index:10}.modal-close:hover{background:var(--border);color:var(--text)}.product-detail-modal{position:relative;width:100%;max-width:900px;max-height:90vh;overflow-y:auto;background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);animation:scaleIn .3s ease both}.product-detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:0}.product-detail-image-wrap{position:relative;aspect-ratio:3/4;overflow:hidden;background:linear-gradient(180deg,var(--bg-elev-2) 0%,var(--bg) 100%);border-radius:var(--radius-lg) 0 0 var(--radius-lg);display:flex;align-items:center;justify-content:center;padding:32px}.product-detail-image{width:100%;height:100%;object-fit:cover}.tshirt-preview-wrap{background:radial-gradient(ellipse at center,var(--bg-elev-2) 0%,var(--bg) 70%)}.tshirt-svg{width:100%;max-width:320px;height:auto;filter:drop-shadow(0 12px 32px rgba(0,0,0,.3));transition:filter .4s ease}.tshirt-sm{max-width:72px}.tshirt-md{max-width:220px}.tshirt-lg{max-width:320px}.product-card-preview{width:100%;height:100%;display:flex;align-items:center;justify-content:center;padding:20px;background:radial-gradient(ellipse at center,var(--bg-elev-2) 0%,var(--bg) 80%)}.product-detail-info{padding:36px 36px 28px;display:flex;flex-direction:column;gap:14px}.product-detail-title{font-family:var(--font-display);font-size:28px;font-weight:700;letter-spacing:-.02em}.product-detail-rating{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--text-muted)}.product-detail-price{display:flex;align-items:baseline;gap:10px;margin:4px 0}.product-detail-price .price-now{font-size:24px}.save-badge{padding:3px 10px;font-size:12px;font-weight:600;background:var(--error);color:#fff;border-radius:6px}.product-detail-desc{font-size:14px;line-height:1.6;color:var(--text-muted)}.option-group{display:flex;flex-direction:column;gap:10px}.option-label{font-size:13px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted)}.selected-color-name{text-transform:capitalize;color:var(--text);font-weight:700;letter-spacing:0}.color-options{display:flex;gap:10px}.color-option{width:34px;height:34px;border-radius:50%;border:2px solid var(--border-soft);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all var(--transition-fast);position:relative}.color-option.selected{border-color:var(--primary);box-shadow:0 0 0 2px #d4a5744d}.color-check{color:#fff;mix-blend-mode:difference}.size-options{display:flex;gap:8px;flex-wrap:wrap}.size-option{min-width:44px;padding:10px 14px;font-size:13px;font-weight:600;border-radius:var(--radius-sm);background:var(--bg-elev-2);color:var(--text-muted);border:1px solid var(--border-soft);transition:all var(--transition-fast)}.size-option:hover{color:var(--text);border-color:var(--border)}.size-option.selected{background:var(--primary);color:#0a0a0b;border-color:var(--primary)}.quantity-control{display:inline-flex;align-items:center;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;width:fit-content}.quantity-control button{width:40px;height:40px;display:flex;align-items:center;justify-content:center;color:var(--text-muted);transition:background var(--transition-fast)}.quantity-control button:hover{background:var(--bg-elev-2);color:var(--text)}.quantity-value{min-width:40px;text-align:center;font-size:15px;font-weight:600}.product-detail-actions{display:flex;gap:10px;margin-top:8px}.product-detail-add{flex:1;justify-content:center;padding:16px}.product-detail-add.added{background:var(--success);color:#fff}.btn.wished{color:var(--error);border-color:var(--error)}.product-detail-features{display:flex;flex-direction:column;gap:8px;padding-top:12px;border-top:1px solid var(--border-soft);margin-top:4px}.detail-feature{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-muted)}.detail-feature svg{color:var(--success)}@media (max-width: 768px){.product-detail-grid{grid-template-columns:1fr}.product-detail-image-wrap{border-radius:var(--radius-lg) var(--radius-lg) 0 0;aspect-ratio:4/3}.product-detail-info{padding:24px}}.drawer-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:150;background:#0009;opacity:0;visibility:hidden;transition:opacity .3s ease,visibility .3s}.drawer-overlay.open{opacity:1;visibility:visible}.cart-drawer{position:fixed;top:0;right:0;z-index:160;width:420px;max-width:100%;height:100vh;background:var(--bg-elev);border-left:1px solid var(--border);display:flex;flex-direction:column;transform:translate(100%);transition:transform .35s cubic-bezier(.4,0,.2,1)}.cart-drawer.open{transform:translate(0)}.cart-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--border-soft)}.cart-drawer-title{display:flex;align-items:center;gap:8px;font-size:18px;font-weight:700}.cart-drawer-count{font-size:12px;font-weight:700;background:var(--primary);color:#0a0a0b;padding:2px 8px;border-radius:100px}.cart-drawer-header .modal-close{position:static}.cart-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px;text-align:center;color:var(--text-dim)}.cart-empty svg{color:var(--border)}.cart-empty p{font-size:18px;font-weight:600;color:var(--text)}.cart-empty span{font-size:14px;margin-bottom:8px}.cart-items{flex:1;overflow-y:auto;padding:16px 24px;display:flex;flex-direction:column;gap:16px}.cart-item{display:flex;gap:14px;position:relative;padding-bottom:16px;border-bottom:1px solid var(--border-soft)}.cart-item:last-child{border-bottom:none}.cart-item-image{width:80px;height:100px;object-fit:cover;border-radius:var(--radius-sm);flex-shrink:0}.cart-item-preview{width:72px;height:90px;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:radial-gradient(ellipse at center,var(--bg-elev-2) 0%,var(--bg) 80%);border-radius:var(--radius-sm);padding:4px}.cart-item-info{flex:1;display:flex;flex-direction:column;gap:6px}.cart-item-name{font-size:14px;font-weight:600}.cart-item-meta{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-dim)}.cart-item-color-name{text-transform:capitalize}.cart-item-sep{opacity:.5}.cart-item-swatch{width:14px;height:14px;border-radius:50%;border:1px solid rgba(255,255,255,.15)}.cart-item-bottom{display:flex;align-items:center;justify-content:space-between;margin-top:auto}.cart-qty{display:inline-flex;align-items:center;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}.cart-qty button{width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:var(--text-muted);transition:background var(--transition-fast)}.cart-qty button:hover{background:var(--bg-elev-2);color:var(--text)}.cart-qty span{min-width:32px;text-align:center;font-size:13px;font-weight:600}.cart-item-price{font-size:15px;font-weight:700}.cart-item-remove{position:absolute;top:0;right:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:50%;color:var(--text-dim);transition:all var(--transition-fast)}.cart-item-remove:hover{background:var(--error);color:#fff}.cart-drawer-footer{padding:20px 24px;border-top:1px solid var(--border-soft);background:var(--bg)}.cart-summary-row{display:flex;justify-content:space-between;align-items:center;font-size:14px;color:var(--text-muted);margin-bottom:8px}.cart-summary-value{color:var(--text);font-weight:600}.cart-summary-total{font-size:18px;font-weight:700;color:var(--text);padding-top:12px;margin-top:4px;border-top:1px solid var(--border-soft);margin-bottom:16px}.checkout-btn{width:100%;justify-content:center;padding:16px;margin-bottom:8px}.continue-btn{width:100%;justify-content:center;padding:14px}.checkout-modal{position:relative;width:100%;max-width:880px;max-height:90vh;overflow-y:auto;background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);animation:scaleIn .3s ease both}.checkout-header{display:flex;align-items:center;justify-content:space-between;padding:24px 32px;border-bottom:1px solid var(--border-soft)}.checkout-header h2{font-family:var(--font-display);font-size:24px;font-weight:700}.checkout-header span{font-size:14px;color:var(--text-muted)}.checkout-body{display:grid;grid-template-columns:1.3fr 1fr;gap:0}.checkout-form{padding:28px 32px;display:flex;flex-direction:column;gap:14px}.checkout-section-title{font-size:14px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted);margin-top:8px}.form-row{display:flex}.form-row.two-col{display:grid;grid-template-columns:1fr 1fr;gap:12px}.form-input{width:100%;padding:12px 16px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-size:14px;font-family:inherit;outline:none;transition:border-color var(--transition)}.form-input:focus{border-color:var(--primary)}.form-input::placeholder{color:var(--text-dim)}.payment-options{display:flex;flex-direction:column;gap:10px}.payment-option{display:flex;align-items:center;gap:14px;padding:14px 16px;border:1px solid var(--border-soft);border-radius:var(--radius-sm);cursor:pointer;transition:all var(--transition-fast)}.payment-option:hover{border-color:var(--border)}.payment-option.selected{border-color:var(--primary);background:var(--primary-soft)}.payment-option input{accent-color:var(--primary)}.payment-option svg{color:var(--primary)}.payment-name{display:block;font-size:14px;font-weight:600}.payment-desc{display:block;font-size:12px;color:var(--text-dim)}.checkout-trust{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-dim);padding:10px 0}.checkout-trust svg{color:var(--success)}.place-order-btn{width:100%;justify-content:center;padding:16px;margin-top:4px}.checkout-summary{padding:28px 32px;background:var(--bg);border-left:1px solid var(--border-soft)}.checkout-items{display:flex;flex-direction:column;gap:14px;margin-bottom:20px}.checkout-summary-item{display:flex;align-items:center;gap:12px}.checkout-summary-image{width:48px;height:60px;object-fit:cover;border-radius:var(--radius-sm);flex-shrink:0}.checkout-summary-preview{width:56px;height:68px;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:radial-gradient(ellipse at center,var(--bg-elev-2) 0%,var(--bg) 80%);border-radius:var(--radius-sm);padding:2px}.checkout-summary-info{flex:1;display:flex;flex-direction:column}.checkout-summary-name{font-size:13px;font-weight:600}.checkout-summary-meta{font-size:12px;color:var(--text-dim)}.checkout-summary-price{font-size:14px;font-weight:700}.checkout-totals{padding-top:16px;border-top:1px solid var(--border-soft)}.checkout-success-modal{position:relative;width:100%;max-width:460px;text-align:center;background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);padding:48px 40px;animation:scaleIn .35s ease both}.success-icon{width:80px;height:80px;margin:0 auto 20px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--success);color:#fff;animation:scaleIn .4s .1s ease both}.checkout-success-modal h2{font-family:var(--font-display);font-size:28px;font-weight:700;margin-bottom:8px}.checkout-success-modal p{font-size:15px;color:var(--text-muted);line-height:1.6;margin-bottom:24px}.order-info{background:var(--bg);border-radius:var(--radius);padding:20px;margin-bottom:24px}.order-info-row{display:flex;justify-content:space-between;font-size:14px;color:var(--text-muted);margin-bottom:10px}.order-info-row:last-child{margin-bottom:0}.order-info-value{color:var(--text);font-weight:600}.checkout-success-modal .btn{width:100%;justify-content:center;padding:16px}@media (max-width: 768px){.checkout-body{grid-template-columns:1fr}.checkout-summary{border-left:none;border-top:1px solid var(--border-soft)}.checkout-form,.checkout-summary,.checkout-header{padding:20px}}.product-card-actions{position:absolute;bottom:12px;left:12px;right:12px;display:flex;gap:8px}.product-card-actions .product-quick-add,.product-card-actions .product-buy-now{flex:1;position:static}.product-buy-now{background:#1a1a1a;color:#fff;border:none;border-radius:8px;padding:10px 12px;font-size:13px;font-weight:600;cursor:pointer}.product-buy-now:hover{background:#333}.search-panel-top{display:flex;align-items:center;gap:12px;padding:10px 14px;background:var(--bg);border:1px solid var(--border-soft);border-radius:var(--radius);color:var(--text-muted)}.search-hint{padding:20px 8px;text-align:center;color:var(--text-dim);font-size:14px}.search-result-category{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--text-dim)}
