CSS

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";