Replaces the static React-Flow world forest with a real-time WebGL view of the swarm working, plus the live event contract that feeds it. Phase A — the live contract + feed: - frontend/src/lib/live/taxonomy.ts — the 13-event Clawmates Event Taxonomy as typed TS (the shared World/Observe contract). - frontend/src/lib/live/useClawmatesLive.ts — native shared-singleton live client (EventSource to /api/world/live, typed fan-out, replay-of-last-state to late subscribers, refcounted, synthetic fallback so views are always alive). - crates/cm-api/src/routes/world.rs — GET /api/world/live, authed + workspace- scoped SSE emitting the taxonomy (real agent.status from live-container state, a topology.update of the workspace's agents, telemetry with real doorsPending), mirroring run_events_sse. normalize() seam documented for run_events->world.touch. Phase B — the WebGL engine: - frontend/src/components/world/engine.ts — Gource-inspired force-directed model: org/company/team tree (sibling repulsion + parent spring + friction), agent pawns that converge on the touched node and beam it, world nodes that glow with heat and fade when idle. Framework-agnostic (renderer-independent) state+math. - frontend/src/components/world/WorldCanvas.tsx — three.js scene (ortho cam, UnrealBloom), render loop syncing engine state, camera auto-fit, HTML labels, raycast click->select, Hierarchy/Flat/Live formation switch. - Dashboard.tsx: swap <WorldFlow/> -> <WorldCanvas/> at the world-tier seam (shared claw-tier pieces untouched; WorldFlow.tsx kept for now). - Adds three (+ @types/three). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
651 lines
65 KiB
HTML
651 lines
65 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<script src="./support.js"></script>
|
||
</head>
|
||
<body>
|
||
<x-dc>
|
||
<helmet>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
* { box-sizing: border-box; }
|
||
html, body { margin: 0; padding: 0; background: #08080a; }
|
||
body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
|
||
@keyframes cm-flow { to { stroke-dashoffset: -24; } }
|
||
@keyframes cm-blink { 0%,100% { opacity: 1; } 50% { opacity: .25; } }
|
||
@keyframes cm-halo { 0% { transform: scale(.7); opacity: .55; } 100% { transform: scale(1.9); opacity: 0; } }
|
||
@keyframes cm-fade { from { opacity: 0; } to { opacity: 1; } }
|
||
</style>
|
||
</helmet>
|
||
|
||
<div style="width:100%; height:100vh; min-height:640px; background:#08080a; display:flex; flex-direction:column; color:#f3f3f5; overflow:hidden;">
|
||
|
||
<!-- TOP BAR -->
|
||
<div style="height:54px; flex:none; display:flex; align-items:center; gap:14px; padding:0 18px; border-bottom:1px solid rgba(255,255,255,.06); background:linear-gradient(180deg,#0d0d10,#0a0a0c);">
|
||
<div style="display:flex; align-items:center; gap:10px;">
|
||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none">
|
||
<path d="M11 3 L18.5 17 L3.5 17 Z" stroke="#ff6f61" stroke-width="1.3" stroke-linejoin="round" opacity="0.55"></path>
|
||
<circle cx="11" cy="3.5" r="2.4" fill="#ff6f61"></circle><circle cx="18" cy="17" r="2.4" fill="#ff6f61"></circle><circle cx="4" cy="17" r="2.4" fill="#ff6f61"></circle>
|
||
</svg>
|
||
<span style="font-size:15px; font-weight:700; color:#f3f3f5; letter-spacing:-.01em;">Clawmates</span>
|
||
</div>
|
||
<div style="width:1px; height:22px; background:rgba(255,255,255,.08);"></div>
|
||
<div style="display:flex; align-items:center; gap:6px; font-family:'JetBrains Mono',monospace; font-size:12px;">
|
||
<span style="cursor:pointer; border-radius:6px;" style="{{ crumbOrg }}" onClick="{{ goOrg }}">Acme Org</span>
|
||
<span style="color:#3a3a40;">/</span>
|
||
<span style="cursor:pointer; border-radius:6px;" style="{{ crumbCo }}" onClick="{{ goCompany }}">Acme Corp</span>
|
||
<span style="color:#3a3a40;">/</span>
|
||
<span style="cursor:pointer; border-radius:6px;" style="{{ crumbTeam }}" onClick="{{ goTeam }}">Growth Team</span>
|
||
<sc-if value="{{ isClaw }}" hint-placeholder-val="{{ false }}">
|
||
<span style="color:#3a3a40;">/</span>
|
||
<span style="cursor:pointer; border-radius:6px;" style="{{ crumbClaw }}">{{ selName }}</span>
|
||
</sc-if>
|
||
</div>
|
||
<div style="flex:1;"></div>
|
||
<div style="display:flex; align-items:center; gap:7px; font-family:'JetBrains Mono',monospace; font-size:11px; color:#5fd08a; padding:5px 10px; border:1px solid rgba(95,208,138,.25); border-radius:7px; background:rgba(95,208,138,.06);">
|
||
<span style="width:7px; height:7px; border-radius:50%; background:#5fd08a; animation:cm-blink 1.6s infinite;"></span>
|
||
6 claws · running
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:7px; padding:6px 12px; border-radius:8px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); color:#2a0d0a; font-size:12px; font-weight:700; cursor:pointer;">
|
||
<span style="font-size:15px; line-height:1;">+</span> Deploy from template
|
||
</div>
|
||
<div style="width:32px; height:32px; border-radius:8px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:700; color:#2a0d0a;">O</div>
|
||
</div>
|
||
|
||
<!-- BODY -->
|
||
<div style="flex:1; display:flex; min-height:0;">
|
||
|
||
<!-- STRUCTURE RAIL -->
|
||
<div style="width:60px; flex:none; border-right:1px solid rgba(255,255,255,.06); background:#0a0a0c; display:flex; flex-direction:column; align-items:center; padding:14px 0;">
|
||
<div style="display:flex; flex-direction:column; gap:6px; align-items:center;">
|
||
|
||
<div style="position:relative; width:42px; height:48px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border-radius:10px; cursor:pointer; color:{{ railOrgColor }}; background:{{ railOrgBg }};" onClick="{{ goOrg }}">
|
||
<sc-if value="{{ railOrgOn }}" hint-placeholder-val="{{ false }}"><span style="position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 3px 3px 0; background:#ff6f61;"></span></sc-if>
|
||
<svg width="20" height="20" viewBox="0 0 20 20"><circle cx="10" cy="10" r="7.5" stroke="currentColor" stroke-width="1.4" fill="none"></circle><circle cx="10" cy="10" r="2.6" fill="currentColor"></circle></svg>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:8px;">ORG</span>
|
||
</div>
|
||
|
||
<div style="position:relative; width:42px; height:48px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border-radius:10px; cursor:pointer; color:{{ railCoColor }}; background:{{ railCoBg }};" onClick="{{ goCompany }}">
|
||
<sc-if value="{{ railCoOn }}" hint-placeholder-val="{{ false }}"><span style="position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 3px 3px 0; background:#ff6f61;"></span></sc-if>
|
||
<svg width="20" height="20" viewBox="0 0 20 20"><rect x="3.5" y="5" width="6" height="11" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect><rect x="10.5" y="2.5" width="6" height="13.5" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect></svg>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:8px;">CO</span>
|
||
</div>
|
||
|
||
<div style="position:relative; width:42px; height:48px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border-radius:10px; cursor:pointer; color:{{ railTeamColor }}; background:{{ railTeamBg }};" onClick="{{ goTeam }}">
|
||
<sc-if value="{{ railTeamOn }}" hint-placeholder-val="{{ true }}"><span style="position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 3px 3px 0; background:#ff6f61;"></span></sc-if>
|
||
<svg width="20" height="20" viewBox="0 0 20 20"><circle cx="10" cy="5" r="2.2" fill="currentColor"></circle><circle cx="5" cy="13.5" r="2.2" fill="currentColor"></circle><circle cx="15" cy="13.5" r="2.2" fill="currentColor"></circle><path d="M10 5 L5 13.5 M10 5 L15 13.5 M5 13.5 L15 13.5" stroke="currentColor" stroke-width="1.1" opacity=".5"></path></svg>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:8px;">TEAM</span>
|
||
</div>
|
||
|
||
<div style="position:relative; width:42px; height:48px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border-radius:10px; cursor:pointer; color:{{ railClawColor }}; background:{{ railClawBg }};" onClick="{{ goClawView }}">
|
||
<sc-if value="{{ railClawOn }}" hint-placeholder-val="{{ true }}"><span style="position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 3px 3px 0; background:#ff6f61;"></span></sc-if>
|
||
<svg width="20" height="20" viewBox="0 0 20 20"><rect x="4" y="4" width="12" height="12" rx="3.5" stroke="currentColor" stroke-width="1.4" fill="none"></rect><circle cx="10" cy="10" r="2.4" fill="currentColor"></circle></svg>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:8px;">CLAW</span>
|
||
</div>
|
||
</div>
|
||
<div style="flex:1;"></div>
|
||
<div style="width:30px; height:30px; border-radius:8px; border:1px dashed rgba(255,255,255,.16); display:flex; align-items:center; justify-content:center; color:#ff6f61; font-size:18px; font-weight:300; cursor:pointer;">+</div>
|
||
</div>
|
||
|
||
<!-- CONTEXT LIST -->
|
||
<div style="width:252px; flex:none; border-right:1px solid rgba(255,255,255,.06); background:#0b0b0e; display:flex; flex-direction:column; min-height:0;">
|
||
<sc-if value="{{ isTeam }}" hint-placeholder-val="{{ true }}">
|
||
<div style="padding:16px 16px 12px;">
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.12em; color:#5a5a62; margin-bottom:6px;">TEAM · 6 CLAWS</div>
|
||
<div style="font-size:18px; font-weight:700; color:#f3f3f5; letter-spacing:-.01em;">Growth Team</div>
|
||
</div>
|
||
<div style="display:flex; gap:18px; padding:0 16px; border-bottom:1px solid rgba(255,255,255,.06);">
|
||
<div style="font-size:12px; font-weight:600; color:#f3f3f5; padding-bottom:9px; border-bottom:2px solid #ff6f61;">Members</div>
|
||
<div style="font-size:12px; font-weight:500; color:#6a6a72; padding-bottom:9px; border-bottom:2px solid transparent; cursor:pointer;">Templates</div>
|
||
</div>
|
||
<div style="flex:1; overflow-y:auto; padding:8px;">
|
||
<div style="display:flex; flex-direction:column; gap:2px;">
|
||
<sc-for list="{{ nodes }}" as="m" hint-placeholder-count="6">
|
||
<div style="display:flex; align-items:center; gap:10px; padding:8px 10px; border-radius:9px; cursor:pointer; position:relative; transition:background .15s; background:{{ m.rowBg }};" onClick="{{ m.onSelect }}">
|
||
<sc-if value="{{ m.selected }}" hint-placeholder-val="{{ false }}"><span style="position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 3px 3px 0; background:#ff6f61;"></span></sc-if>
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:{{ m.grad }}; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:700; color:{{ m.ink }};">{{ m.initial }}</div>
|
||
<div style="flex:1; min-width:0;">
|
||
<div style="font-size:13px; font-weight:600; color:{{ m.labelColor }};">{{ m.name }}</div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72;">{{ m.role }}</div>
|
||
</div>
|
||
<span style="width:7px; height:7px; border-radius:50%; background:{{ m.statusColor }};"></span>
|
||
</div>
|
||
</sc-for>
|
||
</div>
|
||
</div>
|
||
<div style="flex:none; padding:10px 12px; border-top:1px solid rgba(255,255,255,.06);">
|
||
<div style="display:flex; align-items:center; justify-content:center; gap:7px; height:34px; border-radius:8px; background:rgba(255,111,97,.1); border:1px solid rgba(255,111,97,.25); color:#ff8a7a; font-size:12px; font-weight:600; cursor:pointer;">
|
||
<span style="font-size:15px; line-height:1;">+</span> Deploy claw from template
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
<sc-if value="{{ isCompany }}" hint-placeholder-val="{{ false }}">
|
||
<div style="padding:16px 16px 12px;">
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.12em; color:#5a5a62; margin-bottom:6px;">COMPANY · 4 TEAMS</div>
|
||
<div style="font-size:18px; font-weight:700; color:#f3f3f5; letter-spacing:-.01em;">Acme Corp</div>
|
||
</div>
|
||
<div style="display:flex; gap:18px; padding:0 16px; border-bottom:1px solid rgba(255,255,255,.06);">
|
||
<div style="font-size:12px; font-weight:600; color:#f3f3f5; padding-bottom:9px; border-bottom:2px solid #ff6f61;">Teams</div>
|
||
<div style="font-size:12px; font-weight:500; color:#6a6a72; padding-bottom:9px; border-bottom:2px solid transparent; cursor:pointer;">Templates</div>
|
||
</div>
|
||
<div style="flex:1; overflow-y:auto; padding:8px;">
|
||
<div style="display:flex; flex-direction:column; gap:2px;">
|
||
<div style="display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:9px; cursor:pointer;" onClick="{{ enterTeam }}">
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:#141417; border:1px solid rgba(255,255,255,.08); display:flex; align-items:center; justify-content:center;"><span style="width:8px; height:8px; border-radius:2px; background:#5ec8d8;"></span></div>
|
||
<div style="flex:1;"><div style="font-size:13px; font-weight:600; color:#eaeaee;">Intake Team</div><div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72;">star-MoE · 3</div></div>
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:9px; cursor:pointer; background:rgba(255,111,97,.12); border:1px solid rgba(255,111,97,.28); position:relative;" onClick="{{ enterTeam }}">
|
||
<span style="position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 3px 3px 0; background:#ff6f61;"></span>
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:#1a1216; border:1px solid rgba(255,111,97,.3); display:flex; align-items:center; justify-content:center;"><span style="width:8px; height:8px; border-radius:50%; background:#ff6f61;"></span></div>
|
||
<div style="flex:1;"><div style="font-size:13px; font-weight:600; color:#fff;">Growth Team</div><div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#ff8a7a;">hub-spoke · 6 · running</div></div>
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:9px; cursor:pointer;" onClick="{{ enterTeam }}">
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:#141417; border:1px solid rgba(255,255,255,.08); display:flex; align-items:center; justify-content:center;"><span style="width:8px; height:8px; border-radius:50%; background:#5ec8d8;"></span></div>
|
||
<div style="flex:1;"><div style="font-size:13px; font-weight:600; color:#eaeaee;">Research Team</div><div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72;">blackboard · 4</div></div>
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:9px; cursor:pointer;" onClick="{{ enterTeam }}">
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:#141417; border:1px solid rgba(255,255,255,.08); display:flex; align-items:center; justify-content:center;"><span style="width:8px; height:8px; border-radius:2px; background:#3a3a40;"></span></div>
|
||
<div style="flex:1;"><div style="font-size:13px; font-weight:600; color:#eaeaee;">Ops Team</div><div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72;">holacratic · 5</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="flex:none; padding:10px 12px; border-top:1px solid rgba(255,255,255,.06);">
|
||
<div style="display:flex; align-items:center; justify-content:center; gap:7px; height:34px; border-radius:8px; background:rgba(255,111,97,.1); border:1px solid rgba(255,111,97,.25); color:#ff8a7a; font-size:12px; font-weight:600; cursor:pointer;">
|
||
<span style="font-size:15px; line-height:1;">+</span> Deploy team from template
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
<sc-if value="{{ isOrg }}" hint-placeholder-val="{{ false }}">
|
||
<div style="padding:16px 16px 12px;">
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.12em; color:#5a5a62; margin-bottom:6px;">ORG · 3 COMPANIES</div>
|
||
<div style="font-size:18px; font-weight:700; color:#f3f3f5; letter-spacing:-.01em;">Acme Org</div>
|
||
</div>
|
||
<div style="display:flex; gap:18px; padding:0 16px; border-bottom:1px solid rgba(255,255,255,.06);">
|
||
<div style="font-size:12px; font-weight:600; color:#f3f3f5; padding-bottom:9px; border-bottom:2px solid #ff6f61;">Companies</div>
|
||
<div style="font-size:12px; font-weight:500; color:#6a6a72; padding-bottom:9px; border-bottom:2px solid transparent; cursor:pointer;">Templates</div>
|
||
</div>
|
||
<div style="flex:1; overflow-y:auto; padding:8px;">
|
||
<div style="display:flex; flex-direction:column; gap:2px;">
|
||
<div style="display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:9px; cursor:pointer; background:rgba(255,111,97,.12); border:1px solid rgba(255,111,97,.28); position:relative;" onClick="{{ goCompany }}">
|
||
<span style="position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 3px 3px 0; background:#ff6f61;"></span>
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:#1a1216; border:1px solid rgba(255,111,97,.3); display:flex; align-items:center; justify-content:center; color:#ff6f61;"><svg width="15" height="15" viewBox="0 0 20 20"><rect x="3.5" y="5" width="6" height="11" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect><rect x="10.5" y="2.5" width="6" height="13.5" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect></svg></div>
|
||
<div style="flex:1;"><div style="font-size:13px; font-weight:600; color:#fff;">Acme Corp</div><div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#ff8a7a;">4 teams · 18 claws</div></div>
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:9px; cursor:pointer;" onClick="{{ goCompany }}">
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:#141417; border:1px solid rgba(255,255,255,.08); display:flex; align-items:center; justify-content:center; color:#6a6a72;"><svg width="15" height="15" viewBox="0 0 20 20"><rect x="3.5" y="5" width="6" height="11" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect><rect x="10.5" y="2.5" width="6" height="13.5" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect></svg></div>
|
||
<div style="flex:1;"><div style="font-size:13px; font-weight:600; color:#eaeaee;">Helix Labs</div><div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72;">2 teams · 9 claws</div></div>
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:9px; cursor:pointer;" onClick="{{ goCompany }}">
|
||
<div style="width:30px; height:30px; flex:none; border-radius:8px; background:#141417; border:1px solid rgba(255,255,255,.08); display:flex; align-items:center; justify-content:center; color:#6a6a72;"><svg width="15" height="15" viewBox="0 0 20 20"><rect x="3.5" y="5" width="6" height="11" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect><rect x="10.5" y="2.5" width="6" height="13.5" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect></svg></div>
|
||
<div style="flex:1;"><div style="font-size:13px; font-weight:600; color:#eaeaee;">Vega Studio</div><div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72;">1 team · 4 claws</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="flex:none; padding:10px 12px; border-top:1px solid rgba(255,255,255,.06);">
|
||
<div style="display:flex; align-items:center; justify-content:center; gap:7px; height:34px; border-radius:8px; background:rgba(255,111,97,.1); border:1px solid rgba(255,111,97,.25); color:#ff8a7a; font-size:12px; font-weight:600; cursor:pointer;">
|
||
<span style="font-size:15px; line-height:1;">+</span> Deploy company from template
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
<sc-if value="{{ isClaw }}" hint-placeholder-val="{{ false }}">
|
||
<div style="padding:14px 16px 12px;">
|
||
<div style="display:flex; align-items:center; gap:8px; font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72; cursor:pointer; margin-bottom:12px;" onClick="{{ goTeam }}">← Growth Team</div>
|
||
<div style="display:flex; align-items:center; gap:11px;">
|
||
<div style="width:42px; height:42px; flex:none; border-radius:11px; background:{{ selGrad }}; display:flex; align-items:center; justify-content:center; font-size:17px; font-weight:700; color:{{ selInk }};">{{ selInitial }}</div>
|
||
<div style="min-width:0;">
|
||
<div style="font-size:17px; font-weight:700; color:#f3f3f5; letter-spacing:-.01em;">{{ selName }}</div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#6a6a72;">{{ selRole }} · Growth Team</div>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top:11px; display:flex; align-items:center; gap:7px; padding:7px 10px; border-radius:8px; background:#101014; border:1px solid rgba(255,255,255,.07);">
|
||
<span style="width:7px; height:7px; border-radius:50%; background:#ff6f61;"></span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#9a9aa2;">Claude Sonnet 4.5</span>
|
||
<span style="flex:1;"></span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#5fd08a;">online</span>
|
||
</div>
|
||
</div>
|
||
<div style="padding:0 12px 6px;">
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.12em; color:#5a5a62; padding:6px 6px 8px;">COMPARTMENTS</div>
|
||
<div style="display:flex; flex-direction:column; gap:1px;">
|
||
<div style="display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:8px; background:rgba(255,111,97,.1); color:#f3f3f5; font-size:12px; font-weight:600;"><span style="width:6px; height:6px; border-radius:50%; background:#ff6f61;"></span>Anatomy</div>
|
||
<div style="display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:8px; color:#9a9aa2; font-size:12px; cursor:pointer;"><span style="width:6px; height:6px; border-radius:50%; background:#ff6f61;"></span>Skills <span style="flex:1;"></span><span style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#5a5a62;">7</span></div>
|
||
<div style="display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:8px; color:#9a9aa2; font-size:12px; cursor:pointer;"><span style="width:6px; height:6px; border-radius:50%; background:#5ec8d8;"></span>Tools <span style="flex:1;"></span><span style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#5a5a62;">4</span></div>
|
||
<div style="display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:8px; color:#9a9aa2; font-size:12px; cursor:pointer;"><span style="width:6px; height:6px; border-radius:50%; background:#c98af0;"></span>Personality</div>
|
||
<div style="display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:8px; color:#9a9aa2; font-size:12px; cursor:pointer;"><span style="width:6px; height:6px; border-radius:50%; background:#e8b465;"></span>Capabilities</div>
|
||
<div style="display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:8px; color:#9a9aa2; font-size:12px; cursor:pointer;"><span style="width:6px; height:6px; border-radius:50%; background:#5fd08a;"></span>Memory</div>
|
||
<div style="display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:8px; color:#9a9aa2; font-size:12px; cursor:pointer;"><span style="width:6px; height:6px; border-radius:50%; background:#6fd0c0;"></span>Safety · §15</div>
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
</div>
|
||
|
||
<!-- CANVAS -->
|
||
<div style="flex:1; position:relative; min-width:0; overflow:hidden;">
|
||
<sc-if value="{{ isTeam }}" hint-placeholder-val="{{ true }}">
|
||
<div style="position:absolute; inset:0; display:flex; flex-direction:column; background:radial-gradient(120% 90% at 55% 40%, #0e0e13 0%, #08080a 70%);">
|
||
|
||
<!-- topology morph selector (reserved band) -->
|
||
<div style="flex:none; display:flex; align-items:center; gap:10px; padding:14px 18px 10px;">
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.12em; color:#5a5a62; flex:none;">TOPOLOGY</span>
|
||
<div style="flex:1; min-width:0; display:flex; gap:6px; overflow-x:auto; white-space:nowrap; padding-bottom:2px;">
|
||
<sc-for list="{{ topos }}" as="t" hint-placeholder-count="6">
|
||
<div style="flex:none; font-family:'JetBrains Mono',monospace; font-size:11px; font-weight:600; padding:5px 11px; border-radius:7px; cursor:pointer; transition:all .2s; {{ t.style }}" onClick="{{ t.onPick }}">{{ t.label }}</div>
|
||
</sc-for>
|
||
</div>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#5ec8d8; flex:none; cursor:pointer; padding:5px 10px; border:1px solid rgba(94,200,216,.22); border-radius:7px;">⇄ compare all</span>
|
||
</div>
|
||
|
||
<!-- current topology caption -->
|
||
<div style="flex:none; padding:0 18px 4px;">
|
||
<div style="font-size:22px; font-weight:700; color:#f3f3f5; letter-spacing:-.01em;">{{ topoLabel }}</div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:11px; color:#6a6a72; margin-top:2px;">{{ topoKind }}</div>
|
||
</div>
|
||
|
||
<span style="position:absolute; bottom:14px; left:18px; right:18px; z-index:5; font-family:'JetBrains Mono',monospace; font-size:10px; color:#3a3a40;">click a claw to open its computer · pick a topology to re-wire the team</span>
|
||
|
||
<!-- graph stage -->
|
||
<div style="position:relative; flex:1; min-height:0;">
|
||
<svg viewBox="0 0 100 100" preserveAspectRatio="none" style="position:absolute; inset:0; width:100%; height:100%;">
|
||
<sc-for list="{{ linkPaths }}" as="lk" hint-placeholder-count="5">
|
||
<path d="{{ lk.d }}" fill="none" stroke="{{ lk.stroke }}" stroke-width="{{ lk.width }}" stroke-dasharray="{{ lk.dash }}" vector-effect="non-scaling-stroke" style="{{ lk.anim }} transition:stroke .3s;"></path>
|
||
</sc-for>
|
||
</svg>
|
||
|
||
<sc-for list="{{ nodes }}" as="n" hint-placeholder-count="6">
|
||
<div style="position:absolute; left:{{ n.x }}; top:{{ n.y }}; transform:translate(-50%,-50%); transition:left .55s cubic-bezier(.4,0,.2,1), top .55s cubic-bezier(.4,0,.2,1); display:flex; flex-direction:column; align-items:center; gap:7px; z-index:3; cursor:pointer;" onClick="{{ n.onSelect }}">
|
||
<div style="position:relative; width:50px; height:50px;">
|
||
<sc-if value="{{ n.running }}" hint-placeholder-val="{{ false }}"><div style="position:absolute; inset:0; border-radius:50%; background:rgba(94,200,216,.4); animation:cm-halo 1.8s ease-out infinite;"></div></sc-if>
|
||
<sc-if value="{{ n.selected }}" hint-placeholder-val="{{ false }}"><div style="position:absolute; inset:-6px; border-radius:50%; border:2px solid #ff6f61; box-shadow:0 0 0 4px rgba(255,111,97,.12);"></div></sc-if>
|
||
<div style="position:relative; width:50px; height:50px; border-radius:50%; background:{{ n.grad }}; display:flex; align-items:center; justify-content:center; font-size:18px; font-weight:700; color:{{ n.ink }}; box-shadow:0 0 28px rgba(0,0,0,.45);">{{ n.initial }}</div>
|
||
<span style="position:absolute; right:-1px; bottom:-1px; width:12px; height:12px; border-radius:50%; background:{{ n.statusColor }}; border:2px solid #0a0a0c;"></span>
|
||
</div>
|
||
<div style="text-align:center;">
|
||
<div style="font-size:12px; font-weight:600; color:{{ n.labelColor }};">{{ n.name }}</div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#6a6a72;">{{ n.role }}</div>
|
||
</div>
|
||
</div>
|
||
</sc-for>
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
<sc-if value="{{ isCompany }}" hint-placeholder-val="{{ false }}">
|
||
<div style="position:absolute; inset:0; background:#08080a; background-image:linear-gradient(rgba(255,255,255,.022) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.022) 1px, transparent 1px); background-size:28px 28px;">
|
||
|
||
<div style="position:absolute; top:16px; left:18px; z-index:5; display:flex; align-items:center; gap:10px;">
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.1em; color:#e8b465; padding:4px 9px; border-radius:6px; border:1px solid rgba(232,196,106,.25); background:rgba(232,196,106,.07);">PIPELINE</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; color:#5a5a62;">company topology · click a team to enter its claws</span>
|
||
</div>
|
||
<div style="position:absolute; top:14px; right:18px; z-index:5; font-family:'JetBrains Mono',monospace; font-size:10px; color:#5a5a62;">x:248 y:112 · z:1.0×</div>
|
||
|
||
<svg viewBox="0 0 100 100" preserveAspectRatio="none" style="position:absolute; inset:0; width:100%; height:100%;">
|
||
<path d="M16,34 H31 V22 H46" fill="none" stroke="rgba(94,200,216,.5)" stroke-width="1.6" stroke-dasharray="3 4" vector-effect="non-scaling-stroke" style="animation:cm-flow 1.1s linear infinite;"></path>
|
||
<path d="M16,34 H30 V66 H44" fill="none" stroke="rgba(232,196,106,.45)" stroke-width="1.6" stroke-dasharray="3 4" vector-effect="non-scaling-stroke" style="animation:cm-flow 1.4s linear infinite;"></path>
|
||
<path d="M46,22 H63 V46 H80" fill="none" stroke="rgba(255,111,97,.55)" stroke-width="1.8" stroke-dasharray="3 4" vector-effect="non-scaling-stroke" style="animation:cm-flow .9s linear infinite;"></path>
|
||
<path d="M44,66 H62 V46 H80" fill="none" stroke="rgba(255,255,255,.12)" stroke-width="1.5" vector-effect="non-scaling-stroke"></path>
|
||
</svg>
|
||
|
||
<div style="position:absolute; left:16%; top:34%; transform:translate(-50%,-50%); width:158px; z-index:3; cursor:pointer;" onClick="{{ enterTeam }}">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(255,255,255,.09); padding:11px 12px; box-shadow:0 8px 24px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:8px;"><span style="width:7px; height:7px; border-radius:2px; background:#5ec8d8;"></span><span style="font-size:13px; font-weight:700; color:#eaeaee;">Intake Team</span></div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#6a6a72; margin-bottom:9px;">star-MoE · 3 claws</div>
|
||
<div style="display:flex; gap:4px;"><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#6fd0c0,#4aa3b8);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#8a9af0,#5a6ad8);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#e8c46a,#d89a3a);"></span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="position:absolute; left:46%; top:22%; transform:translate(-50%,-50%); width:170px; z-index:4; cursor:pointer;" onClick="{{ enterTeam }}">
|
||
<div style="border-radius:12px; background:#141014; border:1.5px solid #ff6f61; padding:11px 12px; box-shadow:0 0 0 4px rgba(255,111,97,.1), 0 10px 28px rgba(0,0,0,.5);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:8px;"><span style="width:7px; height:7px; border-radius:50%; background:#ff6f61; animation:cm-blink 1.5s infinite;"></span><span style="font-size:13px; font-weight:700; color:#fff;">Growth Team</span><span style="flex:1;"></span><span style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#ff8a7a;">▾ enter</span></div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#ff8a7a; margin-bottom:9px;">hub-spoke · 6 claws · running</div>
|
||
<div style="display:flex; gap:4px;"><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#ff9a6a,#ff6f4a);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#6fd0c0,#4aa3b8);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#8a9af0,#5a6ad8);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#e8c46a,#d89a3a);"></span><span style="width:15px; height:15px; border-radius:5px; background:#1a1a1e; display:flex; align-items:center; justify-content:center; font-family:'JetBrains Mono',monospace; font-size:8px; color:#8a8a92;">+2</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="position:absolute; left:44%; top:66%; transform:translate(-50%,-50%); width:158px; z-index:3; cursor:pointer;" onClick="{{ enterTeam }}">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(255,255,255,.09); padding:11px 12px; box-shadow:0 8px 24px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:8px;"><span style="width:7px; height:7px; border-radius:50%; background:#5ec8d8; animation:cm-blink 1.7s infinite;"></span><span style="font-size:13px; font-weight:700; color:#eaeaee;">Research Team</span></div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#6a6a72; margin-bottom:9px;">blackboard · 4 claws</div>
|
||
<div style="display:flex; gap:4px;"><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#8a9af0,#5a6ad8);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#6fd0c0,#4aa3b8);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#c98af0,#9a5ad8);"></span><span style="width:15px; height:15px; border-radius:5px; background:#1a1a1e; display:flex; align-items:center; justify-content:center; font-family:'JetBrains Mono',monospace; font-size:8px; color:#8a8a92;">+1</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="position:absolute; left:80%; top:46%; transform:translate(-50%,-50%); width:152px; z-index:3; cursor:pointer;" onClick="{{ enterTeam }}">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(255,255,255,.09); padding:11px 12px; box-shadow:0 8px 24px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:8px;"><span style="width:7px; height:7px; border-radius:50%; background:#3a3a40;"></span><span style="font-size:13px; font-weight:700; color:#eaeaee;">Ops Team</span></div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#6a6a72; margin-bottom:9px;">holacratic · 5 claws</div>
|
||
<div style="display:flex; gap:4px;"><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#e8c46a,#d89a3a);"></span><span style="width:15px; height:15px; border-radius:5px; background:linear-gradient(135deg,#ff9a6a,#ff6f4a);"></span><span style="width:15px; height:15px; border-radius:5px; background:#1a1a1e; display:flex; align-items:center; justify-content:center; font-family:'JetBrains Mono',monospace; font-size:8px; color:#8a8a92;">+3</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<span style="position:absolute; bottom:16px; left:18px; z-index:5; font-family:'JetBrains Mono',monospace; font-size:10px; color:#3a3a40;">↑ zoom out to Org · ↓ click a team to enter</span>
|
||
</div>
|
||
</sc-if>
|
||
<sc-if value="{{ isOrg }}" hint-placeholder-val="{{ false }}">
|
||
<div style="position:absolute; inset:0; background:radial-gradient(120% 90% at 50% 40%, #0e0e13 0%, #08080a 70%);">
|
||
<div style="position:absolute; top:16px; left:18px; z-index:5; display:flex; align-items:center; gap:10px;">
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.1em; color:#c98af0; padding:4px 9px; border-radius:6px; border:1px solid rgba(201,138,240,.25); background:rgba(201,138,240,.07);">PORTFOLIO</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; color:#5a5a62;">org topology · click a company to descend</span>
|
||
</div>
|
||
|
||
<svg viewBox="0 0 100 100" preserveAspectRatio="none" style="position:absolute; inset:0; width:100%; height:100%;">
|
||
<path d="M50,46 L26,28" fill="none" stroke="rgba(255,111,97,.5)" stroke-width="1.8" stroke-dasharray="3 4" vector-effect="non-scaling-stroke" style="animation:cm-flow 1s linear infinite;"></path>
|
||
<path d="M50,46 L76,30" fill="none" stroke="rgba(255,255,255,.12)" stroke-width="1.5" vector-effect="non-scaling-stroke"></path>
|
||
<path d="M50,46 L62,74" fill="none" stroke="rgba(255,255,255,.12)" stroke-width="1.5" vector-effect="non-scaling-stroke"></path>
|
||
</svg>
|
||
|
||
<div style="position:absolute; left:50%; top:46%; transform:translate(-50%,-50%); display:flex; flex-direction:column; align-items:center; gap:9px; z-index:3;">
|
||
<div style="width:60px; height:60px; border-radius:16px; background:#141417; border:1px solid rgba(255,255,255,.1); display:flex; align-items:center; justify-content:center; color:#9a9aa2; box-shadow:0 0 30px rgba(0,0,0,.5);"><svg width="26" height="26" viewBox="0 0 20 20"><circle cx="10" cy="10" r="7.5" stroke="currentColor" stroke-width="1.4" fill="none"></circle><circle cx="10" cy="10" r="2.6" fill="currentColor"></circle></svg></div>
|
||
<div style="text-align:center;"><div style="font-size:13px; font-weight:700; color:#fff;">Acme Org</div><div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#6a6a72;">3 companies</div></div>
|
||
</div>
|
||
|
||
<div style="position:absolute; left:26%; top:28%; transform:translate(-50%,-50%); display:flex; flex-direction:column; align-items:center; gap:8px; z-index:3; cursor:pointer;" onClick="{{ goCompany }}">
|
||
<div style="width:54px; height:54px; border-radius:14px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); display:flex; align-items:center; justify-content:center; color:#2a0d0a; box-shadow:0 0 26px rgba(255,111,97,.4);"><svg width="22" height="22" viewBox="0 0 20 20"><rect x="3.5" y="5" width="6" height="11" rx="1" stroke="currentColor" stroke-width="1.6" fill="none"></rect><rect x="10.5" y="2.5" width="6" height="13.5" rx="1" stroke="currentColor" stroke-width="1.6" fill="none"></rect></svg></div>
|
||
<div style="text-align:center;"><div style="font-size:12px; font-weight:700; color:#fff;">Acme Corp</div><div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#ff8a7a;">4 teams · enter ▸</div></div>
|
||
</div>
|
||
|
||
<div style="position:absolute; left:76%; top:30%; transform:translate(-50%,-50%); display:flex; flex-direction:column; align-items:center; gap:8px; z-index:3; cursor:pointer;" onClick="{{ goCompany }}">
|
||
<div style="width:48px; height:48px; border-radius:13px; background:#141417; border:1px solid rgba(255,255,255,.1); display:flex; align-items:center; justify-content:center; color:#8a8a92;"><svg width="20" height="20" viewBox="0 0 20 20"><rect x="3.5" y="5" width="6" height="11" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect><rect x="10.5" y="2.5" width="6" height="13.5" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect></svg></div>
|
||
<div style="text-align:center;"><div style="font-size:12px; font-weight:600; color:#dcdce2;">Helix Labs</div><div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#6a6a72;">2 teams</div></div>
|
||
</div>
|
||
|
||
<div style="position:absolute; left:62%; top:74%; transform:translate(-50%,-50%); display:flex; flex-direction:column; align-items:center; gap:8px; z-index:3; cursor:pointer;" onClick="{{ goCompany }}">
|
||
<div style="width:48px; height:48px; border-radius:13px; background:#141417; border:1px solid rgba(255,255,255,.1); display:flex; align-items:center; justify-content:center; color:#8a8a92;"><svg width="20" height="20" viewBox="0 0 20 20"><rect x="3.5" y="5" width="6" height="11" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect><rect x="10.5" y="2.5" width="6" height="13.5" rx="1" stroke="currentColor" stroke-width="1.4" fill="none"></rect></svg></div>
|
||
<div style="text-align:center;"><div style="font-size:12px; font-weight:600; color:#dcdce2;">Vega Studio</div><div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#6a6a72;">1 team</div></div>
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
<sc-if value="{{ isClaw }}" hint-placeholder-val="{{ false }}">
|
||
<div style="position:absolute; inset:0; display:flex; flex-direction:column; background:radial-gradient(120% 90% at 50% 42%, #100e13 0%, #08080a 70%);">
|
||
|
||
<div style="flex:none; display:flex; align-items:center; gap:10px; padding:14px 18px 6px;">
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.1em; color:#ff8a7a; padding:4px 9px; border-radius:6px; border:1px solid rgba(255,111,97,.25); background:rgba(255,111,97,.07);">ANATOMY</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; color:#6a6a72;">what {{ selName }} is made of · compartments wired to the core</span>
|
||
</div>
|
||
|
||
<div style="position:relative; flex:1; min-height:0; overflow:auto; padding:22px 20px 28px;">
|
||
<div style="max-width:820px; margin:0 auto; display:flex; flex-direction:column; align-items:center; gap:20px;">
|
||
|
||
<!-- core -->
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:9px;">
|
||
<div style="position:relative; width:78px; height:78px;">
|
||
<div style="position:absolute; inset:-7px; border-radius:50%; border:1.5px solid rgba(255,111,97,.35);"></div>
|
||
<div style="position:absolute; inset:0; border-radius:50%; background:rgba(255,111,97,.32); animation:cm-halo 2s ease-out infinite;"></div>
|
||
<div style="position:relative; width:78px; height:78px; border-radius:50%; background:{{ selGrad }}; display:flex; align-items:center; justify-content:center; font-size:28px; font-weight:700; color:{{ selInk }}; box-shadow:0 0 44px rgba(255,111,97,.45);">{{ selInitial }}</div>
|
||
</div>
|
||
<div style="text-align:center;">
|
||
<div style="font-size:14px; font-weight:700; color:#fff;">{{ selName }}</div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#8a8a92; letter-spacing:.04em;">CLAUDE SONNET · CORE</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="width:100%; display:grid; grid-template-columns:repeat(auto-fit, minmax(196px, 1fr)); gap:14px; align-items:start;">
|
||
<!-- SKILLS -->
|
||
<div style="width:100%;">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(255,111,97,.22); padding:11px; box-shadow:0 8px 22px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:9px;"><span style="width:18px; height:18px; border-radius:5px; background:rgba(255,111,97,.16); display:flex; align-items:center; justify-content:center;"><svg width="11" height="11" viewBox="0 0 18 18"><path d="M10 1 L3 10 H8 L7 17 L15 7 H9 Z" fill="#ff6f61"></path></svg></span><span style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.08em; color:#ff8a7a;">SKILLS</span><span style="flex:1;"></span><span style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#5a5a62;">7</span></div>
|
||
<div style="display:flex; flex-wrap:wrap; gap:4px;">
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Web research</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Summarize</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Data viz</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#8a8a92; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.03);">+4</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PERSONALITY -->
|
||
<div style="width:100%;">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(201,138,240,.22); padding:11px; box-shadow:0 8px 22px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:9px;"><span style="width:18px; height:18px; border-radius:5px; background:rgba(201,138,240,.16); display:flex; align-items:center; justify-content:center;"><svg width="11" height="11" viewBox="0 0 18 18"><circle cx="9" cy="6" r="3.4" fill="#c98af0"></circle><path d="M3 16c0-3.3 2.7-6 6-6s6 2.7 6 6" fill="#c98af0"></path></svg></span><span style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.08em; color:#c98af0;">PERSONALITY</span></div>
|
||
<div style="display:flex; flex-wrap:wrap; gap:4px;">
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Analytical</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Concise</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Skeptical</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MEMORY -->
|
||
<div style="width:100%;">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(95,208,138,.22); padding:11px; box-shadow:0 8px 22px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:9px;"><span style="width:18px; height:18px; border-radius:5px; background:rgba(95,208,138,.16); display:flex; align-items:center; justify-content:center;"><svg width="11" height="11" viewBox="0 0 18 18"><rect x="3" y="3" width="12" height="12" rx="2" fill="none" stroke="#5fd08a" stroke-width="1.6"></rect><path d="M6 7h6M6 11h4" stroke="#5fd08a" stroke-width="1.4"></path></svg></span><span style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.08em; color:#5fd08a;">MEMORY</span></div>
|
||
<div style="display:flex; flex-direction:column; gap:5px; font-family:'JetBrains Mono',monospace; font-size:10px; color:#9a9aa2;">
|
||
<div style="display:flex;"><span style="flex:1;">Long-term</span><span style="color:#cfcfd5;">2,418 notes</span></div>
|
||
<div style="display:flex;"><span style="flex:1;">Recent ctx</span><span style="color:#cfcfd5;">18 msgs</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TOOLS -->
|
||
<div style="width:100%;">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(94,200,216,.22); padding:11px; box-shadow:0 8px 22px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:9px;"><span style="width:18px; height:18px; border-radius:5px; background:rgba(94,200,216,.16); display:flex; align-items:center; justify-content:center;"><svg width="11" height="11" viewBox="0 0 18 18"><path d="M4 3v12M4 4h8l-2 3 2 3H4" fill="none" stroke="#5ec8d8" stroke-width="1.5" stroke-linejoin="round"></path></svg></span><span style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.08em; color:#5ec8d8;">TOOLS · DOORS</span></div>
|
||
<div style="display:flex; flex-direction:column; gap:4px; font-family:'JetBrains Mono',monospace; font-size:10px;">
|
||
<div style="display:flex; align-items:center;"><span style="flex:1; color:#cfcfd5;">Email</span><span style="color:#5fd08a;">gated ✓</span></div>
|
||
<div style="display:flex; align-items:center;"><span style="flex:1; color:#cfcfd5;">Slack</span><span style="color:#5fd08a;">gated ✓</span></div>
|
||
<div style="display:flex; align-items:center;"><span style="flex:1; color:#cfcfd5;">Browser</span><span style="color:#5fd08a;">gated ✓</span></div>
|
||
<div style="display:flex; align-items:center;"><span style="flex:1; color:#7a7a82;">Shell</span><span style="color:#e8b465;">blocked ⨯</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- CAPABILITIES -->
|
||
<div style="width:100%;">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(232,196,106,.22); padding:11px; box-shadow:0 8px 22px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:9px;"><span style="width:18px; height:18px; border-radius:5px; background:rgba(232,196,106,.16); display:flex; align-items:center; justify-content:center;"><svg width="11" height="11" viewBox="0 0 18 18"><circle cx="9" cy="9" r="6" fill="none" stroke="#e8b465" stroke-width="1.6"></circle><path d="M9 5v4l3 2" stroke="#e8b465" stroke-width="1.4" fill="none"></path></svg></span><span style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.08em; color:#e8b465;">CAPABILITIES</span></div>
|
||
<div style="display:flex; flex-wrap:wrap; gap:4px;">
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">File mgmt</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Scheduling</span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#cfcfd5; padding:3px 7px; border-radius:5px; background:rgba(255,255,255,.05);">Code exec</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- SAFETY -->
|
||
<div style="width:100%;">
|
||
<div style="border-radius:12px; background:#0f0f13; border:1px solid rgba(111,208,192,.22); padding:11px; box-shadow:0 8px 22px rgba(0,0,0,.4);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:9px;"><span style="width:18px; height:18px; border-radius:5px; background:rgba(111,208,192,.16); display:flex; align-items:center; justify-content:center;"><svg width="11" height="11" viewBox="0 0 18 18"><path d="M9 2l5 2v4c0 4-2.5 6.5-5 8-2.5-1.5-5-4-5-8V4z" fill="none" stroke="#6fd0c0" stroke-width="1.5" stroke-linejoin="round"></path></svg></span><span style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.08em; color:#6fd0c0;">SAFETY · §15</span></div>
|
||
<div style="display:flex; flex-direction:column; gap:5px; font-family:'JetBrains Mono',monospace; font-size:10px; color:#9a9aa2;">
|
||
<div style="display:flex;"><span style="flex:1;">Sandbox</span><span style="color:#6fd0c0;">isolated</span></div>
|
||
<div style="display:flex;"><span style="flex:1;">Network</span><span style="color:#6fd0c0;">none</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<span style="text-align:center; font-family:'JetBrains Mono',monospace; font-size:10px; color:#3a3a40;">click a compartment to inspect · the computer panel runs this claw's apps & routines</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
</div>
|
||
|
||
<!-- COMPUTER PANEL -->
|
||
<sc-if value="{{ showComputer }}" hint-placeholder-val="{{ true }}">
|
||
<div style="width:330px; flex:none; border-left:1px solid rgba(255,255,255,.06); background:#0b0b0e; display:flex; flex-direction:column; min-height:0; animation:cm-fade .25s ease;">
|
||
<div style="padding:16px 16px 12px; border-bottom:1px solid rgba(255,255,255,.06);">
|
||
<div style="display:flex; align-items:center; gap:10px;">
|
||
<div style="position:relative; width:38px; height:38px;">
|
||
<div style="width:38px; height:38px; border-radius:10px; background:{{ selGrad }}; display:flex; align-items:center; justify-content:center; font-size:16px; font-weight:700; color:{{ selInk }};">{{ selInitial }}</div>
|
||
<span style="position:absolute; right:-2px; bottom:-2px; width:11px; height:11px; border-radius:50%; background:#5fd08a; border:2px solid #0b0b0e;"></span>
|
||
</div>
|
||
<div style="flex:1;">
|
||
<div style="font-size:14px; font-weight:700; color:#f3f3f5;">{{ selName }}'s Computer</div>
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; color:#5ec8d8;">● sandbox live · no network</div>
|
||
</div>
|
||
<div style="width:26px; height:26px; border-radius:7px; border:1px solid rgba(255,255,255,.1); display:flex; align-items:center; justify-content:center; color:#6a6a72; font-size:13px; cursor:pointer;">⤢</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="flex:1; overflow-y:auto; padding:16px;">
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.12em; color:#5a5a62; margin-bottom:12px;">APPS</div>
|
||
<div style="display:grid; grid-template-columns:repeat(4,1fr); gap:10px 6px; margin-bottom:22px;">
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;">
|
||
<div style="width:48px; height:48px; border-radius:13px; background:#fff; display:flex; align-items:center; justify-content:center; box-shadow:0 3px 10px rgba(0,0,0,.4);"><svg width="26" height="26" viewBox="0 0 26 26"><circle cx="13" cy="13" r="11" fill="#fff" stroke="#e0e0e0"></circle><circle cx="13" cy="13" r="4.4" fill="#4a90e2"></circle><path d="M13 8.6 H24" stroke="#ea4335" stroke-width="3.6"></path><path d="M9.2 11 L4 3.4" stroke="#34a853" stroke-width="3.6"></path><path d="M13 17.4 L7.5 22.5" stroke="#fbbc05" stroke-width="3.6"></path></svg></div>
|
||
<span style="font-size:10px; color:#b5b5bd;">Browser</span>
|
||
</div>
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;">
|
||
<div style="width:48px; height:48px; border-radius:13px; background:#fff; display:flex; align-items:center; justify-content:center; box-shadow:0 3px 10px rgba(0,0,0,.4);"><svg width="22" height="22" viewBox="0 0 22 22"><rect x="9" y="2" width="4" height="11" rx="2" fill="#36c5f0"></rect><rect x="9" y="13" width="4" height="7" rx="2" fill="#2eb67d"></rect><rect x="2" y="9" width="11" height="4" rx="2" fill="#ecb22e"></rect><rect x="9" y="9" width="11" height="4" rx="2" fill="#e01e5a"></rect></svg></div>
|
||
<span style="font-size:10px; color:#b5b5bd;">Slack</span>
|
||
</div>
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;">
|
||
<div style="width:48px; height:48px; border-radius:13px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); display:flex; align-items:center; justify-content:center; box-shadow:0 3px 10px rgba(0,0,0,.4);"><svg width="22" height="22" viewBox="0 0 22 22"><path d="M3 5a2 2 0 012-2h12a2 2 0 012 2v8a2 2 0 01-2 2H8l-4 4v-4H5a2 2 0 01-2-2z" fill="#fff"></path></svg></div>
|
||
<span style="font-size:10px; color:#b5b5bd;">Claw Chat</span>
|
||
</div>
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;">
|
||
<div style="width:48px; height:48px; border-radius:13px; border:1.5px dashed rgba(255,255,255,.18); display:flex; align-items:center; justify-content:center; color:#ff6f61; font-size:22px; font-weight:300; cursor:pointer;">+</div>
|
||
<span style="font-size:10px; color:#8a8a92;">Add Apps</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.12em; color:#5a5a62; margin-bottom:10px;">NOW RUNNING</div>
|
||
<div style="display:flex; flex-direction:column; gap:8px;">
|
||
<div style="padding:10px 11px; border-radius:10px; background:#101014; border:1px solid rgba(255,255,255,.06);">
|
||
<div style="display:flex; align-items:center; gap:7px; margin-bottom:6px;">
|
||
<span style="width:6px; height:6px; border-radius:50%; background:#5ec8d8; animation:cm-blink 1.4s infinite;"></span>
|
||
<span style="font-size:12px; font-weight:600; color:#e6e6ea;">Q3 competitor scan</span>
|
||
<span style="flex:1;"></span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#5ec8d8;">loop · step 14</span>
|
||
</div>
|
||
<div style="height:4px; border-radius:2px; background:rgba(255,255,255,.08); overflow:hidden;"><div style="width:62%; height:100%; background:linear-gradient(90deg,#5ec8d8,#4aa3b8);"></div></div>
|
||
</div>
|
||
<div style="padding:10px 11px; border-radius:10px; background:#101014; border:1px solid rgba(255,255,255,.06); display:flex; align-items:center; gap:7px;">
|
||
<span style="width:6px; height:6px; border-radius:50%; background:#e8b465;"></span>
|
||
<span style="font-size:12px; font-weight:600; color:#e6e6ea;">Daily digest</span>
|
||
<span style="flex:1;"></span>
|
||
<span style="font-family:'JetBrains Mono',monospace; font-size:9px; color:#e8b465;">cron · 08:00</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="flex:none; margin:0 12px 14px; padding:12px; border-radius:14px; background:#121216; border:1px solid rgba(255,255,255,.07); display:flex; justify-content:space-around;">
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;"><div style="width:40px; height:40px; border-radius:11px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); display:flex; align-items:center; justify-content:center;"><svg width="18" height="18" viewBox="0 0 18 18"><path d="M10 1 L3 10 H8 L7 17 L15 7 H9 Z" fill="#fff"></path></svg></div><span style="font-size:10px; color:#b5b5bd;">Skills</span></div>
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;"><div style="width:40px; height:40px; border-radius:11px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); display:flex; align-items:center; justify-content:center;"><svg width="18" height="18" viewBox="0 0 18 18"><path d="M2 5a1.5 1.5 0 011.5-1.5H7l1.5 1.5h6A1.5 1.5 0 0116 6.5v7A1.5 1.5 0 0114.5 15h-11A1.5 1.5 0 012 13.5z" fill="#fff"></path></svg></div><span style="font-size:10px; color:#b5b5bd;">Files</span></div>
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;"><div style="width:40px; height:40px; border-radius:11px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); display:flex; align-items:center; justify-content:center;"><svg width="18" height="18" viewBox="0 0 18 18"><path d="M9 2a5 5 0 00-5 5c0 4-1.5 5-1.5 5h13S14 11 14 7a5 5 0 00-5-5z" fill="#fff"></path><path d="M7.5 15a1.5 1.5 0 003 0" fill="#fff"></path></svg></div><span style="font-size:10px; color:#ff8a7a;">Routines</span></div>
|
||
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;"><div style="width:40px; height:40px; border-radius:11px; background:linear-gradient(135deg,#ff8a7a,#ff5f57); display:flex; align-items:center; justify-content:center;"><svg width="18" height="18" viewBox="0 0 18 18"><circle cx="9" cy="9" r="2.6" fill="#fff"></circle><path d="M9 1.5v2M9 14.5v2M1.5 9h2M14.5 9h2M3.7 3.7l1.4 1.4M12.9 12.9l1.4 1.4M14.3 3.7l-1.4 1.4M5.1 12.9l-1.4 1.4" stroke="#fff" stroke-width="1.5"></path></svg></div><span style="font-size:10px; color:#b5b5bd;">Settings</span></div>
|
||
</div>
|
||
</div>
|
||
</sc-if>
|
||
|
||
</div>
|
||
|
||
<!-- STATUS BAR -->
|
||
<div style="height:28px; flex:none; display:flex; align-items:center; gap:18px; padding:0 16px; border-top:1px solid rgba(255,255,255,.06); background:#0a0a0c; font-family:'JetBrains Mono',monospace; font-size:10px; color:#5a5a62;">
|
||
<span style="color:#5fd08a;">● durable runner ok</span>
|
||
<span>checkpoint 3s ago</span>
|
||
<span style="flex:1;"></span>
|
||
<span>§15 sandbox: isolated</span>
|
||
<span style="color:#5ec8d8;">2 doors awaiting approval</span>
|
||
</div>
|
||
</div>
|
||
</x-dc>
|
||
<script type="text/x-dc" data-dc-script>
|
||
class Component extends DCLogic {
|
||
state = { tier: 'team', topology: 'hub-spoke', selected: 'morpheus' };
|
||
|
||
renderVals() {
|
||
const s = this.state;
|
||
|
||
const claws = [
|
||
{ id:'atlas', name:'Atlas', role:'team lead', initial:'A', grad:'linear-gradient(135deg,#ff9a6a,#ff6f4a)', ink:'#2a0d05', status:'online' },
|
||
{ id:'iris', name:'Iris', role:'researcher', initial:'I', grad:'linear-gradient(135deg,#6fd0c0,#4aa3b8)', ink:'#06201f', status:'running' },
|
||
{ id:'echo', name:'Echo', role:'researcher', initial:'E', grad:'linear-gradient(135deg,#8a9af0,#5a6ad8)', ink:'#0a0e2a', status:'running' },
|
||
{ id:'nova', name:'Nova', role:'writer', initial:'N', grad:'linear-gradient(135deg,#e8c46a,#d89a3a)', ink:'#2a1d05', status:'online' },
|
||
{ id:'sable', name:'Sable', role:'critic', initial:'S', grad:'linear-gradient(135deg,#c98af0,#9a5ad8)', ink:'#1a0a2a', status:'idle' },
|
||
{ id:'morpheus',name:'Morpheus',role:'analyst', initial:'M', grad:'linear-gradient(135deg,#ff8a7a,#ff5f57)', ink:'#2a0d0a', status:'online' },
|
||
];
|
||
|
||
const POS = {
|
||
'hub-spoke': [[50,48],[22,26],[24,72],[50,15],[78,28],[78,70]],
|
||
'pipeline': [[11,50],[27,50],[42,50],[58,50],[73,50],[89,50]],
|
||
'ring': [[50,15],[80,32],[80,68],[50,85],[20,68],[20,32]],
|
||
'mesh': [[31,26],[69,24],[85,52],[67,80],[31,80],[15,52]],
|
||
'swarm': [[40,38],[60,32],[66,55],[48,66],[33,55],[53,47]],
|
||
'debate': [[26,22],[26,50],[26,78],[74,22],[74,50],[74,78]],
|
||
};
|
||
const LNK = {
|
||
'hub-spoke': [[0,1],[0,2],[0,3],[0,4],[0,5]],
|
||
'pipeline': [[0,1],[1,2],[2,3],[3,4],[4,5]],
|
||
'ring': [[0,1],[1,2],[2,3],[3,4],[4,5],[5,0]],
|
||
'mesh': [[0,1],[1,2],[2,3],[3,4],[4,5],[5,0],[0,3],[1,4],[2,5]],
|
||
'swarm': [[0,1],[0,2],[0,3],[0,4],[0,5],[1,3],[2,4]],
|
||
'debate': [[0,3],[1,4],[2,5],[0,4],[1,3],[1,5],[2,4]],
|
||
};
|
||
const pos = POS[s.topology] || POS['hub-spoke'];
|
||
const lnks = LNK[s.topology] || [];
|
||
const sc = st => st==='running' ? '#5ec8d8' : st==='online' ? '#5fd08a' : '#3a3a40';
|
||
const selIdx = claws.findIndex(c => c.id === s.selected);
|
||
|
||
const nodes = claws.map((c, i) => ({
|
||
name:c.name, role:c.role, initial:c.initial, grad:c.grad, ink:c.ink,
|
||
x: pos[i][0] + '%', y: pos[i][1] + '%',
|
||
selected: c.id === s.selected,
|
||
running: c.status === 'running',
|
||
statusColor: sc(c.status),
|
||
labelColor: c.id === s.selected ? '#ffffff' : '#dcdce2',
|
||
rowBg: c.id === s.selected ? 'rgba(255,111,97,.12)' : 'transparent',
|
||
onSelect: () => this.setState({ selected: c.id, tier: 'claw' }),
|
||
}));
|
||
|
||
const linkPaths = lnks.map(([a,b]) => {
|
||
const ax=pos[a][0], ay=pos[a][1], bx=pos[b][0], by=pos[b][1];
|
||
let stroke='rgba(255,255,255,.12)', width=1.5, dash='0', anim='';
|
||
if (a===selIdx || b===selIdx) { stroke='rgba(255,111,97,.6)'; width=1.8; dash='3 4'; anim='animation:cm-flow .9s linear infinite;'; }
|
||
else if (a===1||a===2||b===1||b===2) { stroke='rgba(94,200,216,.5)'; width=1.6; dash='3 4'; anim='animation:cm-flow 1.2s linear infinite;'; }
|
||
return { d:`M ${ax},${ay} L ${bx},${by}`, stroke, width, dash, anim };
|
||
});
|
||
|
||
const topoMeta = {
|
||
'hub-spoke':{label:'Hub-Spoke',kind:'one coordinator routes every claw'},
|
||
'pipeline': {label:'Pipeline', kind:'output of each claw feeds the next'},
|
||
'ring': {label:'Ring', kind:'cyclic hand-off around the loop'},
|
||
'mesh': {label:'Mesh', kind:'every claw talks to every claw'},
|
||
'swarm': {label:'Swarm', kind:'parallel claws, loose coordination'},
|
||
'debate': {label:'Debate', kind:'adversarial cross-examination'},
|
||
};
|
||
const topos = ['hub-spoke','pipeline','ring','mesh','swarm','debate'].map(id => {
|
||
const active = id === s.topology;
|
||
return {
|
||
id, label: topoMeta[id].label, active,
|
||
style: active
|
||
? 'background:rgba(255,111,97,.14); border:1px solid rgba(255,111,97,.45); color:#ff8a7a;'
|
||
: 'background:#101014; border:1px solid rgba(255,255,255,.08); color:#9a9aa2;',
|
||
onPick: () => this.setState({ topology: id }),
|
||
};
|
||
});
|
||
|
||
const sel = claws.find(c => c.id === s.selected) || null;
|
||
const crumb = on => on
|
||
? 'color:#fff; background:rgba(255,111,97,.14); border:1px solid rgba(255,111,97,.3); padding:3px 8px; border-radius:6px;'
|
||
: 'color:#6a6a72; padding:3px 5px;';
|
||
const railC = on => on ? '#ff6f61' : '#5a5a62';
|
||
const railB = on => on ? 'rgba(255,111,97,.1)' : 'transparent';
|
||
const isClaw = s.tier==='claw';
|
||
|
||
return {
|
||
isOrg:s.tier==='org', isCompany:s.tier==='company', isTeam:s.tier==='team', isClaw,
|
||
showComputer: isClaw,
|
||
nodes, linkPaths, topos,
|
||
topoLabel: topoMeta[s.topology].label, topoKind: topoMeta[s.topology].kind,
|
||
selName: sel?sel.name:'', selGrad: sel?sel.grad:'', selInk: sel?sel.ink:'',
|
||
selInitial: sel?sel.initial:'', selRole: sel?sel.role:'',
|
||
crumbOrg:crumb(s.tier==='org'), crumbCo:crumb(s.tier==='company'), crumbTeam:crumb(s.tier==='team'), crumbClaw:crumb(isClaw),
|
||
railOrgColor:railC(s.tier==='org'), railOrgBg:railB(s.tier==='org'), railOrgOn:s.tier==='org',
|
||
railCoColor:railC(s.tier==='company'), railCoBg:railB(s.tier==='company'), railCoOn:s.tier==='company',
|
||
railTeamColor:railC(s.tier==='team'), railTeamBg:railB(s.tier==='team'), railTeamOn:s.tier==='team',
|
||
railClawColor:railC(isClaw), railClawBg:railB(isClaw), railClawOn:isClaw,
|
||
goClawView:()=>this.setState({tier:'claw'}),
|
||
goOrg:()=>this.setState({tier:'org'}),
|
||
goCompany:()=>this.setState({tier:'company'}),
|
||
goTeam:()=>this.setState({tier:'team'}),
|
||
enterTeam:()=>this.setState({tier:'team'}),
|
||
selectClawTeam:(id)=>this.setState({selected:id, tier:'team'}),
|
||
};
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|