nothumanallowed 13.5.8 → 13.5.9

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.8",
3
+ "version": "13.5.9",
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.8';
8
+ export const VERSION = '13.5.9';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -3310,6 +3310,7 @@ var studioState = {
3310
3310
  var studioAbortController = null;
3311
3311
  var parlActiveAgent = null; // active agent label during parliament streaming
3312
3312
  var parlDoneAgents = {}; // set of completed agent labels during parliament
3313
+ var _parlPersistHtml = null; // persists parliament block HTML across tab navigations
3313
3314
 
3314
3315
  function stopStudio() {
3315
3316
  if (!studioState.running) return;
@@ -3624,10 +3625,10 @@ function officeRoomDecor() {
3624
3625
  // Projects grid positions onto an isometric plane.
3625
3626
  // iso(col, row) → {x, y} pixel coordinates in the scene container.
3626
3627
  // Characters are positioned with position:absolute, scale by row for depth.
3627
- var ISO_TILE_W = 72;
3628
- var ISO_TILE_H = 36;
3629
- var ISO_ORIGIN_X = 300;
3630
- var ISO_ORIGIN_Y = 60;
3628
+ var ISO_TILE_W = 80;
3629
+ var ISO_TILE_H = 40;
3630
+ var ISO_ORIGIN_X = 500;
3631
+ var ISO_ORIGIN_Y = 80;
3631
3632
  function isoProject(col, row) {
3632
3633
  return {
3633
3634
  x: ISO_ORIGIN_X + (col - row) * (ISO_TILE_W / 2),
@@ -3635,118 +3636,148 @@ function isoProject(col, row) {
3635
3636
  };
3636
3637
  }
3637
3638
 
3638
- // Full bright office scene SVG background
3639
+ // Full bright office scene — wide SVG background (1000x560)
3639
3640
  function isoFloorSvg(cols, rows) {
3640
- var w = 640; var h = 320;
3641
- var out = \x27<svg viewBox="0 0 \x27+w+\x27 \x27+h+\x27" width="\x27+w+\x27" height="\x27+h+\x27" xmlns="http://www.w3.org/2000/svg" style="position:absolute;top:0;left:0;pointer-events:none;z-index:0">\x27;
3642
-
3643
- // ── BACK WALL (white/cream) ──────────────────────────────────────────
3644
- out += \x27<polygon points="0,100 320,20 320,120 0,200" fill="#f5f3ee"/>\x27;
3645
- out += \x27<polygon points="320,20 640,100 640,200 320,120" fill="#edeae3"/>\x27;
3646
- out += \x27<line x1="0" y1="100" x2="320" y2="20" stroke="#ccc" stroke-width="1.5"/>\x27;
3647
- out += \x27<line x1="320" y1="20" x2="640" y2="100" stroke="#bbb" stroke-width="1.5"/>\x27;
3648
- // Wall corner vertical line
3649
- out += \x27<line x1="320" y1="20" x2="320" y2="120" stroke="#c8c4bc" stroke-width="1"/>\x27;
3650
-
3651
- // ── WINDOWS — 3 centered on left wall ────────────────────────────────
3652
- // Win L1
3653
- out += \x27<polygon points="30,122 90,102 90,155 30,175" fill="#d0eeff" stroke="#aac8e8" stroke-width="1"/>\x27;
3654
- out += \x27<line x1="60,112" y1="60" x2="60" y2="130" stroke="#aac8e8" stroke-width=".8"/>\x27;
3655
- out += \x27<line x1="30,148" y1="148" x2="90" y2="128" stroke="#aac8e8" stroke-width=".8"/>\x27;
3656
- out += \x27<polygon points="30,122 90,102 90,108 30,128" fill="#b8ddf8" opacity=".4"/>\x27;
3657
- out += \x27<polygon points="30,122 90,102 90,155 30,175" fill="rgba(200,230,255,.12)"/>\x27;
3658
- // Win L2 (center-left)
3659
- out += \x27<polygon points="110,102 175,80 175,132 110,154" fill="#d0eeff" stroke="#aac8e8" stroke-width="1"/>\x27;
3660
- out += \x27<polygon points="110,102 175,80 175,88 110,110" fill="#b8ddf8" opacity=".4"/>\x27;
3661
- out += \x27<line x1="142" y1="91" x2="142" y2="143" stroke="#aac8e8" stroke-width=".8"/>\x27;
3662
- out += \x27<line x1="110" y1="128" x2="175" y2="106" stroke="#aac8e8" stroke-width=".8"/>\x27;
3663
- out += \x27<polygon points="110,102 175,80 175,132 110,154" fill="rgba(200,230,255,.10)"/>\x27;
3664
- // Win L3 (center)
3665
- out += \x27<polygon points="195,88 255,68 255,118 195,138" fill="#d0eeff" stroke="#aac8e8" stroke-width="1"/>\x27;
3666
- out += \x27<polygon points="195,88 255,68 255,76 195,96" fill="#b8ddf8" opacity=".4"/>\x27;
3667
- out += \x27<line x1="225" y1="78" x2="225" y2="128" stroke="#aac8e8" stroke-width=".8"/>\x27;
3668
- out += \x27<line x1="195" y1="113" x2="255" y2="93" stroke="#aac8e8" stroke-width=".8"/>\x27;
3669
- // Sunlight shafts from windows
3670
- out += \x27<polygon points="50,155 90,140 120,260 80,275" fill="rgba(255,250,220,.06)"/>\x27;
3671
- out += \x27<polygon points="130,132 175,116 200,260 155,275" fill="rgba(255,250,220,.05)"/>\x27;
3672
- out += \x27<polygon points="210,116 255,100 270,260 225,275" fill="rgba(255,250,220,.04)"/>\x27;
3673
-
3674
- // ── ART on left wall ────────────────────────────────────────────────
3675
- // Frame 1 (small painting near top-right of left wall)
3676
- out += \x27<polygon points="275,72 310,60 310,90 275,102" fill="#e8e4dc" stroke="#bbb" stroke-width="1"/>\x27;
3677
- out += \x27<polygon points="278,74 307,63 307,88 278,99" fill="#7a9ed4"/>\x27;
3678
- out += \x27<polygon points="285,77 303,70 303,84 285,91" fill="#a8c4e8"/>\x27;
3679
- out += \x27<ellipse cx="294" cy="80" rx="5" ry="4" fill="#fff" opacity=".5"/>\x27;
3680
-
3681
- // ── PLANT (bottom-left corner) ───────────────────────────────────────
3682
- out += \x27<ellipse cx="30" cy="188" rx="10" ry="5" fill="#2d4a1e" opacity=".7"/>\x27;
3683
- out += \x27<rect x="25" y="178" width="10" height="10" rx="2" fill="#5a3a1a"/>\x27;
3684
- out += \x27<path d="M30 178 C25 165 18 155 22 148 C26 142 30 148 30 178" fill="#3a7a1e"/>\x27;
3685
- out += \x27<path d="M30 178 C35 162 42 155 38 148 C34 142 30 150 30 178" fill="#4a8a26"/>\x27;
3686
- out += \x27<path d="M30 175 C22 168 16 160 18 153" stroke="#3a7a1e" stroke-width="2" fill="none" stroke-linecap="round"/>\x27;
3687
- out += \x27<path d="M30 170 C38 165 44 158 42 151" stroke="#4a8a26" stroke-width="2" fill="none" stroke-linecap="round"/>\x27;
3688
-
3689
- // ── CEILING CHANDELIER with glow ─────────────────────────────────────
3690
- out += \x27<line x1="320" y1="0" x2="320" y2="18" stroke="#999" stroke-width="2"/>\x27;
3691
- // Chandelier body
3692
- out += \x27<ellipse cx="320" cy="18" rx="24" ry="7" fill="#d4c88a" stroke="#b8a860" stroke-width="1.5"/>\x27;
3693
- out += \x27<ellipse cx="320" cy="22" rx="20" ry="5" fill="#e8d898"/>\x27;
3694
- // Bulbs hanging down
3695
- out += \x27<circle cx="305" cy="28" r="5" fill="#fffbe8" filter="url(#glow)"/>\x27;
3696
- out += \x27<circle cx="320" cy="26" r="6" fill="#fffbe8" filter="url(#glow)"/>\x27;
3697
- out += \x27<circle cx="335" cy="28" r="5" fill="#fffbe8" filter="url(#glow)"/>\x27;
3698
- out += \x27<line x1="305" y1="22" x2="305" y2="28" stroke="#aaa" stroke-width=".8"/>\x27;
3699
- out += \x27<line x1="320" y1="22" x2="320" y2="26" stroke="#aaa" stroke-width=".8"/>\x27;
3700
- out += \x27<line x1="335" y1="22" x2="335" y2="28" stroke="#aaa" stroke-width=".8"/>\x27;
3701
- // Light cone glow on floor/walls
3702
- out += \x27<radialGradient id="chandelierGlow" cx="50%" cy="0%" r="60%"><stop offset="0%" stop-color="rgba(255,245,180,.22)"/><stop offset="100%" stop-color="rgba(255,245,180,0)"/></radialGradient>\x27;
3703
- out += \x27<filter id="glow"><feGaussianBlur stdDeviation="3" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>\x27;
3704
- out += \x27<ellipse cx="320" cy="180" rx="200" ry="120" fill="url(#chandelierGlow)"/>\x27;
3705
-
3706
- // ── PARQUET FLOOR long narrow planks ───────────────────────────────
3707
- // Draw rectangular plank tiles in iso projection
3708
- var PLANK_W = ISO_TILE_W; var PLANK_H = ISO_TILE_H;
3709
- var plankColors = [\x27#b5854a\x27,\x27#a8783c\x27,\x27#bf9055\x27,\x27#c49a60\x27,\x27#a07234\x27];
3641
+ var W = 1000; var H = 560;
3642
+ var out = \x27<svg viewBox="0 0 \x27+W+\x27 \x27+H+\x27" width="\x27+W+\x27" height="\x27+H+\x27" xmlns="http://www.w3.org/2000/svg" style="position:absolute;top:0;left:0;pointer-events:none;z-index:0">\x27;
3643
+
3644
+ // ── DEFS ────────────────────────────────────────────────────────────
3645
+ out += \x27<defs>\x27;
3646
+ out += \x27<filter id="bGlow" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="6" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>\x27;
3647
+ out += \x27<radialGradient id="lampGlow" cx="50%" cy="20%" r="70%"><stop offset="0%" stop-color="rgba(255,248,200,.28)"/><stop offset="100%" stop-color="rgba(255,248,200,0)"/></radialGradient>\x27;
3648
+ out += \x27<linearGradient id="wallL" x1="0" y1="0" x2="1" y2="0"><stop offset="0%" stop-color="#f8f6f0"/><stop offset="100%" stop-color="#ede9e0"/></linearGradient>\x27;
3649
+ out += \x27<linearGradient id="wallR" x1="0" y1="0" x2="1" y2="0"><stop offset="0%" stop-color="#e8e4dc"/><stop offset="100%" stop-color="#ddd8ce"/></linearGradient>\x27;
3650
+ out += \x27</defs>\x27;
3651
+
3652
+ // ── WALLS ────────────────────────────────────────────────────────────
3653
+ // Left wall (back-left)
3654
+ out += \x27<polygon points="0,200 500,40 500,280 0,440" fill="url(#wallL)"/>\x27;
3655
+ // Right wall (back-right)
3656
+ out += \x27<polygon points="500,40 1000,200 1000,440 500,280" fill="url(#wallR)"/>\x27;
3657
+ // Wall top ridge
3658
+ out += \x27<line x1="0" y1="200" x2="500" y2="40" stroke="#c8c0b0" stroke-width="2"/>\x27;
3659
+ out += \x27<line x1="500" y1="40" x2="1000" y2="200" stroke="#bbb0a0" stroke-width="2"/>\x27;
3660
+ out += \x27<line x1="500" y1="40" x2="500" y2="280" stroke="#c0b8a8" stroke-width="1.5"/>\x27;
3661
+
3662
+ // ── WINDOWS on left wall 3 evenly spaced ──────────────────────────
3663
+ // Helper: window at left-wall position (xL,yTop)→(xR,yTop-slope)
3664
+ // Left wall goes from (0,200)→(500,40), slope = -160/500 per x
3665
+ // Window 1
3666
+ out += \x27<polygon points="60,232 160,206 160,272 60,300" fill="#ceeaff" stroke="#90bcd8" stroke-width="1.5"/>\x27;
3667
+ out += \x27<polygon points="60,232 160,206 160,213 60,239" fill="#a8d8f8" opacity=".6"/>\x27;
3668
+ out += \x27<line x1="60" y1="266" x2="160" y2="239" stroke="#90bcd8" stroke-width="1"/>\x27;
3669
+ out += \x27<line x1="110" y1="219" x2="110" y2="286" stroke="#90bcd8" stroke-width="1"/>\x27;
3670
+ out += \x27<polygon points="60,232 160,206 160,272 60,300" fill="rgba(180,220,255,.1)"/>\x27;
3671
+ // Window 2
3672
+ out += \x27<polygon points="200,178 300,152 300,218 200,246" fill="#ceeaff" stroke="#90bcd8" stroke-width="1.5"/>\x27;
3673
+ out += \x27<polygon points="200,178 300,152 300,159 200,185" fill="#a8d8f8" opacity=".6"/>\x27;
3674
+ out += \x27<line x1="200" y1="212" x2="300" y2="185" stroke="#90bcd8" stroke-width="1"/>\x27;
3675
+ out += \x27<line x1="250" y1="165" x2="250" y2="232" stroke="#90bcd8" stroke-width="1"/>\x27;
3676
+ out += \x27<polygon points="200,178 300,152 300,218 200,246" fill="rgba(180,220,255,.1)"/>\x27;
3677
+ // Window 3
3678
+ out += \x27<polygon points="340,126 440,100 440,166 340,192" fill="#ceeaff" stroke="#90bcd8" stroke-width="1.5"/>\x27;
3679
+ out += \x27<polygon points="340,126 440,100 440,107 340,133" fill="#a8d8f8" opacity=".6"/>\x27;
3680
+ out += \x27<line x1="340" y1="159" x2="440" y2="133" stroke="#90bcd8" stroke-width="1"/>\x27;
3681
+ out += \x27<line x1="390" y1="113" x2="390" y2="179" stroke="#90bcd8" stroke-width="1"/>\x27;
3682
+ out += \x27<polygon points="340,126 440,100 440,166 340,192" fill="rgba(180,220,255,.1)"/>\x27;
3683
+ // Sun shafts
3684
+ out += \x27<polygon points="80,300 160,272 190,540 110,560" fill="rgba(255,248,200,.07)"/>\x27;
3685
+ out += \x27<polygon points="215,246 300,218 320,540 235,560" fill="rgba(255,248,200,.06)"/>\x27;
3686
+ out += \x27<polygon points="352,192 440,166 455,540 367,560" fill="rgba(255,248,200,.05)"/>\x27;
3687
+
3688
+ // ── PAINTING on left wall (between W2 and W3) ────────────────────────
3689
+ out += \x27<polygon points="463,112 490,104 490,132 463,140" fill="#e8e2d8" stroke="#c0b090" stroke-width="1.5"/>\x27;
3690
+ out += \x27<polygon points="466,114 488,107 488,130 466,137" fill="#5080b0"/>\x27;
3691
+ out += \x27<polygon points="469,116 488,110 488,120 469,123" fill="#7aa0c8"/>\x27;
3692
+ out += \x27<ellipse cx="478" cy="120" rx="5" ry="4" fill="#fff" opacity=".35"/>\x27;
3693
+
3694
+ // ── PLANT right wall corner ─────────────────────────────────────────
3695
+ out += \x27<ellipse cx="920" cy="360" rx="14" ry="7" fill="#2d5018" opacity=".6"/>\x27;
3696
+ out += \x27<rect x="912" y="348" width="14" height="14" rx="3" fill="#7a4a20"/>\x27;
3697
+ out += \x27<path d="M919 348 C912 328 900 312 905 300 C910 290 919 300 919 348" fill="#3a8020"/>\x27;
3698
+ out += \x27<path d="M919 348 C926 328 938 315 933 302 C928 292 919 303 919 348" fill="#4a9228"/>\x27;
3699
+ out += \x27<path d="M919 342 C908 332 900 322 902 312" stroke="#3a8020" stroke-width="2.5" fill="none" stroke-linecap="round"/>\x27;
3700
+ out += \x27<path d="M919 336 C930 326 938 318 936 306" stroke="#4a9228" stroke-width="2.5" fill="none" stroke-linecap="round"/>\x27;
3701
+
3702
+ // ── CHANDELIER ────────────────────────────────────────────────────────
3703
+ out += \x27<line x1="500" y1="0" x2="500" y2="30" stroke="#aaa" stroke-width="3"/>\x27;
3704
+ out += \x27<ellipse cx="500" cy="30" rx="38" ry="11" fill="#d8c870" stroke="#b8a850" stroke-width="2"/>\x27;
3705
+ out += \x27<ellipse cx="500" cy="36" rx="30" ry="8" fill="#ece090"/>\x27;
3706
+ out += \x27<line x1="478" y1="36" x2="478" y2="46" stroke="#aaa" stroke-width="1.2"/>\x27;
3707
+ out += \x27<line x1="500" y1="36" x2="500" y2="42" stroke="#aaa" stroke-width="1.2"/>\x27;
3708
+ out += \x27<line x1="522" y1="36" x2="522" y2="46" stroke="#aaa" stroke-width="1.2"/>\x27;
3709
+ out += \x27<circle cx="478" cy="50" r="8" fill="#fffbe0" filter="url(#bGlow)"/>\x27;
3710
+ out += \x27<circle cx="500" cy="46" r="10" fill="#fffbe0" filter="url(#bGlow)"/>\x27;
3711
+ out += \x27<circle cx="522" cy="50" r="8" fill="#fffbe0" filter="url(#bGlow)"/>\x27;
3712
+ // Light glow on scene
3713
+ out += \x27<ellipse cx="500" cy="320" rx="360" ry="220" fill="url(#lampGlow)"/>\x27;
3714
+
3715
+ // ── PARQUET FLOOR ──────────────────────────────────────────────────────
3716
+ var plankCols = [\x27#c8924a\x27,\x27#b8823c\x27,\x27#d4a055\x27,\x27#be9248\x27,\x27#a87838\x27];
3710
3717
  for (var r2 = 0; r2 < rows; r2++) {
3711
3718
  for (var c2 = 0; c2 < cols; c2++) {
3712
3719
  var pp = isoProject(c2, r2);
3713
- var ptx = pp.x; var pty = pp.y + 110;
3714
- var pIdx = (r2 * 3 + c2) % plankColors.length;
3715
- var pFill = plankColors[pIdx];
3716
- var ppts = ptx+\x27,\x27+pty+\x27 \x27+(ptx+PLANK_W/2)+\x27,\x27+(pty+PLANK_H/2)+\x27 \x27+ptx+\x27,\x27+(pty+PLANK_H)+\x27 \x27+(ptx-PLANK_W/2)+\x27,\x27+(pty+PLANK_H/2);
3717
- out += \x27<polygon points="\x27+ppts+\x27" fill="\x27+pFill+\x27" stroke="#8a6028" stroke-width=".7" opacity=".95"/>\x27;
3718
- // Plank grain lines (long horizontal across plank)
3719
- out += \x27<line x1="\x27+(ptx-PLANK_W/2+4)+\x27" y1="\x27+(pty+PLANK_H/2)+\x27" x2="\x27+(ptx+PLANK_W/2-4)+\x27" y2="\x27+(pty+PLANK_H/2)+\x27" stroke="rgba(0,0,0,.06)" stroke-width=".5"/>\x27;
3720
+ var ptx = pp.x; var pty = pp.y + 120;
3721
+ var pFill = plankCols[(r2*3+c2) % plankCols.length];
3722
+ var ppts = ptx+\x27,\x27+pty+\x27 \x27+(ptx+ISO_TILE_W/2)+\x27,\x27+(pty+ISO_TILE_H/2)+\x27 \x27+ptx+\x27,\x27+(pty+ISO_TILE_H)+\x27 \x27+(ptx-ISO_TILE_W/2)+\x27,\x27+(pty+ISO_TILE_H/2);
3723
+ out += \x27<polygon points="\x27+ppts+\x27" fill="\x27+pFill+\x27" stroke="#906820" stroke-width=".8"/>\x27;
3724
+ // long grain line along the plank
3725
+ out += \x27<line x1="\x27+(ptx-ISO_TILE_W/2+5)+\x27" y1="\x27+(pty+ISO_TILE_H/2)+\x27" x2="\x27+(ptx+ISO_TILE_W/2-5)+\x27" y2="\x27+(pty+ISO_TILE_H/2)+\x27" stroke="rgba(0,0,0,.08)" stroke-width=".6"/>\x27;
3720
3726
  }
3721
3727
  }
3722
- // Floor highlight (lamp reflection)
3723
- out += \x27<ellipse cx="320" cy="220" rx="90" ry="30" fill="rgba(255,250,200,.08)"/>\x27;
3728
+ out += \x27<ellipse cx="500" cy="380" rx="120" ry="40" fill="rgba(255,248,200,.1)"/>\x27;
3724
3729
 
3725
3730
  out += \x27</svg>\x27;
3726
3731
  return out;
3727
3732
  }
3728
- // Small isometric desk object at iso position — bright wood
3733
+
3734
+ // Isometric desk — proper 3D look: flat top surface + two visible faces + monitor + keyboard
3729
3735
  function isoDeskSvg(x, y, accentColor) {
3730
3736
  var ac = accentColor || \x27#888\x27;
3731
- var doneDesk = ac === \x27#22c55e\x27;
3732
- return \x27<svg viewBox="0 0 72 44" width="72" height="44" xmlns="http://www.w3.org/2000/svg" style="position:absolute;left:\x27+(x-36)+\x27px;top:\x27+(y+8)+\x27px;z-index:\x27+(Math.round(y))+\x27;pointer-events:none">\x27+
3733
- // Desk top face warm wood
3734
- \x27<polygon points="36,4 62,18 36,32 10,18" fill="#d4a855" stroke="#b8893a" stroke-width="1"/>\x27+
3735
- \x27<polygon points="36,4 62,18 36,32 10,18" fill="rgba(255,255,255,.08)"/>\x27+
3736
- // Grain lines on top
3737
- \x27<line x1="22" y1="18" x2="50" y2="10" stroke="rgba(0,0,0,.1)" stroke-width=".8"/>\x27+
3738
- \x27<line x1="22" y1="22" x2="50" y2="14" stroke="rgba(0,0,0,.07)" stroke-width=".8"/>\x27+
3739
- // Desk right face
3740
- \x27<polygon points="62,18 62,36 36,50 36,32" fill="#a8783c" stroke="#8a5c28" stroke-width=".8"/>\x27+
3741
- // Desk left face
3742
- \x27<polygon points="10,18 36,32 36,50 10,36" fill="#c49050" stroke="#9e7234" stroke-width=".8"/>\x27+
3743
- // Monitor on desk light screen
3744
- \x27<polygon points="28,10 44,16 44,26 28,20" fill="#1e2840" stroke="\x27+ac+\x27" stroke-width="1.2"/>\x27+
3745
- \x27<polygon points="29,11 43,17 43,25 29,19" fill="\x27+(doneDesk?\x27#0d2010\x27:\x27#0d1a2e\x27)+\x27"/>\x27+
3746
- // Screen glow lines
3747
- \x27<line x1="31" y1="14" x2="41" y2="18" stroke="\x27+ac+\x27" stroke-width=".9" opacity=".8"/>\x27+
3748
- \x27<line x1="31" y1="17" x2="40" y2="20" stroke="\x27+ac+\x27" stroke-width=".9" opacity=".5"/>\x27+
3749
- \x27<line x1="31" y1="20" x2="39" y2="23" stroke="\x27+ac+\x27" stroke-width=".9" opacity=".3"/>\x27+
3737
+ var isDone = ac === \x27#22c55e\x27;
3738
+ var isActive = ac === \x27#6366f1\x27;
3739
+ var screenFill = isDone ? \x27#0a2010\x27 : (isActive ? \x27#0d102a\x27 : \x27#111828\x27);
3740
+ var screenGlow = isDone ? \x27#22c55e\x27 : (isActive ? \x27#818cf8\x27 : \x27#4466aa\x27);
3741
+ // Desk is 90x56 viewBox — wide enough to look like a real desk
3742
+ return \x27<svg viewBox="0 0 90 56" width="90" height="56" xmlns="http://www.w3.org/2000/svg" style="position:absolute;left:\x27+(x-45)+\x27px;top:\x27+(y+4)+\x27px;z-index:\x27+(Math.round(y))+\x27;pointer-events:none">\x27+
3743
+ // ── DESK LEGS (4 corners, visible as small rectangles) ──
3744
+ \x27<rect x="14" y="42" width="5" height="10" rx="1" fill="#8a5c20"/>\x27+
3745
+ \x27<rect x="56" y="47" width="5" height="8" rx="1" fill="#8a5c20"/>\x27+
3746
+ \x27<rect x="70" y="40" width="5" height="8" rx="1" fill="#7a4e18"/>\x27+
3747
+ \x27<rect x="28" y="36" width="5" height="8" rx="1" fill="#7a4e18"/>\x27+
3748
+ // ── DESK TOP SURFACE (iso diamond) ──
3749
+ \x27<polygon points="45,4 78,21 45,38 12,21" fill="#d4a448" stroke="#b88830" stroke-width="1.2"/>\x27+
3750
+ // wood grain on top
3751
+ \x27<line x1="28" y1="21" x2="62" y2="12" stroke="rgba(0,0,0,.09)" stroke-width=".9"/>\x27+
3752
+ \x27<line x1="24" y1="26" x2="58" y2="17" stroke="rgba(0,0,0,.07)" stroke-width=".9"/>\x27+
3753
+ \x27<line x1="32" y1="17" x2="66" y2="8" stroke="rgba(0,0,0,.06)" stroke-width=".7"/>\x27+
3754
+ // shine
3755
+ \x27<polygon points="45,4 78,21 74,23 45,8 16,23 12,21" fill="rgba(255,255,255,.12)"/>\x27+
3756
+ // ── RIGHT FACE ──
3757
+ \x27<polygon points="78,21 78,36 45,53 45,38" fill="#a87028" stroke="#906018" stroke-width=".8"/>\x27+
3758
+ // ── LEFT FACE ──
3759
+ \x27<polygon points="12,21 45,38 45,53 12,36" fill="#c08838" stroke="#a07028" stroke-width=".8"/>\x27+
3760
+ // ── MONITOR — proper isometric screen ──
3761
+ // Stand
3762
+ \x27<polygon points="54,14 62,18 62,22 54,18" fill="#555" stroke="#333" stroke-width=".6"/>\x27+
3763
+ // Screen back
3764
+ \x27<polygon points="54,4 72,12 72,24 54,16" fill="#2a2a3a" stroke="#222" stroke-width=".8"/>\x27+
3765
+ // Screen front (bezel)
3766
+ \x27<polygon points="55,5 71,13 71,23 55,15" fill="#1a1a28"/>\x27+
3767
+ // Screen content
3768
+ \x27<polygon points="57,7 69,13 69,21 57,15" fill="\x27+screenFill+\x27"/>\x27+
3769
+ \x27<line x1="58" y1="10" x2="68" y2="14" stroke="\x27+screenGlow+\x27" stroke-width="1" opacity=".9"/>\x27+
3770
+ \x27<line x1="58" y1="13" x2="67" y2="17" stroke="\x27+screenGlow+\x27" stroke-width=".9" opacity=".6"/>\x27+
3771
+ \x27<line x1="58" y1="16" x2="66" y2="19" stroke="\x27+screenGlow+\x27" stroke-width=".8" opacity=".4"/>\x27+
3772
+ // ── KEYBOARD ──
3773
+ \x27<polygon points="24,25 44,32 40,36 20,29" fill="#ddd" stroke="#bbb" stroke-width=".6"/>\x27+
3774
+ \x27<line x1="24" y1="28" x2="44" y2="34" stroke="#aaa" stroke-width=".5"/>\x27+
3775
+ \x27<line x1="28" y1="26" x2="28" y2="30" stroke="#aaa" stroke-width=".4"/>\x27+
3776
+ \x27<line x1="33" y1="28" x2="33" y2="32" stroke="#aaa" stroke-width=".4"/>\x27+
3777
+ \x27<line x1="38" y1="30" x2="38" y2="34" stroke="#aaa" stroke-width=".4"/>\x27+
3778
+ // ── PAPERS on desk ──
3779
+ \x27<polygon points="14,24 28,29 25,34 11,29" fill="#f8f6ee" stroke="#ddd" stroke-width=".6" transform="rotate(-6 20 29)"/>\x27+
3780
+ \x27<polygon points="15,23 29,28 26,33 12,28" fill="#fff" stroke="#eee" stroke-width=".5" transform="rotate(-3 21 28)"/>\x27+
3750
3781
  \x27</svg>\x27;
3751
3782
  }
3752
3783
  // Isometric JRPG sprite character — top-down 3/4 perspective, Pokemon-style
@@ -4438,8 +4469,9 @@ async function runStudio() {
4438
4469
  // Keep attachmentContext — it was loaded before hitting Run
4439
4470
  parlActiveAgent = null;
4440
4471
  parlDoneAgents = {};
4472
+ _parlPersistHtml = null; // clear persisted parliament for fresh run
4441
4473
  var parlBlockEl = document.getElementById('studioParliamentBlock');
4442
- if (parlBlockEl) parlBlockEl.style.display = 'none';
4474
+ if (parlBlockEl) { parlBlockEl.innerHTML = ''; parlBlockEl.style.display = 'none'; }
4443
4475
  renderStudioNodes();
4444
4476
  renderStudioLog();
4445
4477
  renderStudioResult();
@@ -5248,6 +5280,9 @@ async function runStudio() {
5248
5280
  flyingDocHtml += \x27</div>\x27;
5249
5281
  }
5250
5282
 
5283
+ // Persist across tab navigations (snapshot — animations won\x27t replay but structure is preserved)
5284
+ if (pb.innerHTML && pb.innerHTML.length < 60000) { _parlPersistHtml = pb.innerHTML; }
5285
+
5251
5286
  }
5252
5287
 
5253
5288
  // Show initial R1 block and scroll into view
@@ -5414,6 +5449,7 @@ async function runStudio() {
5414
5449
  }
5415
5450
  }
5416
5451
  if (parlFinal && parlFinal.style.display !== 'none' && parlFinal.innerHTML) {
5452
+ _parlPersistHtml = parlFinal.innerHTML; // persist so tab nav doesn't lose it
5417
5453
  doScroll(parlFinal);
5418
5454
  setTimeout(function(){ doScroll(resEl); }, 2200);
5419
5455
  } else if (resEl) {
@@ -5785,6 +5821,12 @@ function runStudioStep(idx, node, task, context, stepDef, signal) {
5785
5821
  }
5786
5822
 
5787
5823
  function renderStudio(el) {
5824
+ // Persist parliament block across tab navigations
5825
+ var existingParl = document.getElementById('studioParliamentBlock');
5826
+ if (existingParl && existingParl.innerHTML.trim()) {
5827
+ _parlPersistHtml = existingParl.innerHTML;
5828
+ }
5829
+
5788
5830
  var examplesHtml = STUDIO_EXAMPLES.map(function(ex) {
5789
5831
  return '<button class="studio-example-btn" onclick="document.getElementById(\\'studioTaskInput\\').value=' + JSON.stringify(ex) + '">' + esc(ex.slice(0, 52)) + (ex.length > 52 ? '...' : '') + '</button>';
5790
5832
  }).join('');
@@ -5947,9 +5989,18 @@ function renderStudio(el) {
5947
5989
  renderStudioLog();
5948
5990
  renderStudioResult();
5949
5991
  renderStudioSessionsBar();
5950
- studioTokens = {in:0,out:0};
5992
+ // Restore token bar (preserve counts across re-renders)
5993
+ studioUpdateTokenBar();
5951
5994
  // Restore pipeline from state
5952
5995
  renderBuilderPipeline();
5996
+ // Restore parliament block if it was visible before tab navigation
5997
+ if (_parlPersistHtml) {
5998
+ var parlRestoreEl = document.getElementById('studioParliamentBlock');
5999
+ if (parlRestoreEl) {
6000
+ parlRestoreEl.innerHTML = _parlPersistHtml;
6001
+ parlRestoreEl.style.display = 'block';
6002
+ }
6003
+ }
5953
6004
  }
5954
6005
 
5955
6006
  // ---- STUDIO SIDEBAR TAB ----