bariweb-widget 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,7 @@ Add the following script to your HTML file:
16
16
  ```html
17
17
  <script
18
18
  src="https://unpkg.com/bariweb-widget@latest/dist/bariweb.iife.js"
19
- data-client-id="YOUR_CLIENT_ID"
19
+ client-id="YOUR_CLIENT_ID"
20
20
  ></script>
21
21
  ```
22
22
 
@@ -31,6 +31,12 @@
31
31
  --bw-border: #e2e8f0;
32
32
  --bw-bg-hover: #f8fafc;
33
33
  --bw-bg-subtle: #f1f5f9;
34
+ --bw-danger: #ef4444;
35
+ --bw-danger-bg: #fee2e2;
36
+ --bw-danger-border: #fecaca;
37
+ --bw-success: #10b981;
38
+ --bw-success-bg: rgba(16, 185, 129, 0.08);
39
+ --bw-success-border: rgba(16, 185, 129, 0.2);
34
40
  --bw-radius: 14px;
35
41
  --bw-radius-sm: 8px;
36
42
  --bw-shadow-panel: 0 20px 60px -10px rgba(0,0,0,0.18), 0 8px 24px -4px rgba(0,0,0,0.1);
@@ -143,7 +149,7 @@
143
149
  transition: all 0.2s;
144
150
  color: var(--bw-fg-muted);
145
151
  }
146
- .close-btn:hover { background: #fee2e2; color: #ef4444; transform: rotate(90deg); }
152
+ .close-btn:hover { background: var(--bw-danger-bg); color: var(--bw-danger); transform: rotate(90deg); }
147
153
  .close-btn svg { width: 18px; height: 18px; }
148
154
 
149
155
  /* ─── Segmented Tab Control ─── */
@@ -177,8 +183,8 @@
177
183
  .bw-tab:hover { background: var(--bw-bg-hover); color: var(--bw-fg); }
178
184
  .bw-tab[active] {
179
185
  background: var(--bw-primary);
180
- color: white;
181
- box-shadow: 0 2px 8px rgba(109, 40, 217, 0.3);
186
+ color: var(--bw-primary-fg);
187
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
182
188
  }
183
189
 
184
190
  /* ─── Content area ─── */
@@ -273,7 +279,7 @@
273
279
  .chat-bubble.user {
274
280
  align-self: flex-end;
275
281
  background: var(--bw-primary);
276
- color: white;
282
+ color: var(--bw-primary-fg);
277
283
  border-bottom-right-radius: 4px;
278
284
  }
279
285
  .chat-bubble.assistant {
@@ -285,12 +291,12 @@
285
291
  }
286
292
 
287
293
  .screen-label-badge {
288
- background: rgba(16, 185, 129, 0.08);
289
- border: 1px solid rgba(16, 185, 129, 0.2);
294
+ background: var(--bw-success-bg);
295
+ border: 1px solid var(--bw-success-border);
290
296
  border-radius: var(--bw-radius-sm);
291
297
  padding: 6px 12px;
292
298
  font-size: 12px;
293
- color: #059669;
299
+ color: var(--bw-success);
294
300
  display: flex;
295
301
  align-items: center;
296
302
  gap: 6px;
@@ -354,17 +360,17 @@
354
360
  }
355
361
  .btn-confirm {
356
362
  width: 100%; min-height: 46px; border-radius: var(--bw-radius-sm);
357
- background: var(--bw-primary); color: white; border: none;
363
+ background: var(--bw-primary); color: var(--bw-primary-fg); border: none;
358
364
  font-weight: 700; font-size: 14px; cursor: pointer;
359
- transition: all 0.2s; box-shadow: 0 4px 12px rgba(109, 40, 217, 0.25);
365
+ transition: all 0.2s; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
360
366
  }
361
367
  .btn-confirm:hover { filter: brightness(1.1); transform: translateY(-1px); }
362
368
  .btn-cancel {
363
369
  width: 100%; min-height: 44px; border-radius: var(--bw-radius-sm);
364
- background: transparent; color: #ef4444; border: 1px solid #fecaca;
370
+ background: transparent; color: var(--bw-danger); border: 1px solid var(--bw-danger-border);
365
371
  font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s;
366
372
  }
367
- .btn-cancel:hover { background: #fef2f2; }
373
+ .btn-cancel:hover { background: var(--bw-danger-bg); }
368
374
 
369
375
  /* Chat input area */
370
376
  .chat-input-area {
@@ -443,14 +449,14 @@
443
449
  }
444
450
  #bw-voice-btn:hover { background: rgba(109, 40, 217, 0.08); transform: scale(1.05); }
445
451
  #bw-voice-btn.recording {
446
- background: #fef2f2;
447
- border-color: #dc2626;
448
- color: #dc2626;
452
+ background: var(--bw-danger-bg);
453
+ border-color: var(--bw-danger);
454
+ color: var(--bw-danger);
449
455
  animation: micPulse 1.5s infinite;
450
456
  }
451
457
  @keyframes micPulse {
452
- 0% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.4); transform: scale(1.05); }
453
- 100% { box-shadow: 0 0 0 10px rgba(220, 38, 38, 0); transform: scale(1.05); }
458
+ 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); transform: scale(1.05); }
459
+ 100% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); transform: scale(1.05); }
454
460
  }
455
461
 
456
462
  .chat-icon-btn.tts-on { background: rgba(16,185,129,0.1); border-color: rgba(16,185,129,0.4); color: #059669; }
@@ -462,13 +468,13 @@
462
468
  border-radius: 50%;
463
469
  border: none;
464
470
  background: var(--bw-primary);
465
- color: white;
471
+ color: var(--bw-primary-fg);
466
472
  cursor: pointer;
467
473
  display: flex;
468
474
  align-items: center;
469
475
  justify-content: center;
470
476
  transition: all 0.2s;
471
- box-shadow: 0 2px 8px rgba(109,40,217,0.3);
477
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
472
478
  margin-left: 6px;
473
479
  }
474
480
  .chat-send-btn:hover:not(:disabled) { transform: scale(1.08); filter: brightness(1.1); }
@@ -824,15 +830,7 @@
824
830
  html[data-bw-has-custom-content] div:not(bw-widget *) {
825
831
  color: var(--bw-custom-content) !important;
826
832
  }
