@spotpatch/runtime 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1050,8 +1050,7 @@ function unionRects(rects) {
1050
1050
  height: bottom - top
1051
1051
  });
1052
1052
  }
1053
- function getElementRect(element2, view) {
1054
- const display = view.getComputedStyle(element2).display;
1053
+ function measureElementRect(element2, display) {
1055
1054
  if (display.startsWith("inline")) {
1056
1055
  const lineBoxRect = unionRects(Array.from(element2.getClientRects()));
1057
1056
  if (lineBoxRect !== void 0) {
@@ -1060,6 +1059,17 @@ function getElementRect(element2, view) {
1060
1059
  }
1061
1060
  return toElementRect(element2.getBoundingClientRect());
1062
1061
  }
1062
+ function getElementRect(element2, view) {
1063
+ return measureElementRect(element2, view.getComputedStyle(element2).display);
1064
+ }
1065
+ function getVisibleElementRect(element2, view) {
1066
+ const style = view.getComputedStyle(element2);
1067
+ if (style.display === "none" || style.visibility === "hidden") {
1068
+ return void 0;
1069
+ }
1070
+ const rect = measureElementRect(element2, style.display);
1071
+ return rect.width > 0 && rect.height > 0 ? rect : void 0;
1072
+ }
1063
1073
 
1064
1074
  // src/ui/ui-constants.ts
1065
1075
  var UI_MARKER_ATTRIBUTE = "data-spotpatch-ui";
@@ -1077,12 +1087,7 @@ function isInsideSpotPatchUI(element2) {
1077
1087
  return root instanceof ShadowRoot && root.host.hasAttribute(UI_MARKER_ATTRIBUTE);
1078
1088
  }
1079
1089
  function hasVisibleArea(element2, view) {
1080
- const style = view.getComputedStyle(element2);
1081
- if (style.display === "none" || style.visibility === "hidden") {
1082
- return false;
1083
- }
1084
- const rect = element2.getBoundingClientRect();
1085
- return rect.width > 0 && rect.height > 0;
1090
+ return getVisibleElementRect(element2, view) !== void 0;
1086
1091
  }
1087
1092
  function isDocumentRoot(element2) {
1088
1093
  return element2.tagName === "HTML" || element2.tagName === "BODY";
@@ -1695,7 +1700,7 @@ function createButton(document, label, className = "") {
1695
1700
  // src/ui/agent-panel.ts
1696
1701
  var AGENT_PANEL_STYLES = `
1697
1702
  .spotpatch-agent {
1698
- margin-top: 14px;
1703
+ margin-top: 10px;
1699
1704
  overflow: hidden;
1700
1705
  border: 1px solid var(--spotpatch-border-subtle);
1701
1706
  border-radius: var(--spotpatch-radius-card);
@@ -1705,36 +1710,36 @@ var AGENT_PANEL_STYLES = `
1705
1710
  display: flex;
1706
1711
  align-items: center;
1707
1712
  justify-content: space-between;
1708
- gap: 12px;
1709
- padding: 14px 16px;
1713
+ gap: 10px;
1714
+ padding: 10px 12px;
1710
1715
  border-bottom: 1px solid rgb(255 255 255 / 7%);
1711
1716
  }
1712
- .spotpatch-agent-title { color: #eef0f5; font-size: 16px; font-weight: 680; }
1717
+ .spotpatch-agent-title { color: #eef0f5; font-size: 13px; font-weight: 650; }
1713
1718
  .spotpatch-agent-badge {
1714
1719
  border: 1px solid rgb(129 112 247 / 24%);
1715
1720
  border-radius: 999px;
1716
1721
  padding: 3px 7px;
1717
1722
  color: #c5cafa;
1718
1723
  background: rgb(109 93 246 / 9%);
1719
- font-size: 11px;
1724
+ font-size: 10px;
1720
1725
  font-weight: 650;
1721
1726
  }
1722
- .spotpatch-agent-setup { padding: 18px; }
1723
- .spotpatch-agent-selectors { display: grid; grid-template-columns: 1fr; gap: 15px; }
1724
- .spotpatch-agent-selectors label { min-width: 0; color: var(--spotpatch-text-secondary); font-size: 14px; font-weight: 580; }
1727
+ .spotpatch-agent-setup { padding: 12px; }
1728
+ .spotpatch-agent-selectors { display: grid; grid-template-columns: 1fr; gap: 10px; }
1729
+ .spotpatch-agent-selectors label { min-width: 0; color: var(--spotpatch-text-secondary); font-size: 11.5px; font-weight: 580; }
1725
1730
  .spotpatch-agent select {
1726
1731
  box-sizing: border-box;
1727
1732
  width: 100%;
1728
1733
  min-width: 0;
1729
- min-height: 46px;
1730
- margin-top: 7px;
1734
+ min-height: 34px;
1735
+ margin-top: 4px;
1731
1736
  border: 1px solid var(--spotpatch-border);
1732
- border-radius: 12px;
1733
- padding: 10px 38px 10px 13px;
1737
+ border-radius: 8px;
1738
+ padding: 7px 32px 7px 9px;
1734
1739
  color: #e8ebf2;
1735
1740
  color-scheme: dark;
1736
1741
  background: linear-gradient(180deg, rgb(255 255 255 / 4%), rgb(255 255 255 / 2%));
1737
- font-size: 15px;
1742
+ font-size: 12px;
1738
1743
  font-weight: 560;
1739
1744
  line-height: 1.35;
1740
1745
  outline: none;
@@ -1746,7 +1751,7 @@ var AGENT_PANEL_STYLES = `
1746
1751
  @supports (appearance: base-select) {
1747
1752
  .spotpatch-agent select,
1748
1753
  ::picker(select) { appearance: base-select; }
1749
- .spotpatch-agent select { padding: 10px 13px; }
1754
+ .spotpatch-agent select { padding: 7px 9px; }
1750
1755
  .spotpatch-agent select::picker-icon {
1751
1756
  color: #9da6b5;
1752
1757
  transition: rotate 180ms cubic-bezier(.2, .8, .2, 1);
@@ -1793,24 +1798,24 @@ var AGENT_PANEL_STYLES = `
1793
1798
  .spotpatch-consent {
1794
1799
  display: flex;
1795
1800
  align-items: flex-start;
1796
- gap: 10px;
1797
- margin-top: 16px;
1801
+ gap: 8px;
1802
+ margin-top: 10px;
1798
1803
  color: var(--spotpatch-text-secondary);
1799
1804
  cursor: pointer;
1800
- font-size: 14px;
1801
- line-height: 1.6;
1805
+ font-size: 11.5px;
1806
+ line-height: 1.5;
1802
1807
  }
1803
- .spotpatch-consent input { width: 16px; height: 16px; flex: none; margin: 3px 0 0; accent-color: var(--spotpatch-accent); }
1808
+ .spotpatch-consent input { width: 14px; height: 14px; flex: none; margin: 2px 0 0; accent-color: var(--spotpatch-accent); }
1804
1809
  .spotpatch-workspace-consent {
1805
- margin-top: 12px;
1810
+ margin-top: 9px;
1806
1811
  border: 1px solid rgb(251 191 36 / 18%);
1807
1812
  border-radius: 10px;
1808
- padding: 11px 12px;
1813
+ padding: 9px 10px;
1809
1814
  background: rgb(120 53 15 / 9%);
1810
1815
  }
1811
- .spotpatch-workspace-consent strong { display: block; color: #fde68a; font-size: 13px; font-weight: 620; }
1812
- .spotpatch-workspace-consent small { display: block; margin-top: 2px; color: #aeb6c4; font-size: 12px; line-height: 1.5; }
1813
- .spotpatch-agent-health-list { display: grid; gap: 8px; margin-top: 14px; }
1816
+ .spotpatch-workspace-consent strong { display: block; color: #fde68a; font-size: 11.5px; font-weight: 620; }
1817
+ .spotpatch-workspace-consent small { display: block; margin-top: 2px; color: #aeb6c4; font-size: 10.5px; line-height: 1.45; }
1818
+ .spotpatch-agent-health-list { display: grid; gap: 6px; margin-top: 10px; }
1814
1819
  .spotpatch-agent-workspace,
1815
1820
  .spotpatch-agent-capability {
1816
1821
  display: flex;
@@ -1818,7 +1823,7 @@ var AGENT_PANEL_STYLES = `
1818
1823
  gap: 8px;
1819
1824
  margin: 0;
1820
1825
  color: #929bab;
1821
- font-size: 13px;
1826
+ font-size: 11px;
1822
1827
  }
1823
1828
  .spotpatch-agent-capability::before {
1824
1829
  width: 6px;
@@ -1848,7 +1853,7 @@ var AGENT_PANEL_STYLES = `
1848
1853
  .spotpatch-agent-workspace[data-state="consent-required"]::before { background: #fbbf24; }
1849
1854
  .spotpatch-agent-workspace[data-state="blocked"] { color: #fecaca; }
1850
1855
  .spotpatch-agent-workspace[data-state="blocked"]::before { background: var(--spotpatch-danger); }
1851
- .spotpatch-agent-job { padding: 16px; }
1856
+ .spotpatch-agent-job { padding: 12px; }
1852
1857
  .spotpatch-agent-job-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
1853
1858
  .spotpatch-agent-model { min-width: 0; overflow: hidden; color: #d6dafe; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }
1854
1859
  .spotpatch-agent-status {
@@ -1990,11 +1995,7 @@ function createAgentPanel(document, ai, localizer) {
1990
1995
  job.append(jobMeta, phase, error, activity, resultPanel);
1991
1996
  root.append(header, setup, job);
1992
1997
  const testButton = createButton(document, messages.agent.testConnection);
1993
- const runButton = createButton(
1994
- document,
1995
- messages.agent.verifyAndRun,
1996
- "spotpatch-run"
1997
- );
1998
+ const runButton = createButton(document, messages.agent.run, "spotpatch-run");
1998
1999
  const cancelButton = createButton(document, messages.agent.cancel);
1999
2000
  const applyButton = createButton(document, messages.agent.apply, "spotpatch-primary");
2000
2001
  const revertButton = createButton(document, messages.agent.revert);
@@ -2039,7 +2040,7 @@ function createAgentPanel(document, ai, localizer) {
2039
2040
  };
2040
2041
  const refreshActions = () => {
2041
2042
  const setupVisible = ai.enabled && selectionVisible && !jobPresented;
2042
- runButton.textContent = capabilityProbing ? messages.agent.verifying : capabilityReady ? messages.agent.run : messages.agent.verifyAndRun;
2043
+ runButton.textContent = capabilityProbing ? messages.agent.verifying : messages.agent.run;
2043
2044
  runButton.classList.toggle("spotpatch-primary", capabilityReady);
2044
2045
  testButton.hidden = !setupVisible;
2045
2046
  runButton.hidden = !setupVisible;
@@ -2394,6 +2395,25 @@ function calculateDialogPlacement({
2394
2395
  }) {
2395
2396
  const maxLeft = viewportWidth - dialogWidth - VIEWPORT_MARGIN;
2396
2397
  const maxTop = viewportHeight - dialogHeight - VIEWPORT_MARGIN;
2398
+ const viewportLeft = clamp(
2399
+ (viewportWidth - dialogWidth) / 2,
2400
+ VIEWPORT_MARGIN,
2401
+ maxLeft
2402
+ );
2403
+ const viewportTop = clamp(
2404
+ (viewportHeight - dialogHeight) / 2,
2405
+ VIEWPORT_MARGIN,
2406
+ maxTop
2407
+ );
2408
+ if (target2 === void 0) {
2409
+ return Object.freeze({
2410
+ anchorX: clamp(dialogWidth / 2, ANCHOR_INSET, dialogWidth - ANCHOR_INSET),
2411
+ anchorY: clamp(dialogHeight / 2, ANCHOR_INSET, dialogHeight - ANCHOR_INSET),
2412
+ left: viewportLeft,
2413
+ mode: "viewport",
2414
+ top: viewportTop
2415
+ });
2416
+ }
2397
2417
  const targetCenterX = target2.x + target2.width / 2;
2398
2418
  const targetCenterY = target2.y + target2.height / 2;
2399
2419
  const centeredLeft = clamp(targetCenterX - dialogWidth / 2, VIEWPORT_MARGIN, maxLeft);
@@ -2472,7 +2492,7 @@ var ERROR_MESSAGES_EN = Object.freeze({
2472
2492
  [ERROR_CODES2.PROVIDER_AUTH_FAILED]: "The provider rejected authentication. Check the server-side Key.",
2473
2493
  [ERROR_CODES2.PROVIDER_PROTOCOL_UNSUPPORTED]: "The relay does not match the configured OpenAI-compatible protocol.",
2474
2494
  [ERROR_CODES2.MODEL_NOT_ALLOWED]: "The selected model profile is not allowed.",
2475
- [ERROR_CODES2.MODEL_TOOL_CALL_UNSUPPORTED]: "The selected model did not complete the required tool-call probe.",
2495
+ [ERROR_CODES2.MODEL_TOOL_CALL_UNSUPPORTED]: "The selected model did not start or continue the required tool call.",
2476
2496
  [ERROR_CODES2.PROVIDER_RATE_LIMITED]: "The provider is rate limited. Wait and try again.",
2477
2497
  [ERROR_CODES2.AGENT_BUSY]: "Another write Agent job is still active.",
2478
2498
  [ERROR_CODES2.AGENT_LIMIT_EXCEEDED]: "The Agent stopped at a configured time, turn, output, or size limit.",
@@ -2507,7 +2527,7 @@ var ERROR_MESSAGES_ZH = Object.freeze({
2507
2527
  [ERROR_CODES2.PROVIDER_AUTH_FAILED]: "\u6A21\u578B\u670D\u52A1\u9274\u6743\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u670D\u52A1\u7AEF Key\u3002",
2508
2528
  [ERROR_CODES2.PROVIDER_PROTOCOL_UNSUPPORTED]: "\u4E2D\u8F6C\u670D\u52A1\u4E0E\u914D\u7F6E\u7684 OpenAI \u517C\u5BB9\u534F\u8BAE\u4E0D\u4E00\u81F4\u3002",
2509
2529
  [ERROR_CODES2.MODEL_NOT_ALLOWED]: "\u5F53\u524D\u6A21\u578B\u914D\u7F6E\u672A\u83B7\u6388\u6743\u3002",
2510
- [ERROR_CODES2.MODEL_TOOL_CALL_UNSUPPORTED]: "\u5F53\u524D\u6A21\u578B\u672A\u901A\u8FC7\u5FC5\u8981\u7684\u5DE5\u5177\u8C03\u7528\u80FD\u529B\u63A2\u6D4B\u3002",
2530
+ [ERROR_CODES2.MODEL_TOOL_CALL_UNSUPPORTED]: "\u5F53\u524D\u6A21\u578B\u672A\u5B8C\u6210\u5FC5\u8981\u7684\u5DE5\u5177\u8C03\u7528\u6216\u7ED3\u679C\u7EED\u63A5\u3002",
2511
2531
  [ERROR_CODES2.PROVIDER_RATE_LIMITED]: "\u6A21\u578B\u670D\u52A1\u6B63\u5728\u9650\u6D41\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
2512
2532
  [ERROR_CODES2.AGENT_BUSY]: "\u5F53\u524D\u9879\u76EE\u5DF2\u6709\u4E00\u4E2A\u5199\u5165\u4EFB\u52A1\u6B63\u5728\u8FD0\u884C\u3002",
2513
2533
  [ERROR_CODES2.AGENT_LIMIT_EXCEEDED]: "Agent \u8FBE\u5230\u65F6\u95F4\u3001\u8F6E\u6B21\u3001\u8F93\u51FA\u6216\u53D8\u66F4\u89C4\u6A21\u9650\u5236\u3002",
@@ -2687,7 +2707,7 @@ var UI_MESSAGES = Object.freeze({
2687
2707
  modelAriaLabel: "AI model",
2688
2708
  providerUnavailable: "Provider configuration is unavailable.",
2689
2709
  consent: (provider) => `I understand selected context and allowed source may be sent to ${provider}; its data policy is my responsibility.`,
2690
- connectionNotTested: "Connection not tested",
2710
+ connectionNotTested: "Optional connection check not run",
2691
2711
  workspaceNotChecked: "Local workspace not checked",
2692
2712
  checkingWorkspace: "Checking Git workspace and isolated execution\u2026",
2693
2713
  workspaceReady: "Local workspace is ready for isolated execution",
@@ -2704,7 +2724,6 @@ var UI_MESSAGES = Object.freeze({
2704
2724
  consentRequired: "Confirm remote provider data transmission before running AI.",
2705
2725
  toolsReady: "tools and streaming ready",
2706
2726
  testConnection: "Check environment",
2707
- verifyAndRun: "Verify & run",
2708
2727
  verifying: "Verifying\u2026",
2709
2728
  run: "Run AI",
2710
2729
  cancel: "Cancel agent",
@@ -2823,7 +2842,7 @@ var UI_MESSAGES = Object.freeze({
2823
2842
  modelAriaLabel: "AI \u6A21\u578B",
2824
2843
  providerUnavailable: "\u6A21\u578B\u670D\u52A1\u914D\u7F6E\u4E0D\u53EF\u7528\u3002",
2825
2844
  consent: (provider) => `\u6211\u4E86\u89E3\u9009\u4E2D\u4E0A\u4E0B\u6587\u4E0E\u83B7\u51C6\u6E90\u7801\u53EF\u80FD\u53D1\u9001\u5230 ${provider}\uFF0C\u5E76\u81EA\u884C\u8D1F\u8D23\u5176\u6570\u636E\u7B56\u7565\u3002`,
2826
- connectionNotTested: "\u5C1A\u672A\u6D4B\u8BD5\u8FDE\u63A5",
2845
+ connectionNotTested: "\u5C1A\u672A\u6267\u884C\u53EF\u9009\u8FDE\u63A5\u68C0\u67E5",
2827
2846
  workspaceNotChecked: "\u5C1A\u672A\u68C0\u67E5\u672C\u5730\u5DE5\u4F5C\u533A",
2828
2847
  checkingWorkspace: "\u6B63\u5728\u68C0\u67E5 Git \u5DE5\u4F5C\u533A\u4E0E\u9694\u79BB\u6267\u884C\u73AF\u5883\u2026\u2026",
2829
2848
  workspaceReady: "\u672C\u5730\u5DE5\u4F5C\u533A\u5DF2\u6EE1\u8DB3\u9694\u79BB\u6267\u884C\u6761\u4EF6",
@@ -2840,7 +2859,6 @@ var UI_MESSAGES = Object.freeze({
2840
2859
  consentRequired: "\u8FD0\u884C AI \u524D\uFF0C\u8BF7\u5148\u786E\u8BA4\u5141\u8BB8\u5411\u8FDC\u7A0B\u6A21\u578B\u670D\u52A1\u4F20\u8F93\u6570\u636E\u3002",
2841
2860
  toolsReady: "\u5DE5\u5177\u8C03\u7528\u4E0E\u6D41\u5F0F\u54CD\u5E94\u5DF2\u5C31\u7EEA",
2842
2861
  testConnection: "\u68C0\u67E5\u8FD0\u884C\u73AF\u5883",
2843
- verifyAndRun: "\u9A8C\u8BC1\u5E76\u8FD0\u884C",
2844
2862
  verifying: "\u9A8C\u8BC1\u4E2D\u2026\u2026",
2845
2863
  run: "\u8FD0\u884C AI",
2846
2864
  cancel: "\u53D6\u6D88 Agent",
@@ -2926,33 +2944,36 @@ function createUiLocalizer(document, preference = "auto") {
2926
2944
  }
2927
2945
 
2928
2946
  // src/ui/runtime-view.ts
2929
- var DIALOG_FALLBACK_WIDTH = 560;
2947
+ var DIALOG_MAX_WIDTH = 460;
2948
+ var DIALOG_MAX_HEIGHT = 620;
2930
2949
  var DIALOG_FALLBACK_HEIGHT = Object.freeze({
2931
- previewing: 640,
2932
- selected: 720
2950
+ previewing: 560,
2951
+ selected: DIALOG_MAX_HEIGHT
2933
2952
  });
2934
2953
  function createStyles(document) {
2935
2954
  const style = document.createElement("style");
2936
2955
  style.textContent = `
2937
2956
  :host {
2938
2957
  all: initial;
2939
- --spotpatch-bg: #11141a;
2940
- --spotpatch-bg-raised: #191d25;
2941
- --spotpatch-bg-input: #0c0f14;
2942
- --spotpatch-border: #303641;
2943
- --spotpatch-border-subtle: #262c35;
2944
- --spotpatch-text: #f4f6fb;
2945
- --spotpatch-text-secondary: #a4adbd;
2946
- --spotpatch-text-muted: #7f899a;
2947
- --spotpatch-accent: #7060ee;
2948
- --spotpatch-accent-strong: #604ee8;
2949
- --spotpatch-accent-cyan: #27b8cf;
2958
+ --spotpatch-bg: #0e0e12;
2959
+ --spotpatch-bg-raised: #17171c;
2960
+ --spotpatch-bg-active: #1c1c22;
2961
+ --spotpatch-bg-input: #0b0b0f;
2962
+ --spotpatch-border: #2a2a32;
2963
+ --spotpatch-border-subtle: #232329;
2964
+ --spotpatch-text: #f2f2f5;
2965
+ --spotpatch-text-secondary: #96969f;
2966
+ --spotpatch-text-muted: #686872;
2967
+ --spotpatch-accent: #8b7bff;
2968
+ --spotpatch-accent-strong: #6a5ce8;
2969
+ --spotpatch-accent-cyan: #52a8ff;
2950
2970
  --spotpatch-danger: #fb7185;
2951
2971
  --spotpatch-success: #34d399;
2952
2972
  --spotpatch-warning: #f59e0b;
2953
- --spotpatch-radius-panel: 24px;
2954
- --spotpatch-radius-card: 15px;
2955
- --spotpatch-shadow-panel: 0 28px 72px rgb(0 0 0 / 38%);
2973
+ --spotpatch-text-on-accent: #0b0b12;
2974
+ --spotpatch-radius-panel: 16px;
2975
+ --spotpatch-radius-card: 10px;
2976
+ --spotpatch-shadow-panel: 0 30px 60px -20px rgb(0 0 0 / 70%);
2956
2977
  color-scheme: dark;
2957
2978
  color: var(--spotpatch-text);
2958
2979
  font-family: Inter, "SF Pro Display", "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
@@ -3072,7 +3093,7 @@ function createStyles(document) {
3072
3093
  left: 16px;
3073
3094
  z-index: ${String(UI_Z_INDEX.controls)};
3074
3095
  box-sizing: border-box;
3075
- width: min(560px, calc(100vw - 32px));
3096
+ width: min(${String(DIALOG_MAX_WIDTH)}px, calc(100vw - 32px));
3076
3097
  color: #edf0f7;
3077
3098
  outline: none;
3078
3099
  filter: drop-shadow(var(--spotpatch-shadow-panel));
@@ -3116,78 +3137,92 @@ function createStyles(document) {
3116
3137
  position: relative;
3117
3138
  z-index: 1;
3118
3139
  display: flex;
3119
- max-height: min(720px, calc(100vh - 32px));
3140
+ box-sizing: border-box;
3141
+ max-height: min(${String(DIALOG_MAX_HEIGHT)}px, calc(100vh - 32px));
3120
3142
  overflow: hidden;
3121
3143
  flex-direction: column;
3122
3144
  border: 1px solid var(--spotpatch-border);
3123
3145
  border-radius: var(--spotpatch-radius-panel);
3124
3146
  background: var(--spotpatch-bg);
3125
- box-shadow: inset 0 1px rgb(255 255 255 / 7%), inset 0 0 0 1px rgb(2 6 23 / 40%);
3147
+ box-shadow: inset 0 1px rgb(255 255 255 / 5%), 0 0 60px -32px rgb(139 123 255 / 20%);
3148
+ }
3149
+ .spotpatch-shell::before {
3150
+ position: absolute;
3151
+ z-index: 2;
3152
+ top: 0;
3153
+ right: 20%;
3154
+ left: 20%;
3155
+ height: 1px;
3156
+ background: linear-gradient(90deg, transparent, var(--spotpatch-accent), var(--spotpatch-accent-cyan), transparent);
3157
+ content: "";
3158
+ opacity: .65;
3159
+ pointer-events: none;
3126
3160
  }
3127
3161
  .spotpatch-header {
3128
3162
  position: relative;
3129
- padding: 20px 22px 18px;
3130
- border-bottom: 1px solid rgb(255 255 255 / 8%);
3163
+ padding: 0 18px 14px;
3131
3164
  }
3132
3165
  .spotpatch-brand-row {
3133
3166
  display: flex;
3134
3167
  align-items: center;
3135
3168
  justify-content: space-between;
3136
- gap: 16px;
3137
- margin-bottom: 18px;
3169
+ gap: 12px;
3170
+ margin: 0 -18px 18px;
3171
+ padding: 14px 18px 13px;
3172
+ border-bottom: 1px solid var(--spotpatch-border-subtle);
3138
3173
  }
3139
3174
  .spotpatch-brand {
3140
3175
  display: inline-flex;
3141
3176
  align-items: center;
3142
- gap: 11px;
3177
+ gap: 10px;
3143
3178
  min-width: 0;
3144
3179
  color: #f8fafc;
3145
3180
  }
3146
3181
  .spotpatch-brand-mark {
3147
- width: 34px;
3148
- height: 34px;
3182
+ width: 30px;
3183
+ height: 30px;
3149
3184
  flex: none;
3150
3185
  filter: drop-shadow(0 6px 12px rgb(76 29 149 / 22%));
3151
3186
  }
3152
3187
  .spotpatch-brand-copy { display: grid; min-width: 0; gap: 1px; }
3153
3188
  .spotpatch-brand-name {
3154
3189
  color: #fff;
3155
- font-size: 15px;
3156
- font-weight: 720;
3190
+ font-size: 13.5px;
3191
+ font-weight: 680;
3157
3192
  letter-spacing: -.01em;
3158
3193
  }
3159
3194
  .spotpatch-brand-context {
3160
3195
  color: #8e98aa;
3161
- font-size: 11px;
3196
+ font-size: 10.5px;
3162
3197
  font-weight: 560;
3163
3198
  letter-spacing: .02em;
3164
3199
  }
3165
3200
  .spotpatch-header-controls {
3166
3201
  display: inline-flex;
3167
3202
  align-items: center;
3168
- gap: 8px;
3203
+ gap: 6px;
3169
3204
  flex: none;
3170
3205
  }
3171
3206
  .spotpatch-repository,
3172
3207
  .spotpatch-locale,
3173
3208
  .spotpatch-close {
3174
- height: 30px;
3209
+ height: 27px;
3175
3210
  border: 1px solid rgb(255 255 255 / 11%);
3176
- border-radius: 9px;
3177
- background: rgb(255 255 255 / 4%);
3211
+ border-radius: 7px;
3212
+ background: transparent;
3178
3213
  }
3179
3214
  .spotpatch-repository {
3180
3215
  display: inline-flex;
3181
3216
  align-items: center;
3182
- padding: 0 10px;
3183
- color: #bcecf2;
3217
+ padding: 0 9px;
3218
+ color: var(--spotpatch-text-secondary);
3184
3219
  font-size: 11px;
3185
3220
  font-weight: 680;
3186
3221
  text-decoration: none;
3187
3222
  }
3188
3223
  .spotpatch-locale {
3189
- min-width: 38px;
3190
- padding: 0 9px;
3224
+ min-width: 34px;
3225
+ padding: 0 8px;
3191
3226
  color: #c5cad5;
3192
3227
  cursor: pointer;
3193
3228
  font-size: 12px;
@@ -3195,12 +3230,12 @@ function createStyles(document) {
3195
3230
  }
3196
3231
  .spotpatch-close {
3197
3232
  display: inline-grid;
3198
- width: 30px;
3233
+ width: 27px;
3199
3234
  padding: 0;
3200
3235
  place-items: center;
3201
3236
  color: #9da5b4;
3202
3237
  cursor: pointer;
3203
- font-size: 17px;
3238
+ font-size: 15px;
3204
3239
  line-height: 1;
3205
3240
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
3206
3241
  }
@@ -3210,30 +3245,30 @@ function createStyles(document) {
3210
3245
  .spotpatch-title {
3211
3246
  margin: 0;
3212
3247
  color: #fff;
3213
- font-size: 24px;
3214
- font-weight: 730;
3215
- letter-spacing: -.025em;
3248
+ font-size: 18px;
3249
+ font-weight: 680;
3250
+ letter-spacing: -.015em;
3216
3251
  }
3217
3252
  .spotpatch-subtitle {
3218
- max-width: 470px;
3219
- margin: 6px 0 0;
3220
- color: #9ca5b5;
3221
- font-size: 15px;
3222
- line-height: 1.55;
3253
+ max-width: 390px;
3254
+ margin: 4px 0 0;
3255
+ color: var(--spotpatch-text-secondary);
3256
+ font-size: 12.5px;
3257
+ line-height: 1.5;
3223
3258
  }
3224
3259
  .spotpatch-target-row {
3225
3260
  display: flex;
3226
3261
  align-items: center;
3227
3262
  gap: 8px;
3228
3263
  min-width: 0;
3229
- margin-top: 16px;
3264
+ margin-top: 14px;
3230
3265
  }
3231
3266
  .spotpatch-target-label {
3232
3267
  min-width: 0;
3233
3268
  overflow: hidden;
3234
3269
  border: 1px solid rgb(129 112 247 / 24%);
3235
3270
  border-radius: 999px;
3236
- padding: 6px 10px;
3271
+ padding: 4px 10px;
3237
3272
  color: #cdd2ff;
3238
3273
  background: rgb(109 93 246 / 10%);
3239
3274
  font: 600 11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
@@ -3246,7 +3281,7 @@ function createStyles(document) {
3246
3281
  gap: 6px;
3247
3282
  flex: none;
3248
3283
  color: #a5adba;
3249
- font-size: 12px;
3284
+ font-size: 11px;
3250
3285
  white-space: nowrap;
3251
3286
  }
3252
3287
  .spotpatch-context-state::before {
@@ -3267,7 +3302,7 @@ function createStyles(document) {
3267
3302
  .spotpatch-body {
3268
3303
  min-height: 0;
3269
3304
  overflow: auto;
3270
- padding: 20px 22px 22px;
3305
+ padding: 0 18px 14px;
3271
3306
  scrollbar-color: rgb(100 116 139 / 50%) transparent;
3272
3307
  scrollbar-width: thin;
3273
3308
  }
@@ -3278,36 +3313,54 @@ function createStyles(document) {
3278
3313
  display: flex;
3279
3314
  align-items: center;
3280
3315
  justify-content: space-between;
3281
- gap: 12px;
3282
- margin-bottom: 7px;
3283
- color: #eef0f5;
3284
- font-size: 14px;
3285
- font-weight: 680;
3316
+ gap: 10px;
3317
+ margin-bottom: 8px;
3318
+ color: var(--spotpatch-text-secondary);
3319
+ font-size: 11px;
3320
+ font-weight: 650;
3321
+ letter-spacing: .04em;
3322
+ text-transform: uppercase;
3286
3323
  }
3287
3324
  .spotpatch-targets-meta {
3288
3325
  display: flex;
3289
3326
  align-items: center;
3290
- justify-content: space-between;
3291
- gap: 12px;
3292
- margin-bottom: 12px;
3327
+ gap: 8px;
3328
+ min-width: 0;
3329
+ letter-spacing: 0;
3330
+ text-transform: none;
3293
3331
  }
3294
- .spotpatch-target-complete { color: var(--spotpatch-text-secondary); font-size: 12px; font-weight: 560; }
3332
+ .spotpatch-target-complete { color: var(--spotpatch-text-muted); font-size: 11px; font-weight: 560; }
3295
3333
  .spotpatch-target-budget {
3296
3334
  color: var(--spotpatch-text-muted);
3297
- font: 550 11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
3335
+ font: 550 10.5px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
3298
3336
  }
3337
+ .spotpatch-target-budget[data-state="ready"] { display: none; }
3299
3338
  .spotpatch-target-budget[data-state="over"] { color: #fda4af; }
3300
3339
  .spotpatch-target-count {
3340
+ margin-left: auto;
3301
3341
  border-radius: 999px;
3302
3342
  padding: 3px 8px;
3303
- color: #b8bffd;
3304
- background: rgb(109 93 246 / 11%);
3305
- font: 650 11px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
3343
+ color: var(--spotpatch-text-muted);
3344
+ font: 600 10.5px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
3345
+ }
3346
+ .spotpatch-target-progress {
3347
+ height: 3px;
3348
+ margin-bottom: 13px;
3349
+ overflow: hidden;
3350
+ border-radius: 999px;
3351
+ background: var(--spotpatch-border-subtle);
3352
+ }
3353
+ .spotpatch-target-progress-fill {
3354
+ width: 0;
3355
+ height: 100%;
3356
+ border-radius: inherit;
3357
+ background: linear-gradient(90deg, var(--spotpatch-accent), var(--spotpatch-accent-cyan));
3358
+ transition: width 180ms ease;
3306
3359
  }
3307
3360
  .spotpatch-target-list {
3308
3361
  display: grid;
3309
- gap: 12px;
3310
- max-height: min(390px, 48vh);
3362
+ gap: 8px;
3363
+ max-height: min(340px, 48vh);
3311
3364
  overflow: auto;
3312
3365
  padding-right: 2px;
3313
3366
  }
@@ -3315,30 +3368,30 @@ function createStyles(document) {
3315
3368
  overflow: hidden;
3316
3369
  border: 1px solid var(--spotpatch-border-subtle);
3317
3370
  border-radius: var(--spotpatch-radius-card);
3318
- background: rgb(255 255 255 / 2.7%);
3371
+ background: var(--spotpatch-bg-raised);
3319
3372
  transition: border-color 150ms ease, background 150ms ease;
3320
3373
  }
3321
3374
  .spotpatch-target-item[data-active="true"] {
3322
- border-color: rgb(125 106 248 / 42%);
3323
- background: rgb(109 93 246 / 6%);
3324
- box-shadow: inset 3px 0 var(--spotpatch-accent-strong);
3375
+ border-color: rgb(139 123 255 / 34%);
3376
+ background: var(--spotpatch-bg-active);
3377
+ box-shadow: 0 0 0 3px rgb(139 123 255 / 10%);
3325
3378
  }
3326
3379
  .spotpatch-target-summary {
3327
3380
  display: grid;
3328
- grid-template-columns: minmax(0, 1fr) 34px 34px;
3381
+ grid-template-columns: minmax(0, 1fr) 28px 28px;
3329
3382
  align-items: stretch;
3330
- gap: 4px;
3331
- padding: 5px;
3383
+ gap: 2px;
3384
+ padding: 4px;
3332
3385
  }
3333
3386
  .spotpatch-target-select {
3334
3387
  display: grid;
3335
- grid-template-columns: 34px minmax(0, 1fr) auto;
3388
+ grid-template-columns: 24px minmax(0, 1fr) auto;
3336
3389
  align-items: center;
3337
- gap: 11px;
3390
+ gap: 9px;
3338
3391
  min-width: 0;
3339
3392
  border: 0;
3340
- border-radius: 11px;
3341
- padding: 10px 11px;
3393
+ border-radius: 8px;
3394
+ padding: 8px;
3342
3395
  color: inherit;
3343
3396
  background: transparent;
3344
3397
  cursor: pointer;
@@ -3347,14 +3400,14 @@ function createStyles(document) {
3347
3400
  .spotpatch-target-select:hover { background: rgb(255 255 255 / 3.5%); }
3348
3401
  .spotpatch-target-index {
3349
3402
  display: inline-grid;
3350
- width: 30px;
3351
- height: 30px;
3403
+ width: 22px;
3404
+ height: 22px;
3352
3405
  place-items: center;
3353
3406
  border: 1px solid rgb(68 202 224 / 25%);
3354
- border-radius: 9px;
3355
- color: #9ce7f0;
3356
- background: rgb(8 145 178 / 10%);
3357
- font: 700 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
3407
+ border-radius: 6px;
3408
+ color: var(--spotpatch-text-secondary);
3409
+ background: var(--spotpatch-bg);
3410
+ font: 650 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
3358
3411
  }
3359
3412
  .spotpatch-target-copy { min-width: 0; }
3360
3413
  .spotpatch-target-name,
@@ -3364,14 +3417,14 @@ function createStyles(document) {
3364
3417
  text-overflow: ellipsis;
3365
3418
  white-space: nowrap;
3366
3419
  }
3367
- .spotpatch-target-name { color: #f2f4f8; font-size: 16px; font-weight: 680; }
3368
- .spotpatch-target-source { margin-top: 5px; color: var(--spotpatch-text-muted); font: 500 13px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace; }
3420
+ .spotpatch-target-name { color: #f2f2f5; font-size: 13px; font-weight: 650; }
3421
+ .spotpatch-target-source { margin-top: 1px; color: var(--spotpatch-text-muted); font: 500 10.5px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; }
3369
3422
  .spotpatch-target-state {
3370
3423
  border-radius: 999px;
3371
- padding: 4px 8px;
3424
+ padding: 3px 8px;
3372
3425
  color: #a7f3d0;
3373
3426
  background: rgb(16 185 129 / 9%);
3374
- font-size: 11px;
3427
+ font-size: 10.5px;
3375
3428
  font-weight: 650;
3376
3429
  white-space: nowrap;
3377
3430
  }
@@ -3379,13 +3432,13 @@ function createStyles(document) {
3379
3432
  .spotpatch-target-open,
3380
3433
  .spotpatch-target-remove {
3381
3434
  display: inline-grid;
3382
- width: 34px;
3435
+ width: 28px;
3383
3436
  height: 100%;
3384
- min-height: 40px;
3437
+ min-height: 34px;
3385
3438
  padding: 0;
3386
3439
  place-items: center;
3387
3440
  border: 1px solid transparent;
3388
- border-radius: 10px;
3441
+ border-radius: 7px;
3389
3442
  color: #7f899a;
3390
3443
  background: transparent;
3391
3444
  cursor: pointer;
@@ -3394,31 +3447,30 @@ function createStyles(document) {
3394
3447
  .spotpatch-target-open:hover:not(:disabled) { border-color: rgb(68 202 224 / 30%); color: #c8f7ff; background: rgb(8 145 178 / 11%); }
3395
3448
  .spotpatch-target-remove:hover:not(:disabled) { border-color: rgb(251 113 133 / 24%); color: #fda4af; background: rgb(127 29 29 / 12%); }
3396
3449
  .spotpatch-target-editor {
3397
- border-top: 1px solid rgb(255 255 255 / 7%);
3398
- padding: 18px;
3450
+ padding: 0 12px 12px;
3399
3451
  }
3400
3452
  .spotpatch-target-editor-head {
3401
3453
  display: flex;
3402
3454
  align-items: baseline;
3403
3455
  justify-content: space-between;
3404
3456
  gap: 12px;
3405
- margin-bottom: 9px;
3457
+ margin-bottom: 6px;
3406
3458
  }
3407
- .spotpatch-target-editor-label { color: #dfe3ea; font-size: 15px; font-weight: 650; }
3408
- .spotpatch-target-editor-count { color: var(--spotpatch-text-muted); font: 500 11px/1.3 ui-monospace, SFMono-Regular, Menlo, monospace; }
3459
+ .spotpatch-target-editor-label { color: var(--spotpatch-text-secondary); font-size: 11px; font-weight: 650; }
3460
+ .spotpatch-target-editor-count { color: var(--spotpatch-text-muted); font: 500 10.5px/1.3 ui-monospace, SFMono-Regular, Menlo, monospace; }
3409
3461
  .spotpatch-target-editor textarea {
3410
3462
  box-sizing: border-box;
3411
3463
  width: 100%;
3412
- min-height: 126px;
3464
+ min-height: 74px;
3413
3465
  resize: vertical;
3414
3466
  border: 1px solid var(--spotpatch-border);
3415
- border-radius: 12px;
3416
- padding: 14px 15px;
3467
+ border-radius: 7px;
3468
+ padding: 9px 10px;
3417
3469
  color: #f8fafc;
3418
3470
  caret-color: #8b7cf7;
3419
3471
  background: var(--spotpatch-bg-input);
3420
- font-size: 15px;
3421
- line-height: 1.65;
3472
+ font-size: 12.5px;
3473
+ line-height: 1.55;
3422
3474
  outline: none;
3423
3475
  transition: border-color 150ms ease, box-shadow 150ms ease, background 150ms ease;
3424
3476
  }
@@ -3427,23 +3479,23 @@ function createStyles(document) {
3427
3479
  .spotpatch-target-editor textarea:focus {
3428
3480
  border-color: rgb(139 124 247 / 68%);
3429
3481
  background: rgb(3 7 18 / 65%);
3430
- box-shadow: 0 0 0 3px rgb(109 93 246 / 10%);
3482
+ box-shadow: 0 0 0 2px rgb(109 93 246 / 10%);
3431
3483
  }
3432
3484
  .spotpatch-diagnostics {
3433
- margin-top: 14px;
3485
+ margin-top: 10px;
3434
3486
  overflow: hidden;
3435
3487
  border: 1px solid rgb(255 255 255 / 8%);
3436
- border-radius: 13px;
3488
+ border-radius: 9px;
3437
3489
  background: rgb(255 255 255 / 2.5%);
3438
3490
  }
3439
3491
  .spotpatch-diagnostics > summary {
3440
3492
  display: flex;
3441
3493
  align-items: center;
3442
3494
  gap: 8px;
3443
- padding: 11px 13px;
3495
+ padding: 9px 11px;
3444
3496
  color: #bfc5d0;
3445
3497
  cursor: pointer;
3446
- font-size: 12px;
3498
+ font-size: 11px;
3447
3499
  font-weight: 650;
3448
3500
  list-style: none;
3449
3501
  user-select: none;
@@ -3472,9 +3524,9 @@ function createStyles(document) {
3472
3524
  margin: 0;
3473
3525
  overflow: auto;
3474
3526
  border-top: 1px solid rgb(255 255 255 / 7%);
3475
- padding: 12px 13px 13px;
3527
+ padding: 10px 11px 11px;
3476
3528
  color: #9ca5b5;
3477
- font: 11.5px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace;
3529
+ font: 10.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
3478
3530
  overflow-wrap: anywhere;
3479
3531
  white-space: pre-wrap;
3480
3532
  user-select: text;
@@ -3484,39 +3536,44 @@ function createStyles(document) {
3484
3536
  margin: 0;
3485
3537
  overflow: auto;
3486
3538
  border: 1px solid rgb(255 255 255 / 9%);
3487
- border-radius: 14px;
3488
- padding: 13px;
3539
+ border-radius: 9px;
3540
+ padding: 11px;
3489
3541
  color: #d8ddeb;
3490
3542
  background: rgb(3 7 18 / 55%);
3491
- font: 12px/1.65 ui-monospace, SFMono-Regular, Menlo, monospace;
3543
+ font: 11px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace;
3492
3544
  overflow-wrap: anywhere;
3493
3545
  white-space: pre-wrap;
3494
3546
  user-select: text;
3495
3547
  }
3496
3548
  .spotpatch-actions {
3497
- display: flex;
3498
- flex-wrap: wrap;
3499
- gap: 9px;
3500
- padding: 14px 22px 18px;
3549
+ display: grid;
3550
+ gap: 8px;
3551
+ padding: 10px 18px 14px;
3501
3552
  border-top: 1px solid rgb(255 255 255 / 8%);
3502
- background: rgb(8 12 22 / 82%);
3553
+ background: rgb(8 8 12 / 86%);
3503
3554
  }
3504
3555
  .spotpatch-editor-feedback {
3505
- flex-basis: 100%;
3506
3556
  white-space: normal;
3507
3557
  }
3558
+ .spotpatch-secondary-actions,
3559
+ .spotpatch-primary-actions {
3560
+ display: flex;
3561
+ align-items: center;
3562
+ gap: 7px;
3563
+ }
3564
+ .spotpatch-secondary-actions { min-height: 30px; }
3508
3565
  .spotpatch-actions button {
3509
3566
  display: inline-flex;
3510
- min-height: 40px;
3567
+ min-height: 34px;
3511
3568
  align-items: center;
3512
3569
  justify-content: center;
3513
3570
  border: 1px solid rgb(255 255 255 / 10%);
3514
- border-radius: 11px;
3515
- padding: 9px 13px;
3516
- color: #d8ddeb;
3571
+ border-radius: 9px;
3572
+ padding: 7px 11px;
3573
+ color: var(--spotpatch-text-secondary);
3517
3574
  background: rgb(255 255 255 / 4%);
3518
3575
  cursor: pointer;
3519
- font-size: 13px;
3576
+ font-size: 12px;
3520
3577
  font-weight: 650;
3521
3578
  transition: border-color 150ms ease, box-shadow 150ms ease, color 150ms ease, transform 150ms ease;
3522
3579
  }
@@ -3526,14 +3583,36 @@ function createStyles(document) {
3526
3583
  transform: translateY(-1px);
3527
3584
  }
3528
3585
  .spotpatch-actions .spotpatch-primary {
3529
- min-width: 154px;
3586
+ min-width: 138px;
3530
3587
  flex: 1;
3531
- border-color: rgb(139 124 247 / 58%);
3532
- color: #fff;
3533
- background: var(--spotpatch-accent-strong);
3534
- box-shadow: 0 9px 24px rgb(55 48 163 / 20%), inset 0 1px rgb(255 255 255 / 14%);
3588
+ border-color: transparent;
3589
+ color: var(--spotpatch-text-on-accent);
3590
+ background: linear-gradient(135deg, var(--spotpatch-accent), var(--spotpatch-accent-strong));
3591
+ box-shadow: 0 8px 20px -8px rgb(139 123 255 / 55%);
3535
3592
  }
3593
+ .spotpatch-actions .spotpatch-primary:hover:not(:disabled) { color: var(--spotpatch-text-on-accent); filter: brightness(1.08); }
3536
3594
  .spotpatch-actions .spotpatch-primary::after { margin-left: 8px; content: "\u2197"; font-size: 12px; }
3595
+ .spotpatch-actions .spotpatch-secondary-action {
3596
+ min-height: 30px;
3597
+ border-style: dashed;
3598
+ padding: 5px 10px;
3599
+ color: var(--spotpatch-text-muted);
3600
+ background: transparent;
3601
+ font-size: 11px;
3602
+ }
3603
+ .spotpatch-actions .spotpatch-icon-action {
3604
+ width: 34px;
3605
+ min-width: 34px;
3606
+ padding: 0;
3607
+ font-size: 0;
3608
+ }
3609
+ .spotpatch-actions .spotpatch-icon-action::before {
3610
+ color: var(--spotpatch-text-secondary);
3611
+ content: attr(data-compact-icon);
3612
+ font-size: 18px;
3613
+ font-weight: 400;
3614
+ line-height: 1;
3615
+ }
3537
3616
  .spotpatch-actions button:disabled { cursor: not-allowed; opacity: .4; transform: none; }
3538
3617
  .spotpatch-actions button:focus-visible,
3539
3618
  .spotpatch-repository:focus-visible,
@@ -3565,11 +3644,13 @@ function createStyles(document) {
3565
3644
  }
3566
3645
  @media (max-width: 520px) {
3567
3646
  .spotpatch-dialog { top: 8px; left: 8px; width: calc(100vw - 16px); }
3568
- .spotpatch-shell { max-height: calc(100vh - 16px); border-radius: 18px; }
3569
- .spotpatch-header, .spotpatch-body { padding-left: 16px; padding-right: 16px; }
3570
- .spotpatch-actions { padding-left: 16px; padding-right: 16px; }
3571
- .spotpatch-target-select { grid-template-columns: 32px minmax(0, 1fr); }
3647
+ .spotpatch-shell { max-height: calc(100vh - 16px); border-radius: 14px; }
3648
+ .spotpatch-header, .spotpatch-body { padding-left: 14px; padding-right: 14px; }
3649
+ .spotpatch-brand-row { margin-right: -14px; margin-left: -14px; padding-right: 14px; padding-left: 14px; }
3650
+ .spotpatch-actions { padding-right: 14px; padding-left: 14px; }
3651
+ .spotpatch-target-select { grid-template-columns: 24px minmax(0, 1fr); }
3572
3652
  .spotpatch-target-state { display: none; }
3653
+ .spotpatch-repository { display: none; }
3573
3654
  }
3574
3655
  ${AGENT_PANEL_STYLES}
3575
3656
  `;
@@ -3672,10 +3753,17 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3672
3753
  const targetCount = createMarkedElement(document, "span");
3673
3754
  targetCount.className = "spotpatch-target-count";
3674
3755
  targetsMeta.append(targetComplete, targetBudget);
3675
- targetsHeading.append(targetsTitle, targetCount);
3756
+ targetRow.append(targetCount);
3757
+ targetsHeading.append(targetsTitle, targetsMeta);
3758
+ const targetProgress = createMarkedElement(document, "div");
3759
+ targetProgress.className = "spotpatch-target-progress";
3760
+ targetProgress.setAttribute("aria-hidden", "true");
3761
+ const targetProgressFill = createMarkedElement(document, "div");
3762
+ targetProgressFill.className = "spotpatch-target-progress-fill";
3763
+ targetProgress.append(targetProgressFill);
3676
3764
  const targetList = createMarkedElement(document, "div");
3677
3765
  targetList.className = "spotpatch-target-list";
3678
- targetsPanel.append(targetsHeading, targetsMeta, targetList);
3766
+ targetsPanel.append(targetsHeading, targetProgress, targetList);
3679
3767
  const diagnostics = createMarkedElement(document, "details");
3680
3768
  diagnostics.className = "spotpatch-diagnostics";
3681
3769
  const diagnosticsLabel = createMarkedElement(document, "summary");
@@ -3716,21 +3804,30 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3716
3804
  );
3717
3805
  const copyButton = createButton(document, messages.actions.copy, "spotpatch-primary");
3718
3806
  const backButton = createButton(document, messages.actions.back);
3719
- actions.append(
3720
- editorFeedback,
3807
+ const secondaryActions = createMarkedElement(document, "div");
3808
+ secondaryActions.className = "spotpatch-secondary-actions";
3809
+ const primaryActions = createMarkedElement(document, "div");
3810
+ primaryActions.className = "spotpatch-primary-actions";
3811
+ addTargetButton.classList.add("spotpatch-icon-action");
3812
+ addTargetButton.dataset.compactIcon = "+";
3813
+ agentPanel.testButton.classList.add("spotpatch-icon-action");
3814
+ agentPanel.testButton.dataset.compactIcon = "\u2713";
3815
+ openEditorButton.classList.add("spotpatch-secondary-action");
3816
+ reselectButton.classList.add("spotpatch-secondary-action");
3817
+ secondaryActions.append(openEditorButton, reselectButton);
3818
+ primaryActions.append(
3819
+ agentPanel.testButton,
3820
+ addTargetButton,
3721
3821
  agentPanel.runButton,
3722
3822
  previewButton,
3723
- agentPanel.testButton,
3724
3823
  agentPanel.cancelButton,
3725
3824
  agentPanel.applyButton,
3726
3825
  agentPanel.revertButton,
3727
3826
  agentPanel.resetButton,
3728
- addTargetButton,
3729
- openEditorButton,
3730
- reselectButton,
3731
3827
  copyButton,
3732
3828
  backButton
3733
3829
  );
3830
+ actions.append(editorFeedback, secondaryActions, primaryActions);
3734
3831
  shell.append(header, body, actions);
3735
3832
  dialog.append(anchor, shell);
3736
3833
  const liveRegion = createMarkedElement(document, "div");
@@ -3769,6 +3866,10 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3769
3866
  }
3770
3867
  return target2.status === "warning" ? messages.targets.statusPartial : messages.targets.statusCollecting;
3771
3868
  }
3869
+ function renderTargetProgress(complete, total) {
3870
+ const ratio = total === 0 ? 0 : complete / total;
3871
+ targetProgressFill.style.width = `${String(ratio * 100)}%`;
3872
+ }
3772
3873
  function instructionInput(targetId) {
3773
3874
  const inputs = targetList.querySelectorAll(
3774
3875
  "textarea[data-target-instruction-id]"
@@ -3794,6 +3895,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3794
3895
  (total, target2) => total + target2.instruction.trim().length,
3795
3896
  0
3796
3897
  );
3898
+ renderTargetProgress(completeCount, targets.length);
3797
3899
  targetCount.textContent = messages.targets.count(targets.length, maximum);
3798
3900
  targetComplete.textContent = messages.targets.complete(
3799
3901
  completeCount,
@@ -3915,10 +4017,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3915
4017
  MAX_TARGET_INSTRUCTION_CHARACTERS2
3916
4018
  );
3917
4019
  }
4020
+ const completeCount = currentTargets.filter(
4021
+ (target2) => target2.instruction.trim().length > 0
4022
+ ).length;
3918
4023
  targetComplete.textContent = messages.targets.complete(
3919
- currentTargets.filter((target2) => target2.instruction.trim().length > 0).length,
4024
+ completeCount,
3920
4025
  currentTargets.length
3921
4026
  );
4027
+ renderTargetProgress(completeCount, currentTargets.length);
3922
4028
  const instructionCharacters = currentTargets.reduce(
3923
4029
  (total, target2) => total + target2.instruction.trim().length,
3924
4030
  0
@@ -3953,7 +4059,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3953
4059
  placeDialog();
3954
4060
  }
3955
4061
  function placeDialog() {
3956
- if (dialog.hidden || currentRect === void 0) {
4062
+ if (dialog.hidden) {
3957
4063
  return;
3958
4064
  }
3959
4065
  const view = document.defaultView;
@@ -3961,14 +4067,14 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
3961
4067
  const viewportHeight = view?.innerHeight ?? document.documentElement.clientHeight;
3962
4068
  const measured = dialog.getBoundingClientRect();
3963
4069
  const status = currentStatus === "previewing" ? "previewing" : "selected";
3964
- const dialogWidth = measured.width > 0 ? measured.width : Math.min(DIALOG_FALLBACK_WIDTH, viewportWidth - 32);
4070
+ const dialogWidth = measured.width > 0 ? measured.width : Math.min(DIALOG_MAX_WIDTH, viewportWidth - 32);
3965
4071
  const dialogHeight = measured.height > 0 ? measured.height : Math.min(DIALOG_FALLBACK_HEIGHT[status], viewportHeight - 32);
3966
4072
  const placement = calculateDialogPlacement({
3967
- target: currentRect,
3968
4073
  dialogWidth,
3969
4074
  dialogHeight,
3970
4075
  viewportWidth,
3971
- viewportHeight
4076
+ viewportHeight,
4077
+ ...currentRect === void 0 ? {} : { target: currentRect }
3972
4078
  });
3973
4079
  dialog.style.left = `${String(placement.left)}px`;
3974
4080
  dialog.style.top = `${String(placement.top)}px`;
@@ -4018,6 +4124,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
4018
4124
  addTargetButton.hidden = !selected;
4019
4125
  openEditorButton.hidden = !selected;
4020
4126
  previewButton.hidden = !selected;
4127
+ secondaryActions.hidden = !selected;
4021
4128
  agentPanel.setSelectionVisible(selected);
4022
4129
  copyButton.hidden = !previewing;
4023
4130
  backButton.hidden = !previewing;
@@ -4056,6 +4163,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
4056
4163
  } else {
4057
4164
  targetCount.textContent = messages.targets.count(0, currentMaximum);
4058
4165
  targetComplete.textContent = messages.targets.complete(0, 0);
4166
+ renderTargetProgress(0, 0);
4059
4167
  targetBudget.dataset.state = "ready";
4060
4168
  targetBudget.textContent = messages.targets.instructionBudget(
4061
4169
  0,
@@ -4124,6 +4232,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
4124
4232
  selectionHighlights.replaceChildren();
4125
4233
  activeSelectionRect = void 0;
4126
4234
  currentRect = void 0;
4235
+ placeDialog();
4127
4236
  },
4128
4237
  showSelection(summaryText, canOpenEditor, canPreview) {
4129
4238
  updateSelection(summaryText, canOpenEditor, canPreview);
@@ -4149,6 +4258,7 @@ function createRuntimeView(document, shortcut, ai = Object.freeze({ enabled: fal
4149
4258
  renderEditorStatus("idle");
4150
4259
  targetCount.textContent = messages.targets.count(0, 0);
4151
4260
  targetComplete.textContent = messages.targets.complete(0, 0);
4261
+ renderTargetProgress(0, 0);
4152
4262
  targetLabel.textContent = messages.context.selectedElement;
4153
4263
  summary.textContent = "";
4154
4264
  promptOutput.textContent = "";
@@ -4593,10 +4703,7 @@ function createAgentWorkflow(options) {
4593
4703
  providerConsents.add(selection.providerProfileId);
4594
4704
  const workflowRevision = ++revision;
4595
4705
  options.view.setAgentEditingEnabled(false);
4596
- void Promise.all([
4597
- probe(workflowRevision),
4598
- refreshWorkspaceHealth(workflowRevision)
4599
- ]).then(async ([, health]) => {
4706
+ void refreshWorkspaceHealth(workflowRevision).then(async (health) => {
4600
4707
  if (workflowRevision !== revision) {
4601
4708
  return;
4602
4709
  }
@@ -4859,11 +4966,15 @@ ${summary}`;
4859
4966
  if (!target2.element?.isConnected) {
4860
4967
  return [];
4861
4968
  }
4969
+ const rect = getVisibleElementRect(target2.element, browser.window);
4970
+ if (rect === void 0) {
4971
+ return [];
4972
+ }
4862
4973
  return [
4863
4974
  {
4864
4975
  id: target2.id,
4865
4976
  label: elementLabel(target2.element),
4866
- rect: getElementRect(target2.element, browser.window),
4977
+ rect,
4867
4978
  active: target2.id === activeTargetId
4868
4979
  }
4869
4980
  ];