/* ═══════════════════════════════════════════════════════════════════════════ OpenFang Components — Premium Glassmorphism Design System ═══════════════════════════════════════════════════════════════════════════ Design Philosophy: - Glassmorphism with frosted glass effects - Soft shadows with colored glow accents - Spring animations for premium feel - WCAG AAA accessibility compliance ═══════════════════════════════════════════════════════════════════════════ */ /* ═══════════════════════════════════════════════════════════════════════════ BUTTONS — Premium tactile interactions ═══════════════════════════════════════════════════════════════════════════ */ .btn { padding: 10px 18px; border: none; border-radius: var(--radius-md); cursor: pointer; font-family: var(--font-sans); font-size: 13px; font-weight: 600; letter-spacing: -0.01em; transition: transform var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-fast), border-color var(--transition-fast); display: inline-flex; align-items: center; justify-content: center; gap: 8px; white-space: nowrap; position: relative; overflow: hidden; } /* Ripple effect container */ .btn::before { content: ''; position: absolute; inset: 0; background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, transparent 70%); transform: scale(0); opacity: 0; transition: transform 0.5s, opacity 0.3s; } .btn:active::before { transform: scale(2.5); opacity: 1; transition: transform 0s, opacity 0s; } .btn:active { transform: scale(0.97); } .btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none !important; } .btn:disabled::before { display: none; } /* Primary button — Accent gradient */ .btn-primary { background: var(--gradient-accent); color: var(--text-on-accent); box-shadow: var(--shadow-sm), var(--shadow-accent); text-shadow: 0 1px 1px rgba(0,0,0,0.1); } .btn-primary:hover:not(:disabled) { box-shadow: var(--shadow-md), var(--shadow-accent); transform: translateY(-2px); filter: brightness(1.05); } .btn-primary:active:not(:disabled) { transform: translateY(0) scale(0.98); box-shadow: var(--shadow-sm), var(--shadow-accent); } /* Success button */ .btn-success { background: var(--gradient-success); color: #FFFFFF; box-shadow: var(--shadow-sm), var(--shadow-success); } .btn-success:hover:not(:disabled) { box-shadow: var(--shadow-md), var(--shadow-success); transform: translateY(-2px); filter: brightness(1.05); } /* Danger button */ .btn-danger { background: var(--error); color: #FFFFFF; box-shadow: var(--shadow-sm), var(--shadow-error); } .btn-danger:hover:not(:disabled) { background: var(--error-hover); box-shadow: var(--shadow-md), var(--shadow-error); transform: translateY(-2px); } /* Ghost button — Glass effect */ .btn-ghost { background: var(--surface-glass); backdrop-filter: blur(var(--glass-blur-subtle)); -webkit-backdrop-filter: blur(var(--glass-blur-subtle)); color: var(--text-secondary); border: 1px solid var(--border); box-shadow: var(--shadow-xs); } .btn-ghost:hover:not(:disabled) { background: var(--surface2); color: var(--text); border-color: var(--border-strong); transform: translateY(-1px); box-shadow: var(--shadow-sm); } /* Button sizes */ .btn-sm { padding: 6px 12px; font-size: 12px; border-radius: var(--radius-sm); } .btn-xs { padding: 4px 8px; font-size: 11px; border-radius: var(--radius-xs); } .btn-lg { padding: 14px 24px; font-size: 15px; border-radius: var(--radius-lg); } .btn-block { width: 100%; } /* Icon-only button */ .btn-icon { padding: 10px; width: 40px; height: 40px; } .btn-icon.btn-sm { width: 32px; height: 32px; padding: 6px; } /* ═══════════════════════════════════════════════════════════════════════════ CARDS — Glassmorphism containers ═══════════════════════════════════════════════════════════════════════════ */ .card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-xl); padding: var(--card-padding); position: relative; transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast); } /* Glass card variant */ .card-glass { background: var(--glass-bg); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); } /* Card with accent border */ .card-accent { border-left: 3px solid var(--accent); } .card-accent-success { border-left-color: var(--success); } .card-accent-error { border-left-color: var(--error); } .card-accent-info { border-left-color: var(--info); } /* Interactive card */ .card-interactive { cursor: pointer; } .card-interactive:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--border-strong); } /* Card header */ .card-header { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 12px; display: flex; align-items: center; gap: 8px; } /* Card shine effect on hover */ .card-shine { overflow: hidden; } .card-shine::after { content: ''; position: absolute; inset: 0; background: var(--gradient-card-shine); background-size: 200% 100%; opacity: 0; transition: opacity 0.3s; pointer-events: none; } .card-shine:hover::after { opacity: 1; animation: shimmer 1s ease-out; } /* ═══════════════════════════════════════════════════════════════════════════ STAT CARDS — Metrics display ═══════════════════════════════════════════════════════════════════════════ */ .stats-row { display: flex; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; } .stats-row-lg { gap: 20px; } .stat-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 16px 20px; flex: 1; min-width: 120px; position: relative; overflow: hidden; transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast); } .stat-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } /* Stat card with glass effect */ .stat-card-glass { background: var(--glass-bg); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); } /* Large stat card */ .stat-card-lg { padding: 20px 24px; border-radius: var(--radius-xl); } .stat-value { font-family: var(--font-mono); font-size: 26px; font-weight: 700; color: var(--text); line-height: 1.2; letter-spacing: -0.02em; } .stat-value-success { color: var(--success); } .stat-value-accent { color: var(--accent); } .stat-label { font-size: 12px; color: var(--text-dim); margin-top: 4px; font-weight: 500; } /* Stat card glow effect */ .stat-card-glow { position: relative; } .stat-card-glow::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 1px; background: linear-gradient(90deg, transparent, var(--accent-glow), transparent); opacity: 0; transition: opacity 0.3s; } .stat-card-glow:hover::before { opacity: 1; } /* ═══════════════════════════════════════════════════════════════════════════ BADGES — Status indicators ═══════════════════════════════════════════════════════════════════════════ */ .badge { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: var(--radius-full); font-size: 11px; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; white-space: nowrap; transition: all var(--transition-fast); } /* Badge variants */ .badge-running { background: var(--success-subtle); color: var(--success); border: 1px solid rgba(34, 197, 94, 0.2); } .badge-suspended { background: var(--warning-subtle); color: var(--warning); border: 1px solid rgba(245, 158, 11, 0.2); } .badge-crashed, .badge-error { background: var(--error-subtle); color: var(--error); border: 1px solid rgba(239, 68, 68, 0.2); } .badge-idle, .badge-dim { background: var(--surface2); color: var(--text-dim); border: 1px solid var(--border); } .badge-info { background: var(--info-subtle); color: var(--info); border: 1px solid rgba(59, 130, 246, 0.2); } .badge-success { background: var(--success-subtle); color: var(--success-dim); border: 1px solid rgba(34, 197, 94, 0.2); } .badge-warning { background: var(--warning-subtle); color: var(--warning-dim); border: 1px solid rgba(245, 158, 11, 0.2); } /* Accent badge */ .badge-accent { background: var(--accent-subtle); color: var(--accent); border: 1px solid rgba(255, 92, 0, 0.2); } /* Badge with glow */ .badge-glow { box-shadow: 0 0 12px currentColor; } /* ═══════════════════════════════════════════════════════════════════════════ FORM ELEMENTS — Modern inputs ═══════════════════════════════════════════════════════════════════════════ */ .form-input, .form-select, .form-textarea { width: 100%; padding: 12px 16px; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface); color: var(--text); font-family: var(--font-sans); font-size: 14px; transition: border-color var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-fast); } .form-input:hover, .form-select:hover, .form-textarea:hover { border-color: var(--border-strong); } .form-input:focus, .form-select:focus, .form-textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); } .form-input::placeholder, .form-textarea::placeholder { color: var(--text-muted); } /* Input with icon */ .form-input-icon { position: relative; } .form-input-icon .form-input { padding-left: 40px; } .form-input-icon svg { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--text-muted); pointer-events: none; } /* Input group */ .input-group { display: flex; gap: 0; } .input-group .form-input, .input-group .btn { border-radius: 0; } .input-group .form-input:first-child, .input-group .btn:first-child { border-top-left-radius: var(--radius-md); border-bottom-left-radius: var(--radius-md); } .input-group .form-input:last-child, .input-group .btn:last-child { border-top-right-radius: var(--radius-md); border-bottom-right-radius: var(--radius-md); } /* Form label */ .form-label { display: block; font-size: 13px; font-weight: 500; color: var(--text-secondary); margin-bottom: 6px; } /* Form helper text */ .form-helper { font-size: 12px; color: var(--text-muted); margin-top: 4px; } /* Form error state */ .form-error .form-input, .form-error .form-select, .form-error .form-textarea { border-color: var(--error); } .form-error-text { font-size: 12px; color: var(--error); margin-top: 4px; } /* ═══════════════════════════════════════════════════════════════════════════ TOGGLE SWITCHES ═══════════════════════════════════════════════════════════════════════════ */ .toggle { position: relative; width: 44px; height: 24px; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-full); cursor: pointer; transition: all var(--transition-fast); } .toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; background: var(--text-dim); border-radius: 50%; transition: all var(--transition-fast); box-shadow: var(--shadow-sm); } .toggle.active { background: var(--accent); border-color: var(--accent); } .toggle.active::after { left: 22px; background: #FFFFFF; } /* ═══════════════════════════════════════════════════════════════════════════ MODALS — Glass overlay dialogs ═══════════════════════════════════════════════════════════════════════════ */ .modal-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); z-index: var(--z-modal-backdrop); display: flex; align-items: center; justify-content: center; padding: 20px; animation: fadeIn 0.2s ease; } .modal { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-2xl); padding: 24px; max-width: 500px; width: 100%; max-height: calc(100vh - 40px); overflow-y: auto; box-shadow: var(--shadow-2xl); animation: springIn 0.4s var(--ease-spring); position: relative; z-index: var(--z-modal); } .modal-glass { background: var(--glass-bg-strong); backdrop-filter: blur(var(--glass-blur-strong)); -webkit-backdrop-filter: blur(var(--glass-blur-strong)); border: 1px solid var(--glass-border); } .modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; } .modal-title { font-size: 18px; font-weight: 600; color: var(--text); } .modal-close { background: transparent; border: none; color: var(--text-dim); cursor: pointer; padding: 4px; border-radius: var(--radius-sm); transition: all var(--transition-fast); } .modal-close:hover { color: var(--text); background: var(--surface2); } .modal-footer { display: flex; gap: 12px; justify-content: flex-end; margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--border); } /* ═══════════════════════════════════════════════════════════════════════════ TOASTS — Notification messages ═══════════════════════════════════════════════════════════════════════════ */ .toast-container { position: fixed; bottom: 24px; right: 24px; z-index: var(--z-toast); display: flex; flex-direction: column; gap: 12px; } .toast { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px 20px; box-shadow: var(--shadow-lg); display: flex; align-items: center; gap: 12px; animation: slideLeft 0.4s var(--ease-spring); min-width: 280px; max-width: 400px; } .toast-glass { background: var(--glass-bg-strong); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); } .toast-success { border-left: 3px solid var(--success); } .toast-error { border-left: 3px solid var(--error); } .toast-warning { border-left: 3px solid var(--warning); } .toast-info { border-left: 3px solid var(--info); } /* ═══════════════════════════════════════════════════════════════════════════ TABS — Navigation tabs ═══════════════════════════════════════════════════════════════════════════ */ .tabs { display: flex; gap: 4px; background: var(--surface2); padding: 4px; border-radius: var(--radius-lg); border: 1px solid var(--border); } .tab { padding: 10px 18px; border-radius: var(--radius-md); font-size: 13px; font-weight: 500; color: var(--text-dim); cursor: pointer; transition: all var(--transition-fast); border: none; background: transparent; } .tab:hover { color: var(--text); } .tab.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); } /* ═══════════════════════════════════════════════════════════════════════════ TOOLTIPS ═══════════════════════════════════════════════════════════════════════════ */ .tooltip { position: relative; } .tooltip::after { content: attr(data-tooltip); position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%) translateY(4px); background: var(--text); color: var(--bg-primary); padding: 6px 12px; border-radius: var(--radius-sm); font-size: 12px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transition: all var(--transition-fast); z-index: var(--z-tooltip); box-shadow: var(--shadow-md); } .tooltip:hover::after { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); } /* ═══════════════════════════════════════════════════════════════════════════ DROPDOWNS ═══════════════════════════════════════════════════════════════════════════ */ .dropdown { position: relative; display: inline-block; } .dropdown-menu { position: absolute; top: calc(100% + 4px); left: 0; min-width: 180px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: 6px; z-index: var(--z-dropdown); animation: slideDown 0.2s var(--ease-smooth); } .dropdown-menu-glass { background: var(--glass-bg-strong); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); } .dropdown-item { padding: 10px 14px; border-radius: var(--radius-md); font-size: 13px; color: var(--text-secondary); cursor: pointer; transition: all var(--transition-fast); display: flex; align-items: center; gap: 10px; } .dropdown-item:hover { background: var(--surface2); color: var(--text); } .dropdown-divider { height: 1px; background: var(--border); margin: 6px 0; } /* ═══════════════════════════════════════════════════════════════════════════ DETAIL GRID — Key-value displays ═══════════════════════════════════════════════════════════════════════════ */ .detail-grid { display: flex; flex-direction: column; gap: 2px; } .detail-row { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--border-subtle); gap: 16px; } .detail-row:last-child { border-bottom: none; } .detail-label { font-size: 12px; color: var(--text-dim); flex-shrink: 0; } .detail-value { font-size: 13px; color: var(--text); text-align: right; word-break: break-word; } /* ═══════════════════════════════════════════════════════════════════════════ HEALTH INDICATORS ═══════════════════════════════════════════════════════════════════════════ */ .health-indicator { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: var(--radius-full); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; } .health-ok { background: var(--success-subtle); color: var(--success); } .health-down { background: var(--error-subtle); color: var(--error); } /* ═══════════════════════════════════════════════════════════════════════════ PROGRESS BAR ═══════════════════════════════════════════════════════════════════════════ */ .progress-bar { height: 6px; background: var(--surface2); border-radius: var(--radius-full); overflow: hidden; } .progress-bar-fill { height: 100%; background: var(--gradient-accent); border-radius: var(--radius-full); transition: width 0.4s var(--ease-smooth); } /* ═══════════════════════════════════════════════════════════════════════════ QUICK ACTION CARDS ═══════════════════════════════════════════════════════════════════════════ */ .quick-action-card { display: flex; align-items: center; gap: 14px; padding: 16px 20px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); cursor: pointer; transition: all var(--transition-fast); } .quick-action-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--border-strong); } .quick-action-icon { width: 40px; height: 40px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .quick-action-label { font-size: 14px; font-weight: 600; color: var(--text); } .quick-action-desc { font-size: 12px; color: var(--text-dim); margin-top: 2px; } /* ═══════════════════════════════════════════════════════════════════════════ EMPTY STATES ═══════════════════════════════════════════════════════════════════════════ */ .empty-state { text-align: center; padding: 48px 24px; } .empty-state-icon { width: 64px; height: 64px; margin: 0 auto 16px; border-radius: var(--radius-lg); background: var(--surface2); display: flex; align-items: center; justify-content: center; color: var(--text-dim); } .empty-state h3 { font-size: 16px; color: var(--text-secondary); margin-bottom: 8px; } .empty-state p { font-size: 13px; color: var(--text-dim); max-width: 300px; margin: 0 auto; } /* ═══════════════════════════════════════════════════════════════════════════ ERROR STATES ═══════════════════════════════════════════════════════════════════════════ */ .error-state { text-align: center; padding: 32px; background: var(--error-subtle); border: 1px solid rgba(239, 68, 68, 0.2); border-radius: var(--radius-lg); } .error-state h3 { color: var(--error); font-size: 16px; margin-bottom: 8px; } /* ═══════════════════════════════════════════════════════════════════════════ ONBOARDING BANNER ═══════════════════════════════════════════════════════════════════════════ */ .onboarding-banner { background: var(--gradient-accent-subtle); border: 1px solid var(--accent-glass); border-radius: var(--radius-xl); padding: 24px; margin-bottom: 20px; } .onboarding-banner h3 { font-size: 18px; color: var(--text); margin-bottom: 8px; } .onboarding-banner p { color: var(--text-dim); margin-bottom: 16px; } /* ═══════════════════════════════════════════════════════════════════════════ SETUP CHECKLIST ═══════════════════════════════════════════════════════════════════════════ */ .setup-checklist { margin-bottom: 20px; } .setup-checklist-item { display: flex; align-items: center; gap: 10px; padding: 8px 0; font-size: 13px; color: var(--text-secondary); } .setup-checklist-icon { width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--border-strong); display: flex; align-items: center; justify-content: center; font-size: 11px; flex-shrink: 0; transition: all var(--transition-fast); } .setup-checklist-icon.done { background: var(--success); border-color: var(--success); color: #FFFFFF; } /* ═══════════════════════════════════════════════════════════════════════════ UTILITY CLASSES ═══════════════════════════════════════════════════════════════════════════ */ /* Text colors */ .text-dim { color: var(--text-dim); } .text-muted { color: var(--text-muted); } .text-accent { color: var(--accent); } .text-success { color: var(--success); } .text-error { color: var(--error); } .text-warning { color: var(--warning); } .text-info { color: var(--info); } /* Font sizes */ .text-xs { font-size: 11px; } .text-sm { font-size: 12px; } .text-base { font-size: 14px; } .text-lg { font-size: 16px; } .text-xl { font-size: 18px; } .text-2xl { font-size: 22px; } /* Font weights */ .font-normal { font-weight: 400; } .font-medium { font-weight: 500; } .font-semibold { font-weight: 600; } .font-bold { font-weight: 700; } .font-mono { font-family: var(--font-mono); } /* Flexbox */ .flex { display: flex; } .flex-col { flex-direction: column; } .items-center { align-items: center; } .justify-center { justify-content: center; } .justify-between { justify-content: space-between; } .justify-end { justify-content: flex-end; } .flex-wrap { flex-wrap: wrap; } .flex-1 { flex: 1; } .flex-grow { flex-grow: 1; } .flex-shrink-0 { flex-shrink: 0; } /* Gap */ .gap-1 { gap: 4px; } .gap-2 { gap: 8px; } .gap-3 { gap: 12px; } .gap-4 { gap: 16px; } .gap-6 { gap: 24px; } .gap-8 { gap: 32px; } /* Margin */ .m-0 { margin: 0; } .mt-1 { margin-top: 4px; } .mt-2 { margin-top: 8px; } .mt-3 { margin-top: 12px; } .mt-4 { margin-top: 16px; } .mb-1 { margin-bottom: 4px; } .mb-2 { margin-bottom: 8px; } .mb-3 { margin-bottom: 12px; } .mb-4 { margin-bottom: 16px; } .ml-1 { margin-left: 4px; } .ml-2 { margin-left: 8px; } .mr-1 { margin-right: 4px; } .mr-2 { margin-right: 8px; } .mx-auto { margin-left: auto; margin-right: auto; } /* Padding */ .p-0 { padding: 0; } .p-1 { padding: 4px; } .p-2 { padding: 8px; } .p-3 { padding: 12px; } .p-4 { padding: 16px; } .p-6 { padding: 24px; } .px-2 { padding-left: 8px; padding-right: 8px; } .px-3 { padding-left: 12px; padding-right: 12px; } .px-4 { padding-left: 16px; padding-right: 16px; } .py-1 { padding-top: 4px; padding-bottom: 4px; } .py-2 { padding-top: 8px; padding-bottom: 8px; } .py-3 { padding-top: 12px; padding-bottom: 12px; } .py-4 { padding-top: 16px; padding-bottom: 16px; } /* Width */ .w-full { width: 100%; } .max-w-sm { max-width: 24rem; } .max-w-md { max-width: 28rem; } .max-w-lg { max-width: 32rem; } .max-w-xl { max-width: 36rem; } /* Border radius */ .rounded { border-radius: var(--radius-md); } .rounded-lg { border-radius: var(--radius-lg); } .rounded-xl { border-radius: var(--radius-xl); } .rounded-full { border-radius: var(--radius-full); } /* Display */ .hidden { display: none; } .block { display: block; } .inline { display: inline; } .inline-flex { display: inline-flex; } /* Position */ .relative { position: relative; } .absolute { position: absolute; } .fixed { position: fixed; } /* Overflow */ .overflow-hidden { overflow: hidden; } .overflow-auto { overflow: auto; } .overflow-scroll { overflow: scroll; } /* Border */ .border { border: 1px solid var(--border); } .border-0 { border: none; } .border-t { border-top: 1px solid var(--border); } .border-b { border-bottom: 1px solid var(--border); } .border-l { border-left: 1px solid var(--border); } .border-r { border-right: 1px solid var(--border); } /* ═══════════════════════════════════════════════════════════════════════════ MESSAGE BUBBLES — Chat messages ═══════════════════════════════════════════════════════════════════════════ */ .message-bubble { padding: 12px 16px; border-radius: var(--radius-lg); background: var(--surface); border: 1px solid var(--border); font-size: 14px; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word; } .message.user .message-bubble { background: var(--accent-subtle); border-color: rgba(255, 92, 0, 0.15); } .message.agent .message-bubble { background: var(--surface); } .message-time { font-size: 10px; color: var(--text-muted); font-family: var(--font-mono); margin-top: 4px; } .message-meta { font-size: 10px; color: var(--text-muted); padding: 2px 8px; background: var(--surface2); border-radius: var(--radius-full); } /* Typing indicator dots */ .typing-dots { display: flex; gap: 4px; padding: 4px 0; } .typing-dots span { width: 6px; height: 6px; background: var(--text-dim); border-radius: 50%; animation: typing-bounce 1.4s ease-in-out infinite; } .typing-dots span:nth-child(2) { animation-delay: 0.2s; } .typing-dots span:nth-child(3) { animation-delay: 0.4s; } @keyframes typing-bounce { 0%, 60%, 100% { transform: translateY(0); } 30% { transform: translateY(-4px); } } /* ═══════════════════════════════════════════════════════════════════════════ TOOL CARDS — Tool execution display ═══════════════════════════════════════════════════════════════════════════ */ .tool-card { margin: 8px 0; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; font-size: 12px; transition: all var(--transition-fast); } .tool-card:hover { border-color: var(--border-strong); } .tool-card-error { border-color: rgba(239, 68, 68, 0.3); background: var(--error-subtle); } .tool-card-header { display: flex; align-items: center; gap: 8px; padding: 10px 14px; cursor: pointer; transition: background var(--transition-fast); } .tool-card-header:hover { background: var(--surface3); } .tool-card-name { font-family: var(--font-mono); font-weight: 600; color: var(--text); font-size: 12px; } .tool-card-icon { width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; color: var(--accent); } .tool-icon-ok { color: var(--success); font-size: 12px; font-weight: bold; } .tool-icon-err { color: var(--error); font-size: 12px; font-weight: bold; } .tool-card-spinner { width: 14px; height: 14px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; } .tool-expand-chevron { font-size: 8px; color: var(--text-muted); transition: transform var(--transition-fast); } .tool-card-body { padding: 12px 14px; border-top: 1px solid var(--border); background: var(--surface); } .tool-section-label { font-size: 10px; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; } .tool-pre { font-family: var(--font-mono); font-size: 11px; line-height: 1.5; color: var(--text-secondary); background: var(--surface2); padding: 10px 12px; border-radius: var(--radius-sm); overflow-x: auto; white-space: pre-wrap; word-break: break-word; max-height: 300px; overflow-y: auto; } .tool-pre-error { color: var(--error); background: var(--error-subtle); } .tool-pre-short { max-height: 100px; } .tool-pre-medium { max-height: 200px; } /* ═══════════════════════════════════════════════════════════════════════════ INPUT AREA — Message input ═══════════════════════════════════════════════════════════════════════════ */ .input-row { display: flex; align-items: flex-end; gap: 10px; } .input-row textarea { flex: 1; resize: none; border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 12px 16px; font-family: var(--font-sans); font-size: 14px; line-height: 1.5; background: var(--surface); color: var(--text); transition: all var(--transition-fast); min-height: 46px; max-height: 150px; } .input-row textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); } .input-row textarea::placeholder { color: var(--text-muted); } .input-row textarea.streaming-active { opacity: 0.7; } .btn-send { width: 46px; height: 46px; border: none; border-radius: var(--radius-lg); background: var(--gradient-accent); color: var(--text-on-accent); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all var(--transition-fast); box-shadow: var(--shadow-accent); } .btn-send:hover:not(:disabled) { transform: scale(1.05); box-shadow: var(--shadow-lg), var(--shadow-accent); } .btn-send:disabled { opacity: 0.4; cursor: not-allowed; transform: none; } .btn-stop { width: 46px; height: 46px; border: none; border-radius: var(--radius-lg); background: var(--error); color: #FFFFFF; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all var(--transition-fast); box-shadow: var(--shadow-error); } .btn-stop:hover { background: var(--error-hover); } .input-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; min-height: 20px; } /* ═══════════════════════════════════════════════════════════════════════════ SLASH COMMAND MENU ═══════════════════════════════════════════════════════════════════════════ */ .slash-menu { position: absolute; bottom: 100%; left: 0; right: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); margin-bottom: 8px; max-height: 200px; overflow-y: auto; z-index: var(--z-dropdown); } .slash-menu-item { display: flex; flex-direction: column; gap: 2px; padding: 10px 14px; cursor: pointer; transition: background var(--transition-fast); } .slash-menu-item:hover, .slash-menu-item.slash-active { background: var(--surface2); } /* ═══════════════════════════════════════════════════════════════════════════ RECORDING INDICATORS ═══════════════════════════════════════════════════════════════════════════ */ .recording-dot { width: 12px; height: 12px; background: var(--error); border-radius: 50%; animation: pulse-ring 1s infinite; } .recording-indicator { display: flex; align-items: center; gap: 8px; padding: 4px 12px; background: var(--error-subtle); border-radius: var(--radius-full); } .btn-recording { background: var(--error-subtle) !important; color: var(--error) !important; } /* ═══════════════════════════════════════════════════════════════════════════ TIP BAR ═══════════════════════════════════════════════════════════════════════════ */ .tip-bar { display: flex; align-items: center; gap: 8px; padding: 4px 10px; background: var(--surface2); border-radius: var(--radius-full); } .tip-bar-dismiss { background: transparent; border: none; color: var(--text-muted); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 4px; } .tip-bar-dismiss:hover { color: var(--text); } /* ═══════════════════════════════════════════════════════════════════════════ AUDIO PLAYER ═══════════════════════════════════════════════════════════════════════════ */ .audio-player { display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: var(--surface2); border-radius: var(--radius-md); } /* ═══════════════════════════════════════════════════════════════════════════ AGENT CHIP — Agent selector cards ═══════════════════════════════════════════════════════════════════════════ */ .agent-chip { cursor: pointer; display: flex; align-items: center; gap: 12px; padding: 14px 20px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); transition: all var(--transition-fast); min-width: 220px; } .agent-chip:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow-md); } /* ═══════════════════════════════════════════════════════════════════════════ MARKDOWN BODY — Rendered markdown styles ═══════════════════════════════════════════════════════════════════════════ */ .markdown-body { line-height: 1.6; color: var(--text); } .markdown-body h1, .markdown-body h2, .markdown-body h3 { margin-top: 1.2em; margin-bottom: 0.6em; font-weight: 600; line-height: 1.3; } .markdown-body h1 { font-size: 1.4em; } .markdown-body h2 { font-size: 1.2em; } .markdown-body h3 { font-size: 1.1em; } .markdown-body p { margin-bottom: 0.8em; } .markdown-body code { font-family: var(--font-mono); font-size: 0.9em; padding: 2px 6px; background: var(--surface2); border-radius: var(--radius-sm); } .markdown-body pre { margin: 1em 0; padding: 12px 16px; background: var(--surface2); border-radius: var(--radius-md); overflow-x: auto; } .markdown-body pre code { padding: 0; background: transparent; } .markdown-body ul, .markdown-body ol { margin: 0.8em 0; padding-left: 1.5em; } .markdown-body li { margin: 0.4em 0; } .markdown-body blockquote { margin: 1em 0; padding: 8px 16px; border-left: 3px solid var(--accent); background: var(--surface2); color: var(--text-dim); } .markdown-body a { color: var(--accent); text-decoration: none; } .markdown-body a:hover { text-decoration: underline; } .markdown-body table { width: 100%; border-collapse: collapse; margin: 1em 0; } .markdown-body th, .markdown-body td { padding: 8px 12px; border: 1px solid var(--border); text-align: left; } .markdown-body th { background: var(--surface2); font-weight: 600; } .markdown-body hr { border: none; border-top: 1px solid var(--border); margin: 1.5em 0; } /* ═══════════════════════════════════════════════════════════════════════════ SPINNER UTILITY ═══════════════════════════════════════════════════════════════════════════ */ .spinner { width: 16px; height: 16px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; display: inline-block; }