827
- `}_applySettings(){let e=document.documentElement;this._ensureGlobalStyles(),e.style.setProperty(`--bw-grayscale`,this.settings.monochrome?`100%`:`0%`);let t=1;this.settings.lowSaturation&&(t=.3),this.settings.highSaturation&&(t=2.5),e.style.setProperty(`--bw-saturation`,t.toString()),this.settings.customBgHue===null?e.removeAttribute(`data-bw-has-custom-bg`):(e.style.setProperty(`--bw-custom-bg`,`hsl(${this.settings.customBgHue}, 50%, 95%)`),e.setAttribute(`data-bw-has-custom-bg`,``)),this.settings.customHeaderHue===null?e.removeAttribute(`data-bw-has-custom-header`):(e.style.setProperty(`--bw-custom-header`,`hsl(${this.settings.customHeaderHue}, 70%, 30%)`),e.setAttribute(`data-bw-has-custom-header`,``)),this.settings.customContentHue===null?e.removeAttribute(`data-bw-has-custom-content`):(e.style.setProperty(`--bw-custom-content`,`hsl(${this.settings.customContentHue}, 60%, 40%)`),e.setAttribute(`data-bw-has-custom-content`,``)),this.settings.textScale>1?e.style.fontSize=`${this.settings.textScale*100}%`:e.style.fontSize=``;let n={"data-bw-monochrome":this.settings.monochrome,"data-bw-dark-high-contrast":this.settings.darkHighContrast,"data-bw-bright-high-contrast":this.settings.brightHighContrast,"data-bw-contrast-mode":this.settings.contrastMode,"data-bw-text-spacing":this.settings.textSpacing,"data-bw-dyslexic":this.settings.dyslexicFont,"data-bw-focus-visualizer":this.settings.focusVisualizer,"data-bw-cursor-magnifier":this.settings.cursorMagnifier,"data-bw-no-animations":this.settings.animationsDisabled,"data-bw-link-highlight":this.settings.linkHighlight,"data-bw-highlight-headers":this.settings.highlightHeaders,"data-bw-enlarge-buttons":this.settings.enlargeButtons};Object.entries(n).forEach(([t,n])=>{n?e.setAttribute(t,``):e.removeAttribute(t)});let r=this.host;r&&r.style.setProperty(`--bw-font-scale`,this.settings.textScale.toString())}toggleMonochrome(){this.settings.monochrome=!this.settings.monochrome,this._saveSettings()}toggleDarkHighContrast(){this.settings.darkHighContrast=!this.settings.darkHighContrast,this.settings.darkHighContrast&&(this.settings.brightHighContrast=!1,this.settings.contrastMode=!1),this._saveSettings()}toggleBrightHighContrast(){this.settings.brightHighContrast=!this.settings.brightHighContrast,this.settings.brightHighContrast&&(this.settings.darkHighContrast=!1,this.settings.contrastMode=!1),this._saveSettings()}toggleLowSaturation(){this.settings.lowSaturation=!this.settings.lowSaturation,this.settings.lowSaturation&&(this.settings.highSaturation=!1),this._saveSettings()}toggleHighSaturation(){this.settings.highSaturation=!this.settings.highSaturation,this.settings.highSaturation&&(this.settings.lowSaturation=!1),this._saveSettings()}toggleContrastMode(){this.settings.contrastMode=!this.settings.contrastMode,this.settings.contrastMode&&(this.settings.darkHighContrast=!1,this.settings.brightHighContrast=!1),this._saveSettings()}setCustomHue(e){this.settings.activeColorTab===`background`?this.settings.customBgHue=e:this.settings.activeColorTab===`header`?this.settings.customHeaderHue=e:this.settings.customContentHue=e,this._saveSettings()}resetCustomColors(){this.settings.customBgHue=null,this.settings.customHeaderHue=null,this.settings.customContentHue=null,this._saveSettings()}toggleHighlightHeaders(){this.settings.highlightHeaders=!this.settings.highlightHeaders,this._saveSettings()}toggleEnlargeButtons(){this.settings.enlargeButtons=!this.settings.enlargeButtons,this._saveSettings()}incrementTextScale(){this.settings.textScale>=1.5?this.settings.textScale=1:this.settings.textScale=parseFloat((this.settings.textScale+.1).toFixed(1)),this._saveSettings()}toggleTextSpacing(){this.settings.textSpacing=!this.settings.textSpacing,this._saveSettings()}toggleDyslexicFont(){this.settings.dyslexicFont=!this.settings.dyslexicFont,this._saveSettings()}toggleFocusVisualizer(){this.settings.focusVisualizer=!this.settings.focusVisualizer,this._saveSettings()}toggleCursorMagnifier(){this.settings.cursorMagnifier=!this.settings.cursorMagnifier,this._saveSettings()}toggleAnimations(){this.settings.animationsDisabled=!this.settings.animationsDisabled,this._saveSettings()}toggleLinkHighlight(){this.settings.linkHighlight=!this.settings.linkHighlight,this._saveSettings()}reset(){this.settings={...U},this._saveSettings()}};function W(e){try{let t=new URL(e),n=t.pathname;n=n.replace(yt,`:id`),n=n.replace(bt,`/:id`),n=n.replace(xt,`/:slug`),n=n.replace(St,`/:id`);let r=new URLSearchParams;t.searchParams.forEach((e,t)=>{Ct.has(t)?r.set(`:${t}`,``):e.length<30&&!/^\d+$/.test(e)&&r.set(t,e)});let i=r.toString();return n.replace(/\/$/,``)+(i?`?${i}`:``)}catch{return e.replace(yt,`:id`).replace(/\/\d{1,20}(?=\/|$)/g,`/:id`).split(`?`)[0]}}function G(e){let t=[`dialog`,`tooltip`,`menu`,`listbox`,`alertdialog`],n=e;for(;n&&n!==document.body;){let e=n.getAttribute(`role`)||``;if(t.includes(e)||n.hasAttribute(`data-radix-popper-content-wrapper`)||n.hasAttribute(`data-floating-ui-portal`))return!0;let r=typeof n.className==`string`?n.className:``;if(/popover|tooltip|dropdown-menu|floating|overlay/i.test(r))return!0;n=n.parentElement}return!1}function gt(e){let t=[`li`,`article`,`tr`,`dd`],n=e.parentElement,r=0;for(;n&&n!==document.body&&r<8;){let e=n.tagName.toLowerCase();if(t.includes(e))return!0;let i=typeof n.className==`string`?n.className:``;if(/\b(card|item|tile|post|entry|product|row-item|list-item|feed-item|cell)\b/i.test(i)){let e=n.parentElement?.children;if(e&&e.length>2)return!0}let a=n.getAttribute(`role`)||``;if(a===`listitem`||a===`row`||a===`gridcell`)return!0;n=n.parentElement,r++}return!1}function _t(e){let t=e,n=(t.getAttribute(`aria-label`)||t.getAttribute(`title`)||t.innerText||t.getAttribute(`placeholder`)||``).trim().toLowerCase();return!n||n.length<2||n.length>40||/^[\d\s₸$€%.,\-+:()]+$/.test(n)||/^\d{1,2}[./]\d{1,2}/.test(n)||wt.has(n)?``:n.replace(/^[\p{Emoji}\s]+/u,``).trim().slice(0,30)}function vt(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t^e.charCodeAt(n);return(t>>>0).toString(16)}function K(){let e=[],t=W(window.location.href);e.push(`route:${t}`);let n=document.querySelector(`h1`);if(n){let t=n.innerText?.trim().toLowerCase();t&&t.length>1&&t.length<50&&!/\d{3,}/.test(t)&&e.push(`h1:${t.slice(0,30)}`)}let r=Array.from(document.querySelectorAll(`input:not([type="hidden"]):not([type="submit"]):not([type="radio"]):not([type="checkbox"]), textarea, select`)).slice(0,8);for(let t of r){if(G(t))continue;let n=t,r=(n.getAttribute(`name`)||n.getAttribute(`placeholder`)||n.getAttribute(`aria-label`)||``).toLowerCase().trim().slice(0,25);r&&r.length>1&&!wt.has(r)&&e.push(`field:${r}`)}let i=Array.from(document.querySelectorAll(`nav a, [role="navigation"] a`)).slice(0,6);for(let t of i){if(G(t))continue;let n=_t(t);n&&e.push(`nav:${n}`)}let a=document.querySelector(`main`)||document.querySelector(`[role="main"]`)||document.getElementById(`root`);return a&&Array.from(a.querySelectorAll(`button:not([aria-hidden="true"]), [role="button"]:not([aria-hidden="true"])`)).filter(e=>!G(e)&&!gt(e)).map(_t).filter(e=>e.length>1).reduce((e,t)=>e.includes(t)?e:[...e,t],[]).slice(0,3).forEach(t=>e.push(`btn:${t}`)),[...new Set(e)].sort().slice(0,15)}function q(){return`bw-${vt(K().join(`|`))}`}var yt,bt,xt,St,Ct,wt,Tt=t((()=>{yt=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,bt=/\/\d{1,20}(?=\/|$)/g,xt=/\/[a-z0-9]+(?:-[a-z0-9]+)*-\d+(?=\/|$)/g,St=/\/[0-9a-f]{8,}(?=\/|$)/gi,Ct=new Set([`id`,`userId`,`user_id`,`orderId`,`order_id`,`itemId`,`item_id`,`productId`,`product_id`,`token`,`key`,`ref`,`code`,`session`]),wt=new Set(`ok,ок,okay,close,закрыть,cancel,отмена,yes,da,no,нет,да,submit,отправить,back,назад,next,далее,more,ещё,еще,menu,меню,...,•,·,loading,загрузка,open,открыть,expand,collapse,toggle,sort`.split(`,`))}));function Et(e,t){let n=new Set([...e].filter(e=>t.has(e))),r=new Set([...e,...t]);return r.size===0?1:n.size/r.size}var Dt,J,Ot=t((()=>{Tt(),Dt=class{constructor(e=1500){this._observer=null,this._debounceTimer=null,this._lastTokens=new Set,this._lastUrl=``,this._callbacks=[],this._discoveryCallbacks=[],this._isDiscovering=!1,this.isAutoDiscoveryEnabled=!1,this._debounceMs=e}start(){this._observer||(this._lastTokens=new Set(K()),this._lastUrl=W(window.location.href),this._observer=new MutationObserver(()=>{this._debounceTimer&&clearTimeout(this._debounceTimer),this._debounceTimer=setTimeout(()=>this._onMutation(),this._debounceMs)}),this._observer.observe(document.body,{childList:!0,subtree:!0,attributes:!1,characterData:!1}))}stop(){this._observer?.disconnect(),this._observer=null,this._debounceTimer&&clearTimeout(this._debounceTimer)}onStateChange(e){this._callbacks.push(e)}onDiscovery(e){this._discoveryCallbacks.push(e)}get isDiscovering(){return this._isDiscovering}getLiveSnapshot(){let e=(e,t)=>{if(e.hasAttribute(`bw-private`)||e.hasAttribute(`data-bw-private`))return`[MASKED]`;if(!t)return t;let n=t.replace(/(?:\d[ \-]*?){13,16}/g,`****`);return n=n.replace(/\b\d{12}\b/g,`****`),n},t=Array.from(document.querySelectorAll(`h1, h2`)).map(t=>e(t,t.innerText?.trim()||``)).filter(Boolean).slice(0,3),n=Array.from(document.querySelectorAll(`button, a[href], [role="button"]`)).map(t=>{let n=t,r=e(n,(n.getAttribute(`aria-label`)||n.innerText||``).trim().slice(0,60));return{id:n.id||``,text:r}}).filter(e=>e.text.length>0).slice(0,30);return{url:window.location.href,headings:t,fingerprint:q(),elements:n}}async _onMutation(){if(document.readyState!==`complete`)return;let e=W(window.location.href),t=new Set(K());if(t.size<2)return;let n=q(),r=e!==this._lastUrl,i=Et(this._lastTokens,t);if(r||i<.55){let a=r?`URL: ${this._lastUrl} → ${e}`:`Sim: ${i.toFixed(2)}`;console.log(`[Watcher] Screen change (${a})`),this._lastUrl=e,this._lastTokens=t;let o=this.getLiveSnapshot();if(this.isAutoDiscoveryEnabled){let e=this._buildTypedTokens();this._discover(n,e).catch(()=>{})}this._callbacks.forEach(e=>e(o))}}_buildTypedTokens(){let e=new Set,t=[],n=(n,r)=>{let i=r.trim().slice(0,40);if(!i||i.length<2)return;let a=`${n}:${i}`;e.has(a)||(e.add(a),t.push(a))};return document.querySelectorAll(`button, [role="button"]`).forEach(e=>{let t=e.innerText?.trim();t&&n(`btn`,t)}),document.querySelectorAll(`a[href]`).forEach(e=>{let t=(e.getAttribute(`aria-label`)||e.innerText)?.trim();t&&n(`a`,t)}),document.querySelectorAll(`input:not([type=hidden]), textarea, select`).forEach(e=>{let t=e.placeholder||e.name;t&&n(`input`,t)}),t.slice(0,8)}async _discover(e,t){let n=localStorage.getItem(`bw_admin_token`);if(n){this._isDiscovering=!0;try{let r=await fetch(`http://localhost:8000/v1/training/discover`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({fingerprint:e,tokens:t,page_url:window.location.href})});if(r.ok){let e=await r.json();console.log(`[Discovery] ${e.status} — ${e.label}`),this._discoveryCallbacks.forEach(t=>t(e))}else r.status===401?(console.warn(`[Discovery] Token expired — disabling auto-discovery`),localStorage.removeItem(`bw_admin_token`),this.isAutoDiscoveryEnabled=!1):console.warn(`[Discovery] Server error ${r.status}`)}catch(e){console.warn(`[Discovery] Network error`,e)}finally{this._isDiscovering=!1}}}async forceDiscovery(){let e=[...new Set(K())],t=q();await this._discover(t,e)}},J=new Dt(1500)}));Ot();var kt=`http://localhost:8000`,At=class{constructor(e){this.isFixing=!1,this.simplifyEnabled=!1,this.autoA11yEnabled=!1,this._onParagraphClick=async e=>{if(!this.simplifyEnabled)return;let t=e.target;if(t.closest(`bw-widget`)||t.closest(`.bw-ai-tooltip`))return;let n=t.tagName.toLowerCase();if([`p`,`span`,`div`,`li`,`article`,`h1`,`h2`,`h3`,`h4`,`h5`,`h6`].includes(n)){let n=t.innerText?.trim();if(n&&n.length>20){e.preventDefault(),e.stopPropagation(),document.querySelectorAll(`.bw-ai-tooltip`).forEach(e=>e.remove());let r=window.matchMedia&&window.matchMedia(`(prefers-color-scheme: dark)`).matches,i=document.createElement(`div`);i.className=`bw-ai-tooltip bw-ai-tooltip-loading`,r&&i.setAttribute(`data-theme`,`dark`),i.innerHTML=`
828
- <div class="bw-ai-tooltip-header">
829
- <span>✨ AI Упрощение</span>
830
- <button class="bw-ai-tooltip-close">✕</button>
831
- </div>
832
- <div class="bw-ai-tooltip-content">
833
- Ожидаем ответ от ИИ...
834
- </div>
835
- `,document.body.appendChild(i),i.style.left=`${Math.max(10,e.pageX-160)}px`,i.style.top=`${e.pageY+20}px`;let a=t.style.outline,o=t.style.backgroundColor;t.style.outline=`2px dashed #a855f7`,t.style.backgroundColor=`rgba(168, 85, 247, 0.05)`,i.querySelector(`.bw-ai-tooltip-close`)?.addEventListener(`click`,()=>{i.remove(),t.style.outline=a,t.style.backgroundColor=o});try{let e=window.BariwebConfig?.clientId||``,t=await fetch(`${kt}/v1/widget/a11y/simplify`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":e},body:JSON.stringify({text:n})});if(t.ok){let e=await t.json();if(e.text)i.classList.remove(`bw-ai-tooltip-loading`),i.querySelector(`.bw-ai-tooltip-content`).innerHTML=e.text;else throw Error(`Empty response`)}else throw Error(`Server error`)}catch(e){console.error(`BariWeb AI: Simplify failed`,e),i.classList.remove(`bw-ai-tooltip-loading`),i.querySelector(`.bw-ai-tooltip-content`).innerHTML=`<span style="color:#ef4444; font-size:13px;">Ошибка создания упрощенного текста. Попробуйте еще раз.</span>`}}}},(this.host=e).addController(this),this.simplifyEnabled=localStorage.getItem(`bw-ai-simplify`)===`true`,this.autoA11yEnabled=localStorage.getItem(`bw-ai-autofix`)===`true`,J.onStateChange(()=>{this.autoA11yEnabled&&!this.isFixing&&this.fixMarkup()}),this.autoA11yEnabled&&setTimeout(()=>this.fixMarkup(),1e3)}toggleAutoA11y(){this.autoA11yEnabled=!this.autoA11yEnabled,localStorage.setItem(`bw-ai-autofix`,this.autoA11yEnabled?`true`:`false`),this.autoA11yEnabled&&!this.isFixing&&this.fixMarkup(),this.host.requestUpdate()}hostConnected(){}hostDisconnected(){this.simplifyEnabled&&(document.body.removeEventListener(`click`,this._onParagraphClick,{capture:!0}),document.body.classList.remove(`bw-simplify-mode`))}async fixMarkup(){this.isFixing=!0,this.host.requestUpdate();try{let e=[];if(document.querySelectorAll(`img:not([alt]), img[alt=""]`).forEach(t=>{t.hasAttribute(`data-bw-ai-id`)||t.setAttribute(`data-bw-ai-id`,`ai-img-`+Math.random().toString(36).substring(2,9)),e.push({id:t.getAttribute(`data-bw-ai-id`),html:t.outerHTML.substring(0,300)+(t.outerHTML.length>300?`...>`:``)})}),document.querySelectorAll(`button:not([aria-label]), a:not([aria-label]), [role="button"]:not([aria-label])`).forEach(t=>{if(t.tagName===`INPUT`)return;let n=t;n.innerText?.trim()||n.textContent?.trim()||(t.hasAttribute(`data-bw-ai-id`)||t.setAttribute(`data-bw-ai-id`,`ai-btn-`+Math.random().toString(36).substring(2,9)),e.push({id:t.getAttribute(`data-bw-ai-id`),html:t.outerHTML.substring(0,300)+(t.outerHTML.length>300?`...>`:``)}))}),e.length===0){console.log(`BariWeb AI: No broken elements found.`);return}console.log(`BariWeb AI: Found ${e.length} broken elements. Processing...`);let t=window.BariwebConfig?.clientId||``;for(let n=0;n<e.length;n+=10){let r=e.slice(n,n+10),i=await fetch(`${kt}/v1/widget/a11y/fix`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":t},body:JSON.stringify({elements:r})});i.ok&&(await i.json()).forEach(e=>{let t=document.querySelector(`[data-bw-ai-id="${e.id}"]`);if(t&&e.value&&(e.attribute===`alt`||e.attribute===`aria-label`)){t.setAttribute(e.attribute,e.value);let n=t,r=n.style.outline;n.style.outline=`3px solid #10b981`,setTimeout(()=>{n.style.outline=r},2e3)}})}}catch(e){console.error(`BariWeb AI: A11y Fix failed`,e)}finally{this.isFixing=!1,this.host.requestUpdate()}}toggleSimplify(){if(this.simplifyEnabled=!this.simplifyEnabled,this.simplifyEnabled){if(document.body.addEventListener(`click`,this._onParagraphClick,{capture:!0}),document.documentElement.style.setProperty(`--bw-simplify-cursor`,`help`),!document.getElementById(`bw-simplify-mode-style`)){let e=document.createElement(`style`);e.id=`bw-simplify-mode-style`,e.textContent=`
833
+ `}_applySettings(){let e=document.documentElement;this._ensureGlobalStyles(),e.style.setProperty(`--bw-grayscale`,this.settings.monochrome?`100%`:`0%`);let t=1;this.settings.lowSaturation&&(t=.3),this.settings.highSaturation&&(t=2.5),e.style.setProperty(`--bw-saturation`,t.toString()),this.settings.customBgHue===null?e.removeAttribute(`data-bw-has-custom-bg`):(e.style.setProperty(`--bw-custom-bg`,`hsl(${this.settings.customBgHue}, 50%, 95%)`),e.setAttribute(`data-bw-has-custom-bg`,``)),this.settings.customHeaderHue===null?e.removeAttribute(`data-bw-has-custom-header`):(e.style.setProperty(`--bw-custom-header`,`hsl(${this.settings.customHeaderHue}, 70%, 30%)`),e.setAttribute(`data-bw-has-custom-header`,``)),this.settings.customContentHue===null?e.removeAttribute(`data-bw-has-custom-content`):(e.style.setProperty(`--bw-custom-content`,`hsl(${this.settings.customContentHue}, 60%, 40%)`),e.setAttribute(`data-bw-has-custom-content`,``)),this.settings.textScale>1?e.style.fontSize=`${this.settings.textScale*100}%`:e.style.fontSize=``;let n={"data-bw-monochrome":this.settings.monochrome,"data-bw-dark-high-contrast":this.settings.darkHighContrast,"data-bw-bright-high-contrast":this.settings.brightHighContrast,"data-bw-contrast-mode":this.settings.contrastMode,"data-bw-text-spacing":this.settings.textSpacing,"data-bw-dyslexic":this.settings.dyslexicFont,"data-bw-focus-visualizer":this.settings.focusVisualizer,"data-bw-cursor-magnifier":this.settings.cursorMagnifier,"data-bw-no-animations":this.settings.animationsDisabled,"data-bw-link-highlight":this.settings.linkHighlight,"data-bw-highlight-headers":this.settings.highlightHeaders,"data-bw-enlarge-buttons":this.settings.enlargeButtons};Object.entries(n).forEach(([t,n])=>{n?e.setAttribute(t,``):e.removeAttribute(t)});let r=this.host;r&&r.style.setProperty(`--bw-font-scale`,this.settings.textScale.toString())}toggleMonochrome(){this.settings.monochrome=!this.settings.monochrome,this._saveSettings()}toggleDarkHighContrast(){this.settings.darkHighContrast=!this.settings.darkHighContrast,this.settings.darkHighContrast&&(this.settings.brightHighContrast=!1,this.settings.contrastMode=!1),this._saveSettings()}toggleBrightHighContrast(){this.settings.brightHighContrast=!this.settings.brightHighContrast,this.settings.brightHighContrast&&(this.settings.darkHighContrast=!1,this.settings.contrastMode=!1),this._saveSettings()}toggleLowSaturation(){this.settings.lowSaturation=!this.settings.lowSaturation,this.settings.lowSaturation&&(this.settings.highSaturation=!1),this._saveSettings()}toggleHighSaturation(){this.settings.highSaturation=!this.settings.highSaturation,this.settings.highSaturation&&(this.settings.lowSaturation=!1),this._saveSettings()}toggleContrastMode(){this.settings.contrastMode=!this.settings.contrastMode,this.settings.contrastMode&&(this.settings.darkHighContrast=!1,this.settings.brightHighContrast=!1),this._saveSettings()}setCustomHue(e){this.settings.activeColorTab===`background`?this.settings.customBgHue=e:this.settings.activeColorTab===`header`?this.settings.customHeaderHue=e:this.settings.customContentHue=e,this._saveSettings()}resetCustomColors(){this.settings.customBgHue=null,this.settings.customHeaderHue=null,this.settings.customContentHue=null,this._saveSettings()}toggleHighlightHeaders(){this.settings.highlightHeaders=!this.settings.highlightHeaders,this._saveSettings()}toggleEnlargeButtons(){this.settings.enlargeButtons=!this.settings.enlargeButtons,this._saveSettings()}incrementTextScale(){this.settings.textScale>=1.5?this.settings.textScale=1:this.settings.textScale=parseFloat((this.settings.textScale+.1).toFixed(1)),this._saveSettings()}toggleTextSpacing(){this.settings.textSpacing=!this.settings.textSpacing,this._saveSettings()}toggleDyslexicFont(){this.settings.dyslexicFont=!this.settings.dyslexicFont,this._saveSettings()}toggleFocusVisualizer(){this.settings.focusVisualizer=!this.settings.focusVisualizer,this._saveSettings()}toggleCursorMagnifier(){this.settings.cursorMagnifier=!this.settings.cursorMagnifier,this._saveSettings()}toggleAnimations(){this.settings.animationsDisabled=!this.settings.animationsDisabled,this._saveSettings()}toggleLinkHighlight(){this.settings.linkHighlight=!this.settings.linkHighlight,this._saveSettings()}reset(){this.settings={...U},this._saveSettings()}};function W(e){try{let t=new URL(e),n=t.pathname;n=n.replace(yt,`:id`),n=n.replace(bt,`/:id`),n=n.replace(xt,`/:slug`),n=n.replace(St,`/:id`);let r=new URLSearchParams;t.searchParams.forEach((e,t)=>{Ct.has(t)?r.set(`:${t}`,``):e.length<30&&!/^\d+$/.test(e)&&r.set(t,e)});let i=r.toString();return n.replace(/\/$/,``)+(i?`?${i}`:``)}catch{return e.replace(yt,`:id`).replace(/\/\d{1,20}(?=\/|$)/g,`/:id`).split(`?`)[0]}}function G(e){let t=[`dialog`,`tooltip`,`menu`,`listbox`,`alertdialog`],n=e;for(;n&&n!==document.body;){let e=n.getAttribute(`role`)||``;if(t.includes(e)||n.hasAttribute(`data-radix-popper-content-wrapper`)||n.hasAttribute(`data-floating-ui-portal`))return!0;let r=typeof n.className==`string`?n.className:``;if(/popover|tooltip|dropdown-menu|floating|overlay/i.test(r))return!0;n=n.parentElement}return!1}function gt(e){let t=[`li`,`article`,`tr`,`dd`],n=e.parentElement,r=0;for(;n&&n!==document.body&&r<8;){let e=n.tagName.toLowerCase();if(t.includes(e))return!0;let i=typeof n.className==`string`?n.className:``;if(/\b(card|item|tile|post|entry|product|row-item|list-item|feed-item|cell)\b/i.test(i)){let e=n.parentElement?.children;if(e&&e.length>2)return!0}let a=n.getAttribute(`role`)||``;if(a===`listitem`||a===`row`||a===`gridcell`)return!0;n=n.parentElement,r++}return!1}function _t(e){let t=e,n=(t.getAttribute(`aria-label`)||t.getAttribute(`title`)||t.innerText||t.getAttribute(`placeholder`)||``).trim().toLowerCase();return!n||n.length<2||n.length>40||/^[\d\s₸$€%.,\-+:()]+$/.test(n)||/^\d{1,2}[./]\d{1,2}/.test(n)||wt.has(n)?``:n.replace(/^[\p{Emoji}\s]+/u,``).trim().slice(0,30)}function vt(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t^e.charCodeAt(n);return(t>>>0).toString(16)}function K(){let e=[],t=W(window.location.href);e.push(`route:${t}`);let n=document.querySelector(`h1`);if(n){let t=n.innerText?.trim().toLowerCase();t&&t.length>1&&t.length<50&&!/\d{3,}/.test(t)&&e.push(`h1:${t.slice(0,30)}`)}let r=Array.from(document.querySelectorAll(`input:not([type="hidden"]):not([type="submit"]):not([type="radio"]):not([type="checkbox"]), textarea, select`)).slice(0,8);for(let t of r){if(G(t))continue;let n=t,r=(n.getAttribute(`name`)||n.getAttribute(`placeholder`)||n.getAttribute(`aria-label`)||``).toLowerCase().trim().slice(0,25);r&&r.length>1&&!wt.has(r)&&e.push(`field:${r}`)}let i=Array.from(document.querySelectorAll(`nav a, [role="navigation"] a`)).slice(0,6);for(let t of i){if(G(t))continue;let n=_t(t);n&&e.push(`nav:${n}`)}let a=document.querySelector(`main`)||document.querySelector(`[role="main"]`)||document.getElementById(`root`);return a&&Array.from(a.querySelectorAll(`button:not([aria-hidden="true"]), [role="button"]:not([aria-hidden="true"])`)).filter(e=>!G(e)&&!gt(e)).map(_t).filter(e=>e.length>1).reduce((e,t)=>e.includes(t)?e:[...e,t],[]).slice(0,3).forEach(t=>e.push(`btn:${t}`)),[...new Set(e)].sort().slice(0,15)}function q(){return`bw-${vt(K().join(`|`))}`}var yt,bt,xt,St,Ct,wt,Tt=t((()=>{yt=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,bt=/\/\d{1,20}(?=\/|$)/g,xt=/\/[a-z0-9]+(?:-[a-z0-9]+)*-\d+(?=\/|$)/g,St=/\/[0-9a-f]{8,}(?=\/|$)/gi,Ct=new Set([`id`,`userId`,`user_id`,`orderId`,`order_id`,`itemId`,`item_id`,`productId`,`product_id`,`token`,`key`,`ref`,`code`,`session`]),wt=new Set(`ok,ок,okay,close,закрыть,cancel,отмена,yes,da,no,нет,да,submit,отправить,back,назад,next,далее,more,ещё,еще,menu,меню,...,•,·,loading,загрузка,open,открыть,expand,collapse,toggle,sort`.split(`,`))}));function Et(e,t){let n=new Set([...e].filter(e=>t.has(e))),r=new Set([...e,...t]);return r.size===0?1:n.size/r.size}var Dt,J,Ot=t((()=>{Tt(),Dt=class{constructor(e=1500){this._observer=null,this._debounceTimer=null,this._lastTokens=new Set,this._lastUrl=``,this._callbacks=[],this._discoveryCallbacks=[],this._isDiscovering=!1,this.isAutoDiscoveryEnabled=!1,this._debounceMs=e}start(){this._observer||(this._lastTokens=new Set(K()),this._lastUrl=W(window.location.href),this._observer=new MutationObserver(()=>{this._debounceTimer&&clearTimeout(this._debounceTimer),this._debounceTimer=setTimeout(()=>this._onMutation(),this._debounceMs)}),this._observer.observe(document.body,{childList:!0,subtree:!0,attributes:!1,characterData:!1}))}stop(){this._observer?.disconnect(),this._observer=null,this._debounceTimer&&clearTimeout(this._debounceTimer)}onStateChange(e){this._callbacks.push(e)}onDiscovery(e){this._discoveryCallbacks.push(e)}get isDiscovering(){return this._isDiscovering}getLiveSnapshot(){let e=(e,t)=>{if(e.hasAttribute(`bw-private`)||e.hasAttribute(`data-bw-private`))return`[MASKED]`;if(!t)return t;let n=t.replace(/(?:\d[ \-]*?){13,16}/g,`****`);return n=n.replace(/\b\d{12}\b/g,`****`),n},t=Array.from(document.querySelectorAll(`h1, h2`)).map(t=>e(t,t.innerText?.trim()||``)).filter(Boolean).slice(0,3),n=Array.from(document.querySelectorAll(`button, a[href], [role="button"]`)).map(t=>{let n=t,r=e(n,(n.getAttribute(`aria-label`)||n.innerText||``).trim().slice(0,60));return{id:n.id||``,text:r}}).filter(e=>e.text.length>0).slice(0,30);return{url:window.location.href,headings:t,fingerprint:q(),elements:n}}async _onMutation(){if(document.readyState!==`complete`)return;let e=W(window.location.href),t=new Set(K());if(t.size<2)return;let n=q(),r=e!==this._lastUrl,i=Et(this._lastTokens,t);if(r||i<.55){let a=r?`URL: ${this._lastUrl} → ${e}`:`Sim: ${i.toFixed(2)}`;console.log(`[Watcher] Screen change (${a})`),this._lastUrl=e,this._lastTokens=t;let o=this.getLiveSnapshot();if(this.isAutoDiscoveryEnabled){let e=this._buildTypedTokens();this._discover(n,e).catch(()=>{})}this._callbacks.forEach(e=>e(o))}}_buildTypedTokens(){let e=new Set,t=[],n=(n,r)=>{let i=r.trim().slice(0,40);if(!i||i.length<2)return;let a=`${n}:${i}`;e.has(a)||(e.add(a),t.push(a))};return document.querySelectorAll(`button, [role="button"]`).forEach(e=>{let t=e.innerText?.trim();t&&n(`btn`,t)}),document.querySelectorAll(`a[href]`).forEach(e=>{let t=(e.getAttribute(`aria-label`)||e.innerText)?.trim();t&&n(`a`,t)}),document.querySelectorAll(`input:not([type=hidden]), textarea, select`).forEach(e=>{let t=e.placeholder||e.name;t&&n(`input`,t)}),t.slice(0,8)}async _discover(e,t){let n=localStorage.getItem(`bw_admin_token`);if(n){this._isDiscovering=!0;try{let r=await fetch(`http://localhost:8000/v1/training/discover`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({fingerprint:e,tokens:t,page_url:window.location.href})});if(r.ok){let e=await r.json();console.log(`[Discovery] ${e.status} — ${e.label}`),this._discoveryCallbacks.forEach(t=>t(e))}else r.status===401?(console.warn(`[Discovery] Token expired — disabling auto-discovery`),localStorage.removeItem(`bw_admin_token`),this.isAutoDiscoveryEnabled=!1):console.warn(`[Discovery] Server error ${r.status}`)}catch(e){console.warn(`[Discovery] Network error`,e)}finally{this._isDiscovering=!1}}}async forceDiscovery(){let e=[...new Set(K())],t=q();await this._discover(t,e)}},J=new Dt(1500)}));Ot();var kt=`http://localhost:8000`,At=class{constructor(e){this.isFixing=!1,this.simplifyEnabled=!1,this.autoA11yEnabled=!1,this._onParagraphKeydown=e=>{if(this.simplifyEnabled&&(e.key===`Enter`||e.key===` `)&&e.target instanceof HTMLElement){if(e.target.closest(`bw-widget`)||e.target.closest(`.bw-ai-tooltip`))return;let t=e.target.tagName.toLowerCase();if([`p`,`span`,`div`,`li`,`article`,`h1`,`h2`,`h3`,`h4`,`h5`,`h6`].includes(t)){e.preventDefault(),e.stopPropagation();let t=e.target.getBoundingClientRect();this._triggerSimplify(e.target,t.left+window.scrollX,t.bottom+window.scrollY)}}},this._onParagraphClick=async e=>{if(!this.simplifyEnabled)return;let t=e.target;if(t.closest(`bw-widget`)||t.closest(`.bw-ai-tooltip`))return;let n=t.tagName.toLowerCase();if([`p`,`span`,`div`,`li`,`article`,`h1`,`h2`,`h3`,`h4`,`h5`,`h6`].includes(n)){let n=t.innerText?.trim();n&&n.length>20&&(e.preventDefault(),e.stopPropagation(),this._triggerSimplify(t,e.pageX,e.pageY))}},(this.host=e).addController(this),this.simplifyEnabled=localStorage.getItem(`bw-ai-simplify`)===`true`,this.autoA11yEnabled=localStorage.getItem(`bw-ai-autofix`)===`true`,J.onStateChange(()=>{this.autoA11yEnabled&&!this.isFixing&&this.fixMarkup()}),this.autoA11yEnabled&&setTimeout(()=>this.fixMarkup(),1e3)}toggleAutoA11y(){this.autoA11yEnabled=!this.autoA11yEnabled,localStorage.setItem(`bw-ai-autofix`,this.autoA11yEnabled?`true`:`false`),this.autoA11yEnabled&&!this.isFixing&&this.fixMarkup(),this.host.requestUpdate()}hostConnected(){}hostDisconnected(){this.simplifyEnabled&&(document.body.removeEventListener(`click`,this._onParagraphClick,{capture:!0}),document.body.classList.remove(`bw-simplify-mode`))}_announce(e){let t=document.getElementById(`bw-ai-announcer`);t||(t=document.createElement(`div`),t.id=`bw-ai-announcer`,t.setAttribute(`aria-live`,`polite`),t.setAttribute(`aria-atomic`,`true`),Object.assign(t.style,{position:`absolute`,width:`1px`,height:`1px`,padding:`0`,margin:`-1px`,overflow:`hidden`,clip:`rect(0, 0, 0, 0)`,whiteSpace:`nowrap`,border:`0`}),document.body.appendChild(t)),t.textContent=e}async fixMarkup(){this.isFixing=!0,this.host.requestUpdate();try{let e=[];if(document.querySelectorAll(`img:not([alt]), img[alt=""]`).forEach(t=>{t.hasAttribute(`data-bw-ai-id`)||t.setAttribute(`data-bw-ai-id`,`ai-img-`+Math.random().toString(36).substring(2,9)),e.push({id:t.getAttribute(`data-bw-ai-id`),html:t.outerHTML.substring(0,300)+(t.outerHTML.length>300?`...>`:``)})}),document.querySelectorAll(`button:not([aria-label]), a:not([aria-label]), [role="button"]:not([aria-label])`).forEach(t=>{if(t.tagName===`INPUT`)return;let n=t;n.innerText?.trim()||n.textContent?.trim()||(t.hasAttribute(`data-bw-ai-id`)||t.setAttribute(`data-bw-ai-id`,`ai-btn-`+Math.random().toString(36).substring(2,9)),e.push({id:t.getAttribute(`data-bw-ai-id`),html:t.outerHTML.substring(0,300)+(t.outerHTML.length>300?`...>`:``)}))}),e.length===0){console.log(`BariWeb AI: No broken elements found.`);return}console.log(`BariWeb AI: Found ${e.length} broken elements. Processing...`);let t=window.BariwebConfig?.clientId||``;for(let n=0;n<e.length;n+=10){let r=e.slice(n,n+10),i=await fetch(`${kt}/v1/widget/a11y/fix`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":t},body:JSON.stringify({elements:r})});i.ok&&(await i.json()).forEach(e=>{let t=document.querySelector(`[data-bw-ai-id="${e.id}"]`);if(t&&e.value&&(e.attribute===`alt`||e.attribute===`aria-label`)){t.setAttribute(e.attribute,e.value);let n=t,r=n.style.outline;n.style.outline=`3px solid #10b981`,setTimeout(()=>{n.style.outline=r},2e3)}})}this._announce(`Режим для незрячих отработал. AI исправил ${e.length} элементов.`)}catch(e){console.error(`BariWeb AI: A11y Fix failed`,e),this._announce(`Произошла ошибка при исправлении элементов.`)}finally{this.isFixing=!1,this.host.requestUpdate()}}toggleSimplify(){if(this.simplifyEnabled=!this.simplifyEnabled,this.simplifyEnabled){if(document.body.addEventListener(`click`,this._onParagraphClick,{capture:!0}),document.body.addEventListener(`keydown`,this._onParagraphKeydown,{capture:!0}),document.querySelectorAll(`p, h1, h2, h3, h4, h5, h6, li, article`).forEach(e=>{!e.hasAttribute(`tabindex`)&&e.textContent?.trim().length>20&&(e.setAttribute(`tabindex`,`0`),e.classList.add(`bw-simplify-focusable`))}),document.documentElement.style.setProperty(`--bw-simplify-cursor`,`help`),!document.getElementById(`bw-simplify-mode-style`)){let e=document.createElement(`style`);e.id=`bw-simplify-mode-style`,e.textContent=`
836
834
  body.bw-simplify-mode *:hover {
837
835
  cursor: help !important;
838
836
  background-color: rgba(168, 85, 247, 0.1) !important;
@@ -909,7 +907,15 @@
909
907
  from { opacity: 0; transform: translateY(4px); }
910
908
  to { opacity: 1; transform: translateY(0); }
911
909
  }
