From d31e86782f62deb6aec9e719ffa3eec3fbfeb59e Mon Sep 17 00:00:00 2001 From: Nawaz Gafar Date: Thu, 16 Oct 2025 11:17:35 -0400 Subject: [PATCH 01/24] Window sizing uses full screen dimensions --- src/main/app.ts | 12 ++++++------ src/main/sessionwindow/sessionwindow.ts | 21 ++++++++++++++++----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/main/app.ts b/src/main/app.ts index 58f79ce5..e1ac3991 100644 --- a/src/main/app.ts +++ b/src/main/app.ts @@ -32,8 +32,6 @@ import { connectAndGetServerInfo, IJupyterServerInfo } from './connect'; import { UpdateDialog } from './updatedialog/updatedialog'; import { CtrlWBehavior, - DEFAULT_WIN_HEIGHT, - DEFAULT_WIN_WIDTH, LogLevel, resolveWorkingDirectory, SettingType, @@ -141,10 +139,12 @@ class SessionWindowManager implements IDisposable { width: screenWidth, height: screenHeight } = display.bounds; - const width = DEFAULT_WIN_WIDTH; - const height = DEFAULT_WIN_HEIGHT; - const x = screenX + Math.round((screenWidth - width) / 2); - const y = screenY + Math.round((screenHeight - height) / 2); + + // Use full screen dimensions instead of default window size + const width = screenWidth; + const height = screenHeight; + const x = screenX; + const y = screenY; return { x, y, width, height }; } diff --git a/src/main/sessionwindow/sessionwindow.ts b/src/main/sessionwindow/sessionwindow.ts index b6e34dd3..687a1092 100644 --- a/src/main/sessionwindow/sessionwindow.ts +++ b/src/main/sessionwindow/sessionwindow.ts @@ -8,7 +8,8 @@ import { dialog, Menu, MenuItemConstructorOptions, - shell + shell, + screen } from 'electron'; import * as fs from 'fs'; import { WelcomeView } from '../welcomeview/welcomeview'; @@ -109,11 +110,21 @@ export class SessionWindow implements IDisposable { if (options.rect) { rect = options.rect; } else { + // Get full screen dimensions for fallback + const cursorPt = screen.getCursorScreenPoint(); + const display = screen.getDisplayNearestPoint(cursorPt); + const { + x: screenX, + y: screenY, + width: screenWidth, + height: screenHeight + } = display.bounds; + rect = { - x: this._sessionConfig?.x !== undefined ? this._sessionConfig.x : 100, - y: this._sessionConfig?.y !== undefined ? this._sessionConfig.y : 100, - width: this._sessionConfig?.width || DEFAULT_WIN_WIDTH, - height: this._sessionConfig?.height || DEFAULT_WIN_HEIGHT + x: this._sessionConfig?.x !== undefined ? this._sessionConfig.x : screenX, + y: this._sessionConfig?.y !== undefined ? this._sessionConfig.y : screenY, + width: this._sessionConfig?.width || screenWidth, + height: this._sessionConfig?.height || screenHeight }; } From e04dd4f207da6a907dd9bf0b533497e28d3c8400 Mon Sep 17 00:00:00 2001 From: Nawaz Gafar Date: Thu, 16 Oct 2025 11:42:08 -0400 Subject: [PATCH 02/24] Reverted back to hard coded size --- src/main/app.ts | 12 ++++++------ src/main/sessionwindow/sessionwindow.ts | 21 +++++---------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/main/app.ts b/src/main/app.ts index e1ac3991..58f79ce5 100644 --- a/src/main/app.ts +++ b/src/main/app.ts @@ -32,6 +32,8 @@ import { connectAndGetServerInfo, IJupyterServerInfo } from './connect'; import { UpdateDialog } from './updatedialog/updatedialog'; import { CtrlWBehavior, + DEFAULT_WIN_HEIGHT, + DEFAULT_WIN_WIDTH, LogLevel, resolveWorkingDirectory, SettingType, @@ -139,12 +141,10 @@ class SessionWindowManager implements IDisposable { width: screenWidth, height: screenHeight } = display.bounds; - - // Use full screen dimensions instead of default window size - const width = screenWidth; - const height = screenHeight; - const x = screenX; - const y = screenY; + const width = DEFAULT_WIN_WIDTH; + const height = DEFAULT_WIN_HEIGHT; + const x = screenX + Math.round((screenWidth - width) / 2); + const y = screenY + Math.round((screenHeight - height) / 2); return { x, y, width, height }; } diff --git a/src/main/sessionwindow/sessionwindow.ts b/src/main/sessionwindow/sessionwindow.ts index 687a1092..b6e34dd3 100644 --- a/src/main/sessionwindow/sessionwindow.ts +++ b/src/main/sessionwindow/sessionwindow.ts @@ -8,8 +8,7 @@ import { dialog, Menu, MenuItemConstructorOptions, - shell, - screen + shell } from 'electron'; import * as fs from 'fs'; import { WelcomeView } from '../welcomeview/welcomeview'; @@ -110,21 +109,11 @@ export class SessionWindow implements IDisposable { if (options.rect) { rect = options.rect; } else { - // Get full screen dimensions for fallback - const cursorPt = screen.getCursorScreenPoint(); - const display = screen.getDisplayNearestPoint(cursorPt); - const { - x: screenX, - y: screenY, - width: screenWidth, - height: screenHeight - } = display.bounds; - rect = { - x: this._sessionConfig?.x !== undefined ? this._sessionConfig.x : screenX, - y: this._sessionConfig?.y !== undefined ? this._sessionConfig.y : screenY, - width: this._sessionConfig?.width || screenWidth, - height: this._sessionConfig?.height || screenHeight + x: this._sessionConfig?.x !== undefined ? this._sessionConfig.x : 100, + y: this._sessionConfig?.y !== undefined ? this._sessionConfig.y : 100, + width: this._sessionConfig?.width || DEFAULT_WIN_WIDTH, + height: this._sessionConfig?.height || DEFAULT_WIN_HEIGHT }; } From 78fe68177902b6200dfdc78a65df303d3dcfb87f Mon Sep 17 00:00:00 2001 From: Nawaz Gafar Date: Thu, 16 Oct 2025 11:42:58 -0400 Subject: [PATCH 03/24] Used .maximize method --- src/main/sessionwindow/sessionwindow.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/sessionwindow/sessionwindow.ts b/src/main/sessionwindow/sessionwindow.ts index b6e34dd3..b2612d2d 100644 --- a/src/main/sessionwindow/sessionwindow.ts +++ b/src/main/sessionwindow/sessionwindow.ts @@ -135,6 +135,7 @@ export class SessionWindow implements IDisposable { }); this._window.setMenuBarVisibility(false); + this._window.maximize(); this._window.show(); this._registerListeners(); From 66d0636b3315ad2ace96b58b718fb8f7434913ae Mon Sep 17 00:00:00 2001 From: Nawaz Gafar Date: Wed, 29 Oct 2025 12:59:48 -0400 Subject: [PATCH 04/24] Added sideload flag --- dev/start-mito-sideloaded.sh | 4 ++-- src/main/utils.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/dev/start-mito-sideloaded.sh b/dev/start-mito-sideloaded.sh index 58267815..b79cd8f4 100755 --- a/dev/start-mito-sideloaded.sh +++ b/dev/start-mito-sideloaded.sh @@ -182,8 +182,8 @@ launch_mito_desktop() { export MITO_PYTHON_PATH="$python_path" export JUPYTERLAB_DESKTOP_PYTHON_PATH="$python_path" -# Launch mito-desktop -exec yarn start "\$@" +# Launch mito-desktop with sideload flag +exec yarn start --sideload "\$@" EOF chmod +x "$temp_launch_script" diff --git a/src/main/utils.ts b/src/main/utils.ts index bf388a42..a8f3be98 100644 --- a/src/main/utils.ts +++ b/src/main/utils.ts @@ -103,6 +103,18 @@ export function getBundledPythonEnvPath(): string { } export function getBundledPythonPath(): string { + // Check if sideload flag is present (--sideload in process.argv) + const isSideload = process.argv.includes('--sideload'); + + if (isSideload) { + // If we are sideloading, we want to use the Python path from the environment variable. + // This is set in the start-mito-sideloaded.sh script, and will give us the python path + // from the conda environment where the mito-ai development version is installed. + const envPythonPath = process.env.MITO_PYTHON_PATH || process.env.JUPYTERLAB_DESKTOP_PYTHON_PATH; + if (envPythonPath) { + return envPythonPath; + } + } return pythonPathForEnvPath(getBundledPythonEnvPath(), true); } From d14b389ec50555de52342444f1b7734e78bec064 Mon Sep 17 00:00:00 2001 From: Aaron Diamond-Reivich Date: Fri, 31 Oct 2025 14:08:13 -0400 Subject: [PATCH 05/24] add input field on homepage --- src/main/config/sessionconfig.ts | 1 + src/main/labview/labview.ts | 5 + src/main/sessionwindow/sessionwindow.ts | 5 +- src/main/welcomeview/preload.ts | 5 +- src/main/welcomeview/welcomeview.ts | 657 +++++++++++++++++++++++- 5 files changed, 669 insertions(+), 4 deletions(-) diff --git a/src/main/config/sessionconfig.ts b/src/main/config/sessionconfig.ts index e51c8fc2..29a94a20 100644 --- a/src/main/config/sessionconfig.ts +++ b/src/main/config/sessionconfig.ts @@ -31,6 +31,7 @@ export class SessionConfig { token: string; pageConfig: any; cookies?: Electron.Cookie[]; + aiPrompt?: string; static createLocal( workingDirectory?: string, diff --git a/src/main/labview/labview.ts b/src/main/labview/labview.ts index e18bb647..5821c7f3 100644 --- a/src/main/labview/labview.ts +++ b/src/main/labview/labview.ts @@ -436,6 +436,8 @@ export class LabView implements IDisposable { private _registerWebAppFrontEndHandlers() { this._view.webContents.on('dom-ready', () => { const setToSingleFileUIMode = this.shouldSetToSingleFileUIMode(); + const aiPrompt = this._sessionConfig.aiPrompt; + console.log('aiPrompt', aiPrompt); this._view.webContents.executeJavaScript(` // disable splash animation @@ -445,6 +447,9 @@ export class LabView implements IDisposable { document.head.append(style); } + // Expose AI prompt if available + ${aiPrompt ? `window.mitoDesktopAIPrompt = ${JSON.stringify(aiPrompt)};` : ''} + async function jlabDesktop_getLab() { return new Promise((resolve) => { const checkLab = () => { diff --git a/src/main/sessionwindow/sessionwindow.ts b/src/main/sessionwindow/sessionwindow.ts index b2612d2d..ace65bd1 100644 --- a/src/main/sessionwindow/sessionwindow.ts +++ b/src/main/sessionwindow/sessionwindow.ts @@ -543,7 +543,7 @@ export class SessionWindow implements IDisposable { this._evm.registerEventHandler( EventTypeMain.CreateNewSession, - async (event, type: 'notebook' | 'blank') => { + async (event, type: 'notebook' | 'blank', aiPrompt?: string) => { if (event.sender !== this.contentView?.webContents) { return; } @@ -551,6 +551,9 @@ export class SessionWindow implements IDisposable { this._showProgressView('Creating new session'); const sessionConfig = SessionConfig.createLocal(); + if (aiPrompt) { + sessionConfig.aiPrompt = aiPrompt; + } this._sessionConfig = sessionConfig; this._wsSettings = new WorkspaceSettings( sessionConfig.workingDirectory diff --git a/src/main/welcomeview/preload.ts b/src/main/welcomeview/preload.ts index 2e84a736..8a95c323 100644 --- a/src/main/welcomeview/preload.ts +++ b/src/main/welcomeview/preload.ts @@ -33,10 +33,11 @@ contextBridge.exposeInMainWorld('electronAPI', { return ipcRenderer.invoke(EventTypeMain.IsDarkTheme); }, newSession: ( - type: 'notebook' | 'blank' | 'open' | 'open-file' | 'open-folder' | 'remote' + type: 'notebook' | 'blank' | 'open' | 'open-file' | 'open-folder' | 'remote', + aiPrompt?: string ) => { if (type === 'notebook' || type === 'blank') { - ipcRenderer.send(EventTypeMain.CreateNewSession, type); + ipcRenderer.send(EventTypeMain.CreateNewSession, type, aiPrompt); } else if (type === 'open') { ipcRenderer.send(EventTypeMain.OpenFileOrFolder); } else if (type === 'open-file') { diff --git a/src/main/welcomeview/welcomeview.ts b/src/main/welcomeview/welcomeview.ts index 69c3fd11..8943203d 100644 --- a/src/main/welcomeview/welcomeview.ts +++ b/src/main/welcomeview/welcomeview.ts @@ -75,7 +75,7 @@ export class WelcomeView { flex-direction: column; align-items: center; justify-content: flex-start; - padding: 25vh 40px 40px 40px; + padding: 15vh 40px 40px 40px; } .header { @@ -369,6 +369,505 @@ export class WelcomeView { .install-python-button:active { transform: translateY(0); } + + /* AI Input Field Styles */ + .ai_input_field_wrapper { + display: flex; + flex-direction: column; + width: 100%; + max-width: 700px; + margin: 0 auto 40px auto; + padding: 0 20px; + } + + @keyframes gradientShift { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } + } + + @keyframes gradientPulse { + 0%, 100% { + opacity: 0.8; + } + 50% { + opacity: 1; + } + } + + @keyframes breathe { + 0%, 100% { + transform: scale(0.99); + } + 50% { + transform: scale(1.0); + } + } + + @keyframes glowPulse { + 0%, 100% { + box-shadow: + 0 4px 20px rgba(0, 0, 0, 0.3), + 0 2px 12px rgba(0, 0, 0, 0.2), + 0 1px 4px rgba(0, 0, 0, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.1), + inset 0 -1px 0 rgba(0, 0, 0, 0.2), + 0 0 20px rgba(157, 108, 255, 0.2), + 0 0 40px rgba(157, 108, 255, 0.1); + } + 50% { + box-shadow: + 0 4px 20px rgba(0, 0, 0, 0.3), + 0 2px 12px rgba(0, 0, 0, 0.2), + 0 1px 4px rgba(0, 0, 0, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.1), + inset 0 -1px 0 rgba(0, 0, 0, 0.2), + 0 0 25px rgba(157, 108, 255, 0.3), + 0 0 50px rgba(157, 108, 255, 0.15); + } + } + + @keyframes iconTwinkle { + 0%, 90%, 100% { + transform: scale(1) rotate(0deg); + filter: drop-shadow(0 2px 4px rgba(157, 108, 255, 0.3)); + } + 5% { + transform: scale(1.1) rotate(5deg); + filter: drop-shadow(0 2px 6px rgba(157, 108, 255, 0.5)) brightness(1.2); + } + 10% { + transform: scale(1.05) rotate(-3deg); + filter: drop-shadow(0 2px 6px rgba(157, 108, 255, 0.5)) brightness(1.1); + } + 15% { + transform: scale(1) rotate(0deg); + filter: drop-shadow(0 2px 4px rgba(157, 108, 255, 0.3)); + } + } + + @keyframes iconColorShift { + 0%, 100% { + color: #9D6CFF; + } + 25% { + color: #ac84fc; + } + 50% { + color: #c084fc; + } + 75% { + color: #ac84fc; + } + } + + @keyframes sparkle { + 0%, 100% { + opacity: 0; + transform: scale(0) rotate(0deg); + } + 50% { + opacity: 1; + transform: scale(1) rotate(180deg); + } + } + + .input_container { + width: 100%; + max-width: 900px; + margin: 0 auto; + margin-bottom: 20px; + height: 30px; + position: relative; + animation: breathe 4s ease-in-out infinite; + } + + .input_container:has(.prompt_input:not(:placeholder-shown)) { + animation: none; + } + + .input_container:focus-within { + animation: none; + } + + .input_container:focus-within:has(.prompt_input:placeholder-shown) { + animation: breathe 4s ease-in-out infinite; + } + + .input_wrapper { + display: flex; + align-items: center; + background: linear-gradient( + 135deg, + rgba(34, 27, 46, 0.9) 0%, + rgba(28, 24, 36, 0.95) 50%, + rgba(19, 15, 26, 0.9) 100% + ); + backdrop-filter: blur(20px) saturate(180%); + -webkit-backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(157, 108, 255, 0.4); + border-radius: 12px; + padding: 8px 10px; + gap: 12px; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: + 0 4px 20px rgba(0, 0, 0, 0.3), + 0 2px 12px rgba(0, 0, 0, 0.2), + 0 1px 4px rgba(0, 0, 0, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.1), + inset 0 -1px 0 rgba(0, 0, 0, 0.2), + 0 0 20px rgba(157, 108, 255, 0.2), + 0 0 40px rgba(157, 108, 255, 0.1); + position: relative; + overflow: hidden; + z-index: 1; + animation: glowPulse 3.5s ease-in-out infinite; + } + + .input_wrapper:has(.prompt_input:not(:placeholder-shown)) { + animation: none; + } + + .input_wrapper::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient( + 135deg, + rgba(255, 255, 255, 0.05) 0%, + rgba(255, 255, 255, 0.02) 50%, + rgba(157, 108, 255, 0.03) 100% + ); + opacity: 0; + transition: opacity 0.4s ease; + pointer-events: none; + } + + .input_wrapper::after { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + rgba(255, 255, 255, 0.1) 50%, + rgba(255, 255, 255, 0) 100% + ); + transition: left 0.6s ease; + pointer-events: none; + } + + .input_wrapper:hover { + transform: translateY(-2px); + box-shadow: + 0 8px 32px rgba(0, 0, 0, 0.4), + 0 4px 20px rgba(0, 0, 0, 0.3), + 0 2px 8px rgba(0, 0, 0, 0.5), + 0 4px 24px rgba(157, 108, 255, 0.3), + 0 2px 12px rgba(172, 132, 252, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.15), + inset 0 -1px 0 rgba(157, 108, 255, 0.2); + background: linear-gradient( + 135deg, + rgba(34, 27, 46, 0.95) 0%, + rgba(28, 24, 36, 1) 50%, + rgba(19, 15, 26, 0.95) 100% + ); + border-color: rgba(157, 108, 255, 0.6); + animation: none; + } + + .input_wrapper:hover::before { + opacity: 1; + } + + .input_wrapper:hover::after { + left: 100%; + } + + .input_wrapper:focus-within { + transform: translateY(-3px); + box-shadow: + 0 12px 40px rgba(0, 0, 0, 0.5), + 0 6px 24px rgba(0, 0, 0, 0.4), + 0 3px 12px rgba(0, 0, 0, 0.6), + 0 8px 32px rgba(157, 108, 255, 0.4), + 0 4px 16px rgba(172, 132, 252, 0.3), + 0 2px 8px rgba(192, 132, 252, 0.25), + 0 0 0 4px rgba(157, 108, 255, 0.25), + inset 0 1px 0 rgba(255, 255, 255, 0.2), + inset 0 -1px 0 rgba(157, 108, 255, 0.3), + inset 0 0 20px rgba(157, 108, 255, 0.1); + background: linear-gradient( + 135deg, + rgba(34, 27, 46, 1) 0%, + rgba(28, 24, 36, 1) 50%, + rgba(25, 20, 35, 1) 100% + ); + border-color: rgba(157, 108, 255, 0.8); + animation: none; + } + + .input_wrapper:focus-within::before { + opacity: 1; + animation: gradientPulse 2s ease-in-out infinite; + } + + .input_icon_left { + font-size: 20px; + color: #9D6CFF; + display: flex; + align-items: center; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + filter: drop-shadow(0 2px 4px rgba(157, 108, 255, 0.3)); + font-weight: 500; + position: relative; + z-index: 2; + animation: + iconTwinkle 5s ease-in-out infinite, + iconColorShift 8s ease-in-out infinite; + } + + .input_wrapper:has(.prompt_input:not(:placeholder-shown)) .input_icon_left { + animation: none; + color: #9D6CFF; + } + + .input_icon_left::before, + .input_icon_left::after { + content: '✨'; + position: absolute; + font-size: 8px; + pointer-events: none; + animation: sparkle 6s ease-in-out infinite; + color: #ac84fc; + } + + .input_wrapper:has(.prompt_input:not(:placeholder-shown)) .input_icon_left::before, + .input_wrapper:has(.prompt_input:not(:placeholder-shown)) .input_icon_left::after { + animation: none; + opacity: 0; + } + + .input_icon_left::before { + top: -5px; + right: -8px; + animation-delay: 0s; + } + + .input_icon_left::after { + bottom: -3px; + left: -6px; + animation-delay: 3s; + } + + .input_wrapper:focus-within .input_icon_left { + color: #ac84fc; + transform: scale(1.15); + filter: drop-shadow(0 4px 8px rgba(157, 108, 255, 0.5)); + animation: none; + } + + .input_wrapper:hover .input_icon_left, + .input_wrapper:hover .input_action_button, + .generating .input_icon_left, + .generating .input_action_button { + color: #9D6CFF; + transform: scale(1.08); + filter: drop-shadow(0 3px 6px rgba(157, 108, 255, 0.4)); + } + + .input_wrapper:hover .input_icon_left { + animation: none; + } + + .prompt_input { + flex: 1; + border: none; + outline: none; + background: transparent; + font-size: 16px; + font-weight: 400; + line-height: 1.4; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; + color: ${this._isDarkTheme ? '#ffffff' : '#000000'}; + padding: 6px 0; + transition: all 0.4s ease; + position: relative; + z-index: 2; + } + + .prompt_input::placeholder { + color: ${this._isDarkTheme ? '#D0D0D0' : '#666666'}; + font-weight: 400; + transition: all 0.3s ease; + } + + .prompt_input:focus { + color: ${this._isDarkTheme ? '#ffffff' : '#000000'}; + } + + .prompt_input:focus::placeholder { + opacity: 0.6; + transform: translateY(-1px); + } + + .input_action_button { + width: 32px; + height: 32px; + border: none; + border-radius: 50%; + background: linear-gradient( + 135deg, + rgba(157, 108, 255, 0.2) 0%, + rgba(172, 132, 252, 0.15) 100% + ); + color: #9D6CFF; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + font-weight: 600; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + position: relative; + z-index: 2; + box-shadow: + 0 2px 8px rgba(157, 108, 255, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.1); + } + + .input_action_button:hover:not(:disabled) { + transform: scale(1.15); + background: linear-gradient( + 135deg, + rgba(157, 108, 255, 0.3) 0%, + rgba(172, 132, 252, 0.2) 100% + ); + box-shadow: + 0 4px 16px rgba(157, 108, 255, 0.3), + 0 2px 8px rgba(172, 132, 252, 0.25), + inset 0 1px 0 rgba(255, 255, 255, 0.2); + } + + .input_action_button:disabled { + opacity: 0.6; + cursor: not-allowed; + transform: none; + color: ${this._isDarkTheme ? '#D0D0D0' : '#666666'}; + background: transparent; + box-shadow: none; + } + + .input_icons_right { + display: flex; + align-items: center; + gap: 4px; + z-index: 2; + position: relative; + } + + .generating { + animation: gradientPulse 2s ease-in-out infinite; + } + + .generating .input_wrapper { + box-shadow: + 0 8px 32px rgba(157, 108, 255, 0.4), + 0 4px 16px rgba(172, 132, 252, 0.3), + 0 2px 8px rgba(192, 132, 252, 0.25), + inset 0 1px 0 rgba(255, 255, 255, 0.15), + inset 0 0 20px rgba(157, 108, 255, 0.15); + animation: none; + } + + .generating .input_container { + animation: none; + } + + .examples_container { + display: flex; + flex-direction: column; + gap: 12px; + margin-top: 24px; + width: 100%; + max-width: 600px; + margin-left: auto; + margin-right: auto; + } + + .example_button { + background: linear-gradient( + 135deg, + rgba(34, 27, 46, 0.8) 0%, + rgba(28, 24, 36, 0.9) 50%, + rgba(19, 15, 26, 0.8) 100% + ); + border: 1px solid rgba(157, 108, 255, 0.3); + border-radius: 8px; + padding: 14px 20px 14px 24px; + color: ${this._isDarkTheme ? '#D0D0D0' : '#666666'}; + font-size: 14px; + font-weight: 400; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + text-align: left; + line-height: 1.4; + width: 100%; + box-shadow: + 0 2px 8px rgba(0, 0, 0, 0.2), + 0 1px 4px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.05); + } + + .example_button:hover { + background: linear-gradient( + 135deg, + rgba(34, 27, 46, 0.9) 0%, + rgba(28, 24, 36, 1) 50%, + rgba(19, 15, 26, 0.9) 100% + ); + border-color: rgba(157, 108, 255, 0.5); + color: ${this._isDarkTheme ? '#ffffff' : '#000000'}; + transform: translateY(-2px); + padding-left: 28px; + box-shadow: + 0 4px 16px rgba(0, 0, 0, 0.3), + 0 2px 8px rgba(0, 0, 0, 0.2), + 0 2px 8px rgba(157, 108, 255, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.1); + } + + .example_button:active { + transform: translateY(-1px); + transition-duration: 0.1s; + } + + .generating + .examples_container { + opacity: 0.5; + pointer-events: none; + transform: translateY(4px); + } + + .loading-circle { + width: 16px; + height: 16px; + }