This commit is contained in:
Your Name committed 2026-06-21 02:09:26 -04:00
1 parent 3cacaacbeb
commit 8b73b8dd2f
52 files changed
+265 -265

No files matched your search

+4 -4
View File
@@ -32,7 +32,7 @@ export default function CartDrawer() {
/>
{/* Drawer */}
<div className="relative w-full max-w-md h-full bg-white shadow-2xl flex flex-col animate-slide-left">
<div className="relative w-full max-w-md h-full bg-spa-light shadow-2xl flex flex-col animate-slide-left">
{/* Header */}
<div className="p-6 border-b border-spa-stone/10 flex items-center justify-between bg-spa-light">
<h2 className="text-xl font-bold flex items-center gap-2 text-pop-black">
@@ -65,7 +65,7 @@ export default function CartDrawer() {
</div>
) : (
items.map((item) => (
<div key={item.cartItemId} className="flex gap-4 p-4 rounded-2xl bg-white border border-spa-stone/10 shadow-sm group relative">
<div key={item.cartItemId} className="flex gap-4 p-4 rounded-2xl bg-spa-light border border-spa-stone/10 shadow-sm group relative">
<div className="w-18 h-22 rounded-lg bg-spa-sage/30 overflow-hidden flex-shrink-0" style={{ width: '72px', height: '88px' }}>
<img
src={item.productImage || '/images/fallback-product.svg'}
@@ -225,7 +225,7 @@ function CartDrawerFooter({ subtotal, onClose, t }: { subtotal: number; onClose:
value={couponInput}
onChange={e => setCouponInput(e.target.value.toUpperCase())}
placeholder={t('cart.couponPlaceholder', 'Discount Code')}
className="flex-1 bg-white border border-spa-stone/20 rounded-lg px-3 py-2 text-sm text-pop-black focus:border-spa-forest outline-none uppercase tracking-widest placeholder:text-spa-stone/50"
className="flex-1 bg-spa-light border border-spa-stone/20 rounded-lg px-3 py-2 text-sm text-pop-black focus:border-spa-forest outline-none uppercase tracking-widest placeholder:text-spa-stone/50"
/>
<button
onClick={handleApplyCoupon}
@@ -292,7 +292,7 @@ function CartDrawerFooter({ subtotal, onClose, t }: { subtotal: number; onClose:
<Link
to="/checkout"
onClick={onClose}
className="flex items-center justify-center gap-2 w-full py-4 bg-spa-forest text-white font-bold rounded-xl uppercase tracking-widest text-sm hover:bg-spa-stone hover:shadow-lg transition-all duration-300 group"
className="flex items-center justify-center gap-2 w-full py-4 bg-spa-forest text-spa-light font-bold rounded-xl uppercase tracking-widest text-sm hover:bg-spa-stone hover:shadow-lg transition-all duration-300 group"
>
<ShoppingBag className="w-4 h-4" />
ดำเนินการชำระเงิน
+1 -1
View File
@@ -16,7 +16,7 @@ export default function DynamicBanner({ payload }: DynamicBannerProps) {
const buttonText = getLocalizedField(payload.buttonText, lang);
return (
<section className="ui-section-band bg-white relative overflow-hidden">
<section className="ui-section-band bg-spa-light relative overflow-hidden">
{linkUrl ? (
<Link to={linkUrl} className="ui-banner-shell group block cursor-pointer">
<div className="absolute inset-0 z-0">
@@ -26,7 +26,7 @@ export default function DynamicCategories({ payload, categories, loading }: Dyna
}, [categories, categoryIds]);
return (
<section id="categories" className="ui-section-band relative overflow-hidden bg-white">
<section id="categories" className="ui-section-band relative overflow-hidden bg-spa-light">
<div className="ui-section-inner space-y-16 relative z-10">
<div className="space-y-4 text-center">
<h2 className="text-4xl font-bold tracking-tight text-pop-black md:text-5xl">
@@ -40,7 +40,7 @@ export default function DynamicCategories({ payload, categories, loading }: Dyna
{loading ? (
<div className="grid grid-cols-2 gap-6 md:grid-cols-5">
{Array.from({ length: 5 }).map((_, i) => (
<div key={i} className="ui-shell-card h-80 animate-pulse bg-gray-50" />
<div key={i} className="ui-shell-card h-80 animate-pulse bg-spa-sage" />
))}
</div>
) : (
@@ -58,12 +58,12 @@ export default function DynamicCategories({ payload, categories, loading }: Dyna
alt={getLocalizedField(cat.name, lang)}
onError={(e) => { (e.target as HTMLImageElement).style.display = 'none' }}
/>
<div className="absolute bottom-6 left-6 right-6 z-20 text-white">
<div className="absolute bottom-6 left-6 right-6 z-20 text-spa-light">
<span className="mb-1 block text-xl font-semibold">
{getLocalizedField(cat.name, localStorage.getItem('app_lang') || 'en')}
</span>
{cat._count && (
<span className="text-sm font-medium text-white/80">
<span className="text-sm font-medium text-spa-light">
{cat._count.products} Products
</span>
)}
@@ -100,7 +100,7 @@ export default function DynamicEditorialCarousel({ payload }: DynamicEditorialCa
<div className="pt-2">
<Link
to={slide.buttonLink}
className="inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-spa-gold hover:text-white transition-colors group/link"
className="inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-spa-gold hover:text-spa-light transition-colors group/link"
>
{slide.buttonText}
<span className="group-hover/link:translate-x-1 transition-transform">&rarr;</span>
@@ -73,7 +73,7 @@ export default function DynamicEditorialTile({ payload }: DynamicEditorialTilePr
<div className="pt-4">
<Link
to={buttonLink}
className="ui-chip border-current px-8 py-3.5 hover:bg-spa-gold hover:border-spa-gold hover:text-white"
className="ui-chip border-current px-8 py-3.5 hover:bg-spa-gold hover:border-spa-gold hover:text-spa-light"
>
{buttonText}
</Link>
@@ -28,7 +28,7 @@ export default function DynamicHeroArticle({ payload }: DynamicHeroArticleProps)
<div className="ui-hero-overlay" />
</div>
)}
<div className="ui-hero-content text-white">
<div className="ui-hero-content text-spa-light">
{category && (
<span className="mb-4 block text-sm font-bold uppercase tracking-widest text-spa-gold">
{category}
@@ -70,7 +70,7 @@ export default function DynamicNewsletter({ payload }: DynamicNewsletterProps) {
</div>
{status === 'success' ? (
<div className="p-6 bg-white/5 border border-spa-gold/30 rounded-2xl animate-pop-in space-y-2">
<div className="p-6 bg-spa-light border border-spa-gold/30 rounded-2xl animate-pop-in space-y-2">
<h4 className="text-spa-gold font-semibold text-lg">{t('newsletter.thankYou')}</h4>
<p className="text-xs text-spa-light/75">{t('newsletter.successMessage')}</p>
</div>
+3 -3
View File
@@ -26,13 +26,13 @@ export default function DynamicProducts({ payload, categories = [] }: DynamicPro
return (
<section className="ui-section-band relative bg-pop-bg">
<div className="ui-section-inner relative z-10 space-y-12">
<div className="flex items-end justify-between gap-6 border-b border-gray-200 pb-6 md:flex-row">
<div className="flex items-end justify-between gap-6 border-b border-spa-stone/20 pb-6 md:flex-row">
<div>
<h2 className="text-4xl font-bold text-pop-black md:text-5xl">
{title || "Featured Picks"}
</h2>
{subtitle && (
<p className="text-gray-500 mt-2">{subtitle}</p>
<p className="text-spa-stone mt-2">{subtitle}</p>
)}
</div>
<Link
@@ -45,7 +45,7 @@ export default function DynamicProducts({ payload, categories = [] }: DynamicPro
</div>
{products.length === 0 ? (
<div className="py-12 text-center text-gray-500">
<div className="py-12 text-center text-spa-stone">
No products found in this section
</div>
) : layout === 'carousel' ? (
@@ -14,7 +14,7 @@ export default function DynamicQuoteCallout({ payload }: DynamicQuoteCalloutProp
const role = getLocalizedField(payload.role, lang);
return (
<section className="ui-section-band bg-white">
<section className="ui-section-band bg-spa-light">
<div className="ui-section-inner text-center">
<svg className="w-12 h-12 mx-auto text-spa-gold/40 mb-8" fill="currentColor" viewBox="0 0 24 24">
<path d="M14.017 21v-7.391c0-5.704 3.731-9.57 8.983-10.609l.995 2.151c-2.432.917-3.995 3.638-3.995 5.849h4v10h-9.983zm-14.017 0v-7.391c0-5.704 3.748-9.57 9-10.609l.996 2.151c-2.433.917-3.996 3.638-3.996 5.849h3.983v10h-9.983z" />
+2 -2
View File
@@ -20,7 +20,7 @@ export default function DynamicText({ payload }: DynamicTextProps) {
}[textAlign] || 'text-left';
return (
<section className="ui-section-band bg-white relative">
<section className="ui-section-band bg-spa-light relative">
<div className={`ui-section-inner space-y-6 ${alignClass}`}>
{title && (
<h2 className="font-serif text-3xl font-semibold text-spa-forest md:text-4xl">
@@ -28,7 +28,7 @@ export default function DynamicText({ payload }: DynamicTextProps) {
</h2>
)}
<div
className="whitespace-pre-wrap text-base font-light leading-relaxed text-gray-600 md:text-lg"
className="whitespace-pre-wrap text-base font-light leading-relaxed text-spa-stone md:text-lg"
dangerouslySetInnerHTML={{ __html: content }}
/>
</div>
+2 -2
View File
@@ -17,13 +17,13 @@ export default function EmptyState({
actionClick
}: EmptyStateProps) {
const ButtonContent = () => (
<span className="inline-block mt-6 px-8 py-3 bg-spa-forest text-white rounded-xl text-sm font-bold uppercase tracking-widest hover:bg-spa-stone hover:shadow-lg transition-all cursor-pointer">
<span className="inline-block mt-6 px-8 py-3 bg-spa-forest text-spa-light rounded-xl text-sm font-bold uppercase tracking-widest hover:bg-spa-stone hover:shadow-lg transition-all cursor-pointer">
{actionText}
</span>
)
return (
<div className="flex flex-col items-center justify-center space-y-4 text-center p-12 bg-white border border-spa-stone/10 rounded-2xl shadow-sm max-w-lg mx-auto my-8">
<div className="flex flex-col items-center justify-center space-y-4 text-center p-12 bg-spa-light border border-spa-stone/10 rounded-2xl shadow-sm max-w-lg mx-auto my-8">
<div className="w-16 h-16 bg-spa-sage/30 rounded-full flex items-center justify-center mb-2">
<PackageOpen className="w-8 h-8 text-spa-forest" />
</div>
+2 -2
View File
@@ -13,7 +13,7 @@ export default function ErrorState({
showHomeButton = true
}: ErrorStateProps) {
const content = (
<div className="flex flex-col items-center justify-center space-y-4 text-center p-8 bg-white border border-rose-500/20 rounded-2xl shadow-sm max-w-md mx-auto">
<div className="flex flex-col items-center justify-center space-y-4 text-center p-8 bg-spa-light border border-rose-500/20 rounded-2xl shadow-sm max-w-md mx-auto">
<div className="w-12 h-12 bg-rose-500/10 rounded-full flex items-center justify-center">
<AlertCircle className="w-6 h-6 text-rose-500" />
</div>
@@ -21,7 +21,7 @@ export default function ErrorState({
{showHomeButton && (
<Link
to="/"
className="mt-4 px-6 py-2 bg-spa-forest text-white rounded-lg text-sm font-bold uppercase tracking-widest hover:bg-spa-stone transition-colors"
className="mt-4 px-6 py-2 bg-spa-forest text-spa-light rounded-lg text-sm font-bold uppercase tracking-widest hover:bg-spa-stone transition-colors"
>
Return Home
</Link>
+22 -22
View File
@@ -71,31 +71,31 @@ export default function Footer({ categories = [] }: FooterProps) {
}, [])
return (
<footer className="bg-night-900 px-6 py-20 border-t border-white/5">
<footer className="bg-night-900 px-6 py-20 border-t border-spa-light">
<div className="ui-section-inner grid grid-cols-1 gap-12 md:grid-cols-4">
<div className="space-y-6">
<div className="text-2xl font-bold tracking-widest">
{settings?.logoUrl ? <img src={settings.logoUrl} alt={brandName} className="h-8 md:h-10 object-contain" /> : brandName}
</div>
<p className="text-sm leading-relaxed text-slate-500">
<p className="text-sm leading-relaxed text-spa-stone">
{settings?.footerDescription || t('footer.catchphrase')}
</p>
<div className="flex gap-4">
{settings && (settings.facebookUrl || settings.instagramUrl || settings.tiktokUrl) ? (
<>
{settings.facebookUrl && (
<a href={settings.facebookUrl} target="_blank" rel="noreferrer" className="ui-chip h-9 w-9 border-white/10 bg-white/5 text-[10px] text-white hover:bg-spa-gold hover:text-night-900">FB</a>
<a href={settings.facebookUrl} target="_blank" rel="noreferrer" className="ui-chip h-9 w-9 border-spa-light bg-spa-light text-[10px] text-spa-light hover:bg-spa-gold hover:text-night-900">FB</a>
)}
{settings.instagramUrl && (
<a href={settings.instagramUrl} target="_blank" rel="noreferrer" className="ui-chip h-9 w-9 border-white/10 bg-white/5 text-[10px] text-white hover:bg-spa-gold hover:text-night-900">IG</a>
<a href={settings.instagramUrl} target="_blank" rel="noreferrer" className="ui-chip h-9 w-9 border-spa-light bg-spa-light text-[10px] text-spa-light hover:bg-spa-gold hover:text-night-900">IG</a>
)}
{settings.tiktokUrl && (
<a href={settings.tiktokUrl} target="_blank" rel="noreferrer" className="ui-chip h-9 w-9 border-white/10 bg-white/5 text-[10px] text-white hover:bg-spa-gold hover:text-night-900">TT</a>
<a href={settings.tiktokUrl} target="_blank" rel="noreferrer" className="ui-chip h-9 w-9 border-spa-light bg-spa-light text-[10px] text-spa-light hover:bg-spa-gold hover:text-night-900">TT</a>
)}
</>
) : (
['IG', 'FB', 'TW', 'YT'].map((s) => (
<a key={s} href="#" className="ui-chip h-9 w-9 border-white/10 bg-white/5 text-[10px] text-white hover:bg-spa-gold hover:text-night-900">
<a key={s} href="#" className="ui-chip h-9 w-9 border-spa-light bg-spa-light text-[10px] text-spa-light hover:bg-spa-gold hover:text-night-900">
{s}
</a>
))
@@ -104,30 +104,30 @@ export default function Footer({ categories = [] }: FooterProps) {
</div>
<div className="space-y-4">
<h4 className="text-xs font-bold uppercase tracking-widest text-white">{t('footer.explore')}</h4>
<div className="flex flex-col space-y-2 text-sm text-slate-400">
<h4 className="text-xs font-bold uppercase tracking-widest text-spa-light">{t('footer.explore')}</h4>
<div className="flex flex-col space-y-2 text-sm text-spa-stone">
{exploreMenu.length > 0 ? (
exploreMenu.map(item => (
<Link key={item.id} to={item.url} className="hover:text-white transition-colors">{translateMenuLabel(item)}</Link>
<Link key={item.id} to={item.url} className="hover:text-spa-light transition-colors">{translateMenuLabel(item)}</Link>
))
) : (
<>
<Link to="/" className="hover:text-white transition-colors">{t('nav.home')}</Link>
<Link to="/shop" className="hover:text-white transition-colors">{t('nav.shop')}</Link>
<Link to="/scent-guide" className="hover:text-white transition-colors">{t('nav.scentGuide')}</Link>
<Link to="/about" className="hover:text-white transition-colors">{t('nav.about')}</Link>
<Link to="/contact" className="hover:text-white transition-colors">{t('nav.contact')}</Link>
<Link to="/faq" className="hover:text-white transition-colors">{t('nav.faq')}</Link>
<Link to="/" className="hover:text-spa-light transition-colors">{t('nav.home')}</Link>
<Link to="/shop" className="hover:text-spa-light transition-colors">{t('nav.shop')}</Link>
<Link to="/scent-guide" className="hover:text-spa-light transition-colors">{t('nav.scentGuide')}</Link>
<Link to="/about" className="hover:text-spa-light transition-colors">{t('nav.about')}</Link>
<Link to="/contact" className="hover:text-spa-light transition-colors">{t('nav.contact')}</Link>
<Link to="/faq" className="hover:text-spa-light transition-colors">{t('nav.faq')}</Link>
</>
)}
</div>
</div>
<div className="space-y-4">
<h4 className="text-xs font-bold uppercase tracking-widest text-white">{t('nav.collections')}</h4>
<div className="flex flex-col space-y-2 text-sm text-slate-400">
<h4 className="text-xs font-bold uppercase tracking-widest text-spa-light">{t('nav.collections')}</h4>
<div className="flex flex-col space-y-2 text-sm text-spa-stone">
{categories.map((c) => (
<Link key={c.id} to={`/category/${c.id}`} className="hover:text-white transition-colors">
<Link key={c.id} to={`/category/${c.id}`} className="hover:text-spa-light transition-colors">
{getLocalizedField(c.name, localStorage.getItem('app_lang') || 'en')}
</Link>
))}
@@ -135,17 +135,17 @@ export default function Footer({ categories = [] }: FooterProps) {
</div>
<div className="space-y-4">
<h4 className="text-xs font-bold uppercase tracking-widest text-white">
<h4 className="text-xs font-bold uppercase tracking-widest text-spa-light">
{settings?.footerSupportHeading || t('footer.support', 'Support & Legal')}
</h4>
<div className="flex flex-col space-y-2 text-sm text-slate-400">
<div className="flex flex-col space-y-2 text-sm text-spa-stone">
{supportMenu.map(item => (
<Link key={item.id} to={item.url} className="hover:text-white transition-colors">{translateMenuLabel(item)}</Link>
<Link key={item.id} to={item.url} className="hover:text-spa-light transition-colors">{translateMenuLabel(item)}</Link>
))}
</div>
<div className="pt-4">
<p className="text-[10px] text-slate-600 uppercase tracking-widest">
<p className="text-[10px] text-spa-stone uppercase tracking-widest">
{settings?.footerCopyrightText || `© ${new Date().getFullYear()} ${brandName}. ${t('footer.rights')}`}
</p>
</div>
+6 -6
View File
@@ -168,10 +168,10 @@ export function MobileDrawer({ isOpen, onClose, items, onOpenLang }: MobileDrawe
onClick={onClose}
/>
<div
className={`absolute top-0 right-0 h-full w-80 max-w-[85vw] bg-white shadow-2xl flex flex-col transition-transform duration-300 ${isOpen ? 'translate-x-0' : 'translate-x-full'}`}
className={`absolute top-0 right-0 h-full w-80 max-w-[85vw] bg-spa-light shadow-2xl flex flex-col transition-transform duration-300 ${isOpen ? 'translate-x-0' : 'translate-x-full'}`}
>
{/* Static Top Header */}
<div className="flex items-center justify-between px-6 py-5 border-b border-spa-stone/10 bg-white z-10 shrink-0">
<div className="flex items-center justify-between px-6 py-5 border-b border-spa-stone/10 bg-spa-light z-10 shrink-0">
<span className="text-sm font-bold uppercase tracking-widest text-spa-forest">Menu</span>
<div className="flex items-center gap-3">
<button onClick={onOpenLang} className="px-2.5 py-1 rounded-md text-[10px] font-bold text-spa-forest border border-spa-forest/30 uppercase bg-spa-sage flex items-center gap-1 shrink-0">
@@ -185,7 +185,7 @@ export function MobileDrawer({ isOpen, onClose, items, onOpenLang }: MobileDrawe
</div>
{/* Sliding Views Container */}
<div className="flex-1 relative overflow-hidden bg-white">
<div className="flex-1 relative overflow-hidden bg-spa-light">
{stack.map((view, index) => {
const isCurrent = index === stack.length - 1;
const isPast = index < stack.length - 1;
@@ -193,7 +193,7 @@ export function MobileDrawer({ isOpen, onClose, items, onOpenLang }: MobileDrawe
return (
<div
key={index}
className={`absolute inset-0 flex flex-col bg-white transition-transform duration-300 ease-in-out ${
className={`absolute inset-0 flex flex-col bg-spa-light transition-transform duration-300 ease-in-out ${
isCurrent ? 'translate-x-0' : isPast ? '-translate-x-full' : 'translate-x-full'
}`}
>
@@ -225,10 +225,10 @@ export function MobileDrawer({ isOpen, onClose, items, onOpenLang }: MobileDrawe
</div>
{/* Static Bottom Footer */}
<div className="px-6 pb-8 pt-6 border-t border-spa-stone/10 bg-white z-10 shrink-0 space-y-3">
<div className="px-6 pb-8 pt-6 border-t border-spa-stone/10 bg-spa-light z-10 shrink-0 space-y-3">
<button
onClick={() => handleLinkClick('/shop')}
className="block w-full py-3.5 bg-spa-forest text-white font-bold text-center rounded-xl text-xs uppercase tracking-widest hover:bg-spa-stone transition-colors duration-300 shadow-sm"
className="block w-full py-3.5 bg-spa-forest text-spa-light font-bold text-center rounded-xl text-xs uppercase tracking-widest hover:bg-spa-stone transition-colors duration-300 shadow-sm"
>
Shop Now
</button>
+10 -10
View File
@@ -153,7 +153,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
ref={navRef}
className={`fixed ${finalTopClassName} z-50 w-full border-b border-black/5 transition-all duration-300 ${
scrolled ? 'shadow-lg shadow-black/5' : 'shadow-none'
} bg-white/80 px-4 py-3.5 backdrop-blur-xl md:bg-spa-sage md:px-6 md:py-4 md:backdrop-blur-none`}
} bg-spa-light px-4 py-3.5 backdrop-blur-xl md:bg-spa-sage md:px-6 md:py-4 md:backdrop-blur-none`}
>
{/* Single-row layout: Logo (left) | Menu (center, desktop) | Actions (right) */}
<div className="w-full flex items-center justify-between gap-4">
@@ -193,7 +193,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
>
<Heart className="w-4 h-4 group-hover:text-rose-500 transition-colors" />
{wishlistCount > 0 && (
<span className="absolute -top-1 -right-1 bg-rose-500 text-white text-[9px] font-bold w-4 h-4 rounded-full flex items-center justify-center">
<span className="absolute -top-1 -right-1 bg-rose-500 text-spa-light text-[9px] font-bold w-4 h-4 rounded-full flex items-center justify-center">
{wishlistCount}
</span>
)}
@@ -206,7 +206,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
>
<ShoppingBag className="w-4 h-4 group-hover:text-spa-forest transition-colors" />
{cartCount > 0 && (
<span className="absolute -top-1 -right-1 bg-rose-500 text-white text-[9px] font-bold w-4 h-4 rounded-full flex items-center justify-center">
<span className="absolute -top-1 -right-1 bg-rose-500 text-spa-light text-[9px] font-bold w-4 h-4 rounded-full flex items-center justify-center">
{cartCount}
</span>
)}
@@ -215,12 +215,12 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
{isDesktop && (
<>
<div className="relative group flex items-center">
<button className="px-3 py-2 rounded-full text-[10px] font-bold transition-all text-spa-forest border border-spa-forest/30 hover:bg-spa-sage bg-white flex items-center gap-1.5 uppercase tracking-wider">
<button className="px-3 py-2 rounded-full text-[10px] font-bold transition-all text-spa-forest border border-spa-forest/30 hover:bg-spa-sage bg-spa-light flex items-center gap-1.5 uppercase tracking-wider">
<Globe className="w-3.5 h-3.5" strokeWidth={1.5} />
{LANGUAGES.find(l => i18n.language.startsWith(l.code))?.short || 'TH'}
</button>
<div className="absolute top-full right-0 pt-2 w-36 opacity-0 pointer-events-none group-hover:opacity-100 group-hover:pointer-events-auto transition-all duration-300">
<div className="bg-white/95 backdrop-blur-xl border border-spa-stone/10 rounded-xl overflow-hidden shadow-2xl p-1.5 space-y-0.5">
<div className="bg-spa-light backdrop-blur-xl border border-spa-stone/10 rounded-xl overflow-hidden shadow-2xl p-1.5 space-y-0.5">
{LANGUAGES.map(lang => {
const isActive = i18n.language.startsWith(lang.code)
return (
@@ -248,7 +248,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
/>
</Link>
<div className="absolute top-full right-0 pt-3 w-36 opacity-0 pointer-events-none group-hover:opacity-100 group-hover:pointer-events-auto transition-all duration-300">
<div className="bg-white/95 backdrop-blur-xl border border-spa-stone/10 rounded-xl overflow-hidden shadow-xl p-1">
<div className="bg-spa-light backdrop-blur-xl border border-spa-stone/10 rounded-xl overflow-hidden shadow-xl p-1">
<div className="px-3 py-2 border-b border-spa-stone/10 mb-1">
<p className="text-[10px] text-spa-stone/60 uppercase tracking-widest leading-tight truncate">{t('nav.signedInAs', 'Signed in as')}</p>
<p className="text-xs text-spa-forest font-bold truncate">{customer.displayName}</p>
@@ -271,7 +271,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
) : (
<button
onClick={loginLiff}
className="ml-2 px-4 py-2 rounded-full text-xs font-bold uppercase tracking-widest bg-[#00B900] text-white hover:bg-[#009900] transition-all duration-300 shadow-sm"
className="ml-2 px-4 py-2 rounded-full text-xs font-bold uppercase tracking-widest bg-[#00B900] text-spa-light hover:bg-[#009900] transition-all duration-300 shadow-sm"
>
{t('nav.login', 'LINE Login')}
</button>
@@ -317,7 +317,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
</div>
<form onSubmit={handleSearch}>
<div className="flex bg-white border-2 border-spa-stone/20 focus-within:border-spa-forest rounded-2xl overflow-hidden transition-colors shadow-sm">
<div className="flex bg-spa-light border-2 border-spa-stone/20 focus-within:border-spa-forest rounded-2xl overflow-hidden transition-colors shadow-sm">
<svg className="w-5 h-5 text-spa-stone/50 m-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
@@ -329,7 +329,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
className="bg-transparent border-none outline-none text-lg md:text-xl p-4 pl-0 w-full text-spa-forest placeholder-spa-stone/40"
autoFocus
/>
<button type="submit" className="bg-spa-forest text-white px-4 md:px-6 font-bold text-xs uppercase tracking-widest shrink-0 hover:bg-spa-stone transition-colors">
<button type="submit" className="bg-spa-forest text-spa-light px-4 md:px-6 font-bold text-xs uppercase tracking-widest shrink-0 hover:bg-spa-stone transition-colors">
Go
</button>
</div>
@@ -346,7 +346,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) {
onClick={() => setLangSheetOpen(false)}
/>
<div
className={`absolute bottom-0 left-0 right-0 bg-white rounded-t-3xl transition-transform duration-300 shadow-2xl pb-safe ${langSheetOpen ? 'translate-y-0' : 'translate-y-full'}`}
className={`absolute bottom-0 left-0 right-0 bg-spa-light rounded-t-3xl transition-transform duration-300 shadow-2xl pb-safe ${langSheetOpen ? 'translate-y-0' : 'translate-y-full'}`}
>
<div className="flex justify-center pt-3 pb-1">
<div className="w-12 h-1.5 bg-spa-stone/20 rounded-full" />
+4 -4
View File
@@ -57,13 +57,13 @@ export default function ProductCard({ product, enableQuickShop = false, category
(e.target as HTMLImageElement).style.display = 'none';
}}
/>
<div className="ui-chip absolute left-3 top-3 border-white/20 bg-white/90 px-2.5 py-1 text-[10px] text-spa-forest shadow-sm backdrop-blur-sm">
<div className="ui-chip absolute left-3 top-3 border-spa-light bg-spa-light px-2.5 py-1 text-[10px] text-spa-forest shadow-sm backdrop-blur-sm">
{displayCategoryName}
</div>
<button
type="button"
onClick={handleWishlistClick}
className="absolute right-3 top-3 z-10 rounded-full bg-white/90 p-2 shadow-sm backdrop-blur-sm transition-transform hover:scale-110 cursor-pointer"
className="absolute right-3 top-3 z-10 rounded-full bg-spa-light p-2 shadow-sm backdrop-blur-sm transition-transform hover:scale-110 cursor-pointer"
>
<Heart
className={`w-4 h-4 transition-colors ${isWished ? 'fill-rose-500 text-rose-500' : 'text-spa-stone/60 hover:text-rose-500'}`}
@@ -96,8 +96,8 @@ export default function ProductCard({ product, enableQuickShop = false, category
}}
className={`rounded-full border px-3 py-1 text-[10px] font-bold uppercase tracking-wider transition-all cursor-pointer ${
isSelected
? 'border-spa-forest bg-spa-forest text-white shadow-sm'
: 'border-spa-stone/10 bg-white text-spa-stone hover:border-spa-forest/30'
? 'border-spa-forest bg-spa-forest text-spa-light shadow-sm'
: 'border-spa-stone/10 bg-spa-light text-spa-stone hover:border-spa-forest/30'
}`}
>
{variant.size}
@@ -28,7 +28,7 @@ export default function ProductImageGallery({ images, fallback, alt = 'Product I
return (
<div className="space-y-4">
{/* Main Image */}
<div className="relative rounded-2xl overflow-hidden h-[480px] group bg-white shadow-sm border border-spa-stone/10 flex items-center justify-center">
<div className="relative rounded-2xl overflow-hidden h-[480px] group bg-spa-light shadow-sm border border-spa-stone/10 flex items-center justify-center">
<img
src={currentImageUrl}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700"
@@ -38,7 +38,7 @@ export default function ProductImageGallery({ images, fallback, alt = 'Product I
<div className="absolute inset-0 bg-gradient-to-t from-black/10 to-transparent pointer-events-none" />
{badgeText && (
<div className="absolute top-6 left-6 bg-white/90 backdrop-blur-sm px-3 py-1.5 rounded-full text-[10px] font-bold uppercase tracking-widest text-spa-forest shadow-sm pointer-events-none">
<div className="absolute top-6 left-6 bg-spa-light backdrop-blur-sm px-3 py-1.5 rounded-full text-[10px] font-bold uppercase tracking-widest text-spa-forest shadow-sm pointer-events-none">
{badgeText}
</div>
)}
@@ -48,7 +48,7 @@ export default function ProductImageGallery({ images, fallback, alt = 'Product I
<>
<button
onClick={handlePrev}
className="absolute left-4 top-1/2 -translate-y-1/2 w-10 h-10 bg-white/80 backdrop-blur-md rounded-full flex items-center justify-center text-spa-forest opacity-0 group-hover:opacity-100 transition-opacity hover:bg-white hover:scale-110 shadow-sm"
className="absolute left-4 top-1/2 -translate-y-1/2 w-10 h-10 bg-spa-light backdrop-blur-md rounded-full flex items-center justify-center text-spa-forest opacity-0 group-hover:opacity-100 transition-opacity hover:bg-spa-light hover:scale-110 shadow-sm"
aria-label="Previous image"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -57,7 +57,7 @@ export default function ProductImageGallery({ images, fallback, alt = 'Product I
</button>
<button
onClick={handleNext}
className="absolute right-4 top-1/2 -translate-y-1/2 w-10 h-10 bg-white/80 backdrop-blur-md rounded-full flex items-center justify-center text-spa-forest opacity-0 group-hover:opacity-100 transition-opacity hover:bg-white hover:scale-110 shadow-sm"
className="absolute right-4 top-1/2 -translate-y-1/2 w-10 h-10 bg-spa-light backdrop-blur-md rounded-full flex items-center justify-center text-spa-forest opacity-0 group-hover:opacity-100 transition-opacity hover:bg-spa-light hover:scale-110 shadow-sm"
aria-label="Next image"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+9 -9
View File
@@ -96,7 +96,7 @@ export default function ProductReviews({ productId }: { productId: number }) {
{/* List & Form */}
<div className="w-full md:w-2/3 space-y-8">
{customer ? (
<form onSubmit={handleSubmit} className="bg-white p-6 rounded-3xl border border-spa-stone/10 shadow-sm space-y-4">
<form onSubmit={handleSubmit} className="bg-spa-light p-6 rounded-3xl border border-spa-stone/10 shadow-sm space-y-4">
<h3 className="font-bold text-pop-black">Write a Review</h3>
<div className="flex gap-2">
{[1, 2, 3, 4, 5].map(star => (
@@ -115,7 +115,7 @@ export default function ProductReviews({ productId }: { productId: number }) {
<button
type="submit"
disabled={submitting}
className="px-6 py-2.5 bg-spa-forest text-white text-sm font-bold tracking-widest uppercase rounded-full hover:bg-spa-stone transition-all disabled:opacity-50"
className="px-6 py-2.5 bg-spa-forest text-spa-light text-sm font-bold tracking-widest uppercase rounded-full hover:bg-spa-stone transition-all disabled:opacity-50"
>
{submitting ? 'Submitting...' : 'Submit Review'}
</button>
@@ -135,8 +135,8 @@ export default function ProductReviews({ productId }: { productId: number }) {
onClick={() => { setFilterRating(null); setVisibleCount(3); }}
className={`flex-shrink-0 px-4 py-1.5 rounded-full text-xs font-bold transition-all border ${
filterRating === null
? 'bg-spa-stone text-white border-spa-stone'
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-stone/50'
? 'bg-spa-stone text-spa-light border-spa-stone'
: 'bg-spa-light text-spa-stone border-spa-stone/20 hover:border-spa-stone/50'
}`}
>
All ({reviews.length})
@@ -150,11 +150,11 @@ export default function ProductReviews({ productId }: { productId: number }) {
onClick={() => { setFilterRating(star); setVisibleCount(3); }}
className={`flex-shrink-0 flex items-center gap-1 px-4 py-1.5 rounded-full text-xs font-bold transition-all border ${
filterRating === star
? 'bg-spa-stone text-white border-spa-stone'
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-stone/50'
? 'bg-spa-stone text-spa-light border-spa-stone'
: 'bg-spa-light text-spa-stone border-spa-stone/20 hover:border-spa-stone/50'
}`}
>
{star} <Star className={`w-3 h-3 ${filterRating === star ? 'fill-white text-white' : 'fill-orange-400 text-orange-400'}`} /> ({count})
{star} <Star className={`w-3 h-3 ${filterRating === star ? 'fill-white text-spa-light' : 'fill-orange-400 text-orange-400'}`} /> ({count})
</button>
);
})}
@@ -174,7 +174,7 @@ export default function ProductReviews({ productId }: { productId: number }) {
{review.customer?.pictureUrl ? (
<img src={review.customer.pictureUrl} className="w-10 h-10 rounded-full object-cover" />
) : (
<div className="w-10 h-10 rounded-full bg-spa-stone/20 flex items-center justify-center text-white font-bold">
<div className="w-10 h-10 rounded-full bg-spa-stone/20 flex items-center justify-center text-spa-light font-bold">
{(review.customerName || 'A')[0].toUpperCase()}
</div>
)}
@@ -197,7 +197,7 @@ export default function ProductReviews({ productId }: { productId: number }) {
<div className="text-center pt-4">
<button
onClick={() => setVisibleCount(prev => prev + 5)}
className="px-6 py-2.5 border border-spa-stone/20 text-spa-stone text-xs font-bold tracking-widest uppercase rounded-full hover:border-spa-stone hover:text-pop-black transition-all bg-white"
className="px-6 py-2.5 border border-spa-stone/20 text-spa-stone text-xs font-bold tracking-widest uppercase rounded-full hover:border-spa-stone hover:text-pop-black transition-all bg-spa-light"
>
Show More Reviews
</button>
@@ -129,7 +129,7 @@ export default function ContactFormSection({ payload }: ContactFormSectionProps)
</p>
</div>
<div className="bg-white rounded-3xl shadow-xl shadow-spa-sand/50 p-8 md:p-12 border border-spa-sage/10">
<div className="bg-spa-light rounded-3xl shadow-xl shadow-spa-sand/50 p-8 md:p-12 border border-spa-sage/10">
{isSuccess ? (
<div className="text-center py-12">
<div className="w-16 h-16 bg-green-100 text-green-600 rounded-full flex items-center justify-center mx-auto mb-6">
@@ -192,10 +192,10 @@ export default function ContactFormSection({ payload }: ContactFormSectionProps)
<button
type="submit"
disabled={isSubmitting}
className="w-full py-4 px-6 bg-spa-sage hover:bg-spa-sage-dark text-white rounded-xl font-medium flex items-center justify-center gap-2 transition-colors disabled:opacity-70 disabled:cursor-not-allowed"
className="w-full py-4 px-6 bg-spa-sage hover:bg-spa-sage-dark text-spa-light rounded-xl font-medium flex items-center justify-center gap-2 transition-colors disabled:opacity-70 disabled:cursor-not-allowed"
>
{isSubmitting ? (
<span className="w-6 h-6 border-2 border-white/30 border-t-white rounded-full animate-spin" />
<span className="w-6 h-6 border-2 border-spa-light border-t-white rounded-full animate-spin" />
) : (
<>
<Send size={18} />
@@ -30,7 +30,7 @@ export default function ContactInfoSection({ payload }: ContactInfoSectionProps)
] as const;
return (
<section className="ui-section-band w-full bg-white px-4 md:px-8">
<section className="ui-section-band w-full bg-spa-light px-4 md:px-8">
<div className="ui-section-inner">
{title && (
<div className="mb-10 text-center">
@@ -78,7 +78,7 @@ export function ThaiAddressInput({ value, onChange }: ThaiAddressInputProps) {
if (focusedField !== field || results.length === 0) return null;
return (
<ul className="absolute z-50 w-full bg-white border border-spa-stone/20 rounded-lg mt-1 max-h-60 overflow-y-auto shadow-xl">
<ul className="absolute z-50 w-full bg-spa-light border border-spa-stone/20 rounded-lg mt-1 max-h-60 overflow-y-auto shadow-xl">
{results.map((item, idx) => (
<li
key={`${item.district}-${item.amphoe}-${item.province}-${item.zipcode}-${idx}`}
+18 -18
View File
@@ -99,11 +99,11 @@
}
.ui-section-subtitle {
@apply mx-auto max-w-2xl text-gray-500;
@apply mx-auto max-w-2xl text-spa-stone;
}
.ui-shell-card {
@apply rounded-3xl border border-spa-stone/10 bg-white shadow-brutal transition-all duration-300;
@apply rounded-3xl border border-spa-stone/10 bg-spa-light shadow-brutal transition-all duration-300;
}
.ui-shell-card-hover {
@@ -115,15 +115,15 @@
}
.ui-button-primary {
@apply inline-flex items-center justify-center rounded-full bg-spa-forest px-6 py-3 text-xs font-bold uppercase tracking-widest text-white transition-colors hover:bg-spa-forest/90;
@apply inline-flex items-center justify-center rounded-full bg-spa-forest px-6 py-3 text-xs font-bold uppercase tracking-widest text-spa-light transition-colors hover:bg-spa-forest/90;
}
.ui-button-secondary {
@apply inline-flex items-center justify-center rounded-full bg-white px-6 py-3 text-xs font-bold uppercase tracking-widest text-spa-forest transition-colors hover:bg-spa-sage;
@apply inline-flex items-center justify-center rounded-full bg-spa-light px-6 py-3 text-xs font-bold uppercase tracking-widest text-spa-forest transition-colors hover:bg-spa-sage;
}
.ui-input-shell {
@apply w-full rounded-full border border-white/10 bg-white/5 px-6 py-4 text-sm text-white outline-none transition placeholder:text-white/40 focus:border-spa-gold/80;
@apply w-full rounded-full border border-spa-light bg-spa-light px-6 py-4 text-sm text-spa-light outline-none transition placeholder:text-spa-light focus:border-spa-gold/80;
}
.ui-muted-text {
@@ -131,7 +131,7 @@
}
.ui-hero-shell {
@apply relative flex min-h-[90vh] items-center justify-center overflow-hidden bg-night-900 text-white md:aspect-[21/9] md:min-h-0;
@apply relative flex min-h-[90vh] items-center justify-center overflow-hidden bg-night-900 text-spa-light md:aspect-[21/9] md:min-h-0;
}
.ui-hero-overlay {
@@ -147,11 +147,11 @@
}
.ui-hero-title {
@apply font-serif text-5xl font-light leading-tight tracking-wide text-white drop-shadow-md md:text-7xl lg:text-8xl;
@apply font-serif text-5xl font-light leading-tight tracking-wide text-spa-light drop-shadow-md md:text-7xl lg:text-8xl;
}
.ui-hero-copy {
@apply mx-auto max-w-2xl pb-8 pt-4 text-lg font-light text-white/90 drop-shadow-md md:text-xl;
@apply mx-auto max-w-2xl pb-8 pt-4 text-lg font-light text-spa-light drop-shadow-md md:text-xl;
}
.ui-banner-shell {
@@ -163,19 +163,19 @@
}
.ui-banner-content {
@apply relative z-10 max-w-xl space-y-4 p-8 text-white md:p-16;
@apply relative z-10 max-w-xl space-y-4 p-8 text-spa-light md:p-16;
}
.ui-card-soft {
@apply rounded-2xl border border-spa-stone/10 bg-white shadow-sm;
@apply rounded-2xl border border-spa-stone/10 bg-spa-light shadow-sm;
}
.ui-dark-shell {
@apply bg-spa-forest px-6 py-20 text-white;
@apply bg-spa-forest px-6 py-20 text-spa-light;
}
.ui-dark-card {
@apply overflow-hidden rounded-3xl border border-white/5 bg-white/5;
@apply overflow-hidden rounded-3xl border border-spa-light bg-spa-light;
}
.ui-dark-card-title {
@@ -187,11 +187,11 @@
}
.ui-dark-link {
@apply inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-spa-gold transition-colors hover:text-white;
@apply inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-spa-gold transition-colors hover:text-spa-light;
}
.brutal-box {
@apply bg-white border border-gray-100 rounded-2xl shadow-brutal transition-all duration-300;
@apply bg-spa-light border border-spa-stone/20 rounded-2xl shadow-brutal transition-all duration-300;
}
.brutal-box-hover {
@@ -199,11 +199,11 @@
}
.brutal-button {
@apply px-8 py-4 bg-pop-pink text-white font-medium rounded-full shadow-brutal transition-all duration-300 hover:bg-pop-red hover:-translate-y-1 hover:shadow-brutal-hover;
@apply px-8 py-4 bg-pop-pink text-spa-light font-medium rounded-full shadow-brutal transition-all duration-300 hover:bg-pop-red hover:-translate-y-1 hover:shadow-brutal-hover;
}
.brutal-button-alt {
@apply px-8 py-4 bg-white text-pop-pink font-medium rounded-full border border-pop-pink shadow-brutal transition-all duration-300 hover:bg-pop-bg hover:-translate-y-1 hover:shadow-brutal-hover;
@apply px-8 py-4 bg-spa-light text-pop-pink font-medium rounded-full border border-pop-pink shadow-brutal transition-all duration-300 hover:bg-pop-bg hover:-translate-y-1 hover:shadow-brutal-hover;
}
}
@@ -217,11 +217,11 @@
}
::-webkit-scrollbar-thumb {
@apply bg-gray-300 rounded-full;
@apply bg-spa-sage rounded-full;
}
::-webkit-scrollbar-thumb:hover {
@apply bg-gray-400;
@apply bg-spa-sage;
}
/* Smooth Scrolling */
+4 -4
View File
@@ -49,13 +49,13 @@ export default function ArticleReaderPage() {
<main className="flex-1 pt-24 pb-20">
<article className="max-w-4xl mx-auto w-full animate-fade-in relative mt-8">
<Link to="/scent-guide" className="absolute -left-16 xl:-left-24 top-0 mt-8 hidden lg:flex p-4 bg-white shadow-sm border border-spa-stone/10 border border-spa-stone/10 rounded-full hover:bg-white/10 transition-colors">
<ArrowLeft className="w-5 h-5 text-slate-300" />
<Link to="/scent-guide" className="absolute -left-16 xl:-left-24 top-0 mt-8 hidden lg:flex p-4 bg-spa-light shadow-sm border border-spa-stone/10 border border-spa-stone/10 rounded-full hover:bg-spa-light transition-colors">
<ArrowLeft className="w-5 h-5 text-spa-stone" />
</Link>
{/* Header */}
<div className="text-center px-6 py-12 space-y-6">
<Link to="/scent-guide" className="lg:hidden text-slate-400 text-sm hover:text-white inline-flex items-center gap-2 mb-4">
<Link to="/scent-guide" className="lg:hidden text-spa-stone text-sm hover:text-spa-light inline-flex items-center gap-2 mb-4">
<ArrowLeft className="w-4 h-4" /> Go Back
</Link>
<p className="text-spa-forest uppercase tracking-[0.3em] font-bold text-xs">
@@ -68,7 +68,7 @@ export default function ArticleReaderPage() {
{/* Cover Image */}
{article.coverImage && (
<div className="w-full aspect-[16/7] bg-white md:rounded-[2rem] overflow-hidden shadow-2xl mb-16 border border-spa-stone/10">
<div className="w-full aspect-[16/7] bg-spa-light md:rounded-[2rem] overflow-hidden shadow-2xl mb-16 border border-spa-stone/10">
<img src={article.coverImage} alt={article.title} className="w-full h-full object-cover" />
</div>
)}
+7 -7
View File
@@ -132,15 +132,15 @@ export default function CategoryPage() {
<div className="max-w-7xl mx-auto">
{/* Breadcrumb */}
<div className="flex items-center gap-2 text-xs text-spa-sage/80 uppercase tracking-widest mb-4 font-semibold">
<Link to="/" className="hover:text-white transition-colors">Home</Link>
<Link to="/" className="hover:text-spa-light transition-colors">Home</Link>
<span>/</span>
<Link to="/shop" className="hover:text-white transition-colors">Shop</Link>
<Link to="/shop" className="hover:text-spa-light transition-colors">Shop</Link>
<span>/</span>
<span className="text-white">{typeof category?.name === 'string' ? category.name : (category?.name as any)?.[localStorage.getItem('app_lang') || 'en'] || (category?.name as any)?.en || '...'}</span>
<span className="text-spa-light">{typeof category?.name === 'string' ? category.name : (category?.name as any)?.[localStorage.getItem('app_lang') || 'en'] || (category?.name as any)?.en || '...'}</span>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-white">
<h1 className="text-4xl md:text-5xl font-bold text-spa-light">
{loading ? (
<div className="h-10 w-48 bg-white/20 animate-pulse rounded-lg" />
<div className="h-10 w-48 bg-spa-light animate-pulse rounded-lg" />
) : (
typeof category?.name === 'string' ? category.name : (category?.name as any)?.[i18n.language] || (category?.name as any)?.en || ''
)}
@@ -165,8 +165,8 @@ export default function CategoryPage() {
to={`/category/${cat.id}`}
className={`px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-widest transition-all duration-300 border ${
cat.id === category?.id
? 'bg-spa-forest text-white border-spa-forest shadow-md'
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
? 'bg-spa-forest text-spa-light border-spa-forest shadow-md'
: 'bg-spa-light text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
}`}
>
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.[localStorage.getItem('app_lang') || 'en'] || (cat.name as any)?.en || ''}
+6 -6
View File
@@ -338,7 +338,7 @@ export default function CheckoutPage() {
{/* Form Section */}
<div className="flex-1 space-y-8 order-2 lg:order-1">
<form id="checkout-form" onSubmit={handleSubmit} className="space-y-6">
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 space-y-6 shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 space-y-6 shadow-sm">
<h2 className="text-xl font-bold uppercase tracking-widest text-spa-forest border-b border-spa-stone/10 pb-4">{t('checkout.shippingInfo')}</h2>
<div className="grid md:grid-cols-2 gap-6">
@@ -433,20 +433,20 @@ export default function CheckoutPage() {
<button
type="submit"
disabled={loading || loadingSettings}
className="w-full py-4 px-6 bg-spa-forest text-white font-bold rounded-xl tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed flex lg:hidden justify-between items-center mt-4"
className="w-full py-4 px-6 bg-spa-forest text-spa-light font-bold rounded-xl tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed flex lg:hidden justify-between items-center mt-4"
>
<div className="flex items-center gap-2">
{loading && <Loader2 className="w-5 h-5 animate-spin" />}
<span>Proceed to Payment</span>
</div>
<span className="text-sm border-l border-white/20 pl-4">{formatPrice(total)}</span>
<span className="text-sm border-l border-spa-light pl-4">{formatPrice(total)}</span>
</button>
</form>
</div>
{/* Summary Section */}
<div className="lg:w-96 space-y-6 order-1 lg:order-2">
<div className="bg-white p-6 lg:p-8 rounded-2xl border border-spa-stone/10 shadow-sm sticky top-32 transition-all">
<div className="bg-spa-light p-6 lg:p-8 rounded-2xl border border-spa-stone/10 shadow-sm sticky top-32 transition-all">
<button
type="button"
onClick={() => setIsSummaryExpanded(!isSummaryExpanded)}
@@ -602,13 +602,13 @@ export default function CheckoutPage() {
form="checkout-form"
type="submit"
disabled={loading || loadingSettings}
className="w-full mt-8 py-4 px-6 bg-spa-forest text-white font-bold rounded-xl tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed hidden lg:flex justify-between items-center"
className="w-full mt-8 py-4 px-6 bg-spa-forest text-spa-light font-bold rounded-xl tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed hidden lg:flex justify-between items-center"
>
<div className="flex items-center gap-2">
{loading && <Loader2 className="w-5 h-5 animate-spin" />}
<span>Proceed to Payment</span>
</div>
<span className="text-sm border-l border-white/20 pl-4">{formatPrice(total)}</span>
<span className="text-sm border-l border-spa-light pl-4">{formatPrice(total)}</span>
</button>
</div>
</div>
+2 -2
View File
@@ -139,7 +139,7 @@ export default function CouponsPage() {
{coupons.map(coupon => (
<div
key={coupon.id}
className="group relative bg-white border border-spa-stone/10 rounded-3xl overflow-hidden hover:border-spa-forest transition-all duration-500 shadow-sm hover:shadow-md"
className="group relative bg-spa-light border border-spa-stone/10 rounded-3xl overflow-hidden hover:border-spa-forest transition-all duration-500 shadow-sm hover:shadow-md"
>
{/* Decoration */}
<div className="absolute top-0 right-0 w-32 h-32 bg-spa-sage/20 blur-3xl rounded-full -translate-y-1/2 translate-x-1/2" />
@@ -184,7 +184,7 @@ export default function CouponsPage() {
<button
onClick={() => handleUseNow(coupon.code)}
className="w-full py-4 bg-spa-forest text-white hover:bg-spa-stone font-bold rounded-xl flex items-center justify-center gap-2 transition-all duration-300 shadow-sm"
className="w-full py-4 bg-spa-forest text-spa-light hover:bg-spa-stone font-bold rounded-xl flex items-center justify-center gap-2 transition-all duration-300 shadow-sm"
>
ใช้คูปองนี้เลย
<ArrowRight className="w-4 h-4" />
+8 -8
View File
@@ -2,7 +2,7 @@ import { Link } from 'react-router-dom'
export default function NotFoundPage() {
return (
<div className="min-h-screen flex items-center justify-center px-6 bg-white">
<div className="min-h-screen flex items-center justify-center px-6 bg-spa-light">
{/* Background glow */}
<div className="absolute inset-0 pointer-events-none overflow-hidden">
<div className="absolute top-1/3 left-1/2 -translate-x-1/2 -translate-y-1/2 w-96 h-96 bg-spa-forest/10 rounded-full blur-3xl" />
@@ -22,7 +22,7 @@ export default function NotFoundPage() {
<div className="space-y-3">
<h1 className="text-3xl font-bold">Page Not Found</h1>
<p className="text-slate-400 leading-relaxed">
<p className="text-spa-stone leading-relaxed">
The page you're looking for seems to have drifted away like morning mist. Let's guide you back to serenity.
</p>
</div>
@@ -30,23 +30,23 @@ export default function NotFoundPage() {
<div className="flex flex-col sm:flex-row gap-4 justify-center pt-2">
<Link
to="/"
className="px-8 py-3.5 bg-white text-spa-forest font-bold rounded-lg tracking-widest uppercase hover:bg-spa-forest text-white hover:shadow-[0_0_25px_rgba(102,252,241,0.4)] transition-all duration-500 text-sm"
className="px-8 py-3.5 bg-spa-light text-spa-forest font-bold rounded-lg tracking-widest uppercase hover:bg-spa-forest text-spa-light hover:shadow-[0_0_25px_rgba(102,252,241,0.4)] transition-all duration-500 text-sm"
>
Go Home
</Link>
<Link
to="/shop"
className="px-8 py-3.5 bg-white shadow-sm border border-spa-stone/10 text-white font-bold rounded-lg tracking-widest uppercase hover:bg-white/10 transition-all duration-300 border border-spa-stone/10 text-sm"
className="px-8 py-3.5 bg-spa-light shadow-sm border border-spa-stone/10 text-spa-light font-bold rounded-lg tracking-widest uppercase hover:bg-spa-light transition-all duration-300 border border-spa-stone/10 text-sm"
>
Browse Products
</Link>
</div>
<div className="pt-4 border-t border-spa-stone/10">
<div className="flex justify-center gap-6 text-xs text-slate-500">
<Link to="/scent-guide" className="hover:text-white transition-colors">Scent Guide</Link>
<Link to="/faq" className="hover:text-white transition-colors">FAQ</Link>
<Link to="/contact" className="hover:text-white transition-colors">Contact</Link>
<div className="flex justify-center gap-6 text-xs text-spa-stone">
<Link to="/scent-guide" className="hover:text-spa-light transition-colors">Scent Guide</Link>
<Link to="/faq" className="hover:text-spa-light transition-colors">FAQ</Link>
<Link to="/contact" className="hover:text-spa-light transition-colors">Contact</Link>
</div>
</div>
</div>
+17 -17
View File
@@ -258,7 +258,7 @@ export default function OrderSuccessPage() {
</div>
{/* Order Summary */}
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 space-y-6 shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 space-y-6 shadow-sm">
<h2 className="text-sm font-bold uppercase tracking-widest text-spa-forest border-b border-spa-stone/10 pb-4">Order Items</h2>
<div className="space-y-4">
{order.items.map(item => (
@@ -293,13 +293,13 @@ export default function OrderSuccessPage() {
{order.status === 'PENDING_PAYMENT' ? (
<div className="space-y-8">
{/* Payment Method Selector */}
<div className="bg-white p-4 rounded-2xl border border-spa-stone/10 shadow-sm flex flex-col md:flex-row gap-3">
<div className="bg-spa-light p-4 rounded-2xl border border-spa-stone/10 shadow-sm flex flex-col md:flex-row gap-3">
<button
onClick={() => setPaymentMethod('bank')}
className={`flex-1 py-4 px-6 rounded-xl font-bold flex items-center justify-center gap-3 border transition-all ${
paymentMethod === 'bank'
? 'bg-spa-forest text-white border-spa-forest shadow-sm'
: 'bg-white text-spa-stone hover:bg-spa-light border-spa-stone/10'
? 'bg-spa-forest text-spa-light border-spa-forest shadow-sm'
: 'bg-spa-light text-spa-stone hover:bg-spa-light border-spa-stone/10'
}`}
>
<Landmark className="w-5 h-5" />
@@ -309,8 +309,8 @@ export default function OrderSuccessPage() {
onClick={() => setPaymentMethod('promptpay')}
className={`flex-1 py-4 px-6 rounded-xl font-bold flex items-center justify-center gap-3 border transition-all ${
paymentMethod === 'promptpay'
? 'bg-spa-forest text-white border-spa-forest shadow-sm'
: 'bg-white text-spa-stone hover:bg-spa-light border-spa-stone/10'
? 'bg-spa-forest text-spa-light border-spa-forest shadow-sm'
: 'bg-spa-light text-spa-stone hover:bg-spa-light border-spa-stone/10'
}`}
>
<QrCode className="w-5 h-5" />
@@ -320,8 +320,8 @@ export default function OrderSuccessPage() {
onClick={() => setPaymentMethod('card')}
className={`flex-1 py-4 px-6 rounded-xl font-bold flex items-center justify-center gap-3 border transition-all ${
paymentMethod === 'card'
? 'bg-spa-forest text-white border-spa-forest shadow-sm'
: 'bg-white text-spa-stone hover:bg-spa-light border-spa-stone/10'
? 'bg-spa-forest text-spa-light border-spa-forest shadow-sm'
: 'bg-spa-light text-spa-stone hover:bg-spa-light border-spa-stone/10'
}`}
>
<CreditCard className="w-5 h-5" />
@@ -332,7 +332,7 @@ export default function OrderSuccessPage() {
{/* Bank Transfer Layout */}
{paymentMethod === 'bank' && settings && (
<div className="space-y-8">
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 text-center space-y-6 relative overflow-hidden shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 text-center space-y-6 relative overflow-hidden shadow-sm">
<div className="absolute top-0 inset-x-0 h-1 bg-gradient-to-r from-transparent via-spa-forest to-transparent opacity-50" />
<h2 className="text-xs uppercase font-bold tracking-widest text-spa-stone/80">Payment Required</h2>
<div className="text-3xl font-bold text-spa-forest">{formatPrice(order.totalAmount)}</div>
@@ -348,7 +348,7 @@ export default function OrderSuccessPage() {
</div>
<button
onClick={copyToClipboard}
className="p-2 bg-white rounded-lg hover:bg-spa-stone/10 border border-spa-stone/20 transition-colors shrink-0 shadow-sm"
className="p-2 bg-spa-light rounded-lg hover:bg-spa-stone/10 border border-spa-stone/20 transition-colors shrink-0 shadow-sm"
title="Copy account number"
>
{copied ? <CheckCircle2 className="w-5 h-5 text-emerald-500" /> : <Copy className="w-5 h-5 text-spa-stone/80" />}
@@ -362,7 +362,7 @@ export default function OrderSuccessPage() {
<p className="text-xs text-spa-stone font-medium">Please transfer the exact amount and upload your slip below.</p>
</div>
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 space-y-6 shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 space-y-6 shadow-sm">
<h2 className="text-sm font-bold uppercase tracking-widest text-spa-forest border-b border-spa-stone/10 pb-4">Payment Slip Verification</h2>
{order.paymentSlipUrl ? (
<div className="flex flex-col items-center justify-center space-y-4 py-4">
@@ -404,7 +404,7 @@ export default function OrderSuccessPage() {
{/* PromptPay Layout */}
{paymentMethod === 'promptpay' && (
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 text-center space-y-6 relative overflow-hidden shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 text-center space-y-6 relative overflow-hidden shadow-sm">
<div className="absolute top-0 inset-x-0 h-1 bg-gradient-to-r from-transparent via-spa-forest to-transparent opacity-50" />
<h2 className="text-xs uppercase font-bold tracking-widest text-spa-stone/80">PromptPay QR Code</h2>
<div className="text-3xl font-bold text-spa-forest">{formatPrice(order.totalAmount)}</div>
@@ -414,7 +414,7 @@ export default function OrderSuccessPage() {
<button
onClick={handleGeneratePromptPay}
disabled={generatingQr}
className="px-8 py-4 bg-spa-forest text-white font-bold rounded-xl tracking-widest uppercase hover:bg-spa-stone transition-all duration-300 disabled:opacity-50 flex items-center justify-center gap-3 mx-auto"
className="px-8 py-4 bg-spa-forest text-spa-light font-bold rounded-xl tracking-widest uppercase hover:bg-spa-stone transition-all duration-300 disabled:opacity-50 flex items-center justify-center gap-3 mx-auto"
>
{generatingQr ? <Loader2 className="w-5 h-5 animate-spin" /> : <QrCode className="w-5 h-5" />}
<span>สร้างคิวอาร์โค้ด PromptPay</span>
@@ -422,7 +422,7 @@ export default function OrderSuccessPage() {
</div>
) : (
<div className="space-y-6 max-w-sm mx-auto">
<div className="bg-white p-4 rounded-xl border border-spa-stone/20 inline-block shadow-sm">
<div className="bg-spa-light p-4 rounded-xl border border-spa-stone/20 inline-block shadow-sm">
<img src={qrCodeUrl} alt="PromptPay QR Code" className="w-64 h-64 object-contain mx-auto" />
</div>
@@ -452,7 +452,7 @@ export default function OrderSuccessPage() {
{/* Credit Card Layout */}
{paymentMethod === 'card' && (
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 space-y-6 relative overflow-hidden shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 space-y-6 relative overflow-hidden shadow-sm">
<div className="absolute top-0 inset-x-0 h-1 bg-gradient-to-r from-transparent via-spa-forest to-transparent opacity-50" />
<div className="text-center space-y-2">
<h2 className="text-xs uppercase font-bold tracking-widest text-spa-stone/80">Credit / Debit Card</h2>
@@ -527,7 +527,7 @@ export default function OrderSuccessPage() {
<button
type="submit"
disabled={payingCard}
className="w-full py-4 bg-spa-forest text-white font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone transition-all duration-300 disabled:opacity-50 flex items-center justify-center gap-2 mt-4"
className="w-full py-4 bg-spa-forest text-spa-light font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone transition-all duration-300 disabled:opacity-50 flex items-center justify-center gap-2 mt-4"
>
{payingCard ? <Loader2 className="w-5 h-5 animate-spin" /> : <CreditCard className="w-5 h-5" />}
<span>ชำระเงิน {formatPrice(order.totalAmount)}</span>
@@ -537,7 +537,7 @@ export default function OrderSuccessPage() {
)}
</div>
) : (
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 text-center space-y-6 shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 text-center space-y-6 shadow-sm">
<div className="w-16 h-16 bg-emerald-500/10 rounded-full flex items-center justify-center border border-emerald-500/20 mx-auto">
<CheckCircle2 className="w-8 h-8 text-emerald-500" />
</div>
+9 -9
View File
@@ -220,12 +220,12 @@ export default function ProductDetailPage() {
onClick={() => setSelectedVariant(i)}
className={`px-5 py-2.5 rounded-lg text-sm font-bold uppercase tracking-widest transition-all duration-300 border ${
selectedVariant === i
? 'bg-spa-forest text-white border-spa-forest shadow-md'
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
? 'bg-spa-forest text-spa-light border-spa-forest shadow-md'
: 'bg-spa-light text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
}`}
>
{v.size}
<span className={`block text-[10px] mt-0.5 ${selectedVariant === i ? 'text-white/80' : 'text-spa-stone/60'}`}>
<span className={`block text-[10px] mt-0.5 ${selectedVariant === i ? 'text-spa-light' : 'text-spa-stone/60'}`}>
{formatPrice(v.price)}
</span>
</button>
@@ -237,11 +237,11 @@ export default function ProductDetailPage() {
<div className="hidden md:flex gap-4">
<button
onClick={handleAddToCart}
className="flex-1 py-4 bg-spa-forest text-white font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300"
className="flex-1 py-4 bg-spa-forest text-spa-light font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300"
>
{t('cart.addToCart')}
</button>
<button className="bg-white border border-spa-stone/20 text-spa-stone p-4 rounded-lg hover:border-spa-forest hover:text-spa-forest shadow-sm transition-all">
<button className="bg-spa-light border border-spa-stone/20 text-spa-stone p-4 rounded-lg hover:border-spa-forest hover:text-spa-forest shadow-sm transition-all">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
</svg>
@@ -322,7 +322,7 @@ export default function ProductDetailPage() {
<Footer categories={categories} />
{/* Mobile Sticky Add to Cart Bar */}
<div className="md:hidden fixed bottom-0 left-0 right-0 p-4 bg-white/95 backdrop-blur-xl border-t border-spa-stone/10 z-40 animate-fade-in flex flex-col gap-3 shadow-[0_-10px_30px_rgba(0,0,0,0.05)]">
<div className="md:hidden fixed bottom-0 left-0 right-0 p-4 bg-spa-light backdrop-blur-xl border-t border-spa-stone/10 z-40 animate-fade-in flex flex-col gap-3 shadow-[0_-10px_30px_rgba(0,0,0,0.05)]">
{/* Mobile Variant Selector */}
{product.variants && product.variants.length > 1 && (
@@ -333,8 +333,8 @@ export default function ProductDetailPage() {
onClick={() => setSelectedVariant(i)}
className={`flex-shrink-0 px-4 py-2 rounded-lg text-[10px] font-bold uppercase tracking-widest transition-all border whitespace-nowrap ${
selectedVariant === i
? 'bg-spa-forest border-spa-forest text-white'
: 'bg-white border-spa-stone/20 text-spa-stone'
? 'bg-spa-forest border-spa-forest text-spa-light'
: 'bg-spa-light border-spa-stone/20 text-spa-stone'
}`}
>
{v.size}
@@ -354,7 +354,7 @@ export default function ProductDetailPage() {
</div>
<button
onClick={handleAddToCart}
className="flex-1 py-3.5 bg-spa-forest text-white font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone shadow-sm transition-all flex justify-center items-center gap-2"
className="flex-1 py-3.5 bg-spa-forest text-spa-light font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone shadow-sm transition-all flex justify-center items-center gap-2"
>
{t('cart.addToCart')}
</button>
+13 -13
View File
@@ -303,7 +303,7 @@ export default function ProfilePage() {
{!customer ? (
/* Login CTA screen */
<div className="max-w-md mx-auto text-center space-y-8 py-20 animate-fade-in bg-white p-10 rounded-3xl border border-spa-stone/10 shadow-sm mt-10">
<div className="max-w-md mx-auto text-center space-y-8 py-20 animate-fade-in bg-spa-light p-10 rounded-3xl border border-spa-stone/10 shadow-sm mt-10">
<div className="w-20 h-20 bg-spa-light rounded-full flex items-center justify-center mx-auto border border-spa-stone/10 shadow-inner">
<User className="w-10 h-10 text-spa-stone" />
</div>
@@ -320,7 +320,7 @@ export default function ProfilePage() {
alert('LINE LIFF System is initializing. Please refresh.')
}
}}
className="w-full py-4 bg-spa-forest hover:bg-spa-stone text-white font-bold rounded-xl tracking-widest uppercase transition-all duration-300 shadow-sm flex items-center justify-center gap-3"
className="w-full py-4 bg-spa-forest hover:bg-spa-stone text-spa-light font-bold rounded-xl tracking-widest uppercase transition-all duration-300 shadow-sm flex items-center justify-center gap-3"
>
<Award className="w-5 h-5" />
<span>เข้าสู่ระบบผ่าน LINE</span>
@@ -331,7 +331,7 @@ export default function ProfilePage() {
/* Logged In Dashboard Layout */
<div className="space-y-10 animate-fade-in">
{/* Header Profile Banner */}
<div className="bg-white rounded-2xl border border-spa-stone/10 p-5 sm:p-6 flex flex-col sm:flex-row justify-between items-center sm:items-center gap-4 shadow-sm relative overflow-hidden">
<div className="bg-spa-light rounded-2xl border border-spa-stone/10 p-5 sm:p-6 flex flex-col sm:flex-row justify-between items-center sm:items-center gap-4 shadow-sm relative overflow-hidden">
<div className="absolute top-0 inset-x-0 h-1 bg-gradient-to-r from-spa-sage via-spa-forest to-spa-stone opacity-40" />
{/* User Avatar & Info */}
@@ -459,7 +459,7 @@ export default function ProfilePage() {
<Loader2 className="w-8 h-8 text-spa-forest animate-spin" />
</div>
) : orders.length === 0 ? (
<div className="text-center py-16 bg-white rounded-2xl border border-spa-stone/10 space-y-4 shadow-sm">
<div className="text-center py-16 bg-spa-light rounded-2xl border border-spa-stone/10 space-y-4 shadow-sm">
<Package className="w-12 h-12 text-spa-stone/40 mx-auto" />
<div>
<p className="font-bold text-pop-black">ไม่มีประวัติการสั่งซื้อ</p>
@@ -467,7 +467,7 @@ export default function ProfilePage() {
</div>
<Link
to="/shop"
className="inline-block px-6 py-2.5 bg-spa-forest hover:bg-spa-stone text-white font-bold rounded-lg text-xs uppercase tracking-wider transition-colors shadow-sm"
className="inline-block px-6 py-2.5 bg-spa-forest hover:bg-spa-stone text-spa-light font-bold rounded-lg text-xs uppercase tracking-wider transition-colors shadow-sm"
>
ไปหน้าช้อปปิ้ง
</Link>
@@ -477,7 +477,7 @@ export default function ProfilePage() {
{orders.map(order => (
<div
key={order.id}
className="bg-white border border-spa-stone/10 rounded-2xl p-6 shadow-sm hover:border-spa-stone transition-all duration-300 space-y-4"
className="bg-spa-light border border-spa-stone/10 rounded-2xl p-6 shadow-sm hover:border-spa-stone transition-all duration-300 space-y-4"
>
{/* Card Header */}
<div className="flex flex-col md:flex-row justify-between md:items-center gap-3 border-b border-spa-stone/10 pb-4">
@@ -550,7 +550,7 @@ export default function ProfilePage() {
resetAddressForm()
setShowAddressForm(true)
}}
className="px-4 py-2 bg-spa-forest hover:bg-spa-stone text-white font-bold rounded-lg text-xs uppercase tracking-wider transition-colors shadow-sm flex items-center gap-2"
className="px-4 py-2 bg-spa-forest hover:bg-spa-stone text-spa-light font-bold rounded-lg text-xs uppercase tracking-wider transition-colors shadow-sm flex items-center gap-2"
>
<Plus className="w-3.5 h-3.5" />
<span>เพิ่มที่อยู่ใหม่</span>
@@ -560,7 +560,7 @@ export default function ProfilePage() {
{/* Address Creation/Editing Form */}
{showAddressForm && (
<form onSubmit={handleAddressSubmit} className="bg-white border border-spa-stone/15 p-6 rounded-2xl shadow-sm space-y-5 animate-slide-down">
<form onSubmit={handleAddressSubmit} className="bg-spa-light border border-spa-stone/15 p-6 rounded-2xl shadow-sm space-y-5 animate-slide-down">
<h3 className="text-sm font-bold uppercase tracking-widest text-spa-forest border-b border-spa-stone/10 pb-2">
{editingAddress ? 'แก้ไขที่อยู่จัดส่ง' : 'เพิ่มที่อยู่จัดส่งใหม่'}
</h3>
@@ -636,7 +636,7 @@ export default function ProfilePage() {
<button
type="submit"
disabled={submittingAddress}
className="px-5 py-2.5 bg-spa-forest hover:bg-spa-stone text-white font-bold rounded-lg text-xs uppercase tracking-wider transition-colors disabled:opacity-50 flex items-center gap-2"
className="px-5 py-2.5 bg-spa-forest hover:bg-spa-stone text-spa-light font-bold rounded-lg text-xs uppercase tracking-wider transition-colors disabled:opacity-50 flex items-center gap-2"
>
{submittingAddress && <Loader2 className="w-3.5 h-3.5 animate-spin" />}
<span>บันทึกที่อยู่</span>
@@ -650,7 +650,7 @@ export default function ProfilePage() {
<Loader2 className="w-8 h-8 text-spa-forest animate-spin" />
</div>
) : addresses.length === 0 ? (
<div className="text-center py-16 bg-white rounded-2xl border border-spa-stone/10 space-y-4 shadow-sm">
<div className="text-center py-16 bg-spa-light rounded-2xl border border-spa-stone/10 space-y-4 shadow-sm">
<MapPin className="w-12 h-12 text-spa-stone/40 mx-auto" />
<div>
<p className="font-bold text-pop-black">ไม่มีข้อมูลที่อยู่จัดส่ง</p>
@@ -662,7 +662,7 @@ export default function ProfilePage() {
{addresses.map(addr => (
<div
key={addr.id}
className={`bg-white border rounded-2xl p-5 shadow-sm space-y-4 transition-all duration-300 relative ${
className={`bg-spa-light border rounded-2xl p-5 shadow-sm space-y-4 transition-all duration-300 relative ${
addr.isDefault
? 'border-spa-forest ring-1 ring-spa-forest/20'
: 'border-spa-stone/10 hover:border-spa-stone'
@@ -729,7 +729,7 @@ export default function ProfilePage() {
<span>ข้อมูลติดต่อสมาชิก</span>
</h2>
<form onSubmit={handleSettingsSubmit} className="bg-white border border-spa-stone/10 rounded-2xl p-6 shadow-sm max-w-lg space-y-5">
<form onSubmit={handleSettingsSubmit} className="bg-spa-light border border-spa-stone/10 rounded-2xl p-6 shadow-sm max-w-lg space-y-5">
{settingsSuccess && (
<div className="p-4 bg-emerald-500/10 border border-emerald-500/20 text-emerald-600 font-bold rounded-xl text-xs text-center flex items-center justify-center gap-2">
<Check className="w-4 h-4" />
@@ -763,7 +763,7 @@ export default function ProfilePage() {
<button
type="submit"
disabled={submittingSettings}
className="w-full py-3 bg-spa-forest hover:bg-spa-stone text-white font-bold rounded-lg text-xs uppercase tracking-widest transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
className="w-full py-3 bg-spa-forest hover:bg-spa-stone text-spa-light font-bold rounded-lg text-xs uppercase tracking-widest transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
>
{submittingSettings ? <Loader2 className="w-4 h-4 animate-spin" /> : <Check className="w-4 h-4" />}
<span>บันทึกข้อมูลติดต่อ</span>
+7 -7
View File
@@ -59,10 +59,10 @@ export default function ScentGuidePage() {
/>
</div>
) : (
<div className="pt-32 pb-16 px-6 text-center space-y-4 border-b border-spa-stone/10 bg-white">
<div className="pt-32 pb-16 px-6 text-center space-y-4 border-b border-spa-stone/10 bg-spa-light">
<p className="text-spa-forest uppercase tracking-[0.4em] text-xs font-semibold opacity-70">Journal</p>
<h1 className="text-5xl font-bold">Scent Guide</h1>
<p className="text-slate-400 max-w-lg mx-auto">
<p className="text-spa-stone max-w-lg mx-auto">
Explore our collection of articles, guides, and sensory knowledge.
</p>
</div>
@@ -70,7 +70,7 @@ export default function ScentGuidePage() {
<div className="flex-1 max-w-7xl mx-auto px-6 py-16 w-full">
{articles.length === 0 ? (
<div className="text-center text-slate-500 italic py-20">
<div className="text-center text-spa-stone italic py-20">
Articles coming soon. Check back later!
</div>
) : (
@@ -81,12 +81,12 @@ export default function ScentGuidePage() {
to={`/article/${article.slug}`}
className="group block bg-pop-bg rounded-2xl overflow-hidden border border-spa-stone/10 hover:border-spa-forest transition-all duration-300 hover:-translate-y-1 hover:shadow-2xl flex flex-col"
>
<div className="aspect-[4/3] bg-white overflow-hidden shrink-0">
<div className="aspect-[4/3] bg-spa-light overflow-hidden shrink-0">
{article.coverImage ? (
<img src={article.coverImage} alt={article.title} className="w-full h-full object-cover opacity-80 group-hover:opacity-100 group-hover:scale-105 transition-all duration-500" />
) : (
<div className="w-full h-full bg-white/5 flex items-center justify-center">
<span className="text-slate-600 text-sm tracking-widest uppercase">No Image</span>
<div className="w-full h-full bg-spa-light flex items-center justify-center">
<span className="text-spa-stone text-sm tracking-widest uppercase">No Image</span>
</div>
)}
</div>
@@ -96,7 +96,7 @@ export default function ScentGuidePage() {
</p>
<h3 className="text-xl font-bold leading-tight group-hover:text-spa-forest transition-colors">{article.title}</h3>
{/* Remove HTML tags for purely excerpt preview */}
<div className="text-slate-400 text-sm line-clamp-3" dangerouslySetInnerHTML={{ __html: article.content }} />
<div className="text-spa-stone text-sm line-clamp-3" dangerouslySetInnerHTML={{ __html: article.content }} />
</div>
</Link>
))}
+3 -3
View File
@@ -100,7 +100,7 @@ export default function SearchPage() {
<h1 className="text-5xl font-bold text-pop-black">Search Products</h1>
<form onSubmit={handleSubmit} className="relative">
<div className="flex bg-white border border-spa-stone/20 rounded-2xl overflow-hidden shadow-sm focus-within:border-spa-forest focus-within:ring-1 focus-within:ring-spa-forest transition-all">
<div className="flex bg-spa-light border border-spa-stone/20 rounded-2xl overflow-hidden shadow-sm focus-within:border-spa-forest focus-within:ring-1 focus-within:ring-spa-forest transition-all">
<svg className="w-5 h-5 text-spa-stone m-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
@@ -114,7 +114,7 @@ export default function SearchPage() {
/>
<button
type="submit"
className="bg-spa-forest text-white px-8 font-bold text-xs uppercase tracking-widest hover:bg-spa-stone transition-colors shrink-0"
className="bg-spa-forest text-spa-light px-8 font-bold text-xs uppercase tracking-widest hover:bg-spa-stone transition-colors shrink-0"
>
Search
</button>
@@ -127,7 +127,7 @@ export default function SearchPage() {
<Link
key={cat.id}
to={`/search?q=${encodeURIComponent(typeof cat.name === 'string' ? cat.name : (cat.name as any)?.[i18n.language] || (cat.name as any)?.en || '')}`}
className="bg-white border border-spa-stone/20 px-4 py-1.5 rounded-full text-xs font-medium text-spa-stone hover:border-spa-forest hover:text-spa-forest shadow-sm transition-all duration-300"
className="bg-spa-light border border-spa-stone/20 px-4 py-1.5 rounded-full text-xs font-medium text-spa-stone hover:border-spa-forest hover:text-spa-forest shadow-sm transition-all duration-300"
>
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.[i18n.language] || (cat.name as any)?.en || ''}
</Link>
+6 -6
View File
@@ -154,7 +154,7 @@ export default function ShopPage() {
{/* Search */}
<div className="max-w-md mx-auto mt-6">
<div className="flex bg-white border border-spa-stone/20 rounded-xl overflow-hidden shadow-sm focus-within:border-spa-forest focus-within:ring-1 focus-within:ring-spa-forest transition-all">
<div className="flex bg-spa-light border border-spa-stone/20 rounded-xl overflow-hidden shadow-sm focus-within:border-spa-forest focus-within:ring-1 focus-within:ring-spa-forest transition-all">
<svg className="w-4 h-4 text-spa-stone m-3.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
@@ -173,7 +173,7 @@ export default function ShopPage() {
{/* Render Search bar below Hero block if Hero is configured */}
{heroSections.length > 0 && (
<div className="max-w-md mx-auto mt-8 px-6">
<div className="flex bg-white border border-spa-stone/20 rounded-xl overflow-hidden shadow-sm focus-within:border-spa-forest focus-within:ring-1 focus-within:ring-spa-forest transition-all">
<div className="flex bg-spa-light border border-spa-stone/20 rounded-xl overflow-hidden shadow-sm focus-within:border-spa-forest focus-within:ring-1 focus-within:ring-spa-forest transition-all">
<svg className="w-4 h-4 text-spa-stone m-3.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
@@ -195,8 +195,8 @@ export default function ShopPage() {
onClick={() => setActiveCategory(null)}
className={`px-5 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all duration-300 border ${
activeCategory === null
? 'bg-spa-forest text-white border-spa-forest shadow-md'
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
? 'bg-spa-forest text-spa-light border-spa-forest shadow-md'
: 'bg-spa-light text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
}`}
>
All
@@ -207,8 +207,8 @@ export default function ShopPage() {
onClick={() => setActiveCategory(cat.id)}
className={`px-5 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all duration-300 border ${
activeCategory === cat.id
? 'bg-spa-forest text-white border-spa-forest shadow-md'
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
? 'bg-spa-forest text-spa-light border-spa-forest shadow-md'
: 'bg-spa-light text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
}`}
>
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.[i18n.language] || (cat.name as any)?.en || ''}
+6 -6
View File
@@ -144,7 +144,7 @@ export default function TrackOrderPage() {
<div className="grid md:grid-cols-2 gap-12">
{/* Tracking Form */}
<div className="bg-white p-8 rounded-2xl border border-spa-stone/10 space-y-6 self-start shadow-sm">
<div className="bg-spa-light p-8 rounded-2xl border border-spa-stone/10 space-y-6 self-start shadow-sm">
<h2 className="text-lg font-bold uppercase tracking-widest border-b border-spa-stone/10 pb-4 flex items-center gap-2 text-spa-forest">
<Search className="w-5 h-5" /> Manual Search
</h2>
@@ -183,7 +183,7 @@ export default function TrackOrderPage() {
<button
type="submit"
disabled={loading}
className="w-full py-4 bg-spa-forest text-white font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300 disabled:opacity-50 flex items-center justify-center gap-2"
className="w-full py-4 bg-spa-forest text-spa-light font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone hover:shadow-lg transition-all duration-300 disabled:opacity-50 flex items-center justify-center gap-2"
>
{loading ? <Loader2 className="w-5 h-5 animate-spin" /> : 'Find Order'}
</button>
@@ -214,7 +214,7 @@ export default function TrackOrderPage() {
<Link
key={order.id}
to={`/order/${order.id}`}
className="flex justify-between items-center p-5 bg-white rounded-xl border border-spa-stone/10 shadow-sm hover:border-spa-forest transition-all group"
className="flex justify-between items-center p-5 bg-spa-light rounded-xl border border-spa-stone/10 shadow-sm hover:border-spa-forest transition-all group"
>
<div>
<div className="flex items-center gap-2 mb-1">
@@ -235,7 +235,7 @@ export default function TrackOrderPage() {
<p className="text-[10px] text-spa-stone uppercase">{order.items.length} items</p>
</div>
<div className="w-10 h-10 rounded-full bg-spa-light flex items-center justify-center group-hover:bg-spa-forest transition-colors shrink-0">
<ChevronRight className="w-5 h-5 text-spa-stone/80 group-hover:text-white" />
<ChevronRight className="w-5 h-5 text-spa-stone/80 group-hover:text-spa-light" />
</div>
</div>
</Link>
@@ -254,14 +254,14 @@ export default function TrackOrderPage() {
<Link
key={id}
to={`/order/${id}`}
className="flex justify-between items-center p-5 bg-white rounded-xl border border-spa-stone/10 shadow-sm hover:border-spa-forest transition-all group"
className="flex justify-between items-center p-5 bg-spa-light rounded-xl border border-spa-stone/10 shadow-sm hover:border-spa-forest transition-all group"
>
<div>
<p className="text-xs text-spa-stone/80 uppercase tracking-widest mb-1 font-semibold">Order</p>
<p className="text-xl font-bold font-mono text-spa-forest">#{id.toString().padStart(4, '0')}</p>
</div>
<div className="w-10 h-10 rounded-full bg-spa-light flex items-center justify-center group-hover:bg-spa-forest transition-colors">
<ChevronRight className="w-5 h-5 text-spa-stone/80 group-hover:text-white" />
<ChevronRight className="w-5 h-5 text-spa-stone/80 group-hover:text-spa-light" />
</div>
</Link>
))}
+2 -2
View File
@@ -76,7 +76,7 @@ export default function WishlistPage() {
)}
{items.length === 0 ? (
<div className="text-center py-24 bg-white shadow-sm border border-spa-stone/10 rounded-3xl max-w-2xl mx-auto space-y-6">
<div className="text-center py-24 bg-spa-light shadow-sm border border-spa-stone/10 rounded-3xl max-w-2xl mx-auto space-y-6">
<div className="w-20 h-20 bg-spa-light rounded-full flex items-center justify-center mx-auto">
<Heart className="w-10 h-10 text-spa-stone/30" />
</div>
@@ -85,7 +85,7 @@ export default function WishlistPage() {
<div className="pt-4">
<Link
to="/shop"
className="inline-block px-8 py-3.5 bg-spa-forest text-white font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone transition-all duration-300 shadow-sm"
className="inline-block px-8 py-3.5 bg-spa-forest text-spa-light font-bold rounded-lg tracking-widest uppercase hover:bg-spa-stone transition-all duration-300 shadow-sm"
>
Browse Shop
</Link>
+1 -1
View File
@@ -105,7 +105,7 @@ export default async function AboutPage({ params }: { params: Promise<{ lang: st
<h2 className="text-4xl font-bold text-text-main">Ready to find your scent?</h2>
<p className="mx-auto max-w-md text-muted-text">Let our Scent Guide help you discover the perfect blend for your moment.</p>
<div className="flex flex-col justify-center gap-4 pt-4 sm:flex-row">
<Link href="/scent-guide" className="rounded-full bg-text-main px-10 py-4 font-bold uppercase tracking-widest text-white transition hover:bg-brand-primary">
<Link href="/scent-guide" className="rounded-full bg-text-main px-10 py-4 font-bold uppercase tracking-widest text-surface-card transition hover:bg-brand-primary">
Take the Scent Guide
</Link>
<Link href="/shop" className="rounded-full border border-brand-primary bg-surface-card px-10 py-4 font-bold uppercase tracking-widest text-brand-primary transition hover:bg-surface-page">
@@ -124,7 +124,7 @@ export default async function CategoryPage({ params }: { params: Promise<{ id: s
href={`/category/${item.id}`}
className={`rounded-full px-5 py-2 text-xs font-bold uppercase tracking-widest transition ${
isActive
? 'bg-text-main text-white'
? 'bg-text-main text-surface-card'
: 'border border-line-primary/20 bg-surface-card text-muted-text hover:border-brand-primary hover:text-brand-primary'
}`}
>
+2 -2
View File
@@ -75,7 +75,7 @@ export default async function CouponsPage({ params }: { params: Promise<{ lang:
<p className="mb-6 text-muted-text">กรุณากลับมาตรวจสอบโปรโมชั่นใหม่ในภายหลัง</p>
<Link
href="/shop"
className="inline-flex rounded-full bg-brand-primary px-8 py-3 font-bold text-white transition hover:bg-brand-primary-hover"
className="inline-flex rounded-full bg-brand-primary px-8 py-3 font-bold text-surface-card transition hover:bg-brand-primary-hover"
>
ไปช้อปปิ้งกันก่อน
</Link>
@@ -116,7 +116,7 @@ export default async function CouponsPage({ params }: { params: Promise<{ lang:
<Link
href={`/shop?coupon=${encodeURIComponent(coupon.code)}`}
className="flex w-full items-center justify-center gap-2 rounded-full bg-text-main py-4 font-bold text-white transition hover:bg-brand-primary"
className="flex w-full items-center justify-center gap-2 rounded-full bg-text-main py-4 font-bold text-surface-card transition hover:bg-brand-primary"
>
ช้อปพร้อมใช้คูปองเลย
<ArrowRight className="h-4 w-4" />
+2 -2
View File
@@ -83,7 +83,7 @@ export default function FaqPage() {
onClick={() => setActiveCategory(category)}
className={`flex items-center gap-2 rounded-full px-5 py-2 text-xs font-bold uppercase tracking-widest transition-all duration-300 ${
activeCategory === category
? 'ui-tab-button-active bg-text-main text-white shadow-card'
? 'ui-tab-button-active bg-text-main text-surface-card shadow-card'
: 'ui-tab-button-inactive border border-line-primary/20 bg-surface-card hover:border-brand-primary hover:text-brand-primary'
}`}
>
@@ -119,7 +119,7 @@ export default function FaqPage() {
<div className="text-3xl">💬</div>
<h3 className="text-xl font-bold text-text-main">Still have questions?</h3>
<p className="text-sm text-muted-text">Our team is here to help — usually responds within 2 hours.</p>
<Link href="/contact" className="inline-block rounded-full bg-text-main px-8 py-3 text-xs font-bold uppercase tracking-widest text-white transition-colors duration-300 hover:bg-brand-primary">
<Link href="/contact" className="inline-block rounded-full bg-text-main px-8 py-3 text-xs font-bold uppercase tracking-widest text-surface-card transition-colors duration-300 hover:bg-brand-primary">
Contact Us
</Link>
</div>
@@ -182,7 +182,7 @@ export default async function OrderStatusPage({ params }: { params: Promise<{ id
<Link href="/track" className="rounded-full bg-surface-card px-6 py-3 font-semibold text-text-main shadow-card transition hover:text-brand-primary">
ค้นหาออเดอร์อื่น
</Link>
<Link href="/shop" className="rounded-full bg-brand-primary px-6 py-3 font-semibold text-white transition hover:bg-brand-primary-hover">
<Link href="/shop" className="rounded-full bg-brand-primary px-6 py-3 font-semibold text-surface-card transition hover:bg-brand-primary-hover">
กลับไปช้อปต่อ
</Link>
</div>
+1 -1
View File
@@ -57,7 +57,7 @@ export default async function SearchPage({ searchParams, params }: { searchParam
placeholder="Search by scent or product name..."
className="min-w-0 flex-1 px-5 py-3 text-sm text-text-main outline-none placeholder:text-muted-text/70"
/>
<button className="bg-text-main px-6 py-3 text-sm font-bold uppercase tracking-widest text-white transition hover:bg-brand-primary">
<button className="bg-text-main px-6 py-3 text-sm font-bold uppercase tracking-widest text-surface-card transition hover:bg-brand-primary">
Search
</button>
</form>
+1 -1
View File
@@ -61,7 +61,7 @@ export default async function ShopPage({ searchParams, params }: { searchParams:
<div className="mx-auto max-w-7xl space-y-10 px-6 py-12">
<div className="flex flex-wrap gap-3">
<Link className="rounded-full bg-text-main px-5 py-2 text-xs font-bold uppercase tracking-widest text-white transition hover:bg-brand-primary" href="/shop">
<Link className="rounded-full bg-text-main px-5 py-2 text-xs font-bold uppercase tracking-widest text-surface-card transition hover:bg-brand-primary" href="/shop">
All
</Link>
{categories.map((category) => {
+36 -36
View File
@@ -10,7 +10,7 @@
--color-brand-soft: #D8BFD8;
--color-surface-page: #FFF0F5;
--color-surface-nav-rest: #F9F8F5;
--color-surface-card: #FFFFFF;
--color-surface-card: var(--color-surface-card);
--color-text-main: #333333;
--color-muted-text: #666666;
--color-line-primary: #00B900;
@@ -91,7 +91,7 @@
@layer components {
.brutal-box {
@apply bg-white border border-gray-100 rounded-2xl shadow-brutal transition-all duration-300;
@apply bg-surface-card border border-line-primary/20 rounded-2xl shadow-brutal transition-all duration-300;
}
.brutal-box-hover {
@@ -99,15 +99,15 @@
}
.brutal-button {
@apply px-8 py-4 bg-brand-primary text-white font-medium rounded-full shadow-brutal transition-all duration-300 hover:bg-brand-primary-hover hover:-translate-y-1 hover:shadow-brutal-hover;
@apply px-8 py-4 bg-brand-primary text-surface-card font-medium rounded-full shadow-brutal transition-all duration-300 hover:bg-brand-primary-hover hover:-translate-y-1 hover:shadow-brutal-hover;
}
.brutal-button-alt {
@apply px-8 py-4 bg-white text-brand-primary font-medium rounded-full border border-brand-primary shadow-brutal transition-all duration-300 hover:bg-surface-page hover:-translate-y-1 hover:shadow-brutal-hover;
@apply px-8 py-4 bg-surface-card text-brand-primary font-medium rounded-full border border-brand-primary shadow-brutal transition-all duration-300 hover:bg-surface-page hover:-translate-y-1 hover:shadow-brutal-hover;
}
.ui-card {
@apply rounded-2xl border border-gray-100 bg-surface-card shadow-card transition-all duration-300;
@apply rounded-2xl border border-line-primary/20 bg-surface-card shadow-card transition-all duration-300;
}
.ui-card-hover {
@@ -115,15 +115,15 @@
}
.ui-button-primary {
@apply inline-flex items-center justify-center rounded-full bg-text-main px-6 py-3 text-xs font-bold uppercase tracking-widest text-white transition-colors hover:bg-brand-primary;
@apply inline-flex items-center justify-center rounded-full bg-text-main px-6 py-3 text-xs font-bold uppercase tracking-widest text-surface-card transition-colors hover:bg-brand-primary;
}
.ui-button-brand {
@apply inline-flex items-center justify-center rounded-full bg-brand-primary px-6 py-3 text-xs font-bold uppercase tracking-widest text-white transition-colors hover:bg-brand-primary-hover;
@apply inline-flex items-center justify-center rounded-full bg-brand-primary px-6 py-3 text-xs font-bold uppercase tracking-widest text-surface-card transition-colors hover:bg-brand-primary-hover;
}
.ui-button-line {
@apply inline-flex items-center justify-center rounded-full bg-line-primary px-4 py-2 text-xs font-bold uppercase tracking-widest text-white shadow-sm transition-colors hover:bg-line-primary-hover;
@apply inline-flex items-center justify-center rounded-full bg-line-primary px-4 py-2 text-xs font-bold uppercase tracking-widest text-surface-card shadow-sm transition-colors hover:bg-line-primary-hover;
}
.ui-icon-button {
@@ -135,11 +135,11 @@
}
.ui-nav-chip {
@apply flex items-center gap-1.5 rounded-full border border-brand-primary/30 bg-white px-3 py-2 text-[10px] font-bold uppercase tracking-wider text-text-main transition-all hover:bg-surface-page hover:text-brand-primary;
@apply flex items-center gap-1.5 rounded-full border border-brand-primary/30 bg-surface-card px-3 py-2 text-[10px] font-bold uppercase tracking-wider text-text-main transition-all hover:bg-surface-page hover:text-brand-primary;
}
.ui-nav-panel {
@apply overflow-hidden rounded-xl border border-text-main/10 bg-white/95 shadow-2xl backdrop-blur-xl;
@apply overflow-hidden rounded-xl border border-text-main/10 bg-surface-card shadow-2xl backdrop-blur-xl;
}
.ui-menu-link {
@@ -159,11 +159,11 @@
}
.ui-muted-text {
@apply text-gray-600;
@apply text-muted-text;
}
.ui-input-shell {
@apply rounded-2xl border border-gray-200 bg-surface-page text-text-main outline-none transition focus:border-brand-primary focus:ring-2 focus:ring-brand-primary/20;
@apply rounded-2xl border border-line-primary/20 bg-surface-page text-text-main outline-none transition focus:border-brand-primary focus:ring-2 focus:ring-brand-primary/20;
}
.ui-footer-link {
@@ -171,7 +171,7 @@
}
.ui-footer-social {
@apply flex h-9 w-9 items-center justify-center rounded-full border border-gray-200 bg-surface-page text-[10px] font-bold text-text-main transition-all duration-300 hover:border-brand-primary hover:bg-brand-primary hover:text-white;
@apply flex h-9 w-9 items-center justify-center rounded-full border border-line-primary/20 bg-surface-page text-[10px] font-bold text-text-main transition-all duration-300 hover:border-brand-primary hover:bg-brand-primary hover:text-surface-card;
}
.ui-section-band {
@@ -187,11 +187,11 @@
}
.ui-section-subtitle {
@apply text-gray-500;
@apply text-muted-text;
}
.ui-section-card {
@apply rounded-3xl bg-white shadow-card;
@apply rounded-3xl bg-surface-card shadow-card;
}
.ui-section-card-muted {
@@ -215,7 +215,7 @@
justify-content: center;
overflow: hidden;
background: var(--color-text-main);
color: #fff;
color: var(--color-surface-card);
}
.ui-hero-overlay {
@@ -236,7 +236,7 @@
}
.ui-hero-title {
color: #fff;
color: var(--color-surface-card);
font-family: var(--font-display-locale);
font-size: 3rem;
font-weight: 300;
@@ -274,7 +274,7 @@
align-items: center;
gap: 0.5rem;
padding: 1rem 2rem;
color: #fff;
color: var(--color-surface-card);
font-size: 0.875rem;
font-weight: 500;
letter-spacing: 0.1em;
@@ -308,7 +308,7 @@
z-index: 10;
max-width: 36rem;
padding: 2rem;
color: #fff;
color: var(--color-surface-card);
}
.ui-banner-content > * + * {
@@ -318,7 +318,7 @@
.ui-section-dark {
background: var(--color-text-main);
padding: 5rem 1.5rem;
color: #fff;
color: var(--color-surface-card);
}
.ui-section-dark-card {
@@ -329,7 +329,7 @@
}
.ui-section-dark-card-title {
color: #fff;
color: var(--color-surface-card);
font-size: 2.25rem;
font-weight: 600;
line-height: 2.5rem;
@@ -389,7 +389,7 @@
}
.ui-panel {
@apply rounded-3xl bg-white shadow-card;
@apply rounded-3xl bg-surface-card shadow-card;
}
.ui-panel-muted {
@@ -397,11 +397,11 @@
}
.ui-panel-border {
@apply rounded-3xl border border-gray-100 bg-white shadow-card;
@apply rounded-3xl border border-line-primary/20 bg-surface-card shadow-card;
}
.ui-panel-header {
@apply flex items-center gap-3 border-b border-gray-100 pb-5;
@apply flex items-center gap-3 border-b border-line-primary/20 pb-5;
}
.ui-panel-title {
@@ -409,31 +409,31 @@
}
.ui-panel-subtitle {
@apply text-sm text-gray-500;
@apply text-sm text-muted-text;
}
.ui-form-label {
@apply text-xs font-bold uppercase tracking-[0.18em] text-gray-500;
@apply text-xs font-bold uppercase tracking-[0.18em] text-muted-text;
}
.ui-form-shell {
@apply w-full rounded-2xl border border-gray-200 bg-surface-page px-4 py-3 text-sm text-text-main outline-none transition focus:border-brand-primary focus:ring-2 focus:ring-brand-primary/20;
@apply w-full rounded-2xl border border-line-primary/20 bg-surface-page px-4 py-3 text-sm text-text-main outline-none transition focus:border-brand-primary focus:ring-2 focus:ring-brand-primary/20;
}
.ui-form-shell-light {
@apply w-full rounded-2xl border border-gray-200 bg-white px-4 py-3 text-sm text-text-main outline-none transition focus:border-brand-primary focus:ring-2 focus:ring-brand-primary/20;
@apply w-full rounded-2xl border border-line-primary/20 bg-surface-card px-4 py-3 text-sm text-text-main outline-none transition focus:border-brand-primary focus:ring-2 focus:ring-brand-primary/20;
}
.ui-form-inline-button {
@apply inline-flex items-center justify-center gap-2 rounded-full bg-text-main px-6 py-4 text-sm font-bold uppercase tracking-[0.16em] text-white transition hover:bg-brand-primary disabled:cursor-not-allowed disabled:opacity-60;
@apply inline-flex items-center justify-center gap-2 rounded-full bg-text-main px-6 py-4 text-sm font-bold uppercase tracking-[0.16em] text-surface-card transition hover:bg-brand-primary disabled:cursor-not-allowed disabled:opacity-60;
}
.ui-form-inline-button-sm {
@apply inline-flex items-center justify-center gap-2 rounded-full bg-text-main px-5 py-2 text-sm font-semibold text-white transition hover:bg-brand-primary disabled:cursor-not-allowed disabled:opacity-60;
@apply inline-flex items-center justify-center gap-2 rounded-full bg-text-main px-5 py-2 text-sm font-semibold text-surface-card transition hover:bg-brand-primary disabled:cursor-not-allowed disabled:opacity-60;
}
.ui-form-secondary-button {
@apply rounded-full border border-gray-200 px-5 py-2 text-sm font-semibold text-gray-600 transition hover:text-brand-primary;
@apply rounded-full border border-line-primary/20 px-5 py-2 text-sm font-semibold text-muted-text transition hover:text-brand-primary;
}
.ui-form-danger-button {
@@ -441,7 +441,7 @@
}
.ui-form-checkbox {
@apply h-4 w-4 rounded border-gray-300 text-brand-primary;
@apply h-4 w-4 rounded border-line-primary/20 text-brand-primary;
}
.ui-status-badge {
@@ -523,7 +523,7 @@
}
.ui-tab-button-inactive {
@apply text-gray-500 hover:text-text-main;
@apply text-muted-text hover:text-text-main;
}
.ui-tab-count {
@@ -531,7 +531,7 @@
}
.ui-empty-panel {
@apply rounded-3xl bg-white px-6 py-16 text-center shadow-card;
@apply rounded-3xl bg-surface-card px-6 py-16 text-center shadow-card;
}
}
@@ -545,11 +545,11 @@
}
::-webkit-scrollbar-thumb {
@apply bg-gray-300 rounded-full;
@apply bg-surface-nav-rest rounded-full;
}
::-webkit-scrollbar-thumb:hover {
@apply bg-gray-400;
@apply bg-surface-nav-rest;
}
/* Smooth Scrolling */
@@ -70,12 +70,12 @@ export default function AddToCartSection({ product }: Props) {
onClick={() => setSelectedVariant(index)}
className={`rounded-xl border px-5 py-3 text-sm font-bold uppercase tracking-widest transition ${
selectedVariant === index
? 'border-brand-primary bg-brand-primary text-white shadow-card'
? 'border-brand-primary bg-brand-primary text-surface-card shadow-card'
: 'border-line-primary/20 bg-surface-card text-muted-text hover:border-brand-primary hover:text-brand-primary'
}`}
>
{variant.size}
<span className={`mt-1 block text-[10px] ${selectedVariant === index ? 'text-white/80' : 'text-muted-text/70'}`}>
<span className={`mt-1 block text-[10px] ${selectedVariant === index ? 'text-surface-card' : 'text-muted-text/70'}`}>
{formatPrice(variant.price)}
</span>
</button>
@@ -124,7 +124,7 @@ export default function AddToCartSection({ product }: Props) {
onClick={() => setSelectedVariant(index)}
className={`flex-shrink-0 rounded-full border px-4 py-2 text-[10px] font-bold uppercase tracking-widest transition ${
selectedVariant === index
? 'border-brand-primary bg-brand-primary text-white'
? 'border-brand-primary bg-brand-primary text-surface-card'
: 'border-line-primary/20 bg-surface-card text-muted-text'
}`}
>
+1 -1
View File
@@ -83,7 +83,7 @@ export default function CartDrawer() {
<span className="text-brand-primary">{formatPrice(getCartTotal())}</span>
</div>
<p className="text-center text-xs text-muted-text">{t('cart.shippingNote')}</p>
<Link href="/checkout" onClick={() => toggleCart(false)} className="block w-full rounded-full bg-text-main py-4 text-center text-sm font-bold uppercase tracking-widest text-white transition hover:bg-brand-primary">
<Link href="/checkout" onClick={() => toggleCart(false)} className="block w-full rounded-full bg-text-main py-4 text-center text-sm font-bold uppercase tracking-widest text-surface-card transition hover:bg-brand-primary">
{t('cart.proceed')}
</Link>
</div>
@@ -401,7 +401,7 @@ export default function CheckoutClient() {
<ShoppingBag className="mx-auto h-14 w-14 text-brand-primary" />
<h2 className="mt-5 text-3xl font-semibold text-text-main">ตะกร้าสินค้าว่าง</h2>
<p className="mt-3 text-muted-text">เลือกสินค้าที่คุณชอบก่อน แล้วกลับมายืนยันคำสั่งซื้อที่หน้านี้ได้เลย</p>
<Link href="/shop" className="mt-8 inline-flex rounded-full bg-text-main px-8 py-4 text-sm font-bold uppercase tracking-[0.16em] text-white transition hover:bg-brand-primary">
<Link href="/shop" className="mt-8 inline-flex rounded-full bg-text-main px-8 py-4 text-sm font-bold uppercase tracking-[0.16em] text-surface-card transition hover:bg-brand-primary">
กลับไปเลือกสินค้า
</Link>
</div>
@@ -642,7 +642,7 @@ export default function CheckoutClient() {
type="button"
onClick={applyCoupon}
disabled={couponLoading || !couponCode.trim()}
className="rounded-2xl bg-text-main px-4 py-3 text-xs font-bold uppercase tracking-widest text-white transition hover:bg-brand-primary disabled:opacity-50"
className="rounded-2xl bg-text-main px-4 py-3 text-xs font-bold uppercase tracking-widest text-surface-card transition hover:bg-brand-primary disabled:opacity-50"
>
{couponLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : 'ใช้'}
</button>
@@ -756,7 +756,7 @@ export default function CheckoutClient() {
type="submit"
form="checkout-form"
disabled={submitting || loadingSettings}
className="hidden w-full items-center justify-between rounded-full bg-text-main px-6 py-4 text-sm font-bold uppercase tracking-[0.16em] text-white transition hover:bg-brand-primary disabled:cursor-not-allowed disabled:opacity-60 lg:flex"
className="hidden w-full items-center justify-between rounded-full bg-text-main px-6 py-4 text-sm font-bold uppercase tracking-[0.16em] text-surface-card transition hover:bg-brand-primary disabled:cursor-not-allowed disabled:opacity-60 lg:flex"
>
<span className="flex items-center gap-2">
{submitting && <Loader2 className="h-5 w-5 animate-spin" />}
+3 -3
View File
@@ -231,7 +231,7 @@ export default function Navbar({ categories = [], initialMenu = [], settings = n
>
<Heart className="h-4 w-4 transition-colors" />
{wishlistCount > 0 && (
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-brand-primary text-[9px] font-bold text-white">
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-brand-primary text-[9px] font-bold text-surface-card">
{wishlistCount}
</span>
)}
@@ -247,7 +247,7 @@ export default function Navbar({ categories = [], initialMenu = [], settings = n
>
<ShoppingBag className="h-4 w-4 transition-colors" />
{cartCount > 0 && (
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-brand-primary text-[9px] font-bold text-white">
<span className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-brand-primary text-[9px] font-bold text-surface-card">
{cartCount}
</span>
)}
@@ -353,7 +353,7 @@ export default function Navbar({ categories = [], initialMenu = [], settings = n
className="w-full border-none bg-transparent p-4 pl-0 text-lg text-text-main outline-none placeholder:text-text-main/35 md:text-xl"
autoFocus
/>
<button type="submit" className="shrink-0 bg-text-main px-4 text-xs font-bold uppercase tracking-widest text-white transition-colors hover:bg-brand-primary md:px-6">
<button type="submit" className="shrink-0 bg-text-main px-4 text-xs font-bold uppercase tracking-widest text-surface-card transition-colors hover:bg-brand-primary md:px-6">
Go
</button>
</div>
@@ -294,7 +294,7 @@ export default function ProfileClient() {
<button
type="button"
onClick={handleLineLogin}
className="mt-8 flex w-full items-center justify-center gap-3 rounded-full bg-line-primary px-6 py-4 text-sm font-bold uppercase tracking-[0.16em] text-white transition hover:bg-line-primary-hover"
className="mt-8 flex w-full items-center justify-center gap-3 rounded-full bg-line-primary px-6 py-4 text-sm font-bold uppercase tracking-[0.16em] text-surface-card transition hover:bg-line-primary-hover"
>
<Award className="h-5 w-5" />
เข้าสู่ระบบผ่าน LINE
@@ -435,7 +435,7 @@ export default function ProfileClient() {
สมุดที่อยู่จัดส่ง
</h2>
{!showAddressForm && (
<button type="button" onClick={() => handleStartAddress()} className="inline-flex items-center justify-center gap-2 rounded-full bg-text-main px-5 py-3 text-xs font-bold uppercase tracking-[0.16em] text-white transition hover:bg-brand-primary">
<button type="button" onClick={() => handleStartAddress()} className="inline-flex items-center justify-center gap-2 rounded-full bg-text-main px-5 py-3 text-xs font-bold uppercase tracking-[0.16em] text-surface-card transition hover:bg-brand-primary">
<Plus className="h-4 w-4" />
เพิ่มที่อยู่ใหม่
</button>
@@ -474,7 +474,7 @@ export default function ProfileClient() {
<button type="button" onClick={resetAddressForm} className="ui-form-secondary-button">
ยกเลิก
</button>
<button type="submit" disabled={submittingAddress} className="inline-flex items-center gap-2 rounded-full bg-brand-primary px-5 py-2 text-sm font-semibold text-white disabled:opacity-60">
<button type="submit" disabled={submittingAddress} className="inline-flex items-center gap-2 rounded-full bg-brand-primary px-5 py-2 text-sm font-semibold text-surface-card disabled:opacity-60">
{submittingAddress && <Loader2 className="h-4 w-4 animate-spin" />}
บันทึกที่อยู่
</button>
@@ -534,7 +534,7 @@ export default function ProfileClient() {
)}
<TextInput label="อีเมล" value={settingsForm.email} onChange={(email) => setSettingsForm((current) => ({ ...current, email }))} type="email" />
<TextInput label="เบอร์โทรศัพท์" value={settingsForm.phone} onChange={(phone) => setSettingsForm((current) => ({ ...current, phone }))} type="tel" />
<button type="submit" disabled={submittingSettings} className="inline-flex w-full items-center justify-center gap-2 rounded-full bg-brand-primary px-6 py-3 text-sm font-bold uppercase tracking-[0.16em] text-white disabled:opacity-60">
<button type="submit" disabled={submittingSettings} className="inline-flex w-full items-center justify-center gap-2 rounded-full bg-brand-primary px-6 py-3 text-sm font-bold uppercase tracking-[0.16em] text-surface-card disabled:opacity-60">
{submittingSettings ? <Loader2 className="h-4 w-4 animate-spin" /> : <Check className="h-4 w-4" />}
บันทึกข้อมูลติดต่อ
</button>
@@ -598,7 +598,7 @@ function EmptyPanel({
<h3 className="text-xl font-semibold text-text-main">{title}</h3>
<p className="mx-auto mt-2 max-w-md text-sm text-muted-text">{description}</p>
{actionHref && actionText && (
<Link href={actionHref} className="mt-6 inline-flex rounded-full bg-brand-primary px-6 py-3 text-sm font-bold text-white">
<Link href={actionHref} className="mt-6 inline-flex rounded-full bg-brand-primary px-6 py-3 text-sm font-bold text-surface-card">
{actionText}
</Link>
)}
@@ -174,7 +174,7 @@ export default function TrackOrderClient() {
<p className="text-xs font-bold uppercase tracking-[0.22em] text-muted-text/70">Order</p>
<p className="mt-1 font-mono text-2xl font-bold text-text-main">{orderLabel(id)}</p>
</div>
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-surface-page text-text-main transition group-hover:bg-brand-primary group-hover:text-white">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-surface-page text-text-main transition group-hover:bg-brand-primary group-hover:text-surface-card">
<ChevronRight className="h-5 w-5" />
</div>
</Link>
@@ -21,7 +21,7 @@ export default function WishlistClient() {
</p>
<Link
href="/shop"
className="mt-8 inline-flex rounded-full bg-brand-primary px-8 py-3 text-sm font-bold uppercase tracking-[0.18em] text-white transition hover:bg-brand-primary-hover"
className="mt-8 inline-flex rounded-full bg-brand-primary px-8 py-3 text-sm font-bold uppercase tracking-[0.18em] text-surface-card transition hover:bg-brand-primary-hover"
>
Browse Shop
</Link>
@@ -80,7 +80,7 @@ function AnnouncementBar({ payload, lang }: { payload: Record<string, unknown>,
return (
<section
className={`announcement-bar absolute left-0 top-0 z-[60] w-full overflow-hidden px-4 py-3 text-center text-sm font-semibold tracking-wide ${backgroundColor ? '' : 'bg-text-main'} ${textColor ? '' : 'text-white'}`}
className={`announcement-bar absolute left-0 top-0 z-[60] w-full overflow-hidden px-4 py-3 text-center text-sm font-semibold tracking-wide ${backgroundColor ? '' : 'bg-text-main'} ${textColor ? '' : 'text-surface-card'}`}
style={{ backgroundColor, color: textColor }}
>
<Swiper
@@ -125,7 +125,7 @@ function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang
<div className="relative z-10 mx-auto mt-16 w-full max-w-4xl space-y-6 px-8 text-center md:mt-0">
<div className="space-y-6">
{tagline && (
<p className="text-xs font-semibold uppercase tracking-[0.3em] text-white drop-shadow-md md:text-sm">
<p className="text-xs font-semibold uppercase tracking-[0.3em] text-surface-card drop-shadow-md md:text-sm">
{tagline}
</p>
)}
@@ -209,10 +209,10 @@ function CategoriesSection({
className="absolute inset-0 h-full w-full object-cover transition duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-t from-text-main/65 to-transparent" />
<div className="absolute bottom-5 left-5 right-5 text-white">
<div className="absolute bottom-5 left-5 right-5 text-surface-card">
<span className="block text-lg font-semibold">{name}</span>
{category._count && (
<span className="text-sm text-white/80">
<span className="text-sm text-surface-card">
{category._count.products} {productsLabel[resolvedLang] ?? productsLabel.en}
</span>
)}
@@ -290,7 +290,7 @@ function BannerSection({ payload, lang }: { payload: Record<string, unknown>, la
<div className="ui-banner-overlay" />
<div className="ui-banner-content">
{title && <h2 className="text-3xl font-semibold md:text-5xl">{title}</h2>}
{description && <p className="text-white/90">{description}</p>}
{description && <p className="text-surface-card">{description}</p>}
{buttonText && <span className="inline-flex rounded-full bg-surface-card px-6 py-3 font-semibold text-text-main">{buttonText}</span>}
</div>
</div>
@@ -332,8 +332,8 @@ function NewsletterSection({ payload, lang }: { payload: Record<string, unknown>
<section className="ui-section-dark">
<div className="mx-auto grid max-w-5xl gap-8 md:grid-cols-[1fr_auto] md:items-end">
<div className="space-y-3">
<h2 className="text-3xl font-semibold text-white md:text-4xl">{title}</h2>
{description && <p className="max-w-2xl text-white/75">{description}</p>}
<h2 className="text-3xl font-semibold text-surface-card md:text-4xl">{title}</h2>
{description && <p className="max-w-2xl text-surface-card">{description}</p>}
</div>
<form className="flex flex-col gap-3 sm:flex-row">
<input className="ui-form-shell min-w-0 rounded-full" placeholder={placeholder} type="email" />
@@ -381,7 +381,7 @@ function EditorialTileSection({ payload, lang }: { payload: Record<string, unkno
<div className="h-px w-14 bg-brand-primary" />
{description && <p className="whitespace-pre-line text-base leading-relaxed text-muted-text md:text-lg" style={{ color: textColor }}>{description}</p>}
{buttonText && buttonLink && (
<Link href={buttonLink} className="ui-section-link inline-flex rounded-full border border-current px-8 py-3 text-xs font-bold uppercase tracking-[0.22em] transition hover:bg-brand-primary hover:text-white">
<Link href={buttonLink} className="ui-section-link inline-flex rounded-full border border-current px-8 py-3 text-xs font-bold uppercase tracking-[0.22em] transition hover:bg-brand-primary hover:text-surface-card">
{buttonText}
</Link>
)}
@@ -403,7 +403,7 @@ function EditorialCarouselSection({ payload, lang }: { payload: Record<string, u
<div className="mx-auto max-w-7xl space-y-12">
{title && (
<div className="mx-auto max-w-3xl space-y-4 text-center">
<h2 className="text-4xl font-semibold text-white md:text-5xl">{renderAccentTitle(title, 'ui-accent-text not-italic')}</h2>
<h2 className="text-4xl font-semibold text-surface-card md:text-5xl">{renderAccentTitle(title, 'ui-accent-text not-italic')}</h2>
<div className="mx-auto h-px w-16 bg-brand-accent" />
</div>
)}
@@ -485,9 +485,9 @@ function HeroArticleSection({ payload, lang }: { payload: Record<string, unknown
<div className="relative z-10 mx-auto max-w-4xl space-y-6">
{category && <p className="text-xs font-bold uppercase tracking-[0.28em] text-brand-accent">{category}</p>}
<h1 className="ui-hero-title">{title}</h1>
{subtitle && <p className="mx-auto max-w-2xl text-lg text-white/85 md:text-xl">{subtitle}</p>}
{subtitle && <p className="mx-auto max-w-2xl text-lg text-surface-card md:text-xl">{subtitle}</p>}
{(author || date) && (
<p className="text-xs font-bold uppercase tracking-[0.22em] text-white/70">
<p className="text-xs font-bold uppercase tracking-[0.22em] text-surface-card">
{[author && `${authorPrefix[resolvedLang] ?? authorPrefix.en} ${author}`, date].filter(Boolean).join(' / ')}
</p>
)}
@@ -213,7 +213,7 @@ export function MobileDrawer({
<Link
href="/shop"
onClick={onClose}
className="block w-full rounded-xl bg-text-main py-3.5 text-center text-xs font-bold uppercase tracking-widest text-white shadow-sm transition-colors hover:bg-brand-primary"
className="block w-full rounded-xl bg-text-main py-3.5 text-center text-xs font-bold uppercase tracking-widest text-surface-card shadow-sm transition-colors hover:bg-brand-primary"
>
Shop Now
</Link>