Skip to content

Commit a58d1dc

Browse files
Nature meets icons and UI
Implemented Emerald Green & Gold brand pivot: - Added Nano minimalist category icons set (Emerald + Gold) in src/components/brand/CategoryIcons.tsx - Reworked AI Concierge prompts and greeting to reflect pharmacist-led Nature Meets Science ethos - Updated hero visuals to align with marble/emerald branding - Updated language translations for brand shift and shadow tokens compatibility - Introduced backward-compatible emerald/maroon shadow aliases in Tailwind config and CSS tokens - Replaced color tokens across index.css and language contexts to reflect Emerald/Gold/Marble palette X-Lovable-Edit-ID: edt-4cada92b-36cc-4e9e-ae20-776963adb3b8
2 parents 62d9286 + 0644e0d commit a58d1dc

6 files changed

Lines changed: 300 additions & 107 deletions

File tree

src/components/AIConcierge.tsx

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ const personaConfig = {
147147
};
148148

149149
const quickPrompts = [
150-
{ label: "Acne routine", text: "I have acne-prone oily skin. What's a good 3-step routine?" },
151-
{ label: "Gift ideas", text: "I need a luxury gift set for my friend's birthday" },
152-
{ label: "Sunscreen help", text: "What SPF should I use for sensitive skin?" },
153-
{ label: "📸 Skin check", text: "" }, // special: triggers image upload
150+
{ label: "✨ Find My Routine", text: "I want a personalized skincare routine based on my concerns" },
151+
{ label: "🧪 Shop by Ingredient", text: "I'm looking for products with Vitamin C, Retinol, or Hyaluronic Acid" },
152+
{ label: "🌿 Natural Options", text: "What natural and organic skincare products do you recommend?" },
153+
{ label: "📸 Skin Analysis", text: "" }, // special: triggers image upload
154154
];
155155

