@viberaven/cli 1.3.1 → 1.3.5

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.
Files changed (4) hide show
  1. package/README.md +109 -128
  2. package/dist/cli.js +3057 -336
  3. package/dist/cli.js.map +2 -2
  4. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -319,6 +319,9 @@ function isSecretFileName(fileName) {
319
319
  if (SECRET_FILE_NAMES.has(fileName.toLowerCase())) {
320
320
  return true;
321
321
  }
322
+ if (SOURCE_CODE_FILE_EXT.test(fileName)) {
323
+ return false;
324
+ }
322
325
  return SECRET_PATTERNS.some((pattern) => pattern.test(fileName));
323
326
  }
324
327
  function isLikelyBinary(buffer) {
@@ -381,7 +384,7 @@ function gitignoreGlobToRegex(pattern) {
381
384
  function escapeRegex(value) {
382
385
  return value.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
383
386
  }
384
- var import_node_fs2, import_node_path2, ALWAYS_SKIP, SECRET_PATTERNS, SECRET_FILE_NAMES, HIGH_SIGNAL_FILES, STACK_SIGNAL_PATHS, DEFAULT_OPTIONS;
387
+ var import_node_fs2, import_node_path2, ALWAYS_SKIP, SECRET_PATTERNS, SECRET_FILE_NAMES, SOURCE_CODE_FILE_EXT, HIGH_SIGNAL_FILES, STACK_SIGNAL_PATHS, DEFAULT_OPTIONS;
385
388
  var init_fileScanner = __esm({
386
389
  "../../src/station/fileScanner.ts"() {
387
390
  "use strict";
@@ -430,6 +433,7 @@ var init_fileScanner = __esm({
430
433
  "kubeconfig",
431
434
  "dockerconfigjson"
432
435
  ]);
436
+ SOURCE_CODE_FILE_EXT = /\.(?:cjs|cts|jsx?|mjs|mts|tsx?)$/i;
433
437
  HIGH_SIGNAL_FILES = [
434
438
  "package.json",
435
439
  "tsconfig.json",
@@ -11554,7 +11558,7 @@ var VERSION;
11554
11558
  var init_version = __esm({
11555
11559
  "src/version.ts"() {
11556
11560
  "use strict";
11557
- VERSION = "1.3.1";
11561
+ VERSION = "1.3.5";
11558
11562
  }
11559
11563
  });
11560
11564
 
@@ -15844,7 +15848,10 @@ const demo = {
15844
15848
  modelMenuOpen: false,
15845
15849
  reasoningMenuOpen: false,
15846
15850
  contextMenuOpen: false,
15851
+ scopeMenuOpen: false,
15852
+ contextTrayOpen: false,
15847
15853
  accessMenuOpen: false,
15854
+ inspectorExpanded: false,
15848
15855
  pickerChatIndex: 0,
15849
15856
  chatContexts: [{ providerId: null, releaseId: null, cliId: 'codex', modelId: 'gpt-5.5', reasoning: 'High', context: 'Production', accessMode: 'approve', messages: [], activeTask: null }],
15850
15857
  activeRecentChatId: null,
@@ -16006,6 +16013,7 @@ const githubStats = {
16006
16013
  };
16007
16014
 
16008
16015
  let lastRenderedModal = demo.activeModal;
16016
+ let stableModalRender = false;
16009
16017
  const chatScrollCache = {};
16010
16018
  let chatTaskTimer = null;
16011
16019
 
@@ -16226,9 +16234,9 @@ function ProviderMcpPanel(provider) {
16226
16234
  const capabilities = Array.isArray(mcp.capabilities) && mcp.capabilities.length ? mcp.capabilities : ['provider context', 'repo-aware chat'];
16227
16235
  const connectButton = connected
16228
16236
  ? ''
16229
- : '<button type="button" class="vr-mcp-connect-btn" data-action="connect-mcp" data-provider-id="' + escapeHtml(provider.id || '') + '">Connect MCP</button>';
16237
+ : '<button type="button" class="vr-mcp-connect-btn" data-action="connect-mcp" data-provider-id="' + escapeHtml(provider.id || '') + '">Connect</button>';
16230
16238
  return '<section class="vr-provider-mcp-panel ' + (connected ? 'is-connected' : 'is-disconnected') + '">' +
16231
- '<header><span>' + Icon('agent') + '</span><div><strong>' + escapeHtml(connected ? 'MCP connected' : 'Connect MCP') + '</strong><em>' + escapeHtml(connected ? (mcp.source || 'local MCP config') : (mcp.connectCommand || 'Add this provider MCP server in your local MCP config.')) + '</em></div>' + connectButton + '</header>' +
16239
+ '<header><span>' + Icon('code') + '</span><div><strong>' + escapeHtml(connected ? 'Connected' : 'Not connected') + '</strong></div>' + connectButton + '</header>' +
16232
16240
  '<div>' + capabilities.map((item) => '<small>' + escapeHtml(item) + '</small>').join('') + '</div>' +
16233
16241
  '</section>';
16234
16242
  }
@@ -16350,14 +16358,24 @@ function formatDiffPreHtml(diffText) {
16350
16358
 
16351
16359
  function releaseChangelogHtml() {
16352
16360
  const log = demo.releaseChangelog || {};
16353
- if (log.loading) return '<p>Loading changelog\u2026</p>';
16361
+ if (log.loading) return '<p class="vr-changelog-empty">Loading changelog...</p>';
16354
16362
  if (log.error) return '<p class="vr-release-error">' + escapeHtml(log.error) + '</p>';
16355
- if (Array.isArray(log.entries) && log.entries.length) {
16356
- return '<ul class="vr-changelog-list">' + log.entries.map(function(entry) {
16357
- return '<li><strong>' + escapeHtml(entry.short || entry.sha || '') + '</strong> ' + escapeHtml(entry.subject || '') + '<em>' + escapeHtml((entry.author || 'unknown') + ' \xB7 ' + (entry.when || '')) + '</em></li>';
16358
- }).join('') + '</ul>';
16363
+ const entries = Array.isArray(log.entries) ? log.entries : [];
16364
+ if (entries.length) {
16365
+ const visible = entries.slice(0, 6);
16366
+ const hidden = entries.slice(6);
16367
+ const rangeLabel = (log.fromLabel || 'previous') + ' to ' + (log.toLabel || 'selected');
16368
+ const entryHtml = function(entry, compact) {
16369
+ const meta = (entry.author || 'unknown') + (entry.when ? ' - ' + entry.when : '');
16370
+ return '<li class="' + (compact ? 'is-compact' : '') + '"><strong>' + escapeHtml(entry.short || entry.sha || '') + '</strong><span>' + escapeHtml(entry.subject || '') + '</span><em>' + escapeHtml(meta) + '</em></li>';
16371
+ };
16372
+ return '<div class="vr-changelog-summary"><span>Release changes</span><strong>' + String(entries.length) + ' commit' + (entries.length === 1 ? '' : 's') + '</strong><em>' + escapeHtml(rangeLabel) + '</em></div>' +
16373
+ '<ul class="vr-changelog-list is-preview">' + visible.map(function(entry) { return entryHtml(entry, false); }).join('') + '</ul>' +
16374
+ (hidden.length
16375
+ ? '<details class="vr-changelog-more"><summary>Show ' + String(hidden.length) + ' older commit' + (hidden.length === 1 ? '' : 's') + '</summary><ul class="vr-changelog-list is-condensed">' + hidden.map(function(entry) { return entryHtml(entry, true); }).join('') + '</ul></details>'
16376
+ : '');
16359
16377
  }
16360
- return '<p>No commits between ' + escapeHtml(log.fromLabel || 'previous') + ' and ' + escapeHtml(log.toLabel || 'selected') + '.</p>';
16378
+ return '<p class="vr-changelog-empty">No commits between ' + escapeHtml(log.fromLabel || 'previous') + ' and ' + escapeHtml(log.toLabel || 'selected') + '.</p>';
16361
16379
  }
16362
16380
 
16363
16381
  async function runReleaseCompare() {
@@ -16835,6 +16853,8 @@ function Icon(name) {
16835
16853
  refresh: '<path d="M20 12a8 8 0 0 1-14.5 4.7"/><path d="M4 17h5v-5"/><path d="M4 12A8 8 0 0 1 18.5 7.3"/><path d="M20 7h-5v5"/>',
16836
16854
  prompt: '<path d="M4 5h16v14H4V5Z"/><path d="m8 10 3 2-3 2M13 15h4"/>',
16837
16855
  external: '<path d="M7 7h10v10"/><path d="M7 17 17 7"/><path d="M5 5v14h14"/>',
16856
+ expand: '<path d="M8 3H3v5M16 3h5v5M3 16v5h5M21 16v5h-5"/><path d="M3 8l6-6M21 8l-6-6M3 16l6 6M21 16l-6 6"/>',
16857
+ collapse: '<path d="M9 3v6H3M15 3v6h6M9 21v-6H3M15 21v-6h6"/><path d="M3 9l6-6M21 9l-6-6M3 15l6 6M21 15l-6 6"/>',
16838
16858
  x: '<path d="M6 6l12 12M18 6 6 18"/>',
16839
16859
  clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',
16840
16860
  cloud: '<path d="M17.5 18H8a5 5 0 1 1 1.3-9.8A6 6 0 0 1 20 12.5 3.5 3.5 0 0 1 17.5 18Z"/>',
@@ -16843,6 +16863,7 @@ function Icon(name) {
16843
16863
  play: '<path d="M8 5v14l11-7-11-7Z"/>',
16844
16864
  code: '<path d="m8 9-4 3 4 3M16 9l4 3-4 3M14 5l-4 14"/>',
16845
16865
  arrowUp: '<path d="M12 19V5"/><path d="m6 11 6-6 6 6"/>',
16866
+ pause: '<path d="M9 6v12M15 6v12"/>',
16846
16867
  stop: '<rect x="6" y="6" width="12" height="12" rx="2.5"/>',
16847
16868
  chevronRight: '<path d="m9 6 6 6-6 6"/>',
16848
16869
  };
@@ -17430,7 +17451,7 @@ function resetLaunchPreview() {
17430
17451
  demo.verified = false;
17431
17452
  demo.providerPickerOpen = false;
17432
17453
  demo.activeModal = null;
17433
- demo.activeStudioTab = 'chat';
17454
+ if (newChatTarget || isRecentChatDrop) demo.activeStudioTab = 'chat';
17434
17455
  demo.selectedCliId = 'codex';
17435
17456
  demo.cliConnected = true;
17436
17457
  demo.studioExpanded = false;
@@ -17594,8 +17615,9 @@ function VersionTimeline() {
17594
17615
  }
17595
17616
 
17596
17617
  function ModalShell(kind, body) {
17597
- return '<section class="vr-modal-backdrop" data-modal-backdrop="' + escapeHtml(kind) + '" aria-label="Preview detail modal">' +
17598
- '<div class="vr-modal-card vr-modal-' + escapeHtml(kind) + '" role="dialog" aria-modal="true">' +
17618
+ const stableClass = stableModalRender ? ' is-stable-render' : '';
17619
+ return '<section class="vr-modal-backdrop' + stableClass + '" data-modal-backdrop="' + escapeHtml(kind) + '" aria-label="Preview detail modal">' +
17620
+ '<div class="vr-modal-card vr-modal-' + escapeHtml(kind) + stableClass + '" role="dialog" aria-modal="true">' +
17599
17621
  '<button class="vr-modal-close" type="button" data-action="close-modal" aria-label="Close">' + Icon('x') + '</button>' +
17600
17622
  body +
17601
17623
  '</div>' +
@@ -17903,19 +17925,28 @@ function resetCliConnectFlow(options) {
17903
17925
  }
17904
17926
  }
17905
17927
 
17906
- async function runStudioShellCommand(command, label) {
17928
+ async function runStudioShellCommand(command, label, cliId) {
17907
17929
  const trimmed = String(command || '').trim();
17908
17930
  if (!trimmed) return;
17909
17931
  appendTerminalLines(['$ ' + trimmed]);
17910
17932
  if (label) demo.cliTerminalTitle = label;
17911
17933
  render();
17912
17934
  try {
17935
+ const requestedCliId = typeof cliId === 'string' && (cliId === 'codex' || cliId === 'claude' || cliId === 'gemini') ? cliId : undefined;
17913
17936
  const response = await fetch('/api/cli-agents/run-command', {
17914
17937
  method: 'POST',
17915
17938
  headers: { 'content-type': 'application/json' },
17916
- body: JSON.stringify({ command: trimmed }),
17939
+ body: JSON.stringify({ command: trimmed, ...(requestedCliId ? { cliId: requestedCliId } : {}) }),
17917
17940
  });
17918
- const payload = response.ok ? await response.json() : null;
17941
+ const payload = await response.json().catch(() => null);
17942
+ if (!response.ok) {
17943
+ appendTerminalLines([
17944
+ String(payload?.message || payload?.error || 'Command could not run from Studio terminal.'),
17945
+ ''
17946
+ ]);
17947
+ render();
17948
+ return;
17949
+ }
17919
17950
  appendTerminalLines([
17920
17951
  String(payload?.output || payload?.message || 'Command finished.'),
17921
17952
  ''
@@ -18387,11 +18418,12 @@ function ModelPicker(index) {
18387
18418
  const selectedModel = selectedModelLabel(index);
18388
18419
  const scoped = demo.pickerChatIndex === index;
18389
18420
  const access = accessModes.find((mode) => mode.id === chat.accessMode) || accessModes[1];
18421
+ const accessButtonLabel = access.id === 'approve' ? 'Approve for me' : access.id === 'ask' ? 'Ask approval' : 'Full access';
18390
18422
  return '<div class="vr-model-picker">' +
18391
18423
  '<button type="button" data-action="toggle-reasoning" data-chat-index="' + String(index) + '"><span>Reasoning</span><strong>' + escapeHtml(chat.reasoning) + '</strong><i></i></button>' +
18392
18424
  '<button type="button" data-action="toggle-models" data-chat-index="' + String(index) + '"><span>Model</span><strong>' + escapeHtml(selectedModel) + '</strong><i></i></button>' +
18393
18425
  '<button type="button" data-action="toggle-context" data-chat-index="' + String(index) + '"><span>Context</span><strong>' + escapeHtml(chat.context) + '</strong><i></i></button>' +
18394
- '<button type="button" data-action="toggle-access" data-chat-index="' + String(index) + '"><span>Access</span><strong>' + escapeHtml(access.label) + '</strong><i></i></button>' +
18426
+ '<button type="button" data-action="toggle-access" data-chat-index="' + String(index) + '"><span>Access</span><strong>' + escapeHtml(accessButtonLabel) + '</strong><i></i></button>' +
18395
18427
  (scoped && demo.reasoningMenuOpen ? '<div class="vr-model-menu is-reasoning" role="menu"><p>Reasoning</p>' + reasoningLevels.map((level) =>
18396
18428
  '<button type="button" data-reasoning="' + escapeHtml(level) + '" data-chat-index="' + String(index) + '">' + escapeHtml(level) + (chat.reasoning === level ? '<b></b>' : '') + '</button>'
18397
18429
  ).join('') + '</div>' : '') +
@@ -18411,7 +18443,7 @@ function ChatBlockersSummary(cards) {
18411
18443
  const blockers = Array.isArray(cards.blockers) ? cards.blockers : [];
18412
18444
  const count = typeof cards.blockerCount === 'number' ? cards.blockerCount : blockers.length;
18413
18445
  if (!blockers.length) return '';
18414
- return '<section><header><strong>Blockers Summary</strong><b>' + String(count) + ' blocking</b></header>' +
18446
+ return '<section class="vr-chat-blockers-card"><header><strong>Blockers Summary</strong><b>' + String(count) + ' blocking</b></header>' +
18415
18447
  blockers.map((blocker) =>
18416
18448
  '<span><i data-tone="' + escapeHtml(blocker.tone || 'neutral') + '"></i><em>' + escapeHtml(blocker.title || 'Launch blocker') +
18417
18449
  (blocker.detail ? '<small>' + escapeHtml(blocker.detail) + '</small>' : '') +
@@ -18966,27 +18998,54 @@ function ChatMissionStatusStrip() {
18966
18998
  (provider.iconHtml || '<img src="' + providerAssetSrc(provider) + '" alt="" />') +
18967
18999
  '</span>'
18968
19000
  ).join('');
19001
+ const versionDots = releases.slice(0, 4).map((release) =>
19002
+ '<span class="vr-chat-version-dot ' + (release.id === demo.selectedReleaseId ? 'is-selected' : '') + '" draggable="true" data-release="' + escapeHtml(release.id) + '" data-tone="' + escapeHtml(release.tone || 'planned') + '" title="' + escapeHtml(release.label + ' \xB7 ' + release.meta) + '">' +
19003
+ '<small>' + escapeHtml(String(release.label || '').replace(/^v/i, '')) + '</small>' +
19004
+ '</span>'
19005
+ ).join('');
18969
19006
  return '<div class="vr-chat-status-strip">' +
18970
19007
  '<button class="vr-chat-gate-chip is-' + tone + '" type="button" data-action="notifications" title="Open launch signals"><i></i>' + escapeHtml(label) + '</button>' +
18971
19008
  (dots ? '<span class="vr-chat-provider-dots" title="Detected providers \u2014 drag one into the chat">' + dots + '</span>' : '') +
19009
+ (versionDots ? '<span class="vr-chat-version-dots" title="Recent versions \u2014 drag one into the chat">' + versionDots + '</span>' : '') +
18972
19010
  '</div>';
18973
19011
  }
18974
19012
 
18975
19013
  function ChatQuickActions(index) {
18976
19014
  const buttons = quickActionButtonSpec(index);
18977
- const plus = '<button type="button" class="vr-chat-plus' + (demo.quickActionsOpen ? ' is-open' : '') + '" data-action="toggle-quick-actions" data-chat-index="' + String(index) + '" title="' + (demo.quickActionsOpen ? 'Hide quick actions' : 'Quick actions') + '" aria-label="Quick actions">' + Icon(demo.quickActionsOpen ? 'x' : 'plus') + '</button>';
18978
- if (!demo.quickActionsOpen) {
18979
- const primary = buttons.find((button) => button.action === 'start-agent-fix') || buttons[0];
18980
- return '<div class="vr-chat-inline-actions is-collapsed">' + plus +
18981
- '<button type="button" class="is-primary" data-chat-index="' + String(index) + '" data-action="' + escapeHtml(primary.action) + '"' + (primary.hint ? ' title="' + escapeHtml(primary.hint) + '"' : '') + '>' +
18982
- Icon(primary.icon) + '<span>' + escapeHtml(primary.label) + '</span></button>' +
18983
- '</div>';
18984
- }
18985
- return '<div class="vr-chat-inline-actions">' + plus +
18986
- buttons.map((button) =>
19015
+ const primary = buttons.find((button) => button.action === 'start-agent-fix') || buttons[0];
19016
+ const scoped = demo.pickerChatIndex === index;
19017
+ const expanded = scoped && demo.quickActionsOpen
19018
+ ? '<div class="vr-chat-command-popover">' + buttons.map((button) =>
18987
19019
  '<button type="button" class="' + (button.primary ? 'is-primary' : button.muted ? 'is-muted' : '') + '" data-chat-index="' + String(index) + '" data-action="' + escapeHtml(button.action) + '"' + (button.hint ? ' title="' + escapeHtml(button.hint) + '"' : '') + '>' +
18988
19020
  Icon(button.icon) + '<span>' + escapeHtml(button.label) + '</span></button>'
18989
- ).join('') +
19021
+ ).join('') + '</div>'
19022
+ : '';
19023
+ return '<div class="vr-chat-inline-actions">' +
19024
+ '<button type="button" data-action="add-context" data-chat-index="' + String(index) + '">' + Icon('plus') + '<span>Add context</span></button>' +
19025
+ '<button type="button" data-action="prompt" data-chat-index="' + String(index) + '">' + Icon('prompt') + '<span>Mention</span></button>' +
19026
+ '<span class="vr-chat-command-trigger"><button type="button" data-action="toggle-quick-actions" data-chat-index="' + String(index) + '" title="' + escapeHtml(primary.hint || 'Open commands') + '">' + Icon('code') + '<span>Commands</span></button>' +
19027
+ expanded +
19028
+ '</span>' +
19029
+ '</div>';
19030
+ }
19031
+
19032
+ function ChatComposerScope(index) {
19033
+ const chat = chatContext(index);
19034
+ const scoped = demo.pickerChatIndex === index;
19035
+ const menu = scoped && demo.scopeMenuOpen
19036
+ ? '<div class="vr-scope-menu" role="menu"><p>Context</p>' + contextLevels.map((level) =>
19037
+ '<button type="button" data-context="' + escapeHtml(level) + '" data-chat-index="' + String(index) + '">' +
19038
+ Icon(level === 'Security' ? 'shield' : level === 'Release' ? 'branch' : level === 'Provider' ? 'cube' : 'spark') +
19039
+ '<span>' + escapeHtml(level) + '</span>' + (chat.context === level ? '<b></b>' : '') +
19040
+ '</button>'
19041
+ ).join('') + '</div>'
19042
+ : '';
19043
+ return '<div class="vr-composer-scope-wrap">' +
19044
+ '<button type="button" class="vr-composer-scope" data-action="toggle-scope-menu" data-chat-index="' + String(index) + '">' +
19045
+ Icon(chat.context === 'Security' ? 'shield' : chat.context === 'Release' ? 'branch' : chat.context === 'Provider' ? 'cube' : 'spark') +
19046
+ '<strong>' + escapeHtml(chat.context || 'Production') + '</strong><i></i>' +
19047
+ '</button>' +
19048
+ menu +
18990
19049
  '</div>';
18991
19050
  }
18992
19051
 
@@ -19014,6 +19073,7 @@ function ContextDropZone(index, showAttached) {
19014
19073
  const context = chatContext(index);
19015
19074
  const provider = show && context.providerId ? providers.find((item) => item.id === context.providerId) : null;
19016
19075
  const release = show && context.releaseId ? releases.find((item) => item.id === context.releaseId) : null;
19076
+ if (!provider && !release && !demo.dropActive) return '';
19017
19077
  return '<div class="vr-provider-drop-zone ' + (demo.dropActive ? 'is-active' : '') + ((provider || release) ? ' has-provider' : '') + '" data-chat-drop="true" data-chat-index="' + String(index) + '">' +
19018
19078
  '<span class="vr-provider-drop-label">' + (provider || release ? 'Context attached' : 'Drop provider or version here to add context') + '</span>' +
19019
19079
  (provider ? contextChipHtml({
@@ -19035,6 +19095,65 @@ function ContextDropZone(index, showAttached) {
19035
19095
  '</div>';
19036
19096
  }
19037
19097
 
19098
+ function ContextTray(index) {
19099
+ if (!(demo.pickerChatIndex === index && demo.contextTrayOpen)) return '';
19100
+ const providerItems = orderedProviders().filter((provider) => provider.state !== 'not_detected').slice(0, 6);
19101
+ const releaseItems = releases.slice(0, 4);
19102
+ const providersHtml = providerItems.map((provider) =>
19103
+ '<button type="button" draggable="true" data-provider="' + escapeHtml(provider.id) + '" data-context-provider="' + escapeHtml(provider.id) + '" data-chat-index="' + String(index) + '">' +
19104
+ '<span>' + (provider.iconHtml || '<img src="' + providerAssetSrc(provider) + '" alt="" />') + '</span>' +
19105
+ '<strong>' + escapeHtml(provider.name) + '</strong>' +
19106
+ '<em>' + escapeHtml(stackSlots[provider.id] || provider.area) + '</em>' +
19107
+ '</button>'
19108
+ ).join('');
19109
+ const releasesHtml = releaseItems.map((release) =>
19110
+ '<button type="button" draggable="true" data-release="' + escapeHtml(release.id) + '" data-context-release="' + escapeHtml(release.id) + '" data-chat-index="' + String(index) + '">' +
19111
+ '<span>' + Icon('branch') + '</span>' +
19112
+ '<strong>' + escapeHtml(release.label) + '</strong>' +
19113
+ '<em>' + escapeHtml(release.meta || release.branch) + '</em>' +
19114
+ '</button>'
19115
+ ).join('');
19116
+ return '<div class="vr-context-tray">' +
19117
+ '<header><strong>Add context</strong><button type="button" data-action="close-context-tray" data-chat-index="' + String(index) + '" aria-label="Close context tray">' + Icon('x') + '</button></header>' +
19118
+ '<section><p>Providers</p><div>' + (providersHtml || '<span class="vr-context-tray-empty">No providers detected yet.</span>') + '</div></section>' +
19119
+ '<section><p>Versions</p><div>' + (releasesHtml || '<span class="vr-context-tray-empty">No versions detected yet.</span>') + '</div></section>' +
19120
+ '</div>';
19121
+ }
19122
+
19123
+ function ChatEnvironmentConnectCard() {
19124
+ const slots = [
19125
+ { label: 'GitHub', providerId: 'github', icon: 'github', action: 'provider' },
19126
+ { label: 'Database', providerId: 'supabase', icon: 'supabase', action: 'provider' },
19127
+ { label: 'Sentry', providerId: 'sentry', icon: 'sentry', action: 'provider' },
19128
+ { label: 'Deployment', providerId: 'vercel', icon: 'vercel', action: 'provider' },
19129
+ { label: 'Payments', providerId: 'stripe', icon: 'stripe', action: 'provider' },
19130
+ { label: 'More', providerId: '', icon: '', action: 'more' },
19131
+ ];
19132
+ const slotHtml = slots.map((slot) => {
19133
+ const provider = slot.providerId ? providers.find((item) => item.id === slot.providerId) : null;
19134
+ const mcp = provider ? providerMcp(provider) : null;
19135
+ const connected = Boolean(mcp && mcp.status === 'connected');
19136
+ const icon = provider
19137
+ ? (provider.iconHtml || '<img src="' + providerAssetSrc(provider) + '" alt="" />')
19138
+ : Icon('plus');
19139
+ const status = connected ? 'Connected' : slot.action === 'more' ? 'Browse' : 'Connect';
19140
+ const attrs = slot.action === 'more'
19141
+ ? 'data-action="add-provider"'
19142
+ : connected
19143
+ ? 'data-provider="' + escapeHtml(slot.providerId) + '"'
19144
+ : 'data-action="connect-mcp" data-provider-id="' + escapeHtml(slot.providerId) + '"';
19145
+ return '<button type="button" class="vr-env-connect-option ' + (connected ? 'is-connected' : 'is-disconnected') + '" ' + attrs + '>' +
19146
+ '<span>' + icon + '</span>' +
19147
+ '<strong>' + escapeHtml(slot.label) + '</strong>' +
19148
+ '<b>' + escapeHtml(status) + '</b>' +
19149
+ '</button>';
19150
+ }).join('');
19151
+ return '<section class="vr-env-connect-card">' +
19152
+ '<header><strong>Connect your environment</strong></header>' +
19153
+ '<div>' + slotHtml + '</div>' +
19154
+ '</section>';
19155
+ }
19156
+
19038
19157
  function StudioChatLane(index) {
19039
19158
  const provider = providers.find((item) => item.id === demo.selectedProviderId) || providers[0];
19040
19159
  const chat = chatContext(index);
@@ -19055,11 +19174,11 @@ function StudioChatLane(index) {
19055
19174
  const sendLabel = laneWorking ? 'Stop connected agent' : 'Send mission to connected agent';
19056
19175
  const gateNotClear = Boolean(currentState.gate && currentState.gate.status && currentState.gate.status !== 'clear');
19057
19176
  const introBlocker = missionCards && Array.isArray(missionCards.blockers) && missionCards.blockers.length ? missionCards.blockers[0] : null;
19058
- const introBody = gateNotClear && introBlocker
19059
- ? '<p><strong>Start here:</strong> ' + escapeHtml(introBlocker.title) + '</p><button class="vr-start-here-cta" type="button" data-action="start-agent-fix" data-chat-index="' + String(index) + '">' + Icon('bolt') + '<span>Fix it with the connected agent</span></button>'
19060
- : '<p>Start a production mission. Drag a provider or version into this chat, or ask what blocks launch.</p>';
19177
+ const introBody = '<p>I\\'m ready to help you debug production issues.<br><strong>Start here:</strong> ' + escapeHtml(gateNotClear && introBlocker ? introBlocker.title : 'connect your code and observability sources.') + '</p>' +
19178
+ (gateNotClear && introBlocker ? '<button class="vr-start-here-cta" type="button" data-action="start-agent-fix" data-chat-index="' + String(index) + '">' + Icon('bolt') + '<span>Fix it with the connected agent</span></button>' : '') +
19179
+ ChatEnvironmentConnectCard();
19061
19180
  const staticIntro = fresh
19062
- ? storyNode('is-agent is-intro', Icon('spark'), '<section class="vr-chat-message is-agent"><div><span><img src="' + mascotUrl() + '" alt="" /></span><p><strong>VibeRaven Agent</strong><em>Ready</em></p></div>' + introBody + '</section>')
19181
+ ? storyNode('is-agent is-intro', Icon('spark'), '<section class="vr-chat-message is-agent vr-chat-intro-message"><div><span><img src="' + mascotUrl() + '" alt="" /></span><p><strong>VibeRaven Agent</strong><b>Agent</b><em class="is-ready">Ready</em></p></div>' + introBody + '</section>')
19063
19182
  : '';
19064
19183
  return '<article class="vr-chat-lane ' + (secondary ? 'is-secondary' : 'is-primary') + '" data-chat-index="' + String(index) + '">' +
19065
19184
  (secondary ? '<button class="vr-chat-close" type="button" data-action="close-chat" data-chat-index="' + String(index) + '" aria-label="Close chat">' + Icon('x') + '</button>' : '') +
@@ -19071,9 +19190,14 @@ function StudioChatLane(index) {
19071
19190
  renderChatMessages(chat, index) +
19072
19191
  '</div>' +
19073
19192
  '<footer class="vr-chat-command-bar">' +
19074
- ChatQuickActions(index) +
19075
19193
  (laneHasTask ? ChatTaskAnimation(index, true) : '') +
19076
- '<div class="vr-chat-composer" data-chat-drop="true" data-chat-index="' + String(index) + '"><textarea class="vr-chat-input" data-chat-input="' + String(index) + '" rows="2" placeholder="Ask VibeRaven anything about this deployment...">' + escapeHtml(chat.draft || '') + '</textarea>' + ContextDropZone(index, true) + ModelPicker(index) + '<button class="vr-chat-send ' + (laneWorking ? 'is-stop' : '') + '" type="button" data-action="' + sendAction + '" data-chat-index="' + String(index) + '" aria-label="' + sendLabel + '">' + Icon(sendIcon) + '</button></div>' +
19194
+ '<div class="vr-chat-composer" data-chat-drop="true" data-chat-index="' + String(index) + '">' +
19195
+ '<div class="vr-composer-top">' + ChatComposerScope(index) + '</div>' +
19196
+ '<textarea class="vr-chat-input" data-chat-input="' + String(index) + '" rows="2" placeholder="Ask VibeRaven anything about this deployment...">' + escapeHtml(chat.draft || '') + '</textarea>' +
19197
+ ContextTray(index) +
19198
+ ContextDropZone(index, true) +
19199
+ '<div class="vr-composer-bottom">' + ChatQuickActions(index) + '<div class="vr-composer-controls">' + ModelPicker(index) + '<button class="vr-chat-send ' + (laneWorking ? 'is-stop' : '') + '" type="button" data-action="' + sendAction + '" data-chat-index="' + String(index) + '" aria-label="' + sendLabel + '">' + Icon(sendIcon) + '</button></div></div>' +
19200
+ '</div>' +
19077
19201
  '</footer>' +
19078
19202
  '</article>';
19079
19203
  }
@@ -19189,16 +19313,42 @@ function buildArchGraph(data, gaps) {
19189
19313
  edges.push({ from: id, to: archAreaTarget(provider.area) });
19190
19314
  });
19191
19315
 
19192
- try {
19193
- const saved = JSON.parse(window.localStorage.getItem('vrArchLayout') || '{}');
19194
- Object.keys(saved).forEach((id) => {
19195
- if (pos[id] && saved[id] && Number.isFinite(saved[id].x) && Number.isFinite(saved[id].y)) {
19196
- pos[id] = { x: saved[id].x, y: saved[id].y };
19197
- }
19316
+ return { nodes, edges, pos, healthGaps, zones: { modulesY: modules.length ? modulesY : 0, providersY } };
19317
+ }
19318
+
19319
+ function compactArchGraph(graph) {
19320
+ const pos = {};
19321
+ const columnGap = 204;
19322
+ const rowGap = 74;
19323
+ const left = 16;
19324
+ const place = (id, x, y) => { pos[id] = { x, y }; };
19325
+ const existing = (ids) => ids.filter((id) => graph.nodes.some((node) => node.id === id));
19326
+ const placeGrid = (ids, y, columns) => {
19327
+ ids.forEach((id, index) => {
19328
+ place(id, left + (index % columns) * columnGap, y + Math.floor(index / columns) * rowGap);
19198
19329
  });
19199
- } catch { /* corrupted layout \u2014 use defaults */ }
19330
+ return y + Math.max(1, Math.ceil(ids.length / columns)) * rowGap;
19331
+ };
19200
19332
 
19201
- return { nodes, edges, pos, healthGaps, zones: { modulesY: modules.length ? modulesY : 0, providersY } };
19333
+ let y = 42;
19334
+ y = placeGrid(existing(['user', 'pages', 'api', 'data']), y, 2);
19335
+ const secondaryCore = existing(['webhooks', 'jobs']);
19336
+ if (secondaryCore.length) y = placeGrid(secondaryCore, y + 6, 2);
19337
+
19338
+ const modulesY = graph.nodes.some((node) => node.id.indexOf('mod:') === 0) ? y + 18 : 0;
19339
+ if (modulesY) {
19340
+ y = placeGrid(graph.nodes.filter((node) => node.id.indexOf('mod:') === 0).map((node) => node.id), modulesY, 2);
19341
+ }
19342
+
19343
+ const providersY = y + 18;
19344
+ placeGrid(graph.nodes.filter((node) => node.id.indexOf('prov:') === 0).map((node) => node.id), providersY, 2);
19345
+
19346
+ return {
19347
+ ...graph,
19348
+ pos,
19349
+ zones: { modulesY, providersY },
19350
+ compact: true,
19351
+ };
19202
19352
  }
19203
19353
 
19204
19354
  function archEdgePath(pos, edge) {
@@ -19342,6 +19492,7 @@ function ArchDrawer(map, graph) {
19342
19492
 
19343
19493
  function StudioArchitectureView() {
19344
19494
  const map = demo.architectureMap || {};
19495
+ const inspectorMap = demo.activeStudioTab === 'architecture' && !demo.inspectorExpanded;
19345
19496
  let body;
19346
19497
  if (map.loading) {
19347
19498
  body = '<p class="vr-arch-empty">Reading architecture evidence\u2026</p>';
@@ -19349,8 +19500,9 @@ function StudioArchitectureView() {
19349
19500
  body = '<p class="vr-arch-empty">' + escapeHtml(map.error) + '</p>';
19350
19501
  } else if (map.data) {
19351
19502
  if (!demo.archGraph) demo.archGraph = buildArchGraph(map.data, map.gaps || []);
19352
- const graph = demo.archGraph;
19353
- const width = Math.max(1120, Math.max.apply(null, Object.values(graph.pos).map((p) => p.x)) + ARCH_NODE_W + 32);
19503
+ const graph = inspectorMap ? compactArchGraph(demo.archGraph) : demo.archGraph;
19504
+ const minWidth = inspectorMap ? 408 : 1120;
19505
+ const width = Math.max(minWidth, Math.max.apply(null, Object.values(graph.pos).map((p) => p.x)) + ARCH_NODE_W + 32);
19354
19506
  const height = Math.max(360, Math.max.apply(null, Object.values(graph.pos).map((p) => p.y)) + ARCH_NODE_H + 32);
19355
19507
  const edgesSvg = '<svg class="vr-arch-edges" width="' + width + '" height="' + height + '" viewBox="0 0 ' + width + ' ' + height + '">' +
19356
19508
  graph.edges.map((edge) => '<path data-arch-edge="' + escapeHtml(edge.from + ':' + edge.to) + '" d="' + archEdgePath(graph.pos, edge) + '" />').join('') +
@@ -19369,7 +19521,7 @@ function StudioArchitectureView() {
19369
19521
  const badge = node.gapCount
19370
19522
  ? '<span class="vr-arch-node-badge is-' + escapeHtml(node.health) + '" title="' + node.gapCount + ' open gap' + (node.gapCount === 1 ? '' : 's') + '">' + node.gapCount + '</span>'
19371
19523
  : '';
19372
- return '<div class="vr-arch-node is-' + node.kind + (node.health ? ' has-health-' + escapeHtml(node.health) : '') + '" data-arch-node="' + escapeHtml(node.id) + '"' + action + ' style="transform:translate(' + p.x + 'px,' + p.y + 'px)">' +
19524
+ return '<div class="vr-arch-node is-' + node.kind + (node.health ? ' has-health-' + escapeHtml(node.health) : '') + (demo.archDrawer === node.id ? ' is-selected' : '') + '" data-arch-node="' + escapeHtml(node.id) + '"' + action + ' style="transform:translate(' + p.x + 'px,' + p.y + 'px)">' +
19373
19525
  icon + '<div><strong>' + escapeHtml(node.label) + '</strong><em>' + escapeHtml(node.sub) + '</em></div>' + ask + badge +
19374
19526
  '</div>';
19375
19527
  }).join('');
@@ -19379,7 +19531,7 @@ function StudioArchitectureView() {
19379
19531
  (zones.modulesY ? '<span class="vr-arch-zone" style="left:16px;top:' + (zones.modulesY - 20) + 'px">Modules</span>' : '') +
19380
19532
  '<span class="vr-arch-zone" style="left:16px;top:' + (zones.providersY - 24) + 'px">Providers</span>' +
19381
19533
  '<i class="vr-arch-divider" style="top:' + (zones.providersY - 30) + 'px"></i>' +
19382
- '<span class="vr-arch-hint">Drag to arrange \xB7 click a node to inspect \xB7 \u2726 sends it to the agent</span>';
19534
+ '<span class="vr-arch-hint">Click a node to inspect \xB7 use zoom to scan \xB7 \u2726 sends it to the agent</span>';
19383
19535
  const zoom = demo.archZoom || 1;
19384
19536
  const zoomControls = '<div class="vr-arch-zoom">' +
19385
19537
  '<button type="button" data-action="arch-zoom" data-dir="out" aria-label="Zoom out">\u2212</button>' +
@@ -19392,8 +19544,8 @@ function StudioArchitectureView() {
19392
19544
  } else {
19393
19545
  body = '<p class="vr-arch-empty">No architecture map yet. Run a scan and it is written automatically.</p>';
19394
19546
  }
19395
- return '<section class="vr-studio-architecture" aria-label="Architecture map">' +
19396
- '<header><strong>Architecture Map</strong><span>Live from repo evidence \u2014 drag nodes, click a provider, or send a boundary to the agent.</span></header>' +
19547
+ return '<section class="vr-studio-architecture ' + (inspectorMap ? 'is-inspector-map' : '') + '" aria-label="Architecture map">' +
19548
+ '<header><strong>Architecture Map</strong><span>Live from repo evidence \u2014 click nodes, inspect providers, or send a boundary to the agent.</span></header>' +
19397
19549
  '<div class="vr-arch-body ' + (map.data ? 'is-graph' : '') + '">' + body + '</div>' +
19398
19550
  '<footer>' +
19399
19551
  '<button type="button" data-action="arch-reset-layout">' + Icon('refresh') + 'Reset layout</button>' +
@@ -19422,16 +19574,131 @@ function loadArchitectureMap() {
19422
19574
  }
19423
19575
 
19424
19576
  function StudioDock() {
19425
- const view = demo.activeStudioTab === 'terminal' ? StudioTerminalView() : demo.activeStudioTab === 'diff' ? StudioDiffView() : demo.activeStudioTab === 'architecture' ? StudioArchitectureView() : StudioChatView();
19426
19577
  return '<section class="vr-studio-dock ' + (demo.agentFixing ? 'is-running' : '') + (demo.verified ? ' is-verified' : '') + '" aria-label="VibeRaven Studio agent workspace">' +
19427
19578
  '<div class="vr-studio-head">' +
19428
19579
  '<div><h2>VibeRaven Chat</h2></div>' +
19429
19580
  '<div class="vr-studio-head-actions"><button class="vr-studio-add-chat" type="button" data-action="split-chat" aria-label="Open a side-by-side chat">' + Icon('plus') + 'Split chat</button><div class="vr-studio-tabs">' + StudioTabButton('chat', 'Chat') + StudioTabButton('architecture', 'Architecture') + StudioTabButton('terminal', 'Terminal') + StudioTabButton('diff', 'Diff') + '</div></div>' +
19430
19581
  '</div>' +
19431
- '<div class="vr-studio-body">' + view + '</div>' +
19582
+ '<div class="vr-studio-body">' + StudioChatView() + '</div>' +
19432
19583
  '</section>';
19433
19584
  }
19434
19585
 
19586
+ function RailLauncherButton(kind, icon, title, caption, attrs) {
19587
+ return '<button class="vr-rail-launcher is-' + escapeHtml(kind) + '" type="button" ' + attrs + '>' +
19588
+ Icon(icon) +
19589
+ '<span><strong>' + escapeHtml(title) + '</strong><em>' + escapeHtml(caption) + '</em></span>' +
19590
+ '<b></b>' +
19591
+ '</button>';
19592
+ }
19593
+
19594
+ function RailLaunchers() {
19595
+ const activeProviders = orderedProviders().filter((provider) => provider.state !== 'not_detected').length;
19596
+ const release = releases[0];
19597
+ return '<nav class="vr-rail-launchers" aria-label="Studio context">' +
19598
+ RailLauncherButton('architecture', 'branch', 'Architecture', 'Open right inspector', 'data-studio-tab="architecture"') +
19599
+ RailLauncherButton('providers', 'cube', 'Providers', String(activeProviders || providers.length) + ' slots', 'data-studio-tab="providers"') +
19600
+ RailLauncherButton('versions', 'clock', 'Versions', release ? release.label : 'local history', 'data-studio-tab="versions"') +
19601
+ RailLauncherButton('worktree', 'repo', 'Worktree', 'Branches and changes', 'data-studio-tab="worktree"') +
19602
+ '</nav>';
19603
+ }
19604
+
19605
+ function InspectorProviderView() {
19606
+ const boardProviders = orderedProviders();
19607
+ const activeCount = boardProviders.filter((provider) => provider.state !== 'not_detected').length;
19608
+ return '<section class="vr-inspector-card vr-provider-inspector">' +
19609
+ '<header class="vr-inspector-hero">' +
19610
+ '<div><p>Provider Control</p><h3>Production slots</h3><em>' + String(activeCount || boardProviders.length) + ' provider contexts ready for chat and proof checks.</em></div>' +
19611
+ '<img src="' + mascotAssets.verified + '" alt="" />' +
19612
+ '</header>' +
19613
+ '<div class="vr-inspector-provider-grid">' + boardProviders.map((provider) =>
19614
+ '<button class="vr-inspector-provider-row" type="button" draggable="true" data-provider="' + escapeHtml(provider.id) + '">' +
19615
+ ProviderToken(provider) +
19616
+ '<span><small>' + escapeHtml(stackSlots[provider.id] || provider.area) + '</small><strong>' + escapeHtml(provider.name) + '</strong><em>' + escapeHtml(provider.status) + '</em></span>' +
19617
+ providerMcpChip(provider) +
19618
+ '</button>'
19619
+ ).join('') + '</div>' +
19620
+ '<footer class="vr-inspector-footer"><button type="button" data-action="add-provider">' + Icon('plus') + 'Add provider</button><button type="button" data-action="provider-proof">' + Icon('agent') + 'Ask agent</button></footer>' +
19621
+ '</section>';
19622
+ }
19623
+
19624
+ function InspectorVersionsView() {
19625
+ const selected = releases.find((item) => item.id === demo.selectedReleaseId) || releases[0];
19626
+ const pair = releaseComparePair();
19627
+ const entries = Array.isArray(demo.releaseChangelog?.entries) ? demo.releaseChangelog.entries.slice(0, 8) : [];
19628
+ const changelog = demo.releaseChangelog?.loading
19629
+ ? '<p class="vr-inspector-empty">Loading changelog...</p>'
19630
+ : demo.releaseChangelog?.error
19631
+ ? '<p class="vr-release-error">' + escapeHtml(demo.releaseChangelog.error) + '</p>'
19632
+ : entries.length
19633
+ ? '<div class="vr-inspector-changelog">' + entries.map((entry) =>
19634
+ '<button type="button" data-action="diff-to-chat"><strong>' + escapeHtml(entry.short || entry.sha || '') + '</strong><span>' + escapeHtml(entry.subject || '') + '</span><em>' + escapeHtml((entry.author || 'unknown') + ' \xB7 ' + (entry.when || '')) + '</em></button>'
19635
+ ).join('') + '</div>'
19636
+ : '<p class="vr-inspector-empty">Open changelog to load commits between ' + escapeHtml(pair.fromLabel) + ' and ' + escapeHtml(pair.toLabel) + '.</p>';
19637
+ return '<section class="vr-inspector-card vr-version-inspector">' +
19638
+ '<header class="vr-inspector-hero">' +
19639
+ '<div><p>Version Control</p><h3>' + escapeHtml(selected.label) + '</h3><em>' + escapeHtml(selected.meta + ' \xB7 ' + selected.branch) + '</em></div>' +
19640
+ '<img src="' + mascotAssets.idle + '" alt="" />' +
19641
+ '</header>' +
19642
+ '<button class="vr-inspector-compare" type="button" data-action="compare">' + Icon('refresh') + '<span>Compare release</span><strong>' + escapeHtml(pair.fromLabel) + ' \u2192 ' + escapeHtml(pair.toLabel) + '</strong></button>' +
19643
+ '<section class="vr-inspector-section"><header><strong>Recent versions</strong><button type="button" data-action="changelog">Load changelog</button></header>' +
19644
+ '<div class="vr-inspector-release-list">' + releases.slice(0, 5).map((release) =>
19645
+ '<button class="' + (release.id === selected.id ? 'is-selected' : '') + '" type="button" draggable="true" data-release="' + escapeHtml(release.id) + '">' +
19646
+ '<span><strong>' + escapeHtml(release.label) + '</strong><em>' + escapeHtml(release.summary || release.meta) + '</em></span><small>' + escapeHtml(release.branch) + '</small>' +
19647
+ '</button>'
19648
+ ).join('') + '</div>' +
19649
+ '</section>' +
19650
+ '<section class="vr-inspector-section"><header><strong>Changelog</strong><button type="button" data-action="ask-release-agent" data-release="' + escapeHtml(selected.id) + '">Ask agent</button></header>' + changelog + '</section>' +
19651
+ '<footer class="vr-inspector-footer"><button type="button" data-action="show-release-diff">' + Icon('code') + 'View diff</button><button type="button" data-action="rollback-release">' + Icon('refresh') + 'Rollback</button></footer>' +
19652
+ '</section>';
19653
+ }
19654
+
19655
+ function InspectorWorktreeView() {
19656
+ const tree = demo.worktree || { branches: [], loading: true };
19657
+ const defaultBranch = tree.defaultBranch || 'main';
19658
+ const branches = Array.isArray(tree.branches) ? tree.branches : [];
19659
+ return '<section class="vr-inspector-card vr-worktree-inspector">' +
19660
+ '<header class="vr-inspector-hero">' +
19661
+ '<div><p>Worktree</p><h3>' + escapeHtml(tree.currentBranch || defaultBranch) + '</h3><em>' + (tree.loading ? 'Reading branches...' : String(branches.length || 0) + ' branches detected') + '</em></div>' +
19662
+ '<img src="' + mascotAssets.idle + '" alt="" />' +
19663
+ '</header>' +
19664
+ (tree.dirtyCount > 0 ? '<section class="vr-inspector-warning"><i></i><span><strong>' + tree.dirtyCount + ' uncommitted change' + (tree.dirtyCount === 1 ? '' : 's') + '</strong><em>Commit or review before merging.</em></span><button type="button" data-action="worktree-commit">Commit</button></section>' : '') +
19665
+ '<section class="vr-inspector-section"><header><strong>Branches</strong><button type="button" data-action="worktree-review" data-branch="' + escapeHtml(defaultBranch) + '">Health report</button></header>' +
19666
+ '<div class="vr-inspector-branch-list">' + (branches.length ? branches.slice(0, 8).map((branch) => {
19667
+ const drift = branch.current ? 'current' : ((branch.ahead ? branch.ahead + ' ahead' : '') + (branch.ahead && branch.behind ? ' \xB7 ' : '') + (branch.behind ? branch.behind + ' behind' : '') || 'in sync');
19668
+ return '<div class="' + (branch.current ? 'is-current' : '') + '"><span><strong>' + escapeHtml(branch.name) + '</strong><em>' + escapeHtml(drift + (branch.when ? ' \xB7 ' + branch.when : '')) + '</em></span><div><button type="button" data-action="worktree-review" data-branch="' + escapeHtml(branch.name) + '">Review</button><button type="button" data-action="worktree-diff" data-branch="' + escapeHtml(branch.name) + '">Diff</button></div></div>';
19669
+ }).join('') : '<p class="vr-inspector-empty">' + (tree.loading ? 'Reading branches...' : 'No branches detected.') + '</p>') + '</div>' +
19670
+ '</section>' +
19671
+ '</section>';
19672
+ }
19673
+
19674
+ function StudioInspectorPanel() {
19675
+ if (demo.activeStudioTab === 'chat') return '';
19676
+ const labels = {
19677
+ architecture: ['Architecture Map', 'Repo structure and provider boundaries'],
19678
+ providers: ['Providers', 'Production slots and MCP context'],
19679
+ versions: ['Versions', 'Release comparison and changelog'],
19680
+ worktree: ['Worktree', 'Branches and local changes'],
19681
+ terminal: ['Terminal', 'Connect and test local CLIs'],
19682
+ diff: ['Diff', 'Release and code changes'],
19683
+ };
19684
+ const label = labels[demo.activeStudioTab] || ['Inspector', 'Context panel'];
19685
+ const view = demo.activeStudioTab === 'terminal'
19686
+ ? StudioTerminalView()
19687
+ : demo.activeStudioTab === 'diff'
19688
+ ? StudioDiffView()
19689
+ : demo.activeStudioTab === 'providers'
19690
+ ? InspectorProviderView()
19691
+ : demo.activeStudioTab === 'versions'
19692
+ ? InspectorVersionsView()
19693
+ : demo.activeStudioTab === 'worktree'
19694
+ ? InspectorWorktreeView()
19695
+ : StudioArchitectureView();
19696
+ return '<aside class="vr-inspector-panel ' + (demo.inspectorExpanded ? 'is-expanded' : '') + '" aria-label="' + escapeHtml(label[0]) + '">' +
19697
+ '<header class="vr-inspector-head"><div><strong>' + escapeHtml(label[0]) + '</strong><span>' + escapeHtml(label[1]) + '</span></div><button type="button" data-action="toggle-inspector-size" aria-label="' + (demo.inspectorExpanded ? 'Shrink inspector' : 'Expand inspector') + '">' + Icon(demo.inspectorExpanded ? 'collapse' : 'expand') + '</button><button type="button" data-studio-tab="chat" aria-label="Close inspector">' + Icon('x') + '</button></header>' +
19698
+ '<div class="vr-inspector-body">' + view + '</div>' +
19699
+ '</aside>';
19700
+ }
19701
+
19435
19702
  function QuickActionRow(action) {
19436
19703
  return '<button class="vr-quick-action" type="button" data-action="' + escapeHtml(action.id) + '">' + Icon(action.icon) + '<span><strong>' + escapeHtml(action.title) + '</strong><em>' + escapeHtml(action.caption) + '</em></span></button>';
19437
19704
  }
@@ -19606,10 +19873,14 @@ function LaunchFlowPage() {
19606
19873
  }
19607
19874
 
19608
19875
  function VibeShell() {
19876
+ const inspectorOpen = demo.activeStudioTab !== 'chat';
19609
19877
  return '<main class="vr-composed-shell">' +
19610
19878
  StudioTopBar() +
19611
- '<div class="vr-composition-body">' + RecentChatRail() + '<section class="vr-main-canvas">' + LaunchFlowPage() + '</section>' + AgentActionPanel() + '</div>' +
19612
- '<div class="vr-bottom-inventory">' + ProviderGrid() + VersionTimeline() + '</div>' +
19879
+ '<div class="vr-composition-body ' + (inspectorOpen ? 'has-inspector' : '') + (demo.inspectorExpanded ? ' inspector-expanded' : '') + '">' +
19880
+ '<aside class="vr-left-context-rail" aria-label="Chat and context shortcuts">' + RailLaunchers() + RecentChatRail() + '</aside>' +
19881
+ '<section class="vr-main-canvas">' + LaunchFlowPage() + '</section>' +
19882
+ StudioInspectorPanel() +
19883
+ '</div>' +
19613
19884
  BottomTipBar() +
19614
19885
  '</main>' +
19615
19886
  ActiveModal();
@@ -19677,9 +19948,21 @@ function refreshPickerMenus() {
19677
19948
  });
19678
19949
  }
19679
19950
 
19951
+ function closeComposerPopovers() {
19952
+ demo.quickActionsOpen = false;
19953
+ demo.contextTrayOpen = false;
19954
+ demo.scopeMenuOpen = false;
19955
+ demo.modelMenuOpen = false;
19956
+ demo.reasoningMenuOpen = false;
19957
+ demo.contextMenuOpen = false;
19958
+ demo.accessMenuOpen = false;
19959
+ demo.dropActive = false;
19960
+ }
19961
+
19680
19962
  function render(options) {
19681
19963
  const opts = options || {};
19682
19964
  const scrollState = opts.preserveScroll === false ? null : readChatScrollState();
19965
+ stableModalRender = Boolean(demo.activeModal && demo.activeModal === lastRenderedModal);
19683
19966
  app.innerHTML = VibeShell();
19684
19967
  window.requestAnimationFrame(() => {
19685
19968
  if (opts.scrollToBottom != null) {
@@ -19753,6 +20036,13 @@ app.addEventListener('click', async (event) => {
19753
20036
  demo.archVisited = true;
19754
20037
  loadArchitectureMap();
19755
20038
  }
20039
+ if (demo.activeStudioTab === 'worktree') {
20040
+ loadWorktree();
20041
+ }
20042
+ if (demo.activeStudioTab === 'versions') {
20043
+ runReleaseChangelog(false);
20044
+ return;
20045
+ }
19756
20046
  demo.notice = 'Studio switched to ' + studioTab.textContent.trim() + '.';
19757
20047
  render();
19758
20048
  return;
@@ -19789,8 +20079,6 @@ app.addEventListener('click', async (event) => {
19789
20079
  return;
19790
20080
  }
19791
20081
 
19792
- if (archClickSuppressed && event.target.closest('[data-arch-node]')) return;
19793
-
19794
20082
  const archZoomButton = event.target.closest('[data-action="arch-zoom"]');
19795
20083
  if (archZoomButton) {
19796
20084
  const dir = archZoomButton.getAttribute('data-dir');
@@ -19833,7 +20121,11 @@ app.addEventListener('click', async (event) => {
19833
20121
 
19834
20122
  const toggleQuickActionsButton = event.target.closest('[data-action="toggle-quick-actions"]');
19835
20123
  if (toggleQuickActionsButton) {
19836
- demo.quickActionsOpen = !demo.quickActionsOpen;
20124
+ const chatIndex = Number(toggleQuickActionsButton.getAttribute('data-chat-index') || '0');
20125
+ const samePicker = demo.pickerChatIndex === chatIndex && demo.quickActionsOpen;
20126
+ closeComposerPopovers();
20127
+ demo.pickerChatIndex = chatIndex;
20128
+ demo.quickActionsOpen = !samePicker;
19837
20129
  render();
19838
20130
  return;
19839
20131
  }
@@ -19873,7 +20165,9 @@ app.addEventListener('click', async (event) => {
19873
20165
 
19874
20166
  const openWorktreeButton = event.target.closest('[data-action="open-worktree"]');
19875
20167
  if (openWorktreeButton) {
19876
- demo.activeModal = 'worktree';
20168
+ demo.activeStudioTab = 'worktree';
20169
+ loadWorktree();
20170
+ demo.notice = 'Worktree opened in the inspector.';
19877
20171
  render();
19878
20172
  return;
19879
20173
  }
@@ -20032,7 +20326,7 @@ app.addEventListener('click', async (event) => {
20032
20326
  const shellInput = app.querySelector('[data-terminal-shell-input]');
20033
20327
  const command = String((shellInput && 'value' in shellInput ? shellInput.value : demo.cliTerminalDraft) || '').trim();
20034
20328
  demo.cliTerminalDraft = command;
20035
- await runStudioShellCommand(command);
20329
+ await runStudioShellCommand(command, undefined, terminalTargetId());
20036
20330
  if (shellInput && 'value' in shellInput) shellInput.value = '';
20037
20331
  demo.cliTerminalDraft = '';
20038
20332
  return;
@@ -20173,6 +20467,9 @@ app.addEventListener('click', async (event) => {
20173
20467
  demo.reasoningMenuOpen = false;
20174
20468
  demo.modelMenuOpen = false;
20175
20469
  demo.contextMenuOpen = false;
20470
+ demo.scopeMenuOpen = false;
20471
+ demo.contextTrayOpen = false;
20472
+ demo.quickActionsOpen = false;
20176
20473
  demo.accessMenuOpen = false;
20177
20474
  demo.activeStudioTab = 'chat';
20178
20475
  demo.pickerChatIndex = chatIndex;
@@ -20190,13 +20487,16 @@ app.addEventListener('click', async (event) => {
20190
20487
  chat.context = contextButton.getAttribute('data-context');
20191
20488
  demo.selectedContext = chat.context;
20192
20489
  demo.contextMenuOpen = false;
20490
+ demo.scopeMenuOpen = false;
20491
+ demo.contextTrayOpen = false;
20492
+ demo.quickActionsOpen = false;
20193
20493
  demo.modelMenuOpen = false;
20194
20494
  demo.reasoningMenuOpen = false;
20195
20495
  demo.accessMenuOpen = false;
20196
20496
  demo.activeStudioTab = 'chat';
20197
20497
  demo.pickerChatIndex = chatIndex;
20198
20498
  demo.notice = chat.context + ' context selected for this chat.';
20199
- refreshPickerMenus();
20499
+ render();
20200
20500
  refreshBottomTip();
20201
20501
  return;
20202
20502
  }
@@ -20211,6 +20511,9 @@ app.addEventListener('click', async (event) => {
20211
20511
  demo.selectedAccessMode = selected.id;
20212
20512
  demo.accessMenuOpen = false;
20213
20513
  demo.contextMenuOpen = false;
20514
+ demo.scopeMenuOpen = false;
20515
+ demo.contextTrayOpen = false;
20516
+ demo.quickActionsOpen = false;
20214
20517
  demo.modelMenuOpen = false;
20215
20518
  demo.reasoningMenuOpen = false;
20216
20519
  demo.activeStudioTab = 'chat';
@@ -20252,6 +20555,40 @@ app.addEventListener('click', async (event) => {
20252
20555
  return;
20253
20556
  }
20254
20557
 
20558
+ const contextProviderButton = event.target.closest('[data-context-provider]');
20559
+ if (contextProviderButton) {
20560
+ const chatIndex = Number(contextProviderButton.getAttribute('data-chat-index') || String(demo.pickerChatIndex || 0));
20561
+ const providerId = contextProviderButton.getAttribute('data-context-provider');
20562
+ const provider = providers.find((item) => item.id === providerId);
20563
+ const chat = chatContext(chatIndex);
20564
+ chat.providerId = providerId;
20565
+ demo.selectedProviderId = providerId;
20566
+ demo.pickerChatIndex = chatIndex;
20567
+ demo.contextTrayOpen = false;
20568
+ demo.dropActive = false;
20569
+ demo.notice = provider ? provider.name + ' context attached to chat.' : 'Provider context attached.';
20570
+ if (chatIndex === 0) syncPrimaryContext();
20571
+ render();
20572
+ return;
20573
+ }
20574
+
20575
+ const contextReleaseButton = event.target.closest('[data-context-release]');
20576
+ if (contextReleaseButton) {
20577
+ const chatIndex = Number(contextReleaseButton.getAttribute('data-chat-index') || String(demo.pickerChatIndex || 0));
20578
+ const releaseId = contextReleaseButton.getAttribute('data-context-release');
20579
+ const release = releases.find((item) => item.id === releaseId);
20580
+ const chat = chatContext(chatIndex);
20581
+ chat.releaseId = releaseId;
20582
+ demo.selectedReleaseId = releaseId;
20583
+ demo.pickerChatIndex = chatIndex;
20584
+ demo.contextTrayOpen = false;
20585
+ demo.dropActive = false;
20586
+ demo.notice = release ? release.label + ' attached to chat.' : 'Version context attached.';
20587
+ if (chatIndex === 0) syncPrimaryContext();
20588
+ render();
20589
+ return;
20590
+ }
20591
+
20255
20592
  const providerButton = event.target.closest('[data-provider]');
20256
20593
  if (providerButton) {
20257
20594
  demo.selectedProviderId = providerButton.getAttribute('data-provider');
@@ -20269,7 +20606,7 @@ app.addEventListener('click', async (event) => {
20269
20606
  if (releaseButton) {
20270
20607
  demo.selectedReleaseId = releaseButton.getAttribute('data-release');
20271
20608
  demo.activeNavId = 'versions';
20272
- demo.activeModal = 'release';
20609
+ if (demo.activeStudioTab !== 'versions') demo.activeModal = 'release';
20273
20610
  demo.notice = 'Release ' + demo.selectedReleaseId + ' selected. Compare changes before verification.';
20274
20611
  runReleaseChangelog(false);
20275
20612
  return;
@@ -20360,7 +20697,7 @@ app.addEventListener('click', async (event) => {
20360
20697
  const shellInput = app.querySelector('[data-terminal-shell-input]');
20361
20698
  const command = String((shellInput && 'value' in shellInput ? shellInput.value : demo.cliTerminalDraft) || '').trim();
20362
20699
  demo.cliTerminalDraft = command;
20363
- await runStudioShellCommand(command);
20700
+ await runStudioShellCommand(command, undefined, terminalTargetId());
20364
20701
  if (shellInput && 'value' in shellInput) shellInput.value = '';
20365
20702
  demo.cliTerminalDraft = '';
20366
20703
  return;
@@ -20411,11 +20748,9 @@ app.addEventListener('click', async (event) => {
20411
20748
  const chatIndex = Number(actionButton.getAttribute('data-chat-index') || '0');
20412
20749
  const samePicker = demo.pickerChatIndex === chatIndex && demo.modelMenuOpen;
20413
20750
  demo.activeStudioTab = 'chat';
20751
+ closeComposerPopovers();
20414
20752
  demo.pickerChatIndex = chatIndex;
20415
20753
  demo.modelMenuOpen = !samePicker;
20416
- demo.reasoningMenuOpen = false;
20417
- demo.contextMenuOpen = false;
20418
- demo.accessMenuOpen = false;
20419
20754
  refreshPickerMenus();
20420
20755
  return;
20421
20756
  }
@@ -20424,24 +20759,31 @@ app.addEventListener('click', async (event) => {
20424
20759
  const chatIndex = Number(actionButton.getAttribute('data-chat-index') || '0');
20425
20760
  const samePicker = demo.pickerChatIndex === chatIndex && demo.reasoningMenuOpen;
20426
20761
  demo.activeStudioTab = 'chat';
20762
+ closeComposerPopovers();
20427
20763
  demo.pickerChatIndex = chatIndex;
20428
20764
  demo.reasoningMenuOpen = !samePicker;
20429
- demo.modelMenuOpen = false;
20430
- demo.contextMenuOpen = false;
20431
- demo.accessMenuOpen = false;
20432
20765
  refreshPickerMenus();
20433
20766
  return;
20434
20767
  }
20768
+ if (action === 'toggle-scope-menu') {
20769
+ event.preventDefault();
20770
+ const chatIndex = Number(actionButton.getAttribute('data-chat-index') || '0');
20771
+ const samePicker = demo.pickerChatIndex === chatIndex && demo.scopeMenuOpen;
20772
+ demo.activeStudioTab = 'chat';
20773
+ closeComposerPopovers();
20774
+ demo.pickerChatIndex = chatIndex;
20775
+ demo.scopeMenuOpen = !samePicker;
20776
+ render();
20777
+ return;
20778
+ }
20435
20779
  if (action === 'toggle-context') {
20436
20780
  event.preventDefault();
20437
20781
  const chatIndex = Number(actionButton.getAttribute('data-chat-index') || '0');
20438
20782
  const samePicker = demo.pickerChatIndex === chatIndex && demo.contextMenuOpen;
20439
20783
  demo.activeStudioTab = 'chat';
20784
+ closeComposerPopovers();
20440
20785
  demo.pickerChatIndex = chatIndex;
20441
20786
  demo.contextMenuOpen = !samePicker;
20442
- demo.modelMenuOpen = false;
20443
- demo.reasoningMenuOpen = false;
20444
- demo.accessMenuOpen = false;
20445
20787
  refreshPickerMenus();
20446
20788
  return;
20447
20789
  }
@@ -20450,11 +20792,9 @@ app.addEventListener('click', async (event) => {
20450
20792
  const chatIndex = Number(actionButton.getAttribute('data-chat-index') || '0');
20451
20793
  const samePicker = demo.pickerChatIndex === chatIndex && demo.accessMenuOpen;
20452
20794
  demo.activeStudioTab = 'chat';
20795
+ closeComposerPopovers();
20453
20796
  demo.pickerChatIndex = chatIndex;
20454
20797
  demo.accessMenuOpen = !samePicker;
20455
- demo.modelMenuOpen = false;
20456
- demo.reasoningMenuOpen = false;
20457
- demo.contextMenuOpen = false;
20458
20798
  refreshPickerMenus();
20459
20799
  return;
20460
20800
  }
@@ -20546,6 +20886,11 @@ app.addEventListener('click', async (event) => {
20546
20886
  render();
20547
20887
  return;
20548
20888
  }
20889
+ if (action === 'toggle-inspector-size') {
20890
+ demo.inspectorExpanded = !demo.inspectorExpanded;
20891
+ render();
20892
+ return;
20893
+ }
20549
20894
  if (action === 'add-chat') {
20550
20895
  demo.activeStudioTab = 'chat';
20551
20896
  demo.activeChatCount = 1;
@@ -20699,13 +21044,21 @@ app.addEventListener('click', async (event) => {
20699
21044
  return;
20700
21045
  }
20701
21046
  if (action === 'add-context') {
20702
- demo.dropActive = true;
20703
- demo.notice = 'Drag a provider or version into the chat composer to attach context.';
21047
+ const chatIndex = Number(actionButton.getAttribute('data-chat-index') || String(actionChatIndex));
21048
+ const samePicker = demo.pickerChatIndex === chatIndex && demo.contextTrayOpen;
21049
+ demo.activeStudioTab = 'chat';
21050
+ closeComposerPopovers();
21051
+ demo.pickerChatIndex = chatIndex;
21052
+ demo.contextTrayOpen = !samePicker;
21053
+ demo.dropActive = demo.contextTrayOpen;
21054
+ demo.notice = demo.contextTrayOpen ? 'Choose a provider or version to attach, or drag it into the chat.' : 'Context tray closed.';
21055
+ render();
21056
+ return;
21057
+ }
21058
+ if (action === 'close-context-tray') {
21059
+ demo.contextTrayOpen = false;
21060
+ demo.dropActive = false;
20704
21061
  render();
20705
- window.setTimeout(() => {
20706
- demo.dropActive = false;
20707
- render();
20708
- }, 1200);
20709
21062
  return;
20710
21063
  }
20711
21064
  if (action === 'terminal-tab') {
@@ -20719,7 +21072,12 @@ app.addEventListener('click', async (event) => {
20719
21072
  return;
20720
21073
  }
20721
21074
  if (action === 'changelog') {
20722
- runReleaseChangelog(true);
21075
+ if (demo.activeStudioTab === 'versions') {
21076
+ runReleaseChangelog(false);
21077
+ } else {
21078
+ demo.activeStudioTab = 'versions';
21079
+ runReleaseChangelog(false);
21080
+ }
20723
21081
  return;
20724
21082
  }
20725
21083
  if (action === 'rollback-release') {
@@ -20735,7 +21093,8 @@ app.addEventListener('click', async (event) => {
20735
21093
  };
20736
21094
  if (actionMessages[action]) {
20737
21095
  if (action === 'all-releases') {
20738
- demo.activeModal = 'release';
21096
+ demo.activeStudioTab = 'versions';
21097
+ demo.activeModal = null;
20739
21098
  runReleaseChangelog(false);
20740
21099
  return;
20741
21100
  }
@@ -20782,7 +21141,7 @@ app.addEventListener('keydown', (event) => {
20782
21141
  const command = String(shellInput.value || '').trim();
20783
21142
  if (!command) return;
20784
21143
  demo.cliTerminalDraft = command;
20785
- runStudioShellCommand(command).then(() => {
21144
+ runStudioShellCommand(command, undefined, terminalTargetId()).then(() => {
20786
21145
  shellInput.value = '';
20787
21146
  demo.cliTerminalDraft = '';
20788
21147
  });
@@ -20794,47 +21153,6 @@ app.addEventListener('keydown', (event) => {
20794
21153
  sendChatInput(input.getAttribute('data-chat-input') || '0');
20795
21154
  });
20796
21155
 
20797
- let archClickSuppressed = false;
20798
- let archDrag = null;
20799
-
20800
- app.addEventListener('pointerdown', (event) => {
20801
- const node = event.target.closest('[data-arch-node]');
20802
- if (!node || event.target.closest('button')) return;
20803
- const graph = demo.archGraph;
20804
- if (!graph) return;
20805
- const id = node.getAttribute('data-arch-node');
20806
- const pos = graph.pos[id];
20807
- if (!pos) return;
20808
- archDrag = { id, node, startX: event.clientX, startY: event.clientY, origX: pos.x, origY: pos.y, moved: false };
20809
- if (typeof node.setPointerCapture === 'function' && event.pointerId !== undefined) {
20810
- try { node.setPointerCapture(event.pointerId); } catch { /* older engines */ }
20811
- }
20812
- });
20813
-
20814
- app.addEventListener('pointermove', (event) => {
20815
- if (!archDrag || !demo.archGraph) return;
20816
- const zoomFactor = demo.archZoom || 1;
20817
- const dx = (event.clientX - archDrag.startX) / zoomFactor;
20818
- const dy = (event.clientY - archDrag.startY) / zoomFactor;
20819
- if (Math.abs(dx) + Math.abs(dy) > 4) archDrag.moved = true;
20820
- const pos = demo.archGraph.pos[archDrag.id];
20821
- if (!pos) return;
20822
- pos.x = Math.max(0, archDrag.origX + dx);
20823
- pos.y = Math.max(0, archDrag.origY + dy);
20824
- archDrag.node.style.transform = 'translate(' + pos.x + 'px,' + pos.y + 'px)';
20825
- updateArchEdges();
20826
- });
20827
-
20828
- app.addEventListener('pointerup', () => {
20829
- if (archDrag && archDrag.moved) {
20830
- archClickSuppressed = true;
20831
- window.setTimeout(() => { archClickSuppressed = false; }, 0);
20832
- if (demo.archGraph) {
20833
- try { window.localStorage.setItem('vrArchLayout', JSON.stringify(demo.archGraph.pos)); } catch { /* storage full or blocked */ }
20834
- }
20835
- }
20836
- archDrag = null;
20837
- });
20838
21156
 
20839
21157
  app.addEventListener('dragstart', (event) => {
20840
21158
  const providerButton = event.target.closest('[data-provider]');
@@ -20960,7 +21278,10 @@ app.addEventListener('drop', (event) => {
20960
21278
  if (chatIndex === 0) syncPrimaryContext();
20961
21279
  demo.notice = release ? 'Version ' + release.label + ' attached to chat ' + String(chatIndex + 1) + '. Ask for compare, rollback, or provider changes.' : 'Version context attached.';
20962
21280
  }
20963
- demo.activeStudioTab = 'chat';
21281
+ if (newChatTarget || isRecentChatDrop) demo.activeStudioTab = 'chat';
21282
+ demo.contextTrayOpen = false;
21283
+ demo.quickActionsOpen = false;
21284
+ demo.scopeMenuOpen = false;
20964
21285
  demo.dropActive = false;
20965
21286
  demo.dragKind = null;
20966
21287
  demo.dragProviderId = null;
@@ -20987,6 +21308,11 @@ window.addEventListener('keydown', (event) => {
20987
21308
  demo.activeModal = null;
20988
21309
  demo.notice = 'Panel closed. Continue from the launch flow.';
20989
21310
  render();
21311
+ return;
21312
+ }
21313
+ if (event.key === 'Escape' && (demo.quickActionsOpen || demo.contextTrayOpen || demo.scopeMenuOpen || demo.modelMenuOpen || demo.reasoningMenuOpen || demo.contextMenuOpen || demo.accessMenuOpen)) {
21314
+ closeComposerPopovers();
21315
+ render();
20990
21316
  }
20991
21317
  });
20992
21318
 
@@ -22136,7 +22462,11 @@ a i[data-icon] {
22136
22462
  .vr-recent-chat[draggable="true"],
22137
22463
  .vr-provider-card[draggable="true"],
22138
22464
  .vr-release-card[draggable="true"],
22139
- .vr-release-row[draggable="true"] {
22465
+ .vr-release-row[draggable="true"],
22466
+ .vr-inspector-provider-row[draggable="true"],
22467
+ .vr-inspector-release-list button[draggable="true"],
22468
+ .vr-chat-provider-dot[draggable="true"],
22469
+ .vr-chat-version-dot[draggable="true"] {
22140
22470
  position: relative;
22141
22471
  cursor: grab;
22142
22472
  user-select: none;
@@ -22146,13 +22476,21 @@ a i[data-icon] {
22146
22476
  .vr-recent-chat[draggable="true"]:active,
22147
22477
  .vr-provider-card[draggable="true"]:active,
22148
22478
  .vr-release-card[draggable="true"]:active,
22149
- .vr-release-row[draggable="true"]:active {
22479
+ .vr-release-row[draggable="true"]:active,
22480
+ .vr-inspector-provider-row[draggable="true"]:active,
22481
+ .vr-inspector-release-list button[draggable="true"]:active,
22482
+ .vr-chat-provider-dot[draggable="true"]:active,
22483
+ .vr-chat-version-dot[draggable="true"]:active {
22150
22484
  cursor: grabbing;
22151
22485
  }
22152
22486
  .vr-recent-chat.is-being-dragged,
22153
22487
  .vr-provider-card.is-being-dragged,
22154
22488
  .vr-release-card.is-being-dragged,
22155
- .vr-release-row.is-being-dragged {
22489
+ .vr-release-row.is-being-dragged,
22490
+ .vr-inspector-provider-row.is-being-dragged,
22491
+ .vr-inspector-release-list button.is-being-dragged,
22492
+ .vr-chat-provider-dot.is-being-dragged,
22493
+ .vr-chat-version-dot.is-being-dragged {
22156
22494
  opacity: 0.94;
22157
22495
  transform: scale(1.018) translateY(-4px);
22158
22496
  border-color: rgba(216, 180, 254, 0.82);
@@ -22167,6 +22505,10 @@ a i[data-icon] {
22167
22505
  .vr-provider-card.is-being-dragged::before,
22168
22506
  .vr-release-card.is-being-dragged::before,
22169
22507
  .vr-release-row.is-being-dragged::before,
22508
+ .vr-inspector-provider-row.is-being-dragged::before,
22509
+ .vr-inspector-release-list button.is-being-dragged::before,
22510
+ .vr-chat-provider-dot.is-being-dragged::before,
22511
+ .vr-chat-version-dot.is-being-dragged::before,
22170
22512
  .vr-recent-chat.is-being-dragged::before {
22171
22513
  content: "Dragging to chat";
22172
22514
  position: absolute;
@@ -22185,7 +22527,9 @@ a i[data-icon] {
22185
22527
  white-space: nowrap;
22186
22528
  }
22187
22529
  .vr-release-card.is-being-dragged::before,
22188
- .vr-release-row.is-being-dragged::before {
22530
+ .vr-release-row.is-being-dragged::before,
22531
+ .vr-inspector-release-list button.is-being-dragged::before,
22532
+ .vr-chat-version-dot.is-being-dragged::before {
22189
22533
  content: "Dragging version";
22190
22534
  }
22191
22535
  .vr-recent-chat.is-being-dragged::before {
@@ -23559,7 +23903,7 @@ body:has(.vr-app.is-dragging) {
23559
23903
  color: #fecaca;
23560
23904
  }
23561
23905
  .vr-chat-mission-summary i[data-tone="danger"]::before {
23562
- content: "\xD7";
23906
+ content: "\xC3\u2014";
23563
23907
  }
23564
23908
  .vr-chat-mission-summary i[data-tone="step"] {
23565
23909
  border: 1px solid rgba(148, 163, 184, 0.28);
@@ -26527,6 +26871,11 @@ body:has(.vr-app.is-dragging) {
26527
26871
  animation: vrModalPop 260ms cubic-bezier(0.23, 1, 0.32, 1) both;
26528
26872
  }
26529
26873
 
26874
+ .vr-modal-backdrop.is-stable-render,
26875
+ .vr-modal-card.is-stable-render {
26876
+ animation: none;
26877
+ }
26878
+
26530
26879
  .vr-modal-card *,
26531
26880
  .vr-modal-card *::before,
26532
26881
  .vr-modal-card *::after {
@@ -27187,73 +27536,166 @@ body:has(.vr-app.is-dragging) {
27187
27536
 
27188
27537
  .vr-changelog-list {
27189
27538
  list-style: none;
27190
- margin: 16px 0 0;
27539
+ margin: 10px 0 0;
27191
27540
  padding: 0;
27192
27541
  display: grid;
27193
- gap: 10px;
27542
+ gap: 8px;
27194
27543
  }
27195
27544
 
27196
- .vr-changelog-list li {
27197
- padding: 10px 12px;
27545
+ .vr-changelog-summary {
27546
+ display: grid;
27547
+ grid-template-columns: minmax(0, 1fr) auto;
27548
+ align-items: center;
27549
+ gap: 4px 12px;
27550
+ margin: 0 0 10px;
27551
+ border: 1px solid rgba(148, 163, 184, 0.14);
27198
27552
  border-radius: 12px;
27199
- background: rgba(15, 23, 42, 0.55);
27200
- border: 1px solid rgba(148, 163, 184, 0.18);
27201
- color: #e2e8f0;
27202
- line-height: 1.45;
27553
+ background: rgba(15, 23, 42, 0.38);
27554
+ padding: 10px 12px;
27203
27555
  }
27204
27556
 
27205
- .vr-changelog-list em {
27206
- display: block;
27207
- margin-top: 4px;
27557
+ .vr-changelog-summary span {
27558
+ color: #a78bfa;
27559
+ font-size: 11px;
27560
+ font-weight: 760;
27561
+ letter-spacing: 0.08em;
27562
+ text-transform: uppercase;
27563
+ }
27564
+
27565
+ .vr-changelog-summary strong {
27566
+ justify-self: end;
27567
+ color: #f8fafc;
27568
+ font-size: 13px;
27569
+ }
27570
+
27571
+ .vr-changelog-summary em {
27572
+ grid-column: 1 / -1;
27208
27573
  color: #94a3b8;
27209
27574
  font-style: normal;
27210
27575
  font-size: 12px;
27211
27576
  }
27212
27577
 
27213
- .vr-release-error {
27214
- color: #fca5a5;
27578
+ .vr-changelog-list li {
27579
+ display: grid;
27580
+ grid-template-columns: 82px minmax(0, 1fr);
27581
+ gap: 3px 10px;
27582
+ align-items: start;
27583
+ padding: 9px 11px;
27584
+ border-radius: 10px;
27585
+ background: rgba(15, 23, 42, 0.38);
27586
+ border: 1px solid rgba(148, 163, 184, 0.13);
27587
+ color: #e2e8f0;
27588
+ line-height: 1.35;
27215
27589
  }
27216
27590
 
27217
- .vr-modal-agent-head {
27218
- position: relative;
27219
- min-height: 210px;
27220
- display: grid;
27221
- grid-template-columns: 180px minmax(0, 1fr) 240px;
27222
- align-items: center;
27223
- gap: 28px;
27224
- border: 1px solid rgba(96, 122, 177, 0.24);
27225
- border-radius: 18px;
27226
- background:
27227
- radial-gradient(circle at 16% 38%, rgba(124, 58, 237, 0.26), transparent 28%),
27228
- linear-gradient(90deg, rgba(8, 17, 34, 0.82), rgba(13, 20, 43, 0.42));
27229
- padding: 18px;
27230
- overflow: hidden;
27591
+ .vr-changelog-list li strong {
27592
+ color: #e9d5ff;
27593
+ font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
27594
+ font-size: 12px;
27595
+ font-weight: 760;
27231
27596
  }
27232
27597
 
27233
- .vr-modal-guide-head,
27234
- .vr-modal-prompt-head {
27235
- position: relative;
27236
- min-height: 190px;
27237
- display: grid;
27238
- grid-template-columns: 170px minmax(0, 1fr) 240px;
27239
- align-items: center;
27240
- gap: 28px;
27241
- border: 1px solid rgba(96, 122, 177, 0.24);
27242
- border-radius: 18px;
27243
- background:
27244
- radial-gradient(circle at 14% 40%, rgba(124, 58, 237, 0.2), transparent 30%),
27245
- linear-gradient(90deg, rgba(8, 17, 34, 0.82), rgba(13, 20, 43, 0.42));
27246
- padding: 18px;
27598
+ .vr-changelog-list li span {
27599
+ min-width: 0;
27247
27600
  overflow: hidden;
27601
+ color: #f1f5f9;
27602
+ font-size: 13px;
27603
+ text-overflow: ellipsis;
27604
+ white-space: nowrap;
27248
27605
  }
27249
27606
 
27250
- .vr-modal-agent-avatar {
27251
- width: 198px;
27252
- height: 198px;
27253
- object-fit: contain;
27254
- filter: saturate(1.32) contrast(1.04) drop-shadow(0 0 38px rgba(124, 58, 237, 0.78));
27255
- animation: vrMascotIdle 3200ms cubic-bezier(0.23, 1, 0.32, 1) infinite;
27256
- }
27607
+ .vr-changelog-list em {
27608
+ grid-column: 2;
27609
+ color: #94a3b8;
27610
+ font-style: normal;
27611
+ font-size: 11.5px;
27612
+ }
27613
+
27614
+ .vr-changelog-more {
27615
+ margin-top: 10px;
27616
+ }
27617
+
27618
+ .vr-changelog-more summary {
27619
+ display: flex;
27620
+ align-items: center;
27621
+ justify-content: center;
27622
+ min-height: 34px;
27623
+ border: 1px solid rgba(148, 163, 184, 0.16);
27624
+ border-radius: 10px;
27625
+ background: rgba(255, 255, 255, 0.025);
27626
+ color: #c4b5fd;
27627
+ font-size: 12px;
27628
+ font-weight: 720;
27629
+ cursor: pointer;
27630
+ list-style: none;
27631
+ }
27632
+
27633
+ .vr-changelog-more summary::-webkit-details-marker {
27634
+ display: none;
27635
+ }
27636
+
27637
+ .vr-changelog-more[open] .vr-changelog-list {
27638
+ max-height: 260px;
27639
+ overflow-y: auto;
27640
+ padding-right: 4px;
27641
+ }
27642
+
27643
+ .vr-changelog-list.is-condensed li,
27644
+ .vr-changelog-list li.is-compact {
27645
+ padding-block: 7px;
27646
+ }
27647
+
27648
+ .vr-changelog-empty {
27649
+ margin: 0;
27650
+ color: #94a3b8;
27651
+ font-size: 13px;
27652
+ line-height: 1.45;
27653
+ }
27654
+
27655
+ .vr-release-error {
27656
+ color: #fca5a5;
27657
+ }
27658
+
27659
+ .vr-modal-agent-head {
27660
+ position: relative;
27661
+ min-height: 210px;
27662
+ display: grid;
27663
+ grid-template-columns: 180px minmax(0, 1fr) 240px;
27664
+ align-items: center;
27665
+ gap: 28px;
27666
+ border: 1px solid rgba(96, 122, 177, 0.24);
27667
+ border-radius: 18px;
27668
+ background:
27669
+ radial-gradient(circle at 16% 38%, rgba(124, 58, 237, 0.26), transparent 28%),
27670
+ linear-gradient(90deg, rgba(8, 17, 34, 0.82), rgba(13, 20, 43, 0.42));
27671
+ padding: 18px;
27672
+ overflow: hidden;
27673
+ }
27674
+
27675
+ .vr-modal-guide-head,
27676
+ .vr-modal-prompt-head {
27677
+ position: relative;
27678
+ min-height: 190px;
27679
+ display: grid;
27680
+ grid-template-columns: 170px minmax(0, 1fr) 240px;
27681
+ align-items: center;
27682
+ gap: 28px;
27683
+ border: 1px solid rgba(96, 122, 177, 0.24);
27684
+ border-radius: 18px;
27685
+ background:
27686
+ radial-gradient(circle at 14% 40%, rgba(124, 58, 237, 0.2), transparent 30%),
27687
+ linear-gradient(90deg, rgba(8, 17, 34, 0.82), rgba(13, 20, 43, 0.42));
27688
+ padding: 18px;
27689
+ overflow: hidden;
27690
+ }
27691
+
27692
+ .vr-modal-agent-avatar {
27693
+ width: 198px;
27694
+ height: 198px;
27695
+ object-fit: contain;
27696
+ filter: saturate(1.32) contrast(1.04) drop-shadow(0 0 38px rgba(124, 58, 237, 0.78));
27697
+ animation: vrMascotIdle 3200ms cubic-bezier(0.23, 1, 0.32, 1) infinite;
27698
+ }
27257
27699
 
27258
27700
  .vr-modal-agent-head em {
27259
27701
  color: #dbeafe;
@@ -28261,39 +28703,75 @@ body:has(.vr-app.is-dragging) {
28261
28703
  border-color: rgba(239, 68, 68, 0.45);
28262
28704
  }
28263
28705
  .vr-chat-gate-chip.is-blocker i { background: var(--vr-red); }
28264
- .vr-chat-provider-dots {
28706
+ .vr-chat-provider-dots,
28707
+ .vr-chat-version-dots {
28265
28708
  display: inline-flex;
28266
28709
  align-items: center;
28267
28710
  }
28268
- .vr-chat-provider-dot {
28711
+ .vr-chat-version-dots {
28712
+ margin-left: 10px;
28713
+ padding-left: 10px;
28714
+ border-left: 1px solid rgba(148, 163, 184, 0.14);
28715
+ }
28716
+ .vr-chat-provider-dot,
28717
+ .vr-chat-version-dot {
28269
28718
  display: inline-flex;
28270
28719
  align-items: center;
28271
28720
  justify-content: center;
28272
- width: 24px;
28273
- height: 24px;
28274
- margin-left: -6px;
28721
+ width: 30px;
28722
+ height: 30px;
28723
+ margin-left: -7px;
28275
28724
  border: 1px solid var(--vr-border);
28276
28725
  border-radius: 50%;
28277
28726
  background: rgba(12, 13, 16, 0.92);
28278
28727
  cursor: grab;
28279
28728
  transition: transform 0.12s ease, border-color 0.12s ease;
28280
28729
  }
28281
- .vr-chat-provider-dot:first-child {
28730
+ .vr-chat-provider-dot:first-child,
28731
+ .vr-chat-version-dot:first-child {
28282
28732
  margin-left: 0;
28283
28733
  }
28284
- .vr-chat-provider-dot:hover {
28734
+ .vr-chat-provider-dot:hover,
28735
+ .vr-chat-version-dot:hover {
28285
28736
  transform: translateY(-2px);
28286
28737
  border-color: rgba(124, 58, 237, 0.6);
28287
28738
  z-index: 1;
28288
28739
  }
28289
28740
  .vr-chat-provider-dot svg,
28290
28741
  .vr-chat-provider-dot img {
28291
- width: 13px;
28292
- height: 13px;
28742
+ width: 17px;
28743
+ height: 17px;
28293
28744
  }
28294
28745
  .vr-chat-provider-dot[data-provider-tone='green'] { border-color: rgba(34, 197, 94, 0.4); }
28295
28746
  .vr-chat-provider-dot[data-provider-tone='orange'] { border-color: rgba(249, 115, 22, 0.4); }
28296
28747
  .vr-chat-provider-dot[data-provider-tone='red'] { border-color: rgba(239, 68, 68, 0.45); }
28748
+ .vr-chat-version-dot {
28749
+ width: auto;
28750
+ min-width: 76px;
28751
+ padding: 0 10px;
28752
+ border-radius: 9px;
28753
+ background: rgba(18, 22, 33, 0.94);
28754
+ color: #c4b5fd;
28755
+ }
28756
+ .vr-chat-version-dot small {
28757
+ display: block;
28758
+ max-width: none;
28759
+ overflow: visible;
28760
+ font-size: 12px;
28761
+ font-weight: 800;
28762
+ letter-spacing: 0;
28763
+ line-height: 1;
28764
+ font-variant-numeric: tabular-nums;
28765
+ white-space: nowrap;
28766
+ }
28767
+ .vr-chat-version-dot[data-tone='current'],
28768
+ .vr-chat-version-dot.is-selected {
28769
+ border-color: rgba(34, 197, 94, 0.46);
28770
+ color: #86efac;
28771
+ }
28772
+ .vr-chat-version-dot[data-tone='prod'] {
28773
+ border-color: rgba(124, 58, 237, 0.46);
28774
+ }
28297
28775
 
28298
28776
  /* --- Provider detail panel: professional pass --- */
28299
28777
  .vr-provider-detail-panel[data-provider-tone='green'] {
@@ -28730,7 +29208,7 @@ body:has(.vr-app.is-dragging) {
28730
29208
  }
28731
29209
 
28732
29210
  /* ==========================================================================
28733
- Clarity pass \u2014 purple budget + text strength.
29211
+ Clarity pass \xE2\u20AC\u201D purple budget + text strength.
28734
29212
  Rule: purple marks interactive/brand only. Surfaces are neutral dark.
28735
29213
  Green/orange/red are reserved for status.
28736
29214
  ========================================================================== */
@@ -28756,6 +29234,235 @@ body:has(.vr-app.is-dragging) {
28756
29234
  color: var(--vr-muted);
28757
29235
  }
28758
29236
 
29237
+ /* Transcript cards: stronger mission input and richer agent output without adding noise. */
29238
+ .vr-story-node.is-user .vr-chat-message.is-user {
29239
+ position: relative;
29240
+ min-height: 96px;
29241
+ padding: 18px 22px 18px 92px;
29242
+ overflow: hidden;
29243
+ border-left: 1px solid rgba(124, 58, 237, 0.78);
29244
+ border-color: rgba(124, 58, 237, 0.38);
29245
+ border-radius: 16px;
29246
+ background:
29247
+ radial-gradient(circle at 94% 18%, rgba(124, 58, 237, 0.14), transparent 170px),
29248
+ linear-gradient(135deg, rgba(19, 18, 33, 0.96), rgba(13, 15, 22, 0.94));
29249
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.035);
29250
+ }
29251
+
29252
+ .vr-story-node.is-user .vr-chat-message.is-user::after {
29253
+ content: "";
29254
+ position: absolute;
29255
+ left: 22px;
29256
+ top: 22px;
29257
+ width: 46px;
29258
+ height: 46px;
29259
+ border: 1px solid rgba(168, 85, 247, 0.42);
29260
+ border-radius: 14px;
29261
+ background:
29262
+ radial-gradient(circle at 50% 50%, rgba(216, 180, 254, 0.55) 0 3px, transparent 4px),
29263
+ radial-gradient(circle at 28% 30%, rgba(168, 85, 247, 0.35), transparent 18px),
29264
+ rgba(124, 58, 237, 0.13);
29265
+ box-shadow: 0 0 28px rgba(124, 58, 237, 0.16);
29266
+ }
29267
+
29268
+ .vr-story-node.is-user .vr-chat-message.is-user::before {
29269
+ margin: 0 0 9px;
29270
+ color: #a78bfa;
29271
+ font-size: 11px;
29272
+ font-weight: 800;
29273
+ letter-spacing: 0.08em;
29274
+ }
29275
+
29276
+ .vr-story-node.is-user .vr-chat-message.is-user > p {
29277
+ color: #f8fafc;
29278
+ font-size: 18px;
29279
+ font-weight: 740;
29280
+ line-height: 1.28;
29281
+ }
29282
+
29283
+ .vr-chat-agent-response {
29284
+ position: relative;
29285
+ width: min(980px, 100%);
29286
+ padding: 16px 18px;
29287
+ overflow: hidden;
29288
+ border: 1px solid rgba(34, 197, 94, 0.32);
29289
+ border-radius: 16px;
29290
+ background:
29291
+ radial-gradient(circle at 100% 0%, rgba(16, 185, 129, 0.12), transparent 210px),
29292
+ linear-gradient(135deg, rgba(7, 30, 28, 0.9), rgba(13, 16, 24, 0.94));
29293
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
29294
+ }
29295
+
29296
+ .vr-chat-agent-response.is-error {
29297
+ border-color: rgba(239, 68, 68, 0.38);
29298
+ background:
29299
+ radial-gradient(circle at 100% 0%, rgba(239, 68, 68, 0.12), transparent 210px),
29300
+ linear-gradient(135deg, rgba(31, 14, 18, 0.9), rgba(13, 16, 24, 0.94));
29301
+ }
29302
+
29303
+ .vr-chat-agent-response > div:first-child {
29304
+ align-items: center;
29305
+ gap: 12px;
29306
+ padding-bottom: 10px;
29307
+ }
29308
+
29309
+ .vr-chat-agent-response > div:first-child > span {
29310
+ width: 44px;
29311
+ height: 44px;
29312
+ border: 1px solid rgba(34, 197, 94, 0.28);
29313
+ border-radius: 999px;
29314
+ background: rgba(6, 78, 59, 0.22);
29315
+ }
29316
+
29317
+ .vr-chat-agent-response.is-error > div:first-child > span {
29318
+ border-color: rgba(239, 68, 68, 0.35);
29319
+ background: rgba(127, 29, 29, 0.18);
29320
+ }
29321
+
29322
+ .vr-chat-agent-response > div:first-child img {
29323
+ width: 54px;
29324
+ height: 54px;
29325
+ transform: translateY(7px);
29326
+ }
29327
+
29328
+ .vr-chat-agent-response > div:first-child p strong {
29329
+ display: inline-block;
29330
+ color: #f8fafc;
29331
+ font-size: 18px;
29332
+ font-weight: 760;
29333
+ }
29334
+
29335
+ .vr-chat-agent-response > div:first-child p em {
29336
+ color: #94a3b8;
29337
+ }
29338
+
29339
+ .vr-chat-agent-response .vr-agent-response-meta {
29340
+ margin: 0 0 10px 56px;
29341
+ gap: 10px;
29342
+ }
29343
+
29344
+ .vr-chat-agent-response .vr-agent-thinking-label {
29345
+ border-color: rgba(34, 197, 94, 0.35);
29346
+ background: rgba(16, 185, 129, 0.11);
29347
+ color: #6ee7b7;
29348
+ }
29349
+
29350
+ .vr-chat-agent-response.is-error .vr-agent-thinking-label {
29351
+ border-color: rgba(249, 115, 22, 0.38);
29352
+ background: rgba(249, 115, 22, 0.1);
29353
+ color: #fdba74;
29354
+ }
29355
+
29356
+ .vr-chat-agent-response .vr-agent-cli-chip {
29357
+ border-color: rgba(34, 197, 94, 0.28);
29358
+ background: rgba(6, 78, 59, 0.14);
29359
+ color: #a7f3d0;
29360
+ }
29361
+
29362
+ .vr-chat-agent-response .vr-agent-context-line,
29363
+ .vr-chat-agent-response .vr-agent-response-stack {
29364
+ margin-left: 56px;
29365
+ }
29366
+
29367
+ .vr-chat-agent-response .vr-agent-answer-body {
29368
+ margin-top: 4px;
29369
+ }
29370
+
29371
+ .vr-chat-agent-response .vr-agent-answer-body > p:first-child {
29372
+ color: #dbeafe;
29373
+ font-size: 15px;
29374
+ }
29375
+
29376
+ .vr-chat-mission-summary .vr-chat-blockers-card {
29377
+ gap: 12px;
29378
+ border-color: rgba(239, 68, 68, 0.35);
29379
+ background:
29380
+ radial-gradient(circle at 100% 0%, rgba(239, 68, 68, 0.1), transparent 180px),
29381
+ rgba(14, 17, 24, 0.86);
29382
+ padding: 16px;
29383
+ }
29384
+
29385
+ .vr-chat-blockers-card header {
29386
+ padding-bottom: 4px;
29387
+ }
29388
+
29389
+ .vr-chat-blockers-card header strong {
29390
+ font-size: 18px;
29391
+ font-weight: 760;
29392
+ }
29393
+
29394
+ .vr-chat-blockers-card header b {
29395
+ border: 1px solid rgba(239, 68, 68, 0.38);
29396
+ border-radius: 999px;
29397
+ background: rgba(239, 68, 68, 0.1);
29398
+ color: #fca5a5;
29399
+ padding: 5px 10px;
29400
+ font-size: 12px;
29401
+ font-weight: 720;
29402
+ }
29403
+
29404
+ .vr-chat-mission-summary .vr-chat-blockers-card > span {
29405
+ position: relative;
29406
+ min-height: 84px;
29407
+ grid-template-columns: 34px minmax(0, 1fr);
29408
+ gap: 12px;
29409
+ border: 1px solid rgba(148, 163, 184, 0.14);
29410
+ border-radius: 12px;
29411
+ background: rgba(15, 23, 42, 0.46);
29412
+ padding: 14px 14px 36px;
29413
+ }
29414
+
29415
+ .vr-chat-mission-summary .vr-chat-blockers-card > span:hover {
29416
+ border-color: rgba(239, 68, 68, 0.42);
29417
+ background: rgba(30, 41, 59, 0.48);
29418
+ }
29419
+
29420
+ .vr-chat-blockers-card > span i {
29421
+ width: 30px;
29422
+ height: 30px;
29423
+ background: rgba(239, 68, 68, 0.12);
29424
+ }
29425
+
29426
+ .vr-chat-blockers-card > span em {
29427
+ color: #f8fafc;
29428
+ font-size: 14px;
29429
+ font-weight: 700;
29430
+ line-height: 1.35;
29431
+ white-space: normal;
29432
+ }
29433
+
29434
+ .vr-chat-blockers-card > span small {
29435
+ margin-top: 7px;
29436
+ color: #aeb8c8;
29437
+ font-size: 12.5px;
29438
+ font-weight: 480;
29439
+ line-height: 1.4;
29440
+ white-space: normal;
29441
+ }
29442
+
29443
+ .vr-chat-blockers-card > span b {
29444
+ position: absolute;
29445
+ right: 14px;
29446
+ bottom: 12px;
29447
+ border: 1px solid rgba(168, 85, 247, 0.24);
29448
+ border-radius: 999px;
29449
+ background: rgba(124, 58, 237, 0.1);
29450
+ color: #c4b5fd;
29451
+ padding: 3px 8px;
29452
+ font-size: 11px;
29453
+ font-weight: 720;
29454
+ }
29455
+
29456
+ @media (min-width: 1260px) {
29457
+ .vr-chat-mission-summary .vr-chat-blockers-card {
29458
+ grid-template-columns: repeat(3, minmax(0, 1fr));
29459
+ }
29460
+
29461
+ .vr-chat-blockers-card header {
29462
+ grid-column: 1 / -1;
29463
+ }
29464
+ }
29465
+
28759
29466
  /* Story rail: neutral line and dots; purple only marks the user's input. */
28760
29467
  .vr-story-node::before {
28761
29468
  background: linear-gradient(180deg, rgba(148, 163, 184, 0.22), rgba(148, 163, 184, 0.04));
@@ -28800,7 +29507,7 @@ body:has(.vr-app.is-dragging) {
28800
29507
  background: rgba(10, 14, 24, 0.85);
28801
29508
  }
28802
29509
 
28803
- /* Composer: neutral until focused \u2014 then purple earns its place. */
29510
+ /* Composer: neutral until focused \xE2\u20AC\u201D then purple earns its place. */
28804
29511
  .vr-chat-composer {
28805
29512
  border-color: rgba(148, 163, 184, 0.2);
28806
29513
  }
@@ -28893,8 +29600,160 @@ body:has(.vr-app.is-dragging) {
28893
29600
  height: 14px;
28894
29601
  }
28895
29602
 
28896
- /* Gate chip is a button now \u2014 keep the pill look. */
28897
- button.vr-chat-gate-chip {
29603
+ .vr-chat-intro-message {
29604
+ width: min(780px, 100%);
29605
+ max-width: min(780px, 100%);
29606
+ }
29607
+
29608
+ .vr-chat-intro-message > div:first-child > p {
29609
+ display: flex;
29610
+ align-items: center;
29611
+ gap: 8px;
29612
+ }
29613
+
29614
+ .vr-chat-intro-message > div:first-child > p strong {
29615
+ font-size: 14px;
29616
+ }
29617
+
29618
+ .vr-chat-intro-message > div:first-child > p b {
29619
+ margin: 0;
29620
+ border-color: rgba(168, 85, 247, 0.35);
29621
+ background: rgba(124, 58, 237, 0.22);
29622
+ color: #d8b4fe;
29623
+ padding: 3px 8px;
29624
+ font-size: 11px;
29625
+ }
29626
+
29627
+ .vr-chat-intro-message > div:first-child > p em.is-ready {
29628
+ position: relative;
29629
+ display: inline-flex;
29630
+ align-items: center;
29631
+ gap: 6px;
29632
+ color: #86efac;
29633
+ font-size: 12px;
29634
+ font-weight: 650;
29635
+ }
29636
+
29637
+ .vr-chat-intro-message > div:first-child > p em.is-ready::before {
29638
+ content: "";
29639
+ width: 6px;
29640
+ height: 6px;
29641
+ border-radius: 999px;
29642
+ background: #22c55e;
29643
+ }
29644
+
29645
+ .vr-chat-intro-message > p {
29646
+ padding-left: 48px;
29647
+ color: #dbe3ee;
29648
+ }
29649
+
29650
+ .vr-chat-intro-message > p strong {
29651
+ color: #f8fafc;
29652
+ }
29653
+
29654
+ .vr-env-connect-card {
29655
+ width: min(690px, calc(100% - 48px));
29656
+ margin: 20px 0 0 48px;
29657
+ display: grid;
29658
+ gap: 12px;
29659
+ border: 1px solid rgba(168, 85, 247, 0.32);
29660
+ border-radius: 16px;
29661
+ background:
29662
+ radial-gradient(circle at 76% 12%, rgba(124, 58, 237, 0.11), transparent 150px),
29663
+ linear-gradient(180deg, rgba(22, 24, 33, 0.82), rgba(15, 17, 24, 0.9));
29664
+ box-shadow:
29665
+ inset 0 1px 0 rgba(255, 255, 255, 0.03),
29666
+ 0 14px 42px rgba(0, 0, 0, 0.24);
29667
+ padding: 18px;
29668
+ }
29669
+
29670
+ .vr-env-connect-card header {
29671
+ display: flex;
29672
+ align-items: center;
29673
+ justify-content: space-between;
29674
+ }
29675
+
29676
+ .vr-env-connect-card header strong {
29677
+ color: #f8fafc;
29678
+ font-size: 16px;
29679
+ font-weight: 760;
29680
+ }
29681
+
29682
+ .vr-env-connect-card > div {
29683
+ display: grid;
29684
+ grid-template-columns: repeat(3, minmax(0, 1fr));
29685
+ gap: 9px;
29686
+ }
29687
+
29688
+ .vr-env-connect-option {
29689
+ min-width: 0;
29690
+ min-height: 48px;
29691
+ display: grid;
29692
+ grid-template-columns: 26px minmax(0, 1fr) auto;
29693
+ align-items: center;
29694
+ gap: 9px;
29695
+ border: 1px solid rgba(148, 163, 184, 0.13);
29696
+ border-radius: 10px;
29697
+ background: rgba(8, 12, 20, 0.34);
29698
+ color: #f4f4f5;
29699
+ padding: 9px 10px;
29700
+ text-align: left;
29701
+ }
29702
+
29703
+ .vr-env-connect-option:hover {
29704
+ border-color: rgba(168, 85, 247, 0.38);
29705
+ background: rgba(124, 58, 237, 0.085);
29706
+ }
29707
+
29708
+ .vr-env-connect-option > span {
29709
+ width: 26px;
29710
+ height: 26px;
29711
+ display: grid;
29712
+ place-items: center;
29713
+ color: #d8b4fe;
29714
+ }
29715
+
29716
+ .vr-env-connect-option > span img,
29717
+ .vr-env-connect-option > span svg {
29718
+ width: 18px;
29719
+ height: 18px;
29720
+ object-fit: contain;
29721
+ }
29722
+
29723
+ .vr-env-connect-option strong {
29724
+ min-width: 0;
29725
+ overflow: hidden;
29726
+ color: #f8fafc;
29727
+ font-size: 13.5px;
29728
+ font-weight: 720;
29729
+ text-overflow: ellipsis;
29730
+ white-space: nowrap;
29731
+ }
29732
+
29733
+ .vr-env-connect-option b {
29734
+ margin: 0;
29735
+ border: 0;
29736
+ border-radius: 999px;
29737
+ background: rgba(148, 163, 184, 0.09);
29738
+ color: #cbd5e1;
29739
+ padding: 4px 9px;
29740
+ font-size: 11px;
29741
+ font-weight: 650;
29742
+ white-space: nowrap;
29743
+ }
29744
+
29745
+ .vr-env-connect-option.is-disconnected b {
29746
+ background: rgba(124, 58, 237, 0.16);
29747
+ color: #d8b4fe;
29748
+ }
29749
+
29750
+ .vr-env-connect-option.is-connected b {
29751
+ background: rgba(34, 197, 94, 0.12);
29752
+ color: #86efac;
29753
+ }
29754
+
29755
+ /* Gate chip is a button now \xE2\u20AC\u201D keep the pill look. */
29756
+ button.vr-chat-gate-chip {
28898
29757
  cursor: pointer;
28899
29758
  background: rgba(12, 13, 16, 0.7);
28900
29759
  font: inherit;
@@ -28939,14 +29798,28 @@ button.vr-chat-gate-chip {
28939
29798
  border-radius: 12px;
28940
29799
  background: rgba(14, 17, 26, 0.96);
28941
29800
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
28942
- cursor: grab;
29801
+ cursor: pointer;
28943
29802
  user-select: none;
28944
- touch-action: none;
29803
+ touch-action: manipulation;
29804
+ transition:
29805
+ border-color 150ms ease,
29806
+ background 150ms ease,
29807
+ box-shadow 150ms ease,
29808
+ transform 150ms ease;
28945
29809
  }
28946
29810
  .vr-arch-node:active {
28947
- cursor: grabbing;
28948
29811
  border-color: rgba(124, 58, 237, 0.6);
28949
29812
  }
29813
+ .vr-arch-node:hover,
29814
+ .vr-arch-node.is-selected {
29815
+ border-color: rgba(168, 85, 247, 0.58);
29816
+ background:
29817
+ radial-gradient(circle at 100% 0%, rgba(124, 58, 237, 0.16), transparent 34px),
29818
+ rgba(16, 19, 29, 0.98);
29819
+ box-shadow:
29820
+ 0 0 0 1px rgba(168, 85, 247, 0.14),
29821
+ 0 12px 30px rgba(0, 0, 0, 0.38);
29822
+ }
28950
29823
  .vr-arch-node strong {
28951
29824
  display: block;
28952
29825
  font-size: 13px;
@@ -29130,9 +30003,15 @@ button.vr-chat-gate-chip {
29130
30003
  }
29131
30004
 
29132
30005
  /* --- Release modal symmetry --- */
30006
+ .vr-modal-release {
30007
+ width: min(820px, calc(100vw - 48px));
30008
+ }
29133
30009
  .vr-modal-two-col {
29134
30010
  align-items: stretch;
29135
30011
  }
30012
+ .vr-modal-release .vr-modal-two-col {
30013
+ grid-template-columns: minmax(0, 1.18fr) minmax(220px, 0.82fr);
30014
+ }
29136
30015
  .vr-modal-two-col > section {
29137
30016
  display: flex;
29138
30017
  flex-direction: column;
@@ -29158,6 +30037,14 @@ button.vr-chat-gate-chip {
29158
30037
  .vr-modal-two-col dd {
29159
30038
  margin: 0;
29160
30039
  text-align: right;
30040
+ min-width: 0;
30041
+ overflow-wrap: anywhere;
30042
+ }
30043
+
30044
+ @media (max-width: 860px) {
30045
+ .vr-modal-release .vr-modal-two-col {
30046
+ grid-template-columns: 1fr;
30047
+ }
29161
30048
  }
29162
30049
 
29163
30050
  /* --- Architecture graph: zones and guidance --- */
@@ -29681,7 +30568,7 @@ div.vr-branch-row {
29681
30568
  }
29682
30569
 
29683
30570
  /* ==========================================================================
29684
- Professional pass v2 \u2014 flat, aligned, quiet.
30571
+ Professional pass v2 \xE2\u20AC\u201D flat, aligned, quiet.
29685
30572
  ========================================================================== */
29686
30573
 
29687
30574
  /* Provider modal: flat header, no glow toys. */
@@ -29982,7 +30869,7 @@ div.vr-branch-row {
29982
30869
  }
29983
30870
 
29984
30871
  /* ==========================================================================
29985
- Global calm pass \u2014 flat surfaces, one quiet accent, breathing room.
30872
+ Global calm pass \xE2\u20AC\u201D flat surfaces, one quiet accent, breathing room.
29986
30873
  ========================================================================== */
29987
30874
 
29988
30875
  /* Flat canvas: no ambient color washes. */
@@ -30049,170 +30936,1973 @@ body {
30049
30936
  }
30050
30937
  }
30051
30938
 
30052
- /* Provider popup checks: identical geometry for every row state. */
30053
- .vr-modal-checks li,
30054
- .vr-modal-checks li.pending,
30055
- .vr-modal-checks li.active,
30056
- .vr-modal-checks li.running,
30057
- .vr-modal-checks li.done {
30058
- display: grid;
30059
- grid-template-columns: 30px minmax(0, 1fr) auto;
30060
- align-items: center;
30061
- gap: 12px;
30062
- min-height: 52px;
30063
- margin: 0 0 6px;
30064
- padding: 6px 14px;
30065
- }
30066
- .vr-modal-checks li > span,
30067
- .vr-modal-checks li.pending > span,
30068
- .vr-modal-checks li.active > span,
30069
- .vr-modal-checks li.running > span,
30070
- .vr-modal-checks li.done > span {
30071
- width: 20px;
30072
- height: 20px;
30073
- justify-self: center;
30939
+ /* Provider popup checks: identical geometry for every row state. */
30940
+ .vr-modal-checks li,
30941
+ .vr-modal-checks li.pending,
30942
+ .vr-modal-checks li.active,
30943
+ .vr-modal-checks li.running,
30944
+ .vr-modal-checks li.done {
30945
+ display: grid;
30946
+ grid-template-columns: 30px minmax(0, 1fr) auto;
30947
+ align-items: center;
30948
+ gap: 12px;
30949
+ min-height: 52px;
30950
+ margin: 0 0 6px;
30951
+ padding: 6px 14px;
30952
+ }
30953
+ .vr-modal-checks li > span,
30954
+ .vr-modal-checks li.pending > span,
30955
+ .vr-modal-checks li.active > span,
30956
+ .vr-modal-checks li.running > span,
30957
+ .vr-modal-checks li.done > span {
30958
+ width: 20px;
30959
+ height: 20px;
30960
+ justify-self: center;
30961
+ }
30962
+ .vr-modal-health-line {
30963
+ flex-wrap: wrap;
30964
+ align-items: center;
30965
+ line-height: 1.4;
30966
+ font-size: 12.5px;
30967
+ }
30968
+ .vr-modal-health-line .vr-modal-pill {
30969
+ flex-shrink: 0;
30970
+ }
30971
+ .vr-mcp-connect-btn {
30972
+ border: 1px solid rgba(124, 58, 237, 0.5);
30973
+ border-radius: 999px;
30974
+ background: rgba(124, 58, 237, 0.1);
30975
+ color: var(--vr-text);
30976
+ font-size: 12px;
30977
+ font-weight: 600;
30978
+ padding: 6px 14px;
30979
+ cursor: pointer;
30980
+ }
30981
+
30982
+ /* Provider modal: calm cockpit treatment. */
30983
+ .vr-modal-provider {
30984
+ width: min(860px, calc(100vw - 48px));
30985
+ }
30986
+ .vr-modal-provider .vr-modal-mascot {
30987
+ display: none;
30988
+ }
30989
+ .vr-modal-provider-head {
30990
+ grid-template-columns: 48px minmax(0, 1fr);
30991
+ min-height: 0;
30992
+ border-color: rgba(148, 163, 184, 0.14);
30993
+ background: rgba(255, 255, 255, 0.018);
30994
+ }
30995
+ .vr-modal-provider-head h2 {
30996
+ font-size: 22px;
30997
+ }
30998
+ .vr-modal-provider-head .vr-status-badge {
30999
+ margin-left: 8px;
31000
+ }
31001
+ .vr-provider-mcp-panel,
31002
+ .vr-provider-mcp-panel.is-connected,
31003
+ .vr-provider-mcp-panel.is-disconnected {
31004
+ border-color: rgba(148, 163, 184, 0.14);
31005
+ border-radius: 12px;
31006
+ background: rgba(255, 255, 255, 0.018);
31007
+ box-shadow: none;
31008
+ }
31009
+ .vr-provider-mcp-panel header {
31010
+ grid-template-columns: 34px minmax(0, 1fr) auto;
31011
+ }
31012
+ .vr-provider-mcp-panel header > span {
31013
+ width: 32px;
31014
+ height: 32px;
31015
+ border-color: rgba(148, 163, 184, 0.18);
31016
+ border-radius: 9px;
31017
+ background: rgba(255, 255, 255, 0.025);
31018
+ color: #aeb9ca;
31019
+ }
31020
+ .vr-provider-mcp-panel.is-connected header > span {
31021
+ border-color: rgba(34, 197, 94, 0.24);
31022
+ background: rgba(34, 197, 94, 0.06);
31023
+ color: #86efac;
31024
+ }
31025
+ .vr-provider-mcp-panel header small {
31026
+ display: block;
31027
+ margin-bottom: 2px;
31028
+ color: #8f9bad;
31029
+ font-size: 10.5px;
31030
+ font-weight: 750;
31031
+ letter-spacing: 0.08em;
31032
+ text-transform: uppercase;
31033
+ }
31034
+ .vr-provider-mcp-panel header strong {
31035
+ color: #f4f4f5;
31036
+ font-size: 13.5px;
31037
+ }
31038
+ .vr-provider-mcp-panel header em {
31039
+ margin-top: 2px;
31040
+ color: #9ca3af;
31041
+ font-size: 12px;
31042
+ }
31043
+ .vr-provider-mcp-panel > div small {
31044
+ border-radius: 7px;
31045
+ background: rgba(255, 255, 255, 0.025);
31046
+ color: #aeb9ca;
31047
+ }
31048
+ .vr-mcp-connect-btn {
31049
+ border-radius: 9px;
31050
+ background: rgba(255, 255, 255, 0.025);
31051
+ color: #e5e7eb;
31052
+ }
31053
+ .vr-mcp-connect-btn:hover {
31054
+ border-color: rgba(168, 85, 247, 0.45);
31055
+ background: rgba(124, 58, 237, 0.1);
31056
+ }
31057
+ .vr-composer-controls .vr-model-picker > button:nth-child(4) {
31058
+ min-width: 158px;
31059
+ max-width: 178px;
31060
+ }
31061
+ .vr-composer-controls .vr-model-picker > button:nth-child(4) strong {
31062
+ max-width: 132px;
31063
+ }
31064
+
31065
+ /* Quickstart */
31066
+ .vr-qs-steps {
31067
+ display: grid;
31068
+ gap: 8px;
31069
+ margin-top: 16px;
31070
+ }
31071
+ .vr-qs-step {
31072
+ display: grid;
31073
+ grid-template-columns: 34px minmax(0, 1fr) auto;
31074
+ align-items: center;
31075
+ gap: 14px;
31076
+ padding: 13px 16px;
31077
+ border: 1px solid rgba(148, 163, 184, 0.14);
31078
+ border-radius: 12px;
31079
+ background: rgba(255, 255, 255, 0.02);
31080
+ }
31081
+ .vr-qs-step.is-done {
31082
+ opacity: 0.72;
31083
+ }
31084
+ .vr-qs-num {
31085
+ display: inline-flex;
31086
+ align-items: center;
31087
+ justify-content: center;
31088
+ width: 30px;
31089
+ height: 30px;
31090
+ border: 1px solid rgba(148, 163, 184, 0.3);
31091
+ border-radius: 50%;
31092
+ font-size: 13px;
31093
+ font-weight: 700;
31094
+ color: var(--vr-muted);
31095
+ }
31096
+ .vr-qs-step.is-done .vr-qs-num {
31097
+ border-color: rgba(34, 197, 94, 0.5);
31098
+ color: var(--vr-green);
31099
+ }
31100
+ .vr-qs-num svg { width: 13px; height: 13px; }
31101
+ .vr-qs-step strong { display: block; font-size: 14px; }
31102
+ .vr-qs-step em { display: block; font-size: 12px; font-style: normal; color: var(--vr-muted); }
31103
+ .vr-qs-step > b {
31104
+ font-size: 11px;
31105
+ font-weight: 650;
31106
+ color: var(--vr-green);
31107
+ border: 1px solid rgba(34, 197, 94, 0.4);
31108
+ border-radius: 999px;
31109
+ padding: 3px 11px;
31110
+ }
31111
+ .vr-qs-step > button {
31112
+ border: 1px solid rgba(124, 58, 237, 0.55);
31113
+ border-radius: 999px;
31114
+ background: rgba(124, 58, 237, 0.12);
31115
+ color: var(--vr-text);
31116
+ font-size: 12.5px;
31117
+ font-weight: 650;
31118
+ padding: 7px 16px;
31119
+ cursor: pointer;
31120
+ }
31121
+ .vr-qs-step > button:hover { background: rgba(124, 58, 237, 0.2); }
31122
+ .vr-qs-foot {
31123
+ display: flex;
31124
+ align-items: center;
31125
+ justify-content: space-between;
31126
+ gap: 12px;
31127
+ margin-top: 16px;
31128
+ }
31129
+ .vr-qs-foot button {
31130
+ border: 0;
31131
+ background: transparent;
31132
+ color: var(--vr-muted);
31133
+ font-size: 12px;
31134
+ text-decoration: underline;
31135
+ cursor: pointer;
31136
+ }
31137
+ .vr-qs-foot span { font-size: 12px; color: var(--vr-muted); }
31138
+
31139
+ /* --- Claude-style composer: one + button, actions on demand, air. --- */
31140
+ .vr-chat-plus {
31141
+ flex: 0 0 auto;
31142
+ display: inline-flex;
31143
+ align-items: center;
31144
+ justify-content: center;
31145
+ width: 34px;
31146
+ height: 34px;
31147
+ border: 1px solid rgba(148, 163, 184, 0.25);
31148
+ border-radius: 50%;
31149
+ background: rgba(255, 255, 255, 0.03);
31150
+ color: var(--vr-muted);
31151
+ cursor: pointer;
31152
+ transition: border-color 0.15s ease, color 0.15s ease, transform 0.12s ease;
31153
+ }
31154
+ .vr-chat-plus:hover {
31155
+ border-color: rgba(124, 58, 237, 0.55);
31156
+ color: var(--vr-text);
31157
+ }
31158
+ .vr-chat-plus.is-open {
31159
+ border-color: rgba(124, 58, 237, 0.55);
31160
+ color: var(--vr-text);
31161
+ transform: rotate(0deg);
31162
+ }
31163
+ .vr-chat-plus svg {
31164
+ width: 14px;
31165
+ height: 14px;
31166
+ }
31167
+ .vr-chat-inline-actions.is-collapsed {
31168
+ overflow: visible;
31169
+ padding: 6px 0 10px;
31170
+ }
31171
+ .vr-chat-inline-actions {
31172
+ align-items: center;
31173
+ }
31174
+
31175
+ /* Breathing room in the chat lane. */
31176
+ .vr-chat-transcript {
31177
+ padding: 14px 16px 10px;
31178
+ }
31179
+ .vr-chat-command-bar {
31180
+ gap: 8px;
31181
+ padding: 10px 14px 14px;
31182
+ }
31183
+ .vr-chat-command-bar > .vr-chat-composer {
31184
+ border-radius: 18px;
31185
+ padding: 14px 16px;
31186
+ }
31187
+
31188
+ /* --- Clean chat canvas correction: sidebars are commands, inspector opens on demand. --- */
31189
+ .vr-composed-shell {
31190
+ grid-template-rows: 52px minmax(0, 1fr);
31191
+ }
31192
+
31193
+ .vr-bottom-tip-bar {
31194
+ display: none;
31195
+ }
31196
+
31197
+ .vr-composition-body,
31198
+ .vr-composition-body.has-inspector {
31199
+ grid-template-columns: 248px minmax(0, 1fr);
31200
+ gap: 10px;
31201
+ padding: 10px;
31202
+ }
31203
+
31204
+ .vr-composition-body.has-inspector {
31205
+ grid-template-columns: 248px minmax(0, 1fr) clamp(460px, 31vw, 620px);
31206
+ }
31207
+
31208
+ .vr-composition-body.has-inspector.inspector-expanded {
31209
+ grid-template-columns: 248px minmax(760px, 0.95fr) minmax(640px, 0.8fr);
31210
+ }
31211
+
31212
+ .vr-left-context-rail {
31213
+ grid-template-rows: auto minmax(0, 1fr);
31214
+ }
31215
+
31216
+ .vr-left-context-rail .vr-releases-panel,
31217
+ .vr-context-rail,
31218
+ .vr-agent-panel,
31219
+ .vr-providers-panel {
31220
+ display: none;
31221
+ }
31222
+
31223
+ .vr-left-context-rail .vr-recent-rail {
31224
+ border-color: rgba(148, 163, 184, 0.12);
31225
+ background: rgba(17, 19, 23, 0.72);
31226
+ }
31227
+
31228
+ .vr-rail-launchers {
31229
+ display: grid;
31230
+ gap: 7px;
31231
+ border: 1px solid rgba(148, 163, 184, 0.12);
31232
+ border-radius: 12px;
31233
+ background: rgba(17, 19, 23, 0.72);
31234
+ padding: 8px;
31235
+ }
31236
+
31237
+ .vr-rail-launcher {
31238
+ min-width: 0;
31239
+ min-height: 44px;
31240
+ display: grid;
31241
+ grid-template-columns: 28px minmax(0, 1fr) 10px;
31242
+ align-items: center;
31243
+ gap: 9px;
31244
+ border: 1px solid transparent;
31245
+ border-radius: 9px;
31246
+ background: transparent;
31247
+ color: #f4f4f5;
31248
+ padding: 7px 8px;
31249
+ text-align: left;
31250
+ }
31251
+
31252
+ .vr-rail-launcher:hover {
31253
+ border-color: rgba(148, 163, 184, 0.18);
31254
+ background: rgba(255, 255, 255, 0.035);
31255
+ }
31256
+
31257
+ .vr-rail-launcher i[data-icon] {
31258
+ width: 24px;
31259
+ height: 24px;
31260
+ display: grid;
31261
+ place-items: center;
31262
+ border: 1px solid rgba(148, 163, 184, 0.18);
31263
+ border-radius: 8px;
31264
+ background: rgba(255, 255, 255, 0.03);
31265
+ color: #cbd5e1;
31266
+ }
31267
+
31268
+ .vr-rail-launcher i[data-icon] svg {
31269
+ width: 14px;
31270
+ height: 14px;
31271
+ }
31272
+
31273
+ .vr-rail-launcher strong,
31274
+ .vr-rail-launcher em {
31275
+ display: block;
31276
+ min-width: 0;
31277
+ overflow: hidden;
31278
+ text-overflow: ellipsis;
31279
+ white-space: nowrap;
31280
+ }
31281
+
31282
+ .vr-rail-launcher strong {
31283
+ font-size: 12.5px;
31284
+ line-height: 1.2;
31285
+ }
31286
+
31287
+ .vr-rail-launcher em {
31288
+ color: var(--vr-muted);
31289
+ font-size: 11px;
31290
+ font-style: normal;
31291
+ line-height: 1.25;
31292
+ }
31293
+
31294
+ .vr-rail-launcher b {
31295
+ width: 7px;
31296
+ height: 7px;
31297
+ border-right: 1.5px solid #717987;
31298
+ border-bottom: 1.5px solid #717987;
31299
+ transform: rotate(-45deg);
31300
+ }
31301
+
31302
+ .vr-main-canvas,
31303
+ .vr-studio-dock {
31304
+ min-height: 0;
31305
+ }
31306
+
31307
+ .vr-studio-dock {
31308
+ border-color: rgba(148, 163, 184, 0.1);
31309
+ background: rgba(15, 17, 21, 0.58);
31310
+ padding: 8px;
31311
+ }
31312
+
31313
+ .vr-studio-head {
31314
+ padding: 4px 4px 0;
31315
+ }
31316
+
31317
+ .vr-studio-body {
31318
+ min-height: 0;
31319
+ }
31320
+
31321
+ .vr-studio-chat {
31322
+ border-color: rgba(148, 163, 184, 0.09);
31323
+ background: rgba(12, 14, 18, 0.54);
31324
+ }
31325
+
31326
+ .vr-studio-chat:not(.is-split) .vr-chat-transcript {
31327
+ padding: clamp(18px, 3vh, 34px) clamp(24px, 5vw, 76px) 24px;
31328
+ }
31329
+
31330
+ .vr-studio-chat:not(.is-split) .vr-chat-message,
31331
+ .vr-studio-chat:not(.is-split) .vr-chat-mission-summary {
31332
+ max-width: min(920px, 100%);
31333
+ }
31334
+
31335
+ .vr-studio-chat:not(.is-split) .vr-chat-message.is-agent {
31336
+ max-width: min(900px, 100%);
31337
+ }
31338
+
31339
+ .vr-studio-chat:not(.is-split) .vr-chat-command-bar {
31340
+ padding: 8px clamp(20px, 5vw, 70px) 12px;
31341
+ }
31342
+
31343
+ .vr-studio-chat:not(.is-split) .vr-chat-command-bar > .vr-chat-composer {
31344
+ min-height: 112px;
31345
+ border-radius: 18px;
31346
+ border-color: rgba(148, 163, 184, 0.16);
31347
+ background: #202124;
31348
+ }
31349
+
31350
+ .vr-inspector-panel {
31351
+ min-width: 0;
31352
+ min-height: 0;
31353
+ height: 100%;
31354
+ display: grid;
31355
+ grid-template-rows: auto minmax(0, 1fr);
31356
+ border: 1px solid rgba(148, 163, 184, 0.14);
31357
+ border-radius: 13px;
31358
+ background: rgba(17, 19, 23, 0.86);
31359
+ overflow: hidden;
31360
+ }
31361
+
31362
+ .vr-inspector-head {
31363
+ min-height: 52px;
31364
+ display: grid;
31365
+ grid-template-columns: minmax(0, 1fr) 32px 32px;
31366
+ align-items: center;
31367
+ gap: 10px;
31368
+ border-bottom: 1px solid rgba(148, 163, 184, 0.1);
31369
+ padding: 8px 10px 8px 14px;
31370
+ }
31371
+
31372
+ .vr-inspector-head strong,
31373
+ .vr-inspector-head span {
31374
+ display: block;
31375
+ min-width: 0;
31376
+ overflow: hidden;
31377
+ text-overflow: ellipsis;
31378
+ white-space: nowrap;
31379
+ }
31380
+
31381
+ .vr-inspector-head strong {
31382
+ font-size: 13.5px;
31383
+ }
31384
+
31385
+ .vr-inspector-head span {
31386
+ color: var(--vr-muted);
31387
+ font-size: 11.5px;
31388
+ }
31389
+
31390
+ .vr-inspector-head button {
31391
+ width: 30px;
31392
+ height: 30px;
31393
+ display: grid;
31394
+ place-items: center;
31395
+ border: 1px solid rgba(148, 163, 184, 0.15);
31396
+ border-radius: 8px;
31397
+ background: rgba(255, 255, 255, 0.03);
31398
+ color: #cbd5e1;
31399
+ }
31400
+
31401
+ .vr-inspector-body {
31402
+ min-height: 0;
31403
+ overflow: auto;
31404
+ padding: 8px;
31405
+ scrollbar-width: thin;
31406
+ }
31407
+
31408
+ .vr-inspector-body .vr-studio-architecture,
31409
+ .vr-inspector-body .vr-studio-terminal,
31410
+ .vr-inspector-body .vr-studio-diff {
31411
+ height: 100%;
31412
+ min-height: 0;
31413
+ border: 0;
31414
+ border-radius: 0;
31415
+ background: transparent;
31416
+ }
31417
+
31418
+ .vr-inspector-body .vr-studio-architecture > header {
31419
+ grid-template-columns: 1fr;
31420
+ gap: 4px;
31421
+ padding: 10px 12px;
31422
+ border: 1px solid rgba(148, 163, 184, 0.12);
31423
+ border-radius: 12px;
31424
+ background:
31425
+ radial-gradient(circle at 100% 0%, rgba(124, 58, 237, 0.12), transparent 32%),
31426
+ rgba(255, 255, 255, 0.025);
31427
+ }
31428
+
31429
+ .vr-inspector-body .vr-studio-architecture > header strong {
31430
+ font-size: 17px;
31431
+ }
31432
+
31433
+ .vr-inspector-body .vr-arch-body {
31434
+ border-radius: 12px;
31435
+ border-color: rgba(148, 163, 184, 0.12);
31436
+ background-color: rgba(9, 12, 18, 0.78);
31437
+ }
31438
+
31439
+ .vr-inspector-body .vr-studio-architecture > footer {
31440
+ justify-content: start;
31441
+ overflow-x: auto;
31442
+ }
31443
+
31444
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map {
31445
+ padding: 0;
31446
+ gap: 10px;
31447
+ }
31448
+
31449
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map > header {
31450
+ display: grid;
31451
+ grid-template-columns: minmax(0, 1fr);
31452
+ padding: 12px 14px;
31453
+ }
31454
+
31455
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map > header span {
31456
+ max-width: 40ch;
31457
+ }
31458
+
31459
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-body {
31460
+ min-height: 0;
31461
+ border-radius: 14px;
31462
+ overflow: hidden;
31463
+ }
31464
+
31465
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-viewport {
31466
+ inset: 0;
31467
+ overflow: auto;
31468
+ padding: 0;
31469
+ }
31470
+
31471
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-canvas {
31472
+ transform-origin: 0 0;
31473
+ }
31474
+
31475
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-node {
31476
+ width: 168px;
31477
+ height: 54px;
31478
+ border-radius: 11px;
31479
+ box-shadow: 0 10px 26px rgba(0, 0, 0, 0.28);
31480
+ }
31481
+
31482
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-node strong {
31483
+ font-size: 12px;
31484
+ }
31485
+
31486
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-node em {
31487
+ font-size: 10px;
31488
+ }
31489
+
31490
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-hint {
31491
+ display: none;
31492
+ }
31493
+
31494
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-zone {
31495
+ color: rgba(196, 181, 253, 0.66);
31496
+ }
31497
+
31498
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map .vr-arch-zoom {
31499
+ left: 12px;
31500
+ right: auto;
31501
+ bottom: 12px;
31502
+ box-shadow: 0 12px 34px rgba(0, 0, 0, 0.34);
31503
+ }
31504
+
31505
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map > footer {
31506
+ display: grid;
31507
+ grid-template-columns: repeat(2, minmax(0, 1fr));
31508
+ gap: 8px;
31509
+ overflow: visible;
31510
+ }
31511
+
31512
+ .vr-inspector-body .vr-studio-architecture.is-inspector-map > footer button {
31513
+ justify-content: center;
31514
+ min-width: 0;
31515
+ padding-inline: 10px;
31516
+ }
31517
+
31518
+ .vr-inspector-card {
31519
+ min-height: 0;
31520
+ display: grid;
31521
+ gap: 10px;
31522
+ }
31523
+
31524
+ .vr-inspector-hero {
31525
+ position: relative;
31526
+ min-height: 112px;
31527
+ display: grid;
31528
+ grid-template-columns: minmax(0, 1fr) 88px;
31529
+ align-items: center;
31530
+ gap: 12px;
31531
+ overflow: hidden;
31532
+ border: 1px solid rgba(148, 163, 184, 0.14);
31533
+ border-radius: 13px;
31534
+ background:
31535
+ radial-gradient(circle at 90% 42%, rgba(124, 58, 237, 0.22), transparent 34%),
31536
+ linear-gradient(180deg, rgba(30, 33, 42, 0.78), rgba(18, 20, 27, 0.82));
31537
+ padding: 14px 16px;
31538
+ }
31539
+
31540
+ .vr-inspector-hero p,
31541
+ .vr-inspector-hero h3,
31542
+ .vr-inspector-hero em {
31543
+ margin: 0;
31544
+ }
31545
+
31546
+ .vr-inspector-hero p {
31547
+ color: #b794f6;
31548
+ font-size: 11px;
31549
+ font-weight: 800;
31550
+ }
31551
+
31552
+ .vr-inspector-hero h3 {
31553
+ margin-top: 5px;
31554
+ font-size: 24px;
31555
+ line-height: 1.05;
31556
+ }
31557
+
31558
+ .vr-inspector-hero em {
31559
+ display: block;
31560
+ margin-top: 7px;
31561
+ color: #cbd5e1;
31562
+ font-size: 12.5px;
31563
+ font-style: normal;
31564
+ line-height: 1.35;
31565
+ }
31566
+
31567
+ .vr-inspector-hero img {
31568
+ width: 86px;
31569
+ height: 86px;
31570
+ object-fit: contain;
31571
+ object-position: bottom;
31572
+ filter: saturate(1.16) drop-shadow(0 0 20px rgba(124, 58, 237, 0.42));
31573
+ }
31574
+
31575
+ .vr-inspector-provider-grid,
31576
+ .vr-inspector-release-list,
31577
+ .vr-inspector-branch-list,
31578
+ .vr-inspector-changelog {
31579
+ display: grid;
31580
+ gap: 8px;
31581
+ }
31582
+
31583
+ .vr-inspector-provider-row,
31584
+ .vr-inspector-release-list button,
31585
+ .vr-inspector-branch-list > div,
31586
+ .vr-inspector-changelog button {
31587
+ min-width: 0;
31588
+ display: grid;
31589
+ align-items: center;
31590
+ gap: 10px;
31591
+ border: 1px solid rgba(148, 163, 184, 0.13);
31592
+ border-radius: 11px;
31593
+ background: rgba(255, 255, 255, 0.025);
31594
+ color: #f4f4f5;
31595
+ padding: 10px 12px;
31596
+ text-align: left;
31597
+ }
31598
+
31599
+ .vr-inspector-provider-row {
31600
+ grid-template-columns: 34px minmax(0, 1fr) auto;
31601
+ }
31602
+
31603
+ .vr-inspector-provider-row:hover,
31604
+ .vr-inspector-release-list button:hover,
31605
+ .vr-inspector-branch-list > div:hover,
31606
+ .vr-inspector-changelog button:hover {
31607
+ border-color: rgba(168, 85, 247, 0.32);
31608
+ background: rgba(124, 58, 237, 0.055);
31609
+ }
31610
+
31611
+ .vr-inspector-provider-row span,
31612
+ .vr-inspector-release-list span,
31613
+ .vr-inspector-branch-list span {
31614
+ min-width: 0;
31615
+ }
31616
+
31617
+ .vr-inspector-provider-row strong,
31618
+ .vr-inspector-provider-row em,
31619
+ .vr-inspector-provider-row small,
31620
+ .vr-inspector-release-list strong,
31621
+ .vr-inspector-release-list em,
31622
+ .vr-inspector-release-list small,
31623
+ .vr-inspector-branch-list strong,
31624
+ .vr-inspector-branch-list em,
31625
+ .vr-inspector-changelog strong,
31626
+ .vr-inspector-changelog span,
31627
+ .vr-inspector-changelog em {
31628
+ display: block;
31629
+ min-width: 0;
31630
+ overflow: hidden;
31631
+ text-overflow: ellipsis;
31632
+ white-space: nowrap;
31633
+ }
31634
+
31635
+ .vr-inspector-provider-row small {
31636
+ color: #a78bfa;
31637
+ font-size: 10px;
31638
+ font-weight: 760;
31639
+ }
31640
+
31641
+ .vr-inspector-provider-row strong,
31642
+ .vr-inspector-release-list strong,
31643
+ .vr-inspector-branch-list strong {
31644
+ font-size: 13px;
31645
+ }
31646
+
31647
+ .vr-inspector-provider-row em,
31648
+ .vr-inspector-release-list em,
31649
+ .vr-inspector-release-list small,
31650
+ .vr-inspector-branch-list em,
31651
+ .vr-inspector-changelog em {
31652
+ color: var(--vr-muted);
31653
+ font-size: 11px;
31654
+ font-style: normal;
31655
+ }
31656
+
31657
+ .vr-inspector-section {
31658
+ display: grid;
31659
+ gap: 8px;
31660
+ border: 1px solid rgba(148, 163, 184, 0.12);
31661
+ border-radius: 13px;
31662
+ background: rgba(255, 255, 255, 0.018);
31663
+ padding: 10px;
31664
+ }
31665
+
31666
+ .vr-inspector-section > header {
31667
+ display: flex;
31668
+ align-items: center;
31669
+ justify-content: space-between;
31670
+ gap: 10px;
31671
+ }
31672
+
31673
+ .vr-inspector-section > header strong {
31674
+ font-size: 12px;
31675
+ }
31676
+
31677
+ .vr-inspector-section > header button,
31678
+ .vr-inspector-footer button,
31679
+ .vr-inspector-branch-list button {
31680
+ min-height: 30px;
31681
+ border: 1px solid rgba(148, 163, 184, 0.16);
31682
+ border-radius: 9px;
31683
+ background: rgba(255, 255, 255, 0.03);
31684
+ color: #f4f4f5;
31685
+ padding: 0 10px;
31686
+ font-size: 11.5px;
31687
+ font-weight: 650;
31688
+ }
31689
+
31690
+ .vr-inspector-release-list button {
31691
+ grid-template-columns: minmax(0, 1fr) auto;
31692
+ }
31693
+
31694
+ .vr-inspector-release-list button.is-selected {
31695
+ border-color: rgba(168, 85, 247, 0.48);
31696
+ background: rgba(124, 58, 237, 0.1);
31697
+ }
31698
+
31699
+ .vr-inspector-compare {
31700
+ min-height: 58px;
31701
+ display: grid;
31702
+ grid-template-columns: 28px minmax(0, 1fr);
31703
+ grid-template-rows: auto auto;
31704
+ align-items: center;
31705
+ gap: 0 10px;
31706
+ border: 1px solid rgba(168, 85, 247, 0.42);
31707
+ border-radius: 13px;
31708
+ background: rgba(124, 58, 237, 0.095);
31709
+ color: #f4f4f5;
31710
+ padding: 10px 13px;
31711
+ text-align: left;
31712
+ }
31713
+
31714
+ .vr-inspector-compare i {
31715
+ grid-row: 1 / span 2;
31716
+ }
31717
+
31718
+ .vr-inspector-compare span {
31719
+ color: #c4b5fd;
31720
+ font-size: 12px;
31721
+ font-weight: 760;
31722
+ }
31723
+
31724
+ .vr-inspector-compare strong {
31725
+ min-width: 0;
31726
+ overflow: hidden;
31727
+ text-overflow: ellipsis;
31728
+ white-space: nowrap;
31729
+ font-size: 13px;
31730
+ }
31731
+
31732
+ .vr-inspector-changelog {
31733
+ max-height: 320px;
31734
+ overflow: auto;
31735
+ padding-right: 2px;
31736
+ scrollbar-width: thin;
31737
+ }
31738
+
31739
+ .vr-inspector-changelog button {
31740
+ grid-template-columns: 74px minmax(0, 1fr);
31741
+ grid-template-rows: auto auto;
31742
+ }
31743
+
31744
+ .vr-inspector-changelog em {
31745
+ grid-column: 2;
31746
+ }
31747
+
31748
+ .vr-inspector-branch-list > div {
31749
+ grid-template-columns: minmax(0, 1fr) auto;
31750
+ }
31751
+
31752
+ .vr-inspector-branch-list > div.is-current {
31753
+ border-color: rgba(34, 197, 94, 0.3);
31754
+ }
31755
+
31756
+ .vr-inspector-branch-list > div > div {
31757
+ display: inline-flex;
31758
+ gap: 6px;
31759
+ }
31760
+
31761
+ .vr-inspector-warning {
31762
+ display: grid;
31763
+ grid-template-columns: 10px minmax(0, 1fr) auto;
31764
+ align-items: center;
31765
+ gap: 10px;
31766
+ border: 1px solid rgba(249, 115, 22, 0.32);
31767
+ border-radius: 12px;
31768
+ background: rgba(249, 115, 22, 0.07);
31769
+ padding: 10px 12px;
31770
+ }
31771
+
31772
+ .vr-inspector-warning > i {
31773
+ width: 8px;
31774
+ height: 8px;
31775
+ border-radius: 999px;
31776
+ background: var(--vr-orange);
31777
+ }
31778
+
31779
+ .vr-inspector-warning strong,
31780
+ .vr-inspector-warning em {
31781
+ display: block;
31782
+ }
31783
+
31784
+ .vr-inspector-warning em {
31785
+ color: var(--vr-muted);
31786
+ font-size: 11px;
31787
+ font-style: normal;
31788
+ }
31789
+
31790
+ .vr-inspector-footer {
31791
+ display: grid;
31792
+ grid-template-columns: repeat(2, minmax(0, 1fr));
31793
+ gap: 8px;
31794
+ }
31795
+
31796
+ .vr-inspector-footer button {
31797
+ display: inline-flex;
31798
+ align-items: center;
31799
+ justify-content: center;
31800
+ gap: 8px;
31801
+ }
31802
+
31803
+ .vr-inspector-empty {
31804
+ margin: 0;
31805
+ color: var(--vr-muted);
31806
+ font-size: 12px;
31807
+ line-height: 1.45;
31808
+ }
31809
+
31810
+ @media (max-width: 1180px) {
31811
+ .vr-composition-body,
31812
+ .vr-composition-body.has-inspector {
31813
+ grid-template-columns: 1fr;
31814
+ grid-template-areas:
31815
+ "main"
31816
+ "inspector"
31817
+ "left";
31818
+ }
31819
+ .vr-left-context-rail {
31820
+ grid-area: left;
31821
+ grid-template-columns: 1fr;
31822
+ grid-template-rows: auto minmax(220px, 360px);
31823
+ }
31824
+ .vr-inspector-panel {
31825
+ grid-area: inspector;
31826
+ height: min(560px, 72dvh);
31827
+ }
31828
+ }
31829
+
31830
+ @media (max-width: 760px) {
31831
+ .vr-composed-shell {
31832
+ grid-template-rows: auto minmax(0, 1fr);
31833
+ }
31834
+ .vr-main-canvas {
31835
+ height: 72dvh;
31836
+ min-height: 560px;
31837
+ }
31838
+ .vr-studio-head-actions {
31839
+ gap: 6px;
31840
+ }
31841
+ .vr-studio-tabs button {
31842
+ padding: 0 10px;
31843
+ }
31844
+ .vr-studio-chat:not(.is-split) .vr-chat-command-bar {
31845
+ padding: 8px;
31846
+ }
31847
+ .vr-studio-chat:not(.is-split) .vr-chat-command-bar > .vr-chat-composer {
31848
+ min-height: 112px;
31849
+ }
31850
+ }
31851
+
31852
+ /* --- Premium composer surface --- */
31853
+ .vr-chat-command-bar {
31854
+ border-top: 0;
31855
+ background: linear-gradient(180deg, rgba(10, 12, 17, 0), rgba(10, 12, 17, 0.86) 24%);
31856
+ }
31857
+
31858
+ .vr-chat-command-bar > .vr-chat-composer {
31859
+ position: relative;
31860
+ min-height: 182px;
31861
+ display: grid;
31862
+ grid-template-columns: minmax(0, 1fr);
31863
+ grid-template-rows: auto minmax(58px, 1fr) auto auto auto;
31864
+ gap: 14px;
31865
+ align-items: stretch;
31866
+ overflow: visible;
31867
+ border: 1px solid rgba(168, 85, 247, 0.66);
31868
+ border-radius: 22px;
31869
+ background:
31870
+ radial-gradient(circle at 94% 84%, rgba(168, 85, 247, 0.24), transparent 110px),
31871
+ radial-gradient(circle at 12% 0%, rgba(124, 58, 237, 0.16), transparent 210px),
31872
+ linear-gradient(180deg, rgba(22, 25, 35, 0.96), rgba(13, 16, 24, 0.98));
31873
+ box-shadow:
31874
+ inset 0 1px 0 rgba(255, 255, 255, 0.04),
31875
+ inset 0 0 0 1px rgba(255, 255, 255, 0.025),
31876
+ 0 0 0 1px rgba(124, 58, 237, 0.1),
31877
+ 0 18px 60px rgba(0, 0, 0, 0.38);
31878
+ padding: 18px 20px;
31879
+ }
31880
+
31881
+ .vr-chat-command-bar > .vr-chat-composer::before {
31882
+ content: "";
31883
+ position: absolute;
31884
+ left: 24px;
31885
+ right: 24px;
31886
+ top: 70px;
31887
+ height: 1px;
31888
+ background: linear-gradient(90deg, transparent, rgba(148, 163, 184, 0.18), transparent);
31889
+ pointer-events: none;
31890
+ }
31891
+
31892
+ .vr-composer-top,
31893
+ .vr-composer-bottom,
31894
+ .vr-composer-controls {
31895
+ min-width: 0;
31896
+ display: flex;
31897
+ align-items: center;
31898
+ }
31899
+
31900
+ .vr-composer-top {
31901
+ justify-content: flex-start;
31902
+ }
31903
+
31904
+ .vr-composer-scope-wrap {
31905
+ position: relative;
31906
+ display: inline-flex;
31907
+ align-items: center;
31908
+ }
31909
+
31910
+ .vr-composer-scope {
31911
+ height: 42px;
31912
+ display: inline-flex;
31913
+ align-items: center;
31914
+ gap: 10px;
31915
+ border: 1px solid rgba(168, 85, 247, 0.32);
31916
+ border-radius: 10px;
31917
+ background: rgba(124, 58, 237, 0.11);
31918
+ color: #f8fafc;
31919
+ padding: 0 13px;
31920
+ font-size: 13px;
31921
+ font-weight: 740;
31922
+ transition: border-color 0.14s ease, background 0.14s ease, transform 0.14s ease;
31923
+ }
31924
+
31925
+ .vr-composer-scope:hover {
31926
+ border-color: rgba(196, 181, 253, 0.52);
31927
+ background: rgba(124, 58, 237, 0.16);
31928
+ transform: translateY(-1px);
31929
+ }
31930
+
31931
+ .vr-composer-scope i[data-icon] {
31932
+ width: 18px;
31933
+ height: 18px;
31934
+ color: #c4b5fd;
31935
+ }
31936
+
31937
+ .vr-composer-scope i[data-icon] svg {
31938
+ width: 18px;
31939
+ height: 18px;
31940
+ }
31941
+
31942
+ .vr-composer-scope > i:not([data-icon]) {
31943
+ width: 8px;
31944
+ height: 8px;
31945
+ border-right: 1.5px solid #9ca3af;
31946
+ border-bottom: 1.5px solid #9ca3af;
31947
+ transform: rotate(45deg) translateY(-2px);
31948
+ margin-left: 4px;
31949
+ }
31950
+
31951
+ .vr-scope-menu {
31952
+ position: absolute;
31953
+ left: 0;
31954
+ bottom: calc(100% + 8px);
31955
+ z-index: 22;
31956
+ width: 212px;
31957
+ display: grid;
31958
+ gap: 3px;
31959
+ border: 1px solid rgba(148, 163, 184, 0.16);
31960
+ border-radius: 12px;
31961
+ background: rgba(16, 18, 24, 0.98);
31962
+ box-shadow: 0 18px 48px rgba(0, 0, 0, 0.44);
31963
+ padding: 8px;
31964
+ }
31965
+
31966
+ .vr-scope-menu p {
31967
+ margin: 0 0 4px;
31968
+ padding: 0 4px;
31969
+ color: #9ca3af;
31970
+ font-size: 11px;
31971
+ font-weight: 720;
31972
+ }
31973
+
31974
+ .vr-scope-menu button {
31975
+ min-height: 36px;
31976
+ display: grid;
31977
+ grid-template-columns: 18px minmax(0, 1fr) 14px;
31978
+ align-items: center;
31979
+ gap: 9px;
31980
+ border: 0;
31981
+ border-radius: 9px;
31982
+ background: transparent;
31983
+ color: #e5e7eb;
31984
+ padding: 0 9px;
31985
+ text-align: left;
31986
+ }
31987
+
31988
+ .vr-scope-menu button:hover {
31989
+ background: rgba(255, 255, 255, 0.055);
31990
+ }
31991
+
31992
+ .vr-scope-menu button i[data-icon],
31993
+ .vr-scope-menu button svg {
31994
+ width: 15px;
31995
+ height: 15px;
31996
+ color: #c4b5fd;
31997
+ }
31998
+
31999
+ .vr-scope-menu button b {
32000
+ width: 8px;
32001
+ height: 14px;
32002
+ border: solid #d8b4fe;
32003
+ border-width: 0 2px 2px 0;
32004
+ transform: rotate(45deg);
32005
+ }
32006
+
32007
+ .vr-chat-command-bar .vr-chat-input {
32008
+ grid-column: 1;
32009
+ grid-row: 2;
32010
+ min-height: 64px;
32011
+ padding: 0 4px;
32012
+ color: #f8fafc;
32013
+ font-size: 16px;
32014
+ font-weight: 500;
32015
+ line-height: 1.55;
32016
+ }
32017
+
32018
+ .vr-chat-command-bar .vr-chat-input::placeholder {
32019
+ color: #9ca3af;
32020
+ }
32021
+
32022
+ .vr-composer-bottom {
32023
+ grid-column: 1;
32024
+ grid-row: 5;
32025
+ align-self: end;
32026
+ justify-content: space-between;
32027
+ gap: 14px;
32028
+ }
32029
+
32030
+ .vr-chat-command-bar > .vr-chat-composer > .vr-provider-drop-zone {
32031
+ grid-row: 4;
32032
+ grid-column: 1;
32033
+ align-self: start;
32034
+ width: 100%;
32035
+ max-width: 100%;
32036
+ display: flex;
32037
+ flex-wrap: nowrap;
32038
+ gap: 8px;
32039
+ overflow: hidden;
32040
+ }
32041
+
32042
+ .vr-chat-command-bar > .vr-chat-composer > .vr-provider-drop-zone:not(.has-provider):not(.is-active) {
32043
+ display: none;
32044
+ min-height: 0;
32045
+ }
32046
+
32047
+ .vr-chat-command-bar > .vr-chat-composer > .vr-provider-drop-zone.has-provider {
32048
+ min-height: 34px;
32049
+ }
32050
+
32051
+ .vr-chat-command-bar > .vr-chat-composer > .vr-provider-drop-zone .vr-context-chip {
32052
+ flex: 0 1 auto;
32053
+ max-width: min(240px, 48%);
32054
+ }
32055
+
32056
+ .vr-chat-inline-actions {
32057
+ position: relative;
32058
+ display: inline-flex;
32059
+ align-items: center;
32060
+ gap: 8px;
32061
+ overflow: visible;
32062
+ }
32063
+
32064
+ .vr-chat-command-trigger {
32065
+ position: relative;
32066
+ display: inline-flex;
32067
+ align-items: center;
32068
+ overflow: visible;
32069
+ }
32070
+
32071
+ .vr-chat-inline-actions > button,
32072
+ .vr-chat-command-trigger > button {
32073
+ height: 40px;
32074
+ display: inline-flex;
32075
+ align-items: center;
32076
+ gap: 9px;
32077
+ border: 1px solid rgba(148, 163, 184, 0.14);
32078
+ border-radius: 10px;
32079
+ background: rgba(12, 15, 22, 0.62);
32080
+ color: #cbd5e1;
32081
+ padding: 0 13px;
32082
+ font-size: 13px;
32083
+ font-weight: 680;
32084
+ }
32085
+
32086
+ .vr-chat-inline-actions > button:hover,
32087
+ .vr-chat-command-trigger > button:hover {
32088
+ border-color: rgba(168, 85, 247, 0.32);
32089
+ background: rgba(124, 58, 237, 0.09);
32090
+ color: #f8fafc;
32091
+ }
32092
+
32093
+ .vr-chat-inline-actions > button i[data-icon],
32094
+ .vr-chat-inline-actions > button svg,
32095
+ .vr-chat-command-trigger > button i[data-icon],
32096
+ .vr-chat-command-trigger > button svg {
32097
+ width: 16px;
32098
+ height: 16px;
32099
+ }
32100
+
32101
+ .vr-chat-command-popover {
32102
+ position: absolute;
32103
+ right: -12px;
32104
+ bottom: calc(100% + 8px);
32105
+ z-index: 8;
32106
+ width: min(292px, 78vw);
32107
+ display: grid;
32108
+ gap: 4px;
32109
+ border: 1px solid rgba(148, 163, 184, 0.16);
32110
+ border-radius: 12px;
32111
+ background: rgba(14, 17, 24, 0.98);
32112
+ box-shadow: 0 18px 52px rgba(0, 0, 0, 0.46);
32113
+ padding: 8px;
32114
+ }
32115
+
32116
+ .vr-chat-command-popover button {
32117
+ min-height: 34px;
32118
+ display: grid;
32119
+ grid-template-columns: 16px minmax(0, 1fr);
32120
+ align-items: center;
32121
+ gap: 9px;
32122
+ border: 1px solid transparent;
32123
+ border-radius: 8px;
32124
+ background: transparent;
32125
+ color: #d1d5db;
32126
+ padding: 0 10px;
32127
+ text-align: left;
32128
+ font-size: 12.5px;
32129
+ font-weight: 650;
32130
+ }
32131
+
32132
+ .vr-chat-command-popover button.is-primary {
32133
+ border-color: transparent;
32134
+ background: transparent;
32135
+ color: #f3e8ff;
32136
+ }
32137
+
32138
+ .vr-chat-command-popover button.is-muted {
32139
+ color: #9ca3af;
32140
+ }
32141
+
32142
+ .vr-chat-command-popover button:hover {
32143
+ border-color: rgba(148, 163, 184, 0.16);
32144
+ background: rgba(255, 255, 255, 0.04);
32145
+ }
32146
+
32147
+ .vr-context-tray {
32148
+ grid-row: 3;
32149
+ display: grid;
32150
+ grid-template-columns: repeat(2, minmax(0, 1fr));
32151
+ gap: 10px;
32152
+ border: 1px solid rgba(148, 163, 184, 0.15);
32153
+ border-radius: 14px;
32154
+ background: rgba(12, 15, 22, 0.78);
32155
+ padding: 10px;
32156
+ }
32157
+
32158
+ .vr-context-tray header {
32159
+ grid-column: 1 / -1;
32160
+ display: flex;
32161
+ align-items: center;
32162
+ justify-content: space-between;
32163
+ gap: 10px;
32164
+ }
32165
+
32166
+ .vr-context-tray header strong {
32167
+ color: #f8fafc;
32168
+ font-size: 13px;
32169
+ }
32170
+
32171
+ .vr-context-tray header button {
32172
+ width: 28px;
32173
+ height: 28px;
32174
+ display: grid;
32175
+ place-items: center;
32176
+ border: 1px solid rgba(148, 163, 184, 0.14);
32177
+ border-radius: 8px;
32178
+ background: transparent;
32179
+ color: #9ca3af;
32180
+ }
32181
+
32182
+ .vr-context-tray section {
32183
+ min-width: 0;
32184
+ display: grid;
32185
+ gap: 7px;
32186
+ }
32187
+
32188
+ .vr-context-tray section p {
32189
+ margin: 0;
32190
+ color: #9ca3af;
32191
+ font-size: 11px;
32192
+ font-weight: 720;
32193
+ }
32194
+
32195
+ .vr-context-tray section > div {
32196
+ display: grid;
32197
+ grid-template-columns: repeat(2, minmax(0, 1fr));
32198
+ gap: 7px;
32199
+ }
32200
+
32201
+ .vr-context-tray section button {
32202
+ min-width: 0;
32203
+ min-height: 40px;
32204
+ display: grid;
32205
+ grid-template-columns: 24px minmax(0, 1fr);
32206
+ grid-template-rows: auto auto;
32207
+ align-items: center;
32208
+ gap: 0 8px;
32209
+ border: 1px solid rgba(148, 163, 184, 0.13);
32210
+ border-radius: 10px;
32211
+ background: rgba(255, 255, 255, 0.025);
32212
+ color: #e5e7eb;
32213
+ padding: 8px 9px;
32214
+ text-align: left;
32215
+ }
32216
+
32217
+ .vr-context-tray section button:hover {
32218
+ border-color: rgba(168, 85, 247, 0.36);
32219
+ background: rgba(124, 58, 237, 0.08);
32220
+ }
32221
+
32222
+ .vr-context-tray section button span {
32223
+ grid-row: 1 / 3;
32224
+ display: grid;
32225
+ place-items: center;
32226
+ }
32227
+
32228
+ .vr-context-tray section button span img,
32229
+ .vr-context-tray section button span svg {
32230
+ width: 18px;
32231
+ height: 18px;
32232
+ }
32233
+
32234
+ .vr-context-tray section button strong,
32235
+ .vr-context-tray section button em {
32236
+ min-width: 0;
32237
+ overflow: hidden;
32238
+ text-overflow: ellipsis;
32239
+ white-space: nowrap;
32240
+ }
32241
+
32242
+ .vr-context-tray section button strong {
32243
+ font-size: 12px;
32244
+ }
32245
+
32246
+ .vr-context-tray section button em {
32247
+ color: #9ca3af;
32248
+ font-size: 10.5px;
32249
+ font-style: normal;
32250
+ }
32251
+
32252
+ .vr-context-tray-empty {
32253
+ color: #9ca3af;
32254
+ font-size: 12px;
32255
+ }
32256
+
32257
+ .vr-composer-controls {
32258
+ justify-content: flex-end;
32259
+ gap: 10px;
32260
+ }
32261
+
32262
+ .vr-composer-controls .vr-provider-drop-zone {
32263
+ max-width: 300px;
32264
+ }
32265
+
32266
+ .vr-composer-controls .vr-provider-drop-zone:not(.has-provider):not(.is-active) {
32267
+ position: absolute;
32268
+ width: 1px;
32269
+ height: 1px;
32270
+ overflow: hidden;
32271
+ clip: rect(0 0 0 0);
32272
+ }
32273
+
32274
+ .vr-composer-controls .vr-provider-drop-zone > .vr-provider-drop-label {
32275
+ border-radius: 12px;
32276
+ }
32277
+
32278
+ .vr-composer-controls .vr-model-picker {
32279
+ position: relative;
32280
+ display: flex;
32281
+ align-items: center;
32282
+ gap: 0;
32283
+ border: 1px solid rgba(148, 163, 184, 0.13);
32284
+ border-radius: 14px;
32285
+ background: rgba(15, 18, 27, 0.74);
32286
+ overflow: visible;
32287
+ }
32288
+
32289
+ .vr-composer-controls .vr-model-picker > button {
32290
+ height: 46px;
32291
+ min-width: 0;
32292
+ border: 0;
32293
+ border-radius: 0;
32294
+ background: transparent;
32295
+ color: #d1d5db;
32296
+ padding: 0 13px;
32297
+ }
32298
+
32299
+ .vr-composer-controls .vr-model-picker > button + button {
32300
+ border-left: 1px solid rgba(148, 163, 184, 0.1);
32301
+ }
32302
+
32303
+ .vr-composer-controls .vr-model-picker > button span {
32304
+ display: none;
32305
+ }
32306
+
32307
+ .vr-composer-controls .vr-model-picker > button strong {
32308
+ max-width: 150px;
32309
+ color: #e5e7eb;
32310
+ font-size: 12.5px;
32311
+ font-weight: 650;
32312
+ }
32313
+
32314
+ .vr-composer-controls .vr-model-picker > button:first-child,
32315
+ .vr-composer-controls .vr-model-picker > button:nth-child(3) {
32316
+ display: none;
32317
+ }
32318
+
32319
+ .vr-composer-controls .vr-model-picker > button:nth-child(2) {
32320
+ min-width: 132px;
32321
+ }
32322
+
32323
+ .vr-composer-controls .vr-model-picker > button:nth-child(4) {
32324
+ max-width: 128px;
32325
+ }
32326
+
32327
+ .vr-composer-controls .vr-model-picker > button:nth-child(4) strong {
32328
+ max-width: 92px;
32329
+ }
32330
+
32331
+ .vr-composer-controls .vr-model-picker > button i {
32332
+ margin-left: 0;
32333
+ }
32334
+
32335
+ .vr-composer-controls .vr-model-menu {
32336
+ bottom: 54px;
32337
+ right: 0;
32338
+ }
32339
+
32340
+ .vr-composer-controls .vr-chat-send {
32341
+ flex: 0 0 46px;
32342
+ width: 46px;
32343
+ height: 46px;
32344
+ display: grid;
32345
+ place-items: center;
32346
+ border: 1px solid rgba(216, 180, 254, 0.48);
32347
+ border-radius: 12px;
32348
+ background: linear-gradient(135deg, #9f4df6, #7c3aed);
32349
+ color: #f8fafc;
32350
+ box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.12), 0 12px 28px rgba(0, 0, 0, 0.34);
32351
+ }
32352
+
32353
+ .vr-composer-controls .vr-chat-send:hover {
32354
+ transform: translateY(-1px);
32355
+ box-shadow: 0 0 0 5px rgba(124, 58, 237, 0.16), 0 16px 32px rgba(0, 0, 0, 0.38);
32356
+ }
32357
+
32358
+ .vr-composer-controls .vr-chat-send.is-stop {
32359
+ border-color: rgba(248, 113, 113, 0.44);
32360
+ background: rgba(239, 68, 68, 0.16);
32361
+ color: #fecaca;
32362
+ box-shadow: none;
32363
+ }
32364
+
32365
+ .vr-composer-controls .vr-chat-send svg {
32366
+ width: 19px;
32367
+ height: 19px;
32368
+ stroke-width: 2.2;
32369
+ }
32370
+
32371
+ .vr-composer-controls .vr-chat-send.is-stop svg {
32372
+ width: 17px;
32373
+ height: 17px;
32374
+ }
32375
+
32376
+ /* --- Compact chat chrome: keep the cockpit full-height without stealing transcript space. --- */
32377
+ .vr-composed-shell {
32378
+ grid-template-rows: 42px minmax(0, 1fr);
32379
+ }
32380
+
32381
+ .vr-studio-topbar {
32382
+ min-height: 42px;
32383
+ padding: 0 8px;
32384
+ }
32385
+
32386
+ .vr-topbar-brand {
32387
+ gap: 7px;
32388
+ }
32389
+
32390
+ .vr-topbar-brand span {
32391
+ width: 26px;
32392
+ height: 26px;
32393
+ }
32394
+
32395
+ .vr-topbar-brand strong {
32396
+ font-size: 18px;
32397
+ }
32398
+
32399
+ .vr-left-context-rail {
32400
+ gap: 8px;
32401
+ }
32402
+
32403
+ .vr-rail-launchers {
32404
+ gap: 4px;
32405
+ padding: 6px;
32406
+ }
32407
+
32408
+ .vr-rail-launcher {
32409
+ min-height: 38px;
32410
+ grid-template-columns: 24px minmax(0, 1fr) 8px;
32411
+ gap: 8px;
32412
+ padding: 5px 6px;
32413
+ }
32414
+
32415
+ .vr-rail-launcher i[data-icon] {
32416
+ width: 22px;
32417
+ height: 22px;
32418
+ border-radius: 7px;
32419
+ }
32420
+
32421
+ .vr-rail-launcher strong {
32422
+ font-size: 12px;
32423
+ }
32424
+
32425
+ .vr-rail-launcher em {
32426
+ font-size: 10.5px;
32427
+ }
32428
+
32429
+ .vr-recent-rail {
32430
+ padding: 8px;
32431
+ }
32432
+
32433
+ .vr-new-chat-button {
32434
+ min-height: 38px;
32435
+ }
32436
+
32437
+ .vr-recent-chat {
32438
+ min-height: 46px;
32439
+ padding: 8px;
32440
+ }
32441
+
32442
+ .vr-composition-body,
32443
+ .vr-composition-body.has-inspector {
32444
+ padding: 8px;
32445
+ gap: 8px;
32446
+ }
32447
+
32448
+ .vr-main-canvas {
32449
+ padding: 6px;
32450
+ }
32451
+
32452
+ .vr-studio-head {
32453
+ min-height: 34px;
32454
+ padding: 2px 2px 0;
32455
+ }
32456
+
32457
+ .vr-studio-head h1 {
32458
+ font-size: 17px;
32459
+ }
32460
+
32461
+ .vr-studio-tabs button,
32462
+ .vr-studio-head-actions > button {
32463
+ min-height: 32px;
32464
+ }
32465
+
32466
+ .vr-cli-panel {
32467
+ min-height: 42px;
32468
+ padding: 6px;
32469
+ }
32470
+
32471
+ .vr-studio-chat:not(.is-split) .vr-chat-transcript {
32472
+ padding: clamp(12px, 2vh, 22px) clamp(20px, 4vw, 64px) 16px;
32473
+ }
32474
+
32475
+ .vr-chat-intro-message {
32476
+ margin-top: 0;
32477
+ }
32478
+
32479
+ .vr-env-connect-card {
32480
+ margin-top: 18px;
32481
+ }
32482
+
32483
+ .vr-studio-chat:not(.is-split) .vr-chat-command-bar {
32484
+ padding: 6px clamp(18px, 4vw, 62px) 8px;
32485
+ }
32486
+
32487
+ .vr-studio-chat:not(.is-split) .vr-chat-command-bar > .vr-chat-composer,
32488
+ .vr-chat-command-bar > .vr-chat-composer {
32489
+ min-height: 132px;
32490
+ grid-template-rows: auto minmax(38px, 1fr) auto auto auto;
32491
+ gap: 9px;
32492
+ border-radius: 16px;
32493
+ padding: 12px 14px;
32494
+ }
32495
+
32496
+ .vr-chat-command-bar > .vr-chat-composer::before {
32497
+ left: 18px;
32498
+ right: 18px;
32499
+ top: 54px;
32500
+ }
32501
+
32502
+ .vr-composer-scope {
32503
+ height: 34px;
32504
+ gap: 8px;
32505
+ padding: 0 10px;
32506
+ font-size: 12.5px;
32507
+ }
32508
+
32509
+ .vr-composer-scope i[data-icon],
32510
+ .vr-composer-scope i[data-icon] svg {
32511
+ width: 15px;
32512
+ height: 15px;
32513
+ }
32514
+
32515
+ .vr-chat-command-bar .vr-chat-input {
32516
+ min-height: 42px;
32517
+ font-size: 14.5px;
32518
+ line-height: 1.42;
32519
+ }
32520
+
32521
+ .vr-chat-inline-actions {
32522
+ gap: 6px;
32523
+ }
32524
+
32525
+ .vr-chat-inline-actions > button,
32526
+ .vr-chat-command-trigger > button {
32527
+ height: 34px;
32528
+ gap: 7px;
32529
+ border-radius: 9px;
32530
+ padding: 0 10px;
32531
+ font-size: 12.5px;
32532
+ }
32533
+
32534
+ .vr-chat-inline-actions > button i[data-icon],
32535
+ .vr-chat-inline-actions > button svg,
32536
+ .vr-chat-command-trigger > button i[data-icon],
32537
+ .vr-chat-command-trigger > button svg {
32538
+ width: 14px;
32539
+ height: 14px;
32540
+ }
32541
+
32542
+ .vr-composer-controls {
32543
+ gap: 8px;
32544
+ }
32545
+
32546
+ .vr-composer-controls .vr-model-picker {
32547
+ border-radius: 12px;
32548
+ }
32549
+
32550
+ .vr-composer-controls .vr-model-picker > button {
32551
+ height: 38px;
32552
+ padding: 0 11px;
32553
+ }
32554
+
32555
+ .vr-composer-controls .vr-model-picker > button:nth-child(2) {
32556
+ min-width: 116px;
32557
+ }
32558
+
32559
+ .vr-composer-controls .vr-model-picker > button:nth-child(4) {
32560
+ max-width: 150px;
32561
+ }
32562
+
32563
+ .vr-composer-controls .vr-model-picker > button:nth-child(4) strong {
32564
+ max-width: 120px;
32565
+ }
32566
+
32567
+ .vr-composer-controls .vr-chat-send {
32568
+ flex-basis: 40px;
32569
+ width: 40px;
32570
+ height: 40px;
32571
+ border-radius: 11px;
32572
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.12), 0 10px 24px rgba(0, 0, 0, 0.32);
32573
+ }
32574
+
32575
+ .vr-composer-controls .vr-chat-send svg {
32576
+ width: 17px;
32577
+ height: 17px;
32578
+ }
32579
+
32580
+ /* --- Density and transcript repair pass --- */
32581
+ .vr-composed-shell {
32582
+ grid-template-rows: 38px minmax(0, 1fr);
32583
+ }
32584
+
32585
+ .vr-studio-topbar {
32586
+ min-height: 38px;
32587
+ padding: 0 6px;
32588
+ }
32589
+
32590
+ .vr-topbar-brand span {
32591
+ width: 22px;
32592
+ height: 22px;
32593
+ }
32594
+
32595
+ .vr-topbar-brand strong {
32596
+ font-size: 16px;
32597
+ }
32598
+
32599
+ .vr-composition-body,
32600
+ .vr-composition-body.has-inspector {
32601
+ padding: 6px;
32602
+ gap: 6px;
32603
+ }
32604
+
32605
+ .vr-main-canvas {
32606
+ padding: 4px;
32607
+ }
32608
+
32609
+ .vr-studio-head {
32610
+ min-height: 30px;
32611
+ padding: 0;
32612
+ }
32613
+
32614
+ .vr-studio-head h1 {
32615
+ font-size: 16px;
32616
+ }
32617
+
32618
+ .vr-studio-tabs button,
32619
+ .vr-studio-head-actions > button {
32620
+ min-height: 30px;
32621
+ padding-inline: 10px;
32622
+ }
32623
+
32624
+ .vr-cli-panel {
32625
+ min-height: 36px;
32626
+ padding: 5px;
32627
+ }
32628
+
32629
+ .vr-studio-chat:not(.is-split) .vr-chat-transcript {
32630
+ gap: 10px;
32631
+ padding: 10px clamp(18px, 4vw, 54px) 12px;
32632
+ }
32633
+
32634
+ .vr-story-node {
32635
+ column-gap: 12px;
32636
+ }
32637
+
32638
+ .vr-story-dot {
32639
+ width: 24px;
32640
+ height: 24px;
32641
+ }
32642
+
32643
+ .vr-story-node.is-user .vr-chat-message.is-user {
32644
+ min-height: 66px;
32645
+ padding: 12px 16px 12px 56px;
32646
+ border-color: rgba(124, 58, 237, 0.28);
32647
+ border-radius: 13px;
32648
+ background:
32649
+ radial-gradient(circle at 96% 16%, rgba(124, 58, 237, 0.08), transparent 140px),
32650
+ rgba(16, 18, 27, 0.88);
32651
+ }
32652
+
32653
+ .vr-story-node.is-user .vr-chat-message.is-user::after {
32654
+ left: 20px;
32655
+ top: 22px;
32656
+ width: 16px;
32657
+ height: 16px;
32658
+ border-color: rgba(168, 85, 247, 0.55);
32659
+ border-radius: 999px;
32660
+ background: radial-gradient(circle at 50% 50%, #a78bfa 0 3px, rgba(124, 58, 237, 0.18) 4px 100%);
32661
+ box-shadow: 0 0 16px rgba(124, 58, 237, 0.2);
32662
+ }
32663
+
32664
+ .vr-story-node.is-user .vr-chat-message.is-user::before {
32665
+ margin-bottom: 6px;
32666
+ font-size: 10px;
32667
+ }
32668
+
32669
+ .vr-story-node.is-user .vr-chat-message.is-user > p {
32670
+ font-size: 15px;
32671
+ font-weight: 720;
32672
+ }
32673
+
32674
+ .vr-chat-agent-response {
32675
+ width: min(820px, 100%);
32676
+ padding: 12px 14px;
32677
+ border-radius: 13px;
32678
+ }
32679
+
32680
+ .vr-chat-agent-response > div:first-child {
32681
+ gap: 9px;
32682
+ padding-bottom: 7px;
30074
32683
  }
30075
- .vr-modal-health-line {
30076
- flex-wrap: wrap;
30077
- align-items: center;
30078
- line-height: 1.4;
30079
- font-size: 12.5px;
32684
+
32685
+ .vr-chat-agent-response > div:first-child > span {
32686
+ width: 34px;
32687
+ height: 34px;
30080
32688
  }
30081
- .vr-modal-health-line .vr-modal-pill {
30082
- flex-shrink: 0;
32689
+
32690
+ .vr-chat-agent-response > div:first-child img {
32691
+ width: 43px;
32692
+ height: 43px;
32693
+ transform: translateY(6px);
30083
32694
  }
30084
- .vr-mcp-connect-btn {
30085
- border: 1px solid rgba(124, 58, 237, 0.5);
30086
- border-radius: 999px;
30087
- background: rgba(124, 58, 237, 0.1);
30088
- color: var(--vr-text);
30089
- font-size: 12px;
30090
- font-weight: 600;
30091
- padding: 6px 14px;
30092
- cursor: pointer;
32695
+
32696
+ .vr-chat-agent-response > div:first-child p strong {
32697
+ font-size: 15px;
30093
32698
  }
30094
32699
 
30095
- /* Quickstart */
30096
- .vr-qs-steps {
30097
- display: grid;
32700
+ .vr-chat-agent-response .vr-agent-response-meta {
32701
+ margin: 0 0 8px 43px;
30098
32702
  gap: 8px;
30099
- margin-top: 16px;
30100
32703
  }
30101
- .vr-qs-step {
30102
- display: grid;
30103
- grid-template-columns: 34px minmax(0, 1fr) auto;
30104
- align-items: center;
30105
- gap: 14px;
30106
- padding: 13px 16px;
30107
- border: 1px solid rgba(148, 163, 184, 0.14);
30108
- border-radius: 12px;
30109
- background: rgba(255, 255, 255, 0.02);
32704
+
32705
+ .vr-chat-agent-response .vr-agent-context-line,
32706
+ .vr-chat-agent-response .vr-agent-response-stack {
32707
+ margin-left: 43px;
30110
32708
  }
30111
- .vr-qs-step.is-done {
30112
- opacity: 0.72;
32709
+
32710
+ .vr-chat-agent-response .vr-agent-answer-body > p:first-child {
32711
+ font-size: 13.5px;
30113
32712
  }
30114
- .vr-qs-num {
30115
- display: inline-flex;
30116
- align-items: center;
30117
- justify-content: center;
30118
- width: 30px;
30119
- height: 30px;
30120
- border: 1px solid rgba(148, 163, 184, 0.3);
30121
- border-radius: 50%;
30122
- font-size: 13px;
30123
- font-weight: 700;
30124
- color: var(--vr-muted);
32713
+
32714
+ .vr-chat-mission-summary {
32715
+ width: min(720px, 100%);
32716
+ padding-left: 43px;
30125
32717
  }
30126
- .vr-qs-step.is-done .vr-qs-num {
30127
- border-color: rgba(34, 197, 94, 0.5);
30128
- color: var(--vr-green);
32718
+
32719
+ .vr-chat-mission-summary .vr-chat-blockers-card {
32720
+ width: 100%;
32721
+ display: grid;
32722
+ grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr)) !important;
32723
+ gap: 8px;
32724
+ overflow: hidden;
32725
+ padding: 12px;
32726
+ box-sizing: border-box;
30129
32727
  }
30130
- .vr-qs-num svg { width: 13px; height: 13px; }
30131
- .vr-qs-step strong { display: block; font-size: 14px; }
30132
- .vr-qs-step em { display: block; font-size: 12px; font-style: normal; color: var(--vr-muted); }
30133
- .vr-qs-step > b {
32728
+
32729
+ .vr-chat-blockers-card header {
32730
+ grid-column: 1 / -1;
32731
+ padding-bottom: 2px;
32732
+ }
32733
+
32734
+ .vr-chat-blockers-card header strong {
32735
+ font-size: 15px;
32736
+ }
32737
+
32738
+ .vr-chat-blockers-card header b {
32739
+ padding: 3px 8px;
30134
32740
  font-size: 11px;
30135
- font-weight: 650;
30136
- color: var(--vr-green);
30137
- border: 1px solid rgba(34, 197, 94, 0.4);
30138
- border-radius: 999px;
30139
- padding: 3px 11px;
30140
32741
  }
30141
- .vr-qs-step > button {
30142
- border: 1px solid rgba(124, 58, 237, 0.55);
30143
- border-radius: 999px;
30144
- background: rgba(124, 58, 237, 0.12);
30145
- color: var(--vr-text);
30146
- font-size: 12.5px;
30147
- font-weight: 650;
30148
- padding: 7px 16px;
30149
- cursor: pointer;
32742
+
32743
+ .vr-chat-mission-summary .vr-chat-blockers-card > span {
32744
+ min-height: 62px;
32745
+ grid-template-columns: 24px minmax(0, 1fr);
32746
+ gap: 8px;
32747
+ padding: 10px 10px 28px;
32748
+ box-sizing: border-box;
30150
32749
  }
30151
- .vr-qs-step > button:hover { background: rgba(124, 58, 237, 0.2); }
30152
- .vr-qs-foot {
30153
- display: flex;
30154
- align-items: center;
30155
- justify-content: space-between;
30156
- gap: 12px;
30157
- margin-top: 16px;
32750
+
32751
+ .vr-chat-blockers-card > span i {
32752
+ width: 22px;
32753
+ height: 22px;
32754
+ font-size: 10px;
30158
32755
  }
30159
- .vr-qs-foot button {
30160
- border: 0;
30161
- background: transparent;
30162
- color: var(--vr-muted);
32756
+
32757
+ .vr-chat-blockers-card > span em {
30163
32758
  font-size: 12px;
30164
- text-decoration: underline;
30165
- cursor: pointer;
32759
+ line-height: 1.28;
30166
32760
  }
30167
- .vr-qs-foot span { font-size: 12px; color: var(--vr-muted); }
30168
32761
 
30169
- /* --- Claude-style composer: one + button, actions on demand, air. --- */
30170
- .vr-chat-plus {
30171
- flex: 0 0 auto;
30172
- display: inline-flex;
30173
- align-items: center;
30174
- justify-content: center;
30175
- width: 34px;
30176
- height: 34px;
30177
- border: 1px solid rgba(148, 163, 184, 0.25);
30178
- border-radius: 50%;
30179
- background: rgba(255, 255, 255, 0.03);
30180
- color: var(--vr-muted);
30181
- cursor: pointer;
30182
- transition: border-color 0.15s ease, color 0.15s ease, transform 0.12s ease;
32762
+ .vr-chat-blockers-card > span small {
32763
+ margin-top: 4px;
32764
+ font-size: 11px;
32765
+ line-height: 1.3;
30183
32766
  }
30184
- .vr-chat-plus:hover {
30185
- border-color: rgba(124, 58, 237, 0.55);
30186
- color: var(--vr-text);
32767
+
32768
+ .vr-chat-blockers-card > span b {
32769
+ right: 10px;
32770
+ bottom: 8px;
32771
+ padding: 2px 7px;
32772
+ font-size: 10px;
30187
32773
  }
30188
- .vr-chat-plus.is-open {
30189
- border-color: rgba(124, 58, 237, 0.55);
30190
- color: var(--vr-text);
30191
- transform: rotate(0deg);
32774
+
32775
+ .vr-chat-command-bar > .vr-chat-composer,
32776
+ .vr-studio-chat:not(.is-split) .vr-chat-command-bar > .vr-chat-composer {
32777
+ min-height: 118px;
32778
+ padding: 10px 12px;
30192
32779
  }
30193
- .vr-chat-plus svg {
30194
- width: 14px;
30195
- height: 14px;
32780
+
32781
+ .vr-composer-controls .vr-chat-send {
32782
+ flex-basis: 38px;
32783
+ width: 38px;
32784
+ height: 38px;
30196
32785
  }
30197
- .vr-chat-inline-actions.is-collapsed {
30198
- overflow: visible;
30199
- padding: 6px 0 10px;
32786
+
32787
+ .vr-composer-controls .vr-chat-send.is-stop {
32788
+ border-color: rgba(216, 180, 254, 0.52);
32789
+ background: linear-gradient(135deg, #9b5cf6, #6d28d9);
32790
+ color: #f5f3ff;
32791
+ box-shadow:
32792
+ 0 0 0 4px rgba(124, 58, 237, 0.13),
32793
+ 0 14px 34px rgba(88, 28, 135, 0.34);
30200
32794
  }
30201
- .vr-chat-inline-actions {
32795
+
32796
+ .vr-composer-controls .vr-chat-send.is-stop svg {
32797
+ width: 17px;
32798
+ height: 17px;
32799
+ display: block;
32800
+ stroke-width: 2.35;
32801
+ }
32802
+
32803
+ .vr-composer-controls .vr-chat-send.is-stop svg rect {
32804
+ x: 6.75px;
32805
+ y: 6.75px;
32806
+ width: 10.5px;
32807
+ height: 10.5px;
32808
+ rx: 2.25px;
32809
+ fill: currentColor;
32810
+ stroke: none;
32811
+ }
32812
+
32813
+ /* --- Worktree commit action polish --- */
32814
+ .vr-branch-row.is-dirty {
32815
+ border-color: rgba(249, 115, 22, 0.22);
32816
+ background:
32817
+ linear-gradient(90deg, rgba(249, 115, 22, 0.09), rgba(124, 58, 237, 0.035)),
32818
+ rgba(255, 255, 255, 0.02);
32819
+ }
32820
+
32821
+ .vr-branch-row.is-dirty b {
32822
+ display: inline-flex;
30202
32823
  align-items: center;
32824
+ justify-content: center;
32825
+ min-width: 66px;
32826
+ min-height: 24px;
32827
+ padding: 0 12px;
32828
+ border-color: rgba(216, 180, 254, 0.34);
32829
+ background: rgba(124, 58, 237, 0.15);
32830
+ color: #ddd6fe;
32831
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
30203
32832
  }
30204
32833
 
30205
- /* Breathing room in the chat lane. */
30206
- .vr-chat-transcript {
30207
- padding: 14px 16px 10px;
32834
+ .vr-branch-row.is-dirty:hover b {
32835
+ border-color: rgba(216, 180, 254, 0.52);
32836
+ background: rgba(124, 58, 237, 0.22);
30208
32837
  }
30209
- .vr-chat-command-bar {
30210
- gap: 8px;
30211
- padding: 10px 14px 14px;
32838
+
32839
+ .vr-inspector-warning button,
32840
+ .vr-wt-dirty button {
32841
+ min-height: 32px;
32842
+ border-color: rgba(216, 180, 254, 0.34);
32843
+ border-radius: 10px;
32844
+ background: rgba(124, 58, 237, 0.14);
32845
+ color: #ede9fe;
32846
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
30212
32847
  }
30213
- .vr-chat-command-bar > .vr-chat-composer {
30214
- border-radius: 18px;
30215
- padding: 14px 16px;
32848
+
32849
+ .vr-inspector-warning button:hover,
32850
+ .vr-wt-dirty button:hover {
32851
+ border-color: rgba(216, 180, 254, 0.52);
32852
+ background: rgba(124, 58, 237, 0.22);
32853
+ }
32854
+
32855
+ @media (max-width: 760px) {
32856
+ .vr-chat-command-bar > .vr-chat-composer {
32857
+ min-height: 156px;
32858
+ padding: 14px;
32859
+ }
32860
+ .vr-composer-bottom,
32861
+ .vr-composer-controls {
32862
+ align-items: stretch;
32863
+ flex-direction: column;
32864
+ }
32865
+ .vr-chat-inline-actions {
32866
+ display: grid;
32867
+ grid-template-columns: repeat(3, minmax(0, 1fr));
32868
+ }
32869
+ .vr-context-tray {
32870
+ grid-template-columns: 1fr;
32871
+ }
32872
+ .vr-context-tray section > div {
32873
+ grid-template-columns: 1fr;
32874
+ }
32875
+ .vr-chat-inline-actions > button {
32876
+ justify-content: center;
32877
+ padding: 0 8px;
32878
+ }
32879
+ .vr-composer-controls .vr-model-picker {
32880
+ width: 100%;
32881
+ }
32882
+ .vr-composer-controls .vr-model-picker > button:nth-child(2) {
32883
+ flex: 1;
32884
+ }
32885
+ .vr-composer-controls .vr-chat-send {
32886
+ align-self: flex-end;
32887
+ }
32888
+ .vr-env-connect-card {
32889
+ width: 100%;
32890
+ margin-left: 0;
32891
+ padding: 16px;
32892
+ }
32893
+ .vr-chat-intro-message {
32894
+ width: 100%;
32895
+ max-width: 100%;
32896
+ }
32897
+ .vr-env-connect-card > div {
32898
+ grid-template-columns: 1fr;
32899
+ }
32900
+ .vr-env-connect-steps {
32901
+ grid-template-columns: 1fr;
32902
+ }
32903
+ .vr-chat-intro-message > p {
32904
+ padding-left: 0;
32905
+ }
30216
32906
  }
30217
32907
  `;
30218
32908
  }
@@ -30230,9 +32920,9 @@ function renderLocalUiHtml(state) {
30230
32920
  <meta name="viewport" content="width=device-width, initial-scale=1" />
30231
32921
  <meta name="theme-color" content="#050816" />
30232
32922
  <title>VibeRaven</title>
30233
- <link rel="icon" type="image/png" sizes="64x64" href="/report/assets/viberaven-favicon.png" />
30234
- <link rel="shortcut icon" type="image/png" href="/report/assets/viberaven-favicon.png" />
30235
- <link rel="apple-touch-icon" href="/report/assets/viberaven-mascot.png" />
32923
+ <link rel="icon" type="image/png" href="/report/assets/viberaven-mascot.png?v=mascot" />
32924
+ <link rel="shortcut icon" type="image/png" href="/report/assets/viberaven-mascot.png?v=mascot" />
32925
+ <link rel="apple-touch-icon" href="/report/assets/viberaven-mascot.png?v=mascot" />
30236
32926
  <style>${localUiCss}</style>
30237
32927
  </head>
30238
32928
  <body>
@@ -30251,6 +32941,25 @@ var init_appHtml = __esm({
30251
32941
  });
30252
32942
 
30253
32943
  // src/local-ui/server.ts
32944
+ function normalizeShellCommand(value) {
32945
+ return value.trim().replace(/\s+/g, " ");
32946
+ }
32947
+ function resolveApprovedShellCommand(command, requestedCliId) {
32948
+ const normalized = normalizeShellCommand(command);
32949
+ const candidateIds = requestedCliId ? [requestedCliId] : ["codex", "claude", "gemini"];
32950
+ for (const cliId of candidateIds) {
32951
+ const setup = CLI_AGENT_SETUP[cliId];
32952
+ const install = normalizeShellCommand(setup.installCommand);
32953
+ if (normalized === install) {
32954
+ return { cliId, step: "install", command: setup.installCommand };
32955
+ }
32956
+ const signIn = normalizeShellCommand(setup.signInCommand);
32957
+ if (normalized === signIn) {
32958
+ return { cliId, step: "sign-in", command: setup.signInCommand };
32959
+ }
32960
+ }
32961
+ return null;
32962
+ }
30254
32963
  async function connectProviderMcp(cwd, providerId) {
30255
32964
  const recipe = MCP_SERVER_RECIPES[providerId];
30256
32965
  if (!recipe) {
@@ -31685,13 +34394,25 @@ async function handleRequest(request, response, options) {
31685
34394
  return;
31686
34395
  }
31687
34396
  const command = isRecord4(body) ? stringField(body.command, 400) : void 0;
34397
+ const requestedCliId = isRecord4(body) && (body.cliId === "codex" || body.cliId === "claude" || body.cliId === "gemini") ? body.cliId : void 0;
31688
34398
  if (!command) {
31689
34399
  sendText(response, 400, "Missing command");
31690
34400
  return;
31691
34401
  }
31692
- const result = await runShellCommand(command, options.cwd, 12e4);
34402
+ const approvedCommand = resolveApprovedShellCommand(command, requestedCliId);
34403
+ if (!approvedCommand) {
34404
+ sendJsonStatus(response, 403, {
34405
+ ok: false,
34406
+ message: "Studio shell is restricted to agent setup commands (install/sign-in) only."
34407
+ });
34408
+ return;
34409
+ }
34410
+ const result = await runShellCommand(approvedCommand.command, options.cwd, 12e4);
31693
34411
  sendJson(response, {
31694
- command,
34412
+ ok: true,
34413
+ command: approvedCommand.command,
34414
+ cliId: approvedCommand.cliId,
34415
+ step: approvedCommand.step,
31695
34416
  exitCode: result.exitCode,
31696
34417
  output: result.output,
31697
34418
  message: result.exitCode === 0 ? "Command finished." : "Command finished with a non-zero exit code."