/* Studio 76 — The Imaginarium (standalone). Dream a piece → rendered in solid gold. Beyond the edit box: Surprise me, a muse builder, and birthstone designs. Talks only to imaginarium.php (brief → hero → wireframe → metal variants). */ const MOODS = ['Celestial','Midnight','Monsoon','Golden hour','Oceanic','Ember','Botanical','Gothic romance','New-age minimal','Maximalist']; const ERAS = ['Art Deco','Victorian','Mughal','1970s','Y2K','Ancient Rome','Belle Époque','Future-organic']; const GEMS = ['Emerald','Ruby','Sapphire','Diamond','Pearl','Opal','Moonstone','Black diamond','Pink tourmaline','Tanzanite']; const FORMS = ['Ring','Necklace','Earrings','Cuff','Pendant','Anklet','Brooch','Tiara']; const OCCASIONS = ['an engagement','an anniversary','a self-gift','an everyday heirloom','the red carpet','a wedding']; const MONTHS = [ ['Jan','Garnet'],['Feb','Amethyst'],['Mar','Aquamarine'],['Apr','Diamond'], ['May','Emerald'],['Jun','Moonstone'],['Jul','Ruby'],['Aug','Peridot'], ['Sep','Sapphire'],['Oct','Opal'],['Nov','Citrine'],['Dec','Tanzanite'], ]; /* curated, gorgeous seeds for Surprise me */ const DREAMS = [ 'A celestial diamond choker scattered like a constellation across the collarbone', 'An Art Deco emerald cocktail ring, stepped and architectural, on a slim band', 'A monsoon-grey moonstone pendant that glows like rain on glass', 'Twin serpent ear-climbers in brushed gold with tiny ruby eyes', 'A Mughal-inspired polki necklace reimagined fine, delicate and barely-there', 'A single pear-cut sapphire suspended on a thread-thin chain, floating at the throat', 'A molten gold cuff that looks poured rather than made, holding one raw emerald', 'Stacking rings like the phases of the moon — pavé to bare polished gold', 'A Belle Époque garland melted into a delicate everyday tiara of white gold', 'Black diamond studs ringed in a whisper of white-gold thorns', 'A botanical vine bracelet, gold leaves curling around a line of tsavorites', 'An ember-orange spessartite solitaire in a fine six-prong, warm as candlelight', ]; const EXAMPLES = [ 'A fine rose-gold pendant with a single pearl — modern and minimal', 'Delicate diamond ear-climbers, contemporary, barely-there', 'A slim stacking ring with a tiny emerald, new-age and clean', ]; const TONES = [ { k:'original', label:'As designed' }, { k:'yellow', label:'Yellow' }, { k:'white', label:'White' }, { k:'rose', label:'Rose' }, ]; async function api(action, payload){ const r = await fetch('imaginarium.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(Object.assign({action},payload))}); let j={}; try{ j=await r.json(); }catch(e){} if(!r.ok || j.error) throw new Error(j.error || ('Something went wrong ('+r.status+')')); return j; } function pick(a){ return a[Math.floor(Math.random()*a.length)]; } const isUrl = x => typeof x === 'string' && x !== 'loading'; function Imaginarium(){ const [tab, setTab] = React.useState('muse'); // muse | stars | words const [muse, setMuse] = React.useState({ mood:null, era:null, gem:null, form:null, occ:null }); const [month, setMonth] = React.useState(null); const [dream, setDream] = React.useState(''); const [phase, setPhase] = React.useState('idle'); // idle | thinking | result const [concept, setConcept] = React.useState(null); const [spec, setSpec] = React.useState(null); const [hero, setHero] = React.useState(null); const [variants, setVariants] = React.useState({}); const [wire, setWire] = React.useState(null); const [active, setActive] = React.useState('original'); const [view, setView] = React.useState('render'); const [err, setErr] = React.useState(''); const heroRef = React.useRef(null); function toggle(dim, val){ setMuse(m => Object.assign({}, m, { [dim]: m[dim] === val ? null : val })); } function composeMuse(){ const m = muse; var s = 'A ' + (m.form ? m.form.toLowerCase() : 'fine jewellery piece'); if (m.occ) s += ' for ' + m.occ; var clauses = []; if (m.mood) clauses.push(m.mood.toLowerCase() + ' in feeling'); if (m.era) clauses.push('inspired by ' + m.era); if (m.gem) clauses.push('centred on ' + m.gem.toLowerCase()); if (clauses.length) s += ', ' + clauses.join(', '); s += '. New-age, fine and wearable — made to be cast in solid gold.'; return s; } const museHasAny = muse.mood || muse.era || muse.gem || muse.form || muse.occ; async function imagine(text){ const d = (text || '').trim(); if (d.length < 4){ setErr('Tell us a little more about the piece.'); return; } setErr(''); setPhase('thinking'); setConcept(null); setSpec(null); setHero(null); heroRef.current = null; setVariants({}); setWire(null); setActive('original'); setView('render'); try{ const b = await api('brief', { dream: d }); setConcept(b.concept); setSpec(b.spec); setPhase('result'); const h = await api('hero', { spec: b.spec }); heroRef.current = h; setHero(h); setVariants({ original: h.dataUrl }); // Blueprint + metal variants are generated ON DEMAND (when tapped) — no wasted renders. }catch(e){ setErr(e.message || 'Could not imagine that — try again.'); setPhase('idle'); } } // on-demand: blueprint function genWire(){ setView('blueprint'); if (wire || !heroRef.current) return; setWire('loading'); api('wireframe', { id: heroRef.current.id }).then(w => setWire(w.dataUrl)).catch(() => setWire(null)); } // on-demand: a metal variant (original is already the hero) function genVariant(tone){ setActive(tone); setView('render'); if (tone === 'original' || variants[tone] || !heroRef.current) return; setVariants(v => Object.assign({}, v, { [tone]: 'loading' })); api('variant', { id: heroRef.current.id, tone }) .then(r => setVariants(v => Object.assign({}, v, { [tone]: r.dataUrl }))) .catch(() => setVariants(v => { const n = Object.assign({}, v); delete n[tone]; return n; })); } function surprise(){ // 70% a curated gem of a dream, 30% a freshly-rolled muse if (Math.random() < 0.7){ imagine(pick(DREAMS)); return; } const m = { form: pick(FORMS), gem: pick(GEMS), mood: pick(MOODS), era: pick(ERAS), occ: null }; setMuse(m); setTab('muse'); imagine('A ' + m.form.toLowerCase() + ', ' + m.mood.toLowerCase() + ' in feeling, inspired by ' + m.era + ', centred on ' + m.gem.toLowerCase() + '. New-age, fine and wearable — made to be cast in solid gold.'); } function imagineBirthstone(){ const mo = MONTHS[month]; if (!mo) return; imagine('A fine, contemporary piece designed around a ' + mo[1].toLowerCase() + ' — the birthstone of ' + ({Jan:'January',Feb:'February',Mar:'March',Apr:'April',May:'May',Jun:'June',Jul:'July',Aug:'August',Sep:'September',Oct:'October',Nov:'November',Dec:'December'})[mo[0]] + '. Let the stone lead, set in solid gold, new-age and wearable every day.'); } const fmtStone = s => s ? [s.carat_estimate, s.cut, s.color, s.type].filter(Boolean).join(' ') : ''; const fmtAcc = a => (a && a.length) ? a.map(x => typeof x === 'string' ? x : [x.cut, x.color, x.type].filter(Boolean).join(' ')).filter(Boolean).join(', ') : ''; const mainSrc = view === 'blueprint' ? (isUrl(wire) ? wire : null) : (isUrl(variants[active]) ? variants[active] : (hero && hero.dataUrl)); const stageMsg = !concept ? 'Composing your concept…' : (!hero ? 'Rendering in solid gold…' : (view === 'blueprint' ? 'Drafting the blueprint…' : 'Rendering in solid gold…')); const Row = ({l,v}) => v ?
{l}{v}
: null; return (
Studio 76 BenchStylistTry-on✦ Imaginarium

Dream it. We’ll draw it in gold.

Describe a piece you’ve always wanted — or let a muse spark it — and watch it render in solid gold, in seconds. No photo needed; just your imagination.

or spark your own
{tab === 'muse' && (
The form
{FORMS.map(f => )}
A feeling
{MOODS.map(f => )}
An era
{ERAS.map(f => )}
The stone
{GEMS.map(f => )}
For…
{OCCASIONS.map(f => )}
{museHasAny &&
Your muse: {composeMuse()}
}
{museHasAny && }
)} {tab === 'stars' && (
Pick a birth month — we’ll design around its stone
{MONTHS.map((mo,i) => )}
)} {tab === 'words' && (