@emmaexcel/shakecursor 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,41 +1,48 @@
1
1
  (function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e,t,n){return Math.min(Math.max(e,t),n)}function n(e){return e.replace(/\s+/g,` `).trim()}function r(e,t=[]){return t.some(t=>{try{return e.matches(t)||!!e.closest(t)}catch{return!1}})}function i(){return/Mac|iPhone|iPad|iPod/i.test(window.navigator.platform)}function a(e){if(e.rangeCount===0)return null;let t=e.getRangeAt(0),n=t.getBoundingClientRect();return n.width>0||n.height>0?n:t.getClientRects()[0]??null}function o(e){return{rect:e,url:window.location.href,title:document.title}}function s(e){let t=n(e.innerText??``),r=e.tagName.toLowerCase(),i=e.getAttribute(`aria-label`),a=e.getAttribute(`title`),o=[i,a,t].find(Boolean);return{label:o?`${r}: ${o.slice(0,64)}`:r,data:void 0,mimeType:void 0,content:[`Selected element: <${r}>`,i?`ARIA label: ${i}`:``,a?`Title: ${a}`:``,t?`Visible text: ${t.slice(0,5e3)}`:``].filter(Boolean).join(`
2
2
  `)}}function c(e){let t=e.currentSrc||e.src,n=e.alt||`No alt text`,r,i;try{let t=document.createElement(`canvas`);t.width=e.naturalWidth,t.height=e.naturalHeight;let n=t.getContext(`2d`);if(n){n.drawImage(e,0,0);let[a,o]=t.toDataURL(`image/jpeg`,.8).split(`,`);r=o,i=a.split(`:`)[1].split(`;`)[0]}}catch(e){console.warn(`Failed to capture image data (likely CORS):`,e)}return{label:`image: ${n.slice(0,64)}`,data:r,mimeType:i,content:[`Selected image`,`Alt text: ${n}`,`Source: ${t}`,`Rendered size: ${Math.round(e.width)}x${Math.round(e.height)}`,`Natural size: ${e.naturalWidth}x${e.naturalHeight}`].join(`
3
- `)}}function l(e,t){return!(r(e,t.blockedSelectors)||t.allowedSelectors.length>0&&!r(e,t.allowedSelectors))}function u(e){let t=t=>{if(!e.isActive())return;let n=t.target;if(!(n instanceof HTMLElement)||e.isOverlayElement(n)){e.onHover(null);return}if(!l(n,e.config)){e.onHover(null);return}e.onHover(n.getBoundingClientRect())},r=()=>{!e.isActive()||!e.config.text||window.setTimeout(()=>{let t=window.getSelection(),r=n(t?.toString()??``);if(!t||!r)return;let i=a(t),s=t.anchorNode?.parentElement;!i||!s||!l(s,e.config)||e.onSelection({kind:`text`,label:`highlighted text`,content:r,...o(i)})},0)},i=t=>{if(!e.isActive())return;let r=t.target;if(!(r instanceof HTMLElement)||e.isOverlayElement(r)||!l(r,e.config)||n(window.getSelection()?.toString()??``))return;let i=r instanceof HTMLImageElement?r:r.querySelector(`img`),a=!!i;if(a&&!e.config.images||!a&&!e.config.elements)return;t.preventDefault(),t.stopPropagation();let u=i?c(i):s(r),d=i?i.getBoundingClientRect():r.getBoundingClientRect();e.onSelection({kind:i?`image`:`element`,label:u.label,content:u.content,data:u.data,mimeType:u.mimeType,...o(d)})};return document.addEventListener(`pointerover`,t),document.addEventListener(`mouseup`,r),document.addEventListener(`click`,i,!0),()=>{document.removeEventListener(`pointerover`,t),document.removeEventListener(`mouseup`,r),document.removeEventListener(`click`,i,!0)}}function d(e){let t=e.windowMs??650,n=e.cooldownMs??1e3,r=e.minSamples??7,i=e.minReversals??5,a=e.minDistance??340,o=e.minDeltaX??16,s=[],c=0,l=l=>{let u=performance.now();if(s.push({x:l.clientX,y:l.clientY,time:u}),s=s.filter(e=>u-e.time<t),s.length<r||u-c<n)return;let d=0,f=0,p=0;for(let e=1;e<s.length;e+=1){let t=s[e].x-s[e-1].x,n=s[e].y-s[e-1].y;if(f+=Math.hypot(t,n),Math.abs(t)<o)continue;let r=Math.sign(t);p!==0&&r!==p&&(d+=1),p=r}d>=i&&f>a&&(c=u,s=[],e.onShake())};return document.addEventListener(`pointermove`,l),()=>{document.removeEventListener(`pointermove`,l)}}var f=`http://localhost:11434/api/chat`,p=`qwen3-coder:480b-cloud`,m=`https://shakeai.onrender.com`;async function h(e,t){let n=e.provider??`ollama`,r=e.endpoint??f,i=e.model??p;if(n===`custom`){let n=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify(t)});if(!n.ok)throw Error(`Custom endpoint returned ${n.status}`);let i=await n.json();return typeof i==`string`?i:i&&typeof i==`object`&&`answer`in i&&typeof i.answer==`string`?i.answer:i&&typeof i==`object`&&`content`in i&&typeof i.content==`string`?i.content:JSON.stringify(i,null,2)}let a=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify({model:i,stream:!1,messages:[{role:`system`,content:`You are an in-page AI assistant. Use the selected website context to answer or transform content. Be direct and practical.`},{role:`user`,content:[`Page title: ${t.selection.title}`,`Page URL: ${t.selection.url}`,`Selection type: ${t.selection.kind}`,`Selection label: ${t.selection.label}`,`Selected context:`,t.selection.content,``,`User request: ${t.question}`].join(`
3
+ `)}}function l(e,t){if(r(e,t.blockedSelectors))return!1;let n=e.getBoundingClientRect(),i=window.innerWidth*window.innerHeight;return!(n.width*n.height>i*.5||t.allowedSelectors.length>0&&!r(e,t.allowedSelectors))}function u(e){let t=t=>{if(!e.isActive())return;let n=t.target;if(!(n instanceof HTMLElement)||e.isOverlayElement(n)){e.onHover(null);return}if(!l(n,e.config)){e.onHover(null);return}e.onHover(n.getBoundingClientRect())},r=()=>{!e.isActive()||!e.config.text||window.setTimeout(()=>{let t=window.getSelection(),r=n(t?.toString()??``);if(!t||!r)return;let i=a(t),s=t.anchorNode?.parentElement;!i||!s||!l(s,e.config)||e.onSelection({kind:`text`,label:`highlighted text`,content:r,...o(i)})},0)},i=t=>{if(!e.isActive())return;let r=t.target;if(!(r instanceof HTMLElement)||e.isOverlayElement(r)||!l(r,e.config)||n(window.getSelection()?.toString()??``))return;let i=r instanceof HTMLImageElement?r:r.querySelector(`img`),a=!!i;if(a&&!e.config.images||!a&&!e.config.elements)return;t.preventDefault(),t.stopPropagation();let u=i?c(i):s(r),d=i?i.getBoundingClientRect():r.getBoundingClientRect();e.onSelection({kind:i?`image`:`element`,label:u.label,content:u.content,data:u.data,mimeType:u.mimeType,...o(d)})};return document.addEventListener(`pointerover`,t),document.addEventListener(`mouseup`,r),document.addEventListener(`click`,i,!0),()=>{document.removeEventListener(`pointerover`,t),document.removeEventListener(`mouseup`,r),document.removeEventListener(`click`,i,!0)}}function d(e){let t=e.windowMs??650,n=e.cooldownMs??1e3,r=e.minSamples??7,i=e.minReversals??5,a=e.minDistance??340,o=e.minDeltaX??16,s=[],c=0,l=l=>{let u=performance.now();if(s.push({x:l.clientX,y:l.clientY,time:u}),s=s.filter(e=>u-e.time<t),s.length<r||u-c<n)return;let d=0,f=0,p=0;for(let e=1;e<s.length;e+=1){let t=s[e].x-s[e-1].x,n=s[e].y-s[e-1].y;if(f+=Math.hypot(t,n),Math.abs(t)<o)continue;let r=Math.sign(t);p!==0&&r!==p&&(d+=1),p=r}d>=i&&f>a&&(c=u,s=[],e.onShake())};return document.addEventListener(`pointermove`,l),()=>{document.removeEventListener(`pointermove`,l)}}var f=`http://localhost:11434/api/chat`,p=`qwen3-coder:480b-cloud`,m=`https://shakeai.onrender.com`;async function h(e,t){let n=e.provider??`ollama`,r=e.endpoint??f,i=e.model??p;if(n===`custom`){let n=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify(t)});if(!n.ok)throw Error(`Custom endpoint returned ${n.status}`);let i=await n.json();return typeof i==`string`?i:i&&typeof i==`object`&&`answer`in i&&typeof i.answer==`string`?i.answer:i&&typeof i==`object`&&`content`in i&&typeof i.content==`string`?i.content:JSON.stringify(i,null,2)}let a=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,...e.headers},body:JSON.stringify({model:i,stream:!1,messages:[{role:`system`,content:`You are an in-page AI assistant. Use the selected website context to answer or transform content. Be direct and practical.`},{role:`user`,content:[`Page title: ${t.selection.title}`,`Page URL: ${t.selection.url}`,`Selection type: ${t.selection.kind}`,`Selection label: ${t.selection.label}`,`Selected context:`,t.selection.content,``,`User request: ${t.question}`].join(`
4
4
  `)}]})});if(!a.ok)throw Error(`Ollama returned ${a.status}`);let o=await a.json();if(o.error)throw Error(o.error);return o.message?.content?.trim()||`No response returned.`}async function g(e){let t=await fetch(`${e.apiBaseUrl??m}/v1/ask`,{method:`POST`,headers:{"Content-Type":`application/json`,"x-site-key":e.siteKey},body:JSON.stringify(e.payload)}),n=await t.json();if(!t.ok||n.error)throw Error(n.error??`Hosted API returned ${t.status}`);return n.answer??`No response returned.`}function _(e){let n=document.createElement(`div`);n.dataset.aiOverlayRoot=`true`;let r=document.createElement(`style`);r.dataset.aiOverlayStyle=`true`,r.textContent=`
5
- body.ai-overlay-active {
6
- cursor: none !important;
7
- }
8
- body.ai-overlay-active * {
9
- cursor: none !important;
5
+ body.ai-overlay-active,
6
+ body.ai-overlay-active * {
7
+ cursor: none !important;
10
8
  }
11
9
  `;let i=n.attachShadow({mode:`open`});document.head.append(r),document.body.append(n),i.innerHTML=`
12
10
  <style>
13
11
  :host {
14
12
  all: initial;
15
- --ai-blue: #4285F4;
16
- --ai-red: #DB4437;
17
- --ai-yellow: #F4B400;
18
- --ai-green: #0F9D58;
19
- --ai-primary: ${e.theme.primaryColor};
13
+ --ai-accent: ${e.theme.primaryColor};
14
+ --ai-accent-strong: #2563eb;
15
+ --ai-accent-soft: color-mix(in srgb, var(--ai-accent), white 88%);
20
16
  --ai-panel: ${e.theme.panelBackground};
17
+ --ai-panel-raised: color-mix(in srgb, var(--ai-panel), white 7%);
21
18
  --ai-text: ${e.theme.textColor};
19
+ --ai-muted: color-mix(in srgb, var(--ai-text), transparent 42%);
20
+ --ai-faint: color-mix(in srgb, var(--ai-text), transparent 88%);
21
+ --ai-border: color-mix(in srgb, var(--ai-text), transparent 86%);
22
22
  --ai-radius: ${e.theme.borderRadius}px;
23
+ --ai-shadow-lg: 0 24px 70px rgba(15, 23, 42, 0.22), 0 8px 24px rgba(15, 23, 42, 0.10);
24
+ --ai-shadow-md: 0 14px 36px rgba(15, 23, 42, 0.16), 0 3px 10px rgba(15, 23, 42, 0.08);
25
+ color: var(--ai-text);
23
26
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
24
27
  }
25
28
 
29
+ * {
30
+ box-sizing: border-box;
31
+ }
32
+
26
33
  .custom-cursor {
27
34
  position: fixed;
28
35
  left: 0;
29
36
  top: 0;
30
- width: 32px;
31
- height: 32px;
37
+ width: 34px;
38
+ height: 34px;
32
39
  pointer-events: none;
33
40
  z-index: 2147483647;
34
41
  display: none;
35
- /* Offset to center the "tip" of the pointer */
36
- margin-left: -4px;
37
- margin-top: -4px;
38
- filter: drop-shadow(0 0 8px rgba(66, 133, 244, 0.6));
42
+ margin-left: -5px;
43
+ margin-top: -5px;
44
+ color: var(--ai-accent-strong);
45
+ filter: drop-shadow(0 10px 16px rgba(37, 99, 235, 0.28));
39
46
  }
40
47
 
41
48
  .custom-cursor.active {
@@ -45,9 +52,9 @@
45
52
  .cursor-shape {
46
53
  width: 100%;
47
54
  height: 100%;
48
- fill: white;
49
- stroke: var(--ai-blue);
50
- stroke-width: 2px;
55
+ fill: #ffffff;
56
+ stroke: currentColor;
57
+ stroke-width: 2;
51
58
  }
52
59
 
53
60
  .toast {
@@ -58,13 +65,18 @@
58
65
  display: none;
59
66
  align-items: center;
60
67
  gap: 10px;
61
- border: 1px solid color-mix(in srgb, var(--ai-primary), transparent 74%);
62
- border-radius: var(--ai-radius);
63
- background: var(--ai-panel);
68
+ min-height: 42px;
69
+ border: 1px solid color-mix(in srgb, var(--ai-accent), transparent 78%);
70
+ border-radius: 999px;
71
+ background:
72
+ linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.74)),
73
+ var(--ai-panel);
64
74
  color: var(--ai-text);
65
- padding: 10px 12px;
66
- font: 700 13px/1 Inter, ui-sans-serif, system-ui, sans-serif;
67
- box-shadow: 0 16px 42px rgba(15, 23, 42, 0.18);
75
+ padding: 8px 10px 8px 12px;
76
+ font: 700 12px/1 Inter, ui-sans-serif, system-ui, sans-serif;
77
+ letter-spacing: 0;
78
+ box-shadow: var(--ai-shadow-md);
79
+ backdrop-filter: blur(18px) saturate(1.25);
68
80
  }
69
81
 
70
82
  .toast.active {
@@ -72,18 +84,28 @@
72
84
  }
73
85
 
74
86
  .pulse {
75
- width: 8px;
76
- height: 8px;
87
+ position: relative;
88
+ width: 9px;
89
+ height: 9px;
77
90
  border-radius: 999px;
78
- background: var(--ai-primary);
79
- box-shadow: 0 0 0 0 color-mix(in srgb, var(--ai-primary), transparent 38%);
80
- animation: pulse-ring 1.3s infinite;
91
+ background: var(--ai-accent);
92
+ box-shadow: 0 0 0 5px color-mix(in srgb, var(--ai-accent), transparent 86%);
93
+ }
94
+
95
+ .pulse::after {
96
+ content: "";
97
+ position: absolute;
98
+ inset: -6px;
99
+ border-radius: inherit;
100
+ border: 1px solid color-mix(in srgb, var(--ai-accent), transparent 58%);
101
+ animation: pulse-ring 1.45s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
81
102
  }
82
103
 
83
104
  .count {
84
- border-left: 1px solid rgba(15, 23, 42, 0.12);
85
- padding-left: 10px;
86
- opacity: 0.72;
105
+ border-left: 1px solid var(--ai-border);
106
+ padding: 4px 2px 4px 10px;
107
+ color: var(--ai-muted);
108
+ font-weight: 650;
87
109
  }
88
110
 
89
111
  .hover {
@@ -91,113 +113,182 @@
91
113
  z-index: 2147483644;
92
114
  pointer-events: none;
93
115
  display: none;
94
- /* Thicker, more professional border */
95
- border: 4px solid transparent;
96
- border-radius: var(--ai-radius);
97
- /*Conic gradient on border only, no gray background fill */
98
- background: linear-gradient(transparent, transparent) padding-box,
99
- conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue)) border-box;
116
+ border: 2px solid transparent;
117
+ border-radius: calc(var(--ai-radius) + 3px);
118
+ background:
119
+ linear-gradient(transparent, transparent) padding-box,
120
+ linear-gradient(135deg, #60a5fa, #8b5cf6 48%, #22c55e) border-box;
100
121
  box-shadow:
101
- 0 0 30px color-mix(in srgb, var(--ai-blue), transparent 85%);
102
- transition: all 0.12s ease-out;
122
+ 0 0 0 4px rgba(37, 99, 235, 0.10),
123
+ 0 18px 46px rgba(37, 99, 235, 0.18);
124
+ transition:
125
+ left 120ms ease,
126
+ top 120ms ease,
127
+ width 120ms ease,
128
+ height 120ms ease;
103
129
  }
104
130
 
105
131
  .panel {
106
132
  position: fixed;
107
133
  z-index: 2147483646;
108
- width: 380px;
134
+ width: min(392px, calc(100vw - 32px));
109
135
  display: none;
110
- border: 1px solid rgba(17, 24, 39, 0.14);
111
- border-radius: var(--ai-radius);
112
- background: var(--ai-panel);
136
+ border: 1px solid rgba(15, 23, 42, 0.12);
137
+ border-radius: calc(var(--ai-radius) + 6px);
138
+ background:
139
+ radial-gradient(circle at 18% 0%, color-mix(in srgb, var(--ai-accent), transparent 88%), transparent 36%),
140
+ linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(255, 255, 255, 0.86)),
141
+ var(--ai-panel);
113
142
  color: var(--ai-text);
114
143
  text-align: left;
115
- box-shadow: 0 26px 70px rgba(15, 23, 42, 0.22);
144
+ box-shadow: var(--ai-shadow-lg);
116
145
  overflow: hidden;
146
+ backdrop-filter: blur(22px) saturate(1.18);
117
147
  }
118
148
 
119
149
  .panel.visible {
120
150
  display: block;
151
+ animation: panel-in 140ms ease-out;
121
152
  }
122
153
 
123
154
  .head {
124
- display: flex;
125
- align-items: center;
126
- justify-content: space-between;
155
+ display: grid;
156
+ grid-template-columns: minmax(0, 1fr) 34px;
157
+ align-items: start;
127
158
  gap: 14px;
128
- border-bottom: 1px solid rgba(17, 24, 39, 0.08);
129
- padding: 14px 14px 12px;
159
+ border-bottom: 1px solid rgba(15, 23, 42, 0.08);
160
+ padding: 16px 16px 13px;
130
161
  }
131
162
 
132
163
  .kind {
133
- display: block;
134
- margin-bottom: 4px;
135
- color: var(--ai-blue);
136
- font: 800 11px/1 Inter, ui-sans-serif, system-ui, sans-serif;
164
+ display: inline-flex;
165
+ align-items: center;
166
+ width: fit-content;
167
+ max-width: 100%;
168
+ min-height: 22px;
169
+ margin-bottom: 7px;
170
+ border: 1px solid color-mix(in srgb, var(--ai-accent), transparent 72%);
171
+ border-radius: 999px;
172
+ background: var(--ai-accent-soft);
173
+ color: var(--ai-accent-strong);
174
+ padding: 0 8px;
175
+ font: 800 10px/1 Inter, ui-sans-serif, system-ui, sans-serif;
176
+ letter-spacing: 0.04em;
137
177
  text-transform: uppercase;
138
178
  }
139
179
 
140
180
  .label {
141
- display: block;
181
+ display: -webkit-box;
142
182
  color: var(--ai-text);
143
- font: 700 14px/1.25 Inter, ui-sans-serif, system-ui, sans-serif;
183
+ font: 760 15px/1.35 Inter, ui-sans-serif, system-ui, sans-serif;
184
+ letter-spacing: 0;
185
+ overflow: hidden;
186
+ -webkit-box-orient: vertical;
187
+ -webkit-line-clamp: 2;
144
188
  }
145
189
 
146
190
  button {
147
- border: 1px solid rgba(17, 24, 39, 0.12);
148
- border-radius: var(--ai-radius);
149
- min-height: 40px;
150
- background: #111827;
191
+ appearance: none;
192
+ border: 1px solid rgba(15, 23, 42, 0.12);
193
+ border-radius: calc(var(--ai-radius) - 2px);
194
+ min-height: 42px;
195
+ background: #0f172a;
151
196
  color: #ffffff;
152
- font: 700 14px/1 Inter, ui-sans-serif, system-ui, sans-serif;
197
+ font: 760 14px/1 Inter, ui-sans-serif, system-ui, sans-serif;
198
+ letter-spacing: 0;
153
199
  cursor: pointer;
200
+ transition:
201
+ transform 120ms ease,
202
+ box-shadow 120ms ease,
203
+ background 120ms ease,
204
+ border-color 120ms ease,
205
+ opacity 120ms ease;
206
+ }
207
+
208
+ button:hover:not(:disabled) {
209
+ transform: translateY(-1px);
210
+ box-shadow: 0 10px 20px rgba(15, 23, 42, 0.16);
211
+ }
212
+
213
+ button:active:not(:disabled) {
214
+ transform: translateY(0);
215
+ }
216
+
217
+ button:focus-visible,
218
+ textarea:focus-visible {
219
+ outline: 3px solid color-mix(in srgb, var(--ai-accent), transparent 78%);
220
+ outline-offset: 2px;
154
221
  }
155
222
 
156
223
  button:disabled {
157
224
  cursor: not-allowed;
158
- opacity: 0.56;
225
+ opacity: 0.58;
226
+ transform: none;
227
+ box-shadow: none;
159
228
  }
160
229
 
161
230
  .close {
162
231
  min-width: 34px;
163
232
  min-height: 34px;
233
+ border-radius: 999px;
164
234
  padding: 0;
165
- background: #f3f4f6;
166
- color: #111827;
235
+ background: rgba(255, 255, 255, 0.72);
236
+ color: var(--ai-muted);
237
+ font-size: 18px;
238
+ line-height: 1;
239
+ }
240
+
241
+ .close:hover:not(:disabled) {
242
+ background: #ffffff;
243
+ color: var(--ai-text);
167
244
  }
168
245
 
169
246
  form {
170
247
  display: grid;
171
- gap: 10px;
172
- padding: 14px;
248
+ gap: 12px;
249
+ padding: 14px 16px 16px;
173
250
  }
174
251
 
175
252
  textarea {
176
- box-sizing: border-box;
177
253
  width: 100%;
178
254
  resize: vertical;
179
- min-height: 86px;
180
- max-height: 180px;
181
- border: 1px solid rgba(17, 24, 39, 0.16);
182
- border-radius: var(--ai-radius);
183
- padding: 12px;
255
+ min-height: 96px;
256
+ max-height: 190px;
257
+ border: 1px solid rgba(15, 23, 42, 0.14);
258
+ border-radius: calc(var(--ai-radius) + 1px);
259
+ padding: 12px 13px;
184
260
  color: #111827;
185
- background: #ffffff;
186
- font: 15px/1.45 Inter, ui-sans-serif, system-ui, sans-serif;
261
+ background: rgba(255, 255, 255, 0.88);
262
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
263
+ font: 450 14px/1.5 Inter, ui-sans-serif, system-ui, sans-serif;
264
+ letter-spacing: 0;
265
+ }
266
+
267
+ textarea::placeholder {
268
+ color: rgba(75, 85, 99, 0.72);
187
269
  }
188
270
 
189
271
  textarea:focus {
190
- border-color: var(--ai-blue);
191
- outline: 3px solid color-mix(in srgb, var(--ai-blue), transparent 86%);
272
+ border-color: color-mix(in srgb, var(--ai-accent), transparent 22%);
273
+ background: #ffffff;
274
+ outline: none;
275
+ }
276
+
277
+ .submit {
278
+ border-color: color-mix(in srgb, var(--ai-accent-strong), black 14%);
279
+ background:
280
+ linear-gradient(180deg, color-mix(in srgb, var(--ai-accent), white 8%), var(--ai-accent-strong));
281
+ box-shadow: 0 12px 22px color-mix(in srgb, var(--ai-accent), transparent 78%);
192
282
  }
193
283
 
194
284
  .error,
195
285
  .answer {
196
286
  display: none;
197
- margin: 0 14px 14px;
198
- border-radius: var(--ai-radius);
199
- padding: 12px;
200
- font: 14px/1.45 Inter, ui-sans-serif, system-ui, sans-serif;
287
+ margin: 0 16px 16px;
288
+ border-radius: calc(var(--ai-radius) + 1px);
289
+ padding: 12px 13px;
290
+ font: 440 14px/1.5 Inter, ui-sans-serif, system-ui, sans-serif;
291
+ letter-spacing: 0;
201
292
  white-space: pre-wrap;
202
293
  }
203
294
 
@@ -207,18 +298,25 @@
207
298
  }
208
299
 
209
300
  .error {
210
- background: #fef2f2;
211
- color: #991b1b;
301
+ border: 1px solid rgba(220, 38, 38, 0.18);
302
+ background: #fff1f2;
303
+ color: #9f1239;
212
304
  }
213
305
 
214
306
  .answer {
215
- max-height: 220px;
307
+ max-height: 230px;
216
308
  overflow: auto;
217
- background: #f8fafc;
309
+ border: 1px solid rgba(15, 23, 42, 0.08);
310
+ background: rgba(248, 250, 252, 0.82);
218
311
  color: #111827;
219
312
  }
220
313
 
221
314
  @media (max-width: 760px) {
315
+ .toast {
316
+ right: 12px;
317
+ bottom: 12px;
318
+ }
319
+
222
320
  .panel {
223
321
  left: 12px !important;
224
322
  right: 12px;
@@ -228,13 +326,40 @@
228
326
  }
229
327
  }
230
328
 
329
+ @media (prefers-reduced-motion: reduce) {
330
+ *,
331
+ *::before,
332
+ *::after {
333
+ animation-duration: 0.001ms !important;
334
+ animation-iteration-count: 1 !important;
335
+ transition-duration: 0.001ms !important;
336
+ }
337
+ }
338
+
231
339
  @keyframes pulse-ring {
232
- 70% { box-shadow: 0 0 0 8px transparent; }
233
- 100% { box-shadow: 0 0 0 0 transparent; }
340
+ 0% {
341
+ opacity: 0.75;
342
+ transform: scale(0.74);
343
+ }
344
+ 100% {
345
+ opacity: 0;
346
+ transform: scale(1.55);
347
+ }
348
+ }
349
+
350
+ @keyframes panel-in {
351
+ from {
352
+ opacity: 0;
353
+ transform: translateY(6px) scale(0.985);
354
+ }
355
+ to {
356
+ opacity: 1;
357
+ transform: translateY(0) scale(1);
358
+ }
234
359
  }
235
360
  </style>
236
361
  <div class="custom-cursor">
237
- <svg viewBox="0 0 28 32" class="cursor-shape">
362
+ <svg viewBox="0 0 28 32" class="cursor-shape" aria-hidden="true">
238
363
  <path d="M2,2 L2,28 L8,22 L14,32 L18,29 L12,19 L22,19 Z" stroke-linejoin="round" stroke-linecap="round" />
239
364
  </svg>
240
365
  </div>
@@ -250,7 +375,7 @@
250
375
  <span class="kind"></span>
251
376
  <strong class="label"></strong>
252
377
  </div>
253
- <button class="close" type="button" aria-label="Close AI prompt">x</button>
378
+ <button class="close" type="button" aria-label="Close AI prompt">×</button>
254
379
  </div>
255
380
  <form>
256
381
  <textarea placeholder="Ask what to do with this selection..."></textarea>
@@ -259,4 +384,4 @@
259
384
  <p class="error"></p>
260
385
  <div class="answer"></div>
261
386
  </section>
262
- `;let a=i.querySelector(`.custom-cursor`),o=i.querySelector(`.toast`),s=i.querySelector(`.count`),c=i.querySelector(`.hover`),l=i.querySelector(`.panel`),u=i.querySelector(`.kind`),d=i.querySelector(`.label`),f=i.querySelector(`form`),p=i.querySelector(`textarea`),m=i.querySelector(`.submit`),h=i.querySelector(`.close`),g=i.querySelector(`.error`),_=i.querySelector(`.answer`);if(!a||!o||!s||!c||!l||!u||!d||!f||!p||!m||!h||!g||!_)throw Error(`AIOverlay UI failed to initialize`);let v=e=>{a.style.left=`${e.clientX}px`,a.style.top=`${e.clientY}px`};return f.addEventListener(`submit`,t=>{t.preventDefault();let n=p.value.trim();n&&e.onSubmit(n)}),h.addEventListener(`click`,()=>{e.onCancel()}),{root:n,contains:e=>e===n||n.contains(e),setActive:(e,t)=>{o.classList.toggle(`active`,e),a.classList.toggle(`active`,e),s.textContent=`shakes ${t}`,e?window.addEventListener(`mousemove`,v):window.removeEventListener(`mousemove`,v)},setHoverRect:e=>{if(!e){c.style.display=`none`;return}c.style.display=`block`,c.style.left=`${e.left}px`,c.style.top=`${e.top}px`,c.style.width=`${e.width}px`,c.style.height=`${e.height}px`},showPrompt:e=>{let n=t(e.rect.left+e.rect.width/2-190,16,window.innerWidth-396),r=t(e.rect.bottom+14,16,window.innerHeight-380);u.textContent=e.kind,d.textContent=e.label,p.value=``,m.disabled=!1,m.textContent=`Ask AI`,g.classList.remove(`visible`),_.classList.remove(`visible`),l.style.left=`${n}px`,l.style.top=`${r}px`,l.classList.add(`visible`),p.focus()},setThinking:e=>{m.disabled=e,m.textContent=e?`Thinking...`:`Ask AI`},setAnswer:e=>{_.textContent=e,_.classList.toggle(`visible`,!!e)},setError:e=>{g.textContent=e,g.classList.toggle(`visible`,!!e)},clearSelection:()=>{l.classList.remove(`visible`),g.classList.remove(`visible`),_.classList.remove(`visible`),p.value=``},destroy:()=>{r.remove(),n.remove(),window.removeEventListener(`mousemove`,v)}}}var v={primaryColor:`#14b8a6`,panelBackground:`rgba(255, 255, 255, 0.96)`,textColor:`#111827`,borderRadius:8},y={shake:!0,keyboardShortcut:`mod+k`},b={text:!0,images:!0,elements:!0,blockedSelectors:[`input[type="password"]`,`[data-ai-private]`,`[data-ai-overlay-ignore]`],allowedSelectors:[]},x=class{active=!1;shakeCount=0;selection=null;disposers=[];ui;config;trigger;constructor(e){this.config=e,this.trigger={...y,...e.trigger};let t={...b,...e.selection};this.ui=_({theme:{...v,...e.theme},onSubmit:e=>{this.ask(e)},onCancel:()=>{this.clearSelection()}}),this.trigger.shake&&this.disposers.push(d({onShake:()=>{this.shakeCount+=1,this.activate()}})),this.disposers.push(u({config:t,isActive:()=>this.active,isOverlayElement:e=>this.ui.contains(e),onHover:e=>{this.ui.setHoverRect(this.selection?null:e)},onSelection:e=>{this.selection=e,this.ui.setHoverRect(null),this.ui.showPrompt(e),this.config.onSelection?.(e)}})),this.disposers.push(this.bindKeyboardShortcut())}activate(){if(this.active){this.ui.setActive(!0,this.shakeCount);return}this.active=!0,document.body.classList.add(`ai-overlay-active`),this.ui.setActive(!0,this.shakeCount),this.config.onActivate?.()}deactivate(){this.active&&(this.active=!1,this.clearSelection(),this.ui.setHoverRect(null),this.ui.setActive(!1,this.shakeCount),document.body.classList.remove(`ai-overlay-active`),this.config.onDeactivate?.())}destroy(){for(let e of this.disposers)e();this.disposers=[],this.deactivate(),this.ui.destroy()}isActive(){return this.active}clearSelection(){this.selection=null,this.ui.clearSelection(),window.getSelection()?.removeAllRanges()}async ask(e){if(!this.selection)return;let t={question:e,selection:this.selection};this.config.onAsk?.(t),this.ui.setThinking(!0),this.ui.setAnswer(``),this.ui.setError(``);try{let e=this.config.siteKey?await g({apiBaseUrl:this.config.apiBaseUrl,siteKey:this.config.siteKey,payload:t}):await h(this.config.model??{},t);this.ui.setAnswer(e),this.config.onResponse?.(e,t)}catch(e){let t=e instanceof Error?e:Error(`Unknown AIOverlay error`);this.ui.setError(t.message),this.config.onError?.(t)}finally{this.ui.setThinking(!1)}}bindKeyboardShortcut(){let e=this.trigger.keyboardShortcut.toLowerCase(),t=t=>{let n=e.includes(`mod+`),r=e.split(`+`).at(-1),a=i()?t.metaKey:t.ctrlKey;n&&!a||r&&t.key.toLowerCase()===r&&(t.preventDefault(),this.active?this.deactivate():this.activate())};return document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`keydown`,t)}}},S={init(e={}){return new x(e)}};typeof window<`u`&&(window.AIOverlay=S),e.AIOverlay=S})(this.AIOverlayBundle=this.AIOverlayBundle||{});
387
+ `;let a=i.querySelector(`.custom-cursor`),o=i.querySelector(`.toast`),s=i.querySelector(`.count`),c=i.querySelector(`.hover`),l=i.querySelector(`.panel`),u=i.querySelector(`.kind`),d=i.querySelector(`.label`),f=i.querySelector(`form`),p=i.querySelector(`textarea`),m=i.querySelector(`.submit`),h=i.querySelector(`.close`),g=i.querySelector(`.error`),_=i.querySelector(`.answer`);if(!a||!o||!s||!c||!l||!u||!d||!f||!p||!m||!h||!g||!_)throw Error(`AIOverlay UI failed to initialize`);let v=e=>{a.style.left=`${e.clientX}px`,a.style.top=`${e.clientY}px`};return f.addEventListener(`submit`,t=>{t.preventDefault();let n=p.value.trim();n&&e.onSubmit(n)}),h.addEventListener(`click`,()=>{e.onCancel()}),{root:n,contains:e=>e===n||n.contains(e),setActive:(e,t)=>{o.classList.toggle(`active`,e),a.classList.toggle(`active`,e),s.textContent=`shakes ${t}`,e?window.addEventListener(`mousemove`,v):window.removeEventListener(`mousemove`,v)},setHoverRect:e=>{if(!e){c.style.display=`none`;return}c.style.display=`block`,c.style.left=`${e.left}px`,c.style.top=`${e.top}px`,c.style.width=`${e.width}px`,c.style.height=`${e.height}px`},showPrompt:e=>{let n=t(e.rect.left+e.rect.width/2-196,16,window.innerWidth-408),r=t(e.rect.bottom+14,16,window.innerHeight-396);u.textContent=e.kind,d.textContent=e.label,p.value=``,m.disabled=!1,m.textContent=`Ask AI`,g.classList.remove(`visible`),_.classList.remove(`visible`),l.style.left=`${n}px`,l.style.top=`${r}px`,l.classList.add(`visible`),p.focus()},setThinking:e=>{m.disabled=e,m.textContent=e?`Thinking...`:`Ask AI`},setAnswer:e=>{_.textContent=e,_.classList.toggle(`visible`,!!e)},setError:e=>{g.textContent=e,g.classList.toggle(`visible`,!!e)},clearSelection:()=>{l.classList.remove(`visible`),g.classList.remove(`visible`),_.classList.remove(`visible`),p.value=``},destroy:()=>{r.remove(),n.remove(),window.removeEventListener(`mousemove`,v)}}}var v={primaryColor:`#14b8a6`,panelBackground:`rgba(255, 255, 255, 0.96)`,textColor:`#111827`,borderRadius:8},y={shake:!0,keyboardShortcut:`mod+k`},b={text:!0,images:!0,elements:!0,blockedSelectors:[`input[type="password"]`,`[data-ai-private]`,`[data-ai-overlay-ignore]`],allowedSelectors:[]},x=class{active=!1;shakeCount=0;selection=null;disposers=[];ui;config;trigger;constructor(e){this.config=e,this.trigger={...y,...e.trigger};let t={...b,...e.selection};this.ui=_({theme:{...v,...e.theme},onSubmit:e=>{this.ask(e)},onCancel:()=>{this.clearSelection()}}),this.trigger.shake&&this.disposers.push(d({onShake:()=>{this.shakeCount+=1,this.activate()}})),this.disposers.push(u({config:t,isActive:()=>this.active,isOverlayElement:e=>this.ui.contains(e),onHover:e=>{this.ui.setHoverRect(this.selection?null:e)},onSelection:e=>{this.selection=e,this.ui.setHoverRect(null),this.ui.showPrompt(e),this.config.onSelection?.(e)}})),this.disposers.push(this.bindKeyboardShortcut())}activate(){if(this.active){this.ui.setActive(!0,this.shakeCount);return}this.active=!0,document.body.classList.add(`ai-overlay-active`),this.ui.setActive(!0,this.shakeCount),this.config.onActivate?.()}deactivate(){this.active&&(this.active=!1,this.clearSelection(),this.ui.setHoverRect(null),this.ui.setActive(!1,this.shakeCount),document.body.classList.remove(`ai-overlay-active`),this.config.onDeactivate?.())}destroy(){for(let e of this.disposers)e();this.disposers=[],this.deactivate(),this.ui.destroy()}isActive(){return this.active}clearSelection(){this.selection=null,this.ui.clearSelection(),window.getSelection()?.removeAllRanges()}async ask(e){if(!this.selection)return;let t={question:e,selection:this.selection};this.config.onAsk?.(t),this.ui.setThinking(!0),this.ui.setAnswer(``),this.ui.setError(``);try{let e=this.config.siteKey?await g({apiBaseUrl:this.config.apiBaseUrl,siteKey:this.config.siteKey,payload:t}):await h(this.config.model??{},t);this.ui.setAnswer(e),this.config.onResponse?.(e,t)}catch(e){let t=e instanceof Error?e:Error(`Unknown AIOverlay error`);this.ui.setError(t.message),this.config.onError?.(t)}finally{this.ui.setThinking(!1)}}bindKeyboardShortcut(){let e=this.trigger.keyboardShortcut.toLowerCase(),t=t=>{let n=e.includes(`mod+`),r=e.split(`+`).at(-1),a=i()?t.metaKey:t.ctrlKey;n&&!a||r&&t.key.toLowerCase()===r&&(t.preventDefault(),this.active?this.deactivate():this.activate())};return document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`keydown`,t)}}},S={init(e={}){return new x(e)}};typeof window<`u`&&(window.AIOverlay=S),e.AIOverlay=S})(this.AIOverlayBundle=this.AIOverlayBundle||{});
package/dist/overlay.js CHANGED
@@ -77,7 +77,9 @@ function s(e) {
77
77
  };
