nothumanallowed 13.5.17 → 13.5.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "13.5.17",
3
+ "version": "13.5.19",
4
4
  "description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '13.5.17';
8
+ export const VERSION = '13.5.19';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -3839,6 +3839,58 @@ function agentPalette(lbl) {
3839
3839
  return {skin: skins[i], shirt: shirts[i], hair: hairs[i]};
3840
3840
  }
3841
3841
 
3842
+ var TOOL_EMOJI_MAP = {
3843
+ websearch: String.fromCodePoint(0x1F50D),
3844
+ search: String.fromCodePoint(0x1F50D),
3845
+ browser: String.fromCodePoint(0x1F310),
3846
+ email: String.fromCodePoint(0x1F4E7),
3847
+ gmail: String.fromCodePoint(0x1F4E7),
3848
+ calendar: String.fromCodePoint(0x1F4C5),
3849
+ github: String.fromCodePoint(0x1F431),
3850
+ notion: String.fromCodePoint(0x1F4D3),
3851
+ slack: String.fromCodePoint(0x1F4AC),
3852
+ data: String.fromCodePoint(0x1F4CA),
3853
+ analyst: String.fromCodePoint(0x1F4CA),
3854
+ writer: String.fromCodePoint(0x270F,0xFE0F),
3855
+ summary: String.fromCodePoint(0x1F4CB),
3856
+ research: String.fromCodePoint(0x1F52C),
3857
+ canvas: String.fromCodePoint(0x1F3A8),
3858
+ security: String.fromCodePoint(0x1F6E1,0xFE0F),
3859
+ devops: String.fromCodePoint(0x2699,0xFE0F),
3860
+ code: String.fromCodePoint(0x1F4BB),
3861
+ file: String.fromCodePoint(0x1F4C2),
3862
+ drive: String.fromCodePoint(0x1F4BE),
3863
+ maps: String.fromCodePoint(0x1F5FA,0xFE0F),
3864
+ voice: String.fromCodePoint(0x1F3A4),
3865
+ pdf: String.fromCodePoint(0x1F4DC),
3866
+ document: String.fromCodePoint(0x1F4DC),
3867
+ task: String.fromCodePoint(0x2705),
3868
+ contacts: String.fromCodePoint(0x1F4F1),
3869
+ reminder: String.fromCodePoint(0x23F0),
3870
+ news: String.fromCodePoint(0x1F4F0),
3871
+ image: String.fromCodePoint(0x1F5BC,0xFE0F),
3872
+ video: String.fromCodePoint(0x1F3AC),
3873
+ music: String.fromCodePoint(0x1F3B5),
3874
+ translate: String.fromCodePoint(0x1F30D),
3875
+ math: String.fromCodePoint(0x1F9EE),
3876
+ sql: String.fromCodePoint(0x1F5C4,0xFE0F),
3877
+ api: String.fromCodePoint(0x1F517),
3878
+ test: String.fromCodePoint(0x1F9EA),
3879
+ monitor: String.fromCodePoint(0x1F4F6),
3880
+ _default: String.fromCodePoint(0x1F527)
3881
+ };
3882
+
3883
+ function getNodeEmoji(n) {
3884
+ var lbl = (n.label || n.agent || '').toLowerCase();
3885
+ var icon = n.icon || '';
3886
+ var keys = Object.keys(TOOL_EMOJI_MAP);
3887
+ for (var ki = 0; ki < keys.length; ki++) {
3888
+ if (keys[ki] !== '_default' && lbl.indexOf(keys[ki]) >= 0) return TOOL_EMOJI_MAP[keys[ki]];
3889
+ }
3890
+ if (icon && icon.length > 0 && icon.charCodeAt(0) > 127) return icon;
3891
+ return TOOL_EMOJI_MAP._default;
3892
+ }
3893
+
3842
3894
  function renderStudioNodes() {
3843
3895
  var el = document.getElementById('studioNodes');
3844
3896
  if (!el) return;
@@ -3851,80 +3903,118 @@ function renderStudioNodes() {
3851
3903
  var hasActive = nodes.some(function(n){ return n.status === \x27running\x27; });
3852
3904
  var doneCount = nodes.filter(function(n){ return n.status === \x27done\x27; }).length;
3853
3905
  var totalCount = nodes.length;
3854
- var showMaster = hasActive || doneCount > 0;
3855
3906
 
3856
- // ── ISO scene dimensions ───────────────────────────────────────────────────
3857
- var ISO_COLS = Math.max(nodes.length, 1);
3858
- var SCENE_W = 640; var SCENE_H = 420;
3907
+ var phaseLabel2 = hasActive
3908
+ ? (\x27Workflow in esecuzione \u2014 \x27+doneCount+\x27/\x27+totalCount)
3909
+ : (doneCount===totalCount && totalCount>0 ? \x27Workflow completato\x27 : \x27Workflow pianificato\x27);
3910
+ var phaseColor2 = hasActive ? \x27#6366f1\x27 : (doneCount===totalCount && totalCount>0 ? \x27#1f2937\x27 : \x27#6b7280\x27);
3911
+
3912
+ // ── CSS Grid layout: 100% width, responsive ──────────────────────────────
3913
+ var totalStations = totalCount + 1; // +1 for orchestrator
3914
+ var cols = totalStations <= 2 ? totalStations : (totalStations <= 4 ? 2 : (totalStations <= 6 ? 3 : 4));
3915
+ var gridTpl = \x27repeat(\x27+cols+\x27,1fr)\x27;
3916
+
3917
+ var bigPlant = String.fromCodePoint(0x1FAB4);
3918
+ var plantEmoji = String.fromCodePoint(0x1F331);
3919
+
3920
+ function buildStation2(label, toolEmoji, isOrch, isActive, isDone, isErr, emojiIdx) {
3921
+ var accentColor = isOrch ? \x27#818cf8\x27 : (isActive ? \x27#6366f1\x27 : (isDone ? \x27#374151\x27 : (isErr ? \x27#ef4444\x27 : \x27#9ca3af\x27)));
3922
+ var nameBg = isDone ? \x27rgba(0,0,0,.1)\x27 : (isActive ? \x27#ede9fe\x27 : (isOrch ? \x27#e0e7ff\x27 : \x27rgba(255,255,255,.85)\x27));
3923
+ var nameColor = isDone ? \x27#111827\x27 : (isActive ? \x27#4f46e5\x27 : (isOrch ? \x27#4338ca\x27 : (isErr ? \x27#dc2626\x27 : \x27#374151\x27)));
3924
+ var monScreen = isOrch
3925
+ ? \x27<span style="font-size:11px">&#128269;</span>\x27
3926
+ : (isDone ? \x27<span style="color:#111827;font-size:13px">&#10003;</span>\x27
3927
+ : (isActive ? \x27<span class="iso-monitor-blink"></span>\x27
3928
+ : \x27<span style="font-size:8px;opacity:.35;color:#818cf8">&#9632;</span>\x27));
3929
+ var bubbleText = isOrch
3930
+ ? (hasActive ? (\x27Step \x27+doneCount+\x27/\x27+totalCount) : (doneCount===totalCount&&totalCount>0 ? \x27\u2714 Fatto!\x27 : \x27In attesa\x27))
3931
+ : (isActive ? \x27\u2022\u2022\u2022 lavora\x27 : (isDone ? \x27\u2714 fatto\x27 : (isErr ? \x27\u2715 errore\x27 : \x27\x27)));
3932
+ var bubbleBg = isOrch ? \x27rgba(99,102,241,.15)\x27 : (isActive ? \x27rgba(99,102,241,.12)\x27 : (isDone ? \x27rgba(0,0,0,.08)\x27 : \x27rgba(239,68,68,.12)\x27));
3933
+ var glowBox = isActive ? (\x270 0 0 3px \x27+accentColor+\x2744,0 8px 24px \x27+accentColor+\x2733\x27) : (isDone ? (\x270 0 0 2px rgba(0,0,0,.25)\x27) : \x27none\x27);
3934
+ var orchWalkClass = (isOrch && hasActive) ? \x27 iso-orch-walking\x27 : (isOrch && doneCount===totalCount&&totalCount>0 ? \x27 iso-orch-done\x27 : \x27\x27);
3935
+ var charHtml = isoCharSvg({emojiIdx: isOrch ? 99 : emojiIdx, isActive: isActive, isDone: isDone, scale: 1.1, accentColor: accentColor});
3936
+ var clickAttr = isOrch ? \x27\x27 : (\x27data-agent-label="\x27+esc(label)+\x27" onclick="studioScrollToAgent(this.getAttribute(String.fromCharCode(100,97,116,97,45,97,103,101,110,116,45,108,97,98,101,108)))"\x27);
3937
+ return \x27<div class="iso-station\x27+orchWalkClass+\x27" \x27+clickAttr+\x27 style="box-shadow:\x27+glowBox+\x27;border-color:\x27+accentColor+\x27;transition:box-shadow .4s">\x27+
3938
+ \x27<div class="iso-bubble\x27+(isActive?\x27 iso-bubble--active\x27:\x27\x27)+\x27" style="border-color:\x27+accentColor+\x27;color:\x27+accentColor+\x27;background:\x27+bubbleBg+\x27;visibility:\x27+(bubbleText||isOrch?\x27visible\x27:\x27hidden\x27)+\x27">\x27+esc(bubbleText)+\x27</div>\x27+
3939
+ \x27<div class="iso-tool-badge">\x27+toolEmoji+\x27</div>\x27+
3940
+ charHtml+
3941
+ \x27<div class="iso-desk" style="width:85%;border-top-color:\x27+accentColor+\x2733"></div>\x27+
3942
+ \x27<div class="iso-monitor" style="border-color:\x27+accentColor+\x2777"><div class="iso-monitor-screen">\x27+monScreen+\x27</div></div>\x27+
3943
+ \x27<div class="iso-name" style="color:\x27+nameColor+\x27;background:\x27+nameBg+\x27">\x27+(isOrch?\x27\u2666\xA0\x27:\x27\x27)+esc(label)+\x27</div>\x27+
3944
+ \x27</div>\x27;
3945
+ }
3859
3946
 
3860
- var agentsHtml = \x27\x27;
3947
+ var stationsHtml = \x27\x27;
3948
+ var orchDone2 = !hasActive && doneCount===totalCount && totalCount>0;
3949
+ stationsHtml += buildStation2(\x27Orchestratore\x27, String.fromCodePoint(0x1F4CB), true, hasActive, orchDone2, false, 99);
3861
3950
  nodes.forEach(function(n, idx) {
3862
- var isActive = n.status === \x27running\x27;
3863
- var isDone = n.status === \x27done\x27;
3864
- var isErr = n.status === \x27error\x27;
3865
- var lbl = n.label || n.agent;
3866
- var pal = agentPalette(lbl);
3867
- var accentColor = isActive ? \x27#6366f1\x27 : (isDone ? \x27#374151\x27 : (isErr ? \x27#ef4444\x27 : \x27#999\x27));
3868
-
3869
- // Spread agents evenly across front rows
3870
- var colStep = ISO_COLS > 1 ? 5 / (ISO_COLS - 1) : 2;
3871
- var col = (ISO_COLS === 1) ? 2.5 : idx * colStep;
3872
- var row = 3.5;
3873
- var pos = isoProject(col, row);
3874
- var px = pos.x; var py = pos.y + 80;
3875
- var charScale = 1.1;
3876
- var zIdx = Math.round(py + 100);
3877
-
3878
- // Bubble: only show when active (live text) or done (checkmark)
3879
- var bubbleText = isActive ? \x27...lavora\x27 : (isDone ? \x27\u2714 fatto\x27 : (isErr ? \x27\u2715 errore\x27 : \x27\x27));
3880
- var bubbleColor = isActive ? \x27#6366f1\x27 : (isDone ? \x27#374151\x27 : \x27#ef4444\x27);
3881
- void pal; // palette no longer used for character rendering
3882
- var charSvg = isoCharSvg({emojiIdx: idx, isActive: isActive, isDone: isDone, scale: charScale, accentColor: accentColor});
3883
- var charW = Math.round(52 * charScale); var charH = Math.round(52 * charScale);
3884
-
3885
- agentsHtml += \x27<div class="iso-agent" data-agent-label="\x27+esc(lbl)+\x27" style="position:absolute;left:\x27+(px-charW/2)+\x27px;top:\x27+(py-charH)+\x27px;z-index:\x27+zIdx+\x27;display:flex;flex-direction:column;align-items:center;gap:3px;cursor:pointer" onclick="studioScrollToAgent(this.getAttribute(String.fromCharCode(100,97,116,97,45,97,103,101,110,116,45,108,97,98,101,108)))">\x27;
3886
- // Bubble — bigger, left-aligned (no mirror issue)
3887
- if (bubbleText || isActive) {
3888
- agentsHtml += \x27<div class="iso-bubble\x27+(isActive?\x27 iso-bubble--active\x27:\x27\x27)+\x27" id="isobubble_\x27+idx+\x27" style="border-color:\x27+bubbleColor+\x27;color:\x27+bubbleColor+\x27;min-width:80px;max-width:140px;font-size:10px;padding:4px 10px;text-align:left">\x27+esc(bubbleText)+\x27</div>\x27;
3889
- } else {
3890
- agentsHtml += \x27<div class="iso-bubble" id="isobubble_\x27+idx+\x27" style="visibility:hidden;min-width:80px"></div>\x27;
3891
- }
3892
- agentsHtml += charSvg;
3893
- agentsHtml += \x27<div class="iso-name" style="font-size:10px;font-weight:700;color:\x27+(isDone?\x27#111827\x27:(isActive?\x27#818cf8\x27:(isErr?\x27#ef4444\x27:\x27#555\x27)))+\x27;text-shadow:0 1px 3px rgba(255,255,255,.8)">\x27+esc(lbl)+\x27</div>\x27;
3894
- // Desk — lighter wood color for bright office
3895
- agentsHtml += isoDeskSvg(px, py - charH/2, accentColor);
3896
- agentsHtml += \x27</div>\x27;
3951
+ stationsHtml += buildStation2(
3952
+ n.label || n.agent,
3953
+ getNodeEmoji(n),
3954
+ false,
3955
+ n.status===\x27running\x27,
3956
+ n.status===\x27done\x27,
3957
+ n.status===\x27error\x27,
3958
+ idx
3959
+ );
3897
3960
  });
3898
3961
 
3899
- // ── Orchestrator ──────────────────────────────────────────────────────────
3900
- var orchHtml = \x27\x27;
3901
- if (showMaster) {
3902
- var oPh = isoProject(ISO_COLS / 2 + 0.5, 1.2);
3903
- var orchDone = !hasActive && doneCount === totalCount;
3904
- var orchAnim = hasActive ? \x27prl-master-walk\x27 : (orchDone ? \x27prl-master-done\x27 : \x27\x27);
3905
- var orchStatus = hasActive
3906
- ? (\x27Step \x27+doneCount+\x27/\x27+totalCount)
3907
- : (orchDone ? \x27Completato!\x27 : \x27Pianificazione\x27);
3908
- orchHtml = \x27<div class="prl-master \x27+orchAnim+\x27" id="wfOrch" style="position:absolute;left:\x27+(oPh.x-28)+\x27px;top:\x27+(oPh.y+60)+\x27px;z-index:50;display:flex;flex-direction:column;align-items:center;gap:3px">\x27+
3909
- \x27<div class="iso-bubble iso-bubble--orch" id="wfOrchBubble" style="border-color:#6366f1;color:#6366f1;max-width:140px;font-size:10px;padding:4px 10px">\x27+esc(orchStatus)+\x27</div>\x27+
3910
- isoOrchSvg(hasActive, doneCount / Math.max(totalCount,1))+
3911
- \x27<div class="prl-master-label" style="color:#6366f1;font-size:9px;font-weight:700;text-shadow:0 1px 3px rgba(255,255,255,.8)">Orchestratore</div>\x27+
3912
- \x27</div>\x27;
3962
+ // Floor SVG
3963
+ var FW = 1000; var FH = 600;
3964
+ var wallH = Math.round(FH * 0.30);
3965
+ var floorSvg = \x27<svg viewBox="0 0 \x27+FW+\x27 \x27+FH+\x27" preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg" style="position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;pointer-events:none">\x27;
3966
+ floorSvg += \x27<defs>\x27;
3967
+ floorSvg += \x27<filter id="bGlow2" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>\x27;
3968
+ floorSvg += \x27<linearGradient id="wallGrad" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#faf7f2"/><stop offset="1" stop-color="#ede8e0"/></linearGradient>\x27;
3969
+ floorSvg += \x27</defs>\x27;
3970
+ floorSvg += \x27<rect x="0" y="0" width="\x27+FW+\x27" height="\x27+wallH+\x27" fill="url(#wallGrad)"/>\x27;
3971
+ floorSvg += \x27<rect x="0" y="\x27+(wallH-5)+\x27" width="\x27+FW+\x27" height="7" fill="#d4c4a8" rx="2"/>\x27;
3972
+ var plankColors2 = [\x27#c8a06a\x27,\x27#bf9860\x27,\x27#d4aa72\x27,\x27#ba9458\x27,\x27#caa86e\x27];
3973
+ var pH = 32; var pW = 120;
3974
+ for (var fy = wallH; fy < FH+pH; fy += pH) {
3975
+ var ro2 = (Math.floor((fy-wallH)/pH) % 2) * (pW/2);
3976
+ for (var fx = -pW+ro2; fx < FW+pW; fx += pW) {
3977
+ var pc2 = plankColors2[Math.abs(Math.round(fx/pW+fy/pH*1.3)) % plankColors2.length];
3978
+ floorSvg += \x27<rect x="\x27+Math.round(fx)+\x27" y="\x27+fy+\x27" width="\x27+(pW-2)+\x27" height="\x27+(pH-2)+\x27" fill="\x27+pc2+\x27" rx="2"/>\x27;
3979
+ floorSvg += \x27<line x1="\x27+Math.round(fx+pW*0.4)+\x27" y1="\x27+fy+\x27" x2="\x27+Math.round(fx+pW*0.4)+\x27" y2="\x27+(fy+pH-2)+\x27" stroke="rgba(0,0,0,.04)" stroke-width="1.5"/>\x27;
3980
+ }
3913
3981
  }
3914
-
3915
- var phaseLabel2 = hasActive
3916
- ? (\x27Workflow in esecuzione \u2014 \x27+doneCount+\x27/\x27+totalCount)
3917
- : (doneCount===totalCount && totalCount>0 ? \x27Workflow completato\x27 : \x27Workflow pianificato\x27);
3918
- var phaseColor2 = hasActive ? \x27#6366f1\x27 : (doneCount===totalCount && totalCount>0 ? \x27#1f2937\x27 : \x27#6b7280\x27);
3982
+ function svgWindow(wx, wy, ww, wh) {
3983
+ var r = \x27<rect x="\x27+wx+\x27" y="\x27+wy+\x27" width="\x27+ww+\x27" height="\x27+wh+\x27" rx="4" fill="#c8e6f8" stroke="#a8cce0" stroke-width="3"/>\x27;
3984
+ r += \x27<rect x="\x27+wx+\x27" y="\x27+wy+\x27" width="\x27+ww+\x27" height="\x27+wh+\x27" rx="4" fill="rgba(255,255,255,.2)"/>\x27;
3985
+ r += \x27<line x1="\x27+(wx+ww/2)+\x27" y1="\x27+wy+\x27" x2="\x27+(wx+ww/2)+\x27" y2="\x27+(wy+wh)+\x27" stroke="#a8cce0" stroke-width="2"/>\x27;
3986
+ r += \x27<line x1="\x27+wx+\x27" y1="\x27+(wy+wh/2)+\x27" x2="\x27+(wx+ww)+\x27" y2="\x27+(wy+wh/2)+\x27" stroke="#a8cce0" stroke-width="2"/>\x27;
3987
+ return r;
3988
+ }
3989
+ floorSvg += svgWindow(40, 20, 100, 80);
3990
+ floorSvg += svgWindow(180, 20, 100, 80);
3991
+ floorSvg += svgWindow(FW-200, 20, 120, 80);
3992
+ floorSvg += \x27<rect x="\x27+(FW/2-35)+\x27" y="0" width="70" height="\x27+wallH+\x27" fill="#c8a87a" stroke="#a07848" stroke-width="2"/>\x27;
3993
+ floorSvg += \x27<rect x="\x27+(FW/2-25)+\x27" y="8" width="50" height="36" rx="4" fill="rgba(255,255,255,.18)"/>\x27;
3994
+ floorSvg += \x27<circle cx="\x27+(FW/2+22)+\x27" cy="\x27+(wallH/2)+\x27" r="5" fill="#8a6028"/>\x27;
3995
+ floorSvg += \x27<line x1="\x27+(FW/2)+\x27" y1="0" x2="\x27+(FW/2)+\x27" y2="30" stroke="#bbb" stroke-width="3"/>\x27;
3996
+ floorSvg += \x27<ellipse cx="\x27+(FW/2)+\x27" cy="38" rx="50" ry="14" fill="#e8d960" stroke="#c8b030" stroke-width="2"/>\x27;
3997
+ floorSvg += \x27<circle cx="\x27+(FW/2-28)+\x27" cy="46" r="8" fill="#fffde0" filter="url(#bGlow2)"/>\x27;
3998
+ floorSvg += \x27<circle cx="\x27+(FW/2)+\x27" cy="50" r="8" fill="#fffde0" filter="url(#bGlow2)"/>\x27;
3999
+ floorSvg += \x27<circle cx="\x27+(FW/2+28)+\x27" cy="46" r="8" fill="#fffde0" filter="url(#bGlow2)"/>\x27;
4000
+ floorSvg += \x27<polygon points="\x27+(FW/2-60)+\x27,60 \x27+(FW/2+60)+\x27,60 \x27+(FW/2+160)+\x27,\x27+FH+\x27 \x27+(FW/2-160)+\x27,\x27+FH+\x27" fill="rgba(255,252,200,.06)"/>\x27;
4001
+ floorSvg += \x27</svg>\x27;
4002
+
4003
+ var decoHtml =
4004
+ \x27<div style="position:absolute;bottom:10px;left:12px;font-size:40px;line-height:1;filter:drop-shadow(0 3px 6px rgba(0,0,0,.25));z-index:5">\x27+bigPlant+\x27</div>\x27+
4005
+ \x27<div style="position:absolute;bottom:10px;right:12px;font-size:40px;line-height:1;filter:drop-shadow(0 3px 6px rgba(0,0,0,.25));z-index:5">\x27+bigPlant+\x27</div>\x27+
4006
+ \x27<div style="position:absolute;top:12px;left:310px;font-size:24px;line-height:1;z-index:5">\x27+plantEmoji+\x27</div>\x27+
4007
+ \x27<div style="position:absolute;top:12px;right:230px;font-size:24px;line-height:1;z-index:5">\x27+plantEmoji+\x27</div>\x27;
3919
4008
 
3920
4009
  el.innerHTML =
3921
4010
  \x27<div class="prl-wrap" style="border-color:\x27+phaseColor2+\x2744;padding-bottom:8px">\x27+
3922
4011
  \x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor2+\x27">\x27+phaseLabel2+\x27</span></div>\x27+
3923
- \x27<div style="display:flex;justify-content:center;width:100%;overflow-x:auto">\x27+
3924
- \x27<div class="iso-scene" style="position:relative;width:\x27+SCENE_W+\x27px;min-width:\x27+SCENE_W+\x27px;height:\x27+SCENE_H+\x27px;overflow:hidden;border-radius:12px;background:#f0ede6">\x27+
3925
- isoFloorSvg(ISO_COLS + 2, 5)+
3926
- agentsHtml+
3927
- orchHtml+
4012
+ \x27<div class="iso-scene" style="position:relative">\x27+
4013
+ floorSvg+
4014
+ decoHtml+
4015
+ \x27<div style="position:relative;z-index:10;display:grid;grid-template-columns:\x27+gridTpl+\x27;gap:0;padding:12px 16px;box-sizing:border-box;align-items:end;min-height:440px">\x27+
4016
+ \x27<div style="grid-column:1/-1;height:calc(30% - 12px)"></div>\x27+
4017
+ stationsHtml+
3928
4018
  \x27</div>\x27+
3929
4019
  \x27</div>\x27+
3930
4020
  \x27</div>\x27;
@@ -6139,8 +6229,22 @@ input:focus,textarea:focus{border-color:var(--green3)}
6139
6229
  .prl-office-plant{position:absolute;bottom:14px;left:4px;width:22px;height:42px;z-index:2;pointer-events:none}
6140
6230
  /* Plant right */
6141
6231
  .prl-office-plant2{position:absolute;bottom:14px;right:8px;width:22px;height:42px;z-index:2;pointer-events:none}
6142
- /* ── ISOMETRIC JRPG SCENE ── */
6143
- .iso-scene{background:#f0ede6;cursor:default;max-width:100%;overflow-x:auto;box-shadow:0 4px 24px rgba(0,0,0,.18)}
6232
+ /* ── OFFICE SCENE ── */
6233
+ .iso-scene{background:#f0ede6;cursor:default;max-width:100%;overflow-x:auto;box-shadow:0 4px 24px rgba(0,0,0,.18);border-radius:12px;overflow:hidden}
6234
+ .iso-station{display:flex;flex-direction:column;align-items:center;gap:3px;cursor:pointer;transition:filter .2s,transform .2s;padding:8px 4px;border-radius:12px;border:1.5px solid transparent;position:relative}
6235
+ .iso-station:hover{filter:brightness(1.06);transform:translateY(-2px)}
6236
+ .iso-station.iso-orch-walking{animation:orchWalkGrid 1.8s ease-in-out infinite alternate}
6237
+ @keyframes orchWalkGrid{0%{transform:translateX(0) scale(1)}100%{transform:translateX(24px) scale(1.04)}}
6238
+ .iso-station.iso-orch-done{animation:orchBounce .7s ease forwards}
6239
+ @keyframes orchBounce{0%{transform:scale(1)}40%{transform:scale(1.18) translateY(-6px)}100%{transform:scale(1)}}
6240
+ .iso-desk{width:90%;height:16px;background:linear-gradient(180deg,#d4a448 0%,#b8832a 100%);border-radius:4px 4px 2px 2px;box-shadow:0 4px 0 #8a5e18,0 6px 10px rgba(0,0,0,.3);border-top:2px solid #e8c060;position:relative;margin-top:4px}
6241
+ .iso-desk::after{content:'';position:absolute;bottom:-4px;left:8px;right:8px;height:4px;background:#7a5010;border-radius:0 0 3px 3px}
6242
+ .iso-monitor{width:56px;height:40px;background:#12101e;border:2px solid #3a3070;border-radius:5px;display:flex;align-items:center;justify-content:center;position:relative;margin-bottom:-2px}
6243
+ .iso-monitor::after{content:'';position:absolute;bottom:-5px;left:50%;transform:translateX(-50%);width:10px;height:5px;background:#252436;border-radius:0 0 3px 3px}
6244
+ .iso-monitor-screen{width:44px;height:28px;background:rgba(60,40,160,.35);border-radius:2px;display:flex;align-items:center;justify-content:center}
6245
+ .iso-monitor-blink{width:7px;height:7px;border-radius:50%;background:#6366f1;animation:monBlink .9s ease-in-out infinite}
6246
+ @keyframes monBlink{0%,100%{opacity:1;box-shadow:0 0 8px #6366f1}50%{opacity:.25;box-shadow:none}}
6247
+ .iso-tool-badge{font-size:22px;line-height:1;filter:drop-shadow(0 2px 5px rgba(0,0,0,.35));user-select:none;margin-bottom:1px}
6144
6248
  /* Animated status chip for [bracket tokens] */
6145
6249
  .iso-status-chip{display:inline-flex;align-items:center;gap:6px;background:rgba(99,102,241,.1);border:1px solid rgba(99,102,241,.3);border-radius:20px;padding:3px 10px;font-size:11px;font-family:var(--mono);color:#818cf8;animation:statusPulse 2s ease-in-out infinite}
6146
6250
  @keyframes statusPulse{0%,100%{opacity:.7;border-color:rgba(99,102,241,.3)}50%{opacity:1;border-color:rgba(99,102,241,.7);box-shadow:0 0 8px rgba(99,102,241,.3)}}
@@ -6153,8 +6257,8 @@ input:focus,textarea:focus{border-color:var(--green3)}
6153
6257
  .iso-orch-wrap{transition:transform .2s}
6154
6258
  .iso-orch-wrap.prl-head{animation:isoCharBob 1.4s ease-in-out infinite}
6155
6259
  /* Thought bubble / speech bubble above character */
6156
- .iso-bubble{font-size:8px;font-family:var(--mono);padding:2px 7px;border-radius:10px 10px 10px 2px;border:1px solid #3a3060;background:rgba(10,8,20,.85);color:#6b7280;white-space:normal;max-width:160px;line-height:1.4;transition:all .25s;pointer-events:none;backdrop-filter:blur(4px)}
6157
- .iso-bubble--active{background:rgba(30,20,60,.9);border-color:#6366f1;color:#a5b4fc;animation:isoBubblePop .35s ease;white-space:normal;max-width:110px;word-break:break-word;line-height:1.35}
6260
+ .iso-bubble{font-size:9px;font-family:var(--mono);padding:3px 9px;border-radius:12px;border:1px solid #ccc;background:rgba(255,255,255,.9);color:#6b7280;white-space:normal;word-break:break-word;max-width:160px;line-height:1.4;transition:all .25s;pointer-events:none;backdrop-filter:blur(6px);text-align:center}
6261
+ .iso-bubble--active{background:rgba(30,20,60,.9);border-color:#6366f1;color:#a5b4fc;animation:isoBubblePop .35s ease;white-space:normal;max-width:160px;word-break:break-word;line-height:1.35}
6158
6262
  .iso-bubble--orch{font-size:9px;padding:3px 9px;border-radius:12px;border-color:#818cf8;color:#a5b4fc;background:rgba(20,15,50,.9)}
6159
6263
  @keyframes isoBubblePop{0%{transform:scale(.8) translateY(4px);opacity:.4}100%{transform:scale(1) translateY(0);opacity:1}}
6160
6264
  .iso-name{font-size:10px;font-family:var(--mono);font-weight:700;letter-spacing:.3px;text-align:center;max-width:160px;white-space:normal;word-break:break-word;line-height:1.3;background:rgba(255,255,255,.85);border-radius:6px;padding:2px 6px;pointer-events:none;backdrop-filter:blur(4px)}