@emmaexcel/shakecursor 0.1.2 → 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,57 +1,60 @@
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: 24px;
31
- height: 24px;
37
+ width: 34px;
38
+ height: 34px;
32
39
  pointer-events: none;
33
40
  z-index: 2147483647;
34
41
  display: none;
35
- transform: translate(-50%, -50%);
36
- transition: transform 0.1s ease-out;
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));
37
46
  }
38
47
 
39
48
  .custom-cursor.active {
40
49
  display: block;
41
50
  }
42
51
 
43
- .cursor-dot {
52
+ .cursor-shape {
44
53
  width: 100%;
45
54
  height: 100%;
46
- background: conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue));
47
- border-radius: 50%;
48
- box-shadow: 0 0 15px rgba(66, 133, 244, 0.8), 0 0 30px rgba(15, 157, 88, 0.4);
49
- animation: rotate-gradient 2s linear infinite;
50
- }
51
-
52
- @keyframes rotate-gradient {
53
- from { transform: rotate(0deg); }
54
- to { transform: rotate(360deg); }
55
+ fill: #ffffff;
56
+ stroke: currentColor;
57
+ stroke-width: 2;
55
58
  }
56
59
 
57
60
  .toast {
@@ -62,13 +65,18 @@
62
65
  display: none;
63
66
  align-items: center;
64
67
  gap: 10px;
65
- border: 1px solid color-mix(in srgb, var(--ai-primary), transparent 74%);
66
- border-radius: var(--ai-radius);
67
- 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);
68
74
  color: var(--ai-text);
69
- padding: 10px 12px;
70
- font: 700 13px/1 Inter, ui-sans-serif, system-ui, sans-serif;
71
- 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);
72
80
  }
73
81
 
74
82
  .toast.active {
@@ -76,18 +84,28 @@
76
84
  }
77
85
 
78
86
  .pulse {
79
- width: 8px;
80
- height: 8px;
87
+ position: relative;
88
+ width: 9px;
89
+ height: 9px;
81
90
  border-radius: 999px;
82
- background: var(--ai-primary);
83
- box-shadow: 0 0 0 0 color-mix(in srgb, var(--ai-primary), transparent 38%);
84
- 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;
85
102
  }
86
103
 
87
104
  .count {
88
- border-left: 1px solid rgba(15, 23, 42, 0.12);
89
- padding-left: 10px;
90
- 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;
91
109
  }
92
110
 
93
111
  .hover {
@@ -96,112 +114,181 @@
96
114
  pointer-events: none;
97
115
  display: none;
98
116
  border: 2px solid transparent;
99
- border-radius: var(--ai-radius);
100
- background: linear-gradient(var(--ai-panel), var(--ai-panel)) padding-box,
101
- conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue)) border-box;
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;
102
121
  box-shadow:
103
- 0 0 20px color-mix(in srgb, var(--ai-blue), transparent 80%),
104
- 0 20px 52px rgba(15, 23, 42, 0.14);
105
- opacity: 0.3;
106
- transition: all 0.15s 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;
107
129
  }
108
130
 
109
131
  .panel {
110
132
  position: fixed;
111
133
  z-index: 2147483646;
112
- width: 380px;
134
+ width: min(392px, calc(100vw - 32px));
113
135
  display: none;
114
- border: 1px solid rgba(17, 24, 39, 0.14);
115
- border-radius: var(--ai-radius);
116
- 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);
117
142
  color: var(--ai-text);
118
143
  text-align: left;
119
- box-shadow: 0 26px 70px rgba(15, 23, 42, 0.22);
144
+ box-shadow: var(--ai-shadow-lg);
120
145
  overflow: hidden;
146
+ backdrop-filter: blur(22px) saturate(1.18);
121
147
  }
122
148
 
123
149
  .panel.visible {
124
150
  display: block;
151
+ animation: panel-in 140ms ease-out;
125
152
  }
126
153
 
127
154
  .head {
128
- display: flex;
129
- align-items: center;
130
- justify-content: space-between;
155
+ display: grid;
156
+ grid-template-columns: minmax(0, 1fr) 34px;
157
+ align-items: start;
131
158
  gap: 14px;
132
- border-bottom: 1px solid rgba(17, 24, 39, 0.08);
133
- padding: 14px 14px 12px;
159
+ border-bottom: 1px solid rgba(15, 23, 42, 0.08);
160
+ padding: 16px 16px 13px;
134
161
  }
135
162
 