912
- `,document.head.appendChild(e)}document.body.classList.add(`bw-simplify-mode`)}else document.body.removeEventListener(`click`,this._onParagraphClick,{capture:!0}),document.body.classList.remove(`bw-simplify-mode`),document.documentElement.style.removeProperty(`--bw-simplify-cursor`);this.host.requestUpdate()}},jt=`bw-tts-enabled-v1`,Mt=class{constructor(){this.enabled=!0,this.enabled=this.loadEnabled()}isEnabled(){return this.enabled}setEnabled(e){this.enabled=e;try{localStorage.setItem(jt,e?`1`:`0`)}catch{}e||this.stop()}stop(){`speechSynthesis`in window&&window.speechSynthesis.cancel()}speak(e){if(!this.enabled||!(`speechSynthesis`in window))return;let t=(e||``).trim();if(t)try{window.speechSynthesis.cancel();let e=new SpeechSynthesisUtterance(t),n=this.detectLanguage(t);e.lang=n;let r=this.pickVoice(n);r&&(e.voice=r),e.rate=1,e.pitch=1,window.speechSynthesis.speak(e)}catch(e){console.warn(`TTS speak failed`,e)}}loadEnabled(){try{let e=localStorage.getItem(jt);return e===null?!0:e!==`0`}catch{return!0}}detectLanguage(e){let t=e.toLowerCase();return/[әіңғүұқөһ]/i.test(t)?`kk-KZ`:/[а-яё]/i.test(t)?`ru-RU`:/[a-z]/i.test(t)?`en-US`:`ru-RU`}pickVoice(e){if(!(`speechSynthesis`in window))return null;let t=window.speechSynthesis.getVoices();if(!t||t.length===0)return null;let n=e.split(`-`)[0].toLowerCase();return t.find(t=>t.lang.toLowerCase()===e.toLowerCase())||t.find(e=>e.lang.toLowerCase().startsWith(n))||t[0]||null}};Tt();var Nt=`http://localhost:8000`,Pt=5,Ft=[/(submit|отправить|оплатить|сгенерировать|сохранить|перевести|подтвердит|купить|удалить|delete|pay|purchase|buy|send|transfer|confirm|place.?order|checkout|remove|drop|unsubscribe|sign.?out|выйти|уволить)/i];function It(e){if(e.type!==`click_element`||!e.element_id)return!1;let t=document.getElementById(e.element_id);if(!t)return!1;if(t.getAttribute(`type`)===`submit`||t.tagName.toLowerCase()===`button`&&t.closest(`form`)!==null&&t.getAttribute(`type`)!==`button`)return!0;let n=[t.textContent?.trim()||``,t.getAttribute(`aria-label`)||``,t.getAttribute(`title`)||``,t.getAttribute(`name`)||``,t.getAttribute(`value`)||``].join(` `);return Ft.some(e=>e.test(n))}var Lt=class{constructor(e){this.messages=[],this.isLoading=!1,this.error=null,this._tts=new Mt,this._voiceMode=!1,this.pendingConfirmation=null,(this.host=e).addController(this),this._loadMessages()}hostConnected(){}hostDisconnected(){this._tts.stop()}_loadMessages(){try{let e=sessionStorage.getItem(`bw-chat-history`);e&&(this.messages=JSON.parse(e),this.messages.length>0&&typeof this.host.setOpen==`function`&&setTimeout(()=>this.host.setOpen(!0),100));let t=sessionStorage.getItem(`bw-auto-resume`);if(t===`true`||t===`verify-only`){sessionStorage.removeItem(`bw-auto-resume`);let e=t===`verify-only`?`Страница загрузилась после отправки формы. Проверь новый DOM: если авторизация прошла успешно (нет формы входа, есть контент приложения) — сообщи об успехе. НЕ нажимай ничего снова.`:`Страница загрузилась. Продолжай выполнение задачи с учетом нового контекста и DOM.`;setTimeout(()=>{this._agentStep(e)},1e3)}}catch(e){console.error(`Failed to load chat history`,e)}}_saveMessages(){try{sessionStorage.setItem(`bw-chat-history`,JSON.stringify(this.messages))}catch(e){console.error(`Failed to save chat history`,e)}}gatherContext(){let e=window.location.href,t=document.body?.innerText?.slice(0,3e3)??``,n=Array.from(document.querySelectorAll(`a[href], button, [role="button"], input:not([type="hidden"]), textarea, select`)).filter(e=>!e.hasAttribute(`bw-private`)).map(e=>{let t=e,n=t.tagName.toLowerCase(),r=n===`input`||n===`textarea`||n===`select`,i=t.getAttribute(`type`)||(n===`input`?`text`:n===`button`?`button`:n),a=t.getAttribute(`name`)||``,o=t.getAttribute(`placeholder`)||``,s=r?(t.value||``).slice(0,80):``;s&&=(s=s.replace(/\b\d{13,19}\b/g,e=>e.slice(0,4)+` **** **** `+e.slice(-4)),s.replace(/\b\d{12}\b/g,`**** **** ****`));let c=t.id&&!t.getAttribute(`data-bw-auto`)?t.id:t.getAttribute(`data-id`)||t.getAttribute(`data-testid`)||``;if(!c){let e=`${n}|${i}|${a}|${o}|${(t.className||``).toString().replace(/\s+/g,`-`).slice(0,40)}|${t.href||``}|${(t.textContent||``).trim().slice(0,30)}|${t.parentElement?.tagName?.toLowerCase()||`root`}`,r=5381;for(let t=0;t<e.length;t++)r=(r<<5)+r^e.charCodeAt(t);c=`bw-${(r>>>0).toString(16)}`,t.id=c,t.setAttribute(`data-bw-auto`,`true`)}let l=t.getAttribute(`aria-label`)||``;if(!l&&c){let e=document.querySelector(`label[for="${c}"]`);e&&(l=e.textContent?.trim()||``)}if(!l){let e=t.parentElement;for(;e&&e.tagName.toLowerCase()!==`form`&&e.tagName.toLowerCase()!==`body`;){if(e.tagName.toLowerCase()===`label`){l=(e.textContent||``).replace(t.textContent||``,``).trim();break}e=e.parentElement}}if(l||=(t.textContent||``).trim().slice(0,80),l||=t.getAttribute(`title`)||``,!l&&o&&(l=o),!l&&n===`button`){let e=t.querySelector(`svg`);if(e&&typeof e.className?.baseVal==`string`){let t=e.className.baseVal.match(/lucide-([a-z0-9\-]+)/);l=t?`[icon:${t[1]}]`:`[icon]`}else l=`[btn:${(t.className||``).toString().slice(0,30)}]`}return{id:c,label:l.trim(),tag:n,type:i,name:a,placeholder:o,value:s}}).filter(e=>e.label.length>0||(e.placeholder??``).length>0||(e.name??``).length>0).slice(0,100).map(e=>`[`+[e.tag,e.type||``,e.id,e.name||``,e.placeholder||``,e.value||``,e.label].join(`|`)+`]`).join(``),r=t;return r=r.replace(/\b\d{13,19}\b/g,`**** **** **** ****`),r=r.replace(/\b\d{12}\b/g,`**** **** ****`),{page_text:r,elements:n,page_url:e}}executeAction(e){if(e.type===`click_element`&&e.element_id){let t=document.getElementById(e.element_id);if(t){if(t.tagName.toLowerCase()===`a`&&t.href){let n=t.href;return new URL(n,window.location.origin).origin===window.location.origin&&sessionStorage.setItem(`bw-auto-resume`,`true`),t.click(),{result:`✅ Нажал на "${t.textContent?.trim()||e.element_id}"`,causesNavigation:!0}}return t.getAttribute(`type`)===`submit`||t.tagName.toLowerCase()===`button`&&t.closest(`form`)!==null&&t.getAttribute(`type`)!==`button`?(sessionStorage.setItem(`bw-auto-resume`,`verify-only`),t.click(),{result:`✅ Нажал на "${t.textContent?.trim()||e.element_id}"`,causesNavigation:!0}):(t.click(),{result:`✅ Нажал на "${t.textContent?.trim()||e.element_id}"`,causesNavigation:!1})}return{result:`⚠️ Элемент "${e.element_id}" не найден.`,causesNavigation:!1}}if(e.type===`navigate`&&e.url)return sessionStorage.setItem(`bw-auto-resume`,`true`),window.location.href=e.url,{result:`🔀 Перехожу на ${e.url}...`,causesNavigation:!0};if(e.type===`input_text`&&e.element_id&&e.value!==void 0){let t=document.getElementById(e.element_id);if(t){let n=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,`value`)?.set,r=Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype,`value`)?.set;return t.tagName.toLowerCase()===`textarea`&&r?r.call(t,e.value):n?n.call(t,e.value):t.value=e.value,t.dispatchEvent(new Event(`input`,{bubbles:!0})),t.dispatchEvent(new Event(`change`,{bubbles:!0})),{result:`⌨️ Ввел текст "${e.value}" в поле.`,causesNavigation:!1}}return{result:`⚠️ Поле ввода "${e.element_id}" не найдено.`,causesNavigation:!1}}return e.type===`continue`?{result:`🔄 Анализирую страницу...`,causesNavigation:!1}:{result:`⚠️ Неизвестное действие.`,causesNavigation:!1}}async _callAPI(e){let{page_text:t,elements:n,page_url:r}=this.gatherContext(),i=q(),a=this.host.clientId||window.__BARIWEB_CLIENT_ID__||``,o=null;try{let e=await fetch(`${Nt}/v1/training/match-screen`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":a},body:JSON.stringify({fingerprint:i})});if(e.ok){let t=await e.json();t.matched&&(o=t.label)}}catch(e){console.warn(`Failed to match screen fingerprint`,e)}let s=await fetch(`${Nt}/v1/chat`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":a},body:JSON.stringify({query:e,history:this._compressedHistory(),page_text:t,elements:n,page_url:r,screen_label:o,screen_fingerprint:i})});if(!s.ok)throw Error(`HTTP ${s.status}: ${s.statusText}`);let c=await s.json();if(c.text&&c.text.trimStart().startsWith(`{`))try{let e=JSON.parse(c.text);e.text&&(c.text=e.text,e.action&&!c.action&&(c.action=e.action))}catch{c.text=c.text.replace(/^\{"text"\s*:\s*"/,``).replace(/",?\s*"action".*$/,``)}return c}_compressedHistory(){let e=this.messages.map(e=>({role:e.role,text:e.text}));if(e.length<=3)return e;let t=-1;for(let n=e.length-1;n>=0;n--)if(e[n].role===`user`){t=n;break}return t===-1?e.slice(-3):[e[t],...e.slice(t+1).filter(e=>e.role===`assistant`).slice(-2)]}async _agentLoop(e,t,n=!1){if(this.isLoading)return;this.isLoading=!0,this.error=null,this._voiceMode=n,t&&(this.messages=[...this.messages,{role:`user`,text:e,timestamp:Date.now()}],this._saveMessages()),this.host.requestUpdate();let r=e,i=0;try{for(;i<Pt;){i++;let e=await this._callAPI(r),t=e.text;if(e.action){if(It(e.action)){let t=document.getElementById(e.action.element_id||``)?.textContent?.trim()||e.action.element_id||`кнопку`;this.pendingConfirmation={text:`${e.text}\n\n⚠️ Нажать «${t}»?`,action:e.action,currentQuery:r,step:i},this.messages=[...this.messages,{role:`assistant`,text:`${e.text}\n\n🛑 **Подтвердите действие:** нажать «${t}»?`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(e.text),this.isLoading=!1,this.host.requestUpdate();return}let n=this.gatherContext().page_text,{result:a,causesNavigation:o}=this.executeAction(e.action);if(e.action.type===`continue`){this.messages=[...this.messages,{role:`assistant`,text:`🔄 Анализирую...`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(`Анализирую...`),this.host.requestUpdate(),await this._waitForDom(800),r=`Страница обновилась. Продолжай задачу, прочитай DOM.`;continue}if(t=`${e.text}\n${a}`,o){this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t),this.host.requestUpdate(),await this._waitForDom(1500);let e=sessionStorage.getItem(`bw-auto-resume`);if(e===`true`||e===`verify-only`){sessionStorage.removeItem(`bw-auto-resume`),r=e===`verify-only`?`Страница загрузилась после отправки формы (SPA навигация). Проверь новый DOM: если задача выполнена — сообщи об успехе. НЕ нажимай ничего снова.`:`Страница загрузилась (SPA навигация). Продолжай задачу, прочитай новый DOM.`;continue}break}this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t),this.host.requestUpdate(),e.action.type===`input_text`&&e.action.element_id?(await this._waitForDom(800),r=(document.getElementById(e.action.element_id)?.value??``).length>0?`✅ Поле заполнено. Переходи к СЛЕДУЮЩЕМУ незаполненному полю или нажми кнопку отправки. НЕ повторяй ввод.`:`⚠️ Поле не получило значение. Попробуй ввести снова в id="${e.action.element_id}".`):(await this._waitForDom(800),r=n===this.gatherContext().page_text?`⚠️ Страница не изменилась. Возможно кнопка не сработала. Проверь DOM.`:`Действие выполнено. Если задача готова — сообщи. Иначе продолжай.`);continue}this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t);break}}catch(e){this.error=e.message??`Ошибка соединения`,this.messages=[...this.messages,{role:`assistant`,text:`❌ Ошибка: ${this.error}`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(`Ошибка: ${this.error}`)}finally{this.isLoading=!1,this.host.requestUpdate()}}async confirmAction(){if(!this.pendingConfirmation)return;let{action:e}=this.pendingConfirmation;this.pendingConfirmation=null,this.messages=[...this.messages,{role:`user`,text:`✅ Подтверждаю`,timestamp:Date.now()}],this._saveMessages(),this.host.requestUpdate();let{result:t,causesNavigation:n}=this.executeAction(e);this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t),this.host.requestUpdate(),!n&&(await this._waitForDom(1200),await this._agentStep(`Действие подтверждено и выполнено. Проверь результат в DOM.`))}cancelAction(){this.pendingConfirmation&&(this.pendingConfirmation=null,this.messages=[...this.messages,{role:`user`,text:`❌ Отмена`,timestamp:Date.now()},{role:`assistant`,text:`🚫 Действие отменено. Чем ещё могу помочь?`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(`Действие отменено. Чем ещё могу помочь?`),this.host.requestUpdate())}_waitForDom(e){return new Promise(t=>setTimeout(t,e))}async sendMessage(e,t=!1){!e.trim()||this.isLoading||(await this._agentLoop(e,!0,t),this.host.updateComplete?.then(()=>{let e=this.host.renderRoot?.querySelector(`.chat-messages`);e&&(e.scrollTop=e.scrollHeight)}))}async _agentStep(e){await this._agentLoop(e,!1,this._voiceMode),this.host.updateComplete?.then(()=>{let e=this.host.renderRoot?.querySelector(`.chat-messages`);e&&(e.scrollTop=e.scrollHeight)})}clearMessages(){this.messages=[],this.error=null,this.pendingConfirmation=null,this._saveMessages(),this.host.requestUpdate()}isTtsEnabled(){return this._tts.isEnabled()}setTtsEnabled(e){this._tts.setEnabled(e),this.host.requestUpdate()}async transcribeAudio(e,t){let n=this.host.clientId||window.__BARIWEB_CLIENT_ID__||``,r=new FormData;r.append(`language_mode`,t),r.append(`audio`,e,`speech.wav`);let i=await fetch(`${Nt}/v1/stt/transcribe`,{method:`POST`,headers:{"X-Client-ID":n},body:r});if(!i.ok){let e=`HTTP ${i.status}`;try{e=(await i.json())?.detail||e}catch{}throw Error(e)}return await i.json()}};function Y(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var Rt=n({initAdminMode:()=>Ht,mountAdminPanel:()=>Vt});function zt(){if(!X)return;let e=K(),t=q(),n=Z?.is_trained===!0,r=Z&&!Z.is_trained,i=Z?.label||null,a=Z?.description||null,o=n?`active`:r?`draft`:`idle`,s=n?`trained`:r?`draft`:`idle`,c=n?`✅ Обучено`:r?`📝 Черновик (не подтверждено)`:`🔍 Сканирование...`,l=X.querySelector(`#bw-admin-panel`);l&&(l.className=n?`trained`:`discovering`,l.id=`bw-admin-panel`,n&&l.classList.add(`trained`));let u=X.querySelector(`#bw-panel-content`);u&&(u.innerHTML=`
910
+ `,document.head.appendChild(e)}document.body.classList.add(`bw-simplify-mode`),this._announce(`Режим AI Упрощение текста включен. Используйте Tab для навигации по тексту и Enter для упрощения.`)}else document.body.removeEventListener(`click`,this._onParagraphClick,{capture:!0}),document.body.removeEventListener(`keydown`,this._onParagraphKeydown,{capture:!0}),document.querySelectorAll(`.bw-simplify-focusable`).forEach(e=>{e.removeAttribute(`tabindex`),e.classList.remove(`bw-simplify-focusable`)}),document.body.classList.remove(`bw-simplify-mode`),document.documentElement.style.removeProperty(`--bw-simplify-cursor`),this._announce(`Режим AI Упрощение текста выключен.`);this.host.requestUpdate()}async _triggerSimplify(e,t,n){let r=e.innerText?.trim();if(!r)return;document.querySelectorAll(`.bw-ai-tooltip`).forEach(e=>e.remove());let i=document.createElement(`div`);i.className=`bw-ai-tooltip bw-ai-tooltip-loading`,i.tabIndex=-1,i.innerHTML=`
911
+ <div class="bw-ai-tooltip-header">
912
+ <span>✨ AI Упрощение</span>
913
+ <button class="bw-ai-tooltip-close" aria-label="Закрыть">✕</button>
914
+ </div>
915
+ <div class="bw-ai-tooltip-content" role="status" aria-live="polite">
916
+ Ожидаем ответ от ИИ...
917
+ </div>
918
+ `,document.body.appendChild(i),i.style.left=`${Math.max(10,t-160)}px`,i.style.top=`${n+20}px`;let a=e.style.outline,o=e.style.backgroundColor;e.style.outline=`2px dashed #a855f7`,e.style.backgroundColor=`rgba(168, 85, 247, 0.05)`,i.querySelector(`.bw-ai-tooltip-close`)?.addEventListener(`click`,()=>{i.remove(),e.style.outline=a,e.style.backgroundColor=o});try{let e=window.BariwebConfig?.clientId||``,t=await fetch(`${kt}/v1/widget/a11y/simplify`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":e},body:JSON.stringify({text:r})});if(t.ok){let e=await t.json();if(e.text)i.classList.remove(`bw-ai-tooltip-loading`),i.querySelector(`.bw-ai-tooltip-content`).innerHTML=e.text,i.focus();else throw Error(`Empty response`)}else throw Error(`Server error`)}catch(e){console.error(`BariWeb AI: Simplify failed`,e),i.classList.remove(`bw-ai-tooltip-loading`),i.querySelector(`.bw-ai-tooltip-content`).innerHTML=`<span style="color:#ef4444; font-size:13px;">Ошибка создания упрощенного текста. Попробуйте еще раз.</span>`,i.focus()}}},jt=`bw-tts-enabled-v1`,Mt=class{constructor(){this.enabled=!0,this.enabled=this.loadEnabled()}isEnabled(){return this.enabled}setEnabled(e){this.enabled=e;try{localStorage.setItem(jt,e?`1`:`0`)}catch{}e||this.stop()}stop(){`speechSynthesis`in window&&window.speechSynthesis.cancel()}speak(e){if(!this.enabled||!(`speechSynthesis`in window))return;let t=(e||``).trim();if(t)try{window.speechSynthesis.cancel();let e=new SpeechSynthesisUtterance(t),n=this.detectLanguage(t);e.lang=n;let r=this.pickVoice(n);r&&(e.voice=r),e.rate=1,e.pitch=1,window.speechSynthesis.speak(e)}catch(e){console.warn(`TTS speak failed`,e)}}loadEnabled(){try{let e=localStorage.getItem(jt);return e===null?!0:e!==`0`}catch{return!0}}detectLanguage(e){let t=e.toLowerCase();return/[әіңғүұқөһ]/i.test(t)?`kk-KZ`:/[а-яё]/i.test(t)?`ru-RU`:/[a-z]/i.test(t)?`en-US`:`ru-RU`}pickVoice(e){if(!(`speechSynthesis`in window))return null;let t=window.speechSynthesis.getVoices();if(!t||t.length===0)return null;let n=e.split(`-`)[0].toLowerCase();return t.find(t=>t.lang.toLowerCase()===e.toLowerCase())||t.find(e=>e.lang.toLowerCase().startsWith(n))||t[0]||null}};Tt();var Nt=`http://localhost:8000`,Pt=5,Ft=[/(submit|отправить|оплатить|сгенерировать|сохранить|перевести|подтвердит|купить|удалить|delete|pay|purchase|buy|send|transfer|confirm|place.?order|checkout|remove|drop|unsubscribe|sign.?out|выйти|уволить)/i];function It(e){if(e.type!==`click_element`||!e.element_id)return!1;let t=document.getElementById(e.element_id);if(!t)return!1;if(t.getAttribute(`type`)===`submit`||t.tagName.toLowerCase()===`button`&&t.closest(`form`)!==null&&t.getAttribute(`type`)!==`button`)return!0;let n=[t.textContent?.trim()||``,t.getAttribute(`aria-label`)||``,t.getAttribute(`title`)||``,t.getAttribute(`name`)||``,t.getAttribute(`value`)||``].join(` `);return Ft.some(e=>e.test(n))}var Lt=class{constructor(e){this.messages=[],this.isLoading=!1,this.error=null,this._tts=new Mt,this._voiceMode=!1,this.pendingConfirmation=null,(this.host=e).addController(this),this._loadMessages()}hostConnected(){}hostDisconnected(){this._tts.stop()}_loadMessages(){try{let e=sessionStorage.getItem(`bw-chat-history`);e&&(this.messages=JSON.parse(e),this.messages.length>0&&typeof this.host.setOpen==`function`&&setTimeout(()=>this.host.setOpen(!0),100));let t=sessionStorage.getItem(`bw-auto-resume`);if(t===`true`||t===`verify-only`){sessionStorage.removeItem(`bw-auto-resume`);let e=t===`verify-only`?`Страница загрузилась после отправки формы. Проверь новый DOM: если авторизация прошла успешно (нет формы входа, есть контент приложения) — сообщи об успехе. НЕ нажимай ничего снова.`:`Страница загрузилась. Продолжай выполнение задачи с учетом нового контекста и DOM.`;setTimeout(()=>{this._agentStep(e)},1e3)}}catch(e){console.error(`Failed to load chat history`,e)}}_saveMessages(){try{sessionStorage.setItem(`bw-chat-history`,JSON.stringify(this.messages))}catch(e){console.error(`Failed to save chat history`,e)}}gatherContext(){let e=window.location.href,t=document.body?.innerText?.slice(0,3e3)??``,n=Array.from(document.querySelectorAll(`a[href], button, [role="button"], input:not([type="hidden"]), textarea, select`)).filter(e=>!e.hasAttribute(`bw-private`)).map(e=>{let t=e,n=t.tagName.toLowerCase(),r=n===`input`||n===`textarea`||n===`select`,i=t.getAttribute(`type`)||(n===`input`?`text`:n===`button`?`button`:n),a=t.getAttribute(`name`)||``,o=t.getAttribute(`placeholder`)||``,s=r?(t.value||``).slice(0,80):``;s&&=(s=s.replace(/\b\d{13,19}\b/g,e=>e.slice(0,4)+` **** **** `+e.slice(-4)),s.replace(/\b\d{12}\b/g,`**** **** ****`));let c=t.id&&!t.getAttribute(`data-bw-auto`)?t.id:t.getAttribute(`data-id`)||t.getAttribute(`data-testid`)||``;if(!c){let e=`${n}|${i}|${a}|${o}|${(t.className||``).toString().replace(/\s+/g,`-`).slice(0,40)}|${t.href||``}|${(t.textContent||``).trim().slice(0,30)}|${t.parentElement?.tagName?.toLowerCase()||`root`}`,r=5381;for(let t=0;t<e.length;t++)r=(r<<5)+r^e.charCodeAt(t);c=`bw-${(r>>>0).toString(16)}`,t.id=c,t.setAttribute(`data-bw-auto`,`true`)}let l=t.getAttribute(`aria-label`)||``;if(!l&&c){let e=document.querySelector(`label[for="${c}"]`);e&&(l=e.textContent?.trim()||``)}if(!l){let e=t.parentElement;for(;e&&e.tagName.toLowerCase()!==`form`&&e.tagName.toLowerCase()!==`body`;){if(e.tagName.toLowerCase()===`label`){l=(e.textContent||``).replace(t.textContent||``,``).trim();break}e=e.parentElement}}if(l||=(t.textContent||``).trim().slice(0,80),l||=t.getAttribute(`title`)||``,!l&&o&&(l=o),!l&&n===`button`){let e=t.querySelector(`svg`);if(e&&typeof e.className?.baseVal==`string`){let t=e.className.baseVal.match(/lucide-([a-z0-9\-]+)/);l=t?`[icon:${t[1]}]`:`[icon]`}else l=`[btn:${(t.className||``).toString().slice(0,30)}]`}return{id:c,label:l.trim(),tag:n,type:i,name:a,placeholder:o,value:s}}).filter(e=>e.label.length>0||(e.placeholder??``).length>0||(e.name??``).length>0).slice(0,100).map(e=>`[`+[e.tag,e.type||``,e.id,e.name||``,e.placeholder||``,e.value||``,e.label].join(`|`)+`]`).join(``),r=t;return r=r.replace(/\b\d{13,19}\b/g,`**** **** **** ****`),r=r.replace(/\b\d{12}\b/g,`**** **** ****`),{page_text:r,elements:n,page_url:e}}executeAction(e){if(e.type===`click_element`&&e.element_id){let t=document.getElementById(e.element_id);if(t){if(t.tagName.toLowerCase()===`a`&&t.href){let n=t.href;return new URL(n,window.location.origin).origin===window.location.origin&&sessionStorage.setItem(`bw-auto-resume`,`true`),t.click(),{result:`✅ Нажал на "${t.textContent?.trim()||e.element_id}"`,causesNavigation:!0}}return t.getAttribute(`type`)===`submit`||t.tagName.toLowerCase()===`button`&&t.closest(`form`)!==null&&t.getAttribute(`type`)!==`button`?(sessionStorage.setItem(`bw-auto-resume`,`verify-only`),t.click(),{result:`✅ Нажал на "${t.textContent?.trim()||e.element_id}"`,causesNavigation:!0}):(t.click(),{result:`✅ Нажал на "${t.textContent?.trim()||e.element_id}"`,causesNavigation:!1})}return{result:`⚠️ Элемент "${e.element_id}" не найден.`,causesNavigation:!1}}if(e.type===`navigate`&&e.url)return sessionStorage.setItem(`bw-auto-resume`,`true`),window.location.href=e.url,{result:`🔀 Перехожу на ${e.url}...`,causesNavigation:!0};if(e.type===`input_text`&&e.element_id&&e.value!==void 0){let t=document.getElementById(e.element_id);if(t){let n=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,`value`)?.set,r=Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype,`value`)?.set;return t.tagName.toLowerCase()===`textarea`&&r?r.call(t,e.value):n?n.call(t,e.value):t.value=e.value,t.dispatchEvent(new Event(`input`,{bubbles:!0})),t.dispatchEvent(new Event(`change`,{bubbles:!0})),{result:`⌨️ Ввел текст "${e.value}" в поле.`,causesNavigation:!1}}return{result:`⚠️ Поле ввода "${e.element_id}" не найдено.`,causesNavigation:!1}}return e.type===`continue`?{result:`🔄 Анализирую страницу...`,causesNavigation:!1}:{result:`⚠️ Неизвестное действие.`,causesNavigation:!1}}async _callAPI(e){let{page_text:t,elements:n,page_url:r}=this.gatherContext(),i=q(),a=this.host.clientId||window.__BARIWEB_CLIENT_ID__||``,o=null;try{let e=await fetch(`${Nt}/v1/training/match-screen`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":a},body:JSON.stringify({fingerprint:i})});if(e.ok){let t=await e.json();t.matched&&(o=t.label)}}catch(e){console.warn(`Failed to match screen fingerprint`,e)}let s=await fetch(`${Nt}/v1/chat`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Client-ID":a},body:JSON.stringify({query:e,history:this._compressedHistory(),page_text:t,elements:n,page_url:r,screen_label:o,screen_fingerprint:i})});if(!s.ok)throw Error(`HTTP ${s.status}: ${s.statusText}`);let c=await s.json();if(c.text&&c.text.trimStart().startsWith(`{`))try{let e=JSON.parse(c.text);e.text&&(c.text=e.text,e.action&&!c.action&&(c.action=e.action))}catch{c.text=c.text.replace(/^\{"text"\s*:\s*"/,``).replace(/",?\s*"action".*$/,``)}return c}_compressedHistory(){let e=this.messages.map(e=>({role:e.role,text:e.text}));if(e.length<=3)return e;let t=-1;for(let n=e.length-1;n>=0;n--)if(e[n].role===`user`){t=n;break}return t===-1?e.slice(-3):[e[t],...e.slice(t+1).filter(e=>e.role===`assistant`).slice(-2)]}async _agentLoop(e,t,n=!1){if(this.isLoading)return;this.isLoading=!0,this.error=null,this._voiceMode=n,t&&(this.messages=[...this.messages,{role:`user`,text:e,timestamp:Date.now()}],this._saveMessages()),this.host.requestUpdate();let r=e,i=0;try{for(;i<Pt;){i++;let e=await this._callAPI(r),t=e.text;if(e.action){if(It(e.action)){let t=document.getElementById(e.action.element_id||``)?.textContent?.trim()||e.action.element_id||`кнопку`;this.pendingConfirmation={text:`${e.text}\n\n⚠️ Нажать «${t}»?`,action:e.action,currentQuery:r,step:i},this.messages=[...this.messages,{role:`assistant`,text:`${e.text}\n\n🛑 **Подтвердите действие:** нажать «${t}»?`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(e.text),this.isLoading=!1,this.host.requestUpdate();return}let n=this.gatherContext().page_text,{result:a,causesNavigation:o}=this.executeAction(e.action);if(e.action.type===`continue`){this.messages=[...this.messages,{role:`assistant`,text:`🔄 Анализирую...`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(`Анализирую...`),this.host.requestUpdate(),await this._waitForDom(800),r=`Страница обновилась. Продолжай задачу, прочитай DOM.`;continue}if(t=`${e.text}\n${a}`,o){this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t),this.host.requestUpdate(),await this._waitForDom(1500);let e=sessionStorage.getItem(`bw-auto-resume`);if(e===`true`||e===`verify-only`){sessionStorage.removeItem(`bw-auto-resume`),r=e===`verify-only`?`Страница загрузилась после отправки формы (SPA навигация). Проверь новый DOM: если задача выполнена — сообщи об успехе. НЕ нажимай ничего снова.`:`Страница загрузилась (SPA навигация). Продолжай задачу, прочитай новый DOM.`;continue}break}this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t),this.host.requestUpdate(),e.action.type===`input_text`&&e.action.element_id?(await this._waitForDom(800),r=(document.getElementById(e.action.element_id)?.value??``).length>0?`✅ Поле заполнено. Переходи к СЛЕДУЮЩЕМУ незаполненному полю или нажми кнопку отправки. НЕ повторяй ввод.`:`⚠️ Поле не получило значение. Попробуй ввести снова в id="${e.action.element_id}".`):(await this._waitForDom(800),r=n===this.gatherContext().page_text?`⚠️ Страница не изменилась. Возможно кнопка не сработала. Проверь DOM.`:`Действие выполнено. Если задача готова — сообщи. Иначе продолжай.`);continue}this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t);break}}catch(e){this.error=e.message??`Ошибка соединения`,this.messages=[...this.messages,{role:`assistant`,text:`❌ Ошибка: ${this.error}`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(`Ошибка: ${this.error}`)}finally{this.isLoading=!1,this.host.requestUpdate()}}async confirmAction(){if(!this.pendingConfirmation)return;let{action:e}=this.pendingConfirmation;this.pendingConfirmation=null,this.messages=[...this.messages,{role:`user`,text:`✅ Подтверждаю`,timestamp:Date.now()}],this._saveMessages(),this.host.requestUpdate();let{result:t,causesNavigation:n}=this.executeAction(e);this.messages=[...this.messages,{role:`assistant`,text:t,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(t),this.host.requestUpdate(),!n&&(await this._waitForDom(1200),await this._agentStep(`Действие подтверждено и выполнено. Проверь результат в DOM.`))}cancelAction(){this.pendingConfirmation&&(this.pendingConfirmation=null,this.messages=[...this.messages,{role:`user`,text:`❌ Отмена`,timestamp:Date.now()},{role:`assistant`,text:`🚫 Действие отменено. Чем ещё могу помочь?`,timestamp:Date.now()}],this._saveMessages(),this._voiceMode&&this._tts.speak(`Действие отменено. Чем ещё могу помочь?`),this.host.requestUpdate())}_waitForDom(e){return new Promise(t=>setTimeout(t,e))}async sendMessage(e,t=!1){!e.trim()||this.isLoading||(await this._agentLoop(e,!0,t),this.host.updateComplete?.then(()=>{let e=this.host.renderRoot?.querySelector(`.chat-messages`);e&&(e.scrollTop=e.scrollHeight)}))}async _agentStep(e){await this._agentLoop(e,!1,this._voiceMode),this.host.updateComplete?.then(()=>{let e=this.host.renderRoot?.querySelector(`.chat-messages`);e&&(e.scrollTop=e.scrollHeight)})}clearMessages(){this.messages=[],this.error=null,this.pendingConfirmation=null,this._saveMessages(),this.host.requestUpdate()}isTtsEnabled(){return this._tts.isEnabled()}setTtsEnabled(e){this._tts.setEnabled(e),this.host.requestUpdate()}async transcribeAudio(e,t){let n=this.host.clientId||window.__BARIWEB_CLIENT_ID__||``,r=new FormData;r.append(`language_mode`,t),r.append(`audio`,e,`speech.wav`);let i=await fetch(`${Nt}/v1/stt/transcribe`,{method:`POST`,headers:{"X-Client-ID":n},body:r});if(!i.ok){let e=`HTTP ${i.status}`;try{e=(await i.json())?.detail||e}catch{}throw Error(e)}return await i.json()}};function Y(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var Rt=n({initAdminMode:()=>Ht,mountAdminPanel:()=>Vt});function zt(){if(!X)return;let e=K(),t=q(),n=Z?.is_trained===!0,r=Z&&!Z.is_trained,i=Z?.label||null,a=Z?.description||null,o=n?`active`:r?`draft`:`idle`,s=n?`trained`:r?`draft`:`idle`,c=n?`✅ Обучено`:r?`📝 Черновик (не подтверждено)`:`🔍 Сканирование...`,l=X.querySelector(`#bw-admin-panel`);l&&(l.className=n?`trained`:`discovering`,l.id=`bw-admin-panel`,n&&l.classList.add(`trained`));let u=X.querySelector(`#bw-panel-content`);u&&(u.innerHTML=`
913
919
  <div class="bw-status-box ${n?`trained`:r?`draft`:``}">