156156
export default function AIConcierge() {
@@ -448,27 +448,42 @@ export default function AIConcierge() {
448448
</div>
449449
)}
450450
{isAuthenticated && messages.length === 0 && (
451-
<div className="space-y-3">
452-
<p className="text-center text-sm text-muted-foreground font-body">
453-
Ask me anything about skincare, beauty, or upload a photo for a skin diagnostic 📸
454-
</p>
451+
<div className="space-y-4 py-4">
452+
{/* Pharmacist greeting */}
453+
<div className="text-center space-y-2">
454+
<div className="flex justify-center mb-3">
455+
<div className="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center">
456+
<span className="text-xl">🌿</span>
457+
</div>
458+
</div>
459+
<p className="text-sm font-heading font-semibold text-foreground">
460+
Welcome to Asper Beauty Shop
461+
</p>
462+
<p className="text-xs text-muted-foreground font-body max-w-[280px] mx-auto leading-relaxed">
463+
I am your Pharmacist-led Concierge. I'm here to help you navigate the intersection of Nature & Science.
464+
</p>
465+
</div>
466+
{/* Quick action buttons */}
455467
<div className="grid grid-cols-2 gap-2">
456468
{quickPrompts.map((qp) => (
457469
<button
458470
key={qp.label}
459471
onClick={() => {
460-
if (qp.label === "📸 Skin check") {
472+
if (qp.label === "📸 Skin Analysis") {
461473
triggerFileInput();
462474
} else {
463475
send(qp.text);
464476
}
465477
}}
466-
className="rounded-lg border border-border/50 bg-secondary/50 px-3 py-2 text-left text-xs font-body text-foreground/80 transition-colors hover:bg-secondary hover:border-primary/20"
478+
className="rounded-lg border border-primary/20 bg-primary/5 px-3 py-2.5 text-left text-xs font-body text-foreground/80 transition-all hover:bg-primary/10 hover:border-primary/40 hover:shadow-sm"
467479
>
468480
{qp.label}
469481
</button>
470482
))}
471483
</div>
484+
<p className="text-center text-[10px] text-accent font-body uppercase tracking-[0.15em]">
485+
Nature Meets Science ✦ Pharmacist Verified
486+
</p>
472487
</div>
473488
)}
474489

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/**
2+
* Asper Beauty Shop — "Nature Meets Science" Category Icon Set
3+
*
4+
* Design DNA:
5+
* - Style: Nano minimalist — 1.2px ultra-thin lines
6+
* - Primary: Emerald Green (inherits from parent via currentColor)
7+
* - Accent: Gold highlights on specific elements
8+
* - Canvas: 24×24 grid
9+
* - Corners: 2px radius, slightly softened
10+
*/
11+
12+
import { cn } from "@/lib/utils";
13+
14+
interface IconProps {
15+
className?: string;
16+
size?: number;
17+
goldAccent?: boolean;
18+
}
19+
20+
const base = (size: number, className?: string) => ({
21+
width: size,
22+
height: size,
23+
viewBox: "0 0 24 24",
24+
fill: "none",
25+
stroke: "currentColor",
26+
strokeWidth: 1.2,
27+
strokeLinecap: "round" as const,
28+
strokeLinejoin: "round" as const,
29+
className: cn("shrink-0", className),
30+
});
31+
32+
const GOLD = "#C5A028";
33+
34+
/** Dropper bottle — Skincare */
35+
export function IconCatSkincare({ className, size = 24, goldAccent = true }: IconProps) {
36+
return (
37+
<svg {...base(size, className)}>
38+
<rect x="8" y="10" width="8" height="11" rx="1.5" />
39+
<path d="M10 10V8a2 2 0 0 1 4 0v2" />
40+
<path d="M12 5V3" />
41+
{/* Gold drop highlight */}
42+
<circle cx="12" cy="6.5" r="1" fill={goldAccent ? GOLD : "none"} stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="0.8" />
43+
</svg>
44+
);
45+
}
46+
47+
/** Capsule — Vitamins & Supplements */
48+
export function IconCatVitamins({ className, size = 24, goldAccent = true }: IconProps) {
49+
return (
50+
<svg {...base(size, className)}>
51+
<rect x="8" y="2" width="8" height="20" rx="4" />
52+
{/* Gold dividing line */}
53+
<line x1="8" y1="12" x2="16" y2="12" stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="1" />
54+
<circle cx="10.5" cy="15" r="0.5" fill="currentColor" stroke="none" />
55+
<circle cx="13.5" cy="15" r="0.5" fill="currentColor" stroke="none" />
56+
<circle cx="12" cy="17.5" r="0.5" fill="currentColor" stroke="none" />
57+
</svg>
58+
);
59+
}
60+
61+
/** Mortar & Pestle — Prescriptions */
62+
export function IconCatPrescriptions({ className, size = 24, goldAccent = true }: IconProps) {
63+
return (
64+
<svg {...base(size, className)}>
65+
<path d="M4 16c0 2.5 3.5 5 8 5s8-2.5 8-5" />
66+
<path d="M4 16c0-1 1-2 3-3l10 0c2 1 3 2 3 3" />
67+
{/* Gold pestle */}
68+
<line x1="12" y1="4" x2="12" y2="13" stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="1.5" strokeLinecap="round" />
69+
<circle cx="12" cy="3.5" r="1.5" fill="none" stroke={goldAccent ? GOLD : "currentColor"} />
70+
</svg>
71+
);
72+
}
73+
74+
/** Leaf & Drop — Mother & Baby */
75+
export function IconCatMomBaby({ className, size = 24, goldAccent = true }: IconProps) {
76+
return (
77+
<svg {...base(size, className)}>
78+
{/* Leaf */}
79+
<path d="M6 18C6 12 10 6 17 4c0 0-1 8-5 11s-6 3-6 3z" />
80+
<path d="M6 18c2-2 5-4 8-5" />
81+
{/* Gold droplet */}
82+
<path d="M18 14c-1.5 2-2.5 3.5-2.5 5a2.5 2.5 0 0 0 5 0c0-1.5-1-3-2.5-5z" fill={goldAccent ? GOLD : "none"} stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="0.8" />
83+
</svg>
84+
);
85+
}
86+
87+
/** Pump Bottle — Personal Care */
88+
export function IconCatPersonalCare({ className, size = 24, goldAccent = true }: IconProps) {
89+
return (
90+
<svg {...base(size, className)}>
91+
<rect x="7" y="10" width="10" height="11" rx="2" />
92+
<rect x="9" y="7" width="6" height="3" rx="1" />
93+
{/* Gold pump */}
94+
<path d="M12 7V4h3" stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="1.2" />
95+
<rect x="14" y="3" width="3" height="2" rx="0.5" fill={goldAccent ? GOLD : "none"} stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="0.8" />
96+
</svg>
97+
);
98+
}
99+
100+
/** Medical Cross — First Aid */
101+
export function IconCatFirstAid({ className, size = 24, goldAccent = true }: IconProps) {
102+
return (
103+
<svg {...base(size, className)}>
104+
<rect x="3" y="3" width="18" height="18" rx="3" />
105+
<path d="M12 8v8M8 12h8" strokeWidth="1.5" />
106+
{/* Subtle gold glow circle behind cross */}
107+
<circle cx="12" cy="12" r="5" fill="none" stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="0.4" opacity="0.5" />
108+
</svg>
109+
);
110+
}
111+
112+
/** Toothbrush — Oral Care */
113+
export function IconCatOralCare({ className, size = 24, goldAccent = true }: IconProps) {
114+
return (
115+
<svg {...base(size, className)}>
116+
<rect x="10" y="2" width="4" height="6" rx="2" />
117+
<rect x="11" y="8" width="2" height="14" rx="1" />
118+
{/* Gold sparkle */}
119+
<path d="M17 4l-1 1M17 4l1 0M17 4l0-1" stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="1" />
120+
</svg>
121+
);
122+
}
123+
124+
/** Shield — Men's Health */
125+
export function IconCatMensHealth({ className, size = 24, goldAccent = true }: IconProps) {
126+
return (
127+
<svg {...base(size, className)}>
128+
<path d="M12 3l7 3v5c0 5-3 8-7 10-4-2-7-5-7-10V6l7-3z" />
129+
{/* Gold rim line */}
130+
<path d="M12 5l5 2.2v3.8c0 3.8-2.2 6.2-5 7.8" stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="0.6" fill="none" />
131+
</svg>
132+
);
133+
}
134+
135+
/** Floral — Beauty */
136+
export function IconCatBeauty({ className, size = 24, goldAccent = true }: IconProps) {
137+
return (
138+
<svg {...base(size, className)}>
139+
{/* Petals */}
140+
<path d="M12 4c-2 2-3 4-3 6s1 3 3 3 3-1 3-3-1-4-3-6z" />
141+
<path d="M4 12c2-2 4-3 6-3s3 1 3 3-1 3-3 3-4-1-6-3z" />
142+
<path d="M20 12c-2-2-4-3-6-3s-3 1-3 3 1 3 3 3 4-1 6-3z" />
143+
<path d="M12 20c-2-2-3-4-3-6s1-3 3-3 3 1 3 3-1 4-3 6z" />
144+
{/* Gold center pistil */}
145+
<circle cx="12" cy="12" r="1.5" fill={goldAccent ? GOLD : "none"} stroke={goldAccent ? GOLD : "currentColor"} />
146+
</svg>
147+
);
148+
}
149+
150+
/** Zen Stones — Wellness */
151+
export function IconCatWellness({ className, size = 24, goldAccent = true }: IconProps) {
152+
return (
153+
<svg {...base(size, className)}>
154+
{/* Stacked stones */}
155+
<ellipse cx="12" cy="19" rx="5" ry="2.5" />
156+
<ellipse cx="12" cy="14" rx="4" ry="2" />
157+
<ellipse cx="12" cy="10" rx="3" ry="1.5" />
158+
{/* Gold leaf accent */}
159+
<path d="M16 6c0 0-1.5 3-4 3s-2-3-2-3c1-1 3-2 4-1.5s2 1.5 2 1.5z" fill={goldAccent ? GOLD : "none"} stroke={goldAccent ? GOLD : "currentColor"} strokeWidth="0.8" />
160+
</svg>
161+
);
162+
}
163+
164+
/** Full category list for navigation */
165+
export const categoryList = [
166+
{ key: "skincare", label: "Skincare", labelAr: "العناية بالبشرة", Icon: IconCatSkincare, href: "/products?category=skincare" },
167+
{ key: "vitamins", label: "Vitamins", labelAr: "فيتامينات", Icon: IconCatVitamins, href: "/products?category=vitamins" },
168+
{ key: "prescriptions", label: "Prescriptions", labelAr: "وصفات طبية", Icon: IconCatPrescriptions, href: "/products?category=prescriptions" },
169+
{ key: "mom-baby", label: "Mother & Baby", labelAr: "الأم والطفل", Icon: IconCatMomBaby, href: "/mom-baby" },
170+
{ key: "personal-care", label: "Personal Care", labelAr: "العناية الشخصية", Icon: IconCatPersonalCare, href: "/products?category=personal-care" },
171+
{ key: "first-aid", label: "First Aid", labelAr: "إسعافات أولية", Icon: IconCatFirstAid, href: "/products?category=first-aid" },
172+
{ key: "oral-care", label: "Oral Care", labelAr: "العناية بالفم", Icon: IconCatOralCare, href: "/products?category=oral-care" },
173+
{ key: "mens-health", label: "Men's Health", labelAr: "صحة الرجل", Icon: IconCatMensHealth, href: "/products?category=mens-health" },
174+
{ key: "beauty", label: "Beauty", labelAr: "الجمال", Icon: IconCatBeauty, href: "/products?category=beauty" },
175+
{ key: "wellness", label: "Wellness", labelAr: "العافية", Icon: IconCatWellness, href: "/products?category=wellness" },
176+
] as const;

src/components/home/Hero.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Link } from "react-router-dom";
22
import { Button } from "@/components/ui/button";
3-
import { ArrowRight, Shield, Sparkles, Thermometer, Sun, Moon, CloudSun } from "lucide-react";
3+
import { ArrowRight, Shield, Sparkles, Leaf, Sun, Moon, CloudSun } from "lucide-react";
44
import { useLanguage } from "@/contexts/LanguageContext";
55
import { useTimeContext } from "@/hooks/useTimeContext";
66
import heroVideo from "@/assets/hero-video.mp4";
@@ -9,29 +9,27 @@ import { cn } from "@/lib/utils";
99
const timeIcons = { morning: Sun, afternoon: CloudSun, evening: Moon };
1010

