Constant CSS
Source pub(crate) const CSS: &str = "/* ============================================\n libp2p-chat - Cyberpunk Theme Styles\n ============================================ */\n\n/* CSS Variables */\n:root {\n --bg-primary: #0a0a0f;\n --bg-secondary: #13131f;\n --bg-tertiary: #1a1a2e;\n --accent-primary: #ff006e;\n --accent-secondary: #00f5ff;\n --accent-glow: rgba(255, 0, 110, 0.5);\n --accent-glow-cyan: rgba(0, 245, 255, 0.5);\n --text-primary: #e0e0e0;\n --text-secondary: #a0a0a0;\n --text-muted: #606060;\n --border-color: #2a2a3e;\n --success: #00ff88;\n --error: #ff4444;\n --warning: #ffaa00;\n}\n\n/* Reset & Base */\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: \'Courier New\', monospace;\n background: var(--bg-primary);\n color: var(--text-primary);\n height: 100vh;\n height: 100dvh;\n overflow: hidden;\n line-height: 1.5;\n}\n\n#app {\n display: flex;\n flex-direction: row;\n height: 100vh;\n height: 100dvh;\n max-width: 1200px;\n margin: 0 auto;\n background: var(--bg-primary);\n position: relative;\n}\n\n/* ============================================\n SIDEBAR\n ============================================ */\n\n.sidebar {\n width: 200px;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n background: var(--bg-secondary);\n border-left: 1px solid var(--border-color);\n transition: width 0.3s ease;\n overflow: hidden;\n}\n\n.sidebar.collapsed {\n width: 0;\n border: none;\n}\n\n.main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.sidebar-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.375rem 1.5rem;\n background: var(--bg-tertiary);\n border-bottom: 1px solid var(--border-color);\n}\n\n.sidebar-header h3 {\n font-size: 1rem;\n color: var(--accent-secondary);\n text-shadow: 0 0 10px var(--accent-glow-cyan);\n margin: 0;\n}\n\n.sidebar-header .close-btn {\n padding: 0;\n line-height: 1;\n}\n\n.peer-list {\n flex: 1;\n overflow-y: auto;\n padding: 0.75rem;\n}\n\n.peer-list::-webkit-scrollbar {\n width: 8px;\n}\n\n.peer-list::-webkit-scrollbar-track {\n background: var(--bg-tertiary);\n border-radius: 4px;\n}\n\n.peer-list::-webkit-scrollbar-thumb {\n background: var(--accent-primary);\n border-radius: 4px;\n}\n\n.peer-list::-webkit-scrollbar-thumb:hover {\n background: var(--accent-secondary);\n}\n\n.peer-section-title {\n font-size: 0.75rem;\n text-transform: uppercase;\n color: var(--text-muted);\n margin: 0.5rem 0;\n}\n\n.peer-item {\n display: flex;\n flex-direction: column;\n padding: 0.5rem 0;\n border-bottom: 1px solid rgba(255, 255, 255, 0.05);\n cursor: pointer;\n}\n\n.peer-item:hover {\n background: rgba(255, 255, 255, 0.03);\n}\n\n.peer-item-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n}\n\n.peer-id {\n font-family: \'Courier New\', monospace;\n font-size: 0.8rem;\n color: var(--text-primary);\n}\n\n.peer-transports {\n font-size: 0.85rem;\n}\n\n.peer-info {\n display: flex;\n align-items: center;\n gap: 0.35rem;\n}\n\n.peer-status {\n font-size: 0.6rem;\n cursor: help;\n}\n\n.peer-status.open,\n.peer-status.mesh {\n color: var(--success);\n}\n\n.peer-status.none,\n.peer-status.connected {\n color: var(--text-muted);\n}\n\n.peer-status.pending {\n color: var(--warning);\n animation: pulse 1.5s infinite;\n}\n\n.peer-empty {\n font-size: 0.85rem;\n color: var(--text-muted);\n font-style: italic;\n padding: 0.25rem 0;\n}\n\n.peer-address-popup {\n padding: 0.5rem;\n margin-top: 0.25rem;\n background: var(--bg-primary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n}\n\n.popup-title {\n font-size: 0.75rem;\n color: var(--text-secondary);\n margin-bottom: 0.25rem;\n}\n\n.popup-addr {\n font-family: \'Courier New\', monospace;\n font-size: 0.75rem;\n color: var(--accent-secondary);\n word-break: break-all;\n padding: 0.2rem 0;\n}\n\n.popup-empty {\n font-size: 0.8rem;\n color: var(--text-muted);\n font-style: italic;\n}\n\n.leave-btn {\n background: var(--bg-tertiary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.4rem 0.75rem;\n color: var(--text-secondary);\n font-family: inherit;\n font-size: 0.85rem;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.leave-btn:hover {\n background: var(--accent-primary);\n color: white;\n border-color: var(--accent-primary);\n}\n\n.sidebar-toggle {\n background: var(--bg-tertiary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.4rem 0.75rem;\n color: var(--text-secondary);\n font-family: inherit;\n font-size: 0.85rem;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.sidebar-toggle:hover {\n background: var(--accent-primary);\n color: white;\n border-color: var(--accent-primary);\n}\n\n.sidebar-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 150;\n transition: opacity 0.3s ease;\n}\n\n.sidebar-backdrop.hidden {\n opacity: 0;\n pointer-events: none;\n visibility: hidden;\n}\n\n/* Background Grid Effect */\nbody::before {\n content: \'\';\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-image: \n linear-gradient(rgba(0, 245, 255, 0.03) 1px, transparent 1px),\n linear-gradient(90deg, rgba(0, 245, 255, 0.03) 1px, transparent 1px);\n background-size: 50px 50px;\n pointer-events: none;\n z-index: -1;\n}\n\n/* ============================================\n HEADER\n ============================================ */\n\n.chat-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n background: var(--bg-secondary);\n border-bottom: 1px solid var(--border-color);\n box-shadow: 0 2px 20px rgba(0, 0, 0, 0.5);\n}\n\n.logo {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.logo-icon {\n font-size: 1.5rem;\n filter: drop-shadow(0 0 8px var(--accent-glow));\n}\n\n.logo-text {\n font-size: 1.25rem;\n font-weight: bold;\n background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n text-shadow: 0 0 20px var(--accent-glow);\n}\n\n.header-stats {\n display: flex;\n gap: 1rem;\n align-items: center;\n}\n\n.stat-badge {\n background: var(--bg-tertiary);\n padding: 0.4rem 0.8rem;\n border-radius: 4px;\n font-size: 0.85rem;\n border: 1px solid var(--border-color);\n color: var(--text-secondary);\n}\n\n.status-badge {\n padding: 0.4rem 0.8rem;\n border-radius: 4px;\n font-size: 0.85rem;\n font-weight: bold;\n transition: all 0.3s ease;\n}\n\n.status-badge.online {\n background: rgba(0, 255, 136, 0.1);\n color: var(--success);\n border: 1px solid var(--success);\n box-shadow: 0 0 10px rgba(0, 255, 136, 0.3);\n}\n\n.status-badge.offline {\n background: rgba(255, 68, 68, 0.1);\n color: var(--error);\n border: 1px solid var(--error);\n}\n\n.status-badge.connecting {\n background: rgba(255, 170, 0, 0.1);\n color: var(--warning);\n border: 1px solid var(--warning);\n animation: pulse 1.5s infinite;\n}\n\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n/* ============================================\n CHAT CONTAINER\n ============================================ */\n\n.chat-container {\n flex: 1;\n overflow: hidden;\n padding: 1rem;\n background: var(--bg-primary);\n}\n\n.messages-list {\n height: 100%;\n overflow-y: auto;\n padding: 1rem;\n background: var(--bg-secondary);\n border: 1px solid var(--border-color);\n border-radius: 8px;\n box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.3);\n}\n\n/* Custom Scrollbar */\n.messages-list::-webkit-scrollbar {\n width: 8px;\n}\n\n.messages-list::-webkit-scrollbar-track {\n background: var(--bg-tertiary);\n border-radius: 4px;\n}\n\n.messages-list::-webkit-scrollbar-thumb {\n background: var(--accent-primary);\n border-radius: 4px;\n}\n\n.messages-list::-webkit-scrollbar-thumb:hover {\n background: var(--accent-secondary);\n}\n\n/* ============================================\n MESSAGES\n ============================================ */\n\n.chat-message {\n padding: 0.6rem 0;\n border-bottom: 1px solid rgba(255, 255, 255, 0.05);\n animation: fadeIn 0.3s ease;\n line-height: 1.6;\n}\n\n.chat-message.local {\n color: var(--text-primary);\n}\n\n.chat-message.local .msg-sender {\n color: var(--accent-secondary);\n text-shadow: 0 0 5px var(--accent-glow-cyan);\n}\n\n.chat-message.dimmed {\n opacity: 0.25;\n filter: grayscale(100%);\n}\n\n.msg-time {\n color: var(--text-muted);\n font-size: 0.85rem;\n}\n\n.msg-sender {\n color: var(--accent-primary);\n font-weight: bold;\n text-shadow: 0 0 5px var(--accent-glow);\n}\n\n.msg-content {\n color: var(--text-primary);\n}\n\n.system-message {\n padding: 0.6rem 0;\n color: var(--text-muted);\n font-style: italic;\n border-left: 2px solid var(--accent-primary);\n padding-left: 1rem;\n margin: 0.5rem 0;\n}\n\n.error-message {\n padding: 0.6rem 0;\n color: var(--error);\n border-left: 2px solid var(--error);\n padding-left: 1rem;\n margin: 0.5rem 0;\n background: rgba(255, 68, 68, 0.05);\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateX(-10px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n}\n\n/* Screen-reader-only */\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* ============================================\n FOOTER / INPUT AREA\n ============================================ */\n\n.chat-footer {\n padding: 1rem 1.5rem;\n background: var(--bg-secondary);\n border-top: 1px solid var(--border-color);\n}\n\n.input-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 0.75rem;\n}\n\n.nickname-section {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.nickname-section label {\n color: var(--text-secondary);\n font-size: 0.85rem;\n}\n\n#nickname {\n background: var(--bg-tertiary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.4rem 0.75rem;\n color: var(--accent-secondary);\n font-family: inherit;\n font-size: 0.9rem;\n width: 150px;\n transition: all 0.3s ease;\n}\n\n#nickname:focus {\n outline: none;\n border-color: var(--accent-secondary);\n box-shadow: 0 0 10px var(--accent-glow-cyan);\n}\n\n.stats-btn {\n background: var(--bg-tertiary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.4rem 0.75rem;\n color: var(--text-secondary);\n font-family: inherit;\n font-size: 0.85rem;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.stats-btn:hover {\n background: var(--accent-primary);\n color: white;\n border-color: var(--accent-primary);\n}\n\n.message-input-section {\n display: flex;\n gap: 0.5rem;\n}\n\n#message-input {\n flex: 1;\n background: var(--bg-tertiary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.75rem 1rem;\n color: var(--text-primary);\n font-family: inherit;\n font-size: 1rem;\n transition: all 0.3s ease;\n}\n\n#message-input:focus {\n outline: none;\n border-color: var(--accent-primary);\n box-shadow: 0 0 15px var(--accent-glow);\n}\n\n#message-input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* ============================================\n STATS PANEL\n ============================================ */\n\n.stats-panel {\n position: absolute;\n top: 80px;\n right: 20px;\n width: 350px;\n max-height: calc(100vh - 200px);\n background: var(--bg-secondary);\n border: 1px solid var(--border-color);\n border-radius: 8px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.8), 0 0 30px var(--accent-glow);\n z-index: 100;\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.stats-panel.hidden {\n opacity: 0;\n visibility: hidden;\n transform: translateY(-10px);\n}\n\n.stats-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem;\n background: var(--bg-tertiary);\n border-bottom: 1px solid var(--border-color);\n}\n\n.stats-header h3 {\n font-size: 1rem;\n color: var(--accent-secondary);\n text-shadow: 0 0 10px var(--accent-glow-cyan);\n}\n\n.close-btn {\n background: none;\n border: none;\n color: var(--text-secondary);\n font-size: 1.5rem;\n cursor: pointer;\n transition: color 0.3s ease;\n}\n\n.close-btn:hover {\n color: var(--error);\n}\n\n.stats-content {\n padding: 1rem;\n overflow-y: auto;\n max-height: 400px;\n}\n\n.stat-row {\n display: flex;\n justify-content: space-between;\n padding: 0.5rem 0;\n border-bottom: 1px solid rgba(255, 255, 255, 0.05);\n}\n\n.stat-label {\n color: var(--text-secondary);\n font-size: 0.85rem;\n}\n\n.stat-value {\n color: var(--text-primary);\n font-size: 0.85rem;\n text-align: right;\n}\n\n.stat-value.mono {\n font-family: \'Courier New\', monospace;\n font-size: 0.8rem;\n}\n\n.stat-section {\n padding: 0.75rem 0;\n border-bottom: 1px solid rgba(255, 255, 255, 0.05);\n}\n\n.stat-list {\n list-style: none;\n margin-top: 0.5rem;\n padding-left: 1rem;\n}\n\n.stat-list li {\n color: var(--text-secondary);\n font-size: 0.8rem;\n padding: 0.2rem 0;\n position: relative;\n}\n\n.stat-list li::before {\n content: \'\u{25b8}\';\n position: absolute;\n left: -1rem;\n color: var(--accent-primary);\n}\n\n/* ============================================\n PEER CONNECT SECTION\n ============================================ */\n\n.peer-connect-section {\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid var(--border-color);\n}\n\n.peer-address-row {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 0.75rem;\n flex-wrap: wrap;\n}\n\n.peer-label {\n color: var(--text-secondary);\n font-size: 0.85rem;\n white-space: nowrap;\n}\n\n.peer-address {\n color: var(--accent-secondary);\n font-size: 0.75rem;\n word-break: break-all;\n flex: 1;\n background: var(--bg-primary);\n padding: 0.3rem 0.5rem;\n border-radius: 4px;\n border: 1px solid var(--border-color);\n}\n\n.copy-btn {\n background: var(--bg-tertiary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.3rem 0.5rem;\n cursor: pointer;\n font-size: 0.85rem;\n transition: all 0.2s ease;\n}\n\n.copy-btn:hover {\n background: var(--accent-primary);\n border-color: var(--accent-primary);\n}\n\n.peer-dial-row {\n display: flex;\n gap: 0.5rem;\n}\n\n#peer-address-input {\n flex: 1;\n background: var(--bg-primary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.4rem 0.75rem;\n color: var(--text-primary);\n font-family: inherit;\n font-size: 0.85rem;\n}\n\n#peer-address-input:focus {\n outline: none;\n border-color: var(--accent-secondary);\n box-shadow: 0 0 8px var(--accent-glow-cyan);\n}\n\n#peer-dial-btn {\n background: var(--bg-tertiary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.4rem 0.75rem;\n color: var(--text-secondary);\n font-family: inherit;\n font-size: 0.85rem;\n cursor: pointer;\n transition: all 0.3s ease;\n white-space: nowrap;\n}\n\n#peer-dial-btn:hover {\n background: var(--accent-primary);\n color: white;\n border-color: var(--accent-primary);\n}\n\n/* ============================================\n ROOM PROMPT OVERLAY\n ============================================ */\n\n.room-prompt-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(10, 10, 15, 0.95);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n transition: opacity 0.3s ease;\n}\n\n.room-prompt-overlay.hidden {\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n}\n\n.room-prompt-box {\n background: var(--bg-secondary);\n border: 1px solid var(--border-color);\n border-radius: 8px;\n padding: 2rem;\n width: 100%;\n max-width: 400px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.8), 0 0 30px var(--accent-glow);\n text-align: center;\n}\n\n.room-prompt-box h2 {\n font-size: 1.5rem;\n color: var(--accent-secondary);\n text-shadow: 0 0 10px var(--accent-glow-cyan);\n margin-bottom: 1.5rem;\n}\n\n#room-name-input {\n width: 100%;\n background: var(--bg-primary);\n border: 1px solid var(--border-color);\n border-radius: 4px;\n padding: 0.75rem 1rem;\n color: var(--text-primary);\n font-family: inherit;\n font-size: 1rem;\n margin-bottom: 1rem;\n transition: all 0.3s ease;\n}\n\n#room-name-input:focus {\n outline: none;\n border-color: var(--accent-primary);\n box-shadow: 0 0 15px var(--accent-glow);\n}\n\n.btn-primary {\n background: linear-gradient(135deg, var(--accent-primary), #ff4080);\n border: none;\n border-radius: 4px;\n padding: 0.75rem 1.5rem;\n color: white;\n font-family: inherit;\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.3s ease;\n box-shadow: 0 4px 15px var(--accent-glow);\n}\n\n.btn-primary:hover:not(:disabled) {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px var(--accent-glow);\n}\n\n.btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n box-shadow: none;\n}\n\n#room-join-btn,\n#tab-retry-btn {\n width: 100%;\n}\n\n.room-hint {\n color: var(--text-muted);\n font-size: 0.85rem;\n margin-top: 1rem;\n font-style: italic;\n}\n\n/* ============================================\n RESPONSIVE\n ============================================ */\n\n@media (max-width: 768px) {\n .sidebar {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 200px;\n z-index: 200;\n transform: translateX(100%);\n transition: transform 0.3s ease;\n }\n\n .sidebar.open {\n transform: translateX(0);\n }\n\n .sidebar.collapsed {\n width: 200px;\n }\n\n .chat-header {\n padding: 0.75rem 1rem;\n }\n\n .logo-text {\n font-size: 1rem;\n }\n\n .header-stats {\n gap: 0.5rem;\n }\n\n .stat-badge,\n .status-badge {\n font-size: 0.75rem;\n padding: 0.3rem 0.6rem;\n }\n\n .stats-panel {\n width: calc(100vw - 40px);\n right: 20px;\n left: 20px;\n }\n\n #nickname {\n width: 100px;\n }\n}\n";