78
78
  }
79
79
  function c(e, t) {
80
- return !(n(e, t.blockedSelectors) || t.allowedSelectors.length > 0 && !n(e, t.allowedSelectors));
80
+ if (n(e, t.blockedSelectors)) return !1;
81
+ let r = e.getBoundingClientRect(), i = window.innerWidth * window.innerHeight;
82
+ return !(r.width * r.height > i * .5 || t.allowedSelectors.length > 0 && !n(e, t.allowedSelectors));
81
83
  }
82
84
  function l(e) {
83
85
  let n = (t) => {
@@ -216,36 +218,45 @@ function g(t) {
216
218
  let n = document.createElement("div");
217
219
  n.dataset.aiOverlayRoot = "true";
218
220
  let r = document.createElement("style");
219
- r.dataset.aiOverlayStyle = "true", r.textContent = "\n body.ai-overlay-active { \n cursor: none !important; \n }\n body.ai-overlay-active * { \n cursor: none !important; \n }\n ";
221
+ r.dataset.aiOverlayStyle = "true", r.textContent = "\n body.ai-overlay-active,\n body.ai-overlay-active * {\n cursor: none !important;\n }\n ";
220
222
  let i = n.attachShadow({ mode: "open" });
221
223
  document.head.append(r), document.body.append(n), i.innerHTML = `
222
224
  <style>
223
225
  :host {
224
226
  all: initial;
225
- --ai-blue: #4285F4;
226
- --ai-red: #DB4437;
227
- --ai-yellow: #F4B400;
228
- --ai-green: #0F9D58;
229
- --ai-primary: ${t.theme.primaryColor};
227
+ --ai-accent: ${t.theme.primaryColor};
228
+ --ai-accent-strong: #2563eb;
229
+ --ai-accent-soft: color-mix(in srgb, var(--ai-accent), white 88%);
230
230
  --ai-panel: ${t.theme.panelBackground};
231
+ --ai-panel-raised: color-mix(in srgb, var(--ai-panel), white 7%);
231
232
  --ai-text: ${t.theme.textColor};
233
+ --ai-muted: color-mix(in srgb, var(--ai-text), transparent 42%);
234
+ --ai-faint: color-mix(in srgb, var(--ai-text), transparent 88%);
235
+ --ai-border: color-mix(in srgb, var(--ai-text), transparent 86%);
232
236
  --ai-radius: ${t.theme.borderRadius}px;
237
+ --ai-shadow-lg: 0 24px 70px rgba(15, 23, 42, 0.22), 0 8px 24px rgba(15, 23, 42, 0.10);
238
+ --ai-shadow-md: 0 14px 36px rgba(15, 23, 42, 0.16), 0 3px 10px rgba(15, 23, 42, 0.08);
239
+ color: var(--ai-text);
233
240
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
234
241
  }
235
242
 
243
+ * {
244
+ box-sizing: border-box;
245
+ }
246
+
236
247
  .custom-cursor {
237
248
  position: fixed;
238
249
  left: 0;
239
250
  top: 0;
240
- width: 32px;
241
- height: 32px;
251
+ width: 34px;
252
+ height: 34px;
242
253
  pointer-events: none;
243
254
  z-index: 2147483647;
244
255
  display: none;
245
- /* Offset to center the "tip" of the pointer */
246
- margin-left: -4px;
247
- margin-top: -4px;
248
- filter: drop-shadow(0 0 8px rgba(66, 133, 244, 0.6));
256
+ margin-left: -5px;
257
+ margin-top: -5px;
258
+ color: var(--ai-accent-strong);
259
+ filter: drop-shadow(0 10px 16px rgba(37, 99, 235, 0.28));
249
260
  }
250
261
 
251
262
  .custom-cursor.active {
@@ -255,9 +266,9 @@ function g(t) {
255
266
  .cursor-shape {
256
267
  width: 100%;
257
268
  height: 100%;
258
- fill: white;
259
- stroke: var(--ai-blue);
260
- stroke-width: 2px;
269
+ fill: #ffffff;
270
+ stroke: currentColor;
271
+ stroke-width: 2;
261
272
  }
262
273
 
263
274
  .toast {
@@ -268,13 +279,18 @@ function g(t) {
268
279
  display: none;
269
280
  align-items: center;
270
281
  gap: 10px;
271
- border: 1px solid color-mix(in srgb, var(--ai-primary), transparent 74%);
272
- border-radius: var(--ai-radius);
273
- background: var(--ai-panel);
282
+ min-height: 42px;
283
+ border: 1px solid color-mix(in srgb, var(--ai-accent), transparent 78%);
284
+ border-radius: 999px;
285
+ background:
286
+ linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.74)),
287
+ var(--ai-panel);
274
288
  color: var(--ai-text);
275
- padding: 10px 12px;
276
- font: 700 13px/1 Inter, ui-sans-serif, system-ui, sans-serif;
277
- box-shadow: 0 16px 42px rgba(15, 23, 42, 0.18);
289
+ padding: 8px 10px 8px 12px;
290
+ font: 700 12px/1 Inter, ui-sans-serif, system-ui, sans-serif;
291
+ letter-spacing: 0;
292
+ box-shadow: var(--ai-shadow-md);
293
+ backdrop-filter: blur(18px) saturate(1.25);
278
294
  }
279
295
 
280
296
  .toast.active {
@@ -282,18 +298,28 @@ function g(t) {
282
298
  }
283
299
 
284
300
  .pulse {
285
- width: 8px;
286
- height: 8px;
301
+ position: relative;
302
+ width: 9px;
303
+ height: 9px;
287
304
  border-radius: 999px;
288
- background: var(--ai-primary);
289
- box-shadow: 0 0 0 0 color-mix(in srgb, var(--ai-primary), transparent 38%);
290
- animation: pulse-ring 1.3s infinite;
305
+ background: var(--ai-accent);
306
+ box-shadow: 0 0 0 5px color-mix(in srgb, var(--ai-accent), transparent 86%);
307
+ }
308
+
309
+ .pulse::after {
310
+ content: "";
311
+ position: absolute;
312
+ inset: -6px;
313
+ border-radius: inherit;
314
+ border: 1px solid color-mix(in srgb, var(--ai-accent), transparent 58%);
315
+ animation: pulse-ring 1.45s cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
291
316
  }
292
317
 
293
318
  .count {
294
- border-left: 1px solid rgba(15, 23, 42, 0.12);
295
- padding-left: 10px;
296
- opacity: 0.72;
319
+ border-left: 1px solid var(--ai-border);
320
+ padding: 4px 2px 4px 10px;
321
+ color: var(--ai-muted);
322
+ font-weight: 650;
297
323
  }
298
324
 
299
325
  .hover {
@@ -301,113 +327,182 @@ function g(t) {
301
327
  z-index: 2147483644;
302
328
  pointer-events: none;
303
329
  display: none;
304
- /* Thicker, more professional border */
305
- border: 4px solid transparent;
306
- border-radius: var(--ai-radius);
307
- /*Conic gradient on border only, no gray background fill */
308
- background: linear-gradient(transparent, transparent) padding-box,
309
- conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue)) border-box;
330
+ border: 2px solid transparent;
331
+ border-radius: calc(var(--ai-radius) + 3px);
332
+ background:
333
+ linear-gradient(transparent, transparent) padding-box,
334
+ linear-gradient(135deg, #60a5fa, #8b5cf6 48%, #22c55e) border-box;
310
335
  box-shadow:
311
- 0 0 30px color-mix(in srgb, var(--ai-blue), transparent 85%);
312
- transition: all 0.12s ease-out;
336
+ 0 0 0 4px rgba(37, 99, 235, 0.10),
337
+ 0 18px 46px rgba(37, 99, 235, 0.18);
338
+ transition:
339
+ left 120ms ease,
340
+ top 120ms ease,
341
+ width 120ms ease,
342
+ height 120ms ease;
313
343
  }
314
344
 
315
345
  .panel {
316
346
  position: fixed;
317
347
  z-index: 2147483646;
318
- width: 380px;
348
+ width: min(392px, calc(100vw - 32px));
319
349
  display: none;
320
- border: 1px solid rgba(17, 24, 39, 0.14);
321
- border-radius: var(--ai-radius);
322
- background: var(--ai-panel);
350
+ border: 1px solid rgba(15, 23, 42, 0.12);
351
+ border-radius: calc(var(--ai-radius) + 6px);
352
+ background:
353
+ radial-gradient(circle at 18% 0%, color-mix(in srgb, var(--ai-accent), transparent 88%), transparent 36%),
354
+ linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(255, 255, 255, 0.86)),
355
+ var(--ai-panel);
323
356
  color: var(--ai-text);
324
357
  text-align: left;
325
- box-shadow: 0 26px 70px rgba(15, 23, 42, 0.22);
358
+ box-shadow: var(--ai-shadow-lg);
326
359
  overflow: hidden;
360
+ backdrop-filter: blur(22px) saturate(1.18);
327
361
  }
328
362
 
329
363
  .panel.visible {
330
364
  display: block;
365
+ animation: panel-in 140ms ease-out;
331
366
  }
332
367
 
333
368
  .head {
334
- display: flex;
335
- align-items: center;
336
- justify-content: space-between;
369
+ display: grid;
370
+ grid-template-columns: minmax(0, 1fr) 34px;
371
+ align-items: start;
337
372
  gap: 14px;
338
- border-bottom: 1px solid rgba(17, 24, 39, 0.08);
339
- padding: 14px 14px 12px;
373
+ border-bottom: 1px solid rgba(15, 23, 42, 0.08);
374
+ padding: 16px 16px 13px;
340
375
  }
341
376
 
342
377
  .kind {
343
- display: block;
344
- margin-bottom: 4px;
345
- color: var(--ai-blue);
346
- font: 800 11px/1 Inter, ui-sans-serif, system-ui, sans-serif;
378
+ display: inline-flex;
379
+ align-items: center;
380
+ width: fit-content;
381
+ max-width: 100%;
382
+ min-height: 22px;
383
+ margin-bottom: 7px;
384
+ border: 1px solid color-mix(in srgb, var(--ai-accent), transparent 72%);
385
+ border-radius: 999px;
386
+ background: var(--ai-accent-soft);
387
+ color: var(--ai-accent-strong);
388
+ padding: 0 8px;
389
+ font: 800 10px/1 Inter, ui-sans-serif, system-ui, sans-serif;
390
+ letter-spacing: 0.04em;
347
391
  text-transform: uppercase;
348
392
  }
349
393
 
350
394
  .label {
351
- display: block;
395
+ display: -webkit-box;
352
396
  color: var(--ai-text);
353
- font: 700 14px/1.25 Inter, ui-sans-serif, system-ui, sans-serif;
397
+ font: 760 15px/1.35 Inter, ui-sans-serif, system-ui, sans-serif;
398
+ letter-spacing: 0;
399
+ overflow: hidden;
400
+ -webkit-box-orient: vertical;
401
+ -webkit-line-clamp: 2;
354
402
  }
355
403
 
356
404
  button {
357
- border: 1px solid rgba(17, 24, 39, 0.12);
358
- border-radius: var(--ai-radius);
359
- min-height: 40px;
360
- background: #111827;
405
+ appearance: none;
406
+ border: 1px solid rgba(15, 23, 42, 0.12);
407
+ border-radius: calc(var(--ai-radius) - 2px);
408
+ min-height: 42px;
409
+ background: #0f172a;
361
410
  color: #ffffff;
362
- font: 700 14px/1 Inter, ui-sans-serif, system-ui, sans-serif;
411
+ font: 760 14px/1 Inter, ui-sans-serif, system-ui, sans-serif;
412
+ letter-spacing: 0;
363
413
  cursor: pointer;
414
+ transition:
415
+ transform 120ms ease,
416
+ box-shadow 120ms ease,
417
+ background 120ms ease,
418
+ border-color 120ms ease,
419
+ opacity 120ms ease;
420
+ }
421
+
422
+ button:hover:not(:disabled) {
423
+ transform: translateY(-1px);
424
+ box-shadow: 0 10px 20px rgba(15, 23, 42, 0.16);
425
+ }
426
+
427
+ button:active:not(:disabled) {
428
+ transform: translateY(0);
429
+ }
430
+
431
+ button:focus-visible,
432
+ textarea:focus-visible {
433
+ outline: 3px solid color-mix(in srgb, var(--ai-accent), transparent 78%);
434
+ outline-offset: 2px;
364
435
  }
365
436
 
366
437
  button:disabled {
367
438
  cursor: not-allowed;
368
- opacity: 0.56;
439
+ opacity: 0.58;
440
+ transform: none;
441
+ box-shadow: none;
369
442
  }
370
443
 
371
444
  .close {
372
445
  min-width: 34px;
373
446
  min-height: 34px;
447
+ border-radius: 999px;
374
448
  padding: 0;
375
- background: #f3f4f6;
376
- color: #111827;
449
+ background: rgba(255, 255, 255, 0.72);
450
+ color: var(--ai-muted);
451
+ font-size: 18px;
452
+ line-height: 1;
453
+ }
454
+
455
+ .close:hover:not(:disabled) {
456
+ background: #ffffff;
457
+ color: var(--ai-text);
377
458
  }
378
459
 
379
460
  form {
380
461
  display: grid;
381
- gap: 10px;
382
- padding: 14px;
462
+ gap: 12px;
463
+ padding: 14px 16px 16px;
383
464
  }
384
465
 
385
466
  textarea {
386
- box-sizing: border-box;
387
467
  width: 100%;
388
468
  resize: vertical;
389
- min-height: 86px;
390
- max-height: 180px;
391
- border: 1px solid rgba(17, 24, 39, 0.16);
392
- border-radius: var(--ai-radius);
393
- padding: 12px;
469
+ min-height: 96px;
470
+ max-height: 190px;
471
+ border: 1px solid rgba(15, 23, 42, 0.14);
472
+ border-radius: calc(var(--ai-radius) + 1px);
473
+ padding: 12px 13px;
394
474
  color: #111827;
395
- background: #ffffff;
396
- font: 15px/1.45 Inter, ui-sans-serif, system-ui, sans-serif;
475
+ background: rgba(255, 255, 255, 0.88);
476
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
477
+ font: 450 14px/1.5 Inter, ui-sans-serif, system-ui, sans-serif;
478
+ letter-spacing: 0;
479
+ }
480
+
481
+ textarea::placeholder {
482
+ color: rgba(75, 85, 99, 0.72);
397
483
  }
398
484
 
399
485
  textarea:focus {
400
- border-color: var(--ai-blue);
401
- outline: 3px solid color-mix(in srgb, var(--ai-blue), transparent 86%);
486
+ border-color: color-mix(in srgb, var(--ai-accent), transparent 22%);
487
+ background: #ffffff;
488
+ outline: none;
489
+ }
490
+
491
+ .submit {
492
+ border-color: color-mix(in srgb, var(--ai-accent-strong), black 14%);
493
+ background:
494
+ linear-gradient(180deg, color-mix(in srgb, var(--ai-accent), white 8%), var(--ai-accent-strong));
495
+ box-shadow: 0 12px 22px color-mix(in srgb, var(--ai-accent), transparent 78%);
402
496
  }
403
497
 
404
498
  .error,
405
499
  .answer {
406
500
  display: none;
407
- margin: 0 14px 14px;
408
- border-radius: var(--ai-radius);
409
- padding: 12px;
410
- font: 14px/1.45 Inter, ui-sans-serif, system-ui, sans-serif;
501
+ margin: 0 16px 16px;
502
+ border-radius: calc(var(--ai-radius) + 1px);
503
+ padding: 12px 13px;
504
+ font: 440 14px/1.5 Inter, ui-sans-serif, system-ui, sans-serif;
505
+ letter-spacing: 0;
411
506
  white-space: pre-wrap;
412
507
  }
413
508
 
@@ -417,18 +512,25 @@ function g(t) {
417
512
  }
418
513
 
419
514
  .error {
420
- background: #fef2f2;
421
- color: #991b1b;
515
+ border: 1px solid rgba(220, 38, 38, 0.18);
516
+ background: #fff1f2;
517
+ color: #9f1239;
422
518
  }
423
519
 
424
520
  .answer {
425
- max-height: 220px;
521
+ max-height: 230px;
426
522
  overflow: auto;
427
- background: #f8fafc;
523
+ border: 1px solid rgba(15, 23, 42, 0.08);
524
+ background: rgba(248, 250, 252, 0.82);
428
525
  color: #111827;
429
526
  }
430
527
 
431
528
  @media (max-width: 760px) {
529
+ .toast {
530
+ right: 12px;
531
+ bottom: 12px;
532
+ }
533
+
432
534
  .panel {
433
535
  left: 12px !important;
434
536
  right: 12px;
@@ -438,13 +540,40 @@ function g(t) {
438
540
  }
439
541
  }
440
542
 
543
+ @media (prefers-reduced-motion: reduce) {
544
+ *,
545
+ *::before,
546
+ *::after {
547
+ animation-duration: 0.001ms !important;
548
+ animation-iteration-count: 1 !important;
549
+ transition-duration: 0.001ms !important;
550
+ }
551
+ }
552
+
441
553
  @keyframes pulse-ring {
442
- 70% { box-shadow: 0 0 0 8px transparent; }
443
- 100% { box-shadow: 0 0 0 0 transparent; }
554
+ 0% {
555
+ opacity: 0.75;
556
+ transform: scale(0.74);
557
+ }
558
+ 100% {
559
+ opacity: 0;
560
+ transform: scale(1.55);
561
+ }
562
+ }
563
+
564
+ @keyframes panel-in {
565
+ from {
566
+ opacity: 0;
567
+ transform: translateY(6px) scale(0.985);
568
+ }
569
+ to {
570
+ opacity: 1;
571
+ transform: translateY(0) scale(1);
572
+ }
444
573
  }
445
574
  </style>
446
575
  <div class="custom-cursor">
447
- <svg viewBox="0 0 28 32" class="cursor-shape">
576
+ <svg viewBox="0 0 28 32" class="cursor-shape" aria-hidden="true">
448
577
  <path d="M2,2 L2,28 L8,22 L14,32 L18,29 L12,19 L22,19 Z" stroke-linejoin="round" stroke-linecap="round" />
449
578
  </svg>
450
579
  </div>
@@ -460,7 +589,7 @@ function g(t) {
460
589
  <span class="kind"></span>
461
590
  <strong class="label"></strong>
462
591
  </div>
463
- <button class="close" type="button" aria-label="Close AI prompt">x</button>
592
+ <button class="close" type="button" aria-label="Close AI prompt">×</button>
464
593
  </div>
465
594
  <form>
466
595
  <textarea placeholder="Ask what to do with this selection..."></textarea>
@@ -495,7 +624,7 @@ function g(t) {
495
624
  c.style.display = "block", c.style.left = `${e.left}px`, c.style.top = `${e.top}px`, c.style.width = `${e.width}px`, c.style.height = `${e.height}px`;
496
625
  },
497
626
  showPrompt: (t) => {
498
- let n = e(t.rect.left + t.rect.width / 2 - 190, 16, window.innerWidth - 396), r = e(t.rect.bottom + 14, 16, window.innerHeight - 380);
627
+ let n = e(t.rect.left + t.rect.width / 2 - 196, 16, window.innerWidth - 408), r = e(t.rect.bottom + 14, 16, window.innerHeight - 396);
499
628
  u.textContent = t.kind, d.textContent = t.label, p.value = "", m.disabled = !1, m.textContent = "Ask AI", g.classList.remove("visible"), _.classList.remove("visible"), l.style.left = `${n}px`, l.style.top = `${r}px`, l.classList.add("visible"), p.focus();
500
629
  },
501
630
  setThinking: (e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emmaexcel/shakecursor",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Framework-agnostic browser SDK for contextual AI selection overlays.",
5
5
  "type": "module",
6
6
  "main": "./dist/overlay.global.js",