nothumanallowed 13.5.11 → 13.5.13

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.11",
3
+ "version": "13.5.13",
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.11';
8
+ export const VERSION = '13.5.13';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -3918,164 +3918,136 @@ function renderStudioNodes() {
3918
3918
  : (doneCount===totalCount && totalCount>0 ? \x27Workflow completato\x27 : \x27Workflow pianificato\x27);
3919
3919
  var phaseColor2 = hasActive ? \x27#6366f1\x27 : (doneCount===totalCount && totalCount>0 ? \x27#22c55e\x27 : \x27#6b7280\x27);
3920
3920
 
3921
- // ── Layout: all nodes + orchestrator on a grid ────────────────────────────
3922
- // Include orchestrator as first "station" (desk 0), then all agents
3923
- // Total stations = nodes.length + 1 (orchestrator)
3924
- var totalStations = totalCount + 1;
3925
- // Grid: up to 3 per row, rows fill downward
3926
- var cols = Math.min(totalStations, 3);
3921
+ // ── CSS Grid layout: 100% width, responsive ──────────────────────────────
3922
+ // All stations (orch + agents) in a grid, max 4 per row
3923
+ var totalStations = totalCount + 1; // +1 for orchestrator
3924
+ var cols = totalStations <= 2 ? totalStations : (totalStations <= 4 ? 2 : (totalStations <= 6 ? 3 : 4));
3927
3925
  var rows = Math.ceil(totalStations / cols);
3928
3926
 
3929
- // Scene: square, 100% width of parent, dynamic height based on grid rows
3930
- // Each cell = 160px wide, 180px tall
3931
- var CELL_W = 160; var CELL_H = 180;
3932
- var SCENE_W = cols * CELL_W + 40; // +padding
3933
- var SCENE_H = Math.max(rows * CELL_H + 80, 400);
3934
-
3935
- // Plant emoji for decoration corners
3936
- var plantEmoji = String.fromCodePoint(0x1F331); // seedling
3937
- var bigPlant = String.fromCodePoint(0x1FAB4); // potted plant
3938
-
3939
- // ── Build station HTML ───────────────────────────────────────────────────
3940
- var stationsHtml = \x27\x27;
3941
-
3942
- // Station builder — shared for orchestrator and agents
3943
- function buildStation(stationIdx, label, emoji, toolEmoji, isOrch, isActive, isDone, isErr, idx) {
3944
- var col = stationIdx % cols;
3945
- var row2 = Math.floor(stationIdx / cols);
3946
- var left = 20 + col * CELL_W + CELL_W/2;
3947
- var top = 30 + row2 * CELL_H;
3948
- var zIdx = 100 + row2 * 10 + col;
3949
- var accentColor = isOrch ? \x27#818cf8\x27 : (isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : (isErr ? \x27#ef4444\x27 : \x27#aaa\x27)));
3950
-
3951
- // Desk — isometric CSS box using borders
3952
- var deskHtml = \x27<div class="iso-desk" style="--dc:\x27+accentColor+\x27"></div>\x27;
3953
-
3954
- // Monitor — small box on desk
3955
- var monHtml = \x27<div class="iso-monitor" style="border-color:\x27+accentColor+\x2788">\x27+
3956
- \x27<div class="iso-monitor-screen">\x27+(isOrch?\x27<span style="font-size:10px">&#128269;</span>\x27:(isDone?\x27<span style="color:#22c55e;font-size:10px">&#10003;</span>\x27:(isActive?\x27<span class="iso-monitor-blink"></span>\x27:\x27<span style="font-size:9px;opacity:.4">&#9632;</span>\x27)))+\x27</div>\x27+
3957
- \x27</div>\x27;
3958
-
3959
- // Tool badge — the emoji representing what this node does
3960
- var toolBadge = \x27<div class="iso-tool-badge" title="\x27+esc(label)+\x27">\x27+toolEmoji+\x27</div>\x27;
3961
-
3962
- // Agent/tool character emoji
3963
- var charEmojiHtml = isoCharSvg({emojiIdx: isOrch ? 99 : idx, isActive: isActive, isDone: isDone, scale: 1, accentColor: accentColor});
3964
-
3965
- // Status bubble
3927
+ // Each station rendered as a grid cell 100% fills parent
3928
+ // No pixel-based absolute positioning: use CSS grid % cells
3929
+ var gridTpl = \x27repeat(\x27+cols+\x27,1fr)\x27;
3930
+
3931
+ // Plant/deco emojis
3932
+ var bigPlant = String.fromCodePoint(0x1FAB4);
3933
+ var plantEmoji = String.fromCodePoint(0x1F331);
3934
+
3935
+ // Build all station cards (orchestrator first, then agents)
3936
+ function buildStation2(label, toolEmoji, isOrch, isActive, isDone, isErr, emojiIdx) {
3937
+ var accentColor = isOrch ? \x27#818cf8\x27 : (isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : (isErr ? \x27#ef4444\x27 : \x27#9ca3af\x27)));
3938
+ var nameBg = isDone ? \x27#dcfce7\x27 : (isActive ? \x27#ede9fe\x27 : (isOrch ? \x27#e0e7ff\x27 : \x27rgba(255,255,255,.85)\x27));
3939
+ var nameColor = isDone ? \x27#16a34a\x27 : (isActive ? \x27#4f46e5\x27 : (isOrch ? \x27#4338ca\x27 : (isErr ? \x27#dc2626\x27 : \x27#374151\x27)));
3940
+ var monScreen = isOrch
3941
+ ? \x27<span style="font-size:11px">&#128269;</span>\x27
3942
+ : (isDone ? \x27<span style="color:#22c55e;font-size:13px">&#10003;</span>\x27
3943
+ : (isActive ? \x27<span class="iso-monitor-blink"></span>\x27
3944
+ : \x27<span style="font-size:8px;opacity:.35;color:#818cf8">&#9632;</span>\x27));
3966
3945
  var bubbleText = isOrch
3967
- ? (hasActive ? (\x27Step \x27+doneCount+\x27/\x27+totalCount) : ((!hasActive && doneCount===totalCount && totalCount>0) ? \x27Completato!\x27 : \x27In attesa\x27))
3968
- : (isActive ? \x27...lavora\x27 : (isDone ? \x27\u2714 fatto\x27 : (isErr ? \x27\u2715 errore\x27 : \x27\x27)));
3969
- var bubbleColor = isOrch ? \x27#818cf8\x27 : (isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : \x27#ef4444\x27));
3970
- var bubbleHtml = (bubbleText || isOrch)
3971
- ? \x27<div class="iso-bubble\x27+(isActive?\x27 iso-bubble--active\x27:\x27\x27)+\x27" id="isobubble_\x27+(isOrch?\x27orch\x27:idx)+\x27" style="border-color:\x27+bubbleColor+\x27;color:\x27+bubbleColor+\x27">\x27+esc(bubbleText)+\x27</div>\x27
3972
- : \x27<div style="height:22px"></div>\x27;
3973
-
3974
- // Name badge
3975
- var nameColor = isDone ? \x27#16a34a\x27 : (isActive ? \x27#6366f1\x27 : (isOrch ? \x27#818cf8\x27 : (isErr ? \x27#dc2626\x27 : \x27#374151\x27)));
3976
- var nameBg = isDone ? \x27#dcfce7\x27 : (isActive ? \x27#ede9fe\x27 : (isOrch ? \x27#e0e7ff\x27 : \x27#f3f4f6\x27));
3977
- var nameHtml = \x27<div class="iso-name" style="color:\x27+nameColor+\x27;background:\x27+nameBg+\x27">\x27+(isOrch?\x27\u2666 \x27:\x27\x27)+esc(label.slice(0,18))+\x27</div>\x27;
3978
-
3979
- // Orchestrator walk animation — walks between desks horizontally
3980
- var orchWalkStyle = \x27\x27;
3981
- if (isOrch && hasActive) {
3982
- var activeIdx = nodes.findIndex(function(nd){return nd.status===\x27running\x27;});
3983
- if (activeIdx >= 0) {
3984
- var targetStation = activeIdx + 1; // station index of active agent (orch is 0)
3985
- var targetCol = targetStation % cols;
3986
- var targetRow = Math.floor(targetStation / cols);
3987
- var targetLeft = 20 + targetCol * CELL_W + CELL_W/2;
3988
- var targetTop = 30 + targetRow * CELL_H;
3989
- orchWalkStyle = \x27--orch-tx:\x27+(targetLeft - left)+\x27px;--orch-ty:\x27+(targetTop - top)+\x27px\x27;
3990
- }
3991
- }
3992
- var orchClass = (isOrch && hasActive) ? \x27 iso-orch-walking\x27 : (isOrch && !hasActive && doneCount===totalCount && totalCount>0 ? \x27 iso-orch-done\x27 : \x27\x27);
3993
-
3994
- var clickHandler = isOrch ? \x27\x27 : \x27onclick="studioScrollToAgent(this.getAttribute(String.fromCharCode(100,97,116,97,45,97,103,101,110,116,45,108,97,98,101,108)))"\x27;
3995
- var dataAttr = isOrch ? \x27\x27 : \x27data-agent-label="\x27+esc(label)+\x27"\x27;
3996
-
3997
- return \x27<div class="iso-station\x27+orchClass+\x27" \x27+dataAttr+\x27 style="position:absolute;left:\x27+left+\x27px;top:\x27+top+\x27px;z-index:\x27+zIdx+\x27;transform:translateX(-50%);\x27+orchWalkStyle+\x27" \x27+clickHandler+\x27>\x27+
3998
- bubbleHtml+
3999
- toolBadge+
4000
- charEmojiHtml+
4001
- deskHtml+
4002
- monHtml+
4003
- nameHtml+
3946
+ ? (hasActive ? (\x27Step \x27+doneCount+\x27/\x27+totalCount) : (doneCount===totalCount&&totalCount>0 ? \x27\u2714 Fatto!\x27 : \x27In attesa\x27))
3947
+ : (isActive ? \x27\u2022\u2022\u2022 lavora\x27 : (isDone ? \x27\u2714 fatto\x27 : (isErr ? \x27\u2715 errore\x27 : \x27\x27)));
3948
+ var bubbleBg = isOrch ? \x27rgba(99,102,241,.15)\x27 : (isActive ? \x27rgba(99,102,241,.12)\x27 : (isDone ? \x27rgba(34,197,94,.12)\x27 : \x27rgba(239,68,68,.12)\x27));
3949
+ var glowBox = isActive ? (\x270 0 0 3px \x27+accentColor+\x2744,0 8px 24px \x27+accentColor+\x2733\x27) : (isDone ? (\x270 0 0 2px #22c55e44\x27) : \x27none\x27);
3950
+ var orchWalkClass = (isOrch && hasActive) ? \x27 iso-orch-walking\x27 : (isOrch && doneCount===totalCount&&totalCount>0 ? \x27 iso-orch-done\x27 : \x27\x27);
3951
+ var charHtml = isoCharSvg({emojiIdx: isOrch ? 99 : emojiIdx, isActive: isActive, isDone: isDone, scale: 1.1, accentColor: accentColor});
3952
+ 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);
3953
+ 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+
3954
+ // bubble
3955
+ \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+
3956
+ // tool badge above character
3957
+ \x27<div class="iso-tool-badge">\x27+toolEmoji+\x27</div>\x27+
3958
+ // character emoji
3959
+ charHtml+
3960
+ // desk
3961
+ \x27<div class="iso-desk" style="width:85%;border-top-color:\x27+accentColor+\x2733"></div>\x27+
3962
+ // monitor on desk
3963
+ \x27<div class="iso-monitor" style="border-color:\x27+accentColor+\x2777"><div class="iso-monitor-screen">\x27+monScreen+\x27</div></div>\x27+
3964
+ // name
3965
+ \x27<div class="iso-name" style="color:\x27+nameColor+\x27;background:\x27+nameBg+\x27">\x27+(isOrch?\x27\u2666\xA0\x27:\x27\x27)+esc(label.slice(0,16))+\x27</div>\x27+
4004
3966
  \x27</div>\x27;
4005
3967
  }
4006
3968
 
4007
- // Orchestrator station (index 0)
4008
- var orchIsActive2 = hasActive;
4009
- var orchDone2 = !hasActive && doneCount === totalCount && totalCount > 0;
4010
- stationsHtml += buildStation(0, \x27Orchestratore\x27, String.fromCodePoint(0x1F451), String.fromCodePoint(0x1F4CB), true, orchIsActive2, orchDone2, false, -1);
4011
-
4012
- // Agent/tool stations (index 1..N)
3969
+ var stationsHtml = \x27\x27;
3970
+ // Orchestrator
3971
+ var orchDone2 = !hasActive && doneCount===totalCount && totalCount>0;
3972
+ stationsHtml += buildStation2(\x27Orchestratore\x27, String.fromCodePoint(0x1F4CB), true, hasActive, orchDone2, false, 99);
3973
+ // Agents
4013
3974
  nodes.forEach(function(n, idx) {
4014
- var isActive = n.status === \x27running\x27;
4015
- var isDone = n.status === \x27done\x27;
4016
- var isErr = n.status === \x27error\x27;
4017
- var lbl = n.label || n.agent;
4018
- var toolEmoji = getNodeEmoji(n);
4019
- stationsHtml += buildStation(idx + 1, lbl, AGENT_EMOJIS[idx % AGENT_EMOJIS.length], toolEmoji, false, isActive, isDone, isErr, idx);
3975
+ stationsHtml += buildStation2(
3976
+ n.label || n.agent,
3977
+ getNodeEmoji(n),
3978
+ false,
3979
+ n.status===\x27running\x27,
3980
+ n.status===\x27done\x27,
3981
+ n.status===\x27error\x27,
3982
+ idx
3983
+ );
4020
3984
  });
4021
3985
 
4022
- // ── Decorations: plants + door ───────────────────────────────────────────
4023
- var decoHtml =
4024
- \x27<div style="position:absolute;bottom:8px;left:8px;font-size:32px;line-height:1;filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))">\x27+bigPlant+\x27</div>\x27+
4025
- \x27<div style="position:absolute;bottom:8px;right:8px;font-size:32px;line-height:1;filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))">\x27+bigPlant+\x27</div>\x27+
4026
- \x27<div style="position:absolute;top:8px;right:14px;font-size:22px;line-height:1">\x27+plantEmoji+\x27</div>\x27+
4027
- // Door on back wall
4028
- \x27<div style="position:absolute;top:0;left:50%;transform:translateX(-50%);width:38px;height:54px;background:#c8a87a;border:2px solid #a07848;border-radius:4px 4px 0 0;z-index:1">\x27+
4029
- \x27<div style="position:absolute;right:5px;top:50%;width:6px;height:6px;border-radius:50%;background:#7a5a2a;transform:translateY(-50%)"></div>\x27+
4030
- \x27<div style="position:absolute;top:4px;left:4px;right:4px;height:16px;background:rgba(255,255,255,.15);border-radius:2px"></div>\x27+
4031
- \x27</div>\x27;
4032
-
4033
- // ── Floor SVG (fills the whole scene) ────────────────────────────────────
4034
- var floorSvg = \x27<svg viewBox="0 0 \x27+SCENE_W+\x27 \x27+SCENE_H+\x27" width="\x27+SCENE_W+\x27" height="\x27+SCENE_H+\x27" xmlns="http://www.w3.org/2000/svg" style="position:absolute;top:0;left:0;z-index:0;pointer-events:none">\x27;
4035
- // Back wall
4036
- floorSvg += \x27<rect x="0" y="0" width="\x27+SCENE_W+\x27" height="\x27+Math.round(SCENE_H*0.38)+\x27" fill="#f5f0ea"/>\x27;
3986
+ // Floor SVG uses a fixed coordinate space (1000×600) scaled 100% via CSS
3987
+ var FW = 1000; var FH = 600;
3988
+ var wallH = Math.round(FH * 0.30);
3989
+ 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;
3990
+ floorSvg += \x27<defs>\x27;
3991
+ 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;
3992
+ 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;
3993
+ floorSvg += \x27</defs>\x27;
3994
+ // Wall
3995
+ floorSvg += \x27<rect x="0" y="0" width="\x27+FW+\x27" height="\x27+wallH+\x27" fill="url(#wallGrad)"/>\x27;
4037
3996
  // Baseboard
4038
- floorSvg += \x27<rect x="0" y="\x27+Math.round(SCENE_H*0.38-4)+\x27" width="\x27+SCENE_W+\x27" height="6" fill="#d4c4a8" rx="1"/>\x27;
4039
- // Floor parquet planks
4040
- var floorY = Math.round(SCENE_H*0.38);
4041
- var plankColors = [\x27#c8a06a\x27,\x27#bf9860\x27,\x27#d4aa72\x27,\x27#ba9458\x27,\x27#c4a068\x27];
4042
- var plankH = 28; var plankW = 80;
4043
- for (var fy = floorY; fy < SCENE_H; fy += plankH) {
4044
- var rowOff = (Math.floor((fy-floorY)/plankH) % 2) * (plankW/2);
4045
- for (var fx = -plankW + rowOff; fx < SCENE_W + plankW; fx += plankW) {
4046
- var pc = plankColors[Math.abs(Math.round(fx/plankW + fy/plankH)) % plankColors.length];
4047
- floorSvg += \x27<rect x="\x27+fx+\x27" y="\x27+fy+\x27" width="\x27+(plankW-1)+\x27" height="\x27+(plankH-1)+\x27" fill="\x27+pc+\x27" rx="1"/>\x27;
4048
- // Grain line
4049
- floorSvg += \x27<line x1="\x27+(fx+plankW*0.35)+\x27" y1="\x27+fy+\x27" x2="\x27+(fx+plankW*0.35)+\x27" y2="\x27+(fy+plankH-1)+\x27" stroke="rgba(0,0,0,.05)" stroke-width="1"/>\x27;
3997
+ floorSvg += \x27<rect x="0" y="\x27+(wallH-5)+\x27" width="\x27+FW+\x27" height="7" fill="#d4c4a8" rx="2"/>\x27;
3998
+ // Floor parquet
3999
+ var plankColors2 = [\x27#c8a06a\x27,\x27#bf9860\x27,\x27#d4aa72\x27,\x27#ba9458\x27,\x27#caa86e\x27];
4000
+ var pH = 32; var pW = 120;
4001
+ for (var fy = wallH; fy < FH+pH; fy += pH) {
4002
+ var ro2 = (Math.floor((fy-wallH)/pH) % 2) * (pW/2);
4003
+ for (var fx = -pW+ro2; fx < FW+pW; fx += pW) {
4004
+ var pc2 = plankColors2[Math.abs(Math.round(fx/pW+fy/pH*1.3)) % plankColors2.length];
4005
+ 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;
4006
+ 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;
4050
4007
  }
4051
4008
  }
4052
- // Window on back wall
4053
- floorSvg += \x27<rect x="20" y="18" width="60" height="50" rx="3" fill="#bbd8f5" stroke="#a8c4dc" stroke-width="2"/>\x27;
4054
- floorSvg += \x27<line x1="50" y1="18" x2="50" y2="68" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
4055
- floorSvg += \x27<line x1="20" y1="43" x2="80" y2="43" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
4056
- floorSvg += \x27<rect x="20" y="18" width="60" height="50" rx="3" fill="rgba(255,255,255,.15)"/>\x27;
4057
- if (SCENE_W > 350) {
4058
- floorSvg += \x27<rect x="\x27+(SCENE_W-100)+\x27" y="18" width="60" height="50" rx="3" fill="#bbd8f5" stroke="#a8c4dc" stroke-width="2"/>\x27;
4059
- floorSvg += \x27<line x1="\x27+(SCENE_W-70)+\x27" y1="18" x2="\x27+(SCENE_W-70)+\x27" y2="68" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
4060
- floorSvg += \x27<line x1="\x27+(SCENE_W-100)+\x27" y1="43" x2="\x27+(SCENE_W-40)+\x27" y2="43" stroke="#a8c4dc" stroke-width="1.5"/>\x27;
4009
+ // Windows — 2 on left, 1 center-right
4010
+ function svgWindow(wx, wy, ww, wh) {
4011
+ 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;
4012
+ 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;
4013
+ 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;
4014
+ 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;
4015
+ return r;
4061
4016
  }
4017
+ floorSvg += svgWindow(40, 20, 100, 80);
4018
+ floorSvg += svgWindow(180, 20, 100, 80);
4019
+ floorSvg += svgWindow(FW-200, 20, 120, 80);
4020
+ // Door center
4021
+ floorSvg += \x27<rect x="\x27+(FW/2-35)+\x27" y="0" width="70" height="\x27+wallH+\x27" rx="0" fill="#c8a87a" stroke="#a07848" stroke-width="2"/>\x27;
4022
+ floorSvg += \x27<rect x="\x27+(FW/2-25)+\x27" y="8" width="50" height="36" rx="4" fill="rgba(255,255,255,.18)"/>\x27;
4023
+ floorSvg += \x27<circle cx="\x27+(FW/2+22)+\x27" cy="\x27+(wallH/2)+\x27" r="5" fill="#8a6028"/>\x27;
4062
4024
  // Chandelier
4063
- var chandX = Math.round(SCENE_W/2);
4064
- floorSvg += \x27<line x1="\x27+chandX+\x27" y1="0" x2="\x27+chandX+\x27" y2="24" stroke="#999" stroke-width="2"/>\x27;
4065
- floorSvg += \x27<ellipse cx="\x27+chandX+\x27" cy="28" rx="28" ry="8" fill="#e8d980" stroke="#c8b840" stroke-width="1.5"/>\x27;
4066
- floorSvg += \x27<circle cx="\x27+(chandX-18)+\x27" cy="32" r="5" fill="#fff8c0" filter="url(#bGlow)"/>\x27;
4067
- floorSvg += \x27<circle cx="\x27+chandX+\x27" cy="34" r="5" fill="#fff8c0" filter="url(#bGlow)"/>\x27;
4068
- floorSvg += \x27<circle cx="\x27+(chandX+18)+\x27" cy="32" r="5" fill="#fff8c0" filter="url(#bGlow)"/>\x27;
4069
- floorSvg += \x27<defs><filter id="bGlow" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="4" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs>\x27;
4025
+ floorSvg += \x27<line x1="\x27+(FW/2)+\x27" y1="0" x2="\x27+(FW/2)+\x27" y2="30" stroke="#bbb" stroke-width="3"/>\x27;
4026
+ floorSvg += \x27<ellipse cx="\x27+(FW/2)+\x27" cy="38" rx="50" ry="14" fill="#e8d960" stroke="#c8b030" stroke-width="2"/>\x27;
4027
+ floorSvg += \x27<circle cx="\x27+(FW/2-28)+\x27" cy="46" r="8" fill="#fffde0" filter="url(#bGlow2)"/>\x27;
4028
+ floorSvg += \x27<circle cx="\x27+(FW/2)+\x27" cy="50" r="8" fill="#fffde0" filter="url(#bGlow2)"/>\x27;
4029
+ floorSvg += \x27<circle cx="\x27+(FW/2+28)+\x27" cy="46" r="8" fill="#fffde0" filter="url(#bGlow2)"/>\x27;
4030
+ // Light cone
4031
+ 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;
4070
4032
  floorSvg += \x27</svg>\x27;
4071
4033
 
4034
+ // Decorations (CSS positioned, z-index above floor SVG)
4035
+ var decoHtml =
4036
+ \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+
4037
+ \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+
4038
+ \x27<div style="position:absolute;top:12px;left:310px;font-size:24px;line-height:1;z-index:5">\x27+plantEmoji+\x27</div>\x27+
4039
+ \x27<div style="position:absolute;top:12px;right:230px;font-size:24px;line-height:1;z-index:5">\x27+plantEmoji+\x27</div>\x27;
4040
+
4072
4041
  el.innerHTML =
4073
4042
  \x27<div class="prl-wrap" style="border-color:\x27+phaseColor2+\x2744;padding-bottom:8px">\x27+
4074
4043
  \x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor2+\x27">\x27+phaseLabel2+\x27</span></div>\x27+
4075
- \x27<div class="iso-scene-wrap">\x27+
4076
- \x27<div class="iso-scene" style="position:relative;width:\x27+SCENE_W+\x27px;min-width:\x27+SCENE_W+\x27px;height:\x27+SCENE_H+\x27px">\x27+
4044
+ \x27<div class="iso-scene" style="position:relative">\x27+
4077
4045
  floorSvg+
4078
4046
  decoHtml+
4047
+ // Grid overlay for stations
4048
+ \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+
4049
+ // Push agents to bottom half of scene (wall takes top ~30%)
4050
+ \x27<div style="grid-column:1/-1;height:calc(30% - 12px)"></div>\x27+
4079
4051
  stationsHtml+
4080
4052
  \x27</div>\x27+
4081
4053
  \x27</div>\x27+
@@ -4716,58 +4688,118 @@ async function runStudio() {
4716
4688
  if (!parlBlockBuilt || !pb.innerHTML.trim()) {
4717
4689
  parlBlockBuilt = true;
4718
4690
 
4719
- // Build agent seat HTML (emoji avatar)
4691
+ // ── SEAT builder same style as workflow office stations ──────────
4720
4692
  function buildSeat(prop, seatIdx) {
4721
4693
  var lbl = prop.label || prop.agent;
4722
4694
  var safeLbl = lbl.replace(new RegExp('[^a-zA-Z0-9_-]','g'),\x27_\x27);
4723
4695
  var emojiIdx = Math.abs(lbl.charCodeAt(0)+(lbl.charCodeAt(lbl.length-1)||0)) % AGENT_EMOJIS.length;
4724
4696
  var agentEmoji = AGENT_EMOJIS[emojiIdx];
4725
4697
  void seatIdx;
4726
- var agentAvatar = \x27<div style="font-size:36px;line-height:1;user-select:none;filter:drop-shadow(0 2px 4px rgba(0,0,0,.3))">\x27+agentEmoji+\x27</div>\x27;
4698
+ // Each seat: bubble + emoji char + name — states updated surgically later
4727
4699
  return \x27<div class="br-seat" id="brseat_\x27+safeLbl+\x27" data-lbl="\x27+esc(lbl)+\x27">\x27+
4728
- \x27<div class="br-seat-box">\x27+
4729
- \x27<div class="br-bubble" id="brbubble_\x27+safeLbl+\x27"></div>\x27+
4730
- agentAvatar+
4731
- \x27<div class="br-seat-name" id="brname_\x27+safeLbl+\x27">\x27+esc(lbl)+\x27</div>\x27+
4732
- \x27</div>\x27+
4700
+ \x27<div class="br-bubble" id="brbubble_\x27+safeLbl+\x27" style="display:none"></div>\x27+
4701
+ \x27<div class="br-char" style="font-size:38px;line-height:1;user-select:none;filter:drop-shadow(0 2px 6px rgba(0,0,0,.25))">\x27+agentEmoji+\x27</div>\x27+
4702
+ \x27<div class="br-seat-name" id="brname_\x27+safeLbl+\x27">\x27+esc(lbl.slice(0,14))+\x27</div>\x27+
4733
4703
  \x27</div>\x27;
4734
4704
  }
4735
4705
 
4736
- // Arrange seats in a circle around center table
4737
- var seatsHtml = proposals.map(buildSeat).join(\x27\x27);
4738
-
4739
- // Orchestrator at center — emoji (crowned suit)
4740
- var orchEmoji = String.fromCodePoint(0x1F9D1,0x200D,0x1F4BC);
4741
- var crownEmoji = String.fromCodePoint(0x1F451);
4742
- var orchSvgEl = crownEmoji; // crown above orchestrator emoji — not SVG anymore
4743
- var orchSvg = \x27<div style="display:flex;flex-direction:column;align-items:center;gap:2px">\x27+
4744
- \x27<span style="font-size:22px;line-height:1">\x27+crownEmoji+\x27</span>\x27+
4745
- \x27<div style="font-size:52px;line-height:1;filter:drop-shadow(0 0 12px #818cf8AA);user-select:none">\x27+orchEmoji+\x27</div>\x27+
4706
+ // ── Build seat rows: top row (facing down) + bottom row (facing up)
4707
+ // For n agents: ceil(n/2) on top, floor(n/2) on bottom
4708
+ // Orchestrator gets the "head" position (left end of table)
4709
+ var topSeats = [];
4710
+ var botSeats = [];
4711
+ proposals.forEach(function(prop, si) {
4712
+ if (si % 2 === 0) topSeats.push(prop); else botSeats.push(prop);
4713
+ });
4714
+ var topHtml = topSeats.map(buildSeat).join(\x27\x27);
4715
+ var botHtml = botSeats.map(buildSeat).join(\x27\x27);
4716
+
4717
+ // ── Orchestrator head seat ─────────────────────────────────────────
4718
+ var orchEmoji2 = String.fromCodePoint(0x1F9D1,0x200D,0x1F4BC);
4719
+ var crownEm = String.fromCodePoint(0x1F451);
4720
+ var orchHeadHtml = \x27<div class="br-orch" id="brOrch" style="display:flex;flex-direction:column;align-items:center;gap:3px;padding:8px 10px">\x27+
4721
+ \x27<div class="br-orch-speech" id="brOrchSpeech" style="display:none"></div>\x27+
4722
+ \x27<div style="font-size:16px;line-height:1">\x27+crownEm+\x27</div>\x27+
4723
+ \x27<div style="font-size:44px;line-height:1;filter:drop-shadow(0 0 14px #818cf8BB)">\x27+orchEmoji2+\x27</div>\x27+
4724
+ \x27<div class="br-orch-label" style="font-size:9px;font-weight:700;color:#6366f1;background:rgba(99,102,241,.12);border-radius:6px;padding:2px 7px;margin-top:2px">Orchestratore</div>\x27+
4746
4725
  \x27</div>\x27;
4747
- void orchSvgEl;
4748
-
4749
- // Center table (SVG oval)
4750
- var tableSvg = \x27<svg viewBox="0 0 160 80" width="160" height="80" xmlns="http://www.w3.org/2000/svg">\x27+
4751
- // Table shadow
4752
- \x27<ellipse cx="80" cy="44" rx="74" ry="34" fill="rgba(0,0,0,.3)"/>\x27+
4753
- // Table surfaceglossy dark wood
4754
- \x27<ellipse cx="80" cy="40" rx="74" ry="34" fill="#1e1440" stroke="#3a2880" stroke-width="2"/>\x27+
4755
- // Table shine
4756
- \x27<ellipse cx="60" cy="28" rx="30" ry="12" fill="rgba(150,130,255,.08)"/>\x27+
4757
- // NHA logo on table
4758
- \x27<text x="80" y="46" text-anchor="middle" font-family="system-ui" font-size="18" font-weight="900" fill="rgba(100,90,200,.25)" letter-spacing="2">NHA</text>\x27+
4759
- // Documents on table
4760
- \x27<rect x="62" y="34" width="18" height="14" rx="2" fill="#141028" stroke="#4a3880" stroke-width="1" transform="rotate(-8 71 41)"/>\x27+
4761
- \x27<rect x="82" y="36" width="18" height="14" rx="2" fill="#141028" stroke="#4a3880" stroke-width="1" transform="rotate(5 91 43)"/>\x27+
4726
+
4727
+ // ── Conference table SVG — wide rectangle ──────────────────────────
4728
+ // Table is drawn as background SVG, fills the center area
4729
+ var tblSvg = \x27<svg viewBox="0 0 1000 200" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" style="position:absolute;top:50%;left:0;width:100%;height:140px;transform:translateY(-50%);z-index:1;pointer-events:none">\x27+
4730
+ // Shadow
4731
+ \x27<rect x="8" y="12" width="984" height="176" rx="20" fill="rgba(0,0,0,.22)"/>\x27+
4732
+ // Table bodyrich dark walnut
4733
+ \x27<rect x="0" y="4" width="1000" height="176" rx="18" fill="url(#tblGrad)"/>\x27+
4734
+ // Top edge highlight
4735
+ \x27<rect x="0" y="4" width="1000" height="8" rx="8" fill="rgba(255,255,255,.08)"/>\x27+
4736
+ // Wood grain lines
4737
+ \x27<line x1="0" y1="50" x2="1000" y2="50" stroke="rgba(0,0,0,.06)" stroke-width="2"/>\x27+
4738
+ \x27<line x1="0" y1="100" x2="1000" y2="100" stroke="rgba(0,0,0,.08)" stroke-width="2"/>\x27+
4739
+ \x27<line x1="0" y1="150" x2="1000" y2="150" stroke="rgba(0,0,0,.06)" stroke-width="2"/>\x27+
4740
+ // NHA monogram center
4741
+ \x27<text x="500" y="115" text-anchor="middle" font-family="system-ui" font-size="52" font-weight="900" fill="rgba(150,130,255,.12)" letter-spacing="8">NHA</text>\x27+
4742
+ // Laptop/papers scattered on table
4743
+ \x27<rect x="180" y="60" width="60" height="40" rx="4" fill="rgba(99,102,241,.18)" stroke="rgba(99,102,241,.35)" stroke-width="1.5"/>\x27+
4744
+ \x27<rect x="390" y="55" width="70" height="45" rx="4" fill="rgba(99,102,241,.14)" stroke="rgba(99,102,241,.3)" stroke-width="1.5"/>\x27+
4745
+ \x27<rect x="650" y="62" width="55" height="38" rx="4" fill="rgba(99,102,241,.18)" stroke="rgba(99,102,241,.35)" stroke-width="1.5"/>\x27+
4746
+ \x27<rect x="820" y="58" width="50" height="36" rx="4" fill="rgba(99,102,241,.12)" stroke="rgba(99,102,241,.28)" stroke-width="1.5"/>\x27+
4747
+ // Coffee cups
4748
+ \x27<circle cx="300" cy="88" r="14" fill="rgba(180,120,60,.4)" stroke="rgba(180,120,60,.6)" stroke-width="1.5"/>\x27+
4749
+ \x27<circle cx="750" cy="92" r="14" fill="rgba(180,120,60,.4)" stroke="rgba(180,120,60,.6)" stroke-width="1.5"/>\x27+
4750
+ \x27<defs>\x27+
4751
+ \x27<linearGradient id="tblGrad" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#5a3a18"/><stop offset="0.5" stop-color="#3d2510"/><stop offset="1" stop-color="#2a1808"/></linearGradient>\x27+
4752
+ \x27</defs>\x27+
4762
4753
  \x27</svg>\x27;
4763
4754
 
4764
- var orchHtml = \x27<div class="br-orch" id="brOrch">\x27+
4765
- \x27<div class="br-orch-speech" id="brOrchSpeech"></div>\x27+
4766
- orchSvg+
4767
- \x27<div class="br-orch-label">NHA Studio</div>\x27+
4768
- \x27</div>\x27;
4755
+ // ── Floor + wall SVG background (same as workflow scene) ───────────
4756
+ var bgSvg = \x27<svg viewBox="0 0 1000 600" 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+
4757
+ \x27<defs>\x27+
4758
+ \x27<filter id="brGlow" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>\x27+
4759
+ \x27<linearGradient id="brWall" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#faf7f2"/><stop offset="1" stop-color="#ede8e0"/></linearGradient>\x27+
4760
+ \x27</defs>\x27+
4761
+ // Wall
4762
+ \x27<rect x="0" y="0" width="1000" height="210" fill="url(#brWall)"/>\x27+
4763
+ // Baseboard
4764
+ \x27<rect x="0" y="205" width="1000" height="7" fill="#d4c4a8" rx="2"/>\x27+
4765
+ // Parquet floor
4766
+ function() {
4767
+ var s2 = \x27\x27;
4768
+ var pColors = [\x27#c8a06a\x27,\x27#bf9860\x27,\x27#d4aa72\x27,\x27#ba9458\x27,\x27#caa86e\x27];
4769
+ var pH2 = 32; var pW2 = 120;
4770
+ for (var fy2 = 212; fy2 < 600+pH2; fy2 += pH2) {
4771
+ var ro3 = (Math.floor((fy2-212)/pH2) % 2) * (pW2/2);
4772
+ for (var fx2 = -pW2+ro3; fx2 < 1000+pW2; fx2 += pW2) {
4773
+ var pc3 = pColors[Math.abs(Math.round(fx2/pW2+fy2/pH2*1.3)) % pColors.length];
4774
+ s2 += \x27<rect x="\x27+Math.round(fx2)+\x27" y="\x27+fy2+\x27" width="\x27+(pW2-2)+\x27" height="\x27+(pH2-2)+\x27" fill="\x27+pc3+\x27" rx="2"/>\x27;
4775
+ s2 += \x27<line x1="\x27+Math.round(fx2+pW2*.4)+\x27" y1="\x27+fy2+\x27" x2="\x27+Math.round(fx2+pW2*.4)+\x27" y2="\x27+(fy2+pH2-2)+\x27" stroke="rgba(0,0,0,.04)" stroke-width="1.5"/>\x27;
4776
+ }
4777
+ }
4778
+ return s2;
4779
+ }()+
4780
+ // Windows
4781
+ \x27<rect x="40" y="22" width="110" height="88" rx="5" fill="#c8e6f8" stroke="#a8cce0" stroke-width="3"/>\x27+
4782
+ \x27<line x1="95" y1="22" x2="95" y2="110" stroke="#a8cce0" stroke-width="2"/>\x27+
4783
+ \x27<line x1="40" y1="66" x2="150" y2="66" stroke="#a8cce0" stroke-width="2"/>\x27+
4784
+ \x27<rect x="40" y="22" width="110" height="88" rx="5" fill="rgba(255,255,255,.18)"/>\x27+
4785
+ \x27<rect x="850" y="22" width="110" height="88" rx="5" fill="#c8e6f8" stroke="#a8cce0" stroke-width="3"/>\x27+
4786
+ \x27<line x1="905" y1="22" x2="905" y2="110" stroke="#a8cce0" stroke-width="2"/>\x27+
4787
+ \x27<line x1="850" y1="66" x2="960" y2="66" stroke="#a8cce0" stroke-width="2"/>\x27+
4788
+ \x27<rect x="850" y="22" width="110" height="88" rx="5" fill="rgba(255,255,255,.18)"/>\x27+
4789
+ // Door
4790
+ \x27<rect x="463" y="0" width="74" height="210" fill="#c8a87a" stroke="#a07848" stroke-width="2"/>\x27+
4791
+ \x27<rect x="472" y="10" width="56" height="50" rx="5" fill="rgba(255,255,255,.18)"/>\x27+
4792
+ \x27<circle cx="524" cy="108" r="6" fill="#8a6028"/>\x27+
4793
+ // Chandelier
4794
+ \x27<line x1="500" y1="0" x2="500" y2="32" stroke="#bbb" stroke-width="3"/>\x27+
4795
+ \x27<ellipse cx="500" cy="42" rx="60" ry="16" fill="#e8d960" stroke="#c8b030" stroke-width="2"/>\x27+
4796
+ \x27<circle cx="468" cy="52" r="10" fill="#fffde0" filter="url(#brGlow)"/>\x27+
4797
+ \x27<circle cx="500" cy="56" r="10" fill="#fffde0" filter="url(#brGlow)"/>\x27+
4798
+ \x27<circle cx="532" cy="52" r="10" fill="#fffde0" filter="url(#brGlow)"/>\x27+
4799
+ \x27<polygon points="440,66 560,66 680,600 320,600" fill="rgba(255,252,200,.05)"/>\x27+
4800
+ \x27</svg>\x27;
4769
4801
 
4770
- // Phase indicator + progress
4802
+ // ── Phase header ───────────────────────────────────────────────────
4771
4803
  var headerHtml = \x27<div class="br-header">\x27+
4772
4804
  \x27<span class="br-phase-chip" id="brPhaseChip"></span>\x27+
4773
4805
  \x27<div class="br-progress-wrap" id="brProgressWrap"><div class="br-progress-bar" id="brProgressBar"></div></div>\x27+
@@ -4775,12 +4807,31 @@ async function runStudio() {
4775
4807
 
4776
4808
  var convergeHtml = \x27<div class="br-convergence" id="brConvergence" style="display:none"></div>\x27;
4777
4809
 
4810
+ // ── Assemble: full-width scene with table ──────────────────────────
4778
4811
  pb.innerHTML =
4779
4812
  \x27<div class="br-wrap">\x27+
4780
4813
  headerHtml+
4781
- \x27<div class="br-room" style="--br-n:\x27+n+\x27">\x27+
4782
- \x27<div class="br-table-center">\x27+tableSvg+orchHtml+\x27</div>\x27+
4783
- \x27<div class="br-seats-ring" style="--br-n:\x27+n+\x27">\x27+seatsHtml+\x27</div>\x27+
4814
+ \x27<div class="br-room" style="position:relative;width:100%;min-height:480px;overflow:hidden;border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,.18)">\x27+
4815
+ bgSvg+
4816
+ // Decorations
4817
+ \x27<div style="position:absolute;bottom:10px;left:12px;font-size:40px;z-index:5;filter:drop-shadow(0 3px 6px rgba(0,0,0,.25))">\x27+String.fromCodePoint(0x1FAB4)+\x27</div>\x27+
4818
+ \x27<div style="position:absolute;bottom:10px;right:12px;font-size:40px;z-index:5;filter:drop-shadow(0 3px 6px rgba(0,0,0,.25))">\x27+String.fromCodePoint(0x1FAB4)+\x27</div>\x27+
4819
+ \x27<div style="position:absolute;top:14px;left:180px;font-size:24px;z-index:5">\x27+String.fromCodePoint(0x1F331)+\x27</div>\x27+
4820
+ \x27<div style="position:absolute;top:14px;right:180px;font-size:24px;z-index:5">\x27+String.fromCodePoint(0x1F331)+\x27</div>\x27+
4821
+ // Layout: flex column — top row / [orch + table] / bottom row
4822
+ \x27<div style="position:relative;z-index:10;display:flex;flex-direction:column;justify-content:center;min-height:480px;padding:20px 16px;gap:0;box-sizing:border-box">\x27+
4823
+ // Top seats row (faces DOWN toward table)
4824
+ \x27<div class="br-seats-row" style="justify-content:space-around;margin-bottom:8px">\x27+topHtml+\x27</div>\x27+
4825
+ // Middle row: orchestrator head + table SVG
4826
+ \x27<div style="position:relative;display:flex;align-items:center;width:100%;min-height:160px">\x27+
4827
+ // Orch at left head of table
4828
+ orchHeadHtml+
4829
+ // Table fills the rest of the middle row
4830
+ \x27<div style="position:relative;flex:1;min-height:140px">\x27+tblSvg+\x27</div>\x27+
4831
+ \x27</div>\x27+
4832
+ // Bottom seats row (faces UP toward table)
4833
+ \x27<div class="br-seats-row" style="justify-content:space-around;margin-top:8px">\x27+botHtml+\x27</div>\x27+
4834
+ \x27</div>\x27+
4784
4835
  \x27</div>\x27+
4785
4836
  convergeHtml+
4786
4837
  \x27</div>\x27;
@@ -6573,68 +6624,38 @@ input:focus,textarea:focus{border-color:var(--green3)}
6573
6624
  .wf-sbraita-bubble{position:absolute;top:-28px;left:50%;transform:translateX(-50%);background:#1a0a0a;border:1.5px solid #ef4444;color:#fca5a5;font-family:var(--mono);font-size:9px;font-weight:800;padding:3px 8px;border-radius:8px;white-space:nowrap;letter-spacing:.5px;animation:sbraitaPop .4s ease-in-out infinite alternate;pointer-events:none;z-index:4}
6574
6625
  .wf-sbraita-bubble::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:#ef4444}
6575
6626
  @keyframes sbraitaPop{0%{transform:translateX(-50%) scale(1) rotate(-2deg)}100%{transform:translateX(-50%) scale(1.06) rotate(2deg)}}
6576
- /* ── Parliament Boardroom 3D ── */
6577
- /* Outer wrapper */
6578
- .br-wrap{background:#090714;border:1.5px solid #6366f1;border-radius:14px;padding:12px 14px;margin-bottom:16px;animation:stNodeIn .35s ease forwards;overflow:hidden}
6627
+ /* ── Parliament Boardroom bright office, same palette as workflow scene ── */
6628
+ /* Outer wrapper — matches prl-wrap but with slight warm tint */
6629
+ .br-wrap{background:var(--bg2);border:1.5px solid var(--border);border-radius:14px;padding:12px 14px;margin-bottom:16px;animation:stNodeIn .35s ease forwards;overflow:hidden}
6579
6630
  /* Header: phase chip + progress */
6580
6631
  .br-header{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}
6581
- .br-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 var(--pc,rgba(99,102,241,.4));border-radius:20px;padding:3px 12px;display:inline-block;transition:color .4s,border-color .4s}
6582
- .br-progress-wrap{flex:1;height:3px;background:#1a1630;border-radius:4px;overflow:hidden;min-width:60px}
6632
+ .br-phase-chip{font-size:10px;font-weight:800;font-family:var(--mono);letter-spacing:.3px;color:var(--pc,#6366f1);background:rgba(99,102,241,.1);border:1px solid var(--pc,rgba(99,102,241,.35));border-radius:20px;padding:3px 12px;display:inline-block;transition:color .4s,border-color .4s}
6633
+ .br-progress-wrap{flex:1;height:3px;background:var(--border);border-radius:4px;overflow:hidden;min-width:60px}
6583
6634
  .br-progress-bar{height:100%;background:linear-gradient(90deg,#6366f1,#22d3ee);border-radius:4px;transition:width .5s ease;width:0%}
6584
- /* Boardroom 3D scene */
6585
- .br-room{position:relative;min-height:220px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:10px 8px 16px;
6586
- background:linear-gradient(180deg,#141030 0%,#1c1848 50%,#141030 100%);
6587
- border-radius:10px;overflow:hidden}
6588
- /* Ambient ceiling glow */
6589
- .br-room::before{content:"";position:absolute;inset:0;background:
6590
- radial-gradient(ellipse 70% 50% at 50% 5%,rgba(180,160,255,.2) 0%,transparent 70%),
6591
- radial-gradient(ellipse 30% 30% at 50% 0%,rgba(255,220,100,.12) 0%,transparent 60%);pointer-events:none}
6592
- /* Floor perspective */
6593
- .br-room::after{content:"";position:absolute;bottom:0;left:0;right:0;height:40px;
6594
- background:linear-gradient(180deg,transparent 0%,rgba(100,80,200,.08) 50%,rgba(60,40,120,.25) 100%);
6595
- border-top:1px solid rgba(100,80,200,.15);pointer-events:none}
6596
- /* Center: table + orchestrator */
6597
- .br-table-center{position:relative;display:flex;flex-direction:column;align-items:center;gap:0;z-index:3}
6598
- /* Orchestrator standing at head of table */
6599
- .br-orch{display:flex;flex-direction:column;align-items:center;gap:2px;z-index:4;position:relative}
6600
- .br-orch--active .br-orch-arm-l{transform-origin:50% 0%;animation:brOrchArmL 2s ease-in-out infinite}
6601
- .br-orch--active .br-orch-arm-r{transform-origin:50% 0%;animation:brOrchArmR 2.4s ease-in-out infinite}
6602
- @keyframes brOrchArmL{0%,100%{transform:rotate(0deg)}40%{transform:rotate(-22deg)}70%{transform:rotate(-10deg)}}
6603
- @keyframes brOrchArmR{0%,100%{transform:rotate(0deg)}30%{transform:rotate(18deg)}65%{transform:rotate(8deg)}}
6604
- .br-orch--done{filter:drop-shadow(0 0 12px #22c55eaa)}
6605
- .br-orch-speech{position:absolute;top:-28px;left:50%;transform:translateX(-50%);
6606
- font-size:9px;font-weight:800;font-family:var(--mono);letter-spacing:.4px;
6607
- padding:3px 8px;border:1.5px solid #6366f1;border-radius:8px;
6608
- background:#0d0a1e;white-space:nowrap;
6609
- animation:brSpeechPop .6s ease-in-out infinite alternate;z-index:5;pointer-events:none}
6610
- @keyframes brSpeechPop{0%{transform:translateX(-50%) scale(1) rotate(-1deg)}100%{transform:translateX(-50%) scale(1.05) rotate(1deg)}}
6611
- .br-orch-speech::after{content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);border:4px solid transparent;border-top-color:#6366f1}
6612
- .br-orch-label{font-size:8px;font-family:var(--mono);font-weight:800;color:#818cf8;text-align:center;letter-spacing:.5px}
6613
- /* Seats ring around table */
6614
- .br-seats-ring{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;z-index:2;padding:4px 0;width:100%}
6615
- /* Individual seat / cubicle */
6616
- .br-seat{display:flex;flex-direction:column;align-items:center;gap:0;transition:transform .3s}
6617
- .br-seat-box{display:flex;flex-direction:column;align-items:center;gap:2px;padding:6px 8px 6px;border-radius:12px;
6618
- background:#1a1535;border:1.5px solid #3a3060;
6619
- box-shadow:0 2px 10px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.06);
6620
- transition:border-color .3s,background .3s,box-shadow .3s;position:relative;min-width:70px}
6621
- .br-seat--active .br-seat-box{background:#1e1a45;border-color:var(--sc,#6366f1);box-shadow:0 0 20px rgba(99,102,241,.3),0 0 40px rgba(99,102,241,.08),inset 0 1px 0 rgba(150,130,255,.15)}
6622
- .br-seat--active{transform:scale(1.04)}
6623
- .br-seat--done .br-seat-box{background:#162516;border-color:#2a4a2a}
6624
- /* Action bubble above agent — shows streaming text */
6625
- .br-bubble{font-size:8px;font-family:var(--mono);padding:3px 8px;border-radius:8px 8px 8px 2px;border:1px solid #3a3060;background:rgba(10,8,20,.88);min-height:14px;text-align:left;line-height:1.45;transition:border-color .3s;word-break:break-word;max-width:100px;white-space:normal;backdrop-filter:blur(4px)}
6626
- /* Agent name */
6627
- .br-seat-name{font-size:9px;font-family:var(--mono);font-weight:700;text-align:center;white-space:normal;word-break:break-word;max-width:90px;line-height:1.3;margin-top:2px;transition:color .3s}
6628
- /* SVG arm animations when agent is active (typing) */
6629
- .br-seat--active .br-arm-l{transform-origin:50% 100%;animation:brArmType .7s ease-in-out infinite}
6630
- .br-seat--active .br-arm-r{transform-origin:50% 100%;animation:brArmType .7s ease-in-out infinite reverse}
6631
- @keyframes brArmType{0%,100%{transform:rotate(-6deg) translateY(0)}50%{transform:rotate(6deg) translateY(2px)}}
6635
+ /* Boardroom scene — no background (bgSvg covers it) */
6636
+ .br-room{position:relative;width:100%;min-height:480px;overflow:hidden;border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,.18)}
6637
+ /* Seats rows above/below table */
6638
+ .br-seats-row{display:flex;flex-wrap:wrap;gap:6px;align-items:flex-end;justify-content:space-around}
6639
+ /* Individual seat card */
6640
+ .br-seat{display:flex;flex-direction:column;align-items:center;gap:2px;transition:transform .3s;padding:6px 8px;border-radius:12px;background:rgba(255,255,255,.82);border:1.5px solid rgba(200,180,160,.5);box-shadow:0 2px 8px rgba(0,0,0,.12);backdrop-filter:blur(4px);min-width:64px;cursor:default}
6641
+ .br-seat--active{transform:scale(1.07);border-color:var(--sc,#6366f1);box-shadow:0 0 16px rgba(99,102,241,.35),0 2px 8px rgba(0,0,0,.12)}
6642
+ .br-seat--done{border-color:rgba(34,197,94,.5);background:rgba(240,255,240,.9)}
6643
+ /* Orchestrator head seat */
6644
+ .br-orch{display:flex;flex-direction:column;align-items:center;gap:3px;padding:8px 10px;flex-shrink:0}
6645
+ .br-orch-speech{font-size:9px;font-weight:800;font-family:var(--mono);letter-spacing:.4px;padding:3px 8px;border:1.5px solid #6366f1;border-radius:8px;background:rgba(255,255,255,.95);color:#4338ca;white-space:nowrap;animation:brSpeechPop .6s ease-in-out infinite alternate;pointer-events:none;margin-bottom:2px}
6646
+ @keyframes brSpeechPop{0%{transform:scale(1) rotate(-1deg)}100%{transform:scale(1.05) rotate(1deg)}}
6647
+ .br-orch-label{font-size:9px;font-family:var(--mono);font-weight:800;color:#6366f1;background:rgba(99,102,241,.12);border-radius:6px;padding:2px 7px;text-align:center;letter-spacing:.4px}
6648
+ /* Bubble above seat showing streaming text */
6649
+ .br-bubble{font-size:8px;font-family:var(--mono);padding:3px 8px;border-radius:8px 8px 8px 2px;border:1px solid rgba(99,102,241,.35);background:rgba(255,255,255,.95);color:#1e1b4b;min-height:14px;text-align:left;line-height:1.45;transition:border-color .3s;word-break:break-word;max-width:100px;white-space:normal;box-shadow:0 2px 6px rgba(0,0,0,.12);margin-bottom:2px}
6650
+ /* Agent name pill */
6651
+ .br-seat-name{font-size:9px;font-family:var(--mono);font-weight:700;color:#374151;text-align:center;white-space:normal;word-break:break-word;max-width:90px;line-height:1.3;margin-top:1px;transition:color .3s;background:rgba(0,0,0,.04);border-radius:4px;padding:1px 4px}
6652
+ .br-seat--active .br-seat-name{color:#4338ca}
6653
+ .br-seat--done .br-seat-name{color:#15803d}
6632
6654
  /* Convergence */
6633
6655
  .br-convergence{margin-top:10px;padding:8px 12px;background:rgba(34,197,94,.06);border:1px solid rgba(34,197,94,.22);border-radius:8px}
6634
- .br-conv-bar-outer{height:4px;background:#1a2e1a;border-radius:4px;overflow:hidden;margin-bottom:6px}
6656
+ .br-conv-bar-outer{height:4px;background:rgba(34,197,94,.15);border-radius:4px;overflow:hidden;margin-bottom:6px}
6635
6657
  .br-conv-bar-inner{height:100%;background:linear-gradient(90deg,#22c55e,#4ade80);border-radius:4px;transition:width .8s ease}
6636
- .br-conv-text{font-size:9px;color:#86efac;line-height:1.55}
6637
- @keyframes brDashFlow{0%{stroke-dashoffset:20}100%{stroke-dashoffset:0}}
6658
+ .br-conv-text{font-size:9px;color:#166534;line-height:1.55}
6638
6659
  /* Keep old prl-* classes for workflow (not touched) */
6639
6660
  .prl-wrap{background:#0b0918;border:1.5px solid #6366f1;border-radius:14px;padding:14px 16px 12px;margin-bottom:16px;animation:stNodeIn .35s ease forwards;overflow:hidden}
6640
6661
  @keyframes parlPulse{0%,100%{border-color:#6366f1;box-shadow:none}50%{border-color:#818cf8;box-shadow:0 0 20px rgba(99,102,241,.3)}}
@@ -6684,25 +6705,25 @@ input:focus,textarea:focus{border-color:var(--green3)}
6684
6705
  .prl-office-plant2{position:absolute;bottom:14px;right:8px;width:22px;height:42px;z-index:2;pointer-events:none}
6685
6706
  /* ── ISOMETRIC JRPG SCENE ── */
6686
6707
  .iso-scene-wrap{width:100%;overflow-x:auto;display:flex;justify-content:center}
6687
- .iso-scene{background:#f0ede6;cursor:default;overflow:hidden;border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,.18)}
6688
- /* ── Station layout (new grid-based office) ── */
6689
- .iso-station{display:flex;flex-direction:column;align-items:center;gap:2px;cursor:pointer;transition:filter .2s}
6690
- .iso-station:hover{filter:brightness(1.08)}
6691
- .iso-station.iso-orch-walking{animation:orchWalk 2.2s ease-in-out infinite alternate}
6692
- @keyframes orchWalk{0%{transform:translateX(-50%)}100%{transform:translateX(calc(-50% + var(--orch-tx,0px))) translateY(var(--orch-ty,0px))}}
6693
- .iso-station.iso-orch-done{animation:orchDone .6s ease forwards}
6694
- @keyframes orchDone{0%{transform:translateX(-50%) scale(1)}50%{transform:translateX(-50%) scale(1.15)}100%{transform:translateX(-50%) scale(1)}}
6695
- /* Desk */
6696
- .iso-desk{width:90px;height:18px;background:linear-gradient(180deg,#d4a448 0%,#b8832a 100%);border-radius:4px 4px 2px 2px;box-shadow:0 4px 0 #8a5e18,0 6px 8px rgba(0,0,0,.25);border:1px solid #c49038;position:relative;margin-top:2px}
6697
- .iso-desk::after{content:'';position:absolute;bottom:-4px;left:6px;right:6px;height:4px;background:#8a5e18;border-radius:0 0 3px 3px}
6698
- /* Monitor on desk */
6699
- .iso-monitor{width:52px;height:38px;background:#1a1a2c;border:2px solid #3a3070;border-radius:4px;position:absolute;top:-44px;left:50%;transform:translateX(-50%);display:flex;align-items:center;justify-content:center}
6700
- .iso-monitor::before{content:'';position:absolute;bottom:-6px;left:50%;transform:translateX(-50%);width:8px;height:6px;background:#252436;border-radius:0 0 2px 2px}
6701
- .iso-monitor-screen{width:42px;height:28px;background:rgba(80,60,180,.3);border-radius:2px;display:flex;align-items:center;justify-content:center}
6702
- .iso-monitor-blink{width:6px;height:6px;border-radius:50%;background:#6366f1;animation:monBlink .8s ease-in-out infinite}
6703
- @keyframes monBlink{0%,100%{opacity:1;box-shadow:0 0 6px #6366f1}50%{opacity:.3;box-shadow:none}}
6704
- /* Tool badge emoji floating above desk */
6705
- .iso-tool-badge{font-size:18px;line-height:1;filter:drop-shadow(0 2px 4px rgba(0,0,0,.3));margin-bottom:-2px;user-select:none}
6708
+ .iso-scene{background:#f0ede6;cursor:default;overflow:hidden;border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,.18);width:100%}
6709
+ /* ── Station grid layout ── */
6710
+ .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}
6711
+ .iso-station:hover{filter:brightness(1.06);transform:translateY(-2px)}
6712
+ .iso-station.iso-orch-walking{animation:orchWalkGrid 1.8s ease-in-out infinite alternate}
6713
+ @keyframes orchWalkGrid{0%{transform:translateX(0) scale(1)}100%{transform:translateX(var(--orch-tx,24px)) scale(1.04)}}
6714
+ .iso-station.iso-orch-done{animation:orchBounce .7s ease forwards}
6715
+ @keyframes orchBounce{0%{transform:scale(1)}40%{transform:scale(1.18) translateY(-6px)}100%{transform:scale(1)}}
6716
+ /* Desk — CSS 3D look */
6717
+ .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}
6718
+ .iso-desk::after{content:'';position:absolute;bottom:-4px;left:8px;right:8px;height:4px;background:#7a5010;border-radius:0 0 3px 3px}
6719
+ /* Monitor — sits on desk */
6720
+ .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}
6721
+ .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}
6722
+ .iso-monitor-screen{width:44px;height:28px;background:rgba(60,40,160,.35);border-radius:2px;display:flex;align-items:center;justify-content:center}
6723
+ .iso-monitor-blink{width:7px;height:7px;border-radius:50%;background:#6366f1;animation:monBlink .9s ease-in-out infinite}
6724
+ @keyframes monBlink{0%,100%{opacity:1;box-shadow:0 0 8px #6366f1}50%{opacity:.25;box-shadow:none}}
6725
+ /* Tool badge */
6726
+ .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}
6706
6727
  /* Animated status chip for [bracket tokens] */
6707
6728
  .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}
6708
6729
  @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)}}
@@ -6715,7 +6736,7 @@ input:focus,textarea:focus{border-color:var(--green3)}
6715
6736
  .iso-orch-wrap{transition:transform .2s}
6716
6737
  .iso-orch-wrap.prl-head{animation:isoCharBob 1.4s ease-in-out infinite}
6717
6738
  /* Thought bubble / speech bubble above character */
6718
- .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:nowrap;max-width:110px;overflow:hidden;text-overflow:ellipsis;line-height:1.4;transition:all .25s;pointer-events:none;backdrop-filter:blur(4px)}
6739
+ .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:nowrap;max-width:130px;overflow:hidden;text-overflow:ellipsis;line-height:1.5;transition:all .25s;pointer-events:none;backdrop-filter:blur(6px);text-align:center}
6719
6740
  .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}
6720
6741
  .iso-bubble--orch{font-size:9px;padding:3px 9px;border-radius:12px;border-color:#818cf8;color:#a5b4fc;background:rgba(20,15,50,.9)}
6721
6742
  @keyframes isoBubblePop{0%{transform:scale(.8) translateY(4px);opacity:.4}100%{transform:scale(1) translateY(0);opacity:1}}