Solvaria Sidekick - AI CRM Co-Pilot

Enterprise AI co-pilot with ghost-to-cockpit interface, privacy blur, and titanium governance for CRM platforms

Size

35.9 KB

Version

5.7.1

Created

Jan 23, 2026

Updated

11 days ago

1// ==UserScript==
2// @name		Solvaria Sidekick - AI CRM Co-Pilot
3// @description		Enterprise AI co-pilot with ghost-to-cockpit interface, privacy blur, and titanium governance for CRM platforms
4// @version		5.7.1
5// @match		https://*.salesforce.com/*
6// @match		https://*.lightning.force.com/*
7// @match		https://*.zendesk.com/*
8// @match		https://*.robomonkey.io/*
9// @icon		https://robomonkey.io/favicon.ico
10// @grant		GM.getValue
11// @grant		GM.setValue
12// @grant		GM.xmlhttpRequest
13// ==/UserScript==
14(function() {
15    'use strict';
16
17    // ============================================================================
18    // SOLVARIA SIDEKICK - ENTERPRISE AI CRM CO-PILOT
19    // Version 5.7.0 - Ghost-to-Cockpit Architecture
20    // ============================================================================
21
22    console.log('🚀 Solvaria Sidekick v5.7 - Initializing...');
23
24    // ============================================================================
25    // CONFIGURATION & CONSTANTS
26    // ============================================================================
27
28    const CONFIG = {
29        BACKEND_URL: 'https://api.solvaria.io/v1/analyze', // Replace with actual backend
30        SSE_STREAM_URL: 'https://api.solvaria.io/v1/stream',
31        PRIORITY_THRESHOLD: 50,
32        SIDEBAR_WIDTH: 380,
33        ANIMATION_DURATION: 400,
34        GLOW_WIDTH: 2,
35        Z_INDEX_MAX: 2147483647,
36        COLORS: {
37            background: '#0A0A0B',
38            accent: '#4F46E5',
39            border: 'rgba(255, 255, 255, 0.1)',
40            text: '#FFFFFF',
41            textMuted: '#9CA3AF',
42            success: '#10B981',
43            warning: '#F59E0B',
44            danger: '#EF4444'
45        }
46    };
47
48    // ============================================================================
49    // STATE MANAGEMENT
50    // ============================================================================
51
52    const STATE = {
53        isExpanded: false,
54        priorityScore: 0,
55        currentAnalysis: null,
56        blockedButtons: new Set(),
57        shadowRoot: null,
58        glowElement: null,
59        sidebarElement: null
60    };
61
62    // ============================================================================
63    // UTILITY FUNCTIONS
64    // ============================================================================
65
66    function debounce(func, wait) {
67        let timeout;
68        return function executedFunction(...args) {
69            const later = () => {
70                clearTimeout(timeout);
71                func(...args);
72            };
73            clearTimeout(timeout);
74            timeout = setTimeout(later, wait);
75        };
76    }
77
78    function detectCRMPlatform() {
79        const hostname = window.location.hostname;
80        if (hostname.includes('salesforce') || hostname.includes('force.com')) {
81            return 'salesforce';
82        } else if (hostname.includes('zendesk')) {
83            return 'zendesk';
84        }
85        return 'unknown';
86    }
87
88    function getCRMSubmitButtons() {
89        const platform = detectCRMPlatform();
90        const selectors = {
91            salesforce: [
92                'button.slds-button_brand',
93                'button[type="submit"].slds-button',
94                'button[title*="Save"]',
95                'button[title*="Submit"]'
96            ],
97            zendesk: [
98                'button.c-btn--primary',
99                'button[type="submit"]',
100                'button[data-test-id="submit"]'
101            ],
102            unknown: ['button[type="submit"]', 'button.btn-primary']
103        };
104
105        const buttons = [];
106        (selectors[platform] || selectors.unknown).forEach(selector => {
107            buttons.push(...document.querySelectorAll(selector));
108        });
109        return buttons;
110    }
111
112    // ============================================================================
113    // SHADOW DOM ARCHITECTURE
114    // ============================================================================
115
116    function createShadowDOMContainer() {
117        console.log('🔒 Creating Shadow DOM container with maximum isolation...');
118
119        // Create host element
120        const host = document.createElement('div');
121        host.id = 'solvaria-sidekick-host';
122        host.style.cssText = `
123            position: fixed;
124            top: 0;
125            right: 0;
126            height: 100vh;
127            width: 0;
128            z-index: ${CONFIG.Z_INDEX_MAX};
129            pointer-events: none;
130        `;
131
132        // Attach shadow root with closed mode for maximum security
133        const shadowRoot = host.attachShadow({ mode: 'closed' });
134        STATE.shadowRoot = shadowRoot;
135
136        // Inject styles into shadow DOM
137        const styleSheet = document.createElement('style');
138        styleSheet.textContent = getShadowDOMStyles();
139        shadowRoot.appendChild(styleSheet);
140
141        // Append to body
142        document.body.appendChild(host);
143
144        return { host, shadowRoot };
145    }
146
147    function getShadowDOMStyles() {
148        return `
149            * {
150                box-sizing: border-box;
151                margin: 0;
152                padding: 0;
153            }
154
155            :host {
156                all: initial;
157                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
158            }
159
160            /* GLOW TRIGGER */
161            .solvaria-glow {
162                position: fixed;
163                top: 0;
164                right: 0;
165                width: ${CONFIG.GLOW_WIDTH}px;
166                height: 100vh;
167                background: linear-gradient(180deg, ${CONFIG.COLORS.accent}, #7C3AED);
168                cursor: pointer;
169                pointer-events: auto;
170                animation: pulse 2s ease-in-out infinite;
171                transition: width 0.3s ease;
172            }
173
174            .solvaria-glow:hover {
175                width: 4px;
176            }
177
178            @keyframes pulse {
179                0%, 100% { opacity: 0.6; box-shadow: 0 0 10px ${CONFIG.COLORS.accent}; }
180                50% { opacity: 1; box-shadow: 0 0 20px ${CONFIG.COLORS.accent}, 0 0 40px ${CONFIG.COLORS.accent}; }
181            }
182
183            /* SIDEBAR COCKPIT */
184            .solvaria-sidebar {
185                position: fixed;
186                top: 0;
187                right: 0;
188                width: ${CONFIG.SIDEBAR_WIDTH}px;
189                height: 100vh;
190                background: ${CONFIG.COLORS.background};
191                border-left: 1px solid ${CONFIG.COLORS.border};
192                backdrop-filter: blur(20px);
193                display: flex;
194                flex-direction: column;
195                pointer-events: auto;
196                transform: translateX(100%);
197                transition: transform ${CONFIG.ANIMATION_DURATION}ms cubic-bezier(0.4, 0, 0.2, 1);
198                overflow: hidden;
199            }
200
201            .solvaria-sidebar.expanded {
202                transform: translateX(0);
203            }
204
205            /* HEADER */
206            .solvaria-header {
207                padding: 20px;
208                border-bottom: 1px solid ${CONFIG.COLORS.border};
209                display: flex;
210                align-items: center;
211                justify-content: space-between;
212            }
213
214            .solvaria-logo {
215                display: flex;
216                align-items: center;
217                gap: 10px;
218            }
219
220            .solvaria-logo-icon {
221                width: 32px;
222                height: 32px;
223                background: linear-gradient(135deg, ${CONFIG.COLORS.accent}, #7C3AED);
224                border-radius: 8px;
225                display: flex;
226                align-items: center;
227                justify-content: center;
228                font-size: 18px;
229            }
230
231            .solvaria-logo-text {
232                font-size: 16px;
233                font-weight: 600;
234                color: ${CONFIG.COLORS.text};
235            }
236
237            .solvaria-close-btn {
238                background: transparent;
239                border: none;
240                color: ${CONFIG.COLORS.textMuted};
241                cursor: pointer;
242                font-size: 20px;
243                padding: 5px;
244                transition: color 0.2s;
245            }
246
247            .solvaria-close-btn:hover {
248                color: ${CONFIG.COLORS.text};
249            }
250
251            /* CONTENT AREA */
252            .solvaria-content {
253                flex: 1;
254                overflow-y: auto;
255                padding: 20px;
256            }
257
258            .solvaria-content::-webkit-scrollbar {
259                width: 6px;
260            }
261
262            .solvaria-content::-webkit-scrollbar-track {
263                background: transparent;
264            }
265
266            .solvaria-content::-webkit-scrollbar-thumb {
267                background: ${CONFIG.COLORS.border};
268                border-radius: 3px;
269            }
270
271            /* ANALYSIS CARD */
272            .analysis-card {
273                background: rgba(255, 255, 255, 0.03);
274                border: 1px solid ${CONFIG.COLORS.border};
275                border-radius: 12px;
276                padding: 16px;
277                margin-bottom: 16px;
278                transition: all 0.3s ease;
279            }
280
281            .analysis-card:hover {
282                background: rgba(255, 255, 255, 0.05);
283                border-color: ${CONFIG.COLORS.accent};
284            }
285
286            .card-header {
287                display: flex;
288                align-items: center;
289                justify-content: space-between;
290                margin-bottom: 12px;
291            }
292
293            .card-title {
294                font-size: 14px;
295                font-weight: 600;
296                color: ${CONFIG.COLORS.text};
297            }
298
299            .priority-badge {
300                padding: 4px 8px;
301                border-radius: 6px;
302                font-size: 11px;
303                font-weight: 600;
304                text-transform: uppercase;
305            }
306
307            .priority-high {
308                background: rgba(239, 68, 68, 0.2);
309                color: ${CONFIG.COLORS.danger};
310            }
311
312            .priority-medium {
313                background: rgba(245, 158, 11, 0.2);
314                color: ${CONFIG.COLORS.warning};
315            }
316
317            .priority-low {
318                background: rgba(16, 185, 129, 0.2);
319                color: ${CONFIG.COLORS.success};
320            }
321
322            .card-content {
323                font-size: 13px;
324                color: ${CONFIG.COLORS.textMuted};
325                line-height: 1.6;
326            }
327
328            /* PRIVACY BLUR */
329            .sensitive-data {
330                filter: blur(5px);
331                transition: filter 0.3s ease;
332                cursor: pointer;
333                display: inline-block;
334                padding: 2px 6px;
335                background: rgba(79, 70, 229, 0.1);
336                border-radius: 4px;
337            }
338
339            .sensitive-data:hover {
340                filter: blur(0);
341            }
342
343            /* TITANIUM GOVERNANCE ALERT */
344            .governance-alert {
345                background: linear-gradient(135deg, rgba(239, 68, 68, 0.1), rgba(220, 38, 38, 0.1));
346                border: 2px solid ${CONFIG.COLORS.danger};
347                border-radius: 12px;
348                padding: 16px;
349                margin-bottom: 16px;
350                animation: alertPulse 2s ease-in-out infinite;
351            }
352
353            @keyframes alertPulse {
354                0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
355                50% { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); }
356            }
357
358            .governance-alert-title {
359                display: flex;
360                align-items: center;
361                gap: 8px;
362                font-size: 14px;
363                font-weight: 700;
364                color: ${CONFIG.COLORS.danger};
365                margin-bottom: 8px;
366            }
367
368            .governance-alert-message {
369                font-size: 13px;
370                color: ${CONFIG.COLORS.text};
371                line-height: 1.5;
372            }
373
374            /* ACTION BUTTONS */
375            .action-button {
376                width: 100%;
377                padding: 12px;
378                background: ${CONFIG.COLORS.accent};
379                color: ${CONFIG.COLORS.text};
380                border: none;
381                border-radius: 8px;
382                font-size: 14px;
383                font-weight: 600;
384                cursor: pointer;
385                transition: all 0.2s;
386                margin-top: 12px;
387            }
388
389            .action-button:hover {
390                background: #4338CA;
391                transform: translateY(-1px);
392                box-shadow: 0 4px 12px rgba(79, 70, 229, 0.4);
393            }
394
395            .action-button:active {
396                transform: translateY(0);
397            }
398
399            .action-button.secondary {
400                background: rgba(255, 255, 255, 0.05);
401                border: 1px solid ${CONFIG.COLORS.border};
402            }
403
404            .action-button.secondary:hover {
405                background: rgba(255, 255, 255, 0.1);
406            }
407
408            /* STREAMING RESPONSE */
409            .streaming-response {
410                background: rgba(79, 70, 229, 0.05);
411                border: 1px solid ${CONFIG.COLORS.accent};
412                border-radius: 8px;
413                padding: 12px;
414                font-size: 13px;
415                color: ${CONFIG.COLORS.text};
416                line-height: 1.6;
417                font-family: 'SF Mono', Monaco, monospace;
418                white-space: pre-wrap;
419                word-wrap: break-word;
420            }
421
422            .typing-cursor {
423                display: inline-block;
424                width: 2px;
425                height: 14px;
426                background: ${CONFIG.COLORS.accent};
427                margin-left: 2px;
428                animation: blink 1s step-end infinite;
429            }
430
431            @keyframes blink {
432                50% { opacity: 0; }
433            }
434
435            /* FOOTER ROI */
436            .solvaria-footer {
437                padding: 16px 20px;
438                border-top: 1px solid ${CONFIG.COLORS.border};
439                background: rgba(79, 70, 229, 0.05);
440            }
441
442            .roi-display {
443                display: flex;
444                align-items: center;
445                justify-content: space-between;
446            }
447
448            .roi-label {
449                font-size: 12px;
450                color: ${CONFIG.COLORS.textMuted};
451                text-transform: uppercase;
452                letter-spacing: 0.5px;
453            }
454
455            .roi-value {
456                font-size: 20px;
457                font-weight: 700;
458                color: ${CONFIG.COLORS.success};
459            }
460
461            /* LOADING STATE */
462            .loading-spinner {
463                display: inline-block;
464                width: 16px;
465                height: 16px;
466                border: 2px solid ${CONFIG.COLORS.border};
467                border-top-color: ${CONFIG.COLORS.accent};
468                border-radius: 50%;
469                animation: spin 0.8s linear infinite;
470            }
471
472            @keyframes spin {
473                to { transform: rotate(360deg); }
474            }
475        `;
476    }
477
478    // ============================================================================
479    // UI CONSTRUCTION
480    // ============================================================================
481
482    function buildSidebarUI() {
483        console.log('🎨 Building Sidebar UI...');
484
485        const sidebar = document.createElement('div');
486        sidebar.className = 'solvaria-sidebar';
487        sidebar.innerHTML = `
488            <div class="solvaria-header">
489                <div class="solvaria-logo">
490                    <div class="solvaria-logo-icon"></div>
491                    <div class="solvaria-logo-text">Solvaria Sidekick</div>
492                </div>
493                <button class="solvaria-close-btn" id="solvaria-close"></button>
494            </div>
495            <div class="solvaria-content" id="solvaria-content">
496                <div class="analysis-card">
497                    <div class="card-header">
498                        <div class="card-title">🔍 Analyzing CRM Context...</div>
499                    </div>
500                    <div class="card-content">
501                        <div class="loading-spinner"></div> Connecting to Solvaria AI...
502                    </div>
503                </div>
504            </div>
505            <div class="solvaria-footer">
506                <div class="roi-display">
507                    <div class="roi-label">Estimated Time Saved</div>
508                    <div class="roi-value">14 min</div>
509                </div>
510            </div>
511        `;
512
513        STATE.sidebarElement = sidebar;
514        return sidebar;
515    }
516
517    function buildGlowTrigger() {
518        console.log('✨ Building Glow Trigger...');
519
520        const glow = document.createElement('div');
521        glow.className = 'solvaria-glow';
522        glow.style.display = 'none';
523        glow.title = 'Click to open Solvaria Sidekick';
524
525        STATE.glowElement = glow;
526        return glow;
527    }
528
529    // ============================================================================
530    // GHOST-TO-COCKPIT BEHAVIOR
531    // ============================================================================
532
533    function showGlowTrigger(priorityScore) {
534        if (priorityScore > CONFIG.PRIORITY_THRESHOLD && STATE.glowElement) {
535            console.log(`🌟 Priority score ${priorityScore} > ${CONFIG.PRIORITY_THRESHOLD} - Showing glow trigger`);
536            STATE.glowElement.style.display = 'block';
537        }
538    }
539
540    function expandSidebar() {
541        if (STATE.isExpanded) return;
542
543        console.log('🚀 Expanding Sidebar - Ghost to Cockpit transition...');
544        STATE.isExpanded = true;
545
546        // Hide glow trigger
547        if (STATE.glowElement) {
548            STATE.glowElement.style.display = 'none';
549        }
550
551        // Apply margin to HTML element for smooth layout shift
552        const htmlElement = document.documentElement;
553        htmlElement.style.transition = `margin-right ${CONFIG.ANIMATION_DURATION}ms cubic-bezier(0.4, 0, 0.2, 1)`;
554        htmlElement.style.marginRight = `${CONFIG.SIDEBAR_WIDTH}px`;
555
556        // Expand sidebar
557        if (STATE.sidebarElement) {
558            STATE.sidebarElement.classList.add('expanded');
559        }
560
561        // Trigger analysis
562        setTimeout(() => performCRMAnalysis(), 300);
563    }
564
565    function collapseSidebar() {
566        if (!STATE.isExpanded) return;
567
568        console.log('📦 Collapsing Sidebar - Cockpit to Ghost transition...');
569        STATE.isExpanded = false;
570
571        // Remove margin from HTML element
572        const htmlElement = document.documentElement;
573        htmlElement.style.marginRight = '0';
574
575        // Collapse sidebar
576        if (STATE.sidebarElement) {
577            STATE.sidebarElement.classList.remove('expanded');
578        }
579
580        // Show glow trigger again if priority is high
581        if (STATE.priorityScore > CONFIG.PRIORITY_THRESHOLD && STATE.glowElement) {
582            setTimeout(() => {
583                STATE.glowElement.style.display = 'block';
584            }, CONFIG.ANIMATION_DURATION);
585        }
586    }
587
588    // ============================================================================
589    // CRM ANALYSIS ENGINE
590    // ============================================================================
591
592    async function performCRMAnalysis() {
593        console.log('🔬 Performing CRM Analysis...');
594
595        const contentArea = STATE.shadowRoot.getElementById('solvaria-content');
596        if (!contentArea) return;
597
598        try {
599            // Extract CRM context
600            const crmContext = extractCRMContext();
601            console.log('📊 CRM Context extracted:', crmContext);
602
603            // Simulate backend call (replace with actual API)
604            const analysisResult = await simulateBackendAnalysis(crmContext);
605
606            // Update UI with results
607            displayAnalysisResults(analysisResult);
608
609            // Apply governance if needed
610            if (analysisResult.blockSubmit) {
611                applyTitaniumGovernance(analysisResult.blockReason);
612            }
613
614        } catch (error) {
615            console.error('❌ Analysis failed:', error);
616            contentArea.innerHTML = `
617                <div class="analysis-card">
618                    <div class="card-header">
619                        <div class="card-title">⚠️ Analysis Error</div>
620                    </div>
621                    <div class="card-content">
622                        Unable to connect to Solvaria backend. Please check your connection.
623                    </div>
624                </div>
625            `;
626        }
627    }
628
629    function extractCRMContext() {
630        const platform = detectCRMPlatform();
631        const context = {
632            platform: platform,
633            url: window.location.href,
634            title: document.title,
635            timestamp: new Date().toISOString(),
636            fields: []
637        };
638
639        // Extract form fields
640        const inputs = document.querySelectorAll('input, textarea, select');
641        inputs.forEach(input => {
642            if (input.value && input.name) {
643                context.fields.push({
644                    name: input.name,
645                    value: input.value,
646                    type: input.type || input.tagName.toLowerCase()
647                });
648            }
649        });
650
651        return context;
652    }
653
654    async function simulateBackendAnalysis(context) {
655        // Simulate API delay
656        await new Promise(resolve => setTimeout(resolve, 1500));
657
658        // Mock response - replace with actual GM.xmlhttpRequest call
659        const priorityScore = Math.floor(Math.random() * 100);
660        STATE.priorityScore = priorityScore;
661
662        return {
663            priorityScore: priorityScore,
664            insights: [
665                {
666                    title: 'Customer Risk Assessment',
667                    content: 'Customer shows high engagement score. Contact information: <span class="sensitive-data">john.doe@example.com</span>',
668                    priority: priorityScore > 70 ? 'high' : priorityScore > 40 ? 'medium' : 'low'
669                },
670                {
671                    title: 'Recommended Actions',
672                    content: 'Suggest premium tier upgrade. Estimated value: <span class="sensitive-data">$2,450/month</span>',
673                    priority: 'medium'
674                },
675                {
676                    title: 'Compliance Check',
677                    content: 'All GDPR requirements satisfied. Data retention policy compliant.',
678                    priority: 'low'
679                }
680            ],
681            blockSubmit: priorityScore > 80,
682            blockReason: 'Critical procedure verification required: Gas pressure check not completed',
683            suggestedResponse: 'Based on the customer profile and interaction history, I recommend...',
684            estimatedTimeSaved: 14
685        };
686    }
687
688    function displayAnalysisResults(results) {
689        const contentArea = STATE.shadowRoot.getElementById('solvaria-content');
690        if (!contentArea) return;
691
692        let html = '';
693
694        // Governance alert if blocking
695        if (results.blockSubmit) {
696            html += `
697                <div class="governance-alert">
698                    <div class="governance-alert-title">
699                        🔒 TITANIUM GOVERNANCE ACTIVE
700                    </div>
701                    <div class="governance-alert-message">
702                        ${results.blockReason}
703                    </div>
704                    <button class="action-button" onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('solvaria-unlock'))">
705                        ✓ Verify & Unlock
706                    </button>
707                </div>
708            `;
709        }
710
711        // Insights cards
712        results.insights.forEach(insight => {
713            html += `
714                <div class="analysis-card">
715                    <div class="card-header">
716                        <div class="card-title">${insight.title}</div>
717                        <div class="priority-badge priority-${insight.priority}">
718                            ${insight.priority}
719                        </div>
720                    </div>
721                    <div class="card-content">${insight.content}</div>
722                </div>
723            `;
724        });
725
726        // AI Suggested Response
727        if (results.suggestedResponse) {
728            html += `
729                <div class="analysis-card">
730                    <div class="card-header">
731                        <div class="card-title">🤖 AI Suggested Response</div>
732                    </div>
733                    <div class="card-content">
734                        <div class="streaming-response" id="streaming-response"></div>
735                    </div>
736                    <button class="action-button" id="inject-response">
737                        ⚡ Inject Response
738                    </button>
739                    <button class="action-button secondary" id="copy-response">
740                        📋 Copy to Clipboard
741                    </button>
742                </div>
743            `;
744        }
745
746        contentArea.innerHTML = html;
747
748        // Start streaming animation
749        if (results.suggestedResponse) {
750            streamTextAnimation(results.suggestedResponse);
751        }
752
753        // Attach event listeners
754        attachEventListeners();
755    }
756
757    function streamTextAnimation(text) {
758        const streamingElement = STATE.shadowRoot.getElementById('streaming-response');
759        if (!streamingElement) return;
760
761        let index = 0;
762        const words = text.split(' ');
763
764        streamingElement.innerHTML = '<span class="typing-cursor"></span>';
765
766        const interval = setInterval(() => {
767            if (index < words.length) {
768                const cursor = streamingElement.querySelector('.typing-cursor');
769                const textNode = document.createTextNode(words[index] + ' ');
770                streamingElement.insertBefore(textNode, cursor);
771                index++;
772            } else {
773                clearInterval(interval);
774                const cursor = streamingElement.querySelector('.typing-cursor');
775                if (cursor) cursor.remove();
776            }
777        }, 80);
778    }
779
780    // ============================================================================
781    // TITANIUM GOVERNANCE (BLOCKING SYSTEM)
782    // ============================================================================
783
784    function applyTitaniumGovernance(reason) {
785        console.log('🔒 Applying Titanium Governance - Blocking submit buttons');
786
787        const buttons = getCRMSubmitButtons();
788        buttons.forEach(button => {
789            if (!STATE.blockedButtons.has(button)) {
790                // Store original styles
791                button.dataset.originalPointerEvents = button.style.pointerEvents || '';
792                button.dataset.originalOpacity = button.style.opacity || '';
793                button.dataset.originalFilter = button.style.filter || '';
794
795                // Apply blocking styles
796                button.style.pointerEvents = 'none';
797                button.style.opacity = '0.5';
798                button.style.filter = 'grayscale(1)';
799                button.style.transition = 'all 0.3s ease';
800
801                STATE.blockedButtons.add(button);
802                console.log('🚫 Blocked button:', button);
803            }
804        });
805    }
806
807    function removeTitaniumGovernance() {
808        console.log('🔓 Removing Titanium Governance - Unlocking submit buttons');
809
810        STATE.blockedButtons.forEach(button => {
811            // Restore original styles
812            button.style.pointerEvents = button.dataset.originalPointerEvents || '';
813            button.style.opacity = button.dataset.originalOpacity || '';
814            button.style.filter = button.dataset.originalFilter || '';
815
816            delete button.dataset.originalPointerEvents;
817            delete button.dataset.originalOpacity;
818            delete button.dataset.originalFilter;
819
820            console.log('✅ Unlocked button:', button);
821        });
822
823        STATE.blockedButtons.clear();
824    }
825
826    // ============================================================================
827    // INJECTION ENGINE
828    // ============================================================================
829
830    async function injectResponseToField() {
831        console.log('💉 Injecting AI response to CRM field...');
832
833        const streamingElement = STATE.shadowRoot.getElementById('streaming-response');
834        if (!streamingElement) return;
835
836        const responseText = streamingElement.textContent.trim();
837
838        // Find target field (textarea or rich text editor)
839        const targetField = findTargetInputField();
840
841        if (targetField) {
842            try {
843                // Focus the field
844                targetField.focus();
845
846                // Try execCommand first (works with rich text editors)
847                if (document.execCommand) {
848                    targetField.select();
849                    const success = document.execCommand('insertText', false, responseText);
850                    
851                    if (success) {
852                        console.log('✅ Injected using execCommand');
853                        // Dispatch input event
854                        targetField.dispatchEvent(new Event('input', { bubbles: true }));
855                        targetField.dispatchEvent(new Event('change', { bubbles: true }));
856                        showNotification('✓ Response injected successfully', 'success');
857                        return;
858                    }
859                }
860
861                // Fallback: direct value assignment
862                targetField.value = responseText;
863                targetField.dispatchEvent(new Event('input', { bubbles: true }));
864                targetField.dispatchEvent(new Event('change', { bubbles: true }));
865                console.log('✅ Injected using direct assignment');
866                showNotification('✓ Response injected successfully', 'success');
867
868            } catch (error) {
869                console.error('❌ Injection failed:', error);
870                showNotification('⚠ Injection failed - Use copy button', 'warning');
871            }
872        } else {
873            console.warn('⚠ No target field found');
874            showNotification('⚠ No input field found - Use copy button', 'warning');
875        }
876    }
877
878    function findTargetInputField() {
879        // Try to find the most relevant input field
880        const selectors = [
881            'textarea[name*="comment"]',
882            'textarea[name*="description"]',
883            'textarea[name*="notes"]',
884            'textarea[name*="message"]',
885            'div[contenteditable="true"]',
886            'textarea:focus',
887            'textarea'
888        ];
889
890        for (const selector of selectors) {
891            const field = document.querySelector(selector);
892            if (field && field.offsetParent !== null) { // Check if visible
893                return field;
894            }
895        }
896
897        return null;
898    }
899
900    async function copyResponseToClipboard() {
901        const streamingElement = STATE.shadowRoot.getElementById('streaming-response');
902        if (!streamingElement) return;
903
904        const responseText = streamingElement.textContent.trim();
905
906        try {
907            await GM.setClipboard(responseText);
908            console.log('📋 Copied to clipboard');
909            showNotification('✓ Copied to clipboard', 'success');
910        } catch (error) {
911            console.error('❌ Copy failed:', error);
912            showNotification('⚠ Copy failed', 'warning');
913        }
914    }
915
916    function showNotification(message, type = 'info') {
917        const notification = document.createElement('div');
918        notification.style.cssText = `
919            position: fixed;
920            top: 20px;
921            right: ${STATE.isExpanded ? CONFIG.SIDEBAR_WIDTH + 20 : 20}px;
922            background: ${type === 'success' ? CONFIG.COLORS.success : type === 'warning' ? CONFIG.COLORS.warning : CONFIG.COLORS.accent};
923            color: white;
924            padding: 12px 20px;
925            border-radius: 8px;
926            font-size: 14px;
927            font-weight: 600;
928            z-index: ${CONFIG.Z_INDEX_MAX + 1};
929            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
930            animation: slideIn 0.3s ease;
931        `;
932        notification.textContent = message;
933
934        document.body.appendChild(notification);
935
936        setTimeout(() => {
937            notification.style.animation = 'slideOut 0.3s ease';
938            setTimeout(() => notification.remove(), 300);
939        }, 3000);
940    }
941
942    // ============================================================================
943    // EVENT HANDLERS
944    // ============================================================================
945
946    function attachEventListeners() {
947        // Close button
948        const closeBtn = STATE.shadowRoot.getElementById('solvaria-close');
949        if (closeBtn) {
950            closeBtn.addEventListener('click', collapseSidebar);
951        }
952
953        // Inject button
954        const injectBtn = STATE.shadowRoot.getElementById('inject-response');
955        if (injectBtn) {
956            injectBtn.addEventListener('click', injectResponseToField);
957        }
958
959        // Copy button
960        const copyBtn = STATE.shadowRoot.getElementById('copy-response');
961        if (copyBtn) {
962            copyBtn.addEventListener('click', copyResponseToClipboard);
963        }
964
965        // Unlock governance button (via custom event)
966        const host = STATE.shadowRoot.host;
967        host.addEventListener('solvaria-unlock', () => {
968            removeTitaniumGovernance();
969            showNotification('✓ Governance unlocked', 'success');
970            
971            // Update UI to remove alert
972            const alert = STATE.shadowRoot.querySelector('.governance-alert');
973            if (alert) {
974                alert.style.animation = 'slideOut 0.3s ease';
975                setTimeout(() => alert.remove(), 300);
976            }
977        });
978    }
979
980    // ============================================================================
981    // INITIALIZATION
982    // ============================================================================
983
984    async function init() {
985        console.log('🎯 Initializing Solvaria Sidekick...');
986
987        // Wait for body to be ready
988        if (!document.body) {
989            console.log('⏳ Waiting for document.body...');
990            await new Promise(resolve => {
991                if (document.readyState === 'loading') {
992                    document.addEventListener('DOMContentLoaded', resolve);
993                } else {
994                    setTimeout(resolve, 100);
995                }
996            });
997        }
998
999        // Create Shadow DOM container
1000        const { host, shadowRoot } = createShadowDOMContainer();
1001
1002        // Build UI components
1003        const glow = buildGlowTrigger();
1004        const sidebar = buildSidebarUI();
1005
1006        // Append to shadow root
1007        shadowRoot.appendChild(glow);
1008        shadowRoot.appendChild(sidebar);
1009
1010        // Attach glow click handler
1011        glow.addEventListener('click', expandSidebar);
1012
1013        // Monitor CRM changes for auto-trigger
1014        observeCRMChanges();
1015
1016        // Simulate priority check (replace with actual backend call)
1017        setTimeout(() => {
1018            const mockPriorityScore = Math.floor(Math.random() * 100);
1019            STATE.priorityScore = mockPriorityScore;
1020            showGlowTrigger(mockPriorityScore);
1021        }, 2000);
1022
1023        console.log('✅ Solvaria Sidekick initialized successfully');
1024    }
1025
1026    function observeCRMChanges() {
1027        // Debounced observer for CRM form changes
1028        const debouncedAnalysis = debounce(() => {
1029            if (STATE.isExpanded) {
1030                console.log('🔄 CRM context changed - Re-analyzing...');
1031                performCRMAnalysis();
1032            }
1033        }, 1000);
1034
1035        const observer = new MutationObserver(debouncedAnalysis);
1036
1037        observer.observe(document.body, {
1038            childList: true,
1039            subtree: true,
1040            attributes: false
1041        });
1042
1043        console.log('👀 Observing CRM changes...');
1044    }
1045
1046    // ============================================================================
1047    // START APPLICATION
1048    // ============================================================================
1049
1050    // Initialize when DOM is ready
1051    if (document.readyState === 'loading') {
1052        document.addEventListener('DOMContentLoaded', init);
1053    } else {
1054        init();
1055    }
1056
1057})();
Solvaria Sidekick - AI CRM Co-Pilot | Robomonkey