{"title":"Belt","description":"\u003cmeta charset=\"utf-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width,initial-scale=1\"\u003e\n\u003cstyle\u003ebody{margin:0;font-family:Helvetica,Arial,sans-serif;background:#fff;color:#111}.fake{display:flex;justify-content:space-between;padding:18px 24px;font-size:13px;letter-spacing:.08em;border-bottom:1px solid #ddd}.fake.f{border:0;border-top:1px solid #ddd;padding:60px 24px;color:#777}\u003c\/style\u003e\n\u003cdiv class=\"fake\"\u003e\n\u003cb\u003eGOLDFUNK\u003c\/b\u003e\u003cspan\u003eSHOP   ABOUT   CART (0)\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c!-- ==========================================================\n     GOLDFUNK — EXPERIMENT Nº001  ·  \"NOTHING TO SEE HERE\"\n     Paste this whole file into a Custom Liquid section.\n     Vanilla HTML \/ CSS \/ JS. No libraries. All CSS scoped to .gfx\n     ========================================================== --\u003e\n\u003cdiv class=\"gfx is-intro\" data-gfx=\"\"\u003e\n\u003cdiv class=\"gfx-stage\" role=\"region\" aria-label=\"GOLDFUNK interactive experiment\"\u003e\n\u003cp class=\"gfx-sr\"\u003eAn interactive table of photographs. Drag, throw and flip the prints. Spell GOLD or FUNK with the big letters.\u003c\/p\u003e\n\u003cdiv class=\"gfx-mat\" aria-hidden=\"true\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003cdiv class=\"gfx-words\" aria-hidden=\"true\"\u003e\n\u003cspan class=\"gfx-w\"\u003eG\u003c\/span\u003e\u003cspan class=\"gfx-w\"\u003eO\u003c\/span\u003e\u003cspan class=\"gfx-w\"\u003eL\u003c\/span\u003e\u003cspan class=\"gfx-w\"\u003eD\u003c\/span\u003e\u003cspan class=\"gfx-w\"\u003eF\u003c\/span\u003e\u003cspan class=\"gfx-w\"\u003eU\u003c\/span\u003e\u003cspan class=\"gfx-w\"\u003eN\u003c\/span\u003e\u003cspan class=\"gfx-w\"\u003eK\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"gfx-secrets\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003cdiv class=\"gfx-objects\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003ccanvas class=\"gfx-dust\" aria-hidden=\"true\"\u003e\u003c\/canvas\u003e\n\u003cdiv class=\"gfx-xray\" aria-hidden=\"true\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003cdiv class=\"gfx-top\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003cdiv class=\"gfx-grain\" aria-hidden=\"true\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003cdiv class=\"gfx-hud\"\u003e\n\u003cdiv class=\"gfx-brand\"\u003e\n\u003cb\u003eGOLDFUNK\u003c\/b\u003e\u003cspan\u003eEXPERIMENT Nº001 — THIS PAGE IS EMPTY\u003c\/span\u003e\u003cem class=\"gfx-dnt\" data-alt=\"OK. TOUCH.\"\u003eDO NOT TOUCH\u003c\/em\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"gfx-coords\" aria-hidden=\"true\"\u003e\n\u003cspan class=\"gfx-xy\"\u003eX 0000 · Y 0000\u003c\/span\u003e\u003cspan class=\"gfx-obj\"\u003eOBJ —\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cp class=\"gfx-hint\" aria-hidden=\"true\"\u003e\u003cbr\u003e\u003c\/p\u003e\n\u003cdiv class=\"gfx-meta\"\u003e\n\u003cdiv class=\"gfx-found\"\u003e\n\u003cspan\u003eFOUND \u003cb class=\"gfx-fn\"\u003e0\u003c\/b\u003e\/\u003cb class=\"gfx-ft\"\u003e9\u003c\/b\u003e\u003c\/span\u003e\u003cspan class=\"gfx-dots\"\u003e\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cbutton type=\"button\" class=\"gfx-btn\" data-act=\"shuffle\"\u003eSHUFFLE\u003c\/button\u003e \u003cbutton type=\"button\" class=\"gfx-btn\" data-act=\"reset\"\u003eRESET\u003c\/button\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"gfx-toast\" role=\"status\" aria-live=\"polite\"\u003e\n\u003cspan class=\"gfx-tt\"\u003e\u003c\/span\u003e\u003cspan class=\"gfx-ts\"\u003e\u003c\/span\u003e\u003cbr\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"gfx-intro\" aria-hidden=\"true\"\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003cdiv class=\"gfx-cursor\" aria-hidden=\"true\"\u003e\n\u003ci class=\"gfx-cring\"\u003e\u003c\/i\u003e\u003ci class=\"gfx-cdot\"\u003e\u003c\/i\u003e\u003cb class=\"gfx-clabel\"\u003e\u003c\/b\u003e\u003cbr\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cstyle\u003e\n.gfx{--ink:#0c0b09;--paper:#efe8d9;--gold:#e4b23a;--gold-hi:#ffd86b;--red:#ff3b14;--mono:ui-monospace,\"SF Mono\",Menlo,Consolas,monospace;--disp:\"Arial Black\",\"Helvetica Neue\",Helvetica,Arial,sans-serif;--serif:\"Times New Roman\",Times,Georgia,serif;position:relative;width:100%;max-width:100%;overflow:hidden;background:var(--ink);color:var(--paper);isolation:isolate;font-family:var(--mono);line-height:1.2}\n.gfx *,.gfx *::before,.gfx *::after{box-sizing:border-box}\n.gfx p{margin:0}\n.gfx-stage{position:relative;width:100%;height:100vh;min-height:560px;max-height:1100px;overflow:hidden;touch-action:pan-y pinch-zoom;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;contain:layout paint}\n@supports (height:100svh){.gfx-stage{height:100svh}}\n.gfx-stage.has-cursor,.gfx-stage.has-cursor *{cursor:none!important}\n.gfx-sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n\n\/* table *\/\n.gfx-mat{position:absolute;inset:0;background:radial-gradient(120% 90% at 50% 45%,transparent 40%,rgba(0,0,0,.7) 100%),linear-gradient(rgba(239,232,217,.075) 1px,transparent 1px) 0 0\/200px 200px,linear-gradient(90deg,rgba(239,232,217,.075) 1px,transparent 1px) 0 0\/200px 200px,linear-gradient(rgba(239,232,217,.03) 1px,transparent 1px) 0 0\/40px 40px,linear-gradient(90deg,rgba(239,232,217,.03) 1px,transparent 1px) 0 0\/40px 40px;background-color:#13120f;transition:background-color .5s}\n.gfx-mat::before,.gfx-mat::after{content:\"\";position:absolute;left:0;top:0;opacity:.4}\n.gfx-mat::before{right:0;height:9px;background:repeating-linear-gradient(90deg,var(--paper) 0 1px,transparent 1px 10px)}\n.gfx-mat::after{bottom:0;width:9px;background:repeating-linear-gradient(var(--paper) 0 1px,transparent 1px 10px)}\n.gfx-mat.is-beat{background-color:#2a2414;transition:none}\n.gfx.is-midas .gfx-mat{background-color:#241b06}\n.gfx-grain{position:absolute;inset:-60px;pointer-events:none;opacity:.11;background:url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'\/%3E%3C\/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'\/%3E%3C\/svg%3E\");animation:gfx-grain .9s steps(5) infinite}\n@keyframes gfx-grain{to{transform:translate(50px,35px)}}\n\n\/* giant letters *\/\n.gfx-words{position:absolute;left:0;right:0;top:50%;display:flex;justify-content:space-between;padding:0 2vw;transform:translate3d(0,-50%,0);pointer-events:none}\n.gfx-w{display:block;font:900 14.4vw\/.8 var(--disp);color:transparent;-webkit-text-stroke:1.5px rgba(239,232,217,.17);transform-origin:50% 55%;pointer-events:auto;cursor:pointer;transition:color .25s,-webkit-text-stroke-color .25s;will-change:transform}\n.gfx-w.is-lit,.gfx.is-complete .gfx-w{color:var(--gold);-webkit-text-stroke-color:var(--gold)}\n.gfx.is-funk .gfx-w:nth-child(odd){-webkit-text-stroke-color:var(--red)}\n.gfx.is-funk .gfx-w:nth-child(even){-webkit-text-stroke-color:var(--gold)}\n\n\/* things written on the table, under the prints *\/\n.gfx-secrets{position:absolute;inset:0;pointer-events:none}\n.gfx-sec{position:absolute;translate:-50% -50%;rotate:var(--r,0deg);font:700 11px\/1.35 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--red);border:1.5px solid currentColor;padding:6px 9px;max-width:170px;text-align:center}\n.gfx-sec.is-found{animation:gfx-pop .6s cubic-bezier(.2,1.7,.4,1)}\n.gfx-ring{width:40px;height:40px;border-radius:50%;border:6px solid var(--gold);padding:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.45),0 0 0 1px rgba(0,0,0,.45),0 0 20px rgba(228,178,58,.55)}\n.gfx-ring::before{content:\"\";position:absolute;left:50%;top:-14px;width:13px;height:13px;transform:translateX(-50%) rotate(45deg);background:var(--gold-hi);box-shadow:0 0 12px #fff}\n.gfx-ring.is-found{pointer-events:auto;cursor:pointer;animation:gfx-pop .6s cubic-bezier(.2,1.7,.4,1),gfx-glow 1s .6s ease-in-out infinite alternate}\n@keyframes gfx-pop{from{scale:.3;opacity:0}to{scale:1;opacity:1}}\n@keyframes gfx-glow{to{box-shadow:inset 0 0 0 1px rgba(0,0,0,.45),0 0 0 1px rgba(0,0,0,.45),0 0 44px 6px rgba(255,216,107,.9)}}\n\n\/* prints *\/\n.gfx-objects,.gfx-top,.gfx-dust{position:absolute;inset:0}\n.gfx-objects{isolation:isolate}\n.gfx-dust{width:100%;height:100%;pointer-events:none}\n.gfx-top{pointer-events:none}\n.gfx-objects.is-shake{animation:gfx-shake .32s linear}\n@keyframes gfx-shake{20%{transform:translate(-9px,5px)}40%{transform:translate(8px,-6px)}60%{transform:translate(-5px,-3px)}80%{transform:translate(4px,3px)}}\n.gfx-card,.gfx-loupe{position:absolute;left:0;top:0;touch-action:none;outline:none;will-change:transform;cursor:grab}\n.gfx-card{width:var(--w);height:var(--h)}\n.gfx.is-intro .gfx-card,.gfx.is-intro .gfx-loupe{visibility:hidden}\n.gfx .gfx-card.is-drop,.gfx .gfx-loupe.is-drop{visibility:visible}\n.gfx-lift{position:absolute;inset:0;perspective:1400px;transition:transform .35s cubic-bezier(.2,.9,.3,1.4)}\n.is-drop\u003e.gfx-lift{animation:gfx-drop .62s cubic-bezier(.2,.9,.25,1) backwards}\n@keyframes gfx-drop{0%{transform:translateY(-34px) scale(1.75);opacity:0}55%{opacity:1}100%{transform:none;opacity:1}}\n.is-held\u003e.gfx-lift{transform:scale(1.05)}\n.gfx-lift::after{content:\"\";position:absolute;top:-9px;left:var(--tx,50%);width:62px;height:19px;background:rgba(239,232,217,.5);box-shadow:0 1px 2px rgba(0,0,0,.35);transform:translateX(-50%) rotate(var(--tr,0deg));pointer-events:none}\n.gfx-loupe .gfx-lift::after{display:none}\n.gfx-flip{position:absolute;inset:0;transform-style:preserve-3d;transition:transform .8s cubic-bezier(.3,1.35,.4,1)}\n.is-flipped .gfx-flip{transform:rotateY(180deg)}\n.gfx-face{position:absolute;inset:0;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--paper);color:var(--ink);padding:7px 7px 0;box-shadow:0 1px 1px rgba(0,0,0,.35),0 12px 22px -8px rgba(0,0,0,.75);transition:box-shadow .3s,background .5s}\n.is-held .gfx-face{box-shadow:0 2px 2px rgba(0,0,0,.25),0 44px 60px -18px rgba(0,0,0,.9)}\n.gfx-card:focus-visible .gfx-face,.gfx-loupe:focus-visible .gfx-lglass{outline:2px solid var(--gold);outline-offset:4px}\n.gfx-media{position:relative;width:100%;height:calc(100% - 31px);overflow:hidden;background:#1b1a17}\n.gfx-media img,.gfx-media video,.gfx-media canvas{position:absolute;inset:0;width:100%;height:100%;max-width:none;object-fit:cover;display:block;pointer-events:none;transition:filter .5s}\n.gfx-cap{display:flex;justify-content:space-between;align-items:center;gap:8px;height:31px;font:700 9.5px\/1 var(--mono);letter-spacing:.13em;text-transform:uppercase;white-space:nowrap;overflow:hidden}\n.gfx-rate{position:absolute;left:6px;top:6px;font:700 10px\/1 var(--mono);letter-spacing:.1em;color:var(--gold-hi);background:rgba(0,0,0,.65);padding:4px 5px}\n.gfx-back{transform:rotateY(180deg);padding:18px 15px 14px;display:flex;flex-direction:column;justify-content:space-between;background:repeating-linear-gradient(transparent 0 23px,rgba(12,11,9,.13) 23px 24px),#e9e1cf}\n.gfx-note{font:italic 400 clamp(15px,1.45vw,21px)\/24px var(--serif)}\n.gfx-stamp{align-self:flex-end;font:900 9.5px\/1.15 var(--mono);letter-spacing:.1em;color:var(--red);border:2px solid;padding:5px 7px;transform:rotate(-8deg)}\n.is-gold .gfx-face{background:linear-gradient(125deg,#fff3c2,var(--gold) 38%,#86610f 66%,var(--gold-hi))}\n.is-gold .gfx-media\u003e*{filter:sepia(1) saturate(2.7) hue-rotate(-8deg) contrast(1.15)}\n.gfx-rot{position:absolute;right:-15px;top:-15px;width:32px;height:32px;border-radius:50%;background:var(--ink);color:var(--gold);border:1.5px solid var(--gold);display:grid;place-items:center;font:700 16px\/1 var(--mono);opacity:0;scale:.5;transition:opacity .2s,scale .25s}\n.gfx-card:hover .gfx-rot,.gfx-card.is-held .gfx-rot,.gfx-card:focus-visible .gfx-rot{opacity:1;scale:1}\n@media (hover:none){.gfx-rot{display:none}}\n\n\/* loupe + the other side of the table *\/\n.gfx-loupe{width:var(--d);height:var(--d);pointer-events:auto}\n.gfx-lglass{position:absolute;inset:0;border-radius:50%;border:3px solid var(--paper);box-shadow:0 0 0 1px rgba(0,0,0,.5),0 22px 40px -10px rgba(0,0,0,.85),inset 0 0 0 5px var(--ink),inset 0 0 0 6.5px var(--gold)}\n.gfx-lhandle{position:absolute;left:83%;top:83%;width:17px;height:46%;background:var(--ink);border:2px solid var(--paper);border-radius:9px;transform-origin:50% 0;transform:rotate(-45deg)}\n.gfx-llabel{position:absolute;left:50%;top:-20px;transform:translateX(-50%);font:700 10px\/1 var(--mono);letter-spacing:.22em;color:var(--gold);white-space:nowrap}\n.gfx-xray{position:absolute;inset:0;pointer-events:none;overflow:hidden;color:var(--ink);background:radial-gradient(circle,rgba(12,11,9,.3) 1.2px,transparent 1.7px) 0 0\/9px 9px;background-color:var(--gold);-webkit-clip-path:circle(0px at -500px -500px);clip-path:circle(0px at -500px -500px)}\n.gfx-xray img,.gfx-xray video{position:absolute;inset:0;width:100%;height:100%;max-width:none;object-fit:cover;mix-blend-mode:multiply;filter:grayscale(1) contrast(1.25)}\n.gfx-xbig{position:absolute;left:4%;top:50%;transform:translateY(-50%);font:900 13.5vw\/.82 var(--disp);letter-spacing:-.04em;text-transform:uppercase}\n.gfx-xmsg{position:absolute;font:700 11px\/1.3 var(--mono);letter-spacing:.15em;max-width:240px}\n.gfx-xspot{position:absolute;translate:-50% -50%;rotate:-5deg;font:900 13px\/1 var(--mono);letter-spacing:.14em;white-space:nowrap;background:var(--red);color:var(--paper);padding:9px 12px}\n\n\/* hud *\/\n.gfx-hud{position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity .9s .3s}\n.gfx.is-live .gfx-hud{opacity:1}\n.gfx-hud\u003e*{position:absolute}\n.gfx-brand{left:22px;top:20px;display:flex;flex-direction:column;align-items:flex-start;gap:5px}\n.gfx-brand b{font:900 24px\/1 var(--disp);letter-spacing:-.04em}\n.gfx-brand span{font:500 9.5px\/1 var(--mono);letter-spacing:.16em;opacity:.65}\n.gfx-dnt{font:700 10px\/1 var(--mono);font-style:normal;letter-spacing:.16em;background:var(--red);color:var(--ink);padding:5px 8px;rotate:-3deg;margin-top:4px;pointer-events:auto}\n.gfx-dnt:hover{font-size:0;background:var(--gold)}\n.gfx-dnt:hover::after{content:attr(data-alt);font-size:10px}\n.gfx-coords{right:22px;top:22px;display:flex;flex-direction:column;gap:6px;text-align:right;font:500 10px\/1 var(--mono);letter-spacing:.15em;opacity:.7;white-space:pre}\n.gfx-hint{left:22px;bottom:22px;max-width:44vw;font:700 11px\/1.4 var(--mono);letter-spacing:.14em;text-transform:uppercase;transition:opacity .35s,transform .35s}\n.gfx-hint::before{content:\"→ \";color:var(--gold)}\n.gfx-hint.is-out{opacity:0;transform:translateY(6px)}\n.gfx-meta{right:22px;bottom:16px;display:flex;align-items:center;gap:12px;pointer-events:auto}\n.gfx-found{display:flex;align-items:center;gap:9px;font:700 10px\/1 var(--mono);letter-spacing:.14em;margin-right:4px}\n.gfx-found b{font-weight:700}\n.gfx-dots{display:flex;gap:3px}\n.gfx-dots i{width:8px;height:8px;border:1px solid rgba(239,232,217,.5);transition:background .4s,border-color .4s,transform .4s}\n.gfx-dots i.is-on{background:var(--gold);border-color:var(--gold);transform:rotate(45deg) scale(.85)}\n.gfx .gfx-btn{-webkit-appearance:none;appearance:none;margin:0;min-height:0;background:transparent;border:1.5px solid var(--paper);color:var(--paper);font:700 10px\/1 var(--mono);letter-spacing:.16em;padding:10px 14px;border-radius:999px;cursor:pointer;box-shadow:none;transition:background .2s,color .2s,border-color .2s}\n.gfx .gfx-btn:hover,.gfx .gfx-btn:focus-visible{background:var(--gold);border-color:var(--gold);color:var(--ink);outline:none}\n\n\/* big announcements *\/\n.gfx-toast{position:absolute;left:0;right:0;top:50%;padding:0 4vw;transform:translateY(-50%);text-align:center;pointer-events:none;color:var(--paper)}\n.gfx-tt{display:block;font:900 clamp(32px,7.4vw,128px)\/1.02 var(--disp);letter-spacing:-.04em;text-transform:uppercase;-webkit-clip-path:inset(0 0 100% 0);clip-path:inset(0 0 100% 0);transition:clip-path .55s cubic-bezier(.7,0,.2,1),-webkit-clip-path .55s cubic-bezier(.7,0,.2,1)}\n.gfx-tt\u003espan{background:var(--ink);padding:0 .12em;-webkit-box-decoration-break:clone;box-decoration-break:clone}\n.gfx-ts{display:inline-block;margin-top:14px;max-width:560px;background:var(--gold);color:var(--ink);padding:6px 10px;font:700 11px\/1.5 var(--mono);letter-spacing:.2em;text-transform:uppercase;opacity:0;transition:opacity .4s}\n.gfx-toast.is-on .gfx-tt{-webkit-clip-path:inset(0);clip-path:inset(0)}\n.gfx-toast.is-on .gfx-ts{opacity:1;transition-delay:.25s}\n\n\/* intro *\/\n.gfx-intro{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;overflow:hidden;background-color:var(--ink);transition:background-color .7s}\n.gfx-intro.is-clear{background-color:transparent;pointer-events:none}\n.gfx-itext{position:relative;font:900 clamp(54px,14.5vw,250px)\/.84 var(--disp);letter-spacing:-.045em;text-transform:uppercase;text-align:center;color:var(--paper)}\n.gfx-il{display:block;overflow:hidden;padding:0 .05em;white-space:nowrap}\n.gfx-il.is-gold{color:var(--gold)}\n.gfx-il.is-free{overflow:visible}\n.gfx-ch{display:inline-block;transform:translateY(108%);transition:transform .9s cubic-bezier(.2,.9,.2,1);transition-delay:calc(var(--i)*38ms);will-change:transform}\n.gfx-itext.is-in .gfx-ch{transform:none}\n.gfx-il.is-free .gfx-ch{transition:none}\n.gfx-strike{position:absolute;left:-5%;right:-5%;top:46%;height:.17em;background:var(--red);transform:rotate(-7deg) scaleX(0);transform-origin:0 50%;transition:transform .45s cubic-bezier(.7,0,.2,1)}\n.is-struck .gfx-strike{transform:rotate(-7deg) scaleX(1)}\n.gfx-icap,.gfx-iskip{position:absolute;font:700 10px\/1.7 var(--mono);letter-spacing:.18em;opacity:.55;transition:opacity .4s}\n.gfx-icap{left:22px;top:20px}\n.gfx-iskip{bottom:20px;left:0;right:0;text-align:center}\n.is-clear .gfx-icap,.is-clear .gfx-iskip{opacity:0}\n\n\/* cursor *\/\n.gfx-cursor{position:absolute;left:0;top:0;pointer-events:none;opacity:0;transition:opacity .25s}\n.gfx-stage.has-cursor .gfx-cursor{opacity:1}\n.gfx-cursor\u003e*{position:absolute;left:0;top:0;will-change:transform}\n.gfx-cdot{width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;background:var(--gold)}\n.gfx-cring{width:var(--cs,34px);height:var(--cs,34px);margin:calc(var(--cs,34px)\/-2) 0 0 calc(var(--cs,34px)\/-2);border:1.5px solid var(--paper);border-radius:50%;mix-blend-mode:difference;transition:width .35s cubic-bezier(.2,.9,.3,1.3),height .35s cubic-bezier(.2,.9,.3,1.3),margin .35s cubic-bezier(.2,.9,.3,1.3),border-color .3s,box-shadow .3s}\n.gfx.is-midas .gfx-cring{mix-blend-mode:normal;border-color:var(--gold-hi);box-shadow:0 0 22px 2px rgba(255,216,107,.7),inset 0 0 14px rgba(255,216,107,.5)}\n.gfx-clabel{font:700 9.5px\/1 var(--mono);letter-spacing:.16em;white-space:nowrap;color:var(--ink);background:var(--gold);padding:4px 6px 4px 7px;margin:14px 0 0 14px;opacity:0;transition:opacity .2s}\n.gfx-clabel.is-on{opacity:1}\n\n@media (max-width:699px){\n  .gfx-brand{left:14px;top:14px}.gfx-brand b{font-size:19px}.gfx-brand span{font-size:8.5px}\n  .gfx-coords{display:none}\n  .gfx-hint{left:14px;right:14px;bottom:58px;max-width:none;font-size:10px}\n  .gfx-meta{left:14px;right:14px;bottom:12px;justify-content:space-between;gap:8px}\n  .gfx .gfx-btn{padding:9px 11px}\n  .gfx-words{flex-wrap:wrap;padding:0 3vw}\n  .gfx-w{flex:0 0 25%;text-align:center;font-size:23vw;line-height:1.05}\n  .gfx-xbig{font-size:21vw}\n  .gfx-icap{left:14px;top:14px}\n  .gfx-itext{font-size:17.5vw}\n  .gfx-cap{font-size:8px;letter-spacing:.08em}\n}\n@media (prefers-reduced-motion:reduce){\n  .gfx *,.gfx *::before,.gfx *::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;transition-delay:0s!important}\n  .gfx-grain{animation:none}\n}\n\u003c\/style\u003e\n\u003cscript\u003e\n(function () {\n'use strict';\n\n\/* ================================================================\n   1.  MEDIA CONFIGURATION  —  this is the only part you need to edit\n   ================================================================\n   · Leave src empty ('') and a designed placeholder is shown instead.\n   · src accepts a full URL, or a Shopify file name through Liquid:\n         src: \"{{ 'look-01.jpg' | file_url }}\"\n   · type     'image' or 'video'\n   · caption  short label printed under the print\n   · note     handwritten text on the BACK of the print (double-click)\n   · poster   (video only, optional) still image shown before playback\n   · ratio    (optional) width ÷ height of the media, e.g. 0.8 = 4:5\n   Recommended: 6–10 items in total, 1–3 of them videos.               *\/\nvar GOLDFUNK = {\n  media: [\n    { type: 'image', src: '', caption: 'LOOK 01',   note: 'shot at 4am. nobody slept. worth it.' },\n    { type: 'image', src: '', caption: 'DETAIL',    note: 'the ring is somewhere on this table. not in this photo.' },\n    { type: 'video', src: '', poster: '', caption: 'MOTION 01', note: 'throw me. harder. watch what happens to time.' },\n    { type: 'image', src: '', caption: 'LOOK 02',   note: 'rule nº1: there are no rules. rule nº2: see rule nº1.' },\n    { type: 'image', src: '', caption: 'TEXTURE',   note: 'gold is not a colour. it is an attitude.' },\n    { type: 'image', src: '', caption: 'BACKSTAGE', note: 'try spelling a word you can see on the wall.' },\n    { type: 'video', src: '', poster: '', caption: 'MOTION 02', note: 'the loupe sees through everything. even this.' },\n    { type: 'image', src: '', caption: 'LOOK 03',   note: 'tidy people stack everything into one neat pile. try it.' },\n    { type: 'image', src: '', caption: 'CAMPAIGN',  note: 'if you are reading this, you are curious. we like curious.' }\n  ],\n\n  \/* What the X-RAY loupe reveals underneath the table (image or video, optional) *\/\n  xray: { type: 'image', src: '' },\n  xrayHeadline: 'UNDER THE SURFACE.',\n\n  \/* Notes written on the table itself, hidden under the prints *\/\n  secrets: ['YOU MOVED IT. GOOD.', 'RULES ARE SUGGESTIONS.', 'NOTHING HERE. (OR IS THERE?)'],\n\n  \/* Shown when someone finds and clicks the hidden gold ring — put a code or a call to action here *\/\n  ringReward: 'Screenshot this and DM us. You earned it.',\n\n  \/* Shown when every discovery has been found *\/\n  finalMessage: 'You found all of it. Something is coming. You will be the first to know.'\n};\n\/* ======================= end of configuration ======================= *\/\n\nvar TAU = Math.PI * 2;\nfunction rnd(a, b) { return a + Math.random() * (b - a); }\nfunction clamp(v, a, b) { return v \u003c a ? a : v \u003e b ? b : v; }\nfunction pad2(n) { return (n \u003c 10 ? '0' : '') + n; }\nfunction ms() { return performance.now(); }\nfunction esc(s) { return String(s == null ? '' : s).replace(\/\u0026\/g, '\u0026amp;').replace(\/\u003c\/g, '\u0026lt;').replace(\/\u003e\/g, '\u0026gt;').replace(\/\"\/g, '\u0026quot;'); }\nfunction isShop(u) { return \/cdn\\.shopify\\.com|\\\/cdn\\\/shop\\\/\/.test(u); }\nfunction sized(u, w) { return (u \u0026\u0026 isShop(u) \u0026\u0026 !\/[?\u0026]width=\/.test(u)) ? u + (u.indexOf('?') \u003e -1 ? '\u0026' : '?') + 'width=' + w : u; }\nfunction angDiff(a, b) { return Math.atan2(Math.sin(a - b), Math.cos(a - b)); }\nfunction seeded(s) { return function () { s |= 0; s = s + 0x6D2B79F5 | 0; var t = Math.imul(s ^ s \u003e\u003e\u003e 15, 1 | s); t = t + Math.imul(t ^ t \u003e\u003e\u003e 7, 61 | t) ^ t; return ((t ^ t \u003e\u003e\u003e 14) \u003e\u003e\u003e 0) \/ 4294967296; }; }\n\n\/* ---------- placeholder artwork (used while src is empty) ---------- *\/\nvar PAL = [['#ff3b14', '#e4b23a', '#0c0b09'], ['#0c0b09', '#e4b23a', '#efe8d9'], ['#efe8d9', '#0c0b09', '#ff3b14'], ['#e4b23a', '#0c0b09', '#efe8d9'], ['#1b2bff', '#efe8d9', '#e4b23a'], ['#efe8d9', '#ff3b14', '#0c0b09']];\nvar WORDS = ['GF', '24K', 'FUNK', 'Nº', 'GOLD', 'G.'];\nfunction paintPrint(cv, k) {\n  var w = cv.width = 400, h = cv.height = 500, c = cv.getContext('2d'), p = PAL[k % 6], bg = p[0], fg = p[1], ac = p[2], x, y, r;\n  c.fillStyle = bg; c.fillRect(0, 0, w, h); c.fillStyle = fg; c.strokeStyle = fg;\n  switch (k % 6) {\n    case 0: c.beginPath(); c.arc(w * .56, h * .42, 150, 0, TAU); c.fill(); break;\n    case 1: for (x = 0; x \u003c w; x += 18) c.fillRect(x, 0, 12 * (.15 + x \/ w), h); break;\n    case 2: for (r = 20; r \u003c 340; r += 22) { c.lineWidth = r \/ 28; c.beginPath(); c.ellipse(w \/ 2, h * .45, r, r * .62, -.4, 0, TAU); c.stroke(); } break;\n    case 3: c.save(); c.translate(w \/ 2, h \/ 2); c.rotate(-.5); for (y = -500; y \u003c 500; y += 60) c.fillRect(-500, y, 1000, 26); c.restore(); break;\n    case 4: for (y = 10; y \u003c h; y += 16) for (x = 10; x \u003c w; x += 16) { c.beginPath(); c.arc(x, y, 7 * (y \/ h), 0, TAU); c.fill(); } c.fillStyle = ac; c.fillRect(60, 70, 130, 130); break;\n    case 5: c.lineWidth = 3; c.font = '900 560px \"Arial Black\",Arial,sans-serif'; c.textAlign = 'center'; c.textBaseline = 'middle'; c.strokeText('G', w \/ 2, h * .5); break;\n  }\n  c.fillStyle = ac; c.textAlign = 'left'; c.textBaseline = 'alphabetic';\n  c.font = '900 96px \"Arial Black\",Arial,sans-serif'; c.fillText(WORDS[k % 6], 20, h - 28);\n  c.font = '700 13px monospace'; c.fillText('PLACEHOLDER · REPLACE IN CONFIG', 20, 34);\n  var img = c.getImageData(0, 0, w, h), d = img.data, n, i;\n  for (i = 0; i \u003c d.length; i += 4) { n = (Math.random() - .5) * 40; d[i] += n; d[i + 1] += n; d[i + 2] += n; }\n  c.putImageData(img, 0, 0);\n}\nfunction paintReel(c, w, h, t, k) {\n  var i, y, cx = w \/ 2, cy = h * .45, R = w * .3, ph = t * 2.4;\n  c.fillStyle = '#0c0b09'; c.fillRect(0, 0, w, h);\n  for (i = 0; i \u003c 9; i++) { y = ((i \/ 9 + t * .12) % 1) * h; c.fillStyle = i % 3 ? 'rgba(228,178,58,.06)' : 'rgba(255,59,20,.09)'; c.fillRect(0, y, w, 14); }\n  if (k % 2 === 0) {\n    var sx = Math.abs(Math.cos(ph)), g = c.createLinearGradient(cx - R, 0, cx + R, 0);\n    g.addColorStop(0, '#7a5410'); g.addColorStop(.5 + .42 * Math.sin(ph), '#fff0b0'); g.addColorStop(1, '#a8791a');\n    c.lineWidth = 16; c.strokeStyle = g; c.beginPath(); c.ellipse(cx, cy, Math.max(1.5, sx * R), R, 0, 0, TAU); c.stroke();\n    c.fillStyle = '#fff'; c.beginPath(); c.moveTo(cx, cy - R - 32); c.lineTo(cx + 12 * sx + 3, cy - R - 15); c.lineTo(cx, cy - R + 2); c.lineTo(cx - 12 * sx - 3, cy - R - 15); c.closePath(); c.fill();\n  } else {\n    c.save(); c.translate(cx, cy); c.rotate(Math.sin(ph * .5) * .3); c.scale(1, 1.5 + .9 * Math.sin(ph));\n    c.font = '900 72px \"Arial Black\",Arial,sans-serif'; c.textAlign = 'center'; c.textBaseline = 'middle';\n    c.strokeStyle = '#ff3b14'; c.lineWidth = 2; c.strokeText('FUNK', 6, 6); c.fillStyle = '#e4b23a'; c.fillText('FUNK', 0, 0); c.restore();\n  }\n  c.fillStyle = '#e4b23a'; c.font = '700 15px monospace'; c.textAlign = 'left'; c.textBaseline = 'alphabetic';\n  c.fillText('00:' + pad2(Math.floor(t \/ 60) % 60) + ':' + pad2(Math.floor(t) % 60) + ':' + pad2(Math.floor(t * 25) % 25), 14, h - 18);\n  c.fillText('PLACEHOLDER REEL', 14, h - 40);\n  if (Math.floor(t * 2) % 2 === 0) { c.fillStyle = '#ff3b14'; c.beginPath(); c.arc(w - 22, 22, 6, 0, TAU); c.fill(); }\n}\n\n\/* =============================== experience =============================== *\/\nfunction init(root) {\n  if (root.getAttribute('data-gfx-ready')) return;\n  root.setAttribute('data-gfx-ready', '1');\n\n  var RM = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n  var FINE = window.matchMedia('(hover:hover) and (pointer:fine)').matches;\n  function $(s) { return root.querySelector(s); }\n  var stage = $('.gfx-stage'), mat = $('.gfx-mat'), wordsEl = $('.gfx-words'), secretsEl = $('.gfx-secrets'), objLayer = $('.gfx-objects'),\n      topLayer = $('.gfx-top'), xray = $('.gfx-xray'), canvas = $('.gfx-dust'), ctx = canvas.getContext('2d'), introEl = $('.gfx-intro'),\n      toastEl = $('.gfx-toast'), tT = $('.gfx-tt'), tS = $('.gfx-ts'), hintEl = $('.gfx-hint'), xyEl = $('.gfx-xy'), objEl = $('.gfx-obj'),\n      cursorEl = $('.gfx-cursor'), cring = $('.gfx-cring'), cdot = $('.gfx-cdot'), clabel = $('.gfx-clabel');\n\n  var W = 0, H = 0, dpr = 1, rect = stage.getBoundingClientRect(), mobile = false, cardW = 200, placed = false;\n  var bodies = [], vids = [], loupe = null, zc = 10, dragging = null, hoverB = null, hoverT = 0, hoverKind = '';\n  var live = false, visible = false, started = false, introDone = false, raf = 0, last = ms(), frame = 0;\n  var px = -999, py = -999, pIn = false, cx = 0, cy = 0, cAng = 0, cStretch = 1, cSize = 0, cText = '', idleT = ms(), nudgeT = 0;\n  var midas = false, funk = 0, beatT = 0, pileLock = false, shakeT = 0, scrollP = 0;\n  var media = (GOLDFUNK.media || []).filter(Boolean).slice(0, 14);\n\n  \/* ---------------- discoveries ---------------- *\/\n  var DISC = [\n    ['FLIP', 'EVERY PRINT HAS A BACK.', 'They all say something. Read them.'],\n    ['UNDER', 'YOU LOOKED UNDERNEATH.', 'The table keeps notes too.'],\n    ['RING', 'YOU FOUND THE RING.', GOLDFUNK.ringReward],\n    ['THROW', 'OUCH.', 'Handle with zero care.'],\n    ['XRAY', 'X-RAY VISION.', 'The table has another side.'],\n    ['MIDAS', 'EVERYTHING YOU TOUCH TURNS TO GOLD.', 'Touch a print. Spell GOLD again to stop.'],\n    ['FUNK', 'FUNK MODE.', '116 BPM. Nothing stays where you left it.'],\n    ['PILE', 'NEAT FREAK DETECTED.', '…just kidding.'],\n    ['SPEED', 'YOU BROKE THE TIMELINE.', 'Speed = playback. You figured it out.']\n  ];\n  var found = {}, foundN = 0, dotsEl = $('.gfx-dots');\n  $('.gfx-ft').textContent = DISC.length;\n  DISC.forEach(function () { dotsEl.appendChild(document.createElement('i')); });\n  function disc(key, again) {\n    var i, d;\n    for (i = 0; i \u003c DISC.length; i++) if (DISC[i][0] === key) d = DISC[i];\n    if (found[key]) { if (again) toast(d[1], d[2]); return; }\n    found[key] = true; foundN++;\n    dotsEl.children[foundN - 1].className = 'is-on';\n    $('.gfx-fn').textContent = foundN;\n    toast(d[1], 'Discovery ' + pad2(foundN) + '\/' + pad2(DISC.length) + ' — ' + d[2], key === 'RING' ? 4600 : 2500);\n    if (foundN === DISC.length) setTimeout(function () {\n      root.classList.add('is-complete'); toast('THE PAGE WAS NEVER EMPTY.', GOLDFUNK.finalMessage, 6500);\n      emit(W \/ 2, H \/ 2, 260, 1100, 300);\n    }, 1200);\n  }\n  var tq = [], tBusy = false;\n  function toast(t, s, d) { tq.push([t, s, d || 2500]); if (!tBusy) nextToast(); }\n  function nextToast() {\n    var it = tq.shift(); if (!it) { tBusy = false; return; }\n    tBusy = true; tT.innerHTML = '\u003cspan\u003e' + esc(it[0]) + '\u003c\/span\u003e'; tS.textContent = it[1] || '';\n    toastEl.classList.remove('is-on'); void toastEl.offsetWidth; toastEl.classList.add('is-on');\n    setTimeout(function () { toastEl.classList.remove('is-on'); setTimeout(nextToast, 520); }, it[2]);\n  }\n\n  \/* ---------------- gold dust ---------------- *\/\n  var P = [], dusty = false;\n  function emit(x, y, n, spd, up) {\n    if (RM || !visible) return;\n    for (var i = 0; i \u003c n \u0026\u0026 P.length \u003c 560; i++) {\n      var a = Math.random() * TAU, s = Math.random() * spd;\n      P.push({ x: x, y: y, vx: Math.cos(a) * s, vy: Math.sin(a) * s - (up || 0), l: 1, d: rnd(.5, 1.7), z: rnd(1, 2.8) });\n    }\n  }\n  function dust(dt) {\n    if (!P.length) { if (dusty) { ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); dusty = false; } return; }\n    ctx.setTransform(dpr, 0, 0, dpr, 0, 0); ctx.globalCompositeOperation = 'source-over'; ctx.clearRect(0, 0, W, H); ctx.globalCompositeOperation = 'lighter';\n    var k = 1 - 1.8 * dt;\n    for (var i = P.length - 1; i \u003e= 0; i--) {\n      var p = P[i]; p.l -= dt \/ p.d;\n      if (p.l \u003c= 0) { P[i] = P[P.length - 1]; P.pop(); continue; }\n      p.vx *= k; p.vy = p.vy * k + 70 * dt; p.x += p.vx * dt; p.y += p.vy * dt;\n      ctx.globalAlpha = Math.min(1, p.l * 1.5); ctx.fillStyle = p.l \u003e .6 ? '#ffe28a' : '#d9a233'; ctx.fillRect(p.x, p.y, p.z, p.z);\n    }\n    ctx.globalAlpha = 1; dusty = true;\n  }\n  function shake() { if (RM || ms() - shakeT \u003c 400) return; shakeT = ms(); objLayer.classList.remove('is-shake'); void objLayer.offsetWidth; objLayer.classList.add('is-shake'); }\n\n  \/* ---------------- objects ---------------- *\/\n  function body(el, kind) {\n    return { el: el, kind: kind, x: 0, y: 0, a: 0, vx: 0, vy: 0, va: 0, w: 0, h: 0, I: 1, mode: null, pts: {}, np: 0, pid: 0, lx: 0, ly: 0, tx: 0, ty: 0,\n      hx: 0, hy: 0, ha: 0, hover: false, flipped: false, gold: false, thrown: false, lastTap: 0, downT: 0, moved: 0, rPrev: 0, lastAT: 0, ox: 0, oy: 0,\n      player: null, rateEl: null, rateV: 0, idle: 0, key: '', num: '', homeT: 0 };\n  }\n  function makePlayer(item, k) {\n    if (item.src) {\n      var v = document.createElement('video'), loaded = false, on = false;\n      v.muted = true; v.defaultMuted = true; v.loop = true; v.playsInline = true; v.preload = 'none';\n      ['muted', 'playsinline', 'loop', 'disablepictureinpicture'].forEach(function (a) { v.setAttribute(a, ''); });\n      if (item.poster) v.poster = sized(item.poster, 600);\n      return { el: v,\n        load: function () { if (!loaded) { loaded = true; v.preload = 'metadata'; v.src = item.src + (item.src.indexOf('#') \u003e -1 ? '' : '#t=0.1'); } },\n        play: function () { this.load(); if (!on) { on = true; var p = v.play(); if (p \u0026\u0026 p.catch) p.catch(function () { on = false; }); } },\n        pause: function () { if (on) { on = false; v.pause(); } },\n        rate: function (r) { if (Math.abs(v.playbackRate - r) \u003e .04) { try { v.playbackRate = r; } catch (e) {} } },\n        tick: function () {} };\n    }\n    var cv = document.createElement('canvas'), c = cv.getContext('2d'), t = 1 + k * 3.1, run = false, r = 1;\n    cv.width = 270; cv.height = 436; paintReel(c, 270, 436, t, k);\n    return { el: cv, load: function () {}, play: function () { run = true; }, pause: function () { run = false; }, rate: function (x) { r = x; },\n      tick: function (dt) { if (run) { t += dt * r; paintReel(c, 270, 436, t, k); } } };\n  }\n  function placeholder(m, i) { var cv = document.createElement('canvas'); paintPrint(cv, i); m.appendChild(cv); return cv; }\n  function makeCard(item, i) {\n    var el = document.createElement('div'), isV = item.type === 'video', num = pad2(i + 1);\n    el.className = 'gfx-card' + (isV ? ' is-video' : '');\n    el.tabIndex = 0; el.setAttribute('role', 'button');\n    el.setAttribute('aria-label', (item.caption || 'Print ' + num) + '. Drag to move, double-click or press Enter to flip, arrow keys to push.');\n    el.style.setProperty('--tr', rnd(-14, 14).toFixed(1) + 'deg'); el.style.setProperty('--tx', rnd(28, 72).toFixed(0) + '%');\n    el.innerHTML = '\u003cdiv class=\"gfx-lift\"\u003e\u003cdiv class=\"gfx-flip\"\u003e\u003cdiv class=\"gfx-face gfx-front\"\u003e\u003cdiv class=\"gfx-media\"\u003e\u003c\/div\u003e\u003cdiv class=\"gfx-cap\"\u003e\u003cspan\u003eNº' + num + '\u003c\/span\u003e\u003cspan\u003e' + esc(item.caption || 'UNTITLED') + '\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e' +\n      '\u003cdiv class=\"gfx-face gfx-back\"\u003e\u003cp class=\"gfx-note\"\u003e' + esc(item.note || '…') + '\u003c\/p\u003e\u003cdiv class=\"gfx-stamp\"\u003eGOLDFUNK\u003cbr\u003eARCHIVE Nº' + num + '\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cspan class=\"gfx-rot\" aria-hidden=\"true\"\u003e↻\u003c\/span\u003e';\n    var m = el.querySelector('.gfx-media'), b = body(el, isV ? 'video' : 'print');\n    b.num = num; b.item = item;\n    if (isV) {\n      b.player = makePlayer(item, vids.length); m.appendChild(b.player.el);\n      b.rateEl = document.createElement('span'); b.rateEl.className = 'gfx-rate'; b.rateEl.textContent = '×1.00'; m.appendChild(b.rateEl);\n      vids.push(b);\n    } else if (item.src) {\n      var img = new Image(); img.alt = item.alt || item.caption || ''; img.decoding = 'async'; img.draggable = false;\n      if (isShop(item.src)) { img.srcset = [360, 540, 800].map(function (w) { return sized(item.src, w) + ' ' + w + 'w'; }).join(','); img.sizes = '(max-width:700px) 40vw, 260px'; }\n      img.onerror = function () { img.onerror = null; var cv = document.createElement('canvas'); paintPrint(cv, i); img.replaceWith(cv); };\n      img.src = sized(item.src, 800); m.appendChild(img);\n    } else placeholder(m, i);\n    objLayer.appendChild(el); attach(b); return b;\n  }\n  function makeLoupe() {\n    var el = document.createElement('div'); el.className = 'gfx-loupe'; el.tabIndex = 0; el.setAttribute('role', 'button');\n    el.setAttribute('aria-label', 'X-ray loupe. Drag it across the table.');\n    el.innerHTML = '\u003cdiv class=\"gfx-lift\"\u003e\u003cspan class=\"gfx-lhandle\"\u003e\u003c\/span\u003e\u003cspan class=\"gfx-lglass\"\u003e\u003c\/span\u003e\u003cspan class=\"gfx-llabel\"\u003eX-RAY\u003c\/span\u003e\u003c\/div\u003e';\n    topLayer.appendChild(el); var b = body(el, 'loupe'); b.num = 'XR'; attach(b); return b;\n  }\n  function setSize(b) {\n    var w, h;\n    if (b.kind === 'loupe') { w = h = mobile ? 112 : 156; b.el.style.setProperty('--d', w + 'px'); }\n    else {\n      var ratio = b.item.ratio || (b.kind === 'video' ? .62 : .8);\n      w = Math.round(cardW * (b.kind === 'video' ? .86 : 1)); h = Math.round((w - 14) \/ ratio + 38);\n      b.el.style.setProperty('--w', w + 'px'); b.el.style.setProperty('--h', h + 'px');\n    }\n    b.w = w; b.h = h; b.I = (w * w + h * h) \/ 12;\n  }\n  function layout(snap) {\n    var n = media.length, rand = seeded(11), cols = mobile ? 3 : Math.max(2, Math.round(Math.sqrt(n * W \/ H * 1.1))), rows = Math.ceil(n \/ cols),\n        x0 = W * (mobile ? .08 : .13), x1 = W * (mobile ? .92 : .84), y0 = H * (mobile ? .27 : .3), y1 = H * (mobile ? .76 : .74), i = 0;\n    bodies.forEach(function (b) {\n      if (b.kind === 'loupe') { b.hx = W * (mobile ? .8 : .9); b.hy = H * (mobile ? .16 : .34); b.ha = 0; }\n      else {\n        var c = i % cols, r = Math.floor(i \/ cols), inRow = Math.min(cols, n - r * cols);\n        b.hx = x0 + (c + .5 + (cols - inRow) \/ 2) \/ cols * (x1 - x0) + (rand() - .5) * cardW * .4;\n        b.hy = (rows \u003c 2 ? (y0 + y1) \/ 2 : y0 + r \/ (rows - 1) * (y1 - y0)) + (rand() - .5) * cardW * .3;\n        b.ha = (rand() - .5) * .55; i++;\n      }\n      if (snap) { b.x = b.hx; b.y = b.hy; b.a = b.ha; }\n    });\n  }\n  function raise(b) { if (b.kind !== 'loupe') b.el.style.zIndex = ++zc; }\n  function flip(b) { b.flipped = !b.flipped; b.el.classList.toggle('is-flipped', b.flipped); if (!RM) b.va += rnd(-1.2, 1.2); disc('FLIP'); }\n  function gild(b, x, y) { if (midas \u0026\u0026 b.kind !== 'loupe' \u0026\u0026 !b.gold) { b.gold = true; b.el.classList.add('is-gold'); emit(x, y, 46, 520); } }\n\n  \/* ---------------- pointer input ---------------- *\/\n  function pt(e) { return { x: e.clientX - rect.left, y: e.clientY - rect.top }; }\n  function grabAt(b, p) {\n    var dx = p.x - b.x, dy = p.y - b.y, c = Math.cos(b.a), s = Math.sin(b.a);\n    b.lx = dx * c + dy * s; b.ly = -dx * s + dy * c; b.tx = p.x; b.ty = p.y; b.mode = 'drag';\n  }\n  function two(b) { var k = Object.keys(b.pts); return [b.pts[k[0]], b.pts[k[1]]]; }\n  function spin(b, na, t) { var d = Math.max(.008, (t - b.lastAT) \/ 1000); b.va = b.va * .5 + (na - b.a) \/ d * .5; b.a = na; b.lastAT = t; }\n  function attach(b) {\n    var el = b.el;\n    el.addEventListener('pointerdown', function (e) {\n      if (!live || (e.pointerType === 'mouse' \u0026\u0026 e.button !== 0)) return;\n      e.preventDefault(); rect = stage.getBoundingClientRect();\n      var p = pt(e), t = ms();\n      if (!b.pts[e.pointerId]) b.np++;\n      b.pts[e.pointerId] = p;\n      try { el.setPointerCapture(e.pointerId); } catch (err) {}\n      raise(b); idleT = t; b.lastAT = t;\n      if (b.np === 2 \u0026\u0026 b.kind !== 'loupe') {\n        var q = two(b); b.mode = 'pinch'; b.rPrev = Math.atan2(q[1].y - q[0].y, q[1].x - q[0].x);\n        b.ox = b.x - (q[0].x + q[1].x) \/ 2; b.oy = b.y - (q[0].y + q[1].y) \/ 2; b.vx = b.vy = 0; b.moved = 99;\n      } else if (b.np === 1) {\n        b.pid = e.pointerId; b.downT = t; b.moved = 0;\n        if (e.target.classList \u0026\u0026 e.target.classList.contains('gfx-rot')) { b.mode = 'rotate'; b.rPrev = Math.atan2(p.y - b.y, p.x - b.x); b.vx = b.vy = 0; b.moved = 99; }\n        else grabAt(b, p);\n      }\n      el.classList.add('is-held'); dragging = b; gild(b, p.x, p.y);\n      if (b.player) b.player.play();\n    });\n    el.addEventListener('pointermove', function (e) {\n      var prev = b.pts[e.pointerId]; if (!prev) return;\n      var p = pt(e), t = ms(), a; b.pts[e.pointerId] = p; b.moved += Math.abs(p.x - prev.x) + Math.abs(p.y - prev.y);\n      if (b.mode === 'drag' \u0026\u0026 e.pointerId === b.pid) { b.tx = p.x; b.ty = p.y; }\n      else if (b.mode === 'rotate') { a = Math.atan2(p.y - b.y, p.x - b.x); spin(b, b.a + angDiff(a, b.rPrev), t); b.rPrev = a; }\n      else if (b.mode === 'pinch' \u0026\u0026 b.np \u003e= 2) {\n        var q = two(b), d = Math.max(.008, (t - b.lastAT) \/ 1000), nx = (q[0].x + q[1].x) \/ 2 + b.ox, ny = (q[0].y + q[1].y) \/ 2 + b.oy;\n        a = Math.atan2(q[1].y - q[0].y, q[1].x - q[0].x);\n        b.vx = b.vx * .5 + (nx - b.x) \/ d * .5; b.vy = b.vy * .5 + (ny - b.y) \/ d * .5; b.x = nx; b.y = ny;\n        spin(b, b.a + angDiff(a, b.rPrev), t); b.rPrev = a;\n      }\n    });\n    function up(e) {\n      if (!b.pts[e.pointerId]) return;\n      delete b.pts[e.pointerId]; b.np--;\n      try { el.releasePointerCapture(e.pointerId); } catch (err) {}\n      if (b.np === 1) { var k = Object.keys(b.pts)[0]; b.pid = +k; grabAt(b, b.pts[k]); return; }\n      if (b.np \u003e 0) return;\n      b.mode = null; el.classList.remove('is-held'); if (dragging === b) dragging = null;\n      var sp = Math.sqrt(b.vx * b.vx + b.vy * b.vy), t = ms();\n      if (RM) { b.vx *= .15; b.vy *= .15; b.va *= .15; }\n      else if (sp \u003e 4200) { b.vx *= 4200 \/ sp; b.vy *= 4200 \/ sp; }\n      b.va = clamp(b.va, -30, 30); b.thrown = sp \u003e 900;\n      if (b.moved \u003c 9 \u0026\u0026 t - b.downT \u003c 320 \u0026\u0026 b.kind !== 'loupe') {\n        if (t - b.lastTap \u003c 400) { flip(b); b.lastTap = 0; } else b.lastTap = t;\n      }\n    }\n    el.addEventListener('pointerup', up); el.addEventListener('pointercancel', up);\n    el.addEventListener('pointerenter', function (e) { if (e.pointerType === 'mouse') { b.hover = true; hoverB = b; hoverT = ms(); } });\n    el.addEventListener('pointerleave', function (e) { if (e.pointerType === 'mouse') { b.hover = false; if (hoverB === b) hoverB = null; } });\n    el.addEventListener('dragstart', function (e) { e.preventDefault(); });\n    el.addEventListener('keydown', function (e) {\n      var k = e.key, f = e.shiftKey ? 1000 : 420;\n      if ((k === 'Enter' || k === ' ') \u0026\u0026 b.kind !== 'loupe') { e.preventDefault(); flip(b); }\n      else if (k.indexOf('Arrow') === 0) {\n        e.preventDefault(); raise(b); if (RM) f *= .4;\n        if (k === 'ArrowLeft') b.vx -= f; if (k === 'ArrowRight') b.vx += f; if (k === 'ArrowUp') b.vy -= f; if (k === 'ArrowDown') b.vy += f;\n        gild(b, b.x, b.y);\n      } else if (k === 'r' || k === 'R') b.va += e.shiftKey ? -3 : 3;\n    });\n  }\n\n  \/* ---------------- physics ---------------- *\/\n  var REST = .52;\n  function impact(b, v, x, y) {\n    if (v \u003e 320) emit(x, y, Math.min(60, v \/ 45 | 0), v * .35);\n    if (v \u003e 1500 \u0026\u0026 b.thrown) { b.thrown = false; shake(); disc('THROW'); }\n  }\n  function walls(b) {\n    var c = Math.abs(Math.cos(b.a)), s = Math.abs(Math.sin(b.a)), ex = Math.min((c * b.w + s * b.h) \/ 2, W \/ 2), ey = Math.min((s * b.w + c * b.h) \/ 2, H \/ 2), v;\n    if (b.x \u003c ex) { b.x = ex; if (b.vx \u003c 0) { v = -b.vx; if (b.mode) b.vx = 0; else { b.va -= b.vy * .0035; b.vx = v * REST; impact(b, v, 0, b.y); } } }\n    else if (b.x \u003e W - ex) { b.x = W - ex; if (b.vx \u003e 0) { v = b.vx; if (b.mode) b.vx = 0; else { b.va += b.vy * .0035; b.vx = -v * REST; impact(b, v, W, b.y); } } }\n    if (b.y \u003c ey) { b.y = ey; if (b.vy \u003c 0) { v = -b.vy; if (b.mode) b.vy = 0; else { b.va += b.vx * .0035; b.vy = v * REST; impact(b, v, b.x, 0); } } }\n    else if (b.y \u003e H - ey) { b.y = H - ey; if (b.vy \u003e 0) { v = b.vy; if (b.mode) b.vy = 0; else { b.va -= b.vx * .0035; b.vy = -v * REST; impact(b, v, b.x, H); } } }\n  }\n  function step(b, h) {\n    if (b.mode === 'rotate' || b.mode === 'pinch') return;\n    if (b.mode === 'drag') {\n      \/* a spring pulls the exact point you grabbed towards the pointer; grabbing off-centre makes the print swing *\/\n      var c = Math.cos(b.a), s = Math.sin(b.a), rx = b.lx * c - b.ly * s, ry = b.lx * s + b.ly * c,\n          K = 1000, C = 54, fx = K * (b.tx - b.x - rx) - C * (b.vx - b.va * ry), fy = K * (b.ty - b.y - ry) - C * (b.vy + b.va * rx);\n      b.vx += fx * h; b.vy += fy * h;\n      if (!RM) b.va += (rx * fy - ry * fx) \/ b.I * h;\n      var f = Math.exp(-3.5 * h); b.vx *= f; b.vy *= f; b.va *= Math.exp(-5 * h);\n    } else if (b.mode === 'home') {\n      b.vx += (120 * (b.hx - b.x) - 20 * b.vx) * h; b.vy += (120 * (b.hy - b.y) - 20 * b.vy) * h; b.va += (120 * angDiff(b.ha, b.a) - 20 * b.va) * h;\n      if (ms() \u003e b.homeT) b.mode = null;\n    } else {\n      var fr = Math.exp(-(RM ? 9 : 2.3) * h); b.vx *= fr; b.vy *= fr; b.va *= Math.exp(-(RM ? 9 : 2.7) * h);\n    }\n    b.x += b.vx * h; b.y += b.vy * h; b.a += b.va * h;\n    walls(b);\n  }\n  function inside(b, x, y, pad) {\n    var dx = x - b.x, dy = y - b.y, c = Math.cos(b.a), s = Math.sin(b.a);\n    return Math.abs(dx * c + dy * s) \u003c b.w \/ 2 + pad \u0026\u0026 Math.abs(-dx * s + dy * c) \u003c b.h \/ 2 + pad;\n  }\n\n  \/* ---------------- hidden things ---------------- *\/\n  var secrets = [], spot = { px: .2, py: .64 };\n  function buildSecrets() {\n    var prints = bodies.filter(function (b) { return b.kind !== 'loupe'; }), texts = GOLDFUNK.secrets || [], n = prints.length;\n    var idx = [0, Math.floor(n \/ 2), n - 1, Math.min(n - 1, 3)], used = {};\n    idx.forEach(function (bi, j) {\n      var b = prints[bi], isRing = j === 3; if (!b || used[bi] || (!isRing \u0026\u0026 !texts[j])) return; used[bi] = 1;\n      var el = document.createElement(isRing ? 'button' : 'div');\n      el.className = 'gfx-sec' + (isRing ? ' gfx-ring' : '');\n      if (isRing) { el.type = 'button'; el.tabIndex = -1; el.setAttribute('aria-label', 'A hidden gold ring'); el.addEventListener('click', function () { emit(b.hx, b.hy, 90, 620, 120); disc('RING', true); }); }\n      else { el.textContent = texts[j]; el.style.setProperty('--r', rnd(-9, 9).toFixed(1) + 'deg'); }\n      el.style.left = (b.hx \/ W * 100) + '%'; el.style.top = (b.hy \/ H * 100) + '%';\n      secretsEl.appendChild(el); secrets.push({ el: el, px: b.hx \/ W, py: b.hy \/ H, ring: isRing, found: false });\n    });\n  }\n  function checkSecrets() {\n    secrets.forEach(function (s) {\n      if (s.found) return;\n      var x = s.px * W, y = s.py * H, i;\n      for (i = 0; i \u003c bodies.length; i++) if (bodies[i].kind !== 'loupe' \u0026\u0026 inside(bodies[i], x, y, 12)) return;\n      s.found = true; s.el.classList.add('is-found'); emit(x, y, 26, 300);\n      if (s.ring) { s.el.tabIndex = 0; } else disc('UNDER');\n    });\n  }\n  function checkPile() {\n    var ps = bodies.filter(function (b) { return b.kind !== 'loupe'; }), mx = 0, my = 0, lim = Math.max(60, cardW * .45), i;\n    if (ps.length \u003c 3 || dragging || pileLock) return;\n    ps.forEach(function (b) { mx += b.x; my += b.y; }); mx \/= ps.length; my \/= ps.length;\n    for (i = 0; i \u003c ps.length; i++) if (Math.abs(ps[i].x - mx) + Math.abs(ps[i].y - my) \u003e lim || Math.abs(ps[i].vx) + Math.abs(ps[i].vy) \u003e 80) return;\n    pileLock = true; disc('PILE', true);\n    setTimeout(function () {\n      ps.forEach(function (b, j) { var a = j \/ ps.length * TAU + rnd(-.3, .3), s = rnd(1500, 2700) * (RM ? .25 : 1); b.vx = Math.cos(a) * s; b.vy = Math.sin(a) * s; b.va = RM ? 0 : rnd(-9, 9); b.thrown = false; });\n      emit(mx, my, 140, 950); shake(); setTimeout(function () { pileLock = false; }, 3500);\n    }, 1300);\n  }\n  function setMidas(on) {\n    midas = on; root.classList.toggle('is-midas', on);\n    if (on) { disc('MIDAS', true); emit(W \/ 2, H \/ 2, 120, 900, 200); }\n    else { bodies.forEach(function (b) { b.gold = false; b.el.classList.remove('is-gold'); }); }\n  }\n  function beat() {\n    letters.forEach(function (L, i) { L.bs = .1 + (i % 2) * .08; });\n    mat.classList.add('is-beat'); setTimeout(function () { mat.classList.remove('is-beat'); }, 100);\n    bodies.forEach(function (b) { if (b.mode) return; b.vx += rnd(-300, 300); b.vy += rnd(-300, 300); b.va += rnd(-2.6, 2.6); b.thrown = false; });\n    emit(rnd(0, W), rnd(0, H), 26, 600);\n  }\n\n  \/* ---------------- the letters: G O L D F U N K ---------------- *\/\n  var letters = [].map.call(wordsEl.children, function (el, i) { return { el: el, ch: el.textContent, i: i, cx: 0, cy: 0, ox: 0, oy: 0, bs: 0, key: '' }; });\n  var seq = '', seqT = 0, seqClear = 0;\n  function lightSeq() {\n    letters.forEach(function (L) { L.el.classList.remove('is-lit'); });\n    if (!seq) return;\n    var base = seq.charAt(0) === 'G' ? 0 : 4;\n    for (var i = 0; i \u003c seq.length; i++) letters[base + i].el.classList.add('is-lit');\n    letters[base + seq.length - 1].bs = .2;\n  }\n  function spell(ch) {\n    if (!live) return;\n    ch = ch.toUpperCase(); idleT = ms();\n    var T = ['GOLD', 'FUNK'], s = seq + ch;\n    function ok(x) { return T[0].indexOf(x) === 0 || T[1].indexOf(x) === 0; }\n    if (seq.length === 4 || !ok(s)) s = ok(ch) ? ch : '';\n    seq = s; seqT = ms(); lightSeq();\n    if (s.length === 4) {\n      clearTimeout(seqClear); seqClear = setTimeout(function () { seq = ''; lightSeq(); }, 900);\n      if (s === 'GOLD') setMidas(!midas);\n      else { disc('FUNK', true); if (!RM) { funk = 16; beatT = 0; root.classList.add('is-funk'); } }\n    }\n  }\n  letters.forEach(function (L) { L.el.addEventListener('click', function () { spell(L.ch); }); });\n  function onKey(e) {\n    if (!root.isConnected) { document.removeEventListener('keydown', onKey); return; }\n    if (!visible || e.metaKey || e.ctrlKey || e.altKey) return;\n    var t = e.target;\n    if (t \u0026\u0026 (t.isContentEditable || \/^(INPUT|TEXTAREA|SELECT)$\/.test(t.tagName))) return;\n    if (\/^[a-zA-Z]$\/.test(e.key)) spell(e.key);\n  }\n  document.addEventListener('keydown', onKey);\n\n  \/* ---------------- hud buttons (magnetic) ---------------- *\/\n  var btns = [].map.call(root.querySelectorAll('.gfx-btn'), function (el) { return { el: el, cx: 0, cy: 0, ox: 0, oy: 0 }; });\n  $('.gfx-meta').addEventListener('click', function (e) {\n    var act = e.target.getAttribute \u0026\u0026 e.target.getAttribute('data-act'); if (!act || !live) return;\n    idleT = ms();\n    if (act === 'shuffle') bodies.forEach(function (b) { var a = Math.random() * TAU, s = rnd(1100, 2300) * (RM ? .25 : 1); b.mode = null; b.vx = Math.cos(a) * s; b.vy = Math.sin(a) * s; b.va = RM ? 0 : rnd(-8, 8); b.thrown = false; });\n    else {\n      if (midas) setMidas(false);\n      bodies.forEach(function (b) { b.mode = 'home'; b.homeT = ms() + 1500; b.flipped = false; b.el.classList.remove('is-flipped'); if (RM) { b.x = b.hx; b.y = b.hy; b.a = b.ha; b.vx = b.vy = b.va = 0; b.mode = null; } });\n    }\n  });\n\n  \/* ---------------- stage-level pointer (cursor, coordinates) ---------------- *\/\n  stage.addEventListener('pointermove', function (e) {\n    var nx = e.clientX - rect.left, ny = e.clientY - rect.top, d = Math.abs(nx - px) + Math.abs(ny - py);\n    if (live \u0026\u0026 pIn \u0026\u0026 e.pointerType === 'mouse' \u0026\u0026 d \u003e 7 \u0026\u0026 d \u003c 300) emit(nx, ny, midas ? 3 : (d \u003e 26 ? 2 : (frame % 3 === 0 ? 1 : 0)), 60, 10);\n    px = nx; py = ny; idleT = ms();\n    if (!pIn) { pIn = true; cx = px; cy = py; }\n    if (FINE \u0026\u0026 e.pointerType === 'mouse') stage.classList.add('has-cursor');\n  });\n  stage.addEventListener('pointerleave', function () { pIn = false; stage.classList.remove('has-cursor'); });\n  stage.addEventListener('pointerover', function (e) {\n    var t = e.target, c = t.classList; if (!c) return;\n    hoverKind = c.contains('gfx-rot') ? 'rot' : c.contains('gfx-w') ? 'letter' : (c.contains('gfx-btn') || c.contains('gfx-ring') || c.contains('gfx-dnt')) ? 'btn' : '';\n  });\n\n  \/* ---------------- measure \/ resize ---------------- *\/\n  function measure() {\n    rect = stage.getBoundingClientRect();\n    var nW = stage.clientWidth, nH = stage.clientHeight; if (!nW || !nH) return;\n    var sx = W ? nW \/ W : 1, sy = H ? nH \/ H : 1;\n    W = nW; H = nH; mobile = W \u003c 700;\n    cardW = mobile ? clamp(W * .33, 108, 170) : clamp(W * .15, 168, 248);\n    dpr = Math.min(1.5, window.devicePixelRatio || 1); canvas.width = Math.round(W * dpr); canvas.height = Math.round(H * dpr);\n    bodies.forEach(function (b) { setSize(b); b.x *= sx; b.y *= sy; b.key = ''; });\n    layout(!placed);\n    if (!placed) { placed = true; buildSecrets(); }\n    spot.px = mobile ? .32 : .2; spot.py = mobile ? .66 : .64;\n    var sp = xray.querySelector('.gfx-xspot'); if (sp) { sp.style.left = spot.px * 100 + '%'; sp.style.top = spot.py * 100 + '%'; }\n    letters.forEach(function (L) { var r = L.el.getBoundingClientRect(); L.cx = r.left - rect.left + r.width \/ 2 - L.ox; L.cy = r.top - rect.top + r.height \/ 2 - L.oy; });\n    btns.forEach(function (B) { var r = B.el.getBoundingClientRect(); B.cx = r.left - rect.left + r.width \/ 2 - B.ox; B.cy = r.top - rect.top + r.height \/ 2 - B.oy; });\n  }\n  function onScroll() {\n    if (!root.isConnected) { window.removeEventListener('scroll', onScroll); return; }\n    rect = stage.getBoundingClientRect(); scrollP = clamp(-rect.top \/ (rect.height || 1), -1, 1);\n    if (!RM) wordsEl.style.transform = 'translate3d(' + (-scrollP * 9).toFixed(2) + '%,' + (-50 + scrollP * 18).toFixed(2) + '%,0)';\n  }\n  window.addEventListener('scroll', onScroll, { passive: true });\n\n  \/* ---------------- main loop ---------------- *\/\n  function render() {\n    for (var i = 0; i \u003c bodies.length; i++) {\n      var b = bodies[i], k = (b.x * 8 | 0) + '_' + (b.y * 8 | 0) + '_' + (b.a * 800 | 0);\n      if (k === b.key) continue; b.key = k;\n      b.el.style.transform = 'translate3d(' + (b.x - b.w \/ 2).toFixed(2) + 'px,' + (b.y - b.h \/ 2).toFixed(2) + 'px,0) rotate(' + b.a.toFixed(4) + 'rad)';\n      if (b === loupe) { var cp = 'circle(' + (b.w \/ 2 - 3) + 'px at ' + b.x.toFixed(1) + 'px ' + b.y.toFixed(1) + 'px)'; xray.style.webkitClipPath = cp; xray.style.clipPath = cp; }\n    }\n  }\n  function loop(now) {\n    raf = 0; if (!root.isConnected) return;\n    var dt = Math.min(.034, (now - last) \/ 1000), i, j, b, sp; last = now; frame++;\n    if (live) {\n      for (j = 0; j \u003c 4; j++) for (i = 0; i \u003c bodies.length; i++) step(bodies[i], dt \/ 4);\n      \/* videos: motion drives playback speed *\/\n      for (i = 0; i \u003c vids.length; i++) {\n        b = vids[i]; sp = Math.sqrt(b.vx * b.vx + b.vy * b.vy) + Math.abs(b.va) * 110;\n        if (b.hover || b.mode || sp \u003e 40) {\n          var r = RM ? 1 : clamp(1 + sp \/ 480, 1, 4); b.idle = 0; b.player.play(); b.player.rate(r);\n          if (Math.abs(r - b.rateV) \u003e .04) { b.rateV = r; b.rateEl.textContent = '×' + r.toFixed(2); }\n          if (r \u003e= 3.3) disc('SPEED');\n        } else { b.idle += dt; if (b.idle \u003e .3) b.player.pause(); }\n        b.player.tick(dt);\n      }\n      if (funk \u003e 0) { beatT -= dt; if (beatT \u003c= 0) { beatT += 60 \/ 116; funk--; beat(); if (funk \u003c= 0) root.classList.remove('is-funk'); } }\n      if (frame % 12 === 0) checkSecrets();\n      if (frame % 30 === 0) checkPile();\n      if (loupe \u0026\u0026 !found.XRAY \u0026\u0026 Math.abs(loupe.x - spot.px * W) + Math.abs(loupe.y - spot.py * H) \u003c loupe.w * .3) disc('XRAY');\n      if (dragging \u0026\u0026 dragging.gold \u0026\u0026 frame % 2 === 0) emit(dragging.x + rnd(-40, 40), dragging.y + rnd(-40, 40), 1, 80);\n      if (seq \u0026\u0026 seq.length \u003c 4 \u0026\u0026 now - seqT \u003e 3500) { seq = ''; lightSeq(); }\n      \/* the table gets restless when nobody touches it *\/\n      if (!RM \u0026\u0026 now - idleT \u003e 14000 \u0026\u0026 now - nudgeT \u003e 6000 \u0026\u0026 bodies.length) { nudgeT = now; b = bodies[Math.random() * bodies.length | 0]; if (!b.mode) { b.va += rnd(-1.8, 1.8); b.vx += rnd(-160, 160); b.vy += rnd(-160, 160); b.thrown = false; } }\n    }\n    render();\n    dust(dt);\n    \/* letters lean away from the pointer *\/\n    for (i = 0; i \u003c letters.length; i++) {\n      var L = letters[i], tx = 0, ty = 0;\n      if (pIn \u0026\u0026 !RM \u0026\u0026 live) {\n        var dx = L.cx - px, dy = L.cy - py, d = Math.sqrt(dx * dx + dy * dy) || 1, R = mobile ? 130 : 240;\n        if (d \u003c R) { var f = 1 - d \/ R; f = f * f * 80; tx = dx \/ d * f; ty = dy \/ d * f; }\n      }\n      L.ox += (tx - L.ox) * .14; L.oy += (ty - L.oy) * .14; L.bs *= Math.exp(-7 * dt);\n      var sc = 1 + L.bs, lk = (L.ox * 4 | 0) + '_' + (L.oy * 4 | 0) + '_' + (sc * 200 | 0);\n      if (lk !== L.key) { L.key = lk; L.el.style.transform = 'translate3d(' + L.ox.toFixed(1) + 'px,' + L.oy.toFixed(1) + 'px,0) scale(' + sc.toFixed(3) + ',' + (sc * (mobile ? 1.12 : 1.5)).toFixed(3) + ')'; }\n    }\n    if (FINE \u0026\u0026 pIn) {\n      for (i = 0; i \u003c btns.length; i++) {\n        var B = btns[i], bx = px - B.cx, by = py - B.cy, near = !RM \u0026\u0026 Math.abs(bx) \u003c 90 \u0026\u0026 Math.abs(by) \u003c 60;\n        B.ox += ((near ? bx * .35 : 0) - B.ox) * .18; B.oy += ((near ? by * .35 : 0) - B.oy) * .18;\n        B.el.style.transform = 'translate(' + B.ox.toFixed(1) + 'px,' + B.oy.toFixed(1) + 'px)';\n      }\n      \/* cursor *\/\n      var kk = 1 - Math.exp(-dt * 20), size = 34, text = '', st = 1, ang = cAng;\n      cx += (px - cx) * kk; cy += (py - cy) * kk;\n      if (dragging) {\n        sp = Math.sqrt(dragging.vx * dragging.vx + dragging.vy * dragging.vy);\n        text = dragging.kind === 'loupe' ? 'LOOK' : dragging.mode === 'rotate' ? 'SPIN' : 'THROW'; size = 56;\n        if (sp \u003e 60 \u0026\u0026 !RM) { st = 1 + Math.min(sp \/ 2400, .7); ang = Math.atan2(dragging.vy, dragging.vx); }\n      } else if (hoverKind === 'rot') { text = 'SPIN'; size = 46; }\n      else if (hoverB) { size = hoverB.kind === 'loupe' ? 70 : 88; text = hoverB.kind === 'loupe' ? 'LOOK' : now - hoverT \u003e 1600 ? 'DOUBLE-CLICK' : hoverB.player ? 'PLAY' : 'GRAB'; }\n      else if (hoverKind === 'letter') { text = 'SPELL'; size = 62; }\n      else if (hoverKind === 'btn') size = 12;\n      cStretch += (st - cStretch) * .2; cAng = ang;\n      if (size !== cSize) { cSize = size; cring.style.setProperty('--cs', size + 'px'); }\n      if (text !== cText) { cText = text; if (text) clabel.textContent = text; clabel.classList.toggle('is-on', !!text); }\n      cdot.style.transform = 'translate3d(' + px.toFixed(1) + 'px,' + py.toFixed(1) + 'px,0)';\n      cring.style.transform = 'translate3d(' + cx.toFixed(1) + 'px,' + cy.toFixed(1) + 'px,0) rotate(' + cAng.toFixed(3) + 'rad) scale(' + cStretch.toFixed(3) + ',' + (1 \/ cStretch).toFixed(3) + ')';\n      clabel.style.transform = 'translate3d(' + px.toFixed(1) + 'px,' + py.toFixed(1) + 'px,0)';\n      if (frame % 3 === 0) {\n        xyEl.textContent = 'X ' + ('000' + Math.max(0, px | 0)).slice(-4) + ' · Y ' + ('000' + Math.max(0, py | 0)).slice(-4);\n        b = dragging || hoverB;\n        objEl.textContent = b ? 'OBJ ' + b.num + ' · ' + ((((b.a * 57.2958) % 360) + 360) % 360).toFixed(1) + '°' : 'OBJ —';\n      }\n    }\n    kick();\n  }\n  function kick() { if (!raf \u0026\u0026 visible \u0026\u0026 !document.hidden) { last = ms(); raf = requestAnimationFrame(loop); } }\n\n  \/* ---------------- intro ---------------- *\/\n  function chars(t) { var i = 0; return t.split('').map(function (ch) { return ch === ' ' ? ' ' : '\u003cspan class=\"gfx-ch\" style=\"--i:' + (i++) + '\"\u003e' + esc(ch) + '\u003c\/span\u003e'; }).join(''); }\n  function wait(t) { return new Promise(function (r) { setTimeout(r, t); }); }\n  function dropAll(gap) {\n    bodies.forEach(function (b, i) {\n      setTimeout(function () {\n        if (b.el.classList.contains('is-drop')) return;\n        b.el.classList.add('is-drop');\n        if (gap) setTimeout(function () { emit(b.x, b.y, 14, 260); if (i === 0 || i === bodies.length - 1) shake(); }, 380);\n      }, i * gap);\n    });\n  }\n  function finishIntro() {\n    if (introDone) return; introDone = true;\n    dropAll(0);\n    introEl.classList.add('is-clear');\n    setTimeout(function () { if (introEl.parentNode) introEl.parentNode.removeChild(introEl); root.classList.remove('is-intro'); }, 750);\n    root.classList.add('is-live'); live = true; idleT = ms();\n    vids.forEach(function (b) { b.player.load(); });\n    measure(); startHints();\n  }\n  function runIntro() {\n    if (RM) { finishIntro(); return; }\n    introEl.innerHTML = '\u003cdiv class=\"gfx-icap\"\u003eGOLDFUNK \/ EXPERIMENT Nº001\u003cbr\u003eSTATUS: THIS PAGE IS EMPTY\u003c\/div\u003e\u003cdiv class=\"gfx-itext\"\u003e\u003cspan class=\"gfx-il\"\u003e' + chars('NOTHING') + '\u003c\/span\u003e\u003cspan class=\"gfx-il\"\u003e' + chars('TO SEE') + '\u003c\/span\u003e\u003cspan class=\"gfx-il\"\u003e' + chars('HERE.') + '\u003c\/span\u003e\u003ci class=\"gfx-strike\"\u003e\u003c\/i\u003e\u003c\/div\u003e\u003cdiv class=\"gfx-iskip\"\u003e' + (FINE ? 'CLICK' : 'TAP') + ' TO SKIP\u003c\/div\u003e';\n    introEl.addEventListener('pointerdown', finishIntro);\n    var tx = introEl.querySelector('.gfx-itext');\n    wait(90).then(function () { tx.classList.add('is-in'); return wait(2000); })\n      .then(function () { if (!introDone) tx.classList.add('is-struck'); return wait(700); })\n      .then(function () {\n        if (introDone) return;\n        \/* the sentence scrambles itself into a question *\/\n        tx.classList.remove('is-struck');\n        tx.innerHTML = '\u003cspan class=\"gfx-il\"\u003e' + chars('OR IS') + '\u003c\/span\u003e\u003cspan class=\"gfx-il is-gold\"\u003e' + chars('THERE?') + '\u003c\/span\u003e';\n        var cs = [].slice.call(tx.querySelectorAll('.gfx-ch')), fin = cs.map(function (c) { return c.textContent; }), G = 'GOLDFUNK§¥$%\u0026#@*?!', t0 = ms();\n        return new Promise(function (res) {\n          (function f() {\n            var t = ms() - t0, all = true;\n            cs.forEach(function (c, i) { if (t \u003c 240 + i * 60) { all = false; c.textContent = G.charAt(Math.random() * G.length | 0); } else c.textContent = fin[i]; });\n            if (all || introDone) res(); else requestAnimationFrame(f);\n          })();\n        });\n      })\n      .then(function () { return wait(1200); })\n      .then(function () {\n        if (introDone) return;\n        \/* the question falls apart and the prints land on the table *\/\n        introEl.classList.add('is-clear');\n        [].forEach.call(tx.querySelectorAll('.gfx-il'), function (l) { l.classList.add('is-free'); });\n        var st = [].map.call(tx.querySelectorAll('.gfx-ch'), function (c) { return { c: c, x: 0, y: 0, a: 0, vx: rnd(-320, 320), vy: rnd(-900, -200), va: rnd(-7, 7) }; }), l0 = ms(), t0 = l0;\n        (function f() {\n          var now = ms(), dt = Math.min(.034, (now - l0) \/ 1000); l0 = now;\n          st.forEach(function (s) { s.vy += 2600 * dt; s.x += s.vx * dt; s.y += s.vy * dt; s.a += s.va * dt; s.c.style.transform = 'translate(' + s.x.toFixed(1) + 'px,' + s.y.toFixed(1) + 'px) rotate(' + s.a.toFixed(3) + 'rad)'; });\n          if (now - t0 \u003c 1700 \u0026\u0026 introEl.parentNode) requestAnimationFrame(f);\n        })();\n        dropAll(85);\n        return wait(bodies.length * 85 + 500);\n      })\n      .then(finishIntro);\n  }\n  var HINTS = FINE\n    ? ['Drag anything. Throw it harder.', 'Double-click a print to read its back.', 'Grab a print by its corner. Or by the ↻.', 'The loupe sees through the table.', 'Something is hiding under the prints.', 'The big letters are listening. Type.', 'Throw the videos. Speed = playback.']\n    : ['Drag anything. Throw it harder.', 'Double-tap a print to read its back.', 'Two fingers on a print to spin it.', 'The loupe sees through the table.', 'Something is hiding under the prints.', 'The big letters are buttons. Spell something.', 'Throw the videos. Speed = playback.'];\n  function startHints() {\n    var i = 0; hintEl.textContent = HINTS[0];\n    var iv = setInterval(function () {\n      if (!root.isConnected) { clearInterval(iv); return; }\n      if (!visible) return;\n      i = (i + 1) % HINTS.length; hintEl.classList.add('is-out');\n      setTimeout(function () { hintEl.textContent = HINTS[i]; hintEl.classList.remove('is-out'); }, 380);\n    }, 4800);\n  }\n\n  \/* ---------------- boot ---------------- *\/\n  media.forEach(function (item, i) { bodies.push(makeCard(item, i)); });\n  var xr = GOLDFUNK.xray || {}, xv = null;\n  xray.innerHTML = '\u003cdiv class=\"gfx-xbig\"\u003e' + esc(GOLDFUNK.xrayHeadline || '').replace(\/ \/g, '\u003cbr\u003e') + '\u003c\/div\u003e\u003cspan class=\"gfx-xmsg\" style=\"left:60%;top:13%\"\u003eYOU ARE NOT SUPPOSED TO SEE THIS.\u003c\/span\u003e\u003cspan class=\"gfx-xmsg\" style=\"left:7%;top:88%\"\u003eGOLDFUNK — UNDER CONSTRUCTION SINCE FOREVER\u003c\/span\u003e\u003cspan class=\"gfx-xmsg\" style=\"left:68%;top:78%\"\u003eKEEP LOOKING →\u003c\/span\u003e\u003cspan class=\"gfx-xspot\"\u003e✶ THE OTHER SIDE ✶\u003c\/span\u003e';\n  if (xr.src) {\n    if (xr.type === 'video') { xv = document.createElement('video'); xv.muted = true; xv.loop = true; xv.playsInline = true; xv.setAttribute('muted', ''); xv.setAttribute('playsinline', ''); xv.preload = 'none'; xv.src = xr.src; xray.insertBefore(xv, xray.firstChild); }\n    else { var xi = new Image(); xi.alt = ''; xi.loading = 'lazy'; xi.decoding = 'async'; xi.src = sized(xr.src, 1600); xray.insertBefore(xi, xray.firstChild); }\n  }\n  loupe = makeLoupe(); bodies.push(loupe);\n  measure(); render();\n\n  if ('ResizeObserver' in window) { var rt = 0; new ResizeObserver(function () { cancelAnimationFrame(rt); rt = requestAnimationFrame(measure); }).observe(stage); }\n  else window.addEventListener('resize', measure);\n  function setVisible(v) {\n    visible = v;\n    if (xv) { if (v \u0026\u0026 live) { var p = xv.play(); if (p \u0026\u0026 p.catch) p.catch(function () {}); } else xv.pause(); }\n    if (v) { if (!started) { started = true; runIntro(); } kick(); } else vids.forEach(function (b) { b.player.pause(); });\n  }\n  if ('IntersectionObserver' in window) new IntersectionObserver(function (en) { setVisible(en[0].isIntersecting); }, { threshold: .12 }).observe(stage);\n  else setVisible(true);\n  document.addEventListener('visibilitychange', function () { if (root.isConnected) kick(); });\n}\n\nfunction boot() { [].forEach.call(document.querySelectorAll('[data-gfx]'), init); }\nif (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); else boot();\ndocument.addEventListener('shopify:section:load', boot);\n})();\n\u003c\/script\u003e\n\u003cdiv class=\"fake f\"\u003e\n\u003cspan\u003ePreview only — this grey header and footer stand in for your Shopify theme.\u003c\/span\u003e\u003cspan\u003e© GOLDFUNK\u003c\/span\u003e\n\u003c\/div\u003e","products":[],"url":"https:\/\/jewelleryfunk.com\/collections\/gurtel.oembed","provider":"Goldfunk","version":"1.0","type":"link"}