/** * File: static/css/style.css * Description: Stylesheet for the Mariam AI Chatbot Web Application. * Version: Enhanced with PWA support and improved responsiveness. */ /* PWA Specific Styles */ @media (display-mode: standalone) { /* Adjustments for standalone mode (when installed as PWA) */ body { /* Add safe area insets for mobile devices */ padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); /* Better touch handling */ touch-action: manipulation; } /* Hide browser UI when installed as PWA */ .top-bar { padding-top: max(12px, env(safe-area-inset-top)); } /* Ensure content doesn't get hidden beneath the bottom nav bar on iOS */ .input-area { padding-bottom: env(safe-area-inset-bottom); } } /* Offline indicator for PWA */ .offline-indicator { position: fixed; top: 0; left: 0; right: 0; background-color: #FFC107; color: #212121; text-align: center; padding: 8px; font-size: 14px; z-index: 9999; display: none; /* Hidden by default, shown via JS when offline */ } .offline-indicator.visible { display: block; } /* Base Styles */ * { margin: 0; padding: 0; box-sizing: border-box; } html { height: 100%; /* Ensure html takes full height */ } body { font-family: 'Inter', sans-serif; background-color: #FFFFFF; /* Base background */ color: #212121; height: 100%; /* Take full height from html */ overflow-x: hidden; /* Prevent horizontal scroll */ overflow-y: hidden; /* Prevent body from scrolling itself */ margin: 0; /* Remove default body margins */ } /* App Container - Main flex container */ .app-container { display: flex; height: 100%; width: 100%; position: relative; /* For absolute positioning of side nav on mobile */ overflow: hidden; /* Contain side nav */ } /* Side Navigation Bar */ .side-nav { width: 280px; height: 100%; background-color: #FFFFFF; border-right: 1px solid #EEEEEE; display: flex; flex-direction: column; position: absolute; /* Mobile first: hidden off-screen */ top: 0; left: -280px; transition: left 0.3s ease; z-index: 1000; box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1); flex-shrink: 0; /* Prevent shrinking */ } .side-nav.active { left: 0; /* Slide in when active */ } .side-nav-header { display: flex; align-items: center; padding: 16px; border-bottom: 1px solid #EEEEEE; position: relative; /* For close button positioning */ flex-shrink: 0; /* Prevent header shrinking */ } .side-nav-header .logo { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; background-color: #E3F2FD; border-radius: 50%; margin-right: 12px; color: #2196F3; flex-shrink: 0; } .side-nav-header h1 { font-size: 20px; font-weight: 600; color: #424242; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .close-button { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); background-color: transparent; color: #9E9E9E; border: none; width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; flex-shrink: 0; } .close-button:hover { background-color: #F5F5F5; color: #757575; } .side-nav-section { flex: 1; /* Take remaining vertical space */ overflow-y: auto; /* Allow scrolling if history is long */ padding: 16px 0; border-bottom: 1px solid #EEEEEE; display: flex; flex-direction: column; } .section-header { display: flex; justify-content: space-between; align-items: center; padding: 0 16px 12px; flex-shrink: 0; /* Prevent shrinking */ } .section-header h3 { font-size: 16px; font-weight: 600; color: #424242; margin: 0; } .action-button-small { background-color: transparent; color: #2196F3; border: 1px solid #2196F3; border-radius: 4px; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; flex-shrink: 0; } .action-button-small:hover { background-color: #E3F2FD; } .history-list { /* max-height: 100%; Removed, parent (.side-nav-section) handles overflow */ overflow-y: auto; /* Allows scrolling within this specific list if needed */ flex-grow: 1; /* Allows the list to grow */ } .chat-history-item { padding: 12px 16px; cursor: pointer; display: flex; align-items: center; transition: background-color 0.2s ease; border-radius: 8px; margin: 0 8px 8px; } .chat-history-item:hover { background-color: #F5F5F5; } .chat-history-item .icon { margin-right: 12px; color: #757575; flex-shrink: 0; } .chat-history-item .details { flex: 1; overflow: hidden; /* Prevent text overflow issues */ } .chat-history-item .timestamp { font-size: 12px; color: #9E9E9E; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .empty-state { padding: 24px 16px; text-align: center; color: #9E9E9E; font-size: 14px; } .side-nav-footer { padding: 16px; display: flex; flex-direction: column; gap: 8px; flex-shrink: 0; /* Prevent shrinking */ border-top: 1px solid #EEEEEE; /* Separator */ } .nav-button { display: flex; align-items: center; padding: 10px 16px; background-color: transparent; color: #616161; border: none; border-radius: 8px; cursor: pointer; transition: all 0.2s ease; font-size: 14px; text-align: left; } .nav-button i { margin-right: 12px; font-size: 16px; flex-shrink: 0; } .nav-button:hover { background-color: #F5F5F5; } .nav-button#clearButtonNav:hover { color: #F44336; } /* Main Content Area */ .main-content { flex: 1; /* Takes remaining horizontal space */ display: flex; flex-direction: column; /* Stack top-bar and chat-container */ height: 100%; /* Crucial for nested flex children height */ overflow: hidden; /* Prevent main content from overflowing */ position: relative; /* Keep for nav transition */ left: 0; transition: left 0.3s ease; } /* Apply shift when nav is open on mobile/tablet */ .main-content.nav-open { /* This selector might need adjustment based on how 'nav-open' is applied */ /* Typically applied on body or app-container in JS */ } @media (max-width: 991px) { .main-content.nav-open { left: 280px; } } /* Top Bar */ .top-bar { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; background-color: #2196F3; color: white; height: 60px; /* Fixed height */ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); z-index: 10; flex-shrink: 0; /* Prevent shrinking */ } .top-bar-left { display: flex; align-items: center; } .menu-button { background-color: transparent; color: white; border: none; width: 42px; height: 42px; border-radius: 50%; display: flex; /* Changed to flex for desktop */ align-items: center; justify-content: center; cursor: pointer; margin-right: 16px; font-size: 24px; transition: background-color 0.2s ease; } .menu-button:hover { background-color: rgba(255, 255, 255, 0.1); } .top-bar h1 { font-size: 20px; font-weight: 500; margin: 0; color: white; white-space: nowrap; } .top-bar-right { display: flex; align-items: center; } .icon-button { background-color: transparent; color: white; border: none; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.2s ease; } .icon-button:hover { background-color: rgba(255, 255, 255, 0.1); } /* Chat Container - Takes remaining space below top-bar */ .chat-container { display: flex; flex-direction: column; /* Stack chat-window and input-area */ flex: 1; /* Crucial: takes remaining vertical space in main-content */ overflow: hidden; /* Contains children */ background-color: #FAFAFA; /* height: calc(100% - 60px); Removed, flex: 1 handles this */ } /* Scrollable Chat Window */ .chat-window { flex: 1; /* Crucial: takes remaining space IN chat-container */ overflow-y: auto; /* Enables vertical scrolling for content */ padding: 16px; scrollbar-width: thin; /* Firefox scrollbar styling */ scrollbar-color: #E0E0E0 #FAFAFA; /* Firefox scrollbar styling */ -webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */ } /* Webkit scrollbar styling */ .chat-window::-webkit-scrollbar { width: 6px; } .chat-window::-webkit-scrollbar-track { background: #FAFAFA; } .chat-window::-webkit-scrollbar-thumb { background-color: #E0E0E0; border-radius: 10px; } /* Welcome Container with Suggestion Bubbles */ .welcome-container { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; /* Tries to fill the chat-window initially */ padding: 24px; text-align: center; } /* Hide welcome if messages exist (handled by JS) */ .welcome-container.hidden { display: none; } .welcome-logo { display: flex; align-items: center; justify-content: center; width: 64px; height: 64px; background-color: #E3F2FD; border-radius: 50%; margin-bottom: 24px; color: #2196F3; flex-shrink: 0; } .welcome-logo i { font-size: 32px; } .welcome-header h2 { font-size: 28px; font-weight: 600; color: #212121; margin-bottom: 12px; } .welcome-subtitle { font-size: 16px; color: #757575; margin-bottom: 32px; } .suggestion-bubbles { display: flex; flex-direction: column; gap: 16px; max-width: 500px; width: 100%; } .suggestion-bubble { display: flex; align-items: center; padding: 16px; background-color: #F5F5F5; border-radius: 12px; cursor: pointer; transition: all 0.2s ease; text-align: left; } .suggestion-bubble i { font-size: 20px; color: #2196F3; margin-right: 16px; flex-shrink: 0; } .suggestion-bubble span { font-size: 15px; color: #424242; } .suggestion-bubble:hover { background-color: #E3F2FD; transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05); } /* Input Area Container */ .input-area { border-top: 1px solid #EEEEEE; background-color: #FFFFFF; flex-shrink: 0; /* Prevent shrinking */ /* Removed position:sticky from mobile - handled by flex layout */ box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.05); /* Keep shadow for visual separation */ } /* Image Preview Area */ .image-preview-area { padding: 8px 16px; background-color: #F8F9FA; border-bottom: 1px solid #EEEEEE; max-height: 130px; /* Limit height */ overflow-y: auto; /* Allow scroll if many images */ } .image-preview-area.hidden { display: none; } .image-preview-list { display: flex; flex-wrap: wrap; /* Wrap images */ gap: 10px; padding: 5px 0; } .image-preview-container { position: relative; display: inline-block; width: 100px; height: 100px; border-radius: 8px; overflow: hidden; border: 1px solid #EEEEEE; flex-shrink: 0; } .image-preview-container img { width: 100%; height: 100%; display: block; object-fit: cover; } .remove-image-button { position: absolute; top: 4px; right: 4px; background-color: rgba(0, 0, 0, 0.5); color: white; border: none; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.2s ease; z-index: 1; /* Above image */ } .remove-image-button:hover { background-color: rgba(0, 0, 0, 0.7); } /* Message Containers */ .message-container { display: flex; margin: 12px 0; width: 100%; /* Ensure it takes full width for alignment */ } .message-container.user { justify-content: flex-end; /* Align user messages to the right */ } .message-container.bot { justify-content: flex-start; /* Align bot messages to the left */ } /* Message Bubbles */ .message-bubble { max-width: 80%; /* Limit bubble width */ padding: 14px 18px; border-radius: 18px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); word-wrap: break-word; /* Allow long words to break */ overflow-wrap: break-word; /* Better word breaking */ position: relative; /* For absolute positioning of action buttons */ } .message-container.user .message-bubble { background-color: #E3F2FD; /* Light blue for user */ border-top-right-radius: 4px; /* Flat corner for speech bubble effect */ color: #1E4A72; /* Darker text for contrast */ } .message-container.bot .message-bubble { background-color: #FFFFFF; /* White for bot */ border-top-left-radius: 4px; /* Flat corner */ border: 1px solid #EEEEEE; /* Subtle border */ color: #212121; /* Default text color */ } /* Message Text and Images */ .message-bubble p { margin: 0; line-height: 1.5; font-size: 15px; white-space: pre-wrap; /* Preserve whitespace and newlines */ } .message-bubble .image-container { margin-bottom: 8px; } .message-bubble .chat-image { max-width: 100%; border-radius: 8px; margin-bottom: 8px; max-height: 300px; /* Limit image height */ object-fit: contain; /* Prevent distortion */ display: block; /* Ensure it behaves like a block */ } /* Markdown Styling */ .message-bubble ul, .message-bubble ol { margin-left: 25px; /* Indent lists */ margin-top: 8px; margin-bottom: 8px; padding-left: 0; /* Reset default padding */ } .message-bubble li { margin-bottom: 4px; } .message-bubble h1, .message-bubble h2, .message-bubble h3, .message-bubble h4, .message-bubble h5, .message-bubble h6 { margin-top: 16px; margin-bottom: 8px; font-weight: 600; line-height: 1.3; } .message-bubble code:not(pre > code) { /* Inline code */ background-color: #f0f0f0; /* Slightly different background */ padding: 2px 5px; border-radius: 4px; font-family: 'Courier New', monospace; font-size: 14px; color: #C7254E; /* Pinkish color */ border: 1px solid #e0e0e0; } .message-bubble pre { /* Code blocks */ background-color: #2d2d2d; /* Dark background for code blocks */ color: #f8f8f2; /* Light text */ padding: 16px; border-radius: 8px; overflow-x: auto; /* Allow horizontal scroll for long lines */ margin: 12px 0; font-family: 'Courier New', monospace; font-size: 14px; line-height: 1.4; white-space: pre; /* Maintain whitespace */ } .message-bubble pre code { background-color: transparent; /* Code inside pre doesn't need its own bg */ padding: 0; color: inherit; /* Inherit color from pre */ border: none; font-size: inherit; font-family: inherit; display: block; /* Ensure it takes block space */ white-space: inherit; /* Inherit whitespace handling */ } .message-bubble a { color: #1976D2; /* Link color */ text-decoration: underline; } .message-bubble a:hover { color: #1565C0; } .message-bubble table { border-collapse: collapse; width: 100%; margin: 12px 0; border: 1px solid #dddddd; } .message-bubble th, .message-bubble td { border: 1px solid #dddddd; padding: 10px; text-align: left; } .message-bubble th { background-color: #f9f9f9; font-weight: 600; } .message-bubble blockquote { border-left: 4px solid #ccc; margin: 10px 0; padding-left: 16px; color: #666; } /* Error Message Styling */ .message-container.error .message-bubble { background-color: #FFEBEE; /* Light red */ border: 1px solid #FFCDD2; color: #B71C1C; /* Dark red text */ } .retry-button { display: inline-block; margin-top: 8px; padding: 6px 12px; background-color: #F44336; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; transition: background-color 0.2s ease; } .retry-button:hover { background-color: #D32F2F; } /* Message actions (copy button, etc.) */ .message-actions { position: absolute; top: 8px; right: 8px; display: flex; gap: 5px; opacity: 0; transition: opacity 0.2s ease; } .message-bubble:hover .message-actions { opacity: 1; } .copy-button { background-color: rgba(255, 255, 255, 0.8); color: #616161; border: none; border-radius: 4px; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; } .copy-button:hover { background-color: #E3F2FD; color: #2196F3; } /* Loading Animation */ .message-bubble.loading { display: flex; /* Use flex for alignment */ align-items: center; justify-content: center; /* Center dots */ min-width: 60px; /* Ensure some width */ padding: 14px 18px; /* Match normal bubble padding */ background-color: #FFFFFF; /* Match bot background */ border: 1px solid #EEEEEE; /* Match bot border */ border-top-left-radius: 4px; /* Match bot radius */ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); /* Match bubble shadow */ } .dot-typing { position: relative; width: 6px; height: 6px; border-radius: 50%; background-color: #9E9E9E; color: #9E9E9E; /* For ::before/::after color */ animation: dotTyping 1.5s infinite linear; animation-delay: 0.25s; /* Stagger start */ } .dot-typing::before, .dot-typing::after { content: ''; display: inline-block; position: absolute; top: 0; width: 6px; height: 6px; border-radius: 50%; background-color: #9E9E9E; color: #9E9E9E; } .dot-typing::before { left: -12px; /* Position left dot */ animation: dotTypingBefore 1.5s infinite linear; animation-delay: 0s; } .dot-typing::after { left: 12px; /* Position right dot */ animation: dotTypingAfter 1.5s infinite linear; animation-delay: 0.5s; /* Stagger start */ } @keyframes dotTyping { 0%, 60%, 100% { transform: scale(1); opacity: 0.6; } 30% { transform: scale(1.3); opacity: 1; } } @keyframes dotTypingBefore { 0%, 60%, 100% { transform: scale(1); opacity: 0.6; } 30% { transform: scale(1.3); opacity: 1; } } @keyframes dotTypingAfter { 0%, 60%, 100% { transform: scale(1); opacity: 0.6; } 30% { transform: scale(1.3); opacity: 1; } } /* Input Bar at the bottom */ .input-bar { padding: 16px; display: flex; align-items: flex-end; /* Align items to bottom for multiline textarea */ background-color: #FFFFFF; /* Match area background */ } .upload-button { background-color: transparent; color: #616161; border: none; border-radius: 50%; width: 42px; height: 42px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; margin-right: 8px; flex-shrink: 0; } .upload-button:hover { background-color: #F5F5F5; color: #2196F3; } .input-container { flex: 1; /* Take remaining space */ display: flex; align-items: flex-end; /* Align textarea and button */ background-color: #F5F5F5; border-radius: 24px; padding: 6px 8px 6px 16px; /* Adjusted padding */ transition: box-shadow 0.3s ease; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 48px; /* Minimum height */ } .input-container:focus-within { box-shadow: 0 0 0 2px #42A5F5; /* Focus outline */ } /* Text Area */ #userInput { flex: 1; /* Take available space */ border: none; background: transparent; padding: 8px 0; /* Vertical padding */ max-height: 120px; /* Limit height before scroll */ resize: none; /* Disable manual resize */ font-family: inherit; font-size: 15px; line-height: 1.4; /* Better line spacing */ outline: none; color: #212121; overflow-y: auto; /* Allow scroll within textarea if needed */ } #userInput::placeholder { color: #9E9E9E; } /* Send Button */ .send-button { background-color: #2196F3; color: white; border: none; border-radius: 50%; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; margin-left: 8px; flex-shrink: 0; /* Prevent shrinking */ } .send-button:hover { background-color: #1976D2; transform: scale(1.05); } .send-button:disabled { background-color: #BDBDBD; cursor: not-allowed; transform: none; opacity: 0.7; } /* Overlay when side nav is open on mobile */ .overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 999; /* Below side nav, above content */ } .overlay.active { display: block; } /* Responsive adjustments */ /* Desktop styles */ @media (min-width: 992px) { .side-nav { position: relative; /* Static position in flex layout */ left: 0; width: 280px; box-shadow: none; /* No shadow needed if static */ } .main-content { /* width: calc(100% - 280px); Not needed with flex: 1 */ left: 0 !important; /* Ensure it's not shifted */ } .menu-button { display: none; /* Hide hamburger on desktop */ } .overlay { display: none !important; /* Never show overlay on desktop */ } } /* Tablet and Mobile styles */ @media (max-width: 991px) { /* Keep side nav absolute/hidden by default */ /* .main-content.nav-open style handles the shift */ } @media (max-width: 768px) { /* Small tablets and large phones */ .message-bubble { max-width: 85%; } .suggestion-bubbles { max-width: 100%; } .welcome-logo { width: 56px; height: 56px; } .welcome-logo i { font-size: 28px; } .welcome-header h2 { font-size: 24px; } } @media (max-width: 480px) { /* Mobile phones */ .side-nav { width: 85%; /* Make nav wider on small screens */ } .message-bubble { max-width: 90%; padding: 12px 16px; /* Slightly smaller padding */ } .chat-window { padding: 12px; /* Less padding */ } .input-bar { padding: 12px 8px; /* Less padding */ } .input-container { padding: 6px 8px 6px 12px; /* Adjust padding */ min-height: 44px; } #userInput { font-size: 14px; } .top-bar { padding: 10px 12px; height: 56px; /* Slightly shorter */ } .top-bar h1 { font-size: 18px; } .menu-button { margin-right: 12px; } .welcome-header h2 { font-size: 22px; } .welcome-subtitle { font-size: 14px; } .suggestion-bubble { padding: 12px; } .suggestion-bubble i { font-size: 18px; margin-right: 12px; } .suggestion-bubble span { font-size: 14px; } /* Ensure welcome container content is centered but allows scroll */ .welcome-container { justify-content: flex-start; /* Align to top */ padding-top: 40px; /* Add some top padding */ height: auto; /* Allow it to take content height */ min-height: 100%; /* Ensure it tries to fill if content is short */ } }