914
920
  <div class="bw-status-indicator">
915
921
  <span class="bw-status-dot ${o}"></span>
package/dist/bariweb.js CHANGED
@@ -1169,6 +1169,12 @@ var at = rt(K), q = (e) => F`${at(`
1169
1169
  --bw-border: #e2e8f0;
1170
1170
  --bw-bg-hover: #f8fafc;
1171
1171
  --bw-bg-subtle: #f1f5f9;
1172
+ --bw-danger: #ef4444;
1173
+ --bw-danger-bg: #fee2e2;
1174
+ --bw-danger-border: #fecaca;
1175
+ --bw-success: #10b981;
1176
+ --bw-success-bg: rgba(16, 185, 129, 0.08);
1177
+ --bw-success-border: rgba(16, 185, 129, 0.2);
1172
1178
  --bw-radius: 14px;
1173
1179
  --bw-radius-sm: 8px;
1174
1180
  --bw-shadow-panel: 0 20px 60px -10px rgba(0,0,0,0.18), 0 8px 24px -4px rgba(0,0,0,0.1);
@@ -1281,7 +1287,7 @@ var at = rt(K), q = (e) => F`${at(`
1281
1287
  transition: all 0.2s;
1282
1288
  color: var(--bw-fg-muted);
1283
1289
  }
