/* Shared UI primitives + Icon set */ const { useState, useEffect, useContext, createContext, useMemo } = React; /* ===== Icon set ===== */ const I = { home: , grid: <>, user: <>, users: <>, bell: <>, logout: <>, chevronR: , chevronL: , arrowR: <>, arrowL: <>, plus: <>, check: , x: <>, clock: <>, calendar: <>, mapPin: <>, zap: , trending: <>, wallet: <>, cpu: <>, receipt: <>, shield: , coffee: <>, thermometer: , refresh: <>, search: <>, menu: <>, shoppingBag: <>, download: <>, copy: <>, key: <>, edit: <>, trash: <>, eye: <>, lock: <>, alertCircle: <>, settings: <>, }; function Icon({ name, size = 18, className = "", stroke = 1.8, ...rest }) { const node = I[name]; if (!node) return null; return ( {node} ); } /* ===== Context ===== */ const AppCtx = createContext(null); const useApp = () => useContext(AppCtx); /* ===== Button ===== */ function Button({ variant = "primary", size = "md", className = "", children, ...rest }) { const base = "inline-flex items-center justify-center gap-2 font-semibold transition-all duration-150 active:translate-y-px rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-pink-500 disabled:opacity-50 disabled:pointer-events-none"; const sizes = { sm: "text-sm px-4 py-2", md: "text-sm px-5 py-2.5", lg: "text-base px-6 py-3" }; const variants = { primary: "bg-[#FF2D55] text-white hover:bg-[#E61243] shadow-[0_4px_0_#C2143A] active:shadow-[0_1px_0_#C2143A]", dark: "bg-[#1A1A1A] text-white hover:bg-black", ghost: "bg-transparent text-[#1A1A1A] border border-[#1A1A1A] hover:bg-[#1A1A1A] hover:text-white", soft: "bg-pink-50 text-[#FF2D55] hover:bg-pink-100", subtle: "bg-stone-100 text-stone-700 hover:bg-stone-200", danger: "bg-rose-600 text-white hover:bg-rose-700", }; return ( ); } /* ===== Badge ===== */ function Badge({ tone = "neutral", children, className = "" }) { const map = { neutral: "bg-stone-100 text-stone-700", success: "bg-emerald-50 text-emerald-700 ring-1 ring-emerald-200", warning: "bg-amber-50 text-amber-700 ring-1 ring-amber-200", danger: "bg-rose-50 text-rose-700 ring-1 ring-rose-200", info: "bg-sky-50 text-sky-700 ring-1 ring-sky-200", brand: "bg-pink-50 text-[#E61243] ring-1 ring-pink-200", }; return ( {children} ); } /* ===== Card ===== */ function Card({ children, className = "" }) { return
{children}
; } /* ===== Page header ===== */ function PageHeader({ eyebrow, title, jp, sub, actions }) { return (
{eyebrow &&
{eyebrow}
} {jp &&
{jp}
}

{title}

{sub &&

{sub}

}
{actions &&
{actions}
}
); } /* ===== Toast ===== */ function Toast({ toast, onClose }) { useEffect(() => { if (!toast) return; const t = setTimeout(onClose, 4200); return () => clearTimeout(t); }, [toast]); if (!toast) return null; const toneMap = { success: "bg-emerald-600", danger: "bg-rose-600", info: "bg-[#1A1A1A]", warning: "bg-amber-500" }; return (
{toast.msg}
); } /* ===== Modal wrapper ===== */ function Modal({ open, onClose, title, children, width = "max-w-lg" }) { if (!open) return null; return (

{title}

{children}
); } /* ===== Field input ===== */ function Field({ label, type = "text", value, onChange, full, placeholder, required }) { return (
onChange(e.target.value)} placeholder={placeholder} required={required} className="mt-1.5 w-full px-4 py-2.5 rounded-xl border border-stone-300 bg-white text-[#1A1A1A] focus:border-[#FF2D55] focus:ring-2 focus:ring-pink-100 outline-none transition" />
); } /* ===== Stamp ===== */ function Stamp({ children, className = "" }) { return (
{children}
); } Object.assign(window, { Icon, AppCtx, useApp, Button, Badge, Card, PageHeader, Toast, Modal, Field, Stamp });