/* Terminal Shared Styles * This file contains CSS shared between ChatTerminal overlay and terminal popout page */ /* ============================================ TERMINAL CSS VARIABLES (inherit from app.css) ============================================ */ :root { /* Terminal-specific tokens that reference global variables */ --terminal-bg: var(--bg-surface, #0d0d0d); --terminal-header-bg: var(--bg-elevated, #161b22); --terminal-text: var(--text-secondary, #c9d1d9); --terminal-text-muted: var(--text-muted, #8b949e); --terminal-text-faint: var(--text-faint, #6e7681); --terminal-border: var(--border-light, #30363d); --terminal-border-subtle: #21262d; --terminal-active: var(--accent-green, #0f0); --terminal-audio: var(--accent-pink, #ec4899); --terminal-audio-light: var(--accent-pink-light, #f472b6); --terminal-error: var(--error-light, #f85149); } /* ============================================ HEADER & TAB NAVIGATION ============================================ */ .terminal-header { display: flex; align-items: center; padding: 0.5rem 0.75rem; background: var(--terminal-header-bg); border-bottom: 1px solid var(--terminal-border); gap: 0.75rem; } .tab-bar { display: flex; gap: 0.25rem; } .tab-button { display: flex; align-items: center; justify-content: center; padding: 0.35rem 0.5rem; background: var(--bg-hover); border: 1px solid transparent; border-radius: 4px; color: var(--terminal-text-muted); font-size: 0.875rem; font-family: 'Consolas', 'Monaco', monospace; cursor: pointer; transition: all 0.15s ease; } .tab-button:hover { color: var(--terminal-text); background: var(--bg-hover-light); } .tab-button.active { color: var(--terminal-active); background: rgba(0, 255, 0, 0.1); border-color: rgba(0, 255, 0, 0.25); } /* Audio tab special color */ .tab-button.audio.active { color: var(--terminal-audio); background: rgba(236, 72, 153, 0.15); border-color: rgba(236, 72, 153, 0.3); } .header-spacer { flex: 1; } .status { display: flex; align-items: center; } .status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--terminal-error); } .status-dot.connected { background: var(--terminal-active); } .terminal-controls { display: flex; gap: 0.5rem; align-items: center; } .control-button { background: none; border: none; color: var(--terminal-text-muted); cursor: pointer; padding: 0.25rem; width: 1.5rem; height: 1.5rem; display: flex; align-items: center; justify-content: center; border-radius: 4px; transition: all 0.2s; } .control-button:hover { background: var(--terminal-border); color: var(--terminal-text); } .close-button { background: none; border: none; color: var(--terminal-text-muted); font-size: 1.5rem; cursor: pointer; padding: 0; width: 2rem; height: 2rem; display: flex; align-items: center; justify-content: center; border-radius: 4px; } .close-button:hover { background: var(--terminal-border); color: var(--terminal-text); } /* ============================================ TAB CONTENT CONTAINER ============================================ */ .tab-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; opacity: 0.9; } /* ============================================ TERMINAL MESSAGES ============================================ */ .terminal-messages { flex: 1; overflow-y: auto; padding: 1rem; color: var(--terminal-text); background: var(--terminal-bg); } .terminal-messages::-webkit-scrollbar { width: 8px; } .terminal-messages::-webkit-scrollbar-track { background: var(--terminal-bg); } .terminal-messages::-webkit-scrollbar-thumb { background: var(--terminal-border); border-radius: 4px; } .terminal-messages::-webkit-scrollbar-thumb:hover { background: var(--border-hover); } /* ============================================ TERMINAL INPUT ============================================ */ .terminal-input-line { display: flex; align-items: center; gap: 0.35rem; padding: 0.125rem 0; margin-top: 0.25rem; } .prompt { color: var(--terminal-active); font-weight: 600; white-space: nowrap; font-size: 0.8rem; } .terminal-input { flex: 1; background: transparent; border: none; color: var(--terminal-text); font-family: inherit; font-size: 0.8rem; outline: none; caret-color: var(--terminal-active); } .terminal-input::placeholder { color: var(--border-hover); } .terminal-input:disabled { opacity: 0.5; } /* ============================================ SYSTEM MESSAGES ============================================ */ .system-message { padding: 0.125rem 0; color: var(--terminal-text-muted); font-size: 0.8rem; line-height: 1.3; border-left: none; padding-left: 0; margin: 0; } .system-prefix { color: var(--terminal-text-faint); font-size: 0.75rem; margin-right: 0.5rem; } .system-text { color: var(--terminal-text); } /* ============================================ CHAT MESSAGE OVERRIDES (compact terminal mode) ============================================ */ .terminal-messages :global(.chat-message) { padding: 0.125rem 0; margin: 0; background: transparent; border-radius: 0; display: flex; flex-direction: row; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; } .terminal-messages :global(.chat-message:hover) { background: transparent; } .terminal-messages :global(.chat-message .message-header) { margin-bottom: 0; gap: 0.35rem; font-size: 0.8rem; flex-shrink: 0; } .terminal-messages :global(.chat-message .message-content) { font-size: 0.8rem; line-height: 1.3; margin-left: 0; flex: 1; min-width: 0; } .terminal-messages :global(.chat-message .message-content p) { margin: 0; } .terminal-messages :global(.chat-message .user-avatar), .terminal-messages :global(.chat-message .user-avatar-placeholder) { width: 16px; height: 16px; font-size: 0.5rem; } .terminal-messages :global(.chat-message .timestamp) { font-size: 0.7rem; } .terminal-messages :global(.chat-message .badge) { font-size: 0.55rem; padding: 0.05rem 0.25rem; } /* Terminal mode: scale graffiti down to match text height */ .terminal-messages :global(.graffiti-img) { width: auto !important; height: 16px !important; max-width: 100px !important; max-height: 16px !important; } /* ============================================ STREAMS TAB ============================================ */ .streams-tab { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: var(--terminal-bg); } .streams-header { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--terminal-border); } .streams-title { color: var(--terminal-text-muted); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; } .tile-toggle { padding: 0.25rem 0.5rem; background: rgba(0, 255, 0, 0.1); border: 1px solid rgba(0, 255, 0, 0.25); border-radius: 4px; color: var(--terminal-active); font-size: 0.7rem; font-family: inherit; cursor: pointer; transition: all 0.15s ease; } .tile-toggle:hover { background: rgba(0, 255, 0, 0.2); } .streams-list { flex: 1; overflow-y: auto; padding: 0.5rem; } .streams-list::-webkit-scrollbar { width: 6px; } .streams-list::-webkit-scrollbar-track { background: var(--terminal-bg); } .streams-list::-webkit-scrollbar-thumb { background: var(--terminal-border); border-radius: 3px; } .streams-loading, .streams-empty { color: var(--terminal-text-muted); font-size: 0.8rem; text-align: center; padding: 2rem 1rem; } .streams-section-header { font-size: 0.7rem; color: var(--terminal-text-muted); text-transform: uppercase; letter-spacing: 0.05em; padding: 0.5rem 0.25rem 0.25rem; border-bottom: 1px solid var(--terminal-border-subtle); margin-bottom: 0.25rem; } .streams-section-header:not(:first-child) { margin-top: 0.75rem; } .stream-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem; border-radius: 4px; transition: background 0.15s ease; } .stream-item:hover { background: rgba(255, 255, 255, 0.05); } .stream-item.offline { opacity: 0.7; } .stream-item.offline:hover { opacity: 1; } .stream-link { display: flex; align-items: center; gap: 0.5rem; flex: 1; text-decoration: none; color: inherit; min-width: 0; } .stream-preview { width: 48px; height: 27px; border-radius: 3px; overflow: hidden; background: var(--bg-input); flex-shrink: 0; } .stream-preview img { width: 100%; height: 100%; object-fit: cover; } .preview-placeholder { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #561d5e, #8b3a92); color: white; font-size: 0.75rem; font-weight: 600; } .preview-placeholder.live { background: linear-gradient(135deg, #da3633, #f85149); } .preview-placeholder.offline { background: linear-gradient(135deg, #30363d, #484f58); } .stream-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; } .stream-name { color: var(--terminal-text); font-size: 0.8rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .stream-meta { display: flex; align-items: center; gap: 0.5rem; font-size: 0.7rem; color: var(--terminal-text-muted); } .viewer-count { color: var(--terminal-error); font-weight: 500; } .viewer-count::before { content: ''; margin-right: 0.2rem; font-size: 0.5rem; vertical-align: middle; } .stream-user { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .offline-badge { color: var(--terminal-text-muted); font-size: 0.65rem; background: rgba(139, 148, 158, 0.2); padding: 0.1rem 0.3rem; border-radius: 3px; } .tile-btn { width: 24px; height: 24px; border-radius: 4px; border: 1px solid var(--terminal-border); background: var(--bg-hover); color: var(--terminal-text-muted); font-size: 0.9rem; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; flex-shrink: 0; } .tile-btn:hover { background: rgba(0, 255, 0, 0.15); border-color: rgba(0, 255, 0, 0.3); color: var(--terminal-active); } .tile-btn.active { background: rgba(0, 255, 0, 0.2); border-color: var(--terminal-active); color: var(--terminal-active); } /* ============================================ AUDIO TAB ============================================ */ .audio-tab { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: var(--terminal-bg); } /* Player section (foobar/winamp style) */ .player-section { padding: 0.75rem; background: linear-gradient(180deg, rgba(236, 72, 153, 0.15), rgba(236, 72, 153, 0.05)); border-bottom: 1px solid rgba(236, 72, 153, 0.2); } .player-track-info { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.5rem; } .player-thumb { width: 48px; height: 48px; border-radius: 4px; overflow: hidden; background: var(--bg-input); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .player-thumb img { width: 100%; height: 100%; object-fit: cover; } .player-thumb .placeholder { font-size: 1.5rem; } .player-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; } .player-title { font-size: 0.85rem; color: var(--terminal-text); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .player-artist { font-size: 0.7rem; color: var(--terminal-text-muted); } /* Progress bar */ .player-progress { height: 6px; background: var(--bg-hover-light); border-radius: 3px; cursor: pointer; margin-bottom: 0.25rem; overflow: hidden; } .progress-fill { height: 100%; background: linear-gradient(90deg, var(--terminal-audio), var(--terminal-audio-light)); border-radius: 3px; transition: width 0.1s linear; } .player-times { display: flex; justify-content: space-between; font-size: 0.65rem; color: var(--terminal-text-muted); font-family: monospace; margin-bottom: 0.5rem; } /* Player controls */ .player-controls { display: flex; align-items: center; justify-content: center; gap: 0.5rem; margin-bottom: 0.5rem; } .ctrl-btn { width: 28px; height: 28px; border-radius: 50%; border: none; background: var(--bg-hover-light); color: var(--terminal-text); font-size: 0.75rem; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; } .ctrl-btn:hover { background: rgba(255, 255, 255, 0.2); } .ctrl-btn.active { background: rgba(236, 72, 153, 0.3); color: var(--terminal-audio); } .ctrl-btn.play { width: 36px; height: 36px; background: var(--terminal-audio); font-size: 0.9rem; } .ctrl-btn.play:hover { background: var(--terminal-audio-light); } /* Volume control */ .player-volume { display: flex; align-items: center; justify-content: center; gap: 0.5rem; } .vol-btn { width: 24px; height: 24px; border: none; background: transparent; color: var(--terminal-text-muted); font-size: 0.8rem; cursor: pointer; display: flex; align-items: center; justify-content: center; } .vol-btn:hover { color: var(--terminal-text); } .volume-slider { width: 80px; height: 4px; -webkit-appearance: none; appearance: none; background: var(--bg-hover-light); border-radius: 2px; cursor: pointer; } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--terminal-audio); cursor: pointer; } .volume-slider::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: var(--terminal-audio); cursor: pointer; border: none; } /* Empty player state */ .player-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 1.5rem; color: var(--terminal-text-muted); font-size: 0.85rem; } .player-hint { font-size: 0.7rem; color: var(--terminal-text-faint); margin-top: 0.25rem; } /* Queue section */ .queue-section { border-bottom: 1px solid var(--terminal-border); } .queue-header { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 0.75rem; background: rgba(0, 0, 0, 0.2); font-size: 0.7rem; color: var(--terminal-text-muted); } .clear-btn { padding: 0.15rem 0.4rem; background: rgba(248, 81, 73, 0.2); border: 1px solid rgba(248, 81, 73, 0.3); border-radius: 3px; color: var(--terminal-error); font-size: 0.65rem; font-family: inherit; cursor: pointer; } .clear-btn:hover { background: rgba(248, 81, 73, 0.3); } .queue-list { max-height: 120px; overflow-y: auto; } .queue-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.75rem; font-size: 0.75rem; color: var(--terminal-text-muted); cursor: pointer; transition: background 0.15s ease; } .queue-item:hover { background: var(--bg-hover); } .queue-item.active { background: rgba(236, 72, 153, 0.1); color: var(--terminal-audio); } .queue-index { width: 20px; text-align: center; font-size: 0.65rem; } .queue-title { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--terminal-text); } .queue-item.active .queue-title { color: var(--terminal-audio); } .queue-duration { font-size: 0.65rem; font-family: monospace; } .remove-btn { width: 18px; height: 18px; border: none; background: transparent; color: var(--terminal-text-muted); font-size: 0.9rem; cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: 50%; opacity: 0; transition: all 0.15s ease; } .queue-item:hover .remove-btn { opacity: 1; } .remove-btn:hover { background: rgba(248, 81, 73, 0.2); color: var(--terminal-error); } /* Browse section */ .audio-browse-header { font-size: 0.7rem; color: var(--terminal-text-muted); text-transform: uppercase; letter-spacing: 0.05em; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--terminal-border-subtle); } .audio-list { flex: 1; overflow-y: auto; padding: 0.5rem; } .audio-list::-webkit-scrollbar { width: 6px; } .audio-list::-webkit-scrollbar-track { background: var(--terminal-bg); } .audio-list::-webkit-scrollbar-thumb { background: var(--terminal-border); border-radius: 3px; } .audio-loading, .audio-empty { color: var(--terminal-text-muted); font-size: 0.8rem; text-align: center; padding: 2rem 1rem; } .audio-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem; border-radius: 4px; transition: background 0.15s ease; } .audio-item:hover { background: rgba(255, 255, 255, 0.05); } .audio-thumb { width: 40px; height: 40px; border-radius: 4px; overflow: hidden; background: var(--bg-input); flex-shrink: 0; display: flex; align-items: center; justify-content: center; position: relative; } .audio-thumb img { width: 100%; height: 100%; object-fit: cover; } .audio-thumb .placeholder { font-size: 1rem; opacity: 0.5; } .audio-thumb .duration { position: absolute; bottom: 2px; right: 2px; background: rgba(0, 0, 0, 0.8); color: white; font-size: 0.5rem; padding: 1px 3px; border-radius: 2px; } .audio-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; } .audio-name { color: var(--terminal-text); font-size: 0.8rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .audio-meta { display: flex; align-items: center; gap: 0.5rem; font-size: 0.7rem; color: var(--terminal-text-muted); } .audio-plays { color: var(--terminal-audio); } .audio-user { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .audio-actions { display: flex; gap: 0.25rem; opacity: 0; transition: opacity 0.15s ease; } .audio-item:hover .audio-actions { opacity: 1; } .audio-btn { width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--terminal-border); background: var(--bg-hover); color: var(--terminal-text-muted); font-size: 0.75rem; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; } .audio-btn:hover { background: rgba(236, 72, 153, 0.15); border-color: rgba(236, 72, 153, 0.3); color: var(--terminal-audio); } .audio-btn.play { background: rgba(236, 72, 153, 0.2); border-color: rgba(236, 72, 153, 0.3); color: var(--terminal-audio); } .audio-btn.play:hover { background: var(--terminal-audio); color: white; }