136
163
  .kind {
137
- display: block;
138
- margin-bottom: 4px;
139
- color: var(--ai-blue);
140
- 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;
141
177
  text-transform: uppercase;
142
178
  }
143
179
 
144
180
  .label {
145
- display: block;
181
+ display: -webkit-box;
146
182
  color: var(--ai-text);
147
- 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;
148
188
  }
149
189
 
150
190
  button {
151
- border: 1px solid rgba(17, 24, 39, 0.12);
152
- border-radius: var(--ai-radius);
153
- min-height: 40px;
154
- 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;
155
196
  color: #ffffff;
156
- 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;
157
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;
158
221
  }
159
222
 
160
223
  button:disabled {
161
224
  cursor: not-allowed;
162
- opacity: 0.56;
225
+ opacity: 0.58;
226
+ transform: none;
227
+ box-shadow: none;
163
228
  }
164
229
 
165
230
  .close {
166
231
  min-width: 34px;
167
232
  min-height: 34px;
233
+ border-radius: 999px;
168
234
  padding: 0;
169
- background: #f3f4f6;
170
- 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);
171
244
  }
172
245
 
173
246
  form {
174
247
  display: grid;
175
- gap: 10px;
176
- padding: 14px;
248
+ gap: 12px;
249
+ padding: 14px 16px 16px;
177
250
  }
178
251
 
179
252
  textarea {
180
- box-sizing: border-box;
181
253
  width: 100%;
182
254
  resize: vertical;
183
- min-height: 86px;
184
- max-height: 180px;
185
- border: 1px solid rgba(17, 24, 39, 0.16);
186
- border-radius: var(--ai-radius);
187
- 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;
188
260
  color: #111827;
189
- background: #ffffff;
190
- 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);
191
269
  }
192
270
 
193
271
  textarea:focus {
194
- border-color: var(--ai-blue);
195
- 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%);
196
282
  }
197
283
 
198
284
  .error,
199
285
  .answer {
200
286
  display: none;
201
- margin: 0 14px 14px;
202
- border-radius: var(--ai-radius);
203
- padding: 12px;
204
- 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;
205
292
  white-space: pre-wrap;
206
293
  }
207
294
 
@@ -211,18 +298,25 @@
211
298
  }
212
299
 
213
300
  .error {
214
- background: #fef2f2;
215
- color: #991b1b;
301
+ border: 1px solid rgba(220, 38, 38, 0.18);
302
+ background: #fff1f2;
303
+ color: #9f1239;
216
304
  }
217
305
 
218
306
  .answer {
219
- max-height: 220px;
307
+ max-height: 230px;
220
308
  overflow: auto;
221
- background: #f8fafc;
309
+ border: 1px solid rgba(15, 23, 42, 0.08);
310
+ background: rgba(248, 250, 252, 0.82);
222
311
  color: #111827;
223
312
  }
224
313
 
225
314
  @media (max-width: 760px) {
315
+ .toast {
316
+ right: 12px;
317
+ bottom: 12px;
318
+ }
319
+
226
320
  .panel {
227
321
  left: 12px !important;
228
322
  right: 12px;
@@ -232,13 +326,42 @@
232
326
  }
233
327
  }
234
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
+
235
339
  @keyframes pulse-ring {
236
- 70% { box-shadow: 0 0 0 8px transparent; }
237
- 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
+ }
238
359
  }
239
360
  </style>
240
361
  <div class="custom-cursor">
241
- <div class="cursor-dot"></div>
362
+ <svg viewBox="0 0 28 32" class="cursor-shape" aria-hidden="true">
363
+ <path d="M2,2 L2,28 L8,22 L14,32 L18,29 L12,19 L22,19 Z" stroke-linejoin="round" stroke-linecap="round" />
364
+ </svg>
242
365
  </div>
243
366
  <div class="toast" role="status">
244
367
  <span class="pulse"></span>
@@ -252,7 +375,7 @@
252
375
  <span class="kind"></span>
253
376
  <strong class="label"></strong>
254
377
  </div>
255
- <button class="close" type="button" aria-label="Close AI prompt">x</button>
378
+ <button class="close" type="button" aria-label="Close AI prompt">×</button>
256
379
  </div>
257
380
  <form>
258
381
  <textarea placeholder="Ask what to do with this selection..."></textarea>
@@ -261,4 +384,4 @@
261
384
  <p class="error"></p>
262
385
  <div class="answer"></div>
263
386
  </section>
