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