/* ============================================================ GlowMerald — Shared UI primitives + AppCtx ============================================================ */ const { useState, useEffect, useRef, useContext, createContext } = React; /* ---- App context (cart / wishlist / nav / toast) ---- */ const AppCtx = createContext(null); const useApp = () => useContext(AppCtx); /* ---- Icon set (thin line, currentColor) ---- */ const PATHS = { cart:'M6 7h13l-1.2 8.5a2 2 0 0 1-2 1.7H9.4a2 2 0 0 1-2-1.7L6 4H3M9 21a1 1 0 1 0 0-.01M17 21a1 1 0 1 0 0-.01', search:'M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM21 21l-4.3-4.3', heart:'M12 20s-7-4.6-7-9.7C5 7.4 7 6 9 6c1.5 0 2.5.8 3 1.8C12.5 6.8 13.5 6 15 6c2 0 4 1.4 4 4.3 0 5.1-7 9.7-7 9.7Z', user:'M5 20a7 7 0 0 1 14 0M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z', menu:'M4 7h16M4 12h16M4 17h16', close:'M6 6l12 12M18 6 6 18', home:'M4 11 12 4l8 7M6 9.5V20h12V9.5', shop:'M5 8h14l-1 12H6L5 8ZM9 8V6a3 3 0 0 1 6 0v2', book:'M5 5a2 2 0 0 1 2-2h11v15H7a2 2 0 0 0-2 2V5ZM18 18v3H7', shield:'M12 3 5 6v5c0 4 3 7 7 9 4-2 7-5 7-9V6l-7-3Z M9.5 12l1.8 1.8L15 10', layers:'M12 3 3 8l9 5 9-5-9-5ZM3 13l9 5 9-5M3 8v0', gem:'M6 4h12l3 5-9 11L3 9l3-5ZM3 9h18M9 4 7.5 9 12 20M15 4l1.5 5L12 20', leaf:'M5 19c0-8 6-13 14-13 0 8-6 13-14 13ZM5 19c3-4 6-6 9-7.5', star:'M12 3.5l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 17l-5.2 2.7 1-5.8L3.5 9.7l5.9-.9L12 3.5Z', check:'M5 12.5 10 17l9-10', chevron:'M9 6l6 6-6 6', chevronDown:'M6 9l6 6 6-6', plus:'M12 5v14M5 12h14', minus:'M5 12h14', arrow:'M5 12h14M13 6l6 6-6 6', trash:'M5 7h14M10 7V5h4v2M6 7l1 13h10l1-13', ig:'M7 3h10a4 4 0 0 1 4 4v10a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V7a4 4 0 0 1 4-4ZM12 8.5a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7ZM17 7v.01', tiktok:'M14 4c.5 2.5 2 4 4.5 4.3M14 4v9.5a3.5 3.5 0 1 1-3-3.5M14 4h-2.8v9.5', whatsapp:'M5 19l1.2-3.4A7 7 0 1 1 9 18.2L5 19ZM9 9c0 4 3 6 5.5 6.2', truck:'M3 6h11v9H3zM14 9h4l3 3v3h-7M7 18a1.5 1.5 0 1 0 0-.01M17.5 18a1.5 1.5 0 1 0 0-.01', spark:'M12 3v6M12 15v6M3 12h6M15 12h6', filter:'M4 6h16M7 12h10M10 18h4', }; function Icon({ name, size=20, stroke=1.6, fill=false, style }){ const d = PATHS[name] || ''; return ( {d.split('M').filter(Boolean).map((seg,i)=>)} ); } /* ---- Logo: official GlowMerald horizontal lockup ---- */ function Logo({ size=26, mark='gold', word=true, dark=false }){ const useCream = dark || mark==='cream'; const src = useCream ? 'assets/logo-cream.png' : 'assets/logo-gold.png'; return GlowMerald; } /* ---- Stars ---- */ function Stars({ value=5, size=14 }){ return ( {[1,2,3,4,5].map(i=>( ))} ); } /* ---- Chips ---- */ function Chips({ items=[], variant='ghost-gold' }){ return
{items.map((t,i)=>{t})}
; } /* ---- Product visual stand-ins (CSS rendered) ---- */ function ProductVisual({ kind='serum', tag, style }){ return (
{kind==='serum' && (
GSerum
)} {kind==='mask' && (
GHydrogel
)} {kind==='bundle' && (
GSerum
GMask
)} {tag && {tag}}
); } /* ---- Striped placeholder ---- */ function Placeholder({ label='image', className='', style, circle=false }){ return
{label}
; } /* ---- Avatar (initial monogram) ---- */ function Avatar({ name='', size=44, style }){ const initials = name.split(' ').slice(0,2).map(w=>w[0]).join(''); return
{initials}
; } /* ---- Section heading w/ rule ---- */ function SectionHead({ eyebrow, title, sub, center=true, onDark=false }){ return (
{eyebrow &&
{eyebrow}
}

{title}

{sub &&

{sub}

}
); } /* ---- Skeleton product card ---- */ function SkeletonCard(){ return (
); } Object.assign(window, { AppCtx, useApp, Icon, Logo, Stars, Chips, ProductVisual, Placeholder, Avatar, SectionHead, SkeletonCard, });