copilotoffice 1.0.1 → 1.0.3

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.
@@ -140044,7 +140044,7 @@ var CopilotOffice = (() => {
140044
140044
  CORE_AGENT_IDS.clear();
140045
140045
  for (const a of AGENTS) CORE_AGENT_IDS.add(a.id);
140046
140046
  }
140047
- var FLEET_NAMES, FLEET_COLORS, FLEET_SEAT_POSITIONS, ARTHUR_FLEET_SEAT_INDEX, FLEET_AGENTS, RESERVE_AGENTS, CORE_AGENT_IDS, RESERVE_AGENT_DESK, AGENTS, DEFAULT_AGENTS, DEFAULT_RESERVE_MAP, RANDOM_POOL_CONFIGS, RANDOM_SPRITE_COUNT, CORE_POSITIONS, RESERVE_DESK_IDS, RESERVE_POSITIONS, ROLE_TITLES;
140047
+ var FLEET_NAMES, FLEET_COLORS, FLEET_SEAT_POSITIONS, ARTHUR_FLEET_SEAT_INDEX, FLEET_AGENTS, RESERVE_AGENTS, SHOW_ARCHITECT_IN_DEFAULT_OFFICE, CORE_AGENT_IDS, RESERVE_AGENT_DESK, AGENTS, DEFAULT_AGENTS, DEFAULT_RESERVE_MAP, RANDOM_POOL_CONFIGS, RANDOM_SPRITE_COUNT, CORE_POSITIONS, RESERVE_DESK_IDS, RESERVE_POSITIONS, ROLE_TITLES;
140048
140048
  var init_agents = __esm({
140049
140049
  "src/config/agents.ts"() {
140050
140050
  "use strict";
@@ -140289,7 +140289,13 @@ var CopilotOffice = (() => {
140289
140289
  description: "The Accountant"
140290
140290
  }
140291
140291
  };
140292
- CORE_AGENT_IDS = /* @__PURE__ */ new Set(["generalist", "architect", "debugger", "admin"]);
140292
+ SHOW_ARCHITECT_IN_DEFAULT_OFFICE = false;
140293
+ CORE_AGENT_IDS = /* @__PURE__ */ new Set([
140294
+ "generalist",
140295
+ ...SHOW_ARCHITECT_IN_DEFAULT_OFFICE ? ["architect"] : [],
140296
+ "debugger",
140297
+ "admin"
140298
+ ]);
140293
140299
  RESERVE_AGENT_DESK = Object.fromEntries(
140294
140300
  Object.entries(RESERVE_AGENTS).map(([deskId, config]) => [config.id, deskId])
140295
140301
  );
@@ -140306,7 +140312,7 @@ var CopilotOffice = (() => {
140306
140312
  greeting: "Hey! I'm Gene, the Generalist. I can help with just about anything - coding, debugging, research, you name it!",
140307
140313
  description: "the Generalist"
140308
140314
  },
140309
- {
140315
+ ...SHOW_ARCHITECT_IN_DEFAULT_OFFICE ? [{
140310
140316
  id: "architect",
140311
140317
  name: "Arthur",
140312
140318
  skill: "general",
@@ -140317,7 +140323,7 @@ var CopilotOffice = (() => {
140317
140323
  // bottom-left corner, own desk
140318
140324
  greeting: "\u26A1 I am Arthur, The Architect. I design systems, orchestrate plans, and spin up agents to execute complex tasks. Tell me your vision, and I'll build the team to make it happen.",
140319
140325
  description: "The Architect"
140320
- },
140326
+ }] : [],
140321
140327
  {
140322
140328
  id: "debugger",
140323
140329
  name: "Dan",
@@ -148592,6 +148598,7 @@ WARNING: This link could potentially be dangerous`)) {
148592
148598
  this.historyPopover = null;
148593
148599
  this.isFullWidth = false;
148594
148600
  this.fullscreenBtn = null;
148601
+ this.mobileKeyboardBtn = null;
148595
148602
  this.isFocused = false;
148596
148603
  this.resizeHandler = null;
148597
148604
  this.resizeObserver = null;
@@ -148599,6 +148606,7 @@ WARNING: This link could potentially be dangerous`)) {
148599
148606
  this.attachedOfficeId = null;
148600
148607
  this.isReadOnly = false;
148601
148608
  this.isReplaying = false;
148609
+ this.launchMode = "copilot";
148602
148610
  this.scene = scene;
148603
148611
  this.inputManager = inputManager;
148604
148612
  this.getOfficeId = getOfficeId;
@@ -148642,6 +148650,7 @@ WARNING: This link could potentially be dangerous`)) {
148642
148650
  parseSessionId(_data) {
148643
148651
  }
148644
148652
  acknowledgeCompletedWork(officeId, agentId) {
148653
+ if (agentId === "pc-terminal") return;
148645
148654
  if (officeManager.acknowledgeAgentCompletion(officeId, agentId)) {
148646
148655
  this.scene.game.events.emit("agent:status:changed", agentId);
148647
148656
  }
@@ -148663,6 +148672,7 @@ WARNING: This link could potentially be dangerous`)) {
148663
148672
  this.currentAgentId = agent.id;
148664
148673
  this.onCloseCallback = onClose;
148665
148674
  this.isReadOnly = options?.readOnly ?? false;
148675
+ this.launchMode = options?.launchMode ?? "copilot";
148666
148676
  this.attachedOfficeId = this.getOfficeId();
148667
148677
  this.currentAgent = agent;
148668
148678
  if (!this.container) {
@@ -148707,6 +148717,8 @@ WARNING: This link could potentially be dangerous`)) {
148707
148717
  if (this.spriteCardElement) {
148708
148718
  this.spriteCardElement.style.display = "flex";
148709
148719
  }
148720
+ this.applySpriteCardResponsiveStyles();
148721
+ this.updateMobileKeyboardButtonVisibility();
148710
148722
  this.applyPanelLayout();
148711
148723
  this.updateFullscreenButton();
148712
148724
  const colorHex = "#" + agent.color.toString(16).padStart(6, "0");
@@ -148804,7 +148816,21 @@ WARNING: This link could potentially be dangerous`)) {
148804
148816
  this.fitAddon?.fit();
148805
148817
  const dims = this.fitAddon?.proposeDimensions();
148806
148818
  const result = await withTimeout(
148807
- window.copilotBridge.terminalStart(this.getOfficeId(), agentId, workingDir, dims?.cols, dims?.rows),
148819
+ this.launchMode === "shell" ? window.copilotBridge.terminalStart(
148820
+ this.getOfficeId(),
148821
+ agentId,
148822
+ workingDir,
148823
+ dims?.cols,
148824
+ dims?.rows,
148825
+ void 0,
148826
+ "shell"
148827
+ ) : window.copilotBridge.terminalStart(
148828
+ this.getOfficeId(),
148829
+ agentId,
148830
+ workingDir,
148831
+ dims?.cols,
148832
+ dims?.rows
148833
+ ),
148808
148834
  IPC_TIMEOUT,
148809
148835
  "terminalStart"
148810
148836
  );
@@ -148928,6 +148954,13 @@ WARNING: This link could potentially be dangerous`)) {
148928
148954
  </div>
148929
148955
  `;
148930
148956
  this.spriteCardElement.appendChild(agentDisplay);
148957
+ const controlsColumn = document.createElement("div");
148958
+ controlsColumn.style.cssText = `
148959
+ display: flex;
148960
+ flex-direction: column;
148961
+ gap: 10px;
148962
+ align-items: stretch;
148963
+ `;
148931
148964
  const buttonGrid = document.createElement("div");
148932
148965
  buttonGrid.style.cssText = `
148933
148966
  display: grid;
@@ -149001,7 +149034,30 @@ WARNING: This link could potentially be dangerous`)) {
149001
149034
  refreshFocusBtn.onclick = () => this.focusTerminal();
149002
149035
  refreshFocusBtn.title = "Re-focus terminal input when typing stops working";
149003
149036
  buttonGrid.appendChild(refreshFocusBtn);
149004
- this.spriteCardElement.appendChild(buttonGrid);
149037
+ this.mobileKeyboardBtn = document.createElement("button");
149038
+ this.mobileKeyboardBtn.textContent = "\u2328 Open Keyboard";
149039
+ this.mobileKeyboardBtn.style.cssText = `
149040
+ ${btnStyle}
149041
+ width: 100%;
149042
+ min-height: 56px;
149043
+ font-size: 20px;
149044
+ font-weight: bold;
149045
+ color: #ffffff;
149046
+ background: #3a4f8f;
149047
+ border: 2px solid #6f86d8;
149048
+ `;
149049
+ this.mobileKeyboardBtn.onmouseover = () => {
149050
+ if (this.mobileKeyboardBtn) this.mobileKeyboardBtn.style.background = "#4a63b0";
149051
+ };
149052
+ this.mobileKeyboardBtn.onmouseout = () => {
149053
+ if (this.mobileKeyboardBtn) this.mobileKeyboardBtn.style.background = "#3a4f8f";
149054
+ };
149055
+ this.mobileKeyboardBtn.onclick = () => this.focusTerminal();
149056
+ this.mobileKeyboardBtn.title = "Tap to open the device keyboard for terminal input";
149057
+ controlsColumn.appendChild(this.mobileKeyboardBtn);
149058
+ controlsColumn.appendChild(buttonGrid);
149059
+ this.spriteCardElement.appendChild(controlsColumn);
149060
+ this.updateMobileKeyboardButtonVisibility();
149005
149061
  const gameContainer = document.getElementById("game-container");
149006
149062
  if (gameContainer) {
149007
149063
  gameContainer.appendChild(this.spriteCardElement);
@@ -149044,7 +149100,21 @@ WARNING: This link could potentially be dangerous`)) {
149044
149100
  this.fitAddon?.fit();
149045
149101
  const dims = this.fitAddon?.proposeDimensions();
149046
149102
  const result = await withTimeout(
149047
- window.copilotBridge.terminalStart(officeId, this.currentAgentId, this.currentAgent.workingDir || officeManager.getCurrentWorkingDirectory(), dims?.cols, dims?.rows),
149103
+ this.launchMode === "shell" ? window.copilotBridge.terminalStart(
149104
+ officeId,
149105
+ this.currentAgentId,
149106
+ this.currentAgent.workingDir || officeManager.getCurrentWorkingDirectory(),
149107
+ dims?.cols,
149108
+ dims?.rows,
149109
+ void 0,
149110
+ "shell"
149111
+ ) : window.copilotBridge.terminalStart(
149112
+ officeId,
149113
+ this.currentAgentId,
149114
+ this.currentAgent.workingDir || officeManager.getCurrentWorkingDirectory(),
149115
+ dims?.cols,
149116
+ dims?.rows
149117
+ ),
149048
149118
  IPC_TIMEOUT,
149049
149119
  "terminalStart"
149050
149120
  );
@@ -149237,12 +149307,16 @@ WARNING: This link could potentially be dangerous`)) {
149237
149307
  });
149238
149308
  this.resizeHandler = () => {
149239
149309
  if (this.isVisible) {
149310
+ this.applySpriteCardResponsiveStyles();
149311
+ this.updateMobileKeyboardButtonVisibility();
149240
149312
  this.debouncedRefit();
149241
149313
  }
149242
149314
  };
149243
149315
  window.addEventListener("resize", this.resizeHandler);
149244
149316
  this.resizeObserver = new ResizeObserver(() => {
149245
149317
  if (this.isVisible) {
149318
+ this.applySpriteCardResponsiveStyles();
149319
+ this.updateMobileKeyboardButtonVisibility();
149246
149320
  this.debouncedRefit();
149247
149321
  }
149248
149322
  });
@@ -149252,6 +149326,13 @@ WARNING: This link could potentially be dangerous`)) {
149252
149326
  }
149253
149327
  /** Toggle between half-width and full-width terminal panel. */
149254
149328
  toggleFullWidth() {
149329
+ if (window.__copilotOfficeMobileModeActive?.() === true) {
149330
+ this.isFullWidth = true;
149331
+ this.applyPanelLayout();
149332
+ this.updateFullscreenButton();
149333
+ this.debouncedRefit();
149334
+ return;
149335
+ }
149255
149336
  this.isFullWidth = !this.isFullWidth;
149256
149337
  localStorage.setItem(_TerminalOverlay.STORAGE_KEY, String(this.isFullWidth));
149257
149338
  console.log(`[TerminalOverlay] toggleFullWidth() \u2014 now ${this.isFullWidth ? "full" : "half"}`);
@@ -149264,6 +149345,12 @@ WARNING: This link could potentially be dangerous`)) {
149264
149345
  const officePanel = document.getElementById("office-panel");
149265
149346
  const terminalPanel = document.getElementById("terminal-panel");
149266
149347
  if (!officePanel || !terminalPanel) return;
149348
+ if (window.__copilotOfficeMobileModeActive?.() === true) {
149349
+ officePanel.style.display = "none";
149350
+ terminalPanel.style.width = "100%";
149351
+ terminalPanel.style.borderLeft = "none";
149352
+ return;
149353
+ }
149267
149354
  if (this.isFullWidth) {
149268
149355
  officePanel.style.display = "none";
149269
149356
  terminalPanel.style.width = "100%";
@@ -149275,6 +149362,7 @@ WARNING: This link could potentially be dangerous`)) {
149275
149362
  }
149276
149363
  /** Restore half-width layout (used when hiding terminal). */
149277
149364
  restorePanelLayout() {
149365
+ if (window.__copilotOfficeMobileModeActive?.() === true) return;
149278
149366
  const officePanel = document.getElementById("office-panel");
149279
149367
  const terminalPanel = document.getElementById("terminal-panel");
149280
149368
  if (!officePanel || !terminalPanel) return;
@@ -149306,9 +149394,30 @@ WARNING: This link could potentially be dangerous`)) {
149306
149394
  /** Update the fullscreen toggle button label. */
149307
149395
  updateFullscreenButton() {
149308
149396
  if (this.fullscreenBtn) {
149397
+ if (window.__copilotOfficeMobileModeActive?.() === true) {
149398
+ this.fullscreenBtn.textContent = "\u26F6 Locked";
149399
+ this.fullscreenBtn.title = "Fullscreen is locked in mobile mode";
149400
+ return;
149401
+ }
149309
149402
  this.fullscreenBtn.textContent = this.isFullWidth ? "\u26F6 Half" : "\u26F6 Fullscreen";
149403
+ this.fullscreenBtn.title = "";
149310
149404
  }
149311
149405
  }
149406
+ applySpriteCardResponsiveStyles() {
149407
+ if (!this.spriteCardElement) return;
149408
+ const isMobile = window.__copilotOfficeMobileModeActive?.() === true;
149409
+ if (isMobile) {
149410
+ this.spriteCardElement.style.minHeight = "416px";
149411
+ this.spriteCardElement.style.padding = "39px";
149412
+ return;
149413
+ }
149414
+ this.spriteCardElement.style.minHeight = "";
149415
+ this.spriteCardElement.style.padding = "15px 30px";
149416
+ }
149417
+ updateMobileKeyboardButtonVisibility() {
149418
+ if (!this.mobileKeyboardBtn) return;
149419
+ this.mobileKeyboardBtn.style.display = "none";
149420
+ }
149312
149421
  /** Give keyboard focus to the terminal. Safe to call when already focused. */
149313
149422
  focusTerminal() {
149314
149423
  console.log("[TerminalOverlay] focusTerminal() \u2014 delegating to InputManager");
@@ -149317,6 +149426,9 @@ WARNING: This link could potentially be dangerous`)) {
149317
149426
  () => this.handleNewSession(),
149318
149427
  () => this.toggleFullWidth()
149319
149428
  );
149429
+ if (window.__copilotOfficeMobileModeActive?.() === true) {
149430
+ this.terminal?.focus();
149431
+ }
149320
149432
  this.inputManager.focusTerminalXterm(this.terminal);
149321
149433
  if (this.currentAgent) {
149322
149434
  this.scene.game.events.emit("npc:highlight", this.currentAgent.id);
@@ -149332,7 +149444,12 @@ WARNING: This link could potentially be dangerous`)) {
149332
149444
  /** Give keyboard focus back to the game canvas. Safe to call when already blurred. */
149333
149445
  blurTerminal() {
149334
149446
  console.log("[TerminalOverlay] blurTerminal() \u2014 delegating to InputManager");
149335
- this.inputManager.switchToGame("TerminalOverlay.blurTerminal()");
149447
+ const mobileLocked = window.__copilotOfficeMobileModeActive?.() === true;
149448
+ if (mobileLocked) {
149449
+ this.inputManager.switchToNone("TerminalOverlay.blurTerminal() mobile lock");
149450
+ } else {
149451
+ this.inputManager.switchToGame("TerminalOverlay.blurTerminal()");
149452
+ }
149336
149453
  this.inputManager.blurTerminalXterm(this.terminal);
149337
149454
  if (this.currentAgentId) {
149338
149455
  const officeId = this.attachedOfficeId ?? this.getOfficeId();
@@ -149363,6 +149480,7 @@ WARNING: This link could potentially be dangerous`)) {
149363
149480
  if (this.spriteCardElement) {
149364
149481
  this.spriteCardElement.style.display = "none";
149365
149482
  }
149483
+ this.updateMobileKeyboardButtonVisibility();
149366
149484
  this.isVisible = false;
149367
149485
  this.isReadOnly = false;
149368
149486
  this.closeHistoryPopover();
@@ -149384,7 +149502,9 @@ WARNING: This link could potentially be dangerous`)) {
149384
149502
  if (this.onCloseCallback) {
149385
149503
  this.onCloseCallback();
149386
149504
  }
149387
- this.scene.game.canvas.focus();
149505
+ if (window.__copilotOfficeMobileModeActive?.() !== true) {
149506
+ this.scene.game.canvas.focus();
149507
+ }
149388
149508
  }
149389
149509
  getIsVisible() {
149390
149510
  return this.isVisible;
@@ -150346,15 +150466,102 @@ WARNING: This link could potentially be dangerous`)) {
150346
150466
  }
150347
150467
  });
150348
150468
 
150469
+ // src/layouts/types.ts
150470
+ function getDashboardTypography() {
150471
+ const isMobile = typeof window !== "undefined" && window.__copilotOfficeMobileModeActive?.() === true;
150472
+ return isMobile ? MOBILE_DASHBOARD_TYPOGRAPHY : DESKTOP_DASHBOARD_TYPOGRAPHY;
150473
+ }
150474
+ var DESKTOP_DASHBOARD_TYPOGRAPHY, MOBILE_DASHBOARD_TYPOGRAPHY;
150475
+ var init_types = __esm({
150476
+ "src/layouts/types.ts"() {
150477
+ "use strict";
150478
+ DESKTOP_DASHBOARD_TYPOGRAPHY = {
150479
+ cardTitle: "15px",
150480
+ cardDescription: "11px",
150481
+ statusText: "11px",
150482
+ statusDot: "8px",
150483
+ elapsed: "10px",
150484
+ badge: "10px",
150485
+ queue: "9px",
150486
+ toolRow: "10px",
150487
+ sectionLabel: "9px",
150488
+ activityRow: "10px",
150489
+ taskSummary: "10px",
150490
+ sessionLabel: "9px",
150491
+ sessionTitle: "13px",
150492
+ sessionButton: "11px",
150493
+ emptyState: "11px",
150494
+ arthurHint: "10px"
150495
+ };
150496
+ MOBILE_DASHBOARD_TYPOGRAPHY = {
150497
+ cardTitle: "19px",
150498
+ cardDescription: "15px",
150499
+ statusText: "16px",
150500
+ statusDot: "11px",
150501
+ elapsed: "14px",
150502
+ badge: "13px",
150503
+ queue: "13px",
150504
+ toolRow: "14px",
150505
+ sectionLabel: "13px",
150506
+ activityRow: "14px",
150507
+ taskSummary: "14px",
150508
+ sessionLabel: "13px",
150509
+ sessionTitle: "17px",
150510
+ sessionButton: "14px",
150511
+ emptyState: "14px",
150512
+ arthurHint: "14px"
150513
+ };
150514
+ }
150515
+ });
150516
+
150349
150517
  // src/layouts/default/DefaultDashboard.ts
150350
150518
  var defaultDashboard;
150351
150519
  var init_DefaultDashboard = __esm({
150352
150520
  "src/layouts/default/DefaultDashboard.ts"() {
150353
150521
  "use strict";
150522
+ init_types();
150354
150523
  defaultDashboard = {
150355
150524
  renderCards(ctx) {
150356
150525
  const { agents, office, selectedAgentId, cachedSessionMeta, agentTools, formatElapsed, formatRelativeTime } = ctx;
150526
+ const t = getDashboardTypography();
150357
150527
  let html = "";
150528
+ const pcCardSelected = selectedAgentId === "pc-terminal";
150529
+ html += `
150530
+ <div class="agent-card" data-agent="pc-terminal" style="
150531
+ background: ${pcCardSelected ? "#1e1e3a" : "#13131f"};
150532
+ border: 1.5px solid ${pcCardSelected ? "#6677ff" : "#252540"};
150533
+ border-radius: 10px;
150534
+ padding: 14px 16px;
150535
+ margin-bottom: 10px;
150536
+ cursor: pointer;
150537
+ transition: border-color 0.15s;
150538
+ display: flex;
150539
+ align-items: center;
150540
+ gap: 12px;
150541
+ ">
150542
+ <div style="
150543
+ width: 64px;
150544
+ background: #5da9ff22;
150545
+ border: 1px solid #5da9ff44;
150546
+ border-radius: 8px;
150547
+ display: flex;
150548
+ align-items: center;
150549
+ justify-content: center;
150550
+ overflow: hidden;
150551
+ flex-shrink: 0;
150552
+ ">
150553
+ <canvas
150554
+ id="overview-sprite-pc-terminal"
150555
+ width="32" height="32"
150556
+ style="image-rendering: pixelated; width: 48px; height: 48px; display: block;"
150557
+ ></canvas>
150558
+ </div>
150559
+ <div style="min-width: 0;">
150560
+ <div style="font-weight: bold; color: #dde; font-size: ${t.cardTitle};">PC TERMINAL</div>
150561
+ <div style="color: #778; font-size: ${t.cardDescription}; margin-top: 2px;">Local shell</div>
150562
+ </div>
150563
+ </div>
150564
+ `;
150358
150565
  for (const agent of agents) {
150359
150566
  const liveStatus = office?.agents.get(agent.id);
150360
150567
  const tools = agentTools.get(agent.id) || [];
@@ -150412,27 +150619,27 @@ WARNING: This link could potentially be dangerous`)) {
150412
150619
  <div style="
150413
150620
  position: absolute; top: -4px; right: -4px;
150414
150621
  background: #e55; color: #fff;
150415
- font-size: 10px; font-weight: bold;
150622
+ font-size: ${t.badge}; font-weight: bold;
150416
150623
  min-width: 18px; height: 18px;
150417
150624
  border-radius: 9px;
150418
150625
  display: flex; align-items: center; justify-content: center;
150419
150626
  padding: 0 4px;
150420
150627
  box-shadow: 0 1px 4px rgba(0,0,0,0.4);
150421
150628
  ">${unread}</div>` : "";
150422
- const elapsedHtml = elapsed ? `<span data-elapsed-agent="${agent.id}" style="color: #8a8; font-size: 10px; margin-left: 8px;">\u23F1 ${elapsed}</span>` : "";
150629
+ const elapsedHtml = elapsed ? `<span data-elapsed-agent="${agent.id}" style="color: #8a8; font-size: ${t.elapsed}; margin-left: 8px;">\u23F1 ${elapsed}</span>` : "";
150423
150630
  const queueHtml = toolCount > 1 ? `<span style="
150424
- background: #334; color: #aac; font-size: 9px;
150631
+ background: #334; color: #aac; font-size: ${t.queue};
150425
150632
  padding: 1px 6px; border-radius: 8px; margin-left: 6px;
150426
150633
  ">${toolCount} tools</span>` : "";
150427
150634
  let toolPipelineHtml = "";
150428
150635
  if (tools.length > 0) {
150429
- const toolRows = tools.map((t, i) => {
150636
+ const toolRows = tools.map((t2, i) => {
150430
150637
  const isLast = i === tools.length - 1;
150431
150638
  const icon = isLast ? "\u25B8" : "\u25E6";
150432
150639
  const color = isLast ? "#8af" : "#556";
150433
- const statusText = isLast ? t.status : "(queued)";
150434
- return `<div style="font-size: 10px; color: ${color}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 1px 0;">
150435
- ${icon} <span style="color: #9ab;">${t.name}</span> <span style="color: #556;">\u2014 ${statusText}</span>
150640
+ const statusText = isLast ? t2.status : "(queued)";
150641
+ return `<div style="font-size: ${t2.toolRow}; color: ${color}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 1px 0;">
150642
+ ${icon} <span style="color: #9ab;">${t2.name}</span> <span style="color: #556;">\u2014 ${statusText}</span>
150436
150643
  </div>`;
150437
150644
  }).join("");
150438
150645
  toolPipelineHtml = `
@@ -150445,24 +150652,24 @@ WARNING: This link could potentially be dangerous`)) {
150445
150652
  if (completedActions.length > 0) {
150446
150653
  const rows = completedActions.map((a) => {
150447
150654
  const relTime = formatRelativeTime(a.timestamp);
150448
- return `<div style="display: flex; gap: 8px; font-size: 10px; padding: 1px 0;" data-action-ts="${a.timestamp}">
150655
+ return `<div style="display: flex; gap: 8px; font-size: ${t.activityRow}; padding: 1px 0;" data-action-ts="${a.timestamp}">
150449
150656
  <span style="color: #445; flex-shrink: 0; min-width: 48px; text-align: right;">${relTime}</span>
150450
150657
  <span style="color: #5a5a7a;">\u2713 ${a.action}</span>
150451
150658
  </div>`;
150452
150659
  }).join("");
150453
150660
  activityLogHtml = `
150454
150661
  <div style="margin-top: 6px; padding-top: 6px; border-top: 1px solid #1a1a30;">
150455
- <div style="font-size: 9px; color: #3a3a5a; margin-bottom: 3px; text-transform: uppercase; letter-spacing: 0.5px;">Recent Activity</div>
150662
+ <div style="font-size: ${t.sectionLabel}; color: #3a3a5a; margin-bottom: 3px; text-transform: uppercase; letter-spacing: 0.5px;">Recent Activity</div>
150456
150663
  ${rows}
150457
150664
  </div>`;
150458
150665
  } else if (liveStatus?.state !== "slacking") {
150459
150666
  activityLogHtml = `
150460
150667
  <div style="margin-top: 6px; padding-top: 6px; border-top: 1px solid #1a1a30;">
150461
- <div style="font-size: 10px; color: #333; font-style: italic;">No recent activity</div>
150668
+ <div style="font-size: ${t.emptyState}; color: #333; font-style: italic;">No recent activity</div>
150462
150669
  </div>`;
150463
150670
  }
150464
150671
  const taskSummaryHtml = taskSummary && isActive ? `
150465
- <div style="font-size: 10px; color: #667; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
150672
+ <div style="font-size: ${t.taskSummary}; color: #667; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
150466
150673
  \u{1F4CB} ${taskSummary}
150467
150674
  </div>` : "";
150468
150675
  const meta = cachedSessionMeta[agent.id];
@@ -150477,9 +150684,9 @@ WARNING: This link could potentially be dangerous`)) {
150477
150684
  align-self: stretch;
150478
150685
  justify-content: center;
150479
150686
  ">
150480
- <div style="font-size: 9px; color: #3a3a5a; text-transform: uppercase; letter-spacing: 0.5px;">Session Info</div>
150687
+ <div style="font-size: ${t.sessionLabel}; color: #3a3a5a; text-transform: uppercase; letter-spacing: 0.5px;">Session Info</div>
150481
150688
  <div class="session-title-display" data-agent="${agent.id}" style="
150482
- font-weight: bold; color: ${metaTitle ? "#ccd" : "#444"}; font-size: 13px;
150689
+ font-weight: bold; color: ${metaTitle ? "#ccd" : "#444"}; font-size: ${t.sessionTitle};
150483
150690
  cursor: text; min-height: 18px; line-height: 1.4;
150484
150691
  overflow: hidden; text-overflow: ellipsis;
150485
150692
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
@@ -150487,7 +150694,7 @@ WARNING: This link could potentially be dangerous`)) {
150487
150694
  <div style="display: flex; justify-content: flex-end; margin-top: 2px;">
150488
150695
  <button class="session-edit-btn" data-agent="${agent.id}" style="
150489
150696
  background: none; border: 1px solid #333; color: #667;
150490
- font-size: 11px; padding: 2px 8px; border-radius: 4px;
150697
+ font-size: ${t.sessionButton}; padding: 2px 8px; border-radius: 4px;
150491
150698
  cursor: pointer; transition: color 0.15s, border-color 0.15s;
150492
150699
  " title="Edit session title">\u270F\uFE0F</button>
150493
150700
  </div>
@@ -150502,7 +150709,7 @@ WARNING: This link could potentially be dangerous`)) {
150502
150709
  justify-content: center;
150503
150710
  opacity: 0.4;
150504
150711
  ">
150505
- <div style="font-size: 11px; color: #444; font-style: italic;">No active session</div>
150712
+ <div style="font-size: ${t.emptyState}; color: #444; font-style: italic;">No active session</div>
150506
150713
  </div>
150507
150714
  `;
150508
150715
  html += `
@@ -150542,17 +150749,17 @@ WARNING: This link could potentially be dangerous`)) {
150542
150749
  </div>
150543
150750
  <div style="flex: 3; min-width: 0; display: flex; flex-direction: column; gap: 4px;">
150544
150751
  <div>
150545
- <div style="font-weight: bold; color: #dde; font-size: 15px;">${agent.name}</div>
150546
- <div style="color: #778; font-size: 11px; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">${agent.description}</div>
150752
+ <div style="font-weight: bold; color: #dde; font-size: ${t.cardTitle};">${agent.name}</div>
150753
+ <div style="color: #778; font-size: ${t.cardDescription}; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">${agent.description}</div>
150547
150754
  </div>
150548
150755
  <div>
150549
150756
  <div style="display: flex; align-items: center; flex-wrap: wrap; margin-top: 4px;">
150550
150757
  <div style="
150551
- font-size: 11px;
150758
+ font-size: ${t.statusText};
150552
150759
  color: ${statusDot};
150553
150760
  display: flex; align-items: center; gap: 4px;
150554
150761
  ">
150555
- <span style="font-size: 8px;">\u25CF</span>
150762
+ <span style="font-size: ${t.statusDot};">\u25CF</span>
150556
150763
  <span>${statusIcon} ${statusLabel}</span>
150557
150764
  </div>
150558
150765
  ${elapsedHtml}
@@ -150581,7 +150788,9 @@ WARNING: This link could potentially be dangerous`)) {
150581
150788
  defaultClickHandler = {
150582
150789
  handleCardClick(agentId, context) {
150583
150790
  context.setSelectedAgent(agentId);
150584
- context.clearUnread(agentId);
150791
+ if (agentId !== "pc-terminal") {
150792
+ context.clearUnread(agentId);
150793
+ }
150585
150794
  context.updateContent();
150586
150795
  context.emitOpenTerminal(agentId);
150587
150796
  },
@@ -150599,9 +150808,11 @@ WARNING: This link could potentially be dangerous`)) {
150599
150808
  var init_FleetDashboard = __esm({
150600
150809
  "src/layouts/fleet/FleetDashboard.ts"() {
150601
150810
  "use strict";
150811
+ init_types();
150602
150812
  fleetDashboard = {
150603
150813
  renderCards(ctx) {
150604
150814
  const { agents, office, selectedAgentId, formatElapsed, formatRelativeTime } = ctx;
150815
+ const t = getDashboardTypography();
150605
150816
  let html = "";
150606
150817
  for (const agent of agents) {
150607
150818
  const liveStatus = office?.agents.get(agent.id);
@@ -150655,29 +150866,29 @@ WARNING: This link could potentially be dangerous`)) {
150655
150866
  const recentActions = liveStatus?.recentActions || [];
150656
150867
  const taskSummary = liveStatus?.taskSummary || "";
150657
150868
  const isActive = liveStatus?.state === "active" && liveStatus?.subState !== "ready" && liveStatus?.subState !== "error";
150658
- const elapsedHtml = elapsed ? `<span data-elapsed-agent="${agent.id}" style="color: #8a8; font-size: 10px; margin-left: 8px;">\u23F1 ${elapsed}</span>` : "";
150869
+ const elapsedHtml = elapsed ? `<span data-elapsed-agent="${agent.id}" style="color: #8a8; font-size: ${t.elapsed}; margin-left: 8px;">\u23F1 ${elapsed}</span>` : "";
150659
150870
  let activityLogHtml = "";
150660
150871
  const completedActions = recentActions.filter((a) => a.type === "completed").slice(-3).reverse();
150661
150872
  if (completedActions.length > 0) {
150662
150873
  const rows = completedActions.map((a) => {
150663
150874
  const relTime = formatRelativeTime(a.timestamp);
150664
- return `<div style="display: flex; gap: 8px; font-size: 10px; padding: 1px 0;" data-action-ts="${a.timestamp}">
150875
+ return `<div style="display: flex; gap: 8px; font-size: ${t.activityRow}; padding: 1px 0;" data-action-ts="${a.timestamp}">
150665
150876
  <span style="color: #445; flex-shrink: 0; min-width: 48px; text-align: right;">${relTime}</span>
150666
150877
  <span style="color: #5a5a7a;">\u2713 ${a.action}</span>
150667
150878
  </div>`;
150668
150879
  }).join("");
150669
150880
  activityLogHtml = `
150670
150881
  <div style="margin-top: 6px; padding-top: 6px; border-top: 1px solid #1a1a30;">
150671
- <div style="font-size: 9px; color: #3a3a5a; margin-bottom: 3px; text-transform: uppercase; letter-spacing: 0.5px;">Recent Activity</div>
150882
+ <div style="font-size: ${t.sectionLabel}; color: #3a3a5a; margin-bottom: 3px; text-transform: uppercase; letter-spacing: 0.5px;">Recent Activity</div>
150672
150883
  ${rows}
150673
150884
  </div>`;
150674
150885
  }
150675
150886
  const taskSummaryHtml = taskSummary && isActive ? `
150676
- <div style="font-size: 10px; color: #667; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
150887
+ <div style="font-size: ${t.taskSummary}; color: #667; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
150677
150888
  \u{1F4CB} ${taskSummary}
150678
150889
  </div>` : "";
150679
150890
  const arthurHint = isArthur ? `
150680
- <div style="font-size: 10px; color: #4af; margin-top: 4px; display: flex; align-items: center; gap: 4px;">
150891
+ <div style="font-size: ${t.arthurHint}; color: #4af; margin-top: 4px; display: flex; align-items: center; gap: 4px;">
150681
150892
  \u{1F4AC} Open Arthur's terminal
150682
150893
  </div>` : "";
150683
150894
  html += `
@@ -150715,17 +150926,17 @@ WARNING: This link could potentially be dangerous`)) {
150715
150926
  </div>
150716
150927
  <div style="flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px;">
150717
150928
  <div>
150718
- <div style="font-weight: bold; color: #dde; font-size: 14px;">${agent.name}</div>
150719
- <div style="color: #778; font-size: 10px; margin-top: 2px;">${agent.description}</div>
150929
+ <div style="font-weight: bold; color: #dde; font-size: ${t.cardTitle};">${agent.name}</div>
150930
+ <div style="color: #778; font-size: ${t.cardDescription}; margin-top: 2px;">${agent.description}</div>
150720
150931
  </div>
150721
150932
  <div>
150722
150933
  <div style="display: flex; align-items: center; flex-wrap: wrap; margin-top: 3px;">
150723
150934
  <div style="
150724
- font-size: 11px;
150935
+ font-size: ${t.statusText};
150725
150936
  color: ${statusDot};
150726
150937
  display: flex; align-items: center; gap: 4px;
150727
150938
  ">
150728
- <span style="font-size: 8px;">\u25CF</span>
150939
+ <span style="font-size: ${t.statusDot};">\u25CF</span>
150729
150940
  <span>${statusIcon} ${statusLabel}</span>
150730
150941
  </div>
150731
150942
  ${elapsedHtml}
@@ -151095,6 +151306,25 @@ WARNING: This link could potentially be dangerous`)) {
151095
151306
  this.currentFocus = "terminal";
151096
151307
  console.log("[InputManager] \u2500\u2500 switchToTerminal() complete \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
151097
151308
  }
151309
+ /**
151310
+ * Switch focus to a neutral dashboard mode.
151311
+ * - Deactivates Phaser keyboard
151312
+ * - Deactivates terminal shortcut intercepts
151313
+ * - Leaves global listener in 'none' mode
151314
+ */
151315
+ switchToNone(reason) {
151316
+ console.log(
151317
+ `[InputManager] \u2500\u2500 switchToNone() \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
151318
+ reason : "${reason}"
151319
+ from : "${this.currentFocus}"
151320
+ time : ${Date.now()}`
151321
+ );
151322
+ this.terminal.deactivateShortcuts();
151323
+ this.game.deactivate(reason);
151324
+ this.global.setMode("none");
151325
+ this.currentFocus = "none";
151326
+ console.log("[InputManager] \u2500\u2500 switchToNone() complete \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
151327
+ }
151098
151328
  /**
151099
151329
  * Install the F10-to-close handler. Should be called whenever a terminal
151100
151330
  * becomes visible (regardless of which side has keyboard focus — F10 always
@@ -151797,7 +152027,7 @@ WARNING: This link could potentially be dangerous`)) {
151797
152027
  function debugLog(scene, ...args) {
151798
152028
  if (scene.physics.world.drawDebug) console.log("[Debug]", ...args);
151799
152029
  }
151800
- var import_phaser8, ENABLE_DECORATIONS, ENABLE_BASKETBALL, ENABLE_GALAXIAN, ENABLE_ZOOM_BAR, OfficeScene;
152030
+ var import_phaser8, ENABLE_DECORATIONS, ENABLE_BASKETBALL, ENABLE_GALAXIAN, ENABLE_ZOOM_BAR, PC_TERMINAL_ID, OfficeScene;
151801
152031
  var init_OfficeScene = __esm({
151802
152032
  "src/scenes/OfficeScene.ts"() {
151803
152033
  "use strict";
@@ -151820,6 +152050,7 @@ WARNING: This link could potentially be dangerous`)) {
151820
152050
  ENABLE_BASKETBALL = false;
151821
152051
  ENABLE_GALAXIAN = true;
151822
152052
  ENABLE_ZOOM_BAR = true;
152053
+ PC_TERMINAL_ID = "pc-terminal";
151823
152054
  OfficeScene = class extends import_phaser8.default.Scene {
151824
152055
  constructor() {
151825
152056
  super({ key: "OfficeScene" });
@@ -151853,11 +152084,32 @@ WARNING: This link could potentially be dangerous`)) {
151853
152084
  this.walkInTimers = [];
151854
152085
  this.walkInAgents = [];
151855
152086
  this.skipButton = null;
152087
+ this.isPortraitDashboardMode = false;
151856
152088
  }
151857
152089
  setAnimating(value) {
151858
152090
  this.animating = value;
151859
152091
  this.game.registry.set("animating", value);
151860
152092
  }
152093
+ handleLayoutChange(payload) {
152094
+ const next = payload?.layoutKey === "portrait-dashboard";
152095
+ if (next === this.isPortraitDashboardMode) return;
152096
+ this.isPortraitDashboardMode = next;
152097
+ if (next) {
152098
+ this.player.disableMovement();
152099
+ this.playerMovementEnabled = false;
152100
+ this.inputManager.switchToNone("layout:portrait-dashboard");
152101
+ this.physics.world.pause();
152102
+ this.anims.pauseAll();
152103
+ return;
152104
+ }
152105
+ this.physics.world.resume();
152106
+ this.anims.resumeAll();
152107
+ if (!this.terminalOverlay.getIsVisible() && this.playerInScene) {
152108
+ this.player.enableMovement();
152109
+ this.playerMovementEnabled = true;
152110
+ this.inputManager.switchToGame("layout:default");
152111
+ }
152112
+ }
151861
152113
  create() {
151862
152114
  const screenWidth = this.cameras.main.width;
151863
152115
  const screenHeight = this.cameras.main.height;
@@ -152036,6 +152288,10 @@ WARNING: This link could potentially be dangerous`)) {
152036
152288
  this.instructionText.setOrigin(0.5, 1);
152037
152289
  this.instructionText.setDepth(Depths.UI_OVERLAY);
152038
152290
  this.game.events.on("open:agent:terminal", (agentId) => {
152291
+ if (agentId === PC_TERMINAL_ID) {
152292
+ this.openPlayerPcTerminal();
152293
+ return;
152294
+ }
152039
152295
  if (this.currentLayout === "fleet-vteam" && agentId !== "architect") return;
152040
152296
  const agents = getLayout(this.currentLayout).agents;
152041
152297
  const agent = agents.find((a) => a.id === agentId);
@@ -152123,6 +152379,10 @@ WARNING: This link could potentially be dangerous`)) {
152123
152379
  console.log("[OfficeScene] Fleet complete!");
152124
152380
  }, this);
152125
152381
  this.game.events.on("game:panel:clicked", () => {
152382
+ if (this.isPortraitDashboardMode) {
152383
+ this.inputManager.switchToNone("game:panel:clicked mobile lock");
152384
+ return;
152385
+ }
152126
152386
  debugLog(this, `game:panel:clicked \u2014 blurring terminal`);
152127
152387
  this.terminalOverlay.blurTerminal();
152128
152388
  if (this.playerInScene) {
@@ -152143,6 +152403,7 @@ WARNING: This link could potentially be dangerous`)) {
152143
152403
  this.playerMovementEnabled = true;
152144
152404
  }
152145
152405
  }, this);
152406
+ this.game.events.on("layout:change", this.handleLayoutChange, this);
152146
152407
  this.input.on("pointerup", (_pointer, currentlyOver) => {
152147
152408
  if (this.cameraDrag?.wasDragging()) return;
152148
152409
  const clickedNPC = currentlyOver.find((go) => go instanceof NPC);
@@ -152150,6 +152411,13 @@ WARNING: This link could potentially be dangerous`)) {
152150
152411
  this.startConversation(clickedNPC.config);
152151
152412
  return;
152152
152413
  }
152414
+ const clickedPcTerminal = this.desks.some(
152415
+ (desk) => desk.agentId === PC_TERMINAL_ID && currentlyOver.includes(desk.sprite)
152416
+ );
152417
+ if (clickedPcTerminal) {
152418
+ this.openPlayerPcTerminal();
152419
+ return;
152420
+ }
152153
152421
  if (this.currentLayout === "default") {
152154
152422
  for (const desk of this.desks) {
152155
152423
  if (!desk.agentId.startsWith("unassigned-")) continue;
@@ -152214,6 +152482,7 @@ WARNING: This link could potentially be dangerous`)) {
152214
152482
  this.bgMusic?.stop();
152215
152483
  this.game.events.off("bgm:volume");
152216
152484
  this.game.events.off("bgm:mute");
152485
+ this.game.events.off("layout:change", this.handleLayoutChange, this);
152217
152486
  this.disposeFleetPipeline();
152218
152487
  this.game.events.off("zoom:change");
152219
152488
  this.cameraDrag?.destroy();
@@ -152330,9 +152599,11 @@ WARNING: This link could potentially be dangerous`)) {
152330
152599
  laptop.setDepth(ySortDepth(deskY, worldH) + 0.1);
152331
152600
  this.desks.push({ sprite: desk, agentId: agent.id, x: deskX, y: deskY, laptopSprite: laptop, laptopDirection: dir });
152332
152601
  };
152602
+ const leftTableAgent = AGENTS.find((a) => a.position.x === 4 && a.position.y === 3);
152603
+ const rightTableAgent = AGENTS.find((a) => a.position.x === 13 && a.position.y === 3);
152333
152604
  const communalTables = [
152334
- { startCol: 4, agent: AGENTS[0] },
152335
- { startCol: 13, agent: AGENTS[2] }
152605
+ { startCol: 4, agent: leftTableAgent },
152606
+ { startCol: 13, agent: rightTableAgent }
152336
152607
  ];
152337
152608
  const tableStartRow = 4;
152338
152609
  communalTables.forEach((table) => {
@@ -152399,7 +152670,8 @@ WARNING: This link could potentially be dangerous`)) {
152399
152670
  y: sideStoolY
152400
152671
  });
152401
152672
  });
152402
- [AGENTS[1], AGENTS[3]].filter(Boolean).forEach((agent) => {
152673
+ const cornerAgents = AGENTS.filter((agent) => agent.position.y >= 8);
152674
+ cornerAgents.forEach((agent) => {
152403
152675
  const deskX = agent.position.x * this.tileSize + this.tileSize / 2;
152404
152676
  const deskY = (agent.position.y + 1) * this.tileSize + this.tileSize / 2;
152405
152677
  placeAgentDesk(agent, deskX, deskY);
@@ -152418,6 +152690,13 @@ WARNING: This link could potentially be dangerous`)) {
152418
152690
  }
152419
152691
  const bossPC = addDecor(bossDeskX, bossDeskY - 2 * scale, "desktop_pc");
152420
152692
  bossPC.setDepth(ySortDepth(bossDeskY, worldH) + 0.1);
152693
+ bossPC.setInteractive({ useHandCursor: true, pixelPerfect: false });
152694
+ this.desks.push({
152695
+ sprite: bossPC,
152696
+ agentId: PC_TERMINAL_ID,
152697
+ x: bossDeskX,
152698
+ y: bossDeskY - 2 * scale
152699
+ });
152421
152700
  addDecor(bossDeskX, bossDeskY + this.tileSize, "chair").setDepth(ySortDepth(bossDeskY + this.tileSize + 16 * scale, worldH));
152422
152701
  if (ENABLE_DECORATIONS) {
152423
152702
  addDecor(2 * this.tileSize + this.tileSize / 2, 2 * this.tileSize + this.tileSize / 2, "plant");
@@ -153317,6 +153596,9 @@ WARNING: This link could potentially be dangerous`)) {
153317
153596
  }
153318
153597
  }
153319
153598
  update() {
153599
+ if (this.isPortraitDashboardMode) {
153600
+ return;
153601
+ }
153320
153602
  if (!this.playerInScene || this.basketballGame.getIsVisible() || this.galaxianGame.getIsVisible() || !this.playerMovementEnabled) {
153321
153603
  return;
153322
153604
  }
@@ -153336,6 +153618,10 @@ WARNING: This link could potentially be dangerous`)) {
153336
153618
  this.updateExitDoorProximity();
153337
153619
  if (import_phaser8.default.Input.Keyboard.JustDown(this.interactKey)) {
153338
153620
  if (this.terminalOverlay.getIsVisible()) {
153621
+ if (this.nearestDesk?.agentId === PC_TERMINAL_ID) {
153622
+ this.openPlayerPcTerminal();
153623
+ return;
153624
+ }
153339
153625
  const targetAgent = this.nearestNPC?.config ?? (this.nearestDesk ? AGENTS.find((a) => a.id === this.nearestDesk.agentId) : null) ?? null;
153340
153626
  if (targetAgent) {
153341
153627
  this.startConversation(targetAgent);
@@ -153349,6 +153635,10 @@ WARNING: This link could potentially be dangerous`)) {
153349
153635
  } else if (this.nearestNPC) {
153350
153636
  this.startConversation(this.nearestNPC.config);
153351
153637
  } else if (this.nearestDesk) {
153638
+ if (this.nearestDesk.agentId === PC_TERMINAL_ID) {
153639
+ this.openPlayerPcTerminal();
153640
+ return;
153641
+ }
153352
153642
  const agent = AGENTS.find((a) => a.id === this.nearestDesk.agentId);
153353
153643
  if (agent) {
153354
153644
  this.startConversation(agent);
@@ -153583,6 +153873,37 @@ WARNING: This link could potentially be dangerous`)) {
153583
153873
  }
153584
153874
  );
153585
153875
  }
153876
+ openPlayerPcTerminal() {
153877
+ if (this.currentLayout !== "default") return;
153878
+ const workingDir = officeManager.getCurrentWorkingDirectory();
153879
+ const pcTerminalConfig = {
153880
+ id: PC_TERMINAL_ID,
153881
+ name: "PC TERMINAL",
153882
+ skill: "general",
153883
+ sprite: "desktop_pc",
153884
+ color: 6138367,
153885
+ position: { x: 10, y: 2 },
153886
+ greeting: "PC terminal ready.",
153887
+ description: "Local Shell",
153888
+ workingDir
153889
+ };
153890
+ this.playerMovementEnabled = false;
153891
+ if (this.playerInScene) {
153892
+ this.player.disableMovement();
153893
+ }
153894
+ this.cameraDrag?.disable();
153895
+ this.terminalOverlay.show(
153896
+ pcTerminalConfig,
153897
+ () => {
153898
+ this.playerMovementEnabled = true;
153899
+ if (this.playerInScene) {
153900
+ this.player.enableMovement();
153901
+ }
153902
+ this.applyZoom(this.cameras.main.zoom);
153903
+ },
153904
+ { launchMode: "shell" }
153905
+ );
153906
+ }
153586
153907
  enterMeeting() {
153587
153908
  this.playerMovementEnabled = false;
153588
153909
  if (this.playerInScene) {
@@ -154252,6 +154573,21 @@ WARNING: This link could potentially be dangerous`)) {
154252
154573
  }
154253
154574
  });
154254
154575
 
154576
+ // src/config/responsiveLayout.ts
154577
+ function computeResponsiveLayout(width, height) {
154578
+ const safeHeight = Math.max(1, height);
154579
+ const ratio = width / safeHeight;
154580
+ return ratio <= PORTRAIT_RATIO_THRESHOLD || width <= PORTRAIT_WIDTH_THRESHOLD_PX ? "portrait-dashboard" : "default";
154581
+ }
154582
+ var PORTRAIT_RATIO_THRESHOLD, PORTRAIT_WIDTH_THRESHOLD_PX;
154583
+ var init_responsiveLayout = __esm({
154584
+ "src/config/responsiveLayout.ts"() {
154585
+ "use strict";
154586
+ PORTRAIT_RATIO_THRESHOLD = 0.9;
154587
+ PORTRAIT_WIDTH_THRESHOLD_PX = 600;
154588
+ }
154589
+ });
154590
+
154255
154591
  // src/ui/ToastNotification.ts
154256
154592
  var MAX_VISIBLE, AUTO_DISMISS_MS, ANIMATION_MS, RATE_LIMIT_WINDOW_MS, RATE_LIMIT_MAX, ToastNotificationManager;
154257
154593
  var init_ToastNotification = __esm({
@@ -155116,6 +155452,7 @@ WARNING: This link could potentially be dangerous`)) {
155116
155452
  init_MeetingScene();
155117
155453
  init_officeManager();
155118
155454
  init_agents();
155455
+ init_responsiveLayout();
155119
155456
  init_layouts();
155120
155457
  init_ToastNotification();
155121
155458
  init_NotificationService();
@@ -155149,6 +155486,7 @@ WARNING: This link could potentially be dangerous`)) {
155149
155486
  var debugMode = false;
155150
155487
  var currentZoom = parseFloat(localStorage.getItem("agencyOffice:zoomLevel") ?? "0.8");
155151
155488
  currentZoom = isNaN(currentZoom) || currentZoom < 0.5 || currentZoom > 2 ? 0.8 : currentZoom;
155489
+ var RESIZE_DEBOUNCE_MS = 200;
155152
155490
  var agentPreloadStatus = /* @__PURE__ */ new Map();
155153
155491
  var pendingStatusBarUpdate = false;
155154
155492
  var pendingTerminalContentUpdate = false;
@@ -155214,6 +155552,61 @@ WARNING: This link could potentially be dangerous`)) {
155214
155552
  position: relative;
155215
155553
  `;
155216
155554
  mainContent.appendChild(terminalPanel);
155555
+ var currentResponsiveLayout = "default";
155556
+ var resizeDebounceTimer = null;
155557
+ function isMobileModeActive() {
155558
+ return currentResponsiveLayout === "portrait-dashboard";
155559
+ }
155560
+ function applyMobileTopBarVisibility() {
155561
+ const hidden = isMobileModeActive();
155562
+ const ids = ["zoom-bar", "sprite-customizer-btn", "debug-toggle-btn"];
155563
+ for (const id of ids) {
155564
+ const el = document.getElementById(id);
155565
+ if (!el) continue;
155566
+ el.style.display = hidden ? "none" : "";
155567
+ }
155568
+ }
155569
+ function applyResponsiveLayout(layoutKey) {
155570
+ if (layoutKey === currentResponsiveLayout) return;
155571
+ currentResponsiveLayout = layoutKey;
155572
+ if (layoutKey === "portrait-dashboard") {
155573
+ officePanel.style.display = "none";
155574
+ terminalPanel.style.width = "100%";
155575
+ terminalPanel.style.borderLeft = "none";
155576
+ } else {
155577
+ officePanel.style.display = "";
155578
+ terminalPanel.style.width = "50%";
155579
+ terminalPanel.style.borderLeft = "2px solid #333";
155580
+ }
155581
+ if (phaserGameRef) {
155582
+ phaserGameRef.events.emit("layout:change", { layoutKey });
155583
+ if (layoutKey === "default") {
155584
+ const width = officePanel.clientWidth || window.innerWidth / 2;
155585
+ const height = officePanel.clientHeight || window.innerHeight;
155586
+ phaserGameRef.scale.resize(width, height);
155587
+ }
155588
+ }
155589
+ applyMobileTopBarVisibility();
155590
+ }
155591
+ function onWindowResize() {
155592
+ if (resizeDebounceTimer !== null) {
155593
+ window.clearTimeout(resizeDebounceTimer);
155594
+ }
155595
+ resizeDebounceTimer = window.setTimeout(() => {
155596
+ const next = computeResponsiveLayout(window.innerWidth, window.innerHeight);
155597
+ applyResponsiveLayout(next);
155598
+ if (phaserGameRef && currentResponsiveLayout === "default") {
155599
+ const width = officePanel.clientWidth || window.innerWidth / 2;
155600
+ const height = officePanel.clientHeight || window.innerHeight;
155601
+ phaserGameRef.scale.resize(width, height);
155602
+ }
155603
+ }, RESIZE_DEBOUNCE_MS);
155604
+ }
155605
+ applyResponsiveLayout(computeResponsiveLayout(window.innerWidth, window.innerHeight));
155606
+ window.addEventListener("resize", onWindowResize);
155607
+ if (typeof window !== "undefined") {
155608
+ window.__copilotOfficeMobileModeActive = isMobileModeActive;
155609
+ }
155217
155610
  function renderOfficeTabs() {
155218
155611
  const offices = officeManager.getAllOffices();
155219
155612
  const currentId = officeManager.currentOfficeId;
@@ -155360,7 +155753,9 @@ WARNING: This link could potentially be dangerous`)) {
155360
155753
  debugMode = !debugMode;
155361
155754
  phaserGame?.events.emit("debug:toggle", debugMode);
155362
155755
  renderOfficeTabs();
155363
- phaserGame?.events.emit("game:panel:clicked");
155756
+ if (!isMobileModeActive()) {
155757
+ phaserGame?.events.emit("game:panel:clicked");
155758
+ }
155364
155759
  console.log(`[Debug] Debug mode ${debugMode ? "ON" : "OFF"}`);
155365
155760
  });
