<div class="stage"><div class="phone"><div class="notch"></div><div class="screen" id="screen">
<div class="rows2">
<div class="row3" id="target"><div class="avatar"></div><div class="txt"><div class="bar w70"></div><div class="bar w50"></div></div></div>
<div class="row3"><div class="avatar"></div><div class="txt"><div class="bar w60"></div><div class="bar w40"></div></div></div>
<div class="row3"><div class="avatar"></div><div class="txt"><div class="bar w65"></div><div class="bar w45"></div></div></div>
</div>
<div class="backdrop" id="backdrop"></div>
<div class="ctxmenu" id="ctx">
<div class="ctxitem">Reply</div><div class="ctxitem">Forward</div><div class="ctxitem del">Delete</div>
</div></div><div class="home"></div></div></div>
.stage{position:absolute;inset:0;display:grid;place-items:center;overflow:hidden}
.phone{position:relative;height:90vmin;max-height:640px;aspect-ratio:9/19.5;background:#08080c;
border-radius:20%/8.6%;box-shadow:0 0 0 2px rgba(255,255,255,.08) inset,0 12px 30px rgba(0,0,0,.35)}
.phone .notch{position:absolute;left:50%;top:0;transform:translateX(-50%);width:38%;height:5.6%;
background:#08080c;border-radius:0 0 46% 46%;z-index:80}
.phone .screen{position:absolute;top:7.6%;left:3%;right:3%;bottom:3%;border-radius:11%/4.6%;overflow:hidden;
background:var(--surface);color:var(--fg)}
.phone .home{position:absolute;left:50%;bottom:1.1%;transform:translateX(-50%);width:32%;height:3px;
border-radius:2px;background:rgba(255,255,255,.45);z-index:80}
.pfx{position:absolute;left:0;top:0;width:16px;height:16px;margin:-8px 0 0 -8px;border-radius:50%;
background:color-mix(in srgb,var(--accent) 55%,transparent);
box-shadow:0 0 0 6px color-mix(in srgb,var(--accent) 15%,transparent);pointer-events:none;z-index:999;
transition:opacity .2s}
.pfx.hold{width:30px;height:30px;margin:-15px 0 0 -15px;
box-shadow:0 0 0 9px color-mix(in srgb,var(--accent) 20%,transparent);
transition:width .5s linear,height .5s linear,margin .5s linear,box-shadow .5s linear,opacity .2s}
.rows2{position:absolute;inset:0;padding:8% 0 0}
.row3{display:flex;align-items:center;gap:6%;padding:6% 6%;border-bottom:1px solid var(--line);position:relative;transition:transform .25s}
.row3.raised{transform:scale(1.05);z-index:20;background:var(--surface)}
.avatar{width:14%;aspect-ratio:1;border-radius:50%;background:var(--accent);flex:none}
.txt{flex:1;display:grid;gap:14%}
.bar{height:clamp(3px,2vmin,6px);border-radius:3px;background:var(--line)}
.w70{width:70%}.w50{width:50%}.w60{width:60%}.w40{width:40%}.w65{width:65%}.w45{width:45%}
.backdrop{position:absolute;inset:0;background:rgba(0,0,0,0);pointer-events:none;z-index:10;transition:background .25s}
.backdrop.show{background:rgba(0,0,0,.28);pointer-events:auto}
.ctxmenu{position:absolute;width:54%;background:var(--surface);border-radius:12px;box-shadow:0 10px 24px rgba(0,0,0,.28);
opacity:0;transform:scale(.85);transition:opacity .2s,transform .2s;z-index:25;pointer-events:none;overflow:hidden}
.ctxmenu.show{opacity:1;transform:scale(1)}
.ctxitem{padding:7% 10%;font-size:clamp(6px,2.2vmin,8.5px);font-weight:600;border-bottom:1px solid var(--line)}
.ctxitem.del{color:#e5534b;border-bottom:none}
const pfx=document.createElement('div');pfx.className='pfx';document.body.appendChild(pfx);
const screenEl=document.getElementById('screen');
let pfxAuto=true;
function pfxHide(){pfx.style.opacity='0';}
addEventListener('pointerdown',()=>{pfxAuto=false;pfxHide();},{capture:true});
function pfxAt(fx,fy){
const r=screenEl.getBoundingClientRect();
const x=r.left+r.width*fx, y=r.top+r.height*fy;
pfx.style.transform='translate('+x+'px,'+y+'px)';
return {x,y};
}
function pfxWalk(x0,y0,x1,y1,ms){
return new Promise(res=>{
const start=performance.now();
function step(now){
if(!pfxAuto) return res();
const p=Math.min(1,(now-start)/ms), e=1-Math.pow(1-p,3);
pfxAt(x0+(x1-x0)*e, y0+(y1-y0)*e);
if(p<1) requestAnimationFrame(step); else res();
}
requestAnimationFrame(step);
});
}
function pfxWait(ms){
return new Promise(res=>{
const start=performance.now();
function step(now){ if(!pfxAuto) return res(); if(now-start<ms) requestAnimationFrame(step); else res(); }
requestAnimationFrame(step);
});
}
const target=document.getElementById('target'), backdrop=document.getElementById('backdrop'), ctx=document.getElementById('ctx');
function openMenu(){
target.classList.add('raised'); backdrop.classList.add('show');
const r=target.getBoundingClientRect(), sr=screenEl.getBoundingClientRect();
ctx.style.left=(r.left-sr.left+8)+'px'; ctx.style.top=(r.bottom-sr.top+6)+'px';
ctx.classList.add('show'); pfx.classList.remove('hold');
}
function closeMenu(){ target.classList.remove('raised'); backdrop.classList.remove('show'); ctx.classList.remove('show'); pfx.classList.remove('hold'); }
let holdTimer=null;
target.addEventListener('pointerdown',()=>{ pfxAuto=false; pfxHide(); holdTimer=setTimeout(openMenu,480); });
addEventListener('pointerup',()=>{ if(holdTimer){ clearTimeout(holdTimer); holdTimer=null; } });
backdrop.addEventListener('pointerdown',closeMenu);
async function autoSeq(){
while(pfxAuto){
closeMenu();
const r=target.getBoundingClientRect(), sr=screenEl.getBoundingClientRect();
const fx=(r.left+30-sr.left)/sr.width, fy=(r.top+r.height/2-sr.top)/sr.height;
await pfxWalk(fx,fy,fx,fy,350); if(!pfxAuto)break;
pfx.classList.add('hold');
await pfxWait(480); if(!pfxAuto)break;
openMenu();
await pfxWait(750); if(!pfxAuto)break;
await pfxWalk(fx,fy,0.85,0.1,300); if(!pfxAuto)break;
closeMenu();
await pfxWait(700);
}
}
autoSeq();