1284
- .close-btn:hover { background: #fee2e2; color: #ef4444; transform: rotate(90deg); }
1290
+ .close-btn:hover { background: var(--bw-danger-bg); color: var(--bw-danger); transform: rotate(90deg); }
1285
1291
  .close-btn svg { width: 18px; height: 18px; }
1286
1292
 
1287
1293
  /* ─── Segmented Tab Control ─── */
@@ -1315,8 +1321,8 @@ var at = rt(K), q = (e) => F`${at(`
1315
1321
  .bw-tab:hover { background: var(--bw-bg-hover); color: var(--bw-fg); }
1316
1322
  .bw-tab[active] {
1317
1323
  background: var(--bw-primary);
1318
- color: white;
1319
- box-shadow: 0 2px 8px rgba(109, 40, 217, 0.3);
1324
+ color: var(--bw-primary-fg);
1325
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
1320
1326
  }
1321
1327
 
1322
1328
  /* ─── Content area ─── */
@@ -1411,7 +1417,7 @@ var at = rt(K), q = (e) => F`${at(`
1411
1417
  .chat-bubble.user {
1412
1418
  align-self: flex-end;
1413
1419
  background: var(--bw-primary);
1414
- color: white;
1420
+ color: var(--bw-primary-fg);
1415
1421
  border-bottom-right-radius: 4px;
1416
1422
  }
1417
1423
  .chat-bubble.assistant {
@@ -1423,12 +1429,12 @@ var at = rt(K), q = (e) => F`${at(`
1423
1429
  }
1424
1430
 
1425
1431
  .screen-label-badge {
1426
- background: rgba(16, 185, 129, 0.08);
1427
- border: 1px solid rgba(16, 185, 129, 0.2);
1432
+ background: var(--bw-success-bg);
1433
+ border: 1px solid var(--bw-success-border);
1428
1434
  border-radius: var(--bw-radius-sm);
1429
1435
  padding: 6px 12px;
1430
1436
  font-size: 12px;
1431
- color: #059669;
1437
+ color: var(--bw-success);
1432
1438
  display: flex;
1433
1439
  align-items: center;
1434
1440
  gap: 6px;
@@ -1492,17 +1498,17 @@ var at = rt(K), q = (e) => F`${at(`
1492
1498
  }
1493
1499
  .btn-confirm {
1494
1500
  width: 100%; min-height: 46px; border-radius: var(--bw-radius-sm);
1495
- background: var(--bw-primary); color: white; border: none;
1501
+ background: var(--bw-primary); color: var(--bw-primary-fg); border: none;
1496
1502
  font-weight: 700; font-size: 14px; cursor: pointer;
1497
- transition: all 0.2s; box-shadow: 0 4px 12px rgba(109, 40, 217, 0.25);
1503
+ transition: all 0.2s; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1498
1504
  }
1499
1505
  .btn-confirm:hover { filter: brightness(1.1); transform: translateY(-1px); }
1500
1506
  .btn-cancel {
1501
1507
  width: 100%; min-height: 44px; border-radius: var(--bw-radius-sm);
1502
- background: transparent; color: #ef4444; border: 1px solid #fecaca;
1508
+ background: transparent; color: var(--bw-danger); border: 1px solid var(--bw-danger-border);
1503
1509
  font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s;
1504
1510
  }
1505
- .btn-cancel:hover { background: #fef2f2; }
1511
+ .btn-cancel:hover { background: var(--bw-danger-bg); }
1506
1512
 
1507
1513
  /* Chat input area */
1508
1514
  .chat-input-area {
@@ -1581,14 +1587,14 @@ var at = rt(K), q = (e) => F`${at(`
1581
1587
  }
1582
1588
  #bw-voice-btn:hover { background: rgba(109, 40, 217, 0.08); transform: scale(1.05); }
1583
1589
  #bw-voice-btn.recording {
1584
- background: #fef2f2;
1585
- border-color: #dc2626;
1586
- color: #dc2626;
1590
+ background: var(--bw-danger-bg);
1591
+ border-color: var(--bw-danger);
1592
+ color: var(--bw-danger);
1587
1593
  animation: micPulse 1.5s infinite;
1588
1594
  }
1589
1595
  @keyframes micPulse {
1590
- 0% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.4); transform: scale(1.05); }
1591
- 100% { box-shadow: 0 0 0 10px rgba(220, 38, 38, 0); transform: scale(1.05); }
1596
+ 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); transform: scale(1.05); }
1597
+ 100% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); transform: scale(1.05); }
1592
1598
  }
