nothumanallowed 13.4.9 → 13.5.1

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.4.9",
3
+ "version": "13.5.1",
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.4.9';
8
+ export const VERSION = '13.5.1';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -729,6 +729,7 @@ function openCanvasPanel(){
729
729
  var cp = document.getElementById('canvasPanel');
730
730
  if (!cp) return;
731
731
  cp.classList.add('open');
732
+ document.body.classList.add('canvas-open');
732
733
  // Always reset tracker so renderCanvasPanel reloads fresh content
733
734
  _canvasFrameLoadedHtml = null;
734
735
  canvasMode = 'canvas';
@@ -746,7 +747,7 @@ function reopenCanvas(){
746
747
  else{canvasMode='canvas';} // show empty state
747
748
  renderCanvasPanel();
748
749
  }
749
- function closeCanvas(){var p=document.getElementById('canvasPanel');if(p)p.classList.remove('open');}
750
+ function closeCanvas(){var p=document.getElementById('canvasPanel');if(p)p.classList.remove('open');document.body.classList.remove('canvas-open');}
750
751
  function canvasDownloadHTML(){
751
752
  var d=getConvCanvasData();var item=d.canvases[canvasIdx];
752
753
  var html=(item&&item.html)||studioState.canvas;
@@ -3423,12 +3424,14 @@ function buildWorkflowChar(n) {
3423
3424
  var shirt = shirtColors[skinIdx];
3424
3425
  var hairColors = [\x27#1a1a1a\x27,\x27#4a3728\x27,\x27#c4a35a\x27,\x27#8b0000\x27,\x27#2c4a7c\x27,\x27#3d2b1f\x27];
3425
3426
  var hair = hairColors[skinIdx];
3426
- var accentColor = isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : \x27#333360\x27);
3427
- var deskBg = isDone ? \x27#1a3a1a\x27 : (isActive ? \x27#1a1a3e\x27 : \x27#1a1a2a\x27);
3428
- var monGlow = isActive ? \x27filter:drop-shadow(0 0 4px #6366f1)\x27 : \x27\x27;
3427
+ // Idle agents still have lit screens (dim amber glow standby mode)
3428
+ var accentColor = isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : \x27#3b3b6e\x27);
3429
+ var idleScreenColor = \x27#1e1b38\x27; // dim purple-blue for idle screens lit but standby
3430
+ var deskBg = isDone ? \x27#1a3a1a\x27 : (isActive ? \x27#1a1a3e\x27 : \x27#181830\x27);
3431
+ var monGlow = isActive ? \x27filter:drop-shadow(0 0 4px #6366f1)\x27 : (isDone ? \x27filter:drop-shadow(0 0 3px #22c55e44)\x27 : \x27filter:drop-shadow(0 0 3px #3b3b6e66)\x27);
3429
3432
  var armCls = isActive ? \x27class="prl-arm"\x27 : \x27\x27;
3430
3433
  var headCls = isActive ? \x27class="prl-head"\x27 : \x27\x27;
3431
- var glowStyle = isActive ? \x27filter:drop-shadow(0 0 5px #6366f1)\x27 : \x27\x27;
3434
+ var glowStyle = isActive ? \x27filter:drop-shadow(0 0 5px #6366f1)\x27 : (isDone ? \x27filter:drop-shadow(0 0 4px #22c55e44)\x27 : \x27\x27);
3432
3435
  var svg = \x27<svg viewBox="0 0 80 96" width="70" height="84" xmlns="http://www.w3.org/2000/svg" style="\x27+glowStyle+\x27;display:block;margin:0 auto">\x27+
3433
3436
  // Desk
3434
3437
  \x27<path d="M4 55 L76 55 L76 63 L4 63 Z" fill="\x27+deskBg+\x27" stroke="\x27+accentColor+\x27" stroke-width="1.2"/>\x27+
@@ -3443,7 +3446,8 @@ function buildWorkflowChar(n) {
3443
3446
  \x27<rect x="33" y="50" width="4" height="6" rx="1" fill="#1a1a2e"/>\x27+
3444
3447
  \x27<rect x="17" y="26" width="36" height="25" rx="4" fill="#050510"/>\x27+
3445
3448
  \x27<rect x="18" y="27" width="34" height="23" rx="3" fill="#0d0d20" stroke="\x27+accentColor+\x27" stroke-width="\x27+(isActive?\x272\x27:\x271\x27)+\x27" style="\x27+monGlow+\x27"/>\x27+
3446
- \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="#0a0a18"/>\x27+
3449
+ // Screen glass idle=dim standby blue, done=dim green, active=lit
3450
+ \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="\x27+(isDone?\x27#0a1a0a\x27:(isActive?\x27#0a0a18\x27:\x27#0e0e22\x27))+\x27"/>\x27+
3447
3451
  (isActive ?
3448
3452
  \x27<defs><linearGradient id="wsg\x27+skinIdx+\x27" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#6366f122"/><stop offset="1" stop-color="#6366f108"/></linearGradient></defs>\x27+
3449
3453
  \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="url(#wsg\x27+skinIdx+\x27)"/>\x27+
@@ -3452,13 +3456,24 @@ function buildWorkflowChar(n) {
3452
3456
  \x27<line x1="22" y1="38" x2="46" y2="38" stroke="#6366f188" stroke-width="1" stroke-linecap="round"/>\x27+
3453
3457
  \x27<line x1="22" y1="41" x2="40" y2="41" stroke="#6366f166" stroke-width="1" stroke-linecap="round"/>\x27+
3454
3458
  \x27<line x1="22" y1="44" x2="43" y2="44" stroke="#6366f144" stroke-width="1" stroke-linecap="round"/>\x27
3459
+ : isDone ?
3460
+ // Done: green screen with completed code
3461
+ \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="#0a1a0a88"/>\x27+
3462
+ \x27<line x1="22" y1="32" x2="44" y2="32" stroke="#22c55e99" stroke-width="1" stroke-linecap="round"/>\x27+
3463
+ \x27<line x1="22" y1="35" x2="46" y2="35" stroke="#22c55e77" stroke-width="1" stroke-linecap="round"/>\x27+
3464
+ \x27<line x1="22" y1="38" x2="40" y2="38" stroke="#22c55e55" stroke-width="1" stroke-linecap="round"/>\x27+
3465
+ \x27<line x1="22" y1="41" x2="43" y2="41" stroke="#22c55e44" stroke-width="1" stroke-linecap="round"/>\x27
3455
3466
  :
3456
- \x27<line x1="22" y1="33" x2="46" y2="33" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27+
3457
- \x27<line x1="22" y1="36" x2="42" y2="36" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27+
3458
- \x27<line x1="22" y1="39" x2="44" y2="39" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27+
3459
- \x27<line x1="22" y1="42" x2="38" y2="42" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27
3467
+ // Idle: dim standby screen agent is waiting, screen lit but quiet
3468
+ \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="rgba(63,63,120,.18)"/>\x27+
3469
+ \x27<line x1="22" y1="33" x2="46" y2="33" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".7"/>\x27+
3470
+ \x27<line x1="22" y1="36" x2="38" y2="36" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".5"/>\x27+
3471
+ \x27<line x1="22" y1="39" x2="44" y2="39" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".4"/>\x27+
3472
+ \x27<line x1="22" y1="42" x2="34" y2="42" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".3"/>\x27+
3473
+ // Standby dot — blinking cursor
3474
+ \x27<circle cx="22" cy="45" r="1" fill="#6366f1" opacity=".6" class="prl-doc-hold"/>\x27
3460
3475
  )+
3461
- \x27<circle cx="35" cy="28.2" r=".9" fill="\x27+(isActive?\x27#6366f1\x27:\x27#2a2a40\x27)+\x27"/>\x27+
3476
+ \x27<circle cx="35" cy="28.2" r=".9" fill="\x27+(isActive?\x27#6366f1\x27:(isDone?\x27#22c55e\x27:\x27#4040a0\x27))+\x27"/>\x27+
3462
3477
  // Keyboard
3463
3478
  \x27<rect x="13" y="48" width="36" height="7" rx="2.5" fill="#0c0c1e" stroke="#202036" stroke-width="1"/>\x27+
3464
3479
  \x27<rect x="14" y="49.5" width="3" height="2" rx=".5" fill="#181830"/>\x27+
@@ -3541,6 +3556,53 @@ function buildWorkflowChar(n) {
3541
3556
  return svg;
3542
3557
  }
3543
3558
 
3559
+ // ── Office room decorations — window, wall art, plants, lamp ──────────────────
3560
+ // Used in both workflow and parliament office blocks.
3561
+ function officeRoomDecor() {
3562
+ // SVG plant: pot + soil + stem + leaves (monstera-ish)
3563
+ var plantSvg = \x27<svg viewBox="0 0 20 36" width="20" height="36" xmlns="http://www.w3.org/2000/svg">\x27+
3564
+ // Pot
3565
+ \x27<path d="M4 27 L6 34 L14 34 L16 27 Z" fill="#2a1a0a" stroke="#3d2810" stroke-width=".8"/>\x27+
3566
+ // Pot rim
3567
+ \x27<rect x="3" y="25" width="14" height="3" rx="1.5" fill="#3d2810" stroke="#4d3215" stroke-width=".5"/>\x27+
3568
+ // Soil
3569
+ \x27<ellipse cx="10" cy="26.5" rx="6" ry="1.5" fill="#1a0f05"/>\x27+
3570
+ // Main stem
3571
+ \x27<path d="M10 25 C10 20 9 14 10 8" stroke="#1a4a10" stroke-width="1.2" fill="none" stroke-linecap="round"/>\x27+
3572
+ // Left leaf
3573
+ \x27<path d="M10 18 C6 14 3 15 4 19 C5 22 9 21 10 18" fill="#166534" opacity=".9"/>\x27+
3574
+ \x27<path d="M10 18 C7.5 16.5 6 17.5 7 19" stroke="#14532d" stroke-width=".5" fill="none"/>\x27+
3575
+ // Right leaf
3576
+ \x27<path d="M10 13 C14 9 17 10 16 14 C15 17 11 16 10 13" fill="#15803d" opacity=".9"/>\x27+
3577
+ \x27<path d="M10 13 C12.5 11.5 14 12.5 13 14" stroke="#14532d" stroke-width=".5" fill="none"/>\x27+
3578
+ // Top leaf
3579
+ \x27<path d="M10 8 C8 4 5 5 6 8 C7 11 10 10 10 8" fill="#166534" opacity=".85"/>\x27+
3580
+ \x27</svg>\x27;
3581
+ // Second plant (taller, cactus-ish)
3582
+ var plant2Svg = \x27<svg viewBox="0 0 20 36" width="20" height="36" xmlns="http://www.w3.org/2000/svg">\x27+
3583
+ // Pot
3584
+ \x27<path d="M4 27 L6 34 L14 34 L16 27 Z" fill="#2a1a0a" stroke="#3d2810" stroke-width=".8"/>\x27+
3585
+ \x27<rect x="3" y="25" width="14" height="3" rx="1.5" fill="#3d2810" stroke="#4d3215" stroke-width=".5"/>\x27+
3586
+ \x27<ellipse cx="10" cy="26.5" rx="6" ry="1.5" fill="#1a0f05"/>\x27+
3587
+ // Main trunk (cactus)
3588
+ \x27<path d="M9 25 L9 10 Q9 8 10 8 Q11 8 11 10 L11 25 Z" fill="#1a5c18" stroke="#145214" stroke-width=".5"/>\x27+
3589
+ // Left arm
3590
+ \x27<path d="M9 16 C5 16 4 14 4 12 Q4 10 6 10 L9 10" fill="#166534" stroke="#145214" stroke-width=".5"/>\x27+
3591
+ // Right arm
3592
+ \x27<path d="M11 19 C15 19 16 17 16 15 Q16 13 14 13 L11 13" fill="#15803d" stroke="#145214" stroke-width=".5"/>\x27+
3593
+ // Spines
3594
+ \x27<line x1="10" y1="20" x2="12" y2="19" stroke="#4ade80" stroke-width=".6" opacity=".4"/>\x27+
3595
+ \x27<line x1="10" y1="14" x2="8" y2="13" stroke="#4ade80" stroke-width=".6" opacity=".4"/>\x27+
3596
+ \x27</svg>\x27;
3597
+ return \x27<div class="prl-office-window"></div>\x27+
3598
+ \x27<div class="prl-office-window-light"></div>\x27+
3599
+ \x27<div class="prl-office-frame"></div>\x27+
3600
+ \x27<div class="prl-office-frame2"></div>\x27+
3601
+ \x27<div class="prl-office-lamp"></div>\x27+
3602
+ \x27<div class="prl-office-plant">\x27+plantSvg+\x27</div>\x27+
3603
+ \x27<div class="prl-office-plant2">\x27+plant2Svg+\x27</div>\x27;
3604
+ }
3605
+
3544
3606
  function renderStudioNodes() {
3545
3607
  var el = document.getElementById('studioNodes');
3546
3608
  if (!el) return;
@@ -3672,8 +3734,9 @@ function renderStudioNodes() {
3672
3734
  var html = \x27<div class="prl-wrap" style="border-color:\x27+phaseColor2+\x2744;padding-bottom:16px">\x27+
3673
3735
  \x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor2+\x27">\x27+phaseLabel2+\x27</span></div>\x27+
3674
3736
  \x27<div class="prl-office wf-office" style="min-height:160px">\x27+
3737
+ officeRoomDecor()+
3675
3738
  \x27<div class="prl-office-floor"></div>\x27+
3676
- \x27<div class="prl-desks-row" style="justify-content:center;flex-wrap:wrap;gap:10px;padding-bottom:8px">\x27+desksHtml2+\x27</div>\x27+
3739
+ \x27<div class="prl-desks-row" style="justify-content:center;flex-wrap:wrap;gap:10px;padding-bottom:8px;position:relative;z-index:2">\x27+desksHtml2+\x27</div>\x27+
3677
3740
  masterWfHtml+
3678
3741
  \x27</div>\x27+
3679
3742
  \x27</div>\x27;
@@ -4276,7 +4339,7 @@ async function runStudio() {
4276
4339
  pb.style.width = \x27calc(100vw - 32px)\x27;
4277
4340
  pb.style.maxWidth = \x27860px\x27;
4278
4341
  pb.style.top = \x27\x27;
4279
- pb.style.zIndex = \x27500\x27;
4342
+ pb.style.zIndex = \x271010\x27;
4280
4343
  pb.style.boxShadow = \x270 8px 40px rgba(99,102,241,.5),0 2px 0 rgba(99,102,241,.2)\x27;
4281
4344
  }
4282
4345
 
@@ -4374,8 +4437,8 @@ async function runStudio() {
4374
4437
  \x27<rect x="17" y="26" width="36" height="25" rx="4" fill="#050510"/>\x27+
4375
4438
  // Monitor bezel
4376
4439
  \x27<rect x="18" y="27" width="34" height="23" rx="3" fill="#0d0d20" stroke="\x27+(isActive?phaseColor:\x27#252535\x27)+\x27" stroke-width="\x27+(isActive?\x272\x27:\x271\x27)+\x27" style="\x27+monitorGlow+\x27"/>\x27+
4377
- // Screen glass — subtle gradient
4378
- \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="#0a0a18"/>\x27+
4440
+ // Screen glass — idle=standby blue, done=green, active=lit
4441
+ \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="\x27+(isDone?\x27#0a1a0a\x27:(isActive?\x27#0a0a18\x27:\x27#0e0e22\x27))+\x27"/>\x27+
4379
4442
  // Screen content
4380
4443
  (isActive ?
4381
4444
  // Active: glowing code/data on screen
@@ -4387,15 +4450,24 @@ async function runStudio() {
4387
4450
  \x27<line x1="22" y1="41" x2="40" y2="41" stroke="\x27+phaseColor+\x2766" stroke-width="1" stroke-linecap="round"/>\x27+
4388
4451
  \x27<line x1="22" y1="44" x2="43" y2="44" stroke="\x27+phaseColor+\x2744" stroke-width="1" stroke-linecap="round"/>\x27+
4389
4452
  \x27<rect x="22" y="30" width="10" height="2.5" rx="1" fill="\x27+phaseColor+\x2733"/>\x27
4453
+ : isDone ?
4454
+ // Done: green screen with completed output
4455
+ \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="#0a1a0a88"/>\x27+
4456
+ \x27<line x1="22" y1="32" x2="44" y2="32" stroke="#22c55e99" stroke-width="1" stroke-linecap="round"/>\x27+
4457
+ \x27<line x1="22" y1="35" x2="46" y2="35" stroke="#22c55e77" stroke-width="1" stroke-linecap="round"/>\x27+
4458
+ \x27<line x1="22" y1="38" x2="40" y2="38" stroke="#22c55e55" stroke-width="1" stroke-linecap="round"/>\x27+
4459
+ \x27<line x1="22" y1="41" x2="43" y2="41" stroke="#22c55e44" stroke-width="1" stroke-linecap="round"/>\x27
4390
4460
  :
4391
- // Idle: dim screen with faint lines
4392
- \x27<line x1="22" y1="33" x2="46" y2="33" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27+
4393
- \x27<line x1="22" y1="36" x2="42" y2="36" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27+
4394
- \x27<line x1="22" y1="39" x2="44" y2="39" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27+
4395
- \x27<line x1="22" y1="42" x2="38" y2="42" stroke="#1e1e30" stroke-width="1" stroke-linecap="round"/>\x27
4461
+ // Idle: dim standby screen waiting, lit but quiet
4462
+ \x27<rect x="20" y="29" width="30" height="18" rx="2" fill="rgba(63,63,120,.18)"/>\x27+
4463
+ \x27<line x1="22" y1="33" x2="46" y2="33" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".7"/>\x27+
4464
+ \x27<line x1="22" y1="36" x2="38" y2="36" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".5"/>\x27+
4465
+ \x27<line x1="22" y1="39" x2="44" y2="39" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".4"/>\x27+
4466
+ \x27<line x1="22" y1="42" x2="34" y2="42" stroke="#5b5b8e" stroke-width="1" stroke-linecap="round" opacity=".3"/>\x27+
4467
+ \x27<circle cx="22" cy="45" r="1" fill="#6366f1" opacity=".6" class="prl-doc-hold"/>\x27
4396
4468
  )+
4397
4469
  // Monitor camera dot
4398
- \x27<circle cx="35" cy="28.2" r=".9" fill="\x27+(isActive?phaseColor:\x27#2a2a40\x27)+\x27"/>\x27+
4470
+ \x27<circle cx="35" cy="28.2" r=".9" fill="\x27+(isActive?phaseColor:(isDone?\x27#22c55e\x27:\x27#4040a0\x27))+\x27"/>\x27+
4399
4471
  // ════ KEYBOARD (detailed, realistic) ════
4400
4472
  \x27<rect x="13" y="48" width="36" height="7" rx="2.5" fill="#0c0c1e" stroke="#202036" stroke-width="1"/>\x27+
4401
4473
  // Key rows
@@ -4527,7 +4599,7 @@ async function runStudio() {
4527
4599
  return \x27<div class="prl-desk\x27+(isActive?\x27 prl-desk--active\x27:\x27\x27)+(isDone?\x27 prl-desk--done\x27:\x27\x27)+\x27" style="--dc:\x27+phaseColor+\x27;box-shadow:\x27+shadow+\x27">\x27+
4528
4600
  (actionStr ? \x27<div class="prl-action-bubble\x27+(isActive?\x27 prl-action-bubble--active\x27:\x27\x27)+\x27">\x27+actionStr+\x27</div>\x27 : \x27\x27)+
4529
4601
  svgChar+
4530
- \x27<div class="prl-desk-name" style="color:\x27+(isDone?\x27#4ade80\x27:(isActive?phaseColor:\x27#6b7280\x27))+\x27">\x27+esc(lbl.slice(0,14))+\x27</div>\x27+
4602
+ \x27<div class="prl-desk-name" style="color:\x27+(isDone?\x27#4ade80\x27:(isActive?phaseColor:\x27#6b7280\x27))+\x27">\x27+esc(lbl)+\x27</div>\x27+
4531
4603
  \x27</div>\x27;
4532
4604
  }
4533
4605
 
@@ -4715,8 +4787,9 @@ async function runStudio() {
4715
4787
  \x27<div class="prl-wrap">\x27+
4716
4788
  \x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor+\x27">\x27+phaseLabel+\x27</span></div>\x27+
4717
4789
  \x27<div class="prl-office">\x27+
4790
+ officeRoomDecor()+
4718
4791
  \x27<div class="prl-office-floor"></div>\x27+
4719
- \x27<div class="prl-desks-row">\x27+desksHtml+\x27</div>\x27+
4792
+ \x27<div class="prl-desks-row" style="position:relative;z-index:2">\x27+desksHtml+\x27</div>\x27+
4720
4793
  masterHtml+
4721
4794
  flyingDocHtml+
4722
4795
  \x27</div>\x27+
@@ -4840,7 +4913,7 @@ async function runStudio() {
4840
4913
  } catch(e3) {
4841
4914
  if (e3.name !== \x27AbortError\x27) {
4842
4915
  studioLog(\x27Parlamento\x27, \x27&#x2656;\x27, \x27Deliberazione non disponibile: \x27 + (e3.message || String(e3)), \x27error\x27);
4843
- var pb2 = document.getElementById(\x27studioParliamentBlock\x27); if (pb2) pb2.style.display = \x27none\x27;
4916
+ // Do NOT hide the parliament block if it already has content — user is watching it
4844
4917
  }
4845
4918
  }
4846
4919
  }
@@ -4914,7 +4987,7 @@ function saveStudioSession(task, nodes, log, result) {
4914
4987
  sessions.unshift({
4915
4988
  id: Date.now(),
4916
4989
  task: task,
4917
- nodes: nodes.map(function(n){return {label:n.label,icon:n.icon,agent:n.agent};}),
4990
+ nodes: nodes.map(function(n){return {label:n.label,icon:n.icon,agent:n.agent,output:n.output||''};}),
4918
4991
  result: result,
4919
4992
  canvas: studioState.canvas || null,
4920
4993
  parlHtml: parlHtml,
@@ -4958,7 +5031,7 @@ function restoreStudioSession(idx) {
4958
5031
  var sessions = loadStudioSessions();
4959
5032
  var s = sessions[idx]; if (!s) return;
4960
5033
  studioState.task = s.task;
4961
- studioState.nodes = s.nodes.map(function(n){return {icon:n.icon,agent:n.agent,label:n.label,status:'done'};});
5034
+ studioState.nodes = s.nodes.map(function(n){return {icon:n.icon,agent:n.agent,label:n.label,output:n.output||'',status:'done'};});
4962
5035
  studioState.log = s.log;
4963
5036
  studioState.result = s.result;
4964
5037
  studioState.canvas = s.canvas || null;
@@ -5870,7 +5943,7 @@ input:focus,textarea:focus{border-color:var(--green3)}
5870
5943
  .studio-arrow--done{color:#22c55e}
5871
5944
  /* ── Workflow scene (office layout, replaces cramped pill nodes) ── */
5872
5945
  .studio-canvas{background:none!important;border:none!important;padding:0!important;margin-bottom:0!important}
5873
- #studioNodes .prl-office{border-radius:10px;border:1px solid var(--border);background:var(--bg2);margin-bottom:16px;min-height:200px;padding:16px 12px 8px;position:relative;overflow:visible}
5946
+ #studioNodes .prl-office{border-radius:10px;border:1px solid rgba(99,102,241,.25);background:linear-gradient(180deg,#0e0c1e 0%,#13102a 55%,#1a172e 100%);margin-bottom:16px;min-height:200px;padding:16px 12px 12px;position:relative;overflow:hidden}
5874
5947
  .wf-office{display:block}
5875
5948
  .wf-desks-row{display:flex;align-items:flex-end;justify-content:center;gap:6px;flex-wrap:wrap;padding-bottom:10px}
5876
5949
  .wf-desk{position:relative;display:flex;flex-direction:column;align-items:center;gap:2px;cursor:pointer;transition:opacity .2s}
@@ -5888,13 +5961,42 @@ input:focus,textarea:focus{border-color:var(--green3)}
5888
5961
  .prl-wrap{background:#07070f;border:1.5px solid #6366f1;border-radius:14px;padding:14px 16px 12px;margin-bottom:16px;animation:stNodeIn .35s ease forwards;overflow:hidden}
5889
5962
  #studioParliamentBlock[style*="fixed"] .prl-wrap{animation:stNodeIn .35s ease forwards,parlPulse 2.2s ease-in-out infinite}
5890
5963
  #studioParliamentBlock[style*="fixed"]{backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
5964
+ /* When canvas panel is open, shift parliament left so they don't overlap */
5965
+ body.canvas-open #studioParliamentBlock[style*="fixed"]{left:16px!important;transform:none!important;max-width:calc(100vw - 520px)!important}
5891
5966
  @keyframes parlPulse{0%,100%{border-color:#6366f1;box-shadow:none}50%{border-color:#818cf8;box-shadow:0 0 20px rgba(99,102,241,.3)}}
5892
5967
  .prl-header{display:flex;align-items:center;margin-bottom:10px}
5893
5968
  .prl-phase-chip{font-size:10px;font-weight:800;font-family:var(--mono);letter-spacing:.3px;color:var(--pc,#6366f1);background:rgba(99,102,241,.12);border:1px solid rgba(99,102,241,.35);border-radius:20px;padding:3px 12px;display:inline-block}
5894
- /* Office scene container */
5895
- .prl-office{position:relative;min-height:130px;display:flex;align-items:flex-end;padding-bottom:8px;overflow:hidden}
5896
- /* Floor — gradient wood planks effect */
5897
- .prl-office-floor{position:absolute;bottom:0;left:0;right:0;height:8px;background:linear-gradient(90deg,#1c1a2e,#26243e,#1e1c32,#28263c,#1c1a2e);border-radius:4px;box-shadow:0 -1px 0 rgba(255,255,255,.05)}
5969
+ /* Office scene container — room with wall, floor, plants, art */
5970
+ .prl-office{position:relative;min-height:150px;display:flex;align-items:flex-end;padding:0 0 12px 0;overflow:hidden;border-radius:10px;
5971
+ background:linear-gradient(180deg,#0e0c1e 0%,#13102a 55%,#1a172e 100%)}
5972
+ /* Back wall — subtle panel lines */
5973
+ .prl-office::before{content:"";position:absolute;inset:0;background:
5974
+ repeating-linear-gradient(90deg,transparent,transparent 79px,rgba(255,255,255,.025) 80px),
5975
+ linear-gradient(180deg,rgba(30,28,60,.0) 0%,rgba(30,28,60,.5) 60%,rgba(10,10,30,.8) 100%);pointer-events:none;z-index:0}
5976
+ /* Floor — parquet wood planks */
5977
+ .prl-office-floor{position:absolute;bottom:0;left:0;right:0;height:14px;
5978
+ background:repeating-linear-gradient(90deg,#1c1630 0px,#221e38 40px,#1a1630 41px,#1c1630 80px);
5979
+ border-top:1px solid rgba(99,102,241,.15);box-shadow:0 -2px 8px rgba(0,0,0,.4);z-index:1}
5980
+ /* Window on back wall (top-left) */
5981
+ .prl-office-window{position:absolute;top:6px;left:10px;width:38px;height:50px;background:linear-gradient(180deg,#0d1a2e 0%,#162840 50%,#1e3a5a 100%);border:1.5px solid #2a3a50;border-radius:3px;box-shadow:inset 0 0 12px rgba(96,165,250,.15),0 0 8px rgba(96,165,250,.08);z-index:1;overflow:hidden}
5982
+ .prl-office-window::before{content:"";position:absolute;left:50%;top:0;bottom:0;width:1px;background:rgba(255,255,255,.15)}
5983
+ .prl-office-window::after{content:"";position:absolute;top:50%;left:0;right:0;height:1px;background:rgba(255,255,255,.15)}
5984
+ /* Sunlight ray from window */
5985
+ .prl-office-window-light{position:absolute;top:0;left:10px;width:80px;height:100%;background:linear-gradient(145deg,rgba(96,165,250,.06) 0%,transparent 60%);pointer-events:none;z-index:1}
5986
+ /* Wall art frame (top center-right) */
5987
+ .prl-office-frame{position:absolute;top:8px;right:12px;width:36px;height:28px;border:2px solid #2a2840;border-radius:2px;background:linear-gradient(135deg,#0d0a1e,#1a1030);box-shadow:0 2px 6px rgba(0,0,0,.5);z-index:1;overflow:hidden}
5988
+ .prl-office-frame::before{content:"";position:absolute;inset:3px;border-radius:1px;background:linear-gradient(135deg,#1a0a2e 0%,#0a1a2e 50%,#0e2010 100%);opacity:.9}
5989
+ .prl-office-frame::after{content:"";position:absolute;inset:0;border:1px solid rgba(255,255,255,.06);border-radius:1px}
5990
+ /* Second frame */
5991
+ .prl-office-frame2{position:absolute;top:8px;right:54px;width:24px;height:20px;border:2px solid #2a2840;border-radius:2px;background:linear-gradient(135deg,#0a1020,#1a1820);box-shadow:0 2px 6px rgba(0,0,0,.5);z-index:1}
5992
+ .prl-office-frame2::before{content:"";position:absolute;inset:2px;background:linear-gradient(45deg,#1e1030,#102018);border-radius:1px}
5993
+ /* Plant left */
5994
+ .prl-office-plant{position:absolute;bottom:12px;left:2px;width:20px;height:36px;z-index:2;pointer-events:none}
5995
+ /* Plant right */
5996
+ .prl-office-plant2{position:absolute;bottom:12px;right:2px;width:20px;height:36px;z-index:2;pointer-events:none}
5997
+ /* Ceiling lamp */
5998
+ .prl-office-lamp{position:absolute;top:0;left:50%;transform:translateX(-50%);width:2px;height:14px;background:rgba(255,255,255,.15);z-index:1}
5999
+ .prl-office-lamp::after{content:"";position:absolute;bottom:0;left:50%;transform:translateX(-50%);width:16px;height:8px;border-radius:0 0 12px 12px;background:rgba(99,102,241,.25);box-shadow:0 4px 20px rgba(99,102,241,.3),0 2px 40px rgba(99,102,241,.1)}
5898
6000
  /* Desks row */
5899
6001
  .prl-desks-row{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;position:relative;z-index:2;padding-bottom:8px}
5900
6002
  /* Individual desk card */
@@ -5902,7 +6004,7 @@ input:focus,textarea:focus{border-color:var(--green3)}
5902
6004
  .prl-desk--active{background:#0c0c20;border-color:var(--dc,#6366f1);box-shadow:0 0 20px rgba(99,102,241,.2),0 0 40px rgba(99,102,241,.08)}
5903
6005
  .prl-desk--done{border-color:#1e3a1e;background:#0a150a}
5904
6006
  /* Action bubble above character */
5905
- .prl-action-bubble{font-size:9px;color:#6b7280;font-family:var(--mono);padding:2px 6px;border-radius:8px;background:#111;border:1px solid #2a2a38;min-height:16px;text-align:center;transition:all .3s}
6007
+ .prl-action-bubble{font-size:9px;color:#6b7280;font-family:var(--mono);padding:2px 6px;border-radius:8px;background:#111;border:1px solid #2a2a38;min-height:16px;text-align:center;white-space:normal;word-break:break-word;max-width:88px;line-height:1.3;transition:all .3s}
5906
6008
  .prl-action-bubble--active{color:var(--dc,#6366f1);border-color:var(--dc,#6366f1);background:rgba(99,102,241,.08);animation:parlBubblePop .4s ease}
5907
6009
  @keyframes parlBubblePop{0%{transform:scale(.85);opacity:.5}100%{transform:scale(1);opacity:1}}
5908
6010
  /* Character SVG animations */
@@ -5913,27 +6015,35 @@ input:focus,textarea:focus{border-color:var(--green3)}
5913
6015
  .prl-head{transform-origin:50% 100%;animation:parlHeadNod .8s ease-in-out infinite}
5914
6016
  .prl-doc-hold{transform-origin:center center;animation:parlDocBob .7s ease-in-out infinite}
5915
6017
  /* Agent name label */
5916
- .prl-desk-name{font-size:9px;font-family:var(--mono);font-weight:700;letter-spacing:.3px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:68px}
6018
+ .prl-desk-name{font-size:9px;font-family:var(--mono);font-weight:700;letter-spacing:.3px;text-align:center;white-space:normal;word-break:break-word;max-width:88px;line-height:1.3}
5917
6019
  /* MASTER ORCHESTRATOR */
5918
6020
  .prl-master{position:absolute;bottom:8px;right:8px;display:flex;flex-direction:column;align-items:center;gap:1px;z-index:3;transition:right .8s cubic-bezier(.4,0,.2,1)}
5919
6021
  .prl-master-label{font-size:8px;font-family:var(--mono);font-weight:700;letter-spacing:.4px;text-align:center;text-shadow:0 0 8px currentColor}
5920
6022
  /* Walking animation — smooth left-right patrol */
5921
- @keyframes parlMasterWalk{0%{right:8px}25%{right:calc(100% - 70px)}50%{right:calc(100% - 70px)}75%{right:8px}100%{right:8px}}
5922
- /* Leg swing for natural walking gait */
5923
- @keyframes parlMasterLegL{0%,100%{transform:rotate(0deg)}25%{transform:rotate(25deg)}75%{transform:rotate(-20deg)}}
5924
- @keyframes parlMasterLegR{0%,100%{transform:rotate(0deg)}25%{transform:rotate(-20deg)}75%{transform:rotate(25deg)}}
5925
- /* Arm swing (opposite to legs) */
5926
- @keyframes parlMasterArmSwing{0%,100%{transform:rotate(0deg)}25%{transform:rotate(-18deg)}75%{transform:rotate(18deg)}}
5927
- /* Head bob while walking */
5928
- @keyframes parlMasterBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-2px)}}
5929
- .prl-master-walk{animation:parlMasterWalk 4s ease-in-out infinite}
5930
- .prl-master-walk .prl-master-leg-l{transform-origin:50% 0;animation:parlMasterLegL .5s ease-in-out infinite}
5931
- .prl-master-walk .prl-master-leg-r{transform-origin:50% 0;animation:parlMasterLegR .5s ease-in-out infinite}
5932
- .prl-master-walk .prl-master-arm-l{transform-origin:50% 0;animation:parlMasterArmSwing .5s ease-in-out infinite}
5933
- .prl-master-walk .prl-master-arm-r{transform-origin:50% 0;animation:parlMasterArmSwing .5s ease-in-out infinite reverse}
5934
- /* R2 supervise: gentle idle bob at active desk */
5935
- @keyframes parlMasterSupervise{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
5936
- .prl-master-supervise{animation:parlMasterSupervise 2s ease-in-out infinite}
6023
+ /* Executive walk: slow measured patrol left↔right */
6024
+ @keyframes parlMasterWalk{0%{right:8px;transform:scaleX(1)}35%{right:calc(100% - 70px);transform:scaleX(1)}40%{right:calc(100% - 70px);transform:scaleX(-1)}75%{right:8px;transform:scaleX(-1)}80%{right:8px;transform:scaleX(1)}100%{right:8px;transform:scaleX(1)}}
6025
+ /* Legs: slow dignified stride */
6026
+ @keyframes parlMasterLegL{0%,100%{transform:rotate(0deg)}25%{transform:rotate(18deg)}75%{transform:rotate(-14deg)}}
6027
+ @keyframes parlMasterLegR{0%,100%{transform:rotate(0deg)}25%{transform:rotate(-14deg)}75%{transform:rotate(18deg)}}
6028
+ /* Arms: clipboard-holding executive swing — tight, not flailing */
6029
+ @keyframes parlMasterArmL{0%,100%{transform:rotate(0deg)}50%{transform:rotate(-12deg)}}
6030
+ @keyframes parlMasterArmR{0%,100%{transform:rotate(0deg)}50%{transform:rotate(8deg)}}
6031
+ /* Clipboard bob while walking — authority gesture */
6032
+ @keyframes parlMasterClipboard{0%,100%{transform:rotate(0deg) translateY(0)}30%{transform:rotate(-6deg) translateY(-1px)}70%{transform:rotate(4deg) translateY(1px)}}
6033
+ /* Whole body: subtle sway of a confident executive */
6034
+ @keyframes parlMasterBodySway{0%,100%{transform:translateY(0) rotate(0deg)}25%{transform:translateY(-2px) rotate(.6deg)}75%{transform:translateY(-1px) rotate(-.5deg)}}
6035
+ .prl-master-walk{animation:parlMasterWalk 8s cubic-bezier(.45,0,.55,1) infinite}
6036
+ .prl-master-walk .prl-master-leg-l{transform-origin:50% 0;animation:parlMasterLegL 1s ease-in-out infinite}
6037
+ .prl-master-walk .prl-master-leg-r{transform-origin:50% 0;animation:parlMasterLegR 1s ease-in-out infinite}
6038
+ .prl-master-walk .prl-master-arm-l{transform-origin:50% 0;animation:parlMasterArmL 1.2s ease-in-out infinite}
6039
+ .prl-master-walk .prl-master-arm-r{transform-origin:50% 0;animation:parlMasterArmR 1.2s ease-in-out infinite}
6040
+ /* R2 supervise: executive pacing — short back-and-forth at the active desk */
6041
+ @keyframes parlMasterSupervise{0%{right:8px}30%{right:28px}60%{right:10px}80%{right:24px}100%{right:8px}}
6042
+ .prl-master-supervise{animation:parlMasterSupervise 4s ease-in-out infinite}
6043
+ .prl-master-supervise .prl-master-leg-l{transform-origin:50% 0;animation:parlMasterLegL 1s ease-in-out infinite}
6044
+ .prl-master-supervise .prl-master-leg-r{transform-origin:50% 0;animation:parlMasterLegR 1s ease-in-out infinite}
6045
+ .prl-master-supervise .prl-master-arm-l{transform-origin:50% 0;animation:parlMasterArmL 1.2s ease-in-out infinite}
6046
+ .prl-master-supervise .prl-master-arm-r{transform-origin:50% 0;animation:parlMasterArmR 1.2s ease-in-out infinite}
5937
6047
  /* Flying documents: smooth parabolic arc between agents */
5938
6048
  .prl-fly-container{position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden;z-index:4}
5939
6049
  @keyframes parlFlyDoc{0%{transform:translate(0,70px) scale(.6) rotate(-20deg);opacity:0}15%{opacity:1;transform:translate(8%,20px) scale(.9) rotate(-5deg)}40%{transform:translate(30%,-15px) scale(1.1) rotate(3deg);opacity:1}65%{transform:translate(60%,5px) scale(.95) rotate(8deg);opacity:.9}85%{opacity:.6}100%{transform:translate(90%,60px) scale(.6) rotate(15deg);opacity:0}}