nothumanallowed 13.5.10 → 13.5.12
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 +1 -1
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +208 -67
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.12",
|
|
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
|
+
export const VERSION = '13.5.12';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -3798,8 +3798,11 @@ function isoCharSvg(opts) {
|
|
|
3798
3798
|
var isDone = opts.isDone;
|
|
3799
3799
|
var scale = opts.scale || 1;
|
|
3800
3800
|
var accentColor = opts.accentColor || \x27#6366f1\x27;
|
|
3801
|
-
var idx = opts.emojiIdx
|
|
3802
|
-
|
|
3801
|
+
var idx = opts.emojiIdx;
|
|
3802
|
+
// idx === 99 means orchestrator — use crown+suit combo
|
|
3803
|
+
var emoji = (idx === 99)
|
|
3804
|
+
? (String.fromCodePoint(0x1F451) + String.fromCodePoint(0x1F9D1,0x200D,0x1F4BC))
|
|
3805
|
+
: AGENT_EMOJIS[(idx || 0) % AGENT_EMOJIS.length];
|
|
3803
3806
|
var sz = Math.round(52 * scale);
|
|
3804
3807
|
var glowColor = isActive ? accentColor : (isDone ? \x27#22c55e\x27 : \x27transparent\x27);
|
|
3805
3808
|
var glowFilter = (isActive || isDone) ? (\x27filter:drop-shadow(0 0 8px \x27+glowColor+\x27aa)\x27) : \x27\x27;
|
|
@@ -3841,6 +3844,61 @@ function agentPalette(lbl) {
|
|
|
3841
3844
|
return {skin: skins[i], shirt: shirts[i], hair: hairs[i]};
|
|
3842
3845
|
}
|
|
3843
3846
|
|
|
3847
|
+
// Tool emoji map — specific icon per agent/tool type, fallback to default
|
|
3848
|
+
var TOOL_EMOJI_MAP = {
|
|
3849
|
+
websearch: String.fromCodePoint(0x1F50D),
|
|
3850
|
+
search: String.fromCodePoint(0x1F50D),
|
|
3851
|
+
browser: String.fromCodePoint(0x1F310),
|
|
3852
|
+
email: String.fromCodePoint(0x1F4E7),
|
|
3853
|
+
gmail: String.fromCodePoint(0x1F4E7),
|
|
3854
|
+
calendar: String.fromCodePoint(0x1F4C5),
|
|
3855
|
+
github: String.fromCodePoint(0x1F431),
|
|
3856
|
+
notion: String.fromCodePoint(0x1F4D3),
|
|
3857
|
+
slack: String.fromCodePoint(0x1F4AC),
|
|
3858
|
+
data: String.fromCodePoint(0x1F4CA),
|
|
3859
|
+
analyst: String.fromCodePoint(0x1F4CA),
|
|
3860
|
+
writer: String.fromCodePoint(0x270F,0xFE0F),
|
|
3861
|
+
summary: String.fromCodePoint(0x1F4CB),
|
|
3862
|
+
research: String.fromCodePoint(0x1F52C),
|
|
3863
|
+
canvas: String.fromCodePoint(0x1F3A8),
|
|
3864
|
+
security: String.fromCodePoint(0x1F6E1,0xFE0F),
|
|
3865
|
+
devops: String.fromCodePoint(0x2699,0xFE0F),
|
|
3866
|
+
code: String.fromCodePoint(0x1F4BB),
|
|
3867
|
+
file: String.fromCodePoint(0x1F4C2),
|
|
3868
|
+
drive: String.fromCodePoint(0x1F4BE),
|
|
3869
|
+
maps: String.fromCodePoint(0x1F5FA,0xFE0F),
|
|
3870
|
+
voice: String.fromCodePoint(0x1F3A4),
|
|
3871
|
+
pdf: String.fromCodePoint(0x1F4DC),
|
|
3872
|
+
document: String.fromCodePoint(0x1F4DC),
|
|
3873
|
+
task: String.fromCodePoint(0x2705),
|
|
3874
|
+
contacts: String.fromCodePoint(0x1F4F1),
|
|
3875
|
+
reminder: String.fromCodePoint(0x23F0),
|
|
3876
|
+
news: String.fromCodePoint(0x1F4F0),
|
|
3877
|
+
image: String.fromCodePoint(0x1F5BC,0xFE0F),
|
|
3878
|
+
video: String.fromCodePoint(0x1F3AC),
|
|
3879
|
+
music: String.fromCodePoint(0x1F3B5),
|
|
3880
|
+
translate: String.fromCodePoint(0x1F30D),
|
|
3881
|
+
math: String.fromCodePoint(0x1F9EE),
|
|
3882
|
+
sql: String.fromCodePoint(0x1F5C4,0xFE0F),
|
|
3883
|
+
api: String.fromCodePoint(0x1F517),
|
|
3884
|
+
test: String.fromCodePoint(0x1F9EA),
|
|
3885
|
+
monitor: String.fromCodePoint(0x1F4F6),
|
|
3886
|
+
_default: String.fromCodePoint(0x1F527) // wrench as fallback
|
|
3887
|
+
};
|
|
3888
|
+
|
|
3889
|
+
function getNodeEmoji(n) {
|
|
3890
|
+
var lbl = (n.label || n.agent || '').toLowerCase();
|
|
3891
|
+
var icon = n.icon || '';
|
|
3892
|
+
// Check by label keywords
|
|
3893
|
+
var keys = Object.keys(TOOL_EMOJI_MAP);
|
|
3894
|
+
for (var ki = 0; ki < keys.length; ki++) {
|
|
3895
|
+
if (keys[ki] !== '_default' && lbl.indexOf(keys[ki]) >= 0) return TOOL_EMOJI_MAP[keys[ki]];
|
|
3896
|
+
}
|
|
3897
|
+
// If icon looks like an emoji code point (not HTML entity), use it
|
|
3898
|
+
if (icon && icon.length > 0 && icon.charCodeAt(0) > 127) return icon;
|
|
3899
|
+
return TOOL_EMOJI_MAP._default;
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3844
3902
|
function renderStudioNodes() {
|
|
3845
3903
|
var el = document.getElementById('studioNodes');
|
|
3846
3904
|
if (!el) return;
|
|
@@ -3855,78 +3913,142 @@ function renderStudioNodes() {
|
|
|
3855
3913
|
var totalCount = nodes.length;
|
|
3856
3914
|
var showMaster = hasActive || doneCount > 0;
|
|
3857
3915
|
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3916
|
+
var phaseLabel2 = hasActive
|
|
3917
|
+
? (\x27Workflow in esecuzione \u2014 \x27+doneCount+\x27/\x27+totalCount)
|
|
3918
|
+
: (doneCount===totalCount && totalCount>0 ? \x27Workflow completato\x27 : \x27Workflow pianificato\x27);
|
|
3919
|
+
var phaseColor2 = hasActive ? \x27#6366f1\x27 : (doneCount===totalCount && totalCount>0 ? \x27#22c55e\x27 : \x27#6b7280\x27);
|
|
3920
|
+
|
|
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));
|
|
3925
|
+
var rows = Math.ceil(totalStations / cols);
|
|
3926
|
+
|
|
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">🔍</span>\x27
|
|
3942
|
+
: (isDone ? \x27<span style="color:#22c55e;font-size:13px">✓</span>\x27
|
|
3943
|
+
: (isActive ? \x27<span class="iso-monitor-blink"></span>\x27
|
|
3944
|
+
: \x27<span style="font-size:8px;opacity:.35;color:#818cf8">■</span>\x27));
|
|
3945
|
+
var bubbleText = isOrch
|
|
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+
|
|
3966
|
+
\x27</div>\x27;
|
|
3967
|
+
}
|
|
3861
3968
|
|
|
3862
|
-
var
|
|
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
|
|
3863
3974
|
nodes.forEach(function(n, idx) {
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
var col = (ISO_COLS === 1) ? 2.5 : idx * colStep;
|
|
3874
|
-
var row = 3.5;
|
|
3875
|
-
var pos = isoProject(col, row);
|
|
3876
|
-
var px = pos.x; var py = pos.y + 80;
|
|
3877
|
-
var charScale = 1.1;
|
|
3878
|
-
var zIdx = Math.round(py + 100);
|
|
3879
|
-
|
|
3880
|
-
// Bubble: only show when active (live text) or done (checkmark)
|
|
3881
|
-
var bubbleText = isActive ? \x27...lavora\x27 : (isDone ? \x27\u2714 fatto\x27 : (isErr ? \x27\u2715 errore\x27 : \x27\x27));
|
|
3882
|
-
var bubbleColor = isActive ? \x27#6366f1\x27 : (isDone ? \x27#22c55e\x27 : \x27#ef4444\x27);
|
|
3883
|
-
void pal; // palette no longer used for character rendering
|
|
3884
|
-
var charSvg = isoCharSvg({emojiIdx: idx, isActive: isActive, isDone: isDone, scale: charScale, accentColor: accentColor});
|
|
3885
|
-
var charW = Math.round(52 * charScale); var charH = Math.round(52 * charScale);
|
|
3886
|
-
|
|
3887
|
-
agentsHtml += \x27<div class="iso-agent" data-agent-label="\x27+esc(lbl)+\x27" style="position:absolute;left:\x27+(px-charW/2)+\x27px;top:\x27+(py-charH)+\x27px;z-index:\x27+zIdx+\x27;display:flex;flex-direction:column;align-items:center;gap:3px;cursor:pointer" onclick="studioScrollToAgent(this.getAttribute(String.fromCharCode(100,97,116,97,45,97,103,101,110,116,45,108,97,98,101,108)))">\x27;
|
|
3888
|
-
// Bubble — bigger, left-aligned (no mirror issue)
|
|
3889
|
-
if (bubbleText || isActive) {
|
|
3890
|
-
agentsHtml += \x27<div class="iso-bubble\x27+(isActive?\x27 iso-bubble--active\x27:\x27\x27)+\x27" id="isobubble_\x27+idx+\x27" style="border-color:\x27+bubbleColor+\x27;color:\x27+bubbleColor+\x27;min-width:80px;max-width:140px;font-size:10px;padding:4px 10px;text-align:left">\x27+esc(bubbleText)+\x27</div>\x27;
|
|
3891
|
-
} else {
|
|
3892
|
-
agentsHtml += \x27<div class="iso-bubble" id="isobubble_\x27+idx+\x27" style="visibility:hidden;min-width:80px"></div>\x27;
|
|
3893
|
-
}
|
|
3894
|
-
agentsHtml += charSvg;
|
|
3895
|
-
agentsHtml += \x27<div class="iso-name" style="font-size:10px;font-weight:700;color:\x27+(isDone?\x27#22c55e\x27:(isActive?\x27#818cf8\x27:(isErr?\x27#ef4444\x27:\x27#555\x27)))+\x27;text-shadow:0 1px 3px rgba(255,255,255,.8)">\x27+esc(lbl)+\x27</div>\x27;
|
|
3896
|
-
// Desk — lighter wood color for bright office
|
|
3897
|
-
agentsHtml += isoDeskSvg(px, py - charH/2, accentColor);
|
|
3898
|
-
agentsHtml += \x27</div>\x27;
|
|
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
|
+
);
|
|
3899
3984
|
});
|
|
3900
3985
|
|
|
3901
|
-
//
|
|
3902
|
-
var
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
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;
|
|
3996
|
+
// Baseboard
|
|
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;
|
|
4007
|
+
}
|
|
3915
4008
|
}
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
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;
|
|
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;
|
|
4024
|
+
// Chandelier
|
|
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;
|
|
4032
|
+
floorSvg += \x27</svg>\x27;
|
|
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;
|
|
3921
4040
|
|
|
3922
4041
|
el.innerHTML =
|
|
3923
4042
|
\x27<div class="prl-wrap" style="border-color:\x27+phaseColor2+\x2744;padding-bottom:8px">\x27+
|
|
3924
4043
|
\x27<div class="prl-header"><span class="prl-phase-chip" style="--pc:\x27+phaseColor2+\x27">\x27+phaseLabel2+\x27</span></div>\x27+
|
|
3925
|
-
\x27<div style="
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
4044
|
+
\x27<div class="iso-scene" style="position:relative">\x27+
|
|
4045
|
+
floorSvg+
|
|
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+
|
|
4051
|
+
stationsHtml+
|
|
3930
4052
|
\x27</div>\x27+
|
|
3931
4053
|
\x27</div>\x27+
|
|
3932
4054
|
\x27</div>\x27;
|
|
@@ -6533,7 +6655,26 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
6533
6655
|
/* Plant right */
|
|
6534
6656
|
.prl-office-plant2{position:absolute;bottom:14px;right:8px;width:22px;height:42px;z-index:2;pointer-events:none}
|
|
6535
6657
|
/* ── ISOMETRIC JRPG SCENE ── */
|
|
6536
|
-
.iso-scene{
|
|
6658
|
+
.iso-scene-wrap{width:100%;overflow-x:auto;display:flex;justify-content:center}
|
|
6659
|
+
.iso-scene{background:#f0ede6;cursor:default;overflow:hidden;border-radius:12px;box-shadow:0 4px 24px rgba(0,0,0,.18);width:100%}
|
|
6660
|
+
/* ── Station grid layout ── */
|
|
6661
|
+
.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}
|
|
6662
|
+
.iso-station:hover{filter:brightness(1.06);transform:translateY(-2px)}
|
|
6663
|
+
.iso-station.iso-orch-walking{animation:orchWalkGrid 1.8s ease-in-out infinite alternate}
|
|
6664
|
+
@keyframes orchWalkGrid{0%{transform:translateX(0) scale(1)}100%{transform:translateX(var(--orch-tx,24px)) scale(1.04)}}
|
|
6665
|
+
.iso-station.iso-orch-done{animation:orchBounce .7s ease forwards}
|
|
6666
|
+
@keyframes orchBounce{0%{transform:scale(1)}40%{transform:scale(1.18) translateY(-6px)}100%{transform:scale(1)}}
|
|
6667
|
+
/* Desk — CSS 3D look */
|
|
6668
|
+
.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}
|
|
6669
|
+
.iso-desk::after{content:'';position:absolute;bottom:-4px;left:8px;right:8px;height:4px;background:#7a5010;border-radius:0 0 3px 3px}
|
|
6670
|
+
/* Monitor — sits on desk */
|
|
6671
|
+
.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}
|
|
6672
|
+
.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}
|
|
6673
|
+
.iso-monitor-screen{width:44px;height:28px;background:rgba(60,40,160,.35);border-radius:2px;display:flex;align-items:center;justify-content:center}
|
|
6674
|
+
.iso-monitor-blink{width:7px;height:7px;border-radius:50%;background:#6366f1;animation:monBlink .9s ease-in-out infinite}
|
|
6675
|
+
@keyframes monBlink{0%,100%{opacity:1;box-shadow:0 0 8px #6366f1}50%{opacity:.25;box-shadow:none}}
|
|
6676
|
+
/* Tool badge */
|
|
6677
|
+
.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}
|
|
6537
6678
|
/* Animated status chip for [bracket tokens] */
|
|
6538
6679
|
.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}
|
|
6539
6680
|
@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)}}
|
|
@@ -6546,7 +6687,7 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
6546
6687
|
.iso-orch-wrap{transition:transform .2s}
|
|
6547
6688
|
.iso-orch-wrap.prl-head{animation:isoCharBob 1.4s ease-in-out infinite}
|
|
6548
6689
|
/* Thought bubble / speech bubble above character */
|
|
6549
|
-
.iso-bubble{font-size:
|
|
6690
|
+
.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}
|
|
6550
6691
|
.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}
|
|
6551
6692
|
.iso-bubble--orch{font-size:9px;padding:3px 9px;border-radius:12px;border-color:#818cf8;color:#a5b4fc;background:rgba(20,15,50,.9)}
|
|
6552
6693
|
@keyframes isoBubblePop{0%{transform:scale(.8) translateY(4px);opacity:.4}100%{transform:scale(1) translateY(0);opacity:1}}
|