1593
1599
 
1594
1600
  .chat-icon-btn.tts-on { background: rgba(16,185,129,0.1); border-color: rgba(16,185,129,0.4); color: #059669; }
@@ -1600,13 +1606,13 @@ var at = rt(K), q = (e) => F`${at(`
1600
1606
  border-radius: 50%;
1601
1607
  border: none;
1602
1608
  background: var(--bw-primary);
1603
- color: white;
1609
+ color: var(--bw-primary-fg);
1604
1610
  cursor: pointer;
1605
1611
  display: flex;
1606
1612
  align-items: center;
1607
1613
  justify-content: center;
1608
1614
  transition: all 0.2s;
1609
- box-shadow: 0 2px 8px rgba(109,40,217,0.3);
1615
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
1610
1616
  margin-left: 6px;
1611
1617
  }
1612
1618
  .chat-send-btn:hover:not(:disabled) { transform: scale(1.08); filter: brightness(1.1); }
@@ -1959,7 +1965,29 @@ var at = rt(K), q = (e) => F`${at(`
1959
1965
  }
1960
1966
  }, lt = "http://localhost:8000", ut = class {
1961
1967
  constructor(e) {
1962
- this.isFixing = !1, this.simplifyEnabled = !1, this.autoA11yEnabled = !1, this._onParagraphClick = async (e) => {
1968
+ this.isFixing = !1, this.simplifyEnabled = !1, this.autoA11yEnabled = !1, this._onParagraphKeydown = (e) => {
1969
+ if (this.simplifyEnabled && (e.key === "Enter" || e.key === " ") && e.target instanceof HTMLElement) {
1970
+ if (e.target.closest("bw-widget") || e.target.closest(".bw-ai-tooltip")) return;
1971
+ let t = e.target.tagName.toLowerCase();
1972
+ if ([
1973
+ "p",
1974
+ "span",
1975
+ "div",
1976
+ "li",
1977
+ "article",
1978
+ "h1",
1979
+ "h2",
1980
+ "h3",
1981
+ "h4",
1982
+ "h5",
1983
+ "h6"
1984
+ ].includes(t)) {
1985
+ e.preventDefault(), e.stopPropagation();
1986
+ let t = e.target.getBoundingClientRect();
1987
+ this._triggerSimplify(e.target, t.left + window.scrollX, t.bottom + window.scrollY);
1988
+ }
1989
+ }
1990
+ }, this._onParagraphClick = async (e) => {
1963
1991
  if (!this.simplifyEnabled) return;
1964
1992
  let t = e.target;
1965
1993
  if (t.closest("bw-widget") || t.closest(".bw-ai-tooltip")) return;
@@ -1978,32 +2006,7 @@ var at = rt(K), q = (e) => F`${at(`
1978
2006
  "h6"
1979
2007
  ].includes(n)) {
1980
2008
  let n = t.innerText?.trim();
1981
- if (n && n.length > 20) {
1982
- e.preventDefault(), e.stopPropagation(), document.querySelectorAll(".bw-ai-tooltip").forEach((e) => e.remove());
1983
- let r = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches, i = document.createElement("div");
1984
- i.className = "bw-ai-tooltip bw-ai-tooltip-loading", r && i.setAttribute("data-theme", "dark"), i.innerHTML = "\n <div class=\"bw-ai-tooltip-header\">\n <span>✨ AI Упрощение</span>\n <button class=\"bw-ai-tooltip-close\">✕</button>\n </div>\n <div class=\"bw-ai-tooltip-content\">\n Ожидаем ответ от ИИ...\n </div>\n ", document.body.appendChild(i), i.style.left = `${Math.max(10, e.pageX - 160)}px`, i.style.top = `${e.pageY + 20}px`;
1985
- let a = t.style.outline, o = t.style.backgroundColor;
1986
- t.style.outline = "2px dashed #a855f7", t.style.backgroundColor = "rgba(168, 85, 247, 0.05)", i.querySelector(".bw-ai-tooltip-close")?.addEventListener("click", () => {
1987
- i.remove(), t.style.outline = a, t.style.backgroundColor = o;
1988
- });
1989
- try {
1990
- let e = window.BariwebConfig?.clientId || "", t = await fetch(`${lt}/v1/widget/a11y/simplify`, {
1991
- method: "POST",
1992
- headers: {
1993
- "Content-Type": "application/json",
1994
- "X-Client-ID": e
1995
- },
1996
- body: JSON.stringify({ text: n })
1997
- });
1998
- if (t.ok) {
1999
- let e = await t.json();
2000
- if (e.text) i.classList.remove("bw-ai-tooltip-loading"), i.querySelector(".bw-ai-tooltip-content").innerHTML = e.text;
2001
- else throw Error("Empty response");
2002
- } else throw Error("Server error");
2003
- } catch (e) {
2004
- console.error("BariWeb AI: Simplify failed", e), i.classList.remove("bw-ai-tooltip-loading"), i.querySelector(".bw-ai-tooltip-content").innerHTML = "<span style=\"color:#ef4444; font-size:13px;\">Ошибка создания упрощенного текста. Попробуйте еще раз.</span>";
2005
- }
2006
- }
2009
+ n && n.length > 20 && (e.preventDefault(), e.stopPropagation(), this._triggerSimplify(t, e.pageX, e.pageY));
2007
2010
  }
2008
2011
  }, (this.host = e).addController(this), this.simplifyEnabled = localStorage.getItem("bw-ai-simplify") === "true", this.autoA11yEnabled = localStorage.getItem("bw-ai-autofix") === "true", t.onStateChange(() => {
2009
2012
  this.autoA11yEnabled && !this.isFixing && this.fixMarkup();
@@ -2016,6 +2019,20 @@ var at = rt(K), q = (e) => F`${at(`
2016
2019
  hostDisconnected() {
2017
2020
  this.simplifyEnabled && (document.body.removeEventListener("click", this._onParagraphClick, { capture: !0 }), document.body.classList.remove("bw-simplify-mode"));
2018
2021
  }
2022
+ _announce(e) {
2023
+ let t = document.getElementById("bw-ai-announcer");
2024
+ t || (t = document.createElement("div"), t.id = "bw-ai-announcer", t.setAttribute("aria-live", "polite"), t.setAttribute("aria-atomic", "true"), Object.assign(t.style, {
2025
+ position: "absolute",
2026
+ width: "1px",
2027
+ height: "1px",
2028
+ padding: "0",
2029
+ margin: "-1px",
2030
+ overflow: "hidden",
2031
+ clip: "rect(0, 0, 0, 0)",
2032
+ whiteSpace: "nowrap",
2033
+ border: "0"
2034
+ }), document.body.appendChild(t)), t.textContent = e;
2035
+ }
2019
2036
  async fixMarkup() {
2020
2037
  this.isFixing = !0, this.host.requestUpdate();
2021
2038
  try {
@@ -2058,22 +2075,55 @@ var at = rt(K), q = (e) => F`${at(`
2058
2075
  }
2059
2076
  });
2060
2077
  }
2078
+ this._announce(`Режим для незрячих отработал. AI исправил ${e.length} элементов.`);
2061
2079
  } catch (e) {
2062
- console.error("BariWeb AI: A11y Fix failed", e);
2080
+ console.error("BariWeb AI: A11y Fix failed", e), this._announce("Произошла ошибка при исправлении элементов.");
2063
2081
  } finally {
2064
2082
  this.isFixing = !1, this.host.requestUpdate();
2065
2083
  }
