"""CSS styles and JavaScript for MedGemma AI Assistant UI""" CUSTOM_CSS = """ /* Global dark theme background */ .gradio-container { background: linear-gradient(135deg, #0f0a1a 0%, #1a1625 50%, #1a1a2e 100%) !important; } /* Main section buttons (Classification, Detection, Seg_3D) */ .main-action-btn { background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%) !important; border: 1px solid #a78bfa !important; color: #ffffff !important; transition: all 0.3s ease !important; box-shadow: 0 2px 10px rgba(139, 92, 246, 0.2) !important; } .main-action-btn:hover { background: linear-gradient(135deg, #8b5cf6 0%, #a78bfa 100%) !important; box-shadow: 0 4px 20px rgba(139, 92, 246, 0.4) !important; transform: translateY(-2px) !important; } /* Action buttons - Predict/Segment (GREEN) */ .action-predict-btn { background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important; border: 1px solid #34d399 !important; color: #ffffff !important; font-weight: 600 !important; transition: all 0.3s ease !important; box-shadow: 0 2px 10px rgba(16, 185, 129, 0.2) !important; margin-top: 8px !important; } .action-predict-btn:hover { background: linear-gradient(135deg, #059669 0%, #047857 100%) !important; box-shadow: 0 4px 20px rgba(16, 185, 129, 0.4) !important; transform: translateY(-2px) !important; } /* Loading state for predict button */ .action-predict-btn:disabled { background: linear-gradient(135deg, #6b7280 0%, #4b5563 100%) !important; border: 1px solid #9ca3af !important; cursor: wait !important; animation: pulse 1.5s ease-in-out infinite !important; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } } /* Action buttons - Explain (BLUE) */ .action-explain-btn { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important; border: 1px solid #60a5fa !important; color: #ffffff !important; font-weight: 600 !important; transition: all 0.3s ease !important; box-shadow: 0 2px 10px rgba(59, 130, 246, 0.2) !important; margin-top: 8px !important; } .action-explain-btn:hover { background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%) !important; box-shadow: 0 4px 20px rgba(59, 130, 246, 0.4) !important; transform: translateY(-2px) !important; } /* Loading state for explain button */ .action-explain-btn:disabled { background: linear-gradient(135deg, #6b7280 0%, #4b5563 100%) !important; border: 1px solid #9ca3af !important; cursor: wait !important; animation: pulse 1.5s ease-in-out infinite !important; } /* Action buttons - View 3D (YELLOW/ORANGE) */ .action-view3d-btn { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%) !important; border: 1px solid #fbbf24 !important; color: #ffffff !important; font-weight: 600 !important; transition: all 0.3s ease !important; box-shadow: 0 2px 10px rgba(245, 158, 11, 0.2) !important; margin-top: 8px !important; } .action-view3d-btn:hover { background: linear-gradient(135deg, #d97706 0%, #b45309 100%) !important; box-shadow: 0 4px 20px rgba(245, 158, 11, 0.4) !important; transform: translateY(-2px) !important; } /* Image filename display */ .image-filename { text-align: center !important; font-size: 14px !important; color: #a0a0a0 !important; margin: 8px 0 !important; padding: 6px 12px !important; background: rgba(255, 255, 255, 0.05) !important; border-radius: 6px !important; font-family: 'Courier New', monospace !important; } /* Navigation controls (prev/next buttons and counter) */ .nav-buttons { display: flex !important; justify-content: center !important; align-items: center !important; gap: 10px !important; margin: 8px 0 !important; } .nav-buttons button { min-width: 40px !important; max-width: 40px !important; padding: 8px !important; font-size: 16px !important; font-weight: bold !important; } .counter-text { text-align: center !important; margin: 0 auto !important; min-width: 150px !important; font-weight: 600 !important; color: #e0e0e0 !important; } .counter-text p { text-align: center !important; margin: 0 !important; } /* Standard image preview (400px for Classification/Detection) */ .image-preview { width: 100% !important; min-height: 400px !important; max-height: 400px !important; display: flex !important; align-items: center !important; justify-content: center !important; background: #000000 !important; border-radius: 8px !important; overflow: hidden !important; } /* Gradio image container sizing */ .image-preview .image-container, .image-preview [data-testid="image"], .image-preview .gr-image { width: 100% !important; height: 400px !important; min-height: 400px !important; max-height: 400px !important; display: flex !important; align-items: center !important; justify-content: center !important; background: #000000 !important; } .image-preview img { object-fit: contain !important; width: 100% !important; height: 400px !important; min-height: 400px !important; max-height: 400px !important; cursor: pointer !important; transition: all 0.2s ease !important; } .image-preview:hover img { opacity: 0.9 !important; transform: scale(1.02) !important; } /* Segmentation image preview (700px, larger than standard) */ #seg3d_image, #seg3d_image > *, #seg3d_image .image-container, #seg3d_image [data-testid="image"], #seg3d_image .gr-image, #seg3d_image .image-frame { width: 100% !important; max-width: 100% !important; height: 700px !important; min-height: 700px !important; max-height: 700px !important; display: flex !important; align-items: center !important; justify-content: center !important; } #seg3d_image img { object-fit: contain !important; width: 100% !important; max-width: 100% !important; height: 700px !important; min-height: 700px !important; max-height: 700px !important; } /* 3D HTML mini preview */ .html-3d-preview { width: 100% !important; height: 400px !important; min-height: 400px !important; max-height: 400px !important; display: block !important; background: #000000 !important; border-radius: 8px !important; overflow: hidden !important; cursor: pointer !important; transition: all 0.2s ease !important; } .html-3d-preview:hover { opacity: 0.95 !important; box-shadow: 0 0 0 2px #f59e0b !important; } /* 3D HTML viewer */ #html-3d-viewer { width: 100% !important; height: 700px !important; min-height: 700px !important; border: 1px solid #35384a !important; border-radius: 8px !important; background: #000000 !important; overflow: hidden !important; } #html-3d-viewer iframe { width: 100% !important; height: 700px !important; border: none !important; } /* Image modal overlay */ .temp-modal-overlay { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0, 0, 0, 0.92); backdrop-filter: blur(12px); z-index: 10000; display: flex; align-items: center; justify-content: center; animation: fadeIn 0.3s ease-out; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .temp-modal-content { background: #16181d; border: 1px solid #35384a; border-radius: 16px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8); max-width: 90vw; max-height: 90vh; overflow: hidden; animation: slideIn 0.3s ease-out; display: flex; flex-direction: column; } @keyframes slideIn { from { opacity: 0; transform: scale(0.9) translateY(-20px); } to { opacity: 1; transform: scale(1) translateY(0); } } .temp-modal-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; background: #1d1f26; border-bottom: 1px solid #2a2d38; } .temp-modal-title { font-size: 18px; font-weight: 600; color: #e8eaed; margin: 0; } .temp-modal-close { background: #23252e; border: 1px solid #35384a; font-size: 20px; cursor: pointer; padding: 8px; border-radius: 8px; color: #b8bcc8; transition: all 0.2s ease; } .temp-modal-close:hover { background: #6a6a7a; color: white; border-color: #6a6a7a; transform: scale(1.1); } .temp-modal-body { padding: 20px; display: flex; justify-content: center; align-items: center; width: auto; height: auto; max-width: 90vw; max-height: calc(90vh - 80px); overflow: auto; flex: 1; background: #0f1014; } .temp-modal-image { width: auto !important; height: auto !important; max-width: 100% !important; max-height: 100% !important; min-width: 800px !important; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); object-fit: contain !important; } /* Segmentation modal (larger, 90vw for multi-slice views) */ .temp-modal-content-seg3d { background: #16181d; border: 1px solid #35384a; border-radius: 16px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8); max-width: 90vw; max-height: 90vh; overflow: hidden; animation: slideIn 0.3s ease-out; display: flex; flex-direction: column; } .temp-modal-body-seg3d { padding: 20px; display: flex; justify-content: center; align-items: flex-start; width: auto; height: auto; max-width: 90vw; max-height: calc(90vh - 80px); overflow: auto; flex: 1; background: #0f1014; } .temp-modal-body-seg3d img { width: auto !important; height: auto !important; max-width: 100% !important; max-height: 100% !important; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); object-fit: contain !important; } /* Enhanced Textbox - Make it 3 lines tall visually */ .gr-multimodal-textbox textarea, [data-testid="multimodal-textbox"] textarea, .multimodal-textbox textarea { min-height: 80px !important; height: 80px !important; font-size: 16px !important; line-height: 1.5 !important; padding: 12px !important; } .gr-multimodal-textbox textarea:focus, [data-testid="multimodal-textbox"] textarea:focus, .multimodal-textbox textarea:focus { border-color: #35384a !important; box-shadow: none !important; outline: none !important; } /* Make System Prompt textbox bigger in Additional Inputs */ .gr-textbox textarea { min-height: 150px !important; font-size: 14px !important; line-height: 1.4 !important; padding: 12px !important; background: #1a1d23 !important; border: 1px solid #35384a !important; border-radius: 8px !important; color: #e8eaed !important; } .gr-textbox textarea:focus { border-color: #35384a !important; box-shadow: none !important; outline: none !important; } /* Chat styling moved to style.css for simplicity */ /* Remove purple focus effects */ .chatbot-input-container:focus-within, [data-testid="textbox"]:focus-within, .gr-textbox:focus-within { box-shadow: none !important; border-color: #35384a !important; transform: none !important; transition: none !important; } /* Make chat messages more readable */ .message-wrap { font-size: 15px !important; line-height: 1.6 !important; } /* Center the chat input area */ .chat-interface-container, [data-testid="chat-interface"], .gradio-chatinterface { display: flex !important; flex-direction: column !important; align-items: center !important; } /* Center the multimodal textbox and buttons */ .multimodal-textbox, [data-testid="multimodal-textbox"], .gr-multimodal-textbox { display: flex !important; justify-content: center !important; align-items: center !important; width: 100% !important; margin: 0 auto !important; } /* Center the input row container */ .input-row, [class*="input"], [class*="textbox-row"] { display: flex !important; justify-content: center !important; align-items: center !important; width: 100% !important; } /* Ensure buttons are centered with the textbox */ .submit-btn, .clear-btn, [data-testid="submit-button"], [data-testid="clear-button"] { margin: 0 4px !important; } /* Fix chat message images to display inline and centered */ .message-wrap .message-content img, .message .message-content img, [data-testid="message"] img { display: inline-block !important; max-width: 300px !important; max-height: 300px !important; object-fit: contain !important; border-radius: 8px !important; margin: 8px auto !important; vertical-align: middle !important; } /* Center images in chat messages */ .message-wrap .message-content, .message .message-content, [data-testid="message"] { display: flex !important; flex-direction: column !important; align-items: center !important; text-align: center !important; } /* Keep text left-aligned but images centered */ .message-wrap .message-content p, .message .message-content p { text-align: left !important; width: 100% !important; } """ # JavaScript for image modal click functionality MODAL_JS = """ """