/* Ivy's Local Mind 🌿 — Elysia Suite * Run LLMs locally in your browser with WebGPU * Made with 💚 by Ivy */ /* ============================================ CUSTOM SCROLLBARS — Ivy Style 🌿 ============================================ */ /* Webkit browsers (Chrome, Safari, Edge) */ ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: var(--bg-secondary); border-radius: 5px; } ::-webkit-scrollbar-thumb { background: var(--border-secondary); border-radius: 5px; border: 2px solid var(--bg-secondary); transition: background 0.2s ease; } ::-webkit-scrollbar-thumb:hover { background: var(--accent-primary); } ::-webkit-scrollbar-thumb:active { background: var(--accent-secondary); } ::-webkit-scrollbar-corner { background: var(--bg-secondary); } /* Firefox */ * { scrollbar-width: thin; scrollbar-color: var(--border-secondary) var(--bg-secondary); } /* Thin scrollbar variant for smaller elements */ .thin-scrollbar::-webkit-scrollbar { width: 6px; height: 6px; } .thin-scrollbar::-webkit-scrollbar-thumb { border: 1px solid var(--bg-secondary); } /* ============================================ CSS CUSTOM PROPERTIES ============================================ */ :root { /* Dark theme with Ivy Green accents */ --bg-primary: #0a0e1a; --bg-secondary: #131826; --bg-tertiary: #1a1f35; --bg-quaternary: #242b42; --text-primary: #ffffff; --text-secondary: #b8c2cc; --text-muted: #6b7785; /* Ivy Green theme! 🌿 */ --accent-primary: #22c55e; --accent-secondary: #16a34a; --accent-success: #10b981; --accent-warning: #f59e0b; --accent-danger: #ef4444; --border-primary: #2d3748; --border-secondary: #4a5568; --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3); --shadow-md: 0 8px 25px rgba(0, 0, 0, 0.4); --shadow-lg: 0 25px 50px rgba(0, 0, 0, 0.5); --gradient-primary: linear-gradient(135deg, #22c55e 0%, #16a34a 100%); --gradient-accent: linear-gradient(135deg, #22c55e 0%, #10b981 100%); --gradient-success: linear-gradient(135deg, #10b981 0%, #059669 100%); --border-radius-sm: 8px; --border-radius-md: 12px; --border-radius-lg: 16px; --border-radius-xl: 24px; --transition-fast: 0.15s ease-out; --transition-normal: 0.3s ease-out; --transition-slow: 0.5s ease-out; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: var(--bg-primary); color: var(--text-primary); min-height: 100vh; padding: 20px; line-height: 1.6; overflow-x: hidden; } /* Animations globales */ @keyframes slideInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } @keyframes shimmer { 0% { background-position: -1000px 0; } 100% { background-position: 1000px 0; } } .container { max-width: 1400px; margin: 0 auto; background: var(--bg-secondary); border-radius: var(--border-radius-xl); box-shadow: var(--shadow-lg); overflow: hidden; animation: slideInUp 0.6s ease-out; border: 1px solid var(--border-primary); } .header { background: var(--gradient-primary); background-size: 400% 400%; animation: gradientShift 8s ease infinite; padding: 32px; text-align: center; position: relative; overflow: hidden; } @keyframes gradientShift { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .header::before { content: ""; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%); animation: pulse 4s ease-in-out infinite; } .header h1 { font-size: 2.5em; font-weight: 700; margin: 0; position: relative; z-index: 1; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); display: flex; align-items: center; justify-content: center; gap: 12px; } .controls { padding: 32px; background: var(--bg-tertiary); border-bottom: 1px solid var(--border-primary); } .control-group { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; margin-bottom: 24px; padding: 20px; background: var(--bg-quaternary); border-radius: var(--border-radius-md); border: 1px solid var(--border-primary); transition: var(--transition-normal); } /* For model action buttons: keep on one line */ #online-model-group { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; } #load-model-btn, #model-info-btn { flex: 0 0 auto; min-width: 120px; margin: 0; white-space: nowrap; } /* Quantization filter group */ #quant-filter-group { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; padding: 16px 20px; margin-bottom: 16px; } #quant-filter-group label { min-width: auto; } #quant-filter { padding: 8px 12px; border-radius: var(--border-radius-sm); background: var(--bg-secondary); border: 1px solid var(--border-primary); color: var(--text-primary); font-size: 0.9rem; cursor: pointer; transition: var(--transition-fast); } #quant-filter:hover { border-color: var(--accent-primary); } #quant-filter:focus { outline: none; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.2); } .quant-hint { font-size: 0.8rem; color: var(--accent-warning); opacity: 0.9; } .control-group:hover { border-color: var(--accent-primary); box-shadow: var(--shadow-sm); } .control-group:last-child { margin-bottom: 0; } .control-group label { font-weight: 600; min-width: 140px; color: var(--text-secondary); display: flex; align-items: center; gap: 8px; } .control-group label i { color: var(--accent-primary); transition: var(--transition-normal); } /* Couleurs spécifiques pour les icônes de chaque slider */ .sliders-grid .control-group:nth-child(1) label i { color: #ff6b6b; text-shadow: 0 0 8px rgba(255, 107, 107, 0.3); } .sliders-grid .control-group:nth-child(2) label i { color: #4ecdc4; text-shadow: 0 0 8px rgba(78, 205, 196, 0.3); } .sliders-grid .control-group:nth-child(3) label i { color: #ffd93d; text-shadow: 0 0 8px rgba(255, 217, 61, 0.3); } .sliders-grid .control-group:nth-child(4) label i { color: #a855f7; text-shadow: 0 0 8px rgba(168, 85, 247, 0.3); } .control-group:hover label i { transform: scale(1.1); filter: brightness(1.2); } /* Select moderne */ select { background: var(--bg-secondary); color: var(--text-primary); border: 2px solid var(--border-primary); border-radius: var(--border-radius-sm); padding: 14px 40px 14px 16px; font-size: 14px; font-weight: 500; transition: var(--transition-normal); min-width: 280px; cursor: pointer; background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236366f1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right 12px center; background-size: 20px; appearance: none; } select:focus { outline: none; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } select:hover { border-color: var(--accent-secondary); } /* 🆕 Champ de recherche pour les modèles */ .model-search { background: var(--bg-secondary); color: var(--text-primary); border: 2px solid var(--border-primary); border-radius: var(--border-radius-sm); padding: 10px 16px; font-size: 13px; font-weight: 400; transition: var(--transition-normal); width: 100%; margin-bottom: 8px; } .model-search:focus { outline: none; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } .model-search::placeholder { color: var(--text-muted); } /* Grille pour les sliders — 2x2 grid */ .sliders-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 24px; } /* Amélioration visuelle pour les control-groups dans la grille */ .sliders-grid .control-group { margin-bottom: 0; } /* Sliders modernes */ .slider-container { display: flex; align-items: center; gap: 16px; flex: 1; min-width: 200px; position: relative; } /* Wrapper pour créer l'effet de progression */ .slider-wrapper { position: relative; flex: 1; height: 12px; border-radius: 8px; overflow: hidden; background: linear-gradient(90deg, var(--bg-secondary) 0%, var(--border-primary) 100%); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3); } .slider-progress { position: absolute; top: 0; left: 0; height: 100%; border-radius: 8px; transition: all var(--transition-normal); z-index: 1; } .sliders-grid .control-group:nth-child(1) .slider-progress { background: linear-gradient(90deg, #ff6b6b 0%, #ff8e8e 100%); box-shadow: 0 0 12px rgba(255, 107, 107, 0.3); } .sliders-grid .control-group:nth-child(2) .slider-progress { background: linear-gradient(90deg, #4ecdc4 0%, #81e6df 100%); box-shadow: 0 0 12px rgba(78, 205, 196, 0.3); } .sliders-grid .control-group:nth-child(3) .slider-progress { background: linear-gradient(90deg, #ffd93d 0%, #ffe066 100%); box-shadow: 0 0 12px rgba(255, 217, 61, 0.3); } .sliders-grid .control-group:nth-child(4) .slider-progress { background: linear-gradient(90deg, #a855f7 0%, #c084fc 100%); box-shadow: 0 0 12px rgba(168, 85, 247, 0.3); } .slider-container input[type="range"] { flex: 1; height: 12px; background: linear-gradient(90deg, var(--bg-secondary) 0%, var(--border-primary) 100%); border-radius: 8px; outline: none; border: none; cursor: pointer; transition: var(--transition-normal); position: relative; box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3); z-index: 2; background: transparent; width: 100%; } .slider-container input[type="range"]:hover { transform: scaleY(1.1); } .slider-container:hover .slider-progress { filter: brightness(1.2); box-shadow: 0 0 20px rgba(99, 102, 241, 0.4); } .sliders-grid .control-group:nth-child(1):hover .slider-progress { box-shadow: 0 0 20px rgba(255, 107, 107, 0.5); } .sliders-grid .control-group:nth-child(2):hover .slider-progress { box-shadow: 0 0 20px rgba(78, 205, 196, 0.5); } .sliders-grid .control-group:nth-child(3):hover .slider-progress { box-shadow: 0 0 20px rgba(255, 217, 61, 0.5); } .sliders-grid .control-group:nth-child(4):hover .slider-progress { box-shadow: 0 0 20px rgba(168, 85, 247, 0.5); } .slider-container input[type="range"]::-webkit-slider-thumb { appearance: none; width: 28px; height: 28px; background: var(--gradient-accent); border-radius: 50%; cursor: pointer; box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3); transition: all var(--transition-fast); border: 3px solid rgba(255, 255, 255, 0.2); position: relative; } .slider-container input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.2); box-shadow: 0 6px 20px rgba(99, 102, 241, 0.6), 0 4px 8px rgba(0, 0, 0, 0.4); border-color: rgba(255, 255, 255, 0.4); } .slider-container input[type="range"]::-webkit-slider-thumb:active { transform: scale(1.1); box-shadow: 0 2px 8px rgba(99, 102, 241, 0.8); } .slider-container input[type="range"]::-moz-range-thumb { width: 28px; height: 28px; background: var(--gradient-accent); border-radius: 50%; cursor: pointer; border: 3px solid rgba(255, 255, 255, 0.2); box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3); transition: all var(--transition-fast); } .slider-container input[type="range"]::-moz-range-thumb:hover { transform: scale(1.2); box-shadow: 0 6px 20px rgba(99, 102, 241, 0.6), 0 4px 8px rgba(0, 0, 0, 0.4); border-color: rgba(255, 255, 255, 0.4); } /* Styles pour Firefox */ .slider-container input[type="range"]::-moz-range-track { height: 12px; background: transparent; border-radius: 8px; border: none; } /* Styles pour WebKit pour rendre la piste transparente */ .slider-container input[type="range"]::-webkit-slider-runnable-track { height: 12px; background: transparent; border-radius: 8px; border: none; } /* Effet de progression colorée pour chaque slider */ .sliders-grid .control-group:nth-child(1) .slider-container input[type="range"]::-webkit-slider-thumb { background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%); box-shadow: 0 4px 12px rgba(255, 107, 107, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3); } .sliders-grid .control-group:nth-child(1) .slider-container input[type="range"]::-webkit-slider-thumb:hover { box-shadow: 0 6px 20px rgba(255, 107, 107, 0.6), 0 4px 8px rgba(0, 0, 0, 0.4); } .sliders-grid .control-group:nth-child(2) .slider-container input[type="range"]::-webkit-slider-thumb { background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%); box-shadow: 0 4px 12px rgba(78, 205, 196, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3); } .sliders-grid .control-group:nth-child(2) .slider-container input[type="range"]::-webkit-slider-thumb:hover { box-shadow: 0 6px 20px rgba(78, 205, 196, 0.6), 0 4px 8px rgba(0, 0, 0, 0.4); } .sliders-grid .control-group:nth-child(3) .slider-container input[type="range"]::-webkit-slider-thumb { background: linear-gradient(135deg, #ffd93d 0%, #ff9800 100%); box-shadow: 0 4px 12px rgba(255, 217, 61, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3); } .sliders-grid .control-group:nth-child(3) .slider-container input[type="range"]::-webkit-slider-thumb:hover { box-shadow: 0 6px 20px rgba(255, 217, 61, 0.6), 0 4px 8px rgba(0, 0, 0, 0.4); } .sliders-grid .control-group:nth-child(4) .slider-container input[type="range"]::-webkit-slider-thumb { background: linear-gradient(135deg, #a855f7 0%, #7c3aed 100%); box-shadow: 0 4px 12px rgba(168, 85, 247, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3); } .sliders-grid .control-group:nth-child(4) .slider-container input[type="range"]::-webkit-slider-thumb:hover { box-shadow: 0 6px 20px rgba(168, 85, 247, 0.6), 0 4px 8px rgba(0, 0, 0, 0.4); } .slider-value { min-width: 80px; text-align: center; font-weight: 700; background: var(--bg-secondary); padding: 12px 16px; border-radius: var(--border-radius-md); border: 2px solid var(--border-primary); color: var(--text-primary); font-family: "JetBrains Mono", "Courier New", monospace; font-size: 14px; transition: all var(--transition-normal); position: relative; overflow: hidden; } .slider-value::before { content: ""; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); transition: var(--transition-normal); } .slider-value:hover::before { left: 100%; } /* Couleurs spécifiques pour chaque valeur de slider */ .sliders-grid .control-group:nth-child(1) .slider-value { border-color: #ff6b6b; color: #ff6b6b; box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.3); animation: pulseTemp 3s infinite; } .sliders-grid .control-group:nth-child(2) .slider-value { border-color: #4ecdc4; color: #4ecdc4; box-shadow: 0 0 0 0 rgba(78, 205, 196, 0.3); animation: pulseTokens 3s infinite 0.5s; } .sliders-grid .control-group:nth-child(3) .slider-value { border-color: #ffd93d; color: #ffd93d; box-shadow: 0 0 0 0 rgba(255, 217, 61, 0.3); animation: pulseTopP 3s infinite 1s; } .sliders-grid .control-group:nth-child(4) .slider-value { border-color: #a855f7; color: #a855f7; box-shadow: 0 0 0 0 rgba(168, 85, 247, 0.3); animation: pulseTopK 3s infinite 1.5s; } @keyframes pulseTemp { 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.3); } 50% { box-shadow: 0 0 0 8px rgba(255, 107, 107, 0); transform: scale(1.05); } } @keyframes pulseTokens { 0%, 100% { box-shadow: 0 0 0 0 rgba(78, 205, 196, 0.3); } 50% { box-shadow: 0 0 0 8px rgba(78, 205, 196, 0); transform: scale(1.05); } } @keyframes pulseTopP { 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 217, 61, 0.3); } 50% { box-shadow: 0 0 0 8px rgba(255, 217, 61, 0); transform: scale(1.05); } } @keyframes pulseTopK { 0%, 100% { box-shadow: 0 0 0 0 rgba(168, 85, 247, 0.3); } 50% { box-shadow: 0 0 0 8px rgba(168, 85, 247, 0); transform: scale(1.05); } } /* Chat container */ #chat-container { height: 600px; overflow-y: auto; padding: 32px; background: var(--bg-primary); position: relative; border-top: 1px solid var(--border-primary); border-bottom: 1px solid var(--border-primary); } #chat-container::-webkit-scrollbar { width: 8px; } #chat-container::-webkit-scrollbar-track { background: var(--bg-secondary); border-radius: 4px; } #chat-container::-webkit-scrollbar-thumb { background: var(--border-secondary); border-radius: 4px; } #chat-container::-webkit-scrollbar-thumb:hover { background: var(--accent-primary); } /* Status bar */ #status { padding: 16px 32px; background: var(--bg-quaternary); border: 1px solid var(--border-primary); display: flex; align-items: center; gap: 12px; font-weight: 500; transition: var(--transition-normal); } .status-indicator { width: 12px; height: 12px; border-radius: 50%; background: var(--accent-warning); box-shadow: 0 0 8px rgba(245, 158, 11, 0.5); animation: pulse 2s infinite; } .status-indicator.ready { background: var(--accent-success); box-shadow: 0 0 8px rgba(16, 185, 129, 0.5); animation: none; } .status-indicator.error { background: var(--accent-danger); box-shadow: 0 0 8px rgba(239, 68, 68, 0.5); animation: none; } .status-indicator.loading { background: var(--accent-primary); box-shadow: 0 0 8px rgba(99, 102, 241, 0.5); animation: pulse 1s infinite; } .status-indicator.warning { background: var(--accent-warning); box-shadow: 0 0 8px rgba(245, 158, 11, 0.5); animation: none; } /* Messages */ .message { margin-bottom: 24px; padding: 20px 24px; border-radius: var(--border-radius-lg); max-width: 85%; position: relative; animation: fadeIn 0.4s ease-out; box-shadow: var(--shadow-sm); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); transition: var(--transition-normal); } .message:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } .message.user { background: var(--gradient-accent); color: white; margin-left: auto; border-bottom-right-radius: 8px; } .message.user::before { content: ""; position: absolute; bottom: -1px; right: -1px; width: 0; height: 0; border: 8px solid transparent; border-top-color: var(--accent-secondary); } .message.assistant { background: var(--bg-tertiary); border: 1px solid var(--border-primary); border-bottom-left-radius: 8px; margin-right: auto; } .message.assistant::before { content: ""; position: absolute; bottom: -1px; left: -1px; width: 0; height: 0; border: 8px solid transparent; border-top-color: var(--bg-tertiary); } .message.error { background: rgba(239, 68, 68, 0.1); border: 1px solid var(--accent-danger); color: #fecaca; } .message.system { background: rgba(245, 158, 11, 0.1); border: 1px solid var(--accent-warning); color: #fbbf24; margin-left: auto; margin-right: auto; max-width: 90%; } .message-header { font-weight: 600; margin-bottom: 8px; font-size: 0.9em; opacity: 0.9; display: flex; align-items: center; gap: 8px; } .message-header i { font-size: 1.1em; } .message.user .message-header i { color: rgba(255, 255, 255, 0.8); } .message.assistant .message-header i { color: var(--accent-primary); } .message.error .message-header i { color: var(--accent-danger); } .message.system .message-header i { color: var(--accent-warning); } .message-content { line-height: 1.6; word-wrap: break-word; } .message-time { font-size: 0.8em; opacity: 0.7; margin-top: 8px; font-weight: 400; } .loading { color: var(--text-muted); font-style: italic; position: relative; display: flex; align-items: center; gap: 8px; } .loading::after { content: ""; display: inline-block; width: 20px; height: 20px; border: 2px solid var(--border-primary); border-radius: 50%; border-top-color: var(--accent-primary); animation: spin 1s ease-in-out infinite; } /* Animation de typing pour les messages en cours */ .typing-indicator { display: inline-flex; align-items: center; gap: 4px; } .typing-indicator span { width: 8px; height: 8px; border-radius: 50%; background: var(--accent-primary); animation: typing 1.4s infinite ease-in-out; } .typing-indicator span:nth-child(1) { animation-delay: 0s; } .typing-indicator span:nth-child(2) { animation-delay: 0.2s; } .typing-indicator span:nth-child(3) { animation-delay: 0.4s; } @keyframes typing { 0%, 60%, 100% { transform: scale(0.8); opacity: 0.5; } 30% { transform: scale(1); opacity: 1; } } @keyframes spin { to { transform: rotate(360deg); } } /* Action buttons section */ .action-buttons { display: flex; justify-content: center; gap: 16px; padding: 20px; background: var(--bg-quaternary); border-radius: var(--border-radius-md); border: 1px solid var(--border-primary); margin-top: 24px; } .action-buttons .btn-secondary { min-width: 140px; padding: 12px 20px; font-size: 13px; font-weight: 500; transition: all var(--transition-normal); } .action-buttons .btn-secondary:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--shadow-sm); } /* Input container moderne avec bouton intégré */ #input-container { padding: 32px; background: var(--bg-tertiary); border-top: 1px solid var(--border-primary); } .input-wrapper { position: relative; display: flex; align-items: stretch; background: var(--bg-secondary); border: 2px solid var(--border-primary); border-radius: var(--border-radius-lg); transition: var(--transition-normal); overflow: hidden; } .input-wrapper:focus-within { border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } .input-wrapper:hover { border-color: var(--accent-secondary); } #user-input { flex: 1; padding: 16px 20px; border: none; background: transparent; font-size: 16px; resize: none; min-height: 60px; max-height: 200px; color: var(--text-primary); font-family: inherit; line-height: 1.5; outline: none; } #user-input::placeholder { color: var(--text-muted); } .send-button { padding: 12px 20px; background: var(--gradient-accent); color: white; border: none; cursor: pointer; font-weight: 600; font-size: 14px; transition: var(--transition-normal); display: flex; align-items: center; justify-content: center; gap: 8px; min-width: 100px; position: relative; overflow: hidden; font-family: inherit; border-left: 1px solid var(--border-primary); } .send-button::before { content: ""; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); transition: var(--transition-normal); } .send-button:hover::before { left: 100%; } .send-button:hover:not(:disabled) { background: var(--gradient-primary); transform: scale(1.02); } .send-button:active { transform: scale(0.98); } .send-button:disabled { background: var(--bg-quaternary); color: var(--text-muted); cursor: not-allowed; transform: none; border-left-color: var(--border-primary); } /* Animation pour le bouton quand l'input a du contenu */ .input-wrapper.has-content .send-button { background: var(--gradient-success); animation: pulse 2s infinite; } .input-wrapper.has-content .send-button:hover:not(:disabled) { background: var(--gradient-success); animation: none; } /* Boutons modernes */ button { padding: 14px 24px; background: var(--gradient-accent); color: white; border: none; border-radius: var(--border-radius-sm); cursor: pointer; font-weight: 600; font-size: 14px; transition: var(--transition-normal); min-width: 120px; display: flex; align-items: center; justify-content: center; gap: 8px; position: relative; overflow: hidden; font-family: inherit; } button::before { content: ""; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); transition: var(--transition-normal); } button:hover::before { left: 100%; } button:hover:not(:disabled) { transform: translateY(-2px); box-shadow: var(--shadow-md); } button:active { transform: translateY(0); } button:disabled { background: var(--bg-quaternary); color: var(--text-muted); cursor: not-allowed; transform: none; box-shadow: none; } .btn-secondary { background: var(--bg-quaternary); border: 1px solid var(--border-primary); color: var(--text-secondary); font-size: 12px; padding: 10px 16px; min-width: auto; } .btn-secondary:hover:not(:disabled) { background: var(--bg-secondary); border-color: var(--accent-primary); color: var(--text-primary); } /* Stats modernes */ .stats { padding: 20px 32px; background: var(--bg-quaternary); border-top: 1px solid var(--border-primary); display: flex; justify-content: space-between; font-size: 14px; color: var(--text-secondary); flex-wrap: wrap; gap: 16px; } .stats > span { display: flex; align-items: center; gap: 8px; font-weight: 500; } .stats i { color: var(--accent-primary); } /* Modal moderne */ .modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background: rgba(10, 14, 26, 0.8); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); animation: fadeIn 0.3s ease-out; } .modal-content { background: var(--bg-secondary); margin: 5% auto; padding: 32px; border-radius: var(--border-radius-lg); width: 90%; max-width: 700px; max-height: 80vh; overflow-y: auto; box-shadow: var(--shadow-lg); border: 1px solid var(--border-primary); animation: slideInUp 0.4s ease-out; } .close { color: var(--text-muted); float: right; font-size: 32px; font-weight: bold; cursor: pointer; transition: var(--transition-fast); line-height: 1; } .close:hover { color: var(--accent-danger); transform: scale(1.1); } /* Styles pour la sélection de source de modèle */ .model-source-selector { display: flex; gap: 24px; align-items: center; flex-wrap: wrap; } .radio-group { display: flex; gap: 8px; align-items: center; } .radio-group input[type="radio"] { margin: 0; } .radio-group label { min-width: auto !important; margin: 0 !important; cursor: pointer; font-weight: 500; transition: var(--transition-fast); } .radio-group:hover label { color: var(--accent-primary); } /* Styles pour le sélecteur de fichier local */ #local-file-group { display: none; } .local-source-options { display: flex; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; } .file-selector { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; flex: 1; } #file-upload-config { display: none; } #server-base-url, #model-filename { padding: 12px; border: 2px solid var(--border-primary); border-radius: var(--border-radius-sm); background: var(--bg-secondary); color: var(--text-primary); font-family: inherit; transition: var(--transition-normal); } #server-base-url { flex: 2; min-width: 300px; } #model-filename { flex: 1; min-width: 150px; } #server-base-url:focus, #model-filename:focus { outline: none; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } #server-base-url::placeholder, #model-filename::placeholder { color: var(--text-muted); } #local-file-input { display: none; } #selected-file-name { color: var(--text-secondary); font-style: italic; flex: 1; min-width: 200px; padding: 8px 12px; background: var(--bg-secondary); border-radius: var(--border-radius-sm); border: 1px solid var(--border-primary); transition: var(--transition-normal); } #selected-file-name.has-file { color: var(--accent-success); border-color: var(--accent-success); background: rgba(16, 185, 129, 0.1); } /* Animation pour le bouton de chargement local */ #load-local-btn:not(:disabled) { background: var(--gradient-success); animation: pulse 2s infinite; } #load-local-btn:not(:disabled):hover { animation: none; background: var(--gradient-success); filter: brightness(1.1); } @media (max-width: 768px) { body { padding: 10px; } .container { margin: 0; border-radius: var(--border-radius-md); } .header h1 { font-size: 1.8em; flex-direction: column; gap: 8px; } .controls { padding: 20px; } .control-group { flex-direction: column; align-items: stretch; gap: 12px; } .control-group label { min-width: auto; text-align: center; } .sliders-grid { grid-template-columns: 1fr; gap: 16px; } .sliders-grid .control-group:nth-child(3) { grid-column: 1; } .model-source-selector { flex-direction: column; gap: 16px; } .local-source-options { flex-direction: column; } .file-selector { flex-direction: column; gap: 12px; } #server-base-url, #model-filename { min-width: auto; width: 100%; } select { min-width: auto; width: 100%; } .action-buttons { flex-wrap: wrap; gap: 12px; } .action-buttons .btn-secondary { min-width: auto; flex: 1; } #chat-container { height: 400px; padding: 20px; } .message { max-width: 95%; margin-left: 0 !important; margin-right: 0 !important; } .message.user { margin-left: 5% !important; } .message.assistant { margin-right: 5% !important; } #input-container { padding: 20px; } .input-wrapper { flex-direction: column; } .send-button { border-left: none; border-top: 1px solid var(--border-primary); border-radius: 0 0 var(--border-radius-lg) var(--border-radius-lg); min-height: 50px; } #user-input { border-radius: var(--border-radius-lg) var(--border-radius-lg) 0 0; } .stats { flex-direction: row; flex-wrap: wrap; gap: 16px; justify-content: center; text-align: center; } .modal-content { margin: 2% auto; width: 95%; max-width: none; } } /* === IVY BRANDING === */ .subtitle { font-size: 1.1em; font-weight: 400; opacity: 0.9; margin-top: 8px; position: relative; z-index: 1; } /* Footer integrated inside container */ .footer-integrated { padding: 24px 32px; text-align: center; font-size: 0.9em; color: var(--text-secondary); position: relative; background: linear-gradient(180deg, var(--bg-quaternary) 0%, var(--bg-tertiary) 100%); border-radius: 0 0 var(--border-radius-xl) var(--border-radius-xl); } /* Decorative separator line */ .footer-integrated::before { content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 60%; height: 1px; background: linear-gradient( 90deg, transparent 0%, var(--accent-primary) 20%, var(--accent-primary) 80%, transparent 100% ); opacity: 0.5; } .footer-integrated p { margin: 0; line-height: 1.8; } .footer-integrated .copyright { margin-top: 8px; font-size: 0.85em; opacity: 0.6; } .footer-integrated a { color: var(--accent-primary); text-decoration: none; transition: var(--transition-fast); } .footer-integrated a:hover { color: var(--text-primary); text-decoration: underline; } .footer-integrated .divider { margin: 0 12px; opacity: 0.4; color: var(--accent-primary); } /* Old footer class (kept for backwards compatibility) */ .footer { background: var(--bg-tertiary); padding: 20px 32px; text-align: center; border-top: 1px solid var(--border-primary); font-size: 0.9em; color: var(--text-secondary); } .footer a { color: var(--accent-primary); text-decoration: none; transition: var(--transition-fast); } .footer a:hover { color: var(--text-primary); text-decoration: underline; } .footer .divider { margin: 0 12px; opacity: 0.5; } .footer .heart { color: var(--accent-primary); } /* === ABOUT MODAL === */ .about-modal-content { max-width: 600px; } .about-header { text-align: center; margin-bottom: 24px; padding-bottom: 16px; border-bottom: 1px solid var(--border-primary); } .about-header h2 { color: var(--accent-primary); font-size: 1.8em; margin: 0; } .about-section { margin-bottom: 24px; } .about-section h3 { color: var(--text-primary); font-size: 1.1em; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; } .about-section p { color: var(--text-secondary); line-height: 1.6; } .features-list { list-style: none; padding: 0; margin: 0; } .features-list li { padding: 8px 0; color: var(--text-secondary); border-bottom: 1px solid var(--border-primary); } .features-list li:last-child { border-bottom: none; } .family-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; text-align: center; } .family-member { background: var(--bg-quaternary); padding: 16px 8px; border-radius: var(--border-radius-md); border: 1px solid var(--border-primary); transition: var(--transition-fast); } .family-member:hover { border-color: var(--accent-primary); transform: translateY(-2px); } .family-member small { color: var(--text-muted); font-size: 0.85em; } .links-grid { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; } .link-btn { display: inline-flex; align-items: center; gap: 8px; padding: 10px 20px; background: var(--bg-quaternary); color: var(--text-primary); text-decoration: none; border-radius: var(--border-radius-md); border: 1px solid var(--border-primary); transition: var(--transition-fast); } .link-btn:hover { background: var(--accent-primary); border-color: var(--accent-primary); transform: translateY(-2px); } .about-quote { background: var(--bg-quaternary); padding: 20px; border-radius: var(--border-radius-md); border-left: 4px solid var(--accent-primary); margin: 24px 0; } .about-quote blockquote { margin: 0; font-style: italic; color: var(--text-secondary); line-height: 1.6; } .about-quote footer { margin-top: 12px; color: var(--text-muted); font-size: 0.9em; text-align: right; } .about-footer { text-align: center; padding-top: 16px; border-top: 1px solid var(--border-primary); color: var(--text-muted); font-size: 0.9em; } @media (max-width: 600px) { .family-grid { grid-template-columns: repeat(2, 1fr); } .links-grid { flex-direction: column; } .link-btn { justify-content: center; } }