118 lines
6.1 KiB
HTML
118 lines
6.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>WEVIA — Agent Avatar Picker (SSOT)</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@700;900&family=Nunito:wght@600;700;800&display=swap" rel="stylesheet">
|
|
<style>
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{background:#050a18;color:#e2e8f0;font-family:Nunito,sans-serif;min-height:100vh}
|
|
.hdr{background:linear-gradient(135deg,#0f1629,#1a2035);padding:14px 20px;border-bottom:1px solid rgba(6,182,212,.2);position:sticky;top:0;z-index:50;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px}
|
|
.hdr h1{font:900 15px Orbitron;color:#06b6d4;letter-spacing:1px}
|
|
.nav{display:flex;gap:8px;font-size:11px;flex-wrap:wrap}
|
|
.nav a{color:#94a3b8;text-decoration:none;padding:4px 10px;border-radius:6px;border:1px solid rgba(255,255,255,.08)}
|
|
.nav a:hover{color:#06b6d4;border-color:#06b6d4}
|
|
.bar{padding:10px 20px;background:#0a0f1e;border-bottom:1px solid rgba(255,255,255,.04);display:flex;gap:8px;align-items:center;flex-wrap:wrap}
|
|
.fb{padding:5px 14px;border-radius:6px;border:1px solid rgba(255,255,255,.1);background:none;color:#94a3b8;font:700 10px Nunito;cursor:pointer;letter-spacing:1px;transition:.15s}
|
|
.fb.ac{border-color:#06b6d4;background:rgba(6,182,212,.12);color:#06b6d4}
|
|
.search{flex:1;min-width:200px;padding:6px 12px;border-radius:6px;border:1px solid rgba(255,255,255,.1);background:rgba(0,0,0,.3);color:#e2e8f0;font:600 11px Nunito;outline:none}
|
|
.stats{font-size:10px;color:#64748b}
|
|
.stats b{color:#06b6d4}
|
|
.grid{padding:16px;display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}
|
|
.card{background:#0f1629;border:1.5px solid rgba(255,255,255,.06);border-radius:12px;padding:14px;display:flex;flex-direction:column;align-items:center;gap:8px;transition:.15s;cursor:pointer}
|
|
.card:hover{transform:translateY(-2px);border-color:#06b6d4;box-shadow:0 4px 16px rgba(6,182,212,.15)}
|
|
.card.master{border-color:rgba(255,215,0,.5);background:linear-gradient(135deg,#1a1410,#0f1629)}
|
|
.card.human{border-color:rgba(74,222,128,.3)}
|
|
.card.tool{border-color:rgba(139,92,246,.3)}
|
|
.card.gap{box-shadow:0 0 14px rgba(34,211,238,.15);border-color:#22d3ee}
|
|
.av{width:72px;height:72px;display:flex;align-items:center;justify-content:center;font-size:42px;line-height:1;border-radius:50%;background:rgba(255,255,255,.05);border:2.5px solid;flex-shrink:0;overflow:hidden}
|
|
.card.master .av{border-color:rgba(255,215,0,.65);background:rgba(255,215,0,.08);width:84px;height:84px;font-size:50px}
|
|
.card.human .av{border-color:rgba(74,222,128,.5);background:rgba(74,222,128,.06)}
|
|
.card.tool .av{border-color:rgba(139,92,246,.5);background:rgba(139,92,246,.08)}
|
|
.nm{font-weight:800;font-size:12px;text-align:center;color:#e2e8f0;line-height:1.2;max-width:160px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
|
|
.meta{display:flex;gap:4px;align-items:center;font-size:9px;color:#64748b;flex-wrap:wrap;justify-content:center}
|
|
.tag{padding:1px 6px;border-radius:3px;background:rgba(255,255,255,.06);font-weight:700;letter-spacing:.5px;text-transform:uppercase}
|
|
.tag.gap{background:rgba(34,211,238,.15);color:#22d3ee}
|
|
.tag.role{background:rgba(255,255,255,.04);color:#94a3b8}
|
|
.empty{text-align:center;padding:40px;color:#64748b;font-size:12px}
|
|
</style></head><body>
|
|
<div class="hdr">
|
|
<h1>🎨 AGENT AVATAR PICKER · SSOT v2.json</h1>
|
|
<div class="nav">
|
|
<a href="/agents-archi.html">← Architecture 3D</a>
|
|
<a href="/wevia-meeting-rooms.html">Meeting Rooms</a>
|
|
<a href="/enterprise-model.html">Enterprise</a>
|
|
<a href="/agents-fleet.html">Fleet</a>
|
|
</div>
|
|
</div>
|
|
<div class="bar">
|
|
<button class="fb ac" data-f="all">ALL</button>
|
|
<button class="fb" data-f="master">MASTER</button>
|
|
<button class="fb" data-f="human">HUMAN</button>
|
|
<button class="fb" data-f="tool">TOOL</button>
|
|
<button class="fb" data-f="gap">GAP ONLY</button>
|
|
<input class="search" id="srch" placeholder="🔍 Search agent...">
|
|
<div class="stats" id="stats">Loading...</div>
|
|
</div>
|
|
<div class="grid" id="G"><div class="empty">Loading SSOT (agent-avatars-v2.json)...</div></div>
|
|
<script>
|
|
let DATA = {};
|
|
let activeFilter = 'all';
|
|
let activeSearch = '';
|
|
|
|
async function load(){
|
|
try {
|
|
const r = await fetch('/api/agent-avatars-v2.json?t=' + Date.now());
|
|
DATA = await r.json();
|
|
render();
|
|
} catch(e) {
|
|
document.getElementById('G').innerHTML = '<div class="empty">ERR loading SSOT: ' + e.message + '</div>';
|
|
}
|
|
}
|
|
|
|
function render(){
|
|
const G = document.getElementById('G');
|
|
const entries = Object.entries(DATA);
|
|
const filtered = entries.filter(([n, a]) => {
|
|
if (activeSearch && !n.toLowerCase().includes(activeSearch)) return false;
|
|
if (activeFilter === 'all') return true;
|
|
if (activeFilter === 'gap') return a.isGap;
|
|
return a.persona === activeFilter;
|
|
});
|
|
|
|
if (!filtered.length) {
|
|
G.innerHTML = '<div class="empty">No agent matches</div>';
|
|
document.getElementById('stats').innerHTML = '<b>0</b> / ' + entries.length;
|
|
return;
|
|
}
|
|
|
|
G.innerHTML = filtered.map(([n, a]) => {
|
|
const cls = ['card', a.persona || 'human'];
|
|
if (a.isGap) cls.push('gap');
|
|
const safeN = n.replace(/[<>"']/g, c => ({'<':'<','>':'>','"':'"',"'":'''})[c]);
|
|
return `<div class="${cls.join(' ')}" title="${safeN}">
|
|
<div class="av">${a.emoji || '👤'}</div>
|
|
<div class="nm">${safeN}</div>
|
|
<div class="meta">
|
|
${a.isGap ? '<span class="tag gap">GAP</span>' : ''}
|
|
${a.role ? '<span class="tag role">' + a.role + '</span>' : ''}
|
|
</div>
|
|
</div>`;
|
|
}).join('');
|
|
|
|
document.getElementById('stats').innerHTML = '<b>' + filtered.length + '</b> / ' + entries.length + ' agents';
|
|
}
|
|
|
|
document.querySelectorAll('.fb').forEach(b => b.onclick = () => {
|
|
document.querySelectorAll('.fb').forEach(x => x.classList.remove('ac'));
|
|
b.classList.add('ac');
|
|
activeFilter = b.dataset.f;
|
|
render();
|
|
});
|
|
|
|
document.getElementById('srch').oninput = e => { activeSearch = e.target.value.toLowerCase().trim(); render(); };
|
|
|
|
load();
|
|
</script>
|
|
|
|
<script src="/api/a11y-auto-enhancer.js" defer></script>
|
|
</body></html>
|