// Gallery, artwork detail (with pricing breakdown), commission builder const { useEffect, useMemo, useRef, useState } = React; // --- pricing engine function computePrice(piece, opts) { const surfaceMul = { canvas: 1.0, wall: 1.6, wearable: 0.7, furniture: 1.4, shoes: 0.55, helmet: 0.6, skate: 0.5, interior: 2.4, glass: 0.9, metal: 1.1, digital: 0.8 }; const sizeMul = { S: 0.7, M: 1.0, L: 1.4, XL: 1.9 }; const frameAdd = { none: 0, wood: 320, oak: 540, brass: 880, museum: 1400 }; const textureMul= { Subtle: 1.0, Layered: 1.18, Heavy: 1.36, Sculptural: 1.6 }; const realismMul= { Atmospheric: 0.95, Figurative: 1.1, Hyperreal: 1.3 }; const rushAdd = { Standard: 0, Priority: 880, Rush: 2200 }; const base = piece.basePrice; const sub = base * (sizeMul[opts.size] ?? 1) * (textureMul[opts.texture] ?? 1) * (realismMul[opts.realism] ?? 1) * (surfaceMul[opts.surface] ?? 1); const frame = frameAdd[opts.frame] ?? 0; const rush = rushAdd[opts.rush] ?? 0; const custom = opts.customDepth * 180; // 0..5 return { base: Math.round(sub), frame, rush, custom, total: Math.round(sub + frame + rush + custom), hours: Math.round(piece.hours * (sizeMul[opts.size] ?? 1) * (textureMul[opts.texture] ?? 1)), }; } const fmt = (n) => "$" + n.toLocaleString("en-US"); // --- gallery (editorial mosaic) function Gallery({ artworks, onOpen, accentTo }) { // editorial layout — six tiles with intentional asymmetry const layout = [ { col: "1 / span 7", row: "span 14", scale: "lg" }, { col: "8 / span 5", row: "span 9", scale: "md" }, { col: "8 / span 5", row: "span 5", scale: "sm" }, { col: "1 / span 4", row: "span 8", scale: "md" }, { col: "5 / span 4", row: "span 8", scale: "md" }, { col: "9 / span 4", row: "span 8", scale: "md" }, { col: "1 / span 6", row: "span 9", scale: "lg" }, { col: "7 / span 6", row: "span 9", scale: "lg" }, ]; return (
{artworks.map((a, i) => { const cell = layout[i % layout.length]; return (
accentTo(a.accent)} onClick={() => onOpen(a)} >
{String(i + 1).padStart(2, "0")} {a.category}

{a.title}

{a.dimensions} {fmt(a.basePrice)}
); })}
); } // --- detail modal function ArtworkDetail({ piece, onClose, accentTo }) { const [opts, setOpts] = useState({ size: "M", surface: piece.surfaces[0] || "canvas", frame: "none", texture: piece.complexity === "Heavy texture" ? "Heavy" : "Layered", realism: "Figurative", rush: "Standard", customDepth: 1, }); useEffect(() => { accentTo(piece.accent); }, [piece, accentTo]); const price = useMemo(() => computePrice(piece, opts), [piece, opts]); const set = (k, v) => setOpts(o => ({ ...o, [k]: v })); // ESC close useEffect(() => { const onKey = (e) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); document.body.style.overflow = "hidden"; return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; }; }, [onClose]); return (
e.stopPropagation()}>
SNIGDHA · {piece.category} {piece.year} · {piece.edition}

{piece.title}

{piece.tagline}

Medium{piece.medium}
Dimensions{piece.dimensions}
Hours invested{piece.hours} h
Availability{piece.availability}
); } function Field({ label, hint, children }) { return (
{label} {hint && {hint}}
{children}
); } function Chip({ active, onClick, children }) { return ( ); } // --- commission builder (multi-step) function CommissionBuilder({ surfaces }) { const STEPS = ["Surface", "Style", "Scale", "Story", "Send"]; const [step, setStep] = useState(0); const [data, setData] = useState({ surface: "wall", style: "Atmospheric", palette: "Warm", scale: "Mid (4-6 ft)", timeline: "8 weeks", budget: "5–10k", note: "", name: "", email: "", }); const [sending, setSending] = useState(false); const [sent, setSent] = useState(false); const set = (k, v) => setData(d => ({ ...d, [k]: v })); // Replace with your Google Apps Script Web App deployment URL const FORM_ENDPOINT = "PASTE_YOUR_WEB_APP_URL_HERE"; const sendInquiry = async () => { if (!data.email) { alert("Please add an email so I can reply."); return; } setSending(true); try { await fetch(FORM_ENDPOINT, { method: "POST", mode: "no-cors", body: JSON.stringify({ ...data, sentAt: new Date().toISOString() }), }); setSent(true); } catch (err) { alert("Send failed — please email studio@snigdha.art directly."); } finally { setSending(false); } }; const goto = (i) => setStep(Math.max(0, Math.min(STEPS.length - 1, i))); return (
Commission · 04

Bring me
your surface,
and a feeling.

A jacket, a ceiling, a console, a wall that feels too quiet. The brief begins here. We'll meet in five short steps — then on a call, in the studio, or in your room.

{STEPS.map((s, i) => ( ))}
{step === 0 && (
{surfaces.map(s => ( ))}
)} {step === 1 && (
{[ ["Atmospheric", "Mood, weather, low contrast."], ["Figurative", "Bodies, objects, recognisable forms."], ["Abstract", "Gesture, mark, surface."], ["Hyperreal", "Detail at the limits."], ].map(([k, sub]) => ( ))}
{["Warm","Cool","Earthen","Monochrome","Jewel","Pastel"].map(p => ( ))}
)} {step === 2 && (
{["Intimate (≤ 2 ft)","Mid (4-6 ft)","Statement (8-12 ft)","Architectural (12 ft+)"].map(v => set("scale", v)}>{v} )}
{["4 weeks","8 weeks","12 weeks","Open"].map(v => set("timeline", v)}>{v} )}
{["≤ 2k","2–5k","5–10k","10–25k","25k+"].map(v => set("budget", v)}>{v} )}
)} {step === 3 && (