| | <!DOCTYPE html> |
| | <html lang="ko"> |
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title>Proto-AGI FACE โ AI ์ฑํ ์๋ฎฌ๋ ์ดํฐ</title> |
| | <link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&family=Noto+Sans+KR:wght@300;400;500;700;900&display=swap" rel="stylesheet"> |
| | <style> |
| | *{margin:0;padding:0;box-sizing:border-box} |
| | :root{--bg:#f8f9fc;--surface:#fff;--surface-alt:#f5f6fa;--border:#e2e5f0;--border-hover:#c7cce0; |
| | --shadow-sm:0 1px 3px rgba(15,23,42,.04),0 1px 2px rgba(15,23,42,.06);--shadow:0 4px 16px rgba(15,23,42,.06),0 1px 3px rgba(15,23,42,.08); |
| | --text:#0f172a;--text-sec:#475569;--text-muted:#94a3b8;--accent:#6366f1;--teal:#0d9488;--rose:#e11d48;--pink:#ec4899;--amber:#d97706; |
| | --radius:16px;--radius-sm:10px;--radius-xs:6px; |
| | --fd:'Sora','Noto Sans KR',sans-serif;--fb:'Noto Sans KR','Sora',sans-serif;--fm:'JetBrains Mono',monospace;--tr:.25s cubic-bezier(.4,0,.2,1)} |
| | html{scroll-behavior:smooth}body{font-family:var(--fb);background:var(--bg);color:var(--text);min-height:100vh;overflow-x:hidden;-webkit-font-smoothing:antialiased} |
| | ::-webkit-scrollbar{width:6px}::-webkit-scrollbar-thumb{background:rgba(99,102,241,.2);border-radius:10px}::selection{background:rgba(99,102,241,.15)} |
| | .bg-p{position:fixed;inset:0;z-index:0;pointer-events:none;background:radial-gradient(ellipse 80% 50% at 20% 10%,rgba(99,102,241,.04),transparent 50%),radial-gradient(ellipse 60% 40% at 80% 90%,rgba(13,148,136,.03),transparent 50%)} |
| | .wrap{position:relative;z-index:1;max-width:960px;margin:0 auto;padding:24px 24px 48px} |
| | .hdr{text-align:center;padding:28px 0 16px;animation:fi .8s ease-out} |
| | @keyframes fi{from{opacity:0;transform:translateY(-16px)}to{opacity:1;transform:translateY(0)}} |
| | .hdr-eye{font-family:var(--fm);font-size:10px;font-weight:600;letter-spacing:5px;text-transform:uppercase;color:var(--accent);margin-bottom:6px} |
| | .hdr-t{font-family:var(--fd);font-size:40px;font-weight:800;letter-spacing:-1.5px;margin-bottom:8px} |
| | .gt{background:linear-gradient(135deg,#6366f1,#e11d48 40%,#0d9488 70%,#6366f1);background-size:200% 200%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:sh 6s ease-in-out infinite} |
| | @keyframes sh{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}} |
| | .pills{display:flex;gap:5px;justify-content:center;flex-wrap:wrap;animation:fu .8s .2s ease-out both} |
| | @keyframes fu{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}} |
| | .pill{padding:3px 10px;background:var(--surface);border:1px solid var(--border);border-radius:20px;font-family:var(--fm);font-size:9px;font-weight:500;color:var(--text-muted);box-shadow:var(--shadow-sm)} |
| | .nav{display:flex;gap:3px;background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:4px;margin-bottom:18px;position:sticky;top:12px;z-index:100;box-shadow:var(--shadow);animation:fu .8s .3s ease-out both} |
| | .ni{flex:1;display:flex;align-items:center;justify-content:center;gap:4px;padding:10px 4px;border-radius:var(--radius-sm);cursor:pointer;font-size:11.5px;font-weight:600;color:var(--text-muted);transition:var(--tr);user-select:none} |
| | .ni:hover{color:var(--text-sec);background:var(--surface-alt)} |
| | .ni.a{color:#fff;box-shadow:0 4px 16px rgba(99,102,241,.3)} |
| | .ni.a[data-t="face"]{background:linear-gradient(135deg,#3b82f6,#2563eb)}.ni.a[data-t="physio"]{background:linear-gradient(135deg,#8b5cf6,#7c3aed)}.ni.a[data-t="compat"]{background:linear-gradient(135deg,#ec4899,#db2777)}.ni.a[data-t="sim"]{background:linear-gradient(135deg,#e11d48,#be123c)} |
| | .pnl{display:none;animation:pi .4s ease-out}.pnl.a{display:block}@keyframes pi{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}} |
| | .card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:22px;margin-bottom:14px;box-shadow:var(--shadow-sm);transition:all .3s} |
| | .card:hover{box-shadow:var(--shadow);border-color:var(--border-hover)} |
| | .ch{display:flex;align-items:center;gap:10px;margin-bottom:12px}.ci{width:34px;height:34px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0} |
| | .ci.bl{background:rgba(59,130,246,.08);border:1px solid rgba(59,130,246,.15)}.ci.pu{background:rgba(99,102,241,.06);border:1px solid rgba(99,102,241,.15)}.ci.pk{background:rgba(236,72,153,.06);border:1px solid rgba(236,72,153,.15)}.ci.ro{background:rgba(225,29,72,.06);border:1px solid rgba(225,29,72,.15)} |
| | .ct{font-family:var(--fd);font-size:15px;font-weight:700} |
| | .fl{display:block;font-size:10.5px;font-weight:600;color:var(--text-sec);margin-bottom:4px}.fr{display:flex;gap:10px;margin-bottom:10px;flex-wrap:wrap}.fg{flex:1;min-width:140px} |
| | select,input[type=password]{width:100%;padding:8px 11px;background:var(--surface-alt);border:1.5px solid var(--border);border-radius:var(--radius-xs);color:var(--text);font-family:var(--fb);font-size:12px;outline:none;transition:border-color .3s} |
| | select:focus,input:focus{border-color:var(--accent)} |
| | textarea{width:100%;min-height:60px;padding:8px 11px;background:var(--surface-alt);border:1.5px solid var(--border);border-radius:var(--radius-xs);color:var(--text);font-family:var(--fb);font-size:12px;line-height:1.6;resize:vertical;outline:none}textarea:focus{border-color:var(--accent)}textarea::placeholder{color:var(--text-muted);font-size:11px} |
| | .uz{position:relative;border:2px dashed var(--border);border-radius:var(--radius);padding:28px 14px;text-align:center;cursor:pointer;transition:all .3s;background:var(--surface-alt)} |
| | .uz:hover{border-color:var(--accent);background:rgba(99,102,241,.03)}.uz.hi{border-style:solid;border-color:var(--teal);background:#fff;padding:6px} |
| | .uz input[type=file]{position:absolute;inset:0;opacity:0;cursor:pointer}.uz img{width:100%;max-height:280px;object-fit:contain;border-radius:var(--radius-sm)} |
| | .uzi{font-size:26px;margin-bottom:4px;opacity:.6}.uzt{font-size:10.5px;color:var(--text-muted)}.uzt b{color:var(--text-sec)} |
| | .uzs{padding:18px 10px}.uzs .uzi{font-size:20px;margin-bottom:2px}.uzs img{max-height:180px} |
| | .btn{padding:11px 20px;border:none;border-radius:var(--radius-sm);cursor:pointer;font-family:var(--fb);font-weight:600;font-size:12.5px;transition:all .25s;width:100%;margin-top:10px} |
| | .btn:disabled{opacity:.4;cursor:not-allowed;transform:none!important}.btn:hover{transform:translateY(-2px)} |
| | .bb{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;box-shadow:0 4px 16px rgba(59,130,246,.25)} |
| | .bp{background:linear-gradient(135deg,#8b5cf6,#7c3aed);color:#fff;box-shadow:0 4px 16px rgba(139,92,246,.25)} |
| | .bk{background:linear-gradient(135deg,#ec4899,#db2777);color:#fff;box-shadow:0 4px 16px rgba(236,72,153,.25)} |
| | .br{background:linear-gradient(135deg,#e11d48,#be123c);color:#fff;box-shadow:0 4px 16px rgba(225,29,72,.25)} |
| | .rg{display:flex;gap:4px;flex-wrap:wrap}.rg label{display:flex;align-items:center;gap:3px;padding:5px 10px;background:var(--surface-alt);border:1.5px solid var(--border);border-radius:20px;cursor:pointer;font-size:10.5px;font-weight:500;color:var(--text-sec);transition:all .2s} |
| | .rg input{display:none}.rg input:checked+label{background:rgba(99,102,241,.06);border-color:var(--accent);color:var(--accent);font-weight:700} |
| | .kt{font-size:10px;color:var(--accent);cursor:pointer;font-weight:600;margin-bottom:8px;display:inline-flex;align-items:center;gap:3px}.kt:hover{text-decoration:underline} |
| | .ks{display:none;margin-bottom:10px;padding:12px;background:var(--surface-alt);border-radius:var(--radius-sm);border:1px solid var(--border)}.ks.o{display:block} |
| | /* Loader */ |
| | .ld{display:none;text-align:center;padding:36px 16px}.ld.a{display:block} |
| | .lr{width:38px;height:38px;border:3px solid rgba(99,102,241,.12);border-top-color:var(--accent);border-radius:50%;animation:sp .9s linear infinite;margin:0 auto 10px;position:relative} |
| | .lr::after{content:'';position:absolute;inset:4px;border:2px solid transparent;border-top-color:var(--teal);border-radius:50%;animation:sp 1.4s linear infinite reverse} |
| | @keyframes sp{to{transform:rotate(360deg)}}.lt{font-size:12px;color:var(--text-sec);animation:br 2s ease-in-out infinite}@keyframes br{0%,100%{opacity:1}50%{opacity:.5}} |
| | /* Scan */ |
| | .sco{display:none;position:relative;padding:44px 14px;text-align:center;background:linear-gradient(180deg,#0f172a,#1e1b4b 50%,#0f172a);border-radius:var(--radius);overflow:hidden;margin-bottom:14px}.sco.a{display:block;animation:sci .5s ease-out} |
| | @keyframes sci{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}} |
| | .sp{position:absolute;inset:0;overflow:hidden}.sp span{position:absolute;width:2px;height:2px;background:#818cf8;border-radius:50%;opacity:0;animation:pd 4s linear infinite} |
| | @keyframes pd{0%{opacity:0;transform:translateY(100%) scale(0)}20%{opacity:.5}80%{opacity:.3}100%{opacity:0;transform:translateY(-100%) scale(1.5)}} |
| | .fc{position:relative;width:160px;height:210px;margin:0 auto 16px} |
| | .fm{width:100%;height:100%;filter:drop-shadow(0 0 14px rgba(99,102,241,.3))} |
| | .fo{fill:none;stroke:#818cf8;stroke-width:1.5;stroke-linecap:round;opacity:0;animation:df 3s ease-out forwards} |
| | @keyframes df{0%{stroke-dasharray:1200;stroke-dashoffset:1200;opacity:0}10%{opacity:1}100%{stroke-dashoffset:0;opacity:1}} |
| | .ll{position:absolute;left:10%;right:10%;height:2px;background:linear-gradient(90deg,transparent,#e11d48,#f97316,#e11d48,transparent);box-shadow:0 0 15px 3px rgba(225,29,72,.4);border-radius:2px;animation:ls 2.8s ease-in-out infinite;z-index:5} |
| | @keyframes ls{0%{top:8%;opacity:0}5%{opacity:1}50%{top:88%;opacity:1}55%{opacity:0}100%{top:8%;opacity:0}} |
| | .sg{position:absolute;inset:0;background:repeating-linear-gradient(0deg,transparent,transparent 19px,rgba(99,102,241,.05) 19px,rgba(99,102,241,.05) 20px),repeating-linear-gradient(90deg,transparent,transparent 19px,rgba(99,102,241,.05) 19px,rgba(99,102,241,.05) 20px);animation:gp 3s ease-in-out infinite}@keyframes gp{0%,100%{opacity:.3}50%{opacity:.7}} |
| | .sc{position:absolute;width:18px;height:18px;z-index:6}.sc::before,.sc::after{content:'';position:absolute;background:#0d9488;border-radius:1px} |
| | .sc.tl{top:0;left:0}.sc.tr{top:0;right:0}.sc.bl{bottom:0;left:0}.sc.br{bottom:0;right:0} |
| | .sc.tl::before,.sc.tr::before{top:0;height:2px;width:12px}.sc.tl::after,.sc.bl::after{left:0;width:2px;height:12px} |
| | .sc.tr::before{right:0;left:auto}.sc.tr::after{right:0;width:2px;height:12px}.sc.bl::before{bottom:0;top:auto;height:2px;width:12px}.sc.bl::after{bottom:0;top:auto} |
| | .sc.br::before{bottom:0;right:0;top:auto;left:auto;height:2px;width:12px}.sc.br::after{right:0;bottom:0;top:auto;width:2px;height:12px} |
| | .pr{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border:1px solid rgba(99,102,241,.2);border-radius:50%;animation:pe 3s ease-out infinite} |
| | @keyframes pe{0%{width:70px;height:95px;opacity:.5}100%{width:220px;height:290px;opacity:0}} |
| | .sd{position:absolute;font-family:var(--fm);font-size:7.5px;color:#818cf8;opacity:0;animation:dfl 4s ease-in-out infinite;white-space:nowrap} |
| | @keyframes dfl{0%,100%{opacity:0}20%{opacity:.7}60%{opacity:.8}80%{opacity:0}} |
| | .ssm{font-family:var(--fd);font-size:13px;font-weight:700;color:#e2e8f0;margin-bottom:3px;animation:br 2s ease-in-out infinite} |
| | .sss{font-family:var(--fm);font-size:9px;color:#818cf8;letter-spacing:1px} |
| | .spb{width:50%;margin:8px auto 0;height:3px;background:rgba(99,102,241,.15);border-radius:3px;overflow:hidden} |
| | .spf{height:100%;background:linear-gradient(90deg,#6366f1,#e11d48,#0d9488);background-size:200% 100%;border-radius:3px;animation:ps 2s linear infinite;transition:width .5s ease} |
| | @keyframes ps{0%{background-position:100% 0}100%{background-position:-100% 0}} |
| | /* Results */ |
| | .ra{margin-top:14px;animation:ri .5s ease-out}@keyframes ri{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}} |
| | .rh{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:18px;box-shadow:var(--shadow-sm);font-size:12.5px;line-height:1.9;color:var(--text-sec);margin-top:10px} |
| | .rh:empty{display:none}.rh h1,.rh h2,.rh h3{font-family:var(--fd);color:var(--text);margin:12px 0 5px}.rh h1{font-size:16px}.rh h2{font-size:13.5px}.rh h3{font-size:12px} |
| | .rh blockquote{border-left:3px solid var(--accent);padding:5px 10px;background:rgba(99,102,241,.06);border-radius:0 var(--radius-xs) var(--radius-xs) 0;margin:8px 0;font-size:11px;color:var(--accent)} |
| | .rh hr{border:none;border-top:1px solid var(--border);margin:12px 0}.rh li{margin-left:14px} |
| | .riw{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);margin-bottom:12px}.riw img{width:100%;display:block} |
| | .ril{padding:8px 12px;font-size:10.5px;font-weight:600;color:var(--text-sec);border-top:1px solid var(--border)} |
| | .rgg{display:grid;grid-template-columns:1fr 1fr;gap:10px}.em{padding:12px;text-align:center;color:var(--rose);font-size:11.5px;background:var(--surface);border:1px solid rgba(225,29,72,.2);border-radius:var(--radius);margin-bottom:10px}.em:empty{display:none} |
| | .rv:empty{display:none} |
| | .ft{text-align:center;margin-top:36px;padding:18px 0;border-top:1px solid var(--border)}.ftb{font-family:var(--fd);font-size:11px;font-weight:600;color:var(--text-muted);margin-bottom:3px} |
| | .ftd{font-size:10px;color:var(--text-muted)}.ftd a{color:var(--accent);text-decoration:none;font-weight:600} |
| | .ftl{width:40px;height:2px;background:linear-gradient(90deg,transparent,var(--accent),var(--rose),transparent);margin:6px auto;border-radius:2px;opacity:.4} |
| | .ftt{font-family:var(--fm);font-size:8px;color:var(--text-muted);opacity:.5;letter-spacing:1px} |
| | @media(max-width:640px){.wrap{padding:12px 12px 32px}.hdr{padding:16px 0 10px}.hdr-t{font-size:28px}.nav{flex-wrap:wrap;position:static}.ni{font-size:10px;padding:8px 3px}.card{padding:16px 12px}.fr{flex-direction:column}.rgg{grid-template-columns:1fr}.fc{width:120px;height:160px}} |
| | </style> |
| | </head> |
| | <body> |
| | <div class="bg-p"></div> |
| | <div class="wrap"> |
| | <header class="hdr"> |
| | <div class="hdr-eye">์ผ๊ตด ์ฑํ ์๋ฎฌ๋ ์ด์
</div> |
| | <h1 class="hdr-t"><span class="gt">๋ด๊ฐ ์์ด ๋ ์์ธ๊ฐ?</span></h1> |
| | <div class="pills"> |
| | <span class="pill" style="background:linear-gradient(135deg,rgba(225,29,72,.08),rgba(249,115,22,.08));border-color:rgba(225,29,72,.25);color:#e11d48;font-weight:700">๐ฅ VIDRAFT</span> |
| | <span class="pill">๐ฉบ ์์ฌ</span><span class="pill">๐ฎ ๊ด์</span><span class="pill">๐ก ์ฐฝ๋ฐ</span><span class="pill">โ๏ธ ๋นํ</span><span class="pill">๐ฏ ๊ฐ๋
</span> |
| | </div> |
| | </header> |
| | <nav class="nav"> |
| | <div class="ni a" data-t="face" onclick="st('face')">๐ ์ผ๊ตด๋ถ์</div> |
| | <div class="ni" data-t="physio" onclick="st('physio')">๐ฎ ๊ด์</div> |
| | <div class="ni" data-t="compat" onclick="st('compat')">๐ ๊ถํฉ</div> |
| | <div class="ni" data-t="sim" onclick="st('sim')">โจ ์๋ฎฌ๋ ์ด์
</div> |
| | </nav> |
| | <div style="margin-bottom:14px"><span class="kt" onclick="document.getElementById('ks').classList.toggle('o')">๐ API Keys โพ</span> |
| | <div class="ks" id="ks"><div class="fr"><div class="fg"><div class="fl">FAL Key</div><input type="password" id="fk" placeholder="fal_..."></div><div class="fg"><div class="fl">Fireworks Key</div><input type="password" id="wk" placeholder="fw_..."></div></div></div></div> |
| |
|
| | |
| | <div class="pnl a" id="p-face"><div class="card"><div class="ch"><div class="ci bl">๐</div><div class="ct">์ํ์ ์ผ๊ตด ๋ถ์</div></div> |
| | <div class="uz" id="uz-face" ><div class="ph"><div class="uzi">๐ผ๏ธ</div><div class="uzt"><b>์ผ๊ตด ์ฌ์ง ์
๋ก๋</b></div></div><img class="ui" style="display:none"><input type="file" accept="image/*" onchange="hu(this,'face')"></div> |
| | <button class="btn bb" id="bf" onclick="runFace()">๐ ์ํ์ ์ผ๊ตด ๋ถ์ ์์</button></div> |
| | <div class="ld" id="ld-face"><div class="lr"></div><div class="lt">๐ฉบ ์ผ๊ตด ๊ตฌ์กฐ ๋ถ์ ์ค...</div></div> |
| | <div class="ra"><div class="rh" id="rf"></div></div></div> |
| |
|
| | |
| | <div class="pnl" id="p-physio"><div class="card"><div class="ch"><div class="ci pu">๐ฎ</div><div class="ct">๊ด์ ๋ถ์</div></div> |
| | <div class="uz" id="uz-physio" ><div class="ph"><div class="uzi">๐ผ๏ธ</div><div class="uzt"><b>์ผ๊ตด ์ฌ์ง ์
๋ก๋</b></div></div><img class="ui" style="display:none"><input type="file" accept="image/*" onchange="hu(this,'physio')"></div> |
| | <button class="btn bp" id="bp" onclick="runPhysio()">๐ฎ ๊ด์ ๋ถ์ ์์</button></div> |
| | <div class="ld" id="ld-physio"><div class="lr"></div><div class="lt">๐ฎ ๊ด์ ๋ถ์ ์ค...</div></div> |
| | <div class="ra"><div class="rv" id="rpv"></div><div class="rh" id="rp"></div></div></div> |
| |
|
| | |
| | <div class="pnl" id="p-compat"><div class="card"><div class="ch"><div class="ci pk">๐</div><div class="ct">๊ด์ ๊ถํฉ ๋ถ์</div></div> |
| | <div class="fr"><div class="fg"><div class="fl">๐ธ ๋์ ์ผ๊ตด</div><div class="uz uzs" id="uz-c1" ><div class="ph"><div class="uzi">๐ง</div><div class="uzt"><b>์ฌ์ง 1</b></div></div><img class="ui" style="display:none"><input type="file" accept="image/*" onchange="hu(this,'c1')"></div></div> |
| | <div class="fg"><div class="fl">๐ธ ์๋๋ฐฉ ์ผ๊ตด</div><div class="uz uzs" id="uz-c2" ><div class="ph"><div class="uzi">๐ง</div><div class="uzt"><b>์ฌ์ง 2</b></div></div><img class="ui" style="display:none"><input type="file" accept="image/*" onchange="hu(this,'c2')"></div></div></div> |
| | <div class="fg"><div class="fl">๐ ๊ด๊ณ ์ ํ</div><div class="rg"> |
| | <input type="radio" name="rel" id="r1" value="๐ผ ๋น์ฆ๋์ค ํํธ๋"><label for="r1">๐ผ ๋น์ฆ๋์ค</label> |
| | <input type="radio" name="rel" id="r2" value="โค๏ธ ์ฐ์ธ / ๋ฐฐ์ฐ์" checked><label for="r2">โค๏ธ ์ฐ์ธ</label> |
| | <input type="radio" name="rel" id="r3" value="๐จโ๐ฉโ๐ง ๊ฐ์กฑ"><label for="r3">๐จโ๐ฉโ๐ง ๊ฐ์กฑ</label> |
| | <input type="radio" name="rel" id="r4" value="๐ค ์น๊ตฌ / ๋๋ฃ"><label for="r4">๐ค ์น๊ตฌ</label> |
| | </div></div> |
| | <button class="btn bk" id="bc" onclick="runCompat()">๐ ๊ถํฉ ๋ถ์ ์์</button></div> |
| | <div class="ld" id="ld-compat"><div class="lr"></div><div class="lt">๐ ๊ถํฉ ๋ถ์ ์ค...</div></div> |
| | <div class="ra"><div class="rv" id="rcv"></div><div class="rh" id="rc"></div></div></div> |
| |
|
| | |
| | <div class="pnl" id="p-sim"><div class="card"><div class="ch"><div class="ci ro">โจ</div><div class="ct">์ฑํ ์๋ฎฌ๋ ์ด์
</div></div> |
| | <div class="uz" id="uz-sim" ><div class="ph"><div class="uzi">๐ผ๏ธ</div><div class="uzt"><b>์ผ๊ตด ์ฌ์ง ์
๋ก๋</b></div></div><img class="ui" style="display:none"><input type="file" accept="image/*" onchange="hu(this,'sim')"></div> |
| | <div class="fr" style="margin-top:10px"><div class="fg" style="flex:2"><div class="fl">๐ฅ ์์ ํ๋ฆฌ์
</div><select id="ps"> |
| | <option>์์ (์ง์ ์
๋ ฅ)</option><option>๐๏ธ ์์ฐ์ ์ฐฉ ์๊บผํ</option><option>๐๏ธ ์ ๊ฐ ์๊บผํ</option><option>๐ ์ฝ๋ ์ฑํ</option><option>๐ ์ฝง๋ ์ฑํ</option> |
| | <option>๐ฆท ์ฌ๊ฐํฑ ์ถ์</option><option>๐ ํ์์ฃผ๋ฆ ํ๋ฌ</option><option>๐ ์ด๋ง ๋ณดํก์ค</option><option>๐ ์
์ ํ๋ฌ</option><option>๐ฅ ๋+์ฝ ๋์</option><option>๐ฅ ํํ์ด์ค ๋ฆฌํํ
</option><option>โจ ๋์ ์คํ์ผ</option> |
| | </select></div><div class="fg" style="flex:1"><div class="fl">๐ ๋น์จ</div><select id="ar"><option>auto</option><option>1:1</option><option>3:4</option><option>4:3</option></select></div></div> |
| | <div class="fg"><div class="fl">โ๏ธ ์ถ๊ฐ ์ง์</div><textarea id="cp" placeholder="ํ๋ฆฌ์
์ธ ์ถ๊ฐ ์์ฒญ"></textarea></div> |
| | <div class="fg" style="margin-top:4px"><div class="fl">๐ช ๊ฐ๋</div><div class="rg"> |
| | <input type="radio" name="int" id="i1" value="์์ฐ์ค๋ฝ๊ฒ (Subtle)"><label for="i1">๐ฟ ์์ฐ</label> |
| | <input type="radio" name="int" id="i2" value="๋ณดํต (Moderate)" checked><label for="i2">โก ๋ณดํต</label> |
| | <input type="radio" name="int" id="i3" value="ํ์คํ๊ฒ (Strong)"><label for="i3">๐ฅ ํ์ค</label> |
| | </div></div> |
| | <button class="btn br" id="bs" onclick="runSim()">๐ ์๋ฎฌ๋ ์ด์
์์</button></div> |
| | |
| | <div class="sco" id="sco"><div class="sp" id="spp"></div><div class="sg"></div> |
| | <div class="fc"><div class="pr"></div><div class="pr" style="animation-delay:1s"></div><div class="pr" style="animation-delay:2s"></div> |
| | <div class="sc tl"></div><div class="sc tr"></div><div class="sc bl"></div><div class="sc br"></div><div class="ll"></div> |
| | <svg class="fm" viewBox="0 0 220 280"><ellipse class="fo" cx="110" cy="145" rx="78" ry="105" style="stroke-dasharray:600"/> |
| | <ellipse class="fo" cx="78" cy="118" rx="22" ry="10" style="animation-delay:.4s;stroke-dasharray:120;stroke:#e11d48;stroke-width:1.2"/> |
| | <ellipse class="fo" cx="142" cy="118" rx="22" ry="10" style="animation-delay:.5s;stroke-dasharray:120;stroke:#e11d48;stroke-width:1.2"/> |
| | <path class="fo" d="M52,98 Q78,84 102,98" style="animation-delay:.7s;stroke-dasharray:80;stroke-width:1"/> |
| | <path class="fo" d="M118,98 Q142,84 168,98" style="animation-delay:.8s;stroke-dasharray:80;stroke-width:1"/> |
| | <path class="fo" d="M110,128 L110,160 Q102,172 94,166 M110,160 Q118,172 126,166" style="animation-delay:1s;stroke-dasharray:100;stroke:#0d9488;stroke-width:1.2"/> |
| | <path class="fo" d="M82,195 Q96,206 110,207 Q124,206 138,195" style="animation-delay:1.3s;stroke-dasharray:80;stroke:#f59e0b;stroke-width:1.2"/> |
| | </svg> |
| | <div class="sd" style="top:10%;left:-22%;animation-delay:.5s">SYMMETRY: ANALYZING</div> |
| | <div class="sd" style="top:38%;right:-25%;animation-delay:1.2s">RATIO: 1.618</div> |
| | <div class="sd" style="top:62%;left:-20%;animation-delay:2s">BONE: MAPPING</div> |
| | <div class="sd" style="top:82%;right:-22%;animation-delay:2.8s">TISSUE: READY</div> |
| | </div> |
| | <div style="position:relative;z-index:10"><div class="ssm" id="stx">๐ฉบ ๋ถ์ ์ค...</div><div class="sss" id="ssu">SOMA Processing</div><div class="spb"><div class="spf" id="spg" style="width:5%"></div></div></div></div> |
| | |
| | <div id="sr" style="display:none"><div class="em" id="se"></div> |
| | <div class="riw" id="sg" style="display:none"><img id="si"><div class="ril">๐จ ์๋ฎฌ๋ ์ด์
๊ฒฐ๊ณผ</div></div> |
| | <div id="sb" style="display:none;margin-top:10px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px"></div> |
| | <div class="rgg" id="sa" style="display:none;margin-top:10px"><div class="riw"><img id="s45"><div class="ril">๐ 45๋</div></div><div class="riw"><img id="ssd"><div class="ril">๐ ์ธก๋ฉด</div></div></div> |
| | <div class="rh" id="srp" style="margin-top:10px"></div></div></div> |
| |
|
| | <footer class="ft"><div class="ftb">Proto-AGI FACE</div><div class="ftd"><a href="https://vidraft.net" target="_blank">VIDRAFT</a> ยท <a href="/gradio" style="color:var(--teal);font-weight:600">Gradio UI โ</a></div><div class="ftl"></div><div class="ftt">ํ์ค์ผ์คํธ๋ ์ด์
ร ํ์ ๋ถ์ ร ๋ฉํ์ธ์ง ยท 5-Agent</div></footer> |
| | </div> |
| | <script> |
| | const B=window.location.origin,U={face:null,physio:null,c1:null,c2:null,sim:null}; |
| | function st(t){document.querySelectorAll('.ni').forEach(e=>e.classList.remove('a'));document.querySelectorAll('.pnl').forEach(e=>e.classList.remove('a'));document.querySelector(`[data-t="${t}"]`).classList.add('a');document.getElementById(`p-${t}`).classList.add('a')} |
| | function hu(inp,k){const f=inp.files&&inp.files[0];if(!f)return;const z=inp.closest('.uz'),ph=z.querySelector('.ph'),im=z.querySelector('.ui');const r=new FileReader();r.onload=e=>{im.src=e.target.result;im.style.display='block';if(ph)ph.style.display='none';z.classList.add('hi')};r.readAsDataURL(f);ul(f,k)} |
| | async function ul(f,k){const fd=new FormData();fd.append('files',f);for(const u of[`${B}/gradio/gradio_api/upload`,`${B}/gradio/upload`,`${B}/gradio_api/upload`,`${B}/upload`]){try{const r=await fetch(u,{method:'POST',body:fd});if(r.ok){const j=await r.json();U[k]=Array.isArray(j)?j[0]:j;return}}catch{}}} |
| | function mf(p){return{path:p,meta:{_type:'gradio.FileData'},orig_name:'face.png',mime_type:'image/png'}} |
| | async function gc(api,data){ |
| | |
| | let sseUrl=null; |
| | for(const u of[`${B}/gradio/gradio_api/call${api}`,`${B}/gradio/call${api}`,`${B}/gradio/api${api}`,`${B}/api${api}`,`${B}/gradio_api/call${api}`]){ |
| | try{ |
| | const r=await fetch(u,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({data})}); |
| | if(!r.ok)continue; |
| | const j=await r.json(); |
| | if(!j.event_id)continue; |
| | sseUrl=`${u}/${j.event_id}`; |
| | break; |
| | }catch{} |
| | } |
| | if(!sseUrl)throw new Error('API ์ฐ๊ฒฐ ์คํจ (์๋ฒ์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค)'); |
| | |
| | |
| | return new Promise((ok,no)=>{ |
| | let done=false,retries=0,es=null; |
| | const MAX_RETRY=150; |
| | const TOTAL_TO=setTimeout(()=>{if(!done){done=true;if(es)es.close();no(new Error('์๊ฐ ์ด๊ณผ (10๋ถ)'));}},600000); |
| | function resolve(val){if(done)return;done=true;clearTimeout(TOTAL_TO);if(es)es.close();ok(val);} |
| | function reject(err){if(done)return;done=true;clearTimeout(TOTAL_TO);if(es)es.close();no(err);} |
| | function onData(e){ |
| | try{ |
| | const raw=JSON.parse(e.data); |
| | if(!raw)return; |
| | |
| | if(raw.msg==='process_completed'&&raw.output&&raw.output.data){resolve(raw.output.data);return;} |
| | |
| | const p=Array.isArray(raw)?raw:(raw.data&&Array.isArray(raw.data)?raw.data:null); |
| | if(p)resolve(p); |
| | }catch{} |
| | } |
| | function connect(){ |
| | if(done)return; |
| | es=new EventSource(sseUrl); |
| | es.onmessage=onData; |
| | es.addEventListener('complete',onData); |
| | es.addEventListener('process_completed',onData); |
| | es.onerror=()=>{ |
| | if(done)return; |
| | es.close(); |
| | retries++; |
| | if(retries>MAX_RETRY){reject(new Error('์ฐ๊ฒฐ์ด ๋ฐ๋ณต ๋๊น (์ฌ์๋ ์ด๊ณผ)'));return;} |
| | setTimeout(connect,2000); |
| | }; |
| | } |
| | connect(); |
| | }); |
| | } |
| | function iu(d){if(!d)return null;if(typeof d==='string'){if(d.startsWith('/file='))return B+'/gradio'+d;return d}const u=d.url||d.path||(d.value&&(d.value.url||d.value.path));if(!u)return null;if(u.startsWith('/file='))return B+'/gradio'+u;if(!u.startsWith('http'))return B+'/gradio/file='+u;return u} |
| | function md(s){return s.replace(/^### (.*$)/gm,'<h3>$1</h3>').replace(/^## (.*$)/gm,'<h2>$1</h2>').replace(/^# (.*$)/gm,'<h1>$1</h1>').replace(/\*\*(.*?)\*\*/g,'<b>$1</b>').replace(/\*(.*?)\*/g,'<em>$1</em>').replace(/^> (.*$)/gm,'<blockquote>$1</blockquote>').replace(/^---$/gm,'<hr>').replace(/^- (.*$)/gm,'<li>$1</li>').replace(/\n\n/g,'<br><br>').replace(/\n/g,'<br>')} |
| | function sl(id){document.getElementById(id).classList.add('a')}function hl(id){document.getElementById(id).classList.remove('a')} |
| | |
| | async function runFace(){if(!U.face){alert('์ฌ์ง์ ์
๋ก๋ํด์ฃผ์ธ์.');return}const b=document.getElementById('bf');b.disabled=true;document.getElementById('rf').innerHTML='';sl('ld-face');try{const r=await gc('/face_analysis',[mf(U.face),document.getElementById('wk').value]);hl('ld-face');document.getElementById('rf').innerHTML=md(r[0]||'')}catch(e){hl('ld-face');document.getElementById('rf').innerHTML='<div class="em">โ ๏ธ '+e.message+'</div>'}b.disabled=false} |
| | |
| | async function runPhysio(){if(!U.physio){alert('์ฌ์ง์ ์
๋ก๋ํด์ฃผ์ธ์.');return}const b=document.getElementById('bp');b.disabled=true;document.getElementById('rpv').innerHTML='';document.getElementById('rp').innerHTML='';sl('ld-physio');try{const r=await gc('/physiognomy_analysis',[mf(U.physio),document.getElementById('wk').value]);hl('ld-physio');document.getElementById('rpv').innerHTML=r[0]||'';document.getElementById('rp').innerHTML=md(r[1]||'')}catch(e){hl('ld-physio');document.getElementById('rp').innerHTML='<div class="em">โ ๏ธ '+e.message+'</div>'}b.disabled=false} |
| | |
| | async function runCompat(){if(!U.c1||!U.c2){alert('๋ ์ฌ๋์ ์ฌ์ง์ ๋ชจ๋ ์
๋ก๋ํด์ฃผ์ธ์.');return}const b=document.getElementById('bc');b.disabled=true;document.getElementById('rcv').innerHTML='';document.getElementById('rc').innerHTML='';sl('ld-compat');const rel=document.querySelector('input[name="rel"]:checked').value;try{const r=await gc('/compatibility_analysis',[mf(U.c1),mf(U.c2),rel,document.getElementById('wk').value]);hl('ld-compat');document.getElementById('rcv').innerHTML=r[0]||'';document.getElementById('rc').innerHTML=md(r[1]||'')}catch(e){hl('ld-compat');document.getElementById('rc').innerHTML='<div class="em">โ ๏ธ '+e.message+'</div>'}b.disabled=false} |
| | |
| | const SS=[{t:'๐ฉบ ์ผ๊ตด ๋ถ์ ์ค...',s:'Doctor Agent',p:12},{t:'๐ก ํ๋กฌํํธ ์ต์ ํ...',s:'Creator Agent',p:25},{t:'๐จ ์ด๋ฏธ์ง ์์ฑ ์ค...',s:'Nano Banana 2',p:45},{t:'โ๏ธ ํ์ง ๊ฒ์ฆ...',s:'Critic Agent',p:65},{t:'๐ ๋ค๊ฐ๋ ์์ฑ...',s:'Angle Gen',p:78},{t:'๐ฏ ๋ฆฌํฌํธ ์์ฑ...',s:'Director Agent',p:90}]; |
| | let si=0,stm=null; |
| | function startSc(){const o=document.getElementById('sco');o.style.display='block';o.classList.add('a');const c=document.getElementById('spp');c.innerHTML='';for(let i=0;i<20;i++){const s=document.createElement('span');s.style.left=Math.random()*100+'%';s.style.animationDelay=Math.random()*4+'s';s.style.animationDuration=(3+Math.random()*3)+'s';c.appendChild(s)}si=0;uSc();stm=setInterval(()=>{si++;if(si<SS.length)uSc()},5000)} |
| | function uSc(){const s=SS[si];document.getElementById('stx').textContent=s.t;document.getElementById('ssu').textContent=s.s;document.getElementById('spg').style.width=s.p+'%'} |
| | function stopSc(){if(stm)clearInterval(stm);const o=document.getElementById('sco');o.classList.remove('a');o.style.display='none'} |
| | async function runSim(){if(!U.sim){alert('์ฌ์ง์ ์
๋ก๋ํด์ฃผ์ธ์.');return}const b=document.getElementById('bs');b.disabled=true;document.getElementById('sr').style.display='none';['sg','sb','sa'].forEach(id=>{document.getElementById(id).style.display='none'});document.getElementById('se').textContent='';document.getElementById('srp').innerHTML='';startSc();try{const r=await gc('/run_simulation',[mf(U.sim),document.getElementById('cp').value,document.getElementById('ps').value,document.querySelector('input[name="int"]:checked').value,document.getElementById('ar').value,document.getElementById('fk').value,document.getElementById('wk').value]);stopSc();document.getElementById('sr').style.display='block';const gi=iu(r[0]),ba=r[1]||'',rp=r[2]||'',a45=iu(r[3]),as=iu(r[4]),er=r[5]||'';if(er)document.getElementById('se').textContent='โ ๏ธ '+er;if(gi){document.getElementById('si').src=gi;document.getElementById('sg').style.display='block'}if(ba){document.getElementById('sb').innerHTML=ba;document.getElementById('sb').style.display='block'}if(a45||as){if(a45)document.getElementById('s45').src=a45;if(as)document.getElementById('ssd').src=as;document.getElementById('sa').style.display='grid'}if(rp)document.getElementById('srp').innerHTML=md(rp);document.getElementById('sr').scrollIntoView({behavior:'smooth'})}catch(e){stopSc();document.getElementById('sr').style.display='block';document.getElementById('se').textContent='โ ๏ธ '+e.message}b.disabled=false} |
| | document.querySelectorAll('.uz').forEach(z=>{z.addEventListener('dragover',e=>{e.preventDefault();z.style.borderColor='var(--accent)'});z.addEventListener('dragleave',()=>{z.style.borderColor=''});z.addEventListener('drop',e=>{e.preventDefault();z.style.borderColor='';const f=e.dataTransfer.files&&e.dataTransfer.files[0];if(f&&f.type.startsWith('image/')){const inp=z.querySelector('input[type=file]');const dt=new DataTransfer();dt.items.add(f);inp.files=dt.files;inp.dispatchEvent(new Event('change'))}})}); |
| | |
| | (function(){ |
| | function initBA(uid){ |
| | var box=document.getElementById(uid+'_box'); |
| | var clip=document.getElementById(uid+'_clip'); |
| | var line=document.getElementById(uid+'_line'); |
| | var range=document.getElementById(uid+'_range'); |
| | if(!box||!clip||!line||!range)return; |
| | if(box.dataset.baInit==='1')return; |
| | box.dataset.baInit='1'; |
| | var dragging=false; |
| | function setPos(pct){pct=Math.max(0,Math.min(100,pct));clip.style.width=pct+'%';line.style.left=pct+'%';range.value=pct;} |
| | function getPct(e){var rect=box.getBoundingClientRect();var x=(e.touches?e.touches[0].clientX:e.clientX)-rect.left;return(x/rect.width)*100;} |
| | box.addEventListener('mousedown',function(e){dragging=true;setPos(getPct(e));e.preventDefault();}); |
| | document.addEventListener('mousemove',function(e){if(dragging)setPos(getPct(e));}); |
| | document.addEventListener('mouseup',function(){dragging=false;}); |
| | box.addEventListener('touchstart',function(e){dragging=true;setPos(getPct(e));e.preventDefault();},{passive:false}); |
| | box.addEventListener('touchmove',function(e){if(dragging){setPos(getPct(e));e.preventDefault();}},{passive:false}); |
| | box.addEventListener('touchend',function(){dragging=false;}); |
| | range.addEventListener('input',function(){setPos(parseFloat(this.value));}); |
| | } |
| | setInterval(function(){ |
| | document.querySelectorAll('[data-ba-uid]').forEach(function(el){ |
| | if(el.dataset.baInit!=='1') initBA(el.dataset.baUid); |
| | }); |
| | },500); |
| | })(); |
| | </script> |
| | </body> |
| | </html> |