2066
2084
  }
2067
2085
  toggleSimplify() {
2068
2086
  if (this.simplifyEnabled = !this.simplifyEnabled, this.simplifyEnabled) {
2069
- if (document.body.addEventListener("click", this._onParagraphClick, { capture: !0 }), document.documentElement.style.setProperty("--bw-simplify-cursor", "help"), !document.getElementById("bw-simplify-mode-style")) {
2087
+ if (document.body.addEventListener("click", this._onParagraphClick, { capture: !0 }), document.body.addEventListener("keydown", this._onParagraphKeydown, { capture: !0 }), document.querySelectorAll("p, h1, h2, h3, h4, h5, h6, li, article").forEach((e) => {
2088
+ !e.hasAttribute("tabindex") && e.textContent?.trim().length > 20 && (e.setAttribute("tabindex", "0"), e.classList.add("bw-simplify-focusable"));
2089
+ }), document.documentElement.style.setProperty("--bw-simplify-cursor", "help"), !document.getElementById("bw-simplify-mode-style")) {
2070
2090
  let e = document.createElement("style");
2071
2091
  e.id = "bw-simplify-mode-style", e.textContent = "\n body.bw-simplify-mode *:hover {\n cursor: help !important;\n background-color: rgba(168, 85, 247, 0.1) !important;\n outline: 1px dashed rgba(168, 85, 247, 0.4) !important;\n }\n bw-widget.bw-simplify-mode *:hover, .bw-ai-tooltip *:hover {\n cursor: inherit !important;\n background-color: transparent !important;\n outline: none !important;\n }\n .bw-ai-tooltip {\n position: absolute;\n width: 320px;\n background: #ffffff;\n border: 1px solid #e2e8f0;\n border-radius: 12px;\n box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n color: #0f172a;\n font-family: system-ui, -apple-system, sans-serif;\n z-index: 999999;\n overflow: hidden;\n animation: bwAiFadeIn 0.2s ease-out;\n }\n .bw-ai-tooltip[data-theme=\"dark\"] {\n background: #1e293b;\n border-color: #334155;\n color: #f8fafc;\n }\n .bw-ai-tooltip-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #f8fafc;\n border-bottom: 1px solid #e2e8f0;\n font-size: 11px;\n font-weight: 700;\n color: #64748b;\n }\n .bw-ai-tooltip[data-theme=\"dark\"] .bw-ai-tooltip-header {\n background: #0f172a;\n border-bottom-color: #334155;\n color: #94a3b8;\n }\n .bw-ai-tooltip-close {\n background: transparent;\n border: none;\n color: inherit;\n cursor: pointer;\n font-size: 14px;\n padding: 2px 6px;\n border-radius: 4px;\n }\n .bw-ai-tooltip-close:hover {\n background: rgba(0,0,0,0.05);\n }\n .bw-ai-tooltip[data-theme=\"dark\"] .bw-ai-tooltip-close:hover {\n background: rgba(255,255,255,0.1);\n }\n .bw-ai-tooltip-content {\n padding: 14px;\n font-size: 14px;\n line-height: 1.6;\n }\n .bw-ai-tooltip-loading .bw-ai-tooltip-content {\n display: flex;\n align-items: center;\n gap: 10px;\n color: #64748b;\n font-style: italic;\n font-size: 13px;\n }\n @keyframes bwAiFadeIn {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n ", document.head.appendChild(e);
2072
2092
  }
2073
- document.body.classList.add("bw-simplify-mode");
2074
- } else document.body.removeEventListener("click", this._onParagraphClick, { capture: !0 }), document.body.classList.remove("bw-simplify-mode"), document.documentElement.style.removeProperty("--bw-simplify-cursor");
2093
+ document.body.classList.add("bw-simplify-mode"), this._announce("Режим AI Упрощение текста включен. Используйте Tab для навигации по тексту и Enter для упрощения.");
2094
+ } else document.body.removeEventListener("click", this._onParagraphClick, { capture: !0 }), document.body.removeEventListener("keydown", this._onParagraphKeydown, { capture: !0 }), document.querySelectorAll(".bw-simplify-focusable").forEach((e) => {
2095
+ e.removeAttribute("tabindex"), e.classList.remove("bw-simplify-focusable");
2096
+ }), document.body.classList.remove("bw-simplify-mode"), document.documentElement.style.removeProperty("--bw-simplify-cursor"), this._announce("Режим AI Упрощение текста выключен.");
2075
2097
  this.host.requestUpdate();
2076
2098
  }