155366
155761
  const zoomSlider = document.getElementById("zoom-slider");
@@ -155396,6 +155791,7 @@ WARNING: This link could potentially be dangerous`)) {
155396
155791
  spriteCustomizerPanel.updatePreview(base64);
155397
155792
  }
155398
155793
  });
155794
+ applyMobileTopBarVisibility();
155399
155795
  }
155400
155796
  function switchToOffice(officeId) {
155401
155797
  if (phaserGame?.registry.get("animating")) {
@@ -155821,6 +156217,19 @@ WARNING: This link could potentially be dangerous`)) {
155821
156217
  ctx.drawImage(source, 0, 0);
155822
156218
  }
155823
156219
  }
156220
+ const pcCanvas = document.getElementById("overview-sprite-pc-terminal");
156221
+ if (pcCanvas) {
156222
+ const ctx = pcCanvas.getContext("2d");
156223
+ if (!ctx) return;
156224
+ const texture = phaserGameRef.textures.get("desktop_pc");
156225
+ if (!texture || texture.key === "__MISSING") return;
156226
+ const source = texture.getSourceImage();
156227
+ if (source) {
156228
+ ctx.imageSmoothingEnabled = false;
156229
+ ctx.clearRect(0, 0, pcCanvas.width, pcCanvas.height);
156230
+ ctx.drawImage(source, 0, 0);
156231
+ }
156232
+ }
155824
156233
  }, 50);
155825
156234
  }
155826
156235
  function setupTerminalClickHandler() {
@@ -156241,11 +156650,13 @@ WARNING: This link could potentially be dangerous`)) {
156241
156650
  canvas?.focus();
156242
156651
  });
156243
156652
  officePanel.addEventListener("mousedown", () => {
156653
+ if (isMobileModeActive()) return;
156244
156654
  console.log("[main] game panel mousedown \u2014 emitting game:panel:clicked");
156245
156655
  phaserGame?.events.emit("game:panel:clicked");
156246
156656
  });
156247
156657
  phaserGame.events.once("ready", () => {
156248
156658
  drawOverviewSprites();
156659
+ phaserGame.events.emit("layout:change", { layoutKey: currentResponsiveLayout });
156249
156660
  });
156250
156661
  window.addEventListener("focus", () => {
156251
156662
  catchUpStatusViews("window focus");