1111
export default function Hero() {
12-
const { t, dir } = useLanguage();
12+
const { t, dir, locale } = useLanguage();
1313
const { timeOfDay, greeting, tagline, moodClass } = useTimeContext();
1414
const TimeIcon = timeIcons[timeOfDay];
15+
const isAr = locale === "ar";
1516

1617
return (
1718
<section className="relative h-[85vh] min-h-[600px] max-h-[900px] overflow-hidden">
1819
{/* Video Background */}
19-
{/* eslint-disable-next-line react/no-unknown-property */}
2020
<video
2121
autoPlay
2222
muted
2323
loop
2424
playsInline
25-
// @ts-ignore fetchpriority is valid HTML but not yet in React types
26-
fetchpriority="high"
2725
className="absolute inset-0 h-full w-full object-cover"
2826
>
2927
<source src={heroVideo} type="video/mp4" />
3028
</video>
3129

32-
{/* Gradient overlays for readability */}
33-
<div className="absolute inset-0 bg-gradient-to-r from-primary/80 via-primary/50 to-transparent" />
34-
<div className="absolute inset-0 bg-gradient-to-t from-primary/70 via-transparent to-primary/30" />
30+
{/* Emerald + marble gradient overlays */}
31+
<div className="absolute inset-0 bg-gradient-to-r from-primary/80 via-primary/40 to-transparent" />
32+
<div className="absolute inset-0 bg-gradient-to-t from-primary/60 via-transparent to-primary/20" />
3533

3634
{/* Gold border frame */}
3735
<div className="absolute inset-4 sm:inset-8 border border-accent/30 pointer-events-none z-10" />
@@ -53,23 +51,25 @@ export default function Hero() {
5351
"font-heading text-4xl sm:text-5xl lg:text-7xl font-bold text-primary-foreground leading-[1.1] tracking-tight",
5452
dir === "rtl" && "font-arabic"
5553
)}>
56-
{t("hero.title_1")}
54+
{isAr ? "الطبيعة" : "Nature"}
5755
<br />
58-
<span className="text-accent">{t("hero.title_2")}</span>
56+
<span className="text-accent">{isAr ? "تلتقي بالعلم" : "Meets Science"}</span>
5957
</h1>
6058

6159
<p className={cn(
6260
"text-base sm:text-lg text-primary-foreground/80 max-w-lg leading-relaxed",
6361
dir === "rtl" ? "font-arabic" : "font-body"
6462
)}>
65-
{tagline}
63+
{isAr
64+
? "منتجات فاخرة للعناية بالبشرة والجمال — مُعتمدة صيدلانياً من أرقى العلامات التجارية العالمية"
65+
: "Curated luxury skincare & beauty from the world's most prestigious brands — pharmacist verified"}
6666
</p>
6767

6868
{/* Trust micro-badges */}
6969
<div className={`flex flex-wrap gap-3 ${dir === "rtl" ? "justify-end" : ""}`}>
7070
{[
7171
{ icon: Shield, label: t("hero.authentic"), color: "text-accent" },
72-
{ icon: Thermometer, label: t("hero.temperature"), color: "text-accent" },
72+
{ icon: Leaf, label: isAr ? "طبيعي ونقي" : "Natural & Pure", color: "text-accent" },
7373
{ icon: Sparkles, label: t("hero.pharmacist_led"), color: "text-accent" },
7474
].map((item) => (
7575
<span
@@ -87,7 +87,7 @@ export default function Hero() {
8787
<Link to="/products">
8888
<Button
8989
size="lg"
90-
className="group bg-accent text-primary hover:bg-accent/90 text-sm uppercase tracking-widest px-8 h-12 font-semibold shadow-lg shadow-accent/20"
90+
className="group bg-accent text-primary-foreground hover:bg-accent/90 text-sm uppercase tracking-widest px-8 h-12 font-semibold shadow-lg shadow-accent/20"
9191
>
9292
{t("hero.cta_primary")}
9393
<ArrowRight className={`h-4 w-4 group-hover:translate-x-1 transition-transform ${dir === "rtl" ? "mr-2 rotate-180" : "ml-2"}`} />
@@ -107,10 +107,10 @@ export default function Hero() {
107107
</div>
108108
</div>
109109

110-
{/* Bottom sanctuary label */}
110+
{/* Bottom "Nature Meets Science" label */}
111111
<div className="absolute bottom-6 sm:bottom-10 right-6 sm:right-10 z-20">
112112
<p className="text-primary-foreground/50 font-body text-[10px] sm:text-xs uppercase tracking-[0.3em]">
113-
{t("hero.sanctuary")}
113+
{isAr ? "الطبيعة تلتقي بالعلم" : "Nature Meets Science"}
114114
</p>
115115
</div>
116116
</section>

src/contexts/LanguageContext.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ const translations: Record<string, Record<Locale, string>> = {
1515
"nav.concierge": { en: "AI Concierge", ar: "المساعد الذكي" },
1616
"nav.about": { en: "About", ar: "عن أسبر" },
1717
"nav.shop_now": { en: "Shop Now", ar: "تسوق الآن" },
18-
"hero.badge": { en: "THE FUTURE OF DERMO-RETAIL", ar: "مستقبل التجميل الطبي" },
19-
"hero.title_1": { en: "Curated by Pharmacists.", ar: "بإشراف صيدلاني." },
20-
"hero.title_2": { en: "Powered by Intelligence.", ar: "مدعوم بالذكاء." },
18+
"hero.badge": { en: "NATURE MEETS SCIENCE", ar: "الطبيعة تلتقي بالعلم" },
19+
"hero.title_1": { en: "Nature", ar: "الطبيعة" },
20+
"hero.title_2": { en: "Meets Science.", ar: "تلتقي بالعلم." },
2121
"hero.subtitle": {
22-
en: "We do not just sell cosmetics. We dispense beauty through intelligence. Bridging the gap between clinical dermocosmetics and everyday essentials.",
23-
ar: "لا نبيع مستحضرات تجميل فحسب. نقدم الجمال من خلال الذكاء. نسد الفجوة بين مستحضرات التجميل الطبية والاحتياجات اليومية.",
22+
en: "Curated luxury skincare & beauty from the world's most prestigious brands — pharmacist verified. Where botanical purity meets clinical precision.",
23+
ar: "منتجات فاخرة للعناية بالبشرة والجمال من أرقى العلامات التجارية العالمية — مُعتمدة صيدلانياً. حيث تلتقي النقاء النباتي بالدقة السريرية.",
2424
},
2525
"hero.cta_primary": { en: "Find My Ritual", ar: "اكتشف روتيني" },
2626
"hero.cta_secondary": { en: "Shop All Brands", ar: "تصفح العلامات" },
2727
"hero.authentic": { en: "100% Authentic", ar: "أصلي 100%" },
2828
"hero.temperature": { en: "Temperature Controlled", ar: "تخزين مُبرّد" },
2929
"hero.pharmacist_led": { en: "Pharmacist Led", ar: "بإشراف صيدلاني" },
30-
"hero.sanctuary": { en: "The Sanctuary of Science", ar: "حرم العلم" },
30+
"hero.sanctuary": { en: "Nature Meets Science", ar: "الطبيعة تلتقي بالعلم" },
3131
"footer.tagline": {
3232
en: '"We do not just sell cosmetics; we dispense beauty through intelligence."',
3333
ar: '"لا نبيع مستحضرات تجميل فحسب؛ بل نقدم الجمال من خلال الذكاء."',

0 commit comments

Comments
 (0)