2099
+ async _triggerSimplify(e, t, n) {
2100
+ let r = e.innerText?.trim();
2101
+ if (!r) return;
2102
+ document.querySelectorAll(".bw-ai-tooltip").forEach((e) => e.remove());
2103
+ let i = document.createElement("div");
2104
+ i.className = "bw-ai-tooltip bw-ai-tooltip-loading", i.tabIndex = -1, i.innerHTML = "\n <div class=\"bw-ai-tooltip-header\">\n <span>✨ AI Упрощение</span>\n <button class=\"bw-ai-tooltip-close\" aria-label=\"Закрыть\">✕</button>\n </div>\n <div class=\"bw-ai-tooltip-content\" role=\"status\" aria-live=\"polite\">\n Ожидаем ответ от ИИ...\n </div>\n ", document.body.appendChild(i), i.style.left = `${Math.max(10, t - 160)}px`, i.style.top = `${n + 20}px`;
2105
+ let a = e.style.outline, o = e.style.backgroundColor;
2106
+ e.style.outline = "2px dashed #a855f7", e.style.backgroundColor = "rgba(168, 85, 247, 0.05)", i.querySelector(".bw-ai-tooltip-close")?.addEventListener("click", () => {
2107
+ i.remove(), e.style.outline = a, e.style.backgroundColor = o;
2108
+ });
2109
+ try {
2110
+ let e = window.BariwebConfig?.clientId || "", t = await fetch(`${lt}/v1/widget/a11y/simplify`, {
2111
+ method: "POST",
2112
+ headers: {
2113
+ "Content-Type": "application/json",
2114
+ "X-Client-ID": e
2115
+ },
2116
+ body: JSON.stringify({ text: r })
2117
+ });
2118
+ if (t.ok) {
2119
+ let e = await t.json();
2120
+ if (e.text) i.classList.remove("bw-ai-tooltip-loading"), i.querySelector(".bw-ai-tooltip-content").innerHTML = e.text, i.focus();
2121
+ else throw Error("Empty response");
2122
+ } else throw Error("Server error");
2123
+ } catch (e) {
2124
+ console.error("BariWeb AI: Simplify failed", e), i.classList.remove("bw-ai-tooltip-loading"), i.querySelector(".bw-ai-tooltip-content").innerHTML = "<span style=\"color:#ef4444; font-size:13px;\">Ошибка создания упрощенного текста. Попробуйте еще раз.</span>", i.focus();
2125
+ }
2126
+ }
2077
2127
  }, dt = "bw-tts-enabled-v1", ft = class {
2078
2128
  constructor() {
2079
2129
  this.enabled = !0, this.enabled = this.loadEnabled();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bariweb-widget",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "main": "./dist/bariweb.iife.js",
6
6
  "module": "./dist/bariweb.js",