<div class="bg"></div>
<svg width="0" height="0" style="position:absolute">
<filter id="lens" x="0" y="0" width="100%" height="100%">
<feImage href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='140'%3E%3Cdefs%3E%3CradialGradient id='r' cx='50%25' cy='50%25' r='60%25'%3E%3Cstop offset='55%25' stop-color='%23808080'/%3E%3Cstop offset='100%25' stop-color='%23ff00ff'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='220' height='140' rx='70' fill='url(%23r)'/%3E%3C/svg%3E" result="map" preserveAspectRatio="none"/>
<feDisplacementMap in="SourceGraphic" in2="map" scale="46" xChannelSelector="R" yChannelSelector="B"/>
</filter>
</svg>
<div class="glass" id="g"><span>Liquid Glass</span></div>
.bg{position:absolute;inset:0;background:
repeating-linear-gradient(90deg,#111 0 14px,#f5f2ea 14px 28px);}
.bg::after{content:"";position:absolute;inset:0;background:
radial-gradient(circle at 25% 30%,#ff6a3d 0 60px,transparent 61px),
radial-gradient(circle at 70% 65%,#4f7cff 0 80px,transparent 81px);mix-blend-mode:multiply}
.glass{position:absolute;left:calc(50% - 110px);top:calc(50% - 70px);width:220px;height:140px;border-radius:70px;
cursor:grab;display:grid;place-items:center;color:#fff;font-weight:700;letter-spacing:.02em;
text-shadow:0 1px 8px rgba(0,0,0,.45);
backdrop-filter:blur(2px) saturate(1.6);-webkit-backdrop-filter:blur(2px) saturate(1.6);
box-shadow:inset 1px 1px 0 rgba(255,255,255,.9),inset -1px -1px 0 rgba(255,255,255,.35),
inset 0 0 18px rgba(255,255,255,.35),0 12px 30px rgba(0,0,0,.25);
background:linear-gradient(135deg,rgba(255,255,255,.28),rgba(255,255,255,.04));}
@supports (backdrop-filter:url(#lens)){ .glass.refract{backdrop-filter:url(#lens) saturate(1.5)} }
.glass:active{cursor:grabbing}
const g = document.getElementById('g');
// Chromium 만 backdrop-filter:url() 을 지원한다
if (/Chrome/.test(navigator.userAgent)) g.classList.add('refract');
let drag = null;
g.addEventListener('pointerdown', e => { drag = { x: e.clientX - g.offsetLeft, y: e.clientY - g.offsetTop }; g.setPointerCapture(e.pointerId); });
g.addEventListener('pointermove', e => { if (!drag) return; g.style.left = (e.clientX - drag.x) + 'px'; g.style.top = (e.clientY - drag.y) + 'px'; });
g.addEventListener('pointerup', () => drag = null);
// 처음엔 천천히 떠다니며 굴절을 보여준다
let t = 0, auto = true;
g.addEventListener('pointerdown', () => auto = false, { once: true });
(function float(){ if (!auto) return; t += 0.012;
g.style.left = (innerWidth/2 - 110 + Math.sin(t)*innerWidth*0.22) + 'px';
g.style.top = (innerHeight/2 - 70 + Math.cos(t*1.3)*innerHeight*0.12) + 'px';
requestAnimationFrame(float); })();