orquesta-embed 0.1.0

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 ADDED
@@ -0,0 +1,97 @@
1
+ # Orquesta Embed SDK
2
+
3
+ Embed Orquesta AI-powered development UI into any production website.
4
+
5
+ ## Features
6
+
7
+ - 🎯 **Element Selection** - Right-click any element to prompt about it
8
+ - 📋 **Console Capture** - Auto-include console logs in prompts
9
+ - 🌐 **Network Capture** - Include network errors for debugging
10
+ - 📊 **Timeline** - View prompt history and status
11
+ - 🚀 **Deployments** - See current deployment status
12
+ - 🎨 **Customizable** - Position, theme, features
13
+
14
+ ## Installation
15
+
16
+ ### React
17
+
18
+ ```bash
19
+ npm install orquesta-embed
20
+ ```
21
+
22
+ ```tsx
23
+ import { OrquestaEmbed } from 'orquesta-embed'
24
+ import 'orquesta-embed/styles.css'
25
+
26
+ function App() {
27
+ return (
28
+ <>
29
+ <YourApp />
30
+ <OrquestaEmbed
31
+ token="oek_xxxxx"
32
+ position="bottom-right"
33
+ captureConsole={true}
34
+ captureNetwork={true}
35
+ onReady={() => console.log('Orquesta ready!')}
36
+ />
37
+ </>
38
+ )
39
+ }
40
+ ```
41
+
42
+ ### Vanilla JavaScript
43
+
44
+ ```html
45
+ <script src="https://cdn.orquesta.live/embed/v1/orquesta.min.js"></script>
46
+ <script>
47
+ const widget = Orquesta.init({
48
+ token: 'oek_xxxxx',
49
+ position: 'bottom-right',
50
+ captureConsole: true,
51
+ captureNetwork: true,
52
+ onReady: () => console.log('Orquesta ready!')
53
+ });
54
+
55
+ // Programmatic API
56
+ widget.open();
57
+ widget.close();
58
+ widget.toggle();
59
+ widget.startElementSelection();
60
+ widget.submitPrompt('Fix this bug', { includeConsole: true });
61
+ widget.destroy();
62
+ </script>
63
+ ```
64
+
65
+ ## Configuration
66
+
67
+ | Option | Type | Default | Description |
68
+ |--------|------|---------|-------------|
69
+ | `token` | `string` | *required* | Your embed token (oek_xxx) |
70
+ | `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | `'bottom-right'` | Panel position |
71
+ | `defaultOpen` | `boolean` | `false` | Start with panel open |
72
+ | `theme` | `'dark' \| 'light' \| 'auto'` | `'dark'` | Color theme |
73
+ | `features` | `Feature[]` | All features | Enabled features |
74
+ | `captureConsole` | `boolean` | `true` | Capture console.log/error |
75
+ | `captureNetwork` | `boolean` | `true` | Capture fetch/XHR errors |
76
+ | `hotkey` | `string` | `'ctrl+shift+o'` | Keyboard shortcut to toggle |
77
+ | `onReady` | `() => void` | - | Called when connected |
78
+ | `onPromptSubmit` | `(promptId: string) => void` | - | Called when prompt submitted |
79
+ | `onError` | `(error: Error) => void` | - | Called on errors |
80
+
81
+ ## Getting Your Token
82
+
83
+ 1. Go to your project settings on [orquesta.live](https://orquesta.live)
84
+ 2. Navigate to **Settings > Embed**
85
+ 3. Click **Generate Token**
86
+ 4. (Optional) Add domain restrictions
87
+
88
+ ## Security
89
+
90
+ - Embed tokens can be restricted to specific domains
91
+ - Tokens only allow submitting prompts and viewing data
92
+ - No access to credentials or sensitive settings
93
+ - Rate limited to prevent abuse
94
+
95
+ ## License
96
+
97
+ MIT
@@ -0,0 +1,7 @@
1
+ import type { Deployment } from '../core/config';
2
+ interface DeploymentsProps {
3
+ deployments: Deployment[];
4
+ currentDeployment: Deployment | null;
5
+ }
6
+ export declare function Deployments({ deployments, currentDeployment }: DeploymentsProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,6 @@
1
+ interface ElementInspectorProps {
2
+ isActive: boolean;
3
+ onCancel: () => void;
4
+ }
5
+ export declare function ElementInspector({ isActive, onCancel }: ElementInspectorProps): import("react/jsx-runtime").JSX.Element | null;
6
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { EmbedState } from '../core/state';
2
+ import type { Position } from '../core/config';
3
+ interface EmbedPanelProps {
4
+ state: EmbedState;
5
+ position: Position;
6
+ onClose: () => void;
7
+ onMinimize: () => void;
8
+ onSubmitPrompt: (content: string) => void;
9
+ onSelectElement: () => void;
10
+ onClearElement: () => void;
11
+ onToggleConsole: () => void;
12
+ onToggleNetwork: () => void;
13
+ onTabChange: (tab: EmbedState['activeTab']) => void;
14
+ }
15
+ export declare function EmbedPanel({ state, position, onClose, onMinimize, onSubmitPrompt, onSelectElement, onClearElement, onToggleConsole, onToggleNetwork, onTabChange }: EmbedPanelProps): import("react/jsx-runtime").JSX.Element;
16
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { OutputLine } from '../core/state';
2
+ interface LogStreamProps {
3
+ lines: OutputLine[];
4
+ isRunning: boolean;
5
+ }
6
+ export declare function LogStream({ lines, isRunning }: LogStreamProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { OrquestaEmbedConfig } from '../core/config';
3
+ interface OrquestaEmbedProps extends OrquestaEmbedConfig {
4
+ children?: React.ReactNode;
5
+ }
6
+ export declare function OrquestaEmbed(props: OrquestaEmbedProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { ElementContext } from '../core/config';
2
+ interface PromptInputProps {
3
+ onSubmit: (content: string) => void;
4
+ isSubmitting: boolean;
5
+ selectedElement: ElementContext | null;
6
+ includeConsole: boolean;
7
+ includeNetwork: boolean;
8
+ onToggleConsole: () => void;
9
+ onToggleNetwork: () => void;
10
+ onSelectElement: () => void;
11
+ onClearElement: () => void;
12
+ agentOnline: boolean;
13
+ }
14
+ export declare function PromptInput({ onSubmit, isSubmitting, selectedElement, includeConsole, includeNetwork, onToggleConsole, onToggleNetwork, onSelectElement, onClearElement, agentOnline }: PromptInputProps): import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { Prompt } from '../core/config';
2
+ interface TimelineProps {
3
+ prompts: Prompt[];
4
+ currentPromptId?: string;
5
+ onSelectPrompt?: (prompt: Prompt) => void;
6
+ }
7
+ export declare function Timeline({ prompts, currentPromptId, onSelectPrompt }: TimelineProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ interface BadgeProps {
3
+ variant?: 'default' | 'success' | 'warning' | 'error' | 'info';
4
+ size?: 'sm' | 'md';
5
+ children: React.ReactNode;
6
+ className?: string;
7
+ }
8
+ export declare function Badge({ variant, size, children, className }: BadgeProps): import("react/jsx-runtime").JSX.Element;
9
+ interface StatusDotProps {
10
+ status: 'online' | 'offline' | 'pending' | 'running' | 'completed' | 'failed';
11
+ className?: string;
12
+ }
13
+ export declare function StatusDot({ status, className }: StatusDotProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
3
+ variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
4
+ size?: 'sm' | 'md' | 'lg';
5
+ loading?: boolean;
6
+ children: React.ReactNode;
7
+ }
8
+ export declare function Button({ variant, size, loading, disabled, className, children, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
3
+ label?: string;
4
+ error?: string;
5
+ }
6
+ export declare function Input({ label, error, className, ...props }: InputProps): import("react/jsx-runtime").JSX.Element;
7
+ interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
8
+ label?: string;
9
+ error?: string;
10
+ }
11
+ export declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
12
+ export {};
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ interface TabsProps {
3
+ defaultValue?: string;
4
+ value?: string;
5
+ onChange?: (value: string) => void;
6
+ children: React.ReactNode;
7
+ className?: string;
8
+ }
9
+ export declare function Tabs({ defaultValue, value, onChange, children, className }: TabsProps): import("react/jsx-runtime").JSX.Element;
10
+ interface TabsListProps {
11
+ children: React.ReactNode;
12
+ className?: string;
13
+ }
14
+ export declare function TabsList({ children, className }: TabsListProps): import("react/jsx-runtime").JSX.Element;
15
+ interface TabsTriggerProps {
16
+ value: string;
17
+ children: React.ReactNode;
18
+ className?: string;
19
+ }
20
+ export declare function TabsTrigger({ value, children, className }: TabsTriggerProps): import("react/jsx-runtime").JSX.Element;
21
+ interface TabsContentProps {
22
+ value: string;
23
+ children: React.ReactNode;
24
+ className?: string;
25
+ }
26
+ export declare function TabsContent({ value, children, className }: TabsContentProps): import("react/jsx-runtime").JSX.Element | null;
27
+ export {};
@@ -0,0 +1,4 @@
1
+ export { Button } from './Button';
2
+ export { Input, Textarea } from './Input';
3
+ export { Badge, StatusDot } from './Badge';
4
+ export { Tabs, TabsList, TabsTrigger, TabsContent } from './Tabs';
@@ -0,0 +1,40 @@
1
+ import type { OrquestaEmbedConfig, ElementContext } from './config';
2
+ import { StateManager } from './state';
3
+ import { ConsoleCapture } from './console-capture';
4
+ import { NetworkCapture } from './network-capture';
5
+ import { ElementSelector } from './element-selector';
6
+ export declare class OrquestaEmbedClient {
7
+ private config;
8
+ private supabase;
9
+ private channel;
10
+ private projectId;
11
+ private state;
12
+ private consoleCapture;
13
+ private networkCapture;
14
+ private elementSelector;
15
+ private hotkeyHandler;
16
+ constructor(config: OrquestaEmbedConfig);
17
+ connect(): Promise<void>;
18
+ disconnect(): void;
19
+ private setupHotkey;
20
+ private removeHotkey;
21
+ private handleOutput;
22
+ private handleComplete;
23
+ private handleError;
24
+ submitPrompt(content: string, options?: {
25
+ includeConsole?: boolean;
26
+ includeNetwork?: boolean;
27
+ elementContext?: ElementContext;
28
+ }): Promise<string>;
29
+ private loadTimeline;
30
+ private loadDeployments;
31
+ open(): void;
32
+ close(): void;
33
+ toggle(): void;
34
+ startElementSelection(): void;
35
+ getState(): ReturnType<StateManager['getState']>;
36
+ subscribe(listener: (state: ReturnType<StateManager['getState']>) => void): () => void;
37
+ getConsoleCapture(): ConsoleCapture;
38
+ getNetworkCapture(): NetworkCapture;
39
+ getElementSelector(): ElementSelector;
40
+ }
@@ -0,0 +1,87 @@
1
+ export type Position = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
2
+ export type Theme = 'dark' | 'light' | 'auto';
3
+ export type Feature = 'prompts' | 'timeline' | 'deployments' | 'elements' | 'captures';
4
+ export interface OrquestaEmbedConfig {
5
+ /** Embed token (oek_xxx) */
6
+ token: string;
7
+ /** Panel position on screen */
8
+ position?: Position;
9
+ /** Start with panel open */
10
+ defaultOpen?: boolean;
11
+ /** Color theme */
12
+ theme?: Theme;
13
+ /** Enabled features */
14
+ features?: Feature[];
15
+ /** Capture console.log/error */
16
+ captureConsole?: boolean;
17
+ /** Capture fetch/XHR errors */
18
+ captureNetwork?: boolean;
19
+ /** Keyboard shortcut to toggle panel */
20
+ hotkey?: string;
21
+ /** Callback when SDK is ready */
22
+ onReady?: () => void;
23
+ /** Callback when prompt is submitted */
24
+ onPromptSubmit?: (promptId: string) => void;
25
+ /** Callback on errors */
26
+ onError?: (error: Error) => void;
27
+ /** API base URL (defaults to https://orquesta.live) */
28
+ apiUrl?: string;
29
+ }
30
+ export declare const DEFAULT_CONFIG: Partial<OrquestaEmbedConfig>;
31
+ export interface ElementContext {
32
+ selector: string;
33
+ tag: string;
34
+ id?: string;
35
+ className?: string;
36
+ textContent?: string;
37
+ boundingRect?: DOMRect;
38
+ attributes?: Record<string, string>;
39
+ }
40
+ export interface ConsoleEntry {
41
+ timestamp: number;
42
+ level: 'log' | 'info' | 'warn' | 'error';
43
+ message: string;
44
+ args?: unknown[];
45
+ stack?: string;
46
+ }
47
+ export interface NetworkEntry {
48
+ timestamp: number;
49
+ method: string;
50
+ url: string;
51
+ status?: number;
52
+ duration?: number;
53
+ error?: string;
54
+ requestBody?: unknown;
55
+ responseBody?: unknown;
56
+ }
57
+ export interface Prompt {
58
+ id: string;
59
+ content: string;
60
+ status: 'pending' | 'running' | 'completed' | 'failed';
61
+ created_at: string;
62
+ completed_at?: string;
63
+ user_id: string;
64
+ source: string;
65
+ element_context?: ElementContext;
66
+ }
67
+ export interface Deployment {
68
+ id: string;
69
+ status: string;
70
+ commit_sha?: string;
71
+ commit_message?: string;
72
+ branch?: string;
73
+ created_at: string;
74
+ deployed_at?: string;
75
+ url?: string;
76
+ }
77
+ export interface ValidationResponse {
78
+ valid: boolean;
79
+ projectId: string;
80
+ supabaseUrl: string;
81
+ supabaseAnonKey: string;
82
+ channelName: string;
83
+ project?: {
84
+ name: string;
85
+ agent_online: boolean;
86
+ };
87
+ }
@@ -0,0 +1,19 @@
1
+ import type { ConsoleEntry } from './config';
2
+ export declare class ConsoleCapture {
3
+ private buffer;
4
+ private maxSize;
5
+ private originalConsole;
6
+ private errorHandler;
7
+ private rejectionHandler;
8
+ private listeners;
9
+ start(): void;
10
+ stop(): void;
11
+ private createEntry;
12
+ private addEntry;
13
+ getAll(): ConsoleEntry[];
14
+ getRecent(count?: number): ConsoleEntry[];
15
+ getErrors(): ConsoleEntry[];
16
+ clear(): void;
17
+ subscribe(listener: (entry: ConsoleEntry) => void): () => void;
18
+ formatForPrompt(entries?: ConsoleEntry[]): string;
19
+ }
@@ -0,0 +1,23 @@
1
+ import type { ElementContext } from './config';
2
+ export declare class ElementSelector {
3
+ private overlay;
4
+ private highlight;
5
+ private contextMenu;
6
+ private selectedElement;
7
+ private isActive;
8
+ private onSelect;
9
+ private onCancel;
10
+ activate(onSelect: (context: ElementContext) => void, onCancel?: () => void): void;
11
+ deactivate(): void;
12
+ private createOverlay;
13
+ private removeOverlay;
14
+ private addListeners;
15
+ private removeListeners;
16
+ private handleMouseMove;
17
+ private handleClick;
18
+ private handleContextMenu;
19
+ private handleKeyDown;
20
+ private showContextMenu;
21
+ getElementContext(el: HTMLElement): ElementContext;
22
+ private generateSelector;
23
+ }
@@ -0,0 +1,20 @@
1
+ import type { NetworkEntry } from './config';
2
+ export declare class NetworkCapture {
3
+ private buffer;
4
+ private maxSize;
5
+ private originalFetch;
6
+ private originalXHROpen;
7
+ private originalXHRSend;
8
+ private listeners;
9
+ start(): void;
10
+ stop(): void;
11
+ private patchFetch;
12
+ private patchXHR;
13
+ private addEntry;
14
+ getAll(): NetworkEntry[];
15
+ getRecent(count?: number): NetworkEntry[];
16
+ getErrors(): NetworkEntry[];
17
+ clear(): void;
18
+ subscribe(listener: (entry: NetworkEntry) => void): () => void;
19
+ formatForPrompt(entries?: NetworkEntry[]): string;
20
+ }
@@ -0,0 +1,59 @@
1
+ import type { Prompt, Deployment, ElementContext, ConsoleEntry, NetworkEntry } from './config';
2
+ export interface EmbedState {
3
+ isConnected: boolean;
4
+ isConnecting: boolean;
5
+ connectionError: string | null;
6
+ projectId: string | null;
7
+ projectName: string | null;
8
+ agentOnline: boolean;
9
+ isOpen: boolean;
10
+ activeTab: 'prompts' | 'timeline' | 'deployments';
11
+ isSelectingElement: boolean;
12
+ selectedElement: ElementContext | null;
13
+ currentPrompt: Prompt | null;
14
+ promptHistory: Prompt[];
15
+ isSubmitting: boolean;
16
+ outputLines: OutputLine[];
17
+ deployments: Deployment[];
18
+ currentDeployment: Deployment | null;
19
+ consoleLogs: ConsoleEntry[];
20
+ networkLogs: NetworkEntry[];
21
+ includeConsole: boolean;
22
+ includeNetwork: boolean;
23
+ }
24
+ export interface OutputLine {
25
+ id: string;
26
+ timestamp: number;
27
+ type: 'stdout' | 'stderr' | 'tool' | 'thinking' | 'system';
28
+ content: string;
29
+ details?: Record<string, unknown>;
30
+ }
31
+ export type StateListener = (state: EmbedState) => void;
32
+ export declare class StateManager {
33
+ private state;
34
+ private listeners;
35
+ constructor();
36
+ private getInitialState;
37
+ getState(): EmbedState;
38
+ setState(partial: Partial<EmbedState>): void;
39
+ subscribe(listener: StateListener): () => void;
40
+ private notify;
41
+ setConnected(projectId: string, projectName: string, agentOnline: boolean): void;
42
+ setConnectionError(error: string): void;
43
+ setOpen(isOpen: boolean): void;
44
+ toggle(): void;
45
+ setActiveTab(tab: EmbedState['activeTab']): void;
46
+ setCurrentPrompt(prompt: Prompt | null): void;
47
+ updatePrompt(promptId: string, updates: Partial<Prompt>): void;
48
+ addOutputLine(line: Omit<OutputLine, 'id'>): void;
49
+ clearOutput(): void;
50
+ setSelectedElement(element: ElementContext | null): void;
51
+ startElementSelection(): void;
52
+ cancelElementSelection(): void;
53
+ setDeployments(deployments: Deployment[]): void;
54
+ addConsoleLogs(logs: ConsoleEntry[]): void;
55
+ addNetworkLogs(logs: NetworkEntry[]): void;
56
+ toggleIncludeConsole(): void;
57
+ toggleIncludeNetwork(): void;
58
+ reset(): void;
59
+ }
@@ -0,0 +1,25 @@
1
+ export interface StoredState {
2
+ isOpen: boolean;
3
+ position: {
4
+ x: number;
5
+ y: number;
6
+ } | null;
7
+ size: {
8
+ width: number;
9
+ height: number;
10
+ } | null;
11
+ activeTab: string;
12
+ theme: 'dark' | 'light' | 'auto';
13
+ }
14
+ export declare class Storage {
15
+ private projectId;
16
+ setProjectId(projectId: string): void;
17
+ private getKey;
18
+ get<T>(key: keyof StoredState): T | null;
19
+ set<T>(key: keyof StoredState, value: T): void;
20
+ remove(key: keyof StoredState): void;
21
+ getState(): StoredState;
22
+ setState(state: Partial<StoredState>): void;
23
+ clear(): void;
24
+ }
25
+ export declare const storage: Storage;
package/dist/embed.css ADDED
@@ -0,0 +1 @@
1
+ [class*=" orquesta-"],[class^=orquesta-]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.orquesta-embed-panel{--orq-bg:#18181b;--orq-bg-secondary:#27272a;--orq-border:#3f3f46;--orq-text:#fafafa;--orq-text-muted:#a1a1aa;--orq-primary:#3b82f6;--orq-success:#22c55e;--orq-warning:#eab308;--orq-error:#ef4444}.orquesta-embed-panel ::-webkit-scrollbar{height:6px;width:6px}.orquesta-embed-panel ::-webkit-scrollbar-track{background:transparent}.orquesta-embed-panel ::-webkit-scrollbar-thumb{background:#3f3f46;border-radius:3px}.orquesta-embed-panel ::-webkit-scrollbar-thumb:hover{background:#52525b}@keyframes orquesta-spin{to{transform:rotate(1turn)}}@keyframes orquesta-pulse{0%,to{opacity:1}50%{opacity:.5}}.orquesta-embed-panel .animate-spin{animation:orquesta-spin 1s linear infinite}.orquesta-embed-panel .animate-pulse{animation:orquesta-pulse 2s ease-in-out infinite}.orquesta-embed-panel .line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.orquesta-embed-panel .line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.orquesta-embed-panel button:focus-visible,.orquesta-embed-panel input:focus-visible,.orquesta-embed-panel textarea:focus-visible{outline:2px solid var(--orq-primary);outline-offset:2px}#orquesta-element-highlight{animation:orquesta-highlight-pulse 1.5s ease-in-out infinite}@keyframes orquesta-highlight-pulse{0%,to{box-shadow:0 0 0 0 rgba(59,130,246,.4)}50%{box-shadow:0 0 0 4px rgba(59,130,246,.2)}}.orquesta-tooltip{background:#18181b;border:1px solid #3f3f46;border-radius:4px;color:#fafafa;font-size:12px;padding:4px 8px;pointer-events:none;position:absolute;white-space:nowrap;z-index:2147483647}.orquesta-embed-panel *{transition-duration:.15s;transition-property:color,background-color,border-color,opacity,transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.orquesta-embed-panel{animation:orquesta-panel-enter .2s ease-out}@keyframes orquesta-panel-enter{0%{opacity:0;transform:scale(.95) translateY(10px)}to{opacity:1;transform:scale(1) translateY(0)}}.orquesta-embed-trigger{animation:orquesta-trigger-enter .3s ease-out}@keyframes orquesta-trigger-enter{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}.orquesta-log-stream{background:#0a0a0a;border:1px solid #27272a;border-radius:6px;padding:8px}.orquesta-timeline button:hover{transform:translateX(2px)}@media (max-width:480px){.orquesta-embed-panel{bottom:8px!important;left:8px!important;max-height:70vh!important;position:fixed!important;right:8px!important;top:auto!important;width:auto!important}}