264
- `;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,52 +218,57 @@ 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: 24px;
241
- height: 24px;
251
+ width: 34px;
252
+ height: 34px;
242
253
  pointer-events: none;
243
254
  z-index: 2147483647;
244
255
  display: none;
245
- transform: translate(-50%, -50%);
246
- transition: transform 0.1s ease-out;
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));
247
260
  }
248
261
 
249
262
  .custom-cursor.active {
250
263
  display: block;
251
264
  }
252
265
 
253
- .cursor-dot {
266
+ .cursor-shape {
254
267
  width: 100%;
255
268
  height: 100%;
256
- background: conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue));
257
- border-radius: 50%;
258
- box-shadow: 0 0 15px rgba(66, 133, 244, 0.8), 0 0 30px rgba(15, 157, 88, 0.4);
259
- animation: rotate-gradient 2s linear infinite;
260
- }
261
-
262
- @keyframes rotate-gradient {
263
- from { transform: rotate(0deg); }
264
- to { transform: rotate(360deg); }
269
+ fill: #ffffff;
270
+ stroke: currentColor;
271
+ stroke-width: 2;
265
272
  }
266
273
 
267
274
  .toast {
@@ -272,13 +279,18 @@ function g(t) {
272
279
  display: none;
273
280
  align-items: center;
274
281
  gap: 10px;
275
- border: 1px solid color-mix(in srgb, var(--ai-primary), transparent 74%);
276
- border-radius: var(--ai-radius);
277
- 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);
278
288
  color: var(--ai-text);
279
- padding: 10px 12px;
280
- font: 700 13px/1 Inter, ui-sans-serif, system-ui, sans-serif;
281
- 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);
282
294
  }
283
295
 
284
296
  .toast.active {
@@ -286,18 +298,28 @@ function g(t) {
286
298
  }
287
299
 
288
300
  .pulse {
289
- width: 8px;
290
- height: 8px;
301
+ position: relative;
302
+ width: 9px;
303
+ height: 9px;
291
304
  border-radius: 999px;
292
- background: var(--ai-primary);
293
- box-shadow: 0 0 0 0 color-mix(in srgb, var(--ai-primary), transparent 38%);
294
- 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;
295
316
  }
296
317
 
297
318
  .count {
298
- border-left: 1px solid rgba(15, 23, 42, 0.12);
299
- padding-left: 10px;
300
- 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;
301
323
  }
302
324
 
303
325
  .hover {
@@ -306,112 +328,181 @@ function g(t) {
306
328
  pointer-events: none;
307
329
  display: none;
308
330
  border: 2px solid transparent;
309
- border-radius: var(--ai-radius);
310
- background: linear-gradient(var(--ai-panel), var(--ai-panel)) padding-box,
311
- conic-gradient(var(--ai-blue), var(--ai-red), var(--ai-yellow), var(--ai-green), var(--ai-blue)) border-box;
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;
312
335
  box-shadow:
313
- 0 0 20px color-mix(in srgb, var(--ai-blue), transparent 80%),
314
- 0 20px 52px rgba(15, 23, 42, 0.14);
315
- opacity: 0.3;
316
- transition: all 0.15s 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;
317
343
  }
318
344
 
319
345
  .panel {
320
346
  position: fixed;
321
347
  z-index: 2147483646;
322
- width: 380px;
348
+ width: min(392px, calc(100vw - 32px));
323
349
  display: none;
324
- border: 1px solid rgba(17, 24, 39, 0.14);
325
- border-radius: var(--ai-radius);
326
- 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);
327
356
  color: var(--ai-text);
328
357
  text-align: left;
329
- box-shadow: 0 26px 70px rgba(15, 23, 42, 0.22);
358
+ box-shadow: var(--ai-shadow-lg);
330
359
  overflow: hidden;
360
+ backdrop-filter: blur(22px) saturate(1.18);
331
361
  }
332
362
 
333
363
  .panel.visible {
334
364
  display: block;
365
+ animation: panel-in 140ms ease-out;
335
366
  }
336
367
 
337
368
  .head {
338
- display: flex;
339
- align-items: center;
340
- justify-content: space-between;
369
+ display: grid;
370
+ grid-template-columns: minmax(0, 1fr) 34px;
371
+ align-items: start;
341
372
  gap: 14px;
342
- border-bottom: 1px solid rgba(17, 24, 39, 0.08);
343
- padding: 14px 14px 12px;
373
+ border-bottom: 1px solid rgba(15, 23, 42, 0.08);
374
+ padding: 16px 16px 13px;
344
375
  }
345
376
 
346
377
  .kind {
347
- display: block;
348
- margin-bottom: 4px;
349
- color: var(--ai-blue);
350
- 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;
351
391
  text-transform: uppercase;
352
392
  }
353
393
 
354
394
  .label {
355
- display: block;
395
+ display: -webkit-box;
356
396
  color: var(--ai-text);
357
- 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;
358
402
  }
359
403
 
360
404
  button {
361
- border: 1px solid rgba(17, 24, 39, 0.12);
362
- border-radius: var(--ai-radius);
363
- min-height: 40px;
364
- 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;
365
410
  color: #ffffff;
366
- 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;
367
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;
368
435
  }
369
436
 
370
437
  button:disabled {
371
438
  cursor: not-allowed;
372
- opacity: 0.56;
439
+ opacity: 0.58;
440
+ transform: none;
441
+ box-shadow: none;
373
442
  }
374
443
 
375
444
  .close {
376
445
  min-width: 34px;
377
446
  min-height: 34px;
447
+ border-radius: 999px;
378
448
  padding: 0;
379
- background: #f3f4f6;
380
- 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);
381
458
  }
382
459
 
383
460
  form {
384
461
  display: grid;
385
- gap: 10px;
386
- padding: 14px;
462
+ gap: 12px;
463
+ padding: 14px 16px 16px;
387
464
  }
388
465
 
389
466
  textarea {
390
- box-sizing: border-box;
391
467
  width: 100%;
392
468
  resize: vertical;
393
- min-height: 86px;
394
- max-height: 180px;
395
- border: 1px solid rgba(17, 24, 39, 0.16);
396
- border-radius: var(--ai-radius);
397
- 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;
398
474
  color: #111827;
399
- background: #ffffff;
400
- 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);
401
483
  }
402
484
 
403
485
  textarea:focus {
404
- border-color: var(--ai-blue);
405
- 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%);
406
496
  }
407
497
 
408
498
  .error,
409
499
  .answer {
410
500
  display: none;
411
- margin: 0 14px 14px;
412
- border-radius: var(--ai-radius);
413
- padding: 12px;
414
- 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;
415
506
  white-space: pre-wrap;
416
507
  }
417
508
 
@@ -421,18 +512,25 @@ function g(t) {
421
512
  }
422
513
 
423
514
  .error {
424
- background: #fef2f2;
425
- color: #991b1b;
515
+ border: 1px solid rgba(220, 38, 38, 0.18);
516
+ background: #fff1f2;
517
+ color: #9f1239;
426
518
  }
427
519
 
428
520
  .answer {
429
- max-height: 220px;
521
+ max-height: 230px;
430
522
  overflow: auto;
431
- background: #f8fafc;
523
+ border: 1px solid rgba(15, 23, 42, 0.08);
524
+ background: rgba(248, 250, 252, 0.82);
432
525
  color: #111827;
433
526
  }
434
527
 
435
528
  @media (max-width: 760px) {
529
+ .toast {
530
+ right: 12px;
531
+ bottom: 12px;
532
+ }
533
+
436
534
  .panel {
437
535
  left: 12px !important;
438
536
  right: 12px;
@@ -442,13 +540,42 @@ function g(t) {
442
540
  }
443
541
  }
444
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
+
445
553
  @keyframes pulse-ring {
446
- 70% { box-shadow: 0 0 0 8px transparent; }
447
- 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
+ }
448
573
  }
449
574
  </style>
450
575
  <div class="custom-cursor">
451
- <div class="cursor-dot"></div>
576
+ <svg viewBox="0 0 28 32" class="cursor-shape" aria-hidden="true">
577
+ <path d="M2,2 L2,28 L8,22 L14,32 L18,29 L12,19 L22,19 Z" stroke-linejoin="round" stroke-linecap="round" />
578
+ </svg>
452
579
  </div>
453
580
  <div class="toast" role="status">
454
581
  <span class="pulse"></span>
@@ -462,7 +589,7 @@ function g(t) {
462
589
  <span class="kind"></span>
463
590
  <strong class="label"></strong>
464
591
  </div>
465
- <button class="close" type="button" aria-label="Close AI prompt">x</button>
592
+ <button class="close" type="button" aria-label="Close AI prompt">×</button>
466
593
  </div>
467
594
  <form>
468
595
  <textarea placeholder="Ask what to do with this selection..."></textarea>
@@ -497,7 +624,7 @@ function g(t) {
497
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`;
498
625
  },
499
626
  showPrompt: (t) => {
500
- 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);
501
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();
502
629
  },
503
630
  setThinking: (e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emmaexcel/shakecursor",
3
- "version": "0.1.2",
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",