Dhurgh's picture
Configure server to read cloud database environment variables
09675a5
Raw
History Blame Contribute Delete
139 kB
<!DOCTYPE html>
<!-- GenAI disclosure: I have used GenAI here to fix some bugs and errors that were present in these lines of codes. -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FireTech</title>
<link rel="icon" type="image/png" href="images/logo.png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* I'm resetting everything here so I don't have to fight the browser's default margins */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
input, textarea {
caret-color: var(--primary-color);
}
:root {
--primary-color: #5865f2;
--secondary-color: #404249;
--bg-color: #36393f;
--chat-bg: #2c2f33;
--sidebar-bg: #2f3136;
--text-primary: #ffffff;
--text-secondary: #b9bbbe;
--ui-text-color: #ffffff;
--border-color: #202225;
--shadow: 0 2px 10px rgba(0,0,0,0.3);
--success: #43b581;
--danger: #f04747;
}
[data-theme="light"] {
--primary-color: #5865f2;
--secondary-color: #99aab5;
--bg-color: #ffffff;
--chat-bg: #f2f3f5;
--sidebar-bg: #f9f9f9;
--text-primary: #2e3338;
--text-secondary: #747f8d;
--ui-text-color: #2e3338;
--border-color: #e3e5e8;
--shadow: 0 2px 10px rgba(0,0,0,0.1);
--success: #43b581;
--danger: #f04747;
}
body {
font-family: 'Whitney', 'Helvetica Neue', Helvetica, Arial, sans-serif;
background: var(--bg-color);
color: var(--text-primary);
overflow: hidden;
}
.auth-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, var(--primary-color), #1a1a2e);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
}
.auth-box {
background: var(--bg-color);
padding: 40px;
border-radius: 10px;
box-shadow: var(--shadow);
width: 100%;
max-width: 400px;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from { transform: translateY(30px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.auth-box h2 {
margin-bottom: 30px;
color: var(--primary-color);
font-size: 28px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-size: 14px;
font-weight: 500;
}
.form-group input {
width: 100%;
padding: 12px;
background: var(--chat-bg);
border: 1px solid var(--border-color);
border-radius: 4px;
color: var(--text-primary);
font-size: 14px;
transition: all 0.2s ease;
}
.form-group input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(88, 101, 242, 0.1);
}
.auth-button {
width: 100%;
padding: 12px;
background: var(--primary-color);
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.auth-button:hover {
background: #4752c4;
}
.auth-button:active {
transform: scale(0.98);
}
.auth-toggle {
text-align: center;
margin-top: 15px;
font-size: 14px;
color: var(--text-secondary);
}
.auth-toggle button {
background: none;
border: none;
color: var(--primary-color);
cursor: pointer;
text-decoration: underline;
}
.auth-inline-link {
margin-top: -10px;
margin-bottom: 14px;
text-align: right;
}
.auth-inline-link button {
background: none;
border: none;
color: var(--primary-color);
cursor: pointer;
font-size: 13px;
text-decoration: underline;
padding: 0;
}
.reset-password-panel {
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid var(--border-color);
display: none;
}
.reset-password-panel.show {
display: block;
}
.auth-mini-button {
width: 100%;
margin-top: 8px;
padding: 10px;
border: 1px solid var(--primary-color);
border-radius: 6px;
background: transparent;
color: var(--primary-color);
cursor: pointer;
}
.auth-status {
margin-top: 12px;
font-size: 13px;
min-height: 18px;
color: var(--text-secondary);
text-align: center;
line-height: 1.35;
}
.main-container {
display: grid;
grid-template-columns: 72px 240px 1fr 240px;
height: 100vh;
gap: 0;
}
.main-container.hidden {
display: none;
}
.guild-sidebar {
background: var(--sidebar-bg);
display: flex;
flex-direction: column;
align-items: center;
padding: 8px 0;
border-right: 1px solid var(--border-color);
}
.guild-item {
width: 56px;
height: 56px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary-color), #4752c4);
display: flex;
align-items: center;
justify-content: center;
color: white;
cursor: pointer;
margin-bottom: 8px;
transition: all 0.2s ease;
font-size: 24px;
}
.guild-item:hover {
border-radius: 40%;
transform: scale(1.1);
}
.guild-item.active {
border-radius: 40%;
background: var(--primary-color);
}
.guild-divider {
width: 32px;
height: 2px;
background: var(--border-color);
margin: 8px 0;
}
/* ====== APP LOADER ====== */
#appLoader {
position: fixed; inset: 0; z-index: 999999;
background:
radial-gradient(circle at 50% 42%, rgba(92, 126, 255, 0.28) 0%, rgba(92, 126, 255, 0.08) 18%, transparent 36%),
radial-gradient(circle at 50% 70%, rgba(10, 18, 40, 0.65) 0%, transparent 40%),
linear-gradient(180deg, #07101f 0%, #081423 28%, #0d1730 55%, #04070f 100%);
display: flex; align-items: center; justify-content: center; flex-direction: column;
transition: opacity 0.7s ease; user-select: none;
overflow: hidden;
}
#appLoader.fade-out { opacity: 0; pointer-events: none; }
.loader-scene {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.loader-aura {
position: absolute;
width: 220px;
height: 220px;
border-radius: 50%;
background: radial-gradient(circle, rgba(113, 164, 255, 0.48) 0%, rgba(77, 119, 243, 0.16) 35%, rgba(22, 31, 73, 0) 72%);
filter: blur(6px);
animation: loaderAuraPulse 2.8s ease-in-out infinite;
}
.loader-stage-ring {
position: absolute;
width: 300px;
height: 80px;
border-radius: 50%;
background: radial-gradient(circle, rgba(52, 112, 255, 0.26) 0%, rgba(13, 24, 57, 0.08) 45%, transparent 75%);
bottom: 86px;
filter: blur(10px);
}
.loader-fire-emoji {
position: relative;
font-size: 88px; display: block;
animation: loaderFirePulse 1.25s ease-in-out infinite;
filter: drop-shadow(0 0 18px rgba(255, 152, 77, 0.95)) drop-shadow(0 0 36px rgba(80, 135, 255, 0.38));
z-index: 2;
}
@keyframes loaderFirePulse {
0%, 100% { transform: translateY(0) scale(1) rotate(-3deg); }
50% { transform: translateY(-4px) scale(1.16) rotate(3deg); }
}
@keyframes loaderAuraPulse {
0%, 100% { transform: scale(0.94); opacity: 0.72; }
50% { transform: scale(1.08); opacity: 1; }
}
.loader-app-name {
font-size: 46px;
font-weight: 900;
letter-spacing: 8px;
text-transform: uppercase;
/* Updated to Blue -> Cyan gradient */
background: linear-gradient(90deg, #5f7eff 0%, #7b9cff 50%, #9cc4ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-top: 12px;
line-height: 1;
}
.loader-tagline {
color: rgba(255,255,255,0.35); font-size: 12px; letter-spacing: 4px;
text-transform: uppercase; margin-top: 10px; font-weight: 500;
}
.loader-progress-wrap {
width: 280px; height: 5px; background: rgba(255,255,255,0.07);
border-radius: 999px; margin-top: 44px; overflow: hidden; position: relative;
}
.loader-progress-bar {
height: 100%;
width: 0%;
border-radius: 999px;
/* Matching the logo's deep blue to light blue */
background: linear-gradient(90deg, #3470ff, #5f7eff, #9cc4ff);
transition: width 0.18s ease;
position: relative;
box-shadow: 0 0 10px rgba(95, 126, 255, 0.4);
}
.loader-progress-bar::after {
content: ''; position: absolute; right: 0; top: 0; bottom: 0; width: 36px;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.55));
border-radius: 0 999px 999px 0;
animation: loaderShimmer 1s ease-in-out infinite;
}
@keyframes loaderShimmer { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }
.loader-status {
margin-top: 16px; font-size: 11px; color: rgba(255,255,255,0.28);
letter-spacing: 3px; text-transform: uppercase; min-height: 14px;
}
/* ====== LANGUAGE PICKER ====== */
.lang-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 10px;
max-height: 56vh;
overflow-y: auto;
padding-right: 4px;
width: 100%;
}
.lang-btn {
display: flex; align-items: center; gap: 10px; padding: 11px 12px;
background: var(--bg-color); border: 1px solid var(--border-color);
border-radius: 12px; cursor: pointer; text-align: left; transition: all 0.18s;
min-height: 64px;
}
.lang-btn:hover {
border-color: #ff9d4d;
background: linear-gradient(135deg, rgba(255,157,77,0.14), rgba(88,101,242,0.14));
transform: translateY(-1px);
}
.lang-btn.active {
border-color: var(--primary-color);
background: linear-gradient(135deg, rgba(88,101,242,0.26), rgba(156,196,255,0.16));
box-shadow: 0 6px 16px rgba(88, 101, 242, 0.25);
}
.lang-flag {
font-size: 22px;
min-width: 38px;
width: 38px;
height: 38px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: radial-gradient(circle at 30% 20%, rgba(255,255,255,0.25), rgba(88,101,242,0.15));
border: 1px solid rgba(255,255,255,0.18);
}
.lang-info-name { font-size: 13px; font-weight: 700; }
.lang-info-country { font-size: 11px; color: var(--text-secondary); margin-top: 1px; }
img.twemoji {
width: 1.08em;
height: 1.08em;
vertical-align: -0.14em;
}
#languageSettings {
max-width: 100%;
width: 100%;
}
#languageSettings .settings-item {
max-width: 980px;
margin: 0 auto;
}
@media (max-width: 900px) {
.lang-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 640px) {
.lang-grid {
grid-template-columns: 1fr;
}
}
.channel-sidebar {
background: var(--sidebar-bg);
border-right: 1px solid var(--border-color);
display: flex;
flex-direction: column;
min-height: 0;
}
.sidebar-header {
padding: 16px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.sidebar-header h3 {
font-size: 16px;
font-weight: 600;
}
.sidebar-header button {
background: none;
border: none;
color: var(--primary-color);
cursor: pointer;
font-size: 20px;
}
.channels-list {
flex: 1;
overflow-y: auto;
padding: 8px 0;
scrollbar-gutter: stable;
min-height: 0;
padding-bottom: 24px;
}
.archived-modal-content {
background: var(--chat-bg);
padding: 20px;
border-radius: 10px;
width: min(95vw, 900px);
max-height: 88vh;
display: flex;
flex-direction: column;
box-shadow: 0 16px 44px rgba(0,0,0,0.55);
border: 1px solid var(--border-color);
}
.archived-modal-list {
flex: 1;
overflow-y: auto;
margin-top: 10px;
padding-right: 4px;
min-height: 260px;
scrollbar-gutter: stable;
overscroll-behavior: contain;
}
.archived-modal-list::-webkit-scrollbar {
width: 10px;
}
.archived-modal-list::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.22);
border-radius: 8px;
border: 2px solid transparent;
background-clip: content-box;
}
.archived-modal-list::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.06);
border-radius: 8px;
}
.channel-item {
padding: 8px 16px;
color: var(--text-secondary);
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
transition: all 0.2s ease;
min-width: 0;
position: relative;
z-index: 1;
}
.channel-label {
min-width: 0;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.channel-item:hover {
background: var(--chat-bg);
color: var(--text-primary);
}
.channel-item.active {
background: var(--primary-color);
color: white;
}
.channel-item.pinned {
background: rgba(88, 101, 242, 0.1);
border-left: 3px solid var(--primary-color);
font-weight: 600;
}
.channel-item .pin-indicator {
margin-left: auto;
color: var(--primary-color);
font-size: 12px;
}
.channel-icon {
font-size: 16px;
}
.channel-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary-color), #4752c4);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
font-size: 14px;
flex-shrink: 0;
}
.member-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary-color), #4752c4);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
font-size: 14px;
flex-shrink: 0;
}
.channel-section-title {
padding: 10px;
color: var(--text-secondary);
font-size: 12px;
font-weight: bold;
position: relative;
background: var(--sidebar-bg);
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
}
.chat-area {
position: relative;
display: flex;
flex-direction: column;
background: var(--chat-bg);
min-height: 0;
overflow: hidden;
}
.chat-header {
padding: 16px 24px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.chat-header-left {
display: flex;
align-items: center;
gap: 12px;
}
.chat-header-title {
font-size: 18px;
font-weight: 600;
}
.chat-header-actions {
display: flex;
align-items: center;
gap: 12px;
}
.build-badge {
padding: 4px 8px;
border: 1px solid var(--border-color);
border-radius: 999px;
font-size: 11px;
color: var(--text-secondary);
background: var(--bg-color);
}
.header-btn {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 18px;
transition: all 0.2s ease;
}
@keyframes headerFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-2px); }
}
.chat-header-actions .header-btn {
animation: headerFloat 3.6s ease-in-out infinite;
}
.chat-header-actions .header-btn:nth-child(2) { animation-delay: 0.25s; }
.chat-header-actions .header-btn:nth-child(3) { animation-delay: 0.5s; }
.chat-header-actions .header-btn:nth-child(4) { animation-delay: 0.75s; }
.chat-header-actions .header-btn:nth-child(5) { animation-delay: 1s; }
.header-btn:hover {
color: var(--text-primary);
}
.header-btn.danger {
color: var(--danger);
}
.header-btn.success {
color: var(--success);
}
.mobile-essential {
display: inline-flex;
}
#messages-container {
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
padding: 16px 24px;
padding-right: 44px;
padding-bottom: 24px;
display: flex;
flex-direction: column;
gap: 12px;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
}
#messages-container::-webkit-scrollbar {
width: 0;
height: 0;
}
#messages-container {
scrollbar-width: none;
}
.chat-scroll-rail {
position: absolute;
top: 72px;
right: 8px;
bottom: 84px;
width: 14px;
border-radius: 999px;
background: #d8d8d8;
border: 1px solid #c5c5c5;
z-index: 12;
cursor: pointer;
}
.chat-scroll-thumb {
width: 100%;
min-height: 56px;
border-radius: 999px;
background: linear-gradient(180deg, #10d9a6 0%, #00b88f 50%, #009a78 100%);
border: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
transform: translateY(0);
transition: background 0.15s ease;
}
.chat-scroll-thumb:hover {
background: linear-gradient(180deg, #20ecb8 0%, #00c79a 50%, #00ab86 100%);
}
.chat-scroll-rail.hidden {
display: none;
}
.message {
display: flex;
gap: 12px;
animation: fadeIn 0.2s ease;
scroll-snap-align: end;
scroll-snap-stop: always;
min-width: 0;
max-width: 100%;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.message-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary-color), #4752c4);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
flex-shrink: 0;
}
.message-content {
flex: 1;
min-width: 0;
max-width: 100%;
}
.message-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 4px;
}
.message-actions {
position: absolute;
top: -8px;
right: 8px;
display: none;
gap: 4px;
background: var(--chat-bg);
padding: 6px 8px;
border-radius: 18px;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
border: 1px solid var(--border-color);
flex-direction: row;
align-items: center;
}
.message.message-actions-open .message-actions {
display: flex;
}
.message-action-btn {
background: transparent;
border: none;
color: var(--text-secondary);
padding: 6px 10px;
border-radius: 12px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 4px;
}
.message-action-btn:hover {
background: var(--bg-color);
color: var(--primary-color);
transform: scale(1.05);
}
.message-reactions {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 6px;
margin-top: 8px;
align-items: center;
}
.reaction-item {
background: var(--bg-color);
border: 1px solid var(--border-color);
padding: 2px 8px;
border-radius: 12px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 4px;
}
.reaction-item:hover {
background: var(--primary-color);
border-color: var(--primary-color);
transform: scale(1.05);
}
.reaction-count {
font-size: 11px;
color: var(--text-secondary);
font-weight: 600;
}
.message-username {
font-weight: 600;
color: var(--primary-color);
}
.message-time {
font-size: 11px;
color: var(--text-secondary);
display: block;
margin-top: 2px;
}
.message-text {
color: var(--text-primary);
line-height: 1.5;
overflow-wrap: anywhere;
word-break: break-word;
max-width: 100%;
}
.message-media {
margin-top: 8px;
border-radius: 8px;
max-width: 400px;
width: min(100%, 400px);
overflow: hidden;
}
.message-media img {
max-width: 100%;
border-radius: 8px;
display: block;
}
.message-media video {
max-width: 100%;
border-radius: 8px;
display: block;
cursor: pointer;
}
.message-media video {
max-width: 100%;
border-radius: 4px;
}
.draft-preview {
margin: 8px 24px 0;
padding: 10px;
border: 1px solid var(--border-color);
border-radius: 8px;
background: var(--bg-color);
display: none;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.draft-preview.show {
display: flex;
}
.draft-preview-left {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
flex: 1;
}
.draft-preview-thumb {
width: 56px;
height: 56px;
border-radius: 6px;
object-fit: cover;
border: 1px solid var(--border-color);
background: var(--chat-bg);
display: none;
}
.draft-preview-emoji {
font-size: 36px;
line-height: 1;
display: none;
}
.draft-preview-meta {
font-size: 12px;
color: var(--text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.draft-clear-btn {
border: 1px solid var(--danger);
color: var(--danger);
background: transparent;
border-radius: 6px;
padding: 6px 10px;
cursor: pointer;
}
.input-area {
padding: 16px 24px;
border-top: 1px solid var(--border-color);
display: flex;
gap: 12px;
background: var(--chat-bg);
z-index: 10;
flex-shrink: 0;
}
.input-area input {
flex: 1;
background: var(--bg-color);
border: 1px solid var(--border-color);
border-radius: 21px;
padding: 11px 16px;
color: var(--text-primary);
font-size: 14px;
transition: all 0.2s ease;
}
.input-area input:focus {
outline: none;
border-color: var(--primary-color);
}
.input-btn {
width: 44px;
height: 44px;
border-radius: 50%;
background: var(--primary-color);
border: none;
color: white;
cursor: pointer;
font-size: 18px;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.input-btn:hover {
background: var(--primary-color);
opacity: 0.85;
transform: scale(1.05);
}
.input-file {
display: none;
}
.members-sidebar {
background: var(--sidebar-bg);
border-left: 1px solid var(--border-color);
display: flex;
flex-direction: column;
max-width: 240px;
}
.members-header {
padding: 16px;
border-bottom: 1px solid var(--border-color);
font-weight: 600;
font-size: 14px;
}
.members-list {
flex: 1;
overflow-y: scroll;
padding: 8px;
scrollbar-gutter: stable;
}
.member-item {
padding: 8px 12px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
transition: all 0.2s ease;
font-size: 14px;
}
.member-item:hover {
background: var(--chat-bg);
}
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--success);
}
.status-indicator.offline {
background: var(--text-secondary);
}
.profile-panel {
position: fixed;
right: 0;
top: 0;
width: 400px;
height: 100%;
background: var(--chat-bg);
border-left: 1px solid var(--border-color);
z-index: 1000;
transform: translateX(400px);
transition: transform 0.3s ease;
overflow-y: auto;
display: flex;
flex-direction: column;
visibility: hidden;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
touch-action: pan-y;
pointer-events: none;
}
.profile-panel.show {
transform: translateX(0);
visibility: visible;
pointer-events: auto;
}
.profile-banner-wrap {
position: relative;
width: 100%;
height: 160px;
background: linear-gradient(135deg, var(--primary-color), #4752c4);
overflow: hidden;
flex-shrink: 0;
}
.profile-banner-img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.profile-banner-edit-btn {
position: absolute;
bottom: 8px;
right: 8px;
background: rgba(0,0,0,0.55);
border: none;
color: white;
border-radius: 6px;
padding: 4px 10px;
font-size: 12px;
cursor: pointer;
transition: background 0.2s;
}
.profile-banner-edit-btn:hover { background: rgba(0,0,0,0.85); }
#callOverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
display: none;
touch-action: manipulation;
background: rgba(0,0,0,0.55);
}
#callOverlay.active {
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.call-overlay-stage {
position: relative;
width: min(920px, 100%);
height: min(84vh, 720px);
border-radius: 18px;
overflow: hidden;
background: #0f1116;
box-shadow: 0 28px 80px rgba(0,0,0,0.55);
border: 1px solid rgba(255,255,255,0.12);
}
#callOverlay:not(.desktop-window) .call-overlay-stage {
width: 100%;
height: 100%;
border-radius: 0;
border: none;
box-shadow: none;
}
#remoteCallVideo, #localCallVideo, #localCallVideoOld {
display: block;
}
#hostedCallContainer {
position: absolute;
inset: 0;
z-index: 1;
display: none;
background: #0f1116;
}
#hostedCallContainer iframe {
width: 100%;
height: 100%;
border: 0;
}
#remoteCallVideo {
pointer-events: none;
}
.call-overlay-header {
position: absolute;
top: 0; left: 0; right: 0;
padding: 16px 20px;
background: linear-gradient(180deg, rgba(0,0,0,0.75), transparent);
z-index: 4;
display: flex;
align-items: center;
justify-content: space-between;
pointer-events: auto;
}
.call-overlay-controls {
position: absolute;
bottom: 0; left: 0; right: 0;
padding: 24px 20px 32px;
background: linear-gradient(0deg, rgba(0,0,0,0.75), transparent);
display: flex;
justify-content: center;
gap: 20px;
z-index: 5;
pointer-events: auto;
touch-action: manipulation;
}
.call-ctrl-btn {
width: 64px; height: 64px;
border-radius: 50%;
background: rgba(255,255,255,0.18);
border: 2px solid rgba(255,255,255,0.3);
color: white;
font-size: 24px;
cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: all 0.2s;
pointer-events: auto;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
.call-ctrl-btn:hover { background: rgba(255,255,255,0.35); transform: scale(1.08); }
.call-ctrl-btn:active { transform: scale(0.96); }
.call-ctrl-btn.muted { background: rgba(240,71,71,0.5); border-color: #f04747; }
.call-ctrl-btn.cam-off { background: rgba(240,71,71,0.5); border-color: #f04747; }
.call-end-btn {
width: 72px; height: 72px;
background: #f04747;
border: none;
border-radius: 50%;
color: white;
font-size: 26px;
cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: all 0.2s;
pointer-events: auto;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
.call-end-btn:hover { background: #c0392b; transform: scale(1.1); }
@media (max-width: 700px) {
#callOverlay.active {
padding: 0;
}
.call-overlay-stage {
width: 100%;
height: 100%;
border-radius: 0;
border: none;
box-shadow: none;
}
}
#callDebugPanel {
position: absolute;
top: 80px; right: 10px;
background: rgba(0,0,0,0.88);
color: #00ff88;
font-size: 11px;
padding: 12px;
border-radius: 8px;
z-index: 3;
min-width: 230px;
font-family: monospace;
border: 1px solid #00ff88;
display: none;
}
#callDebugPanel .dbg-row { margin-bottom: 4px; }
#callDebugPanel .dbg-log {
margin-top: 8px;
max-height: 180px;
overflow-y: auto;
border-top: 1px solid rgba(0,255,136,0.35);
padding-top: 8px;
color: #c7ffd9;
}
#callDebugPanel .dbg-log div {
margin-bottom: 4px;
line-height: 1.35;
word-break: break-word;
}
.notif-bell-btn {
position: relative;
}
.notif-badge {
position: absolute;
top: -3px; right: -3px;
background: #f04747;
color: white;
border-radius: 50%;
width: 16px; height: 16px;
font-size: 9px;
font-weight: 700;
display: none;
align-items: center;
justify-content: center;
line-height: 1;
}
.notif-badge.visible { display: flex; }
#notifPanel {
position: fixed;
top: 0; right: -360px;
width: 340px;
max-height: 100vh;
background: var(--chat-bg);
border-left: 1px solid var(--border-color);
z-index: 1050;
transition: right 0.3s ease;
overflow-y: auto;
box-shadow: -4px 0 24px rgba(0,0,0,0.4);
display: flex; flex-direction: column;
}
#notifPanel.show { right: 0; }
.notif-panel-header {
padding: 16px 18px;
border-bottom: 1px solid var(--border-color);
display: flex; align-items: center; justify-content: space-between;
position: sticky; top: 0;
background: var(--chat-bg);
z-index: 2;
}
.notif-item {
padding: 12px 16px;
border-bottom: 1px solid var(--border-color);
cursor: pointer;
transition: background 0.15s;
}
.notif-item:hover { background: var(--bg-color); }
.notif-item.notif-unread { background: rgba(88,101,242,0.1); border-left: 3px solid var(--primary-color); }
.notif-item-title { font-size: 13px; font-weight: 600; margin-bottom: 3px; }
.notif-item-body { font-size: 12px; color: var(--text-secondary); }
.notif-item-time { font-size: 10px; color: var(--text-secondary); margin-top: 4px; }
.upload-progress-bar {
height: 3px;
background: linear-gradient(90deg, var(--primary-color), #4752c4);
border-radius: 2px;
width: 0%;
transition: width 0.3s ease;
position: absolute;
top: 0; left: 0; right: 0;
}
.upload-overlay {
position: absolute;
inset: 0;
background: rgba(0,0,0,0.4);
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
z-index: 5;
}
@keyframes spin { to { transform: rotate(360deg); } }
.spinner-ring {
width: 40px; height: 40px;
border: 3px solid rgba(255,255,255,0.2);
border-top-color: white;
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
.input-area { position: relative; }
.input-upload-spinner {
position: absolute;
top: -2px; left: 0; right: 0;
height: 3px;
background: var(--bg-color);
border-radius: 2px;
overflow: hidden;
}
.input-upload-spinner-bar {
height: 100%;
background: linear-gradient(90deg, var(--primary-color), var(--success), var(--primary-color));
background-size: 200% 100%;
animation: shimmerSlide 1s linear infinite;
width: 100%;
}
@keyframes shimmerSlide {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.message { transition: background 0.15s; border-radius: 8px; padding: 4px 6px; }
.message:hover { background: rgba(88, 101, 242, 0.08); }
.friend-item { transition: all 0.18s ease; }
.friend-item:hover { transform: translateX(3px); box-shadow: -3px 0 0 #ff9d4d; }
.guild-item { transition: all 0.2s; }
.guild-item:hover:not(.active) { border-radius: 16px; background: linear-gradient(135deg, #ff9d4d, #5f7eff); transform: scale(1.08); }
.header-btn { transition: all 0.18s; }
.header-btn:hover { background: rgba(88,101,242,0.25); transform: scale(1.12); border-radius: 6px; box-shadow: 0 2px 8px rgba(88,101,242,0.3); }
.input-btn { transition: all 0.18s; }
.input-btn:hover { background: linear-gradient(135deg, rgba(255,157,77,0.25), rgba(88,101,242,0.25)); color: #ff9d4d; transform: scale(1.1); box-shadow: 0 2px 8px rgba(255,157,77,0.2); }
.tab-btn { transition: all 0.18s; }
.tab-btn:hover:not(.active) { background: rgba(88,101,242,0.15); transform: translateY(-2px); }
.secondary-btn { transition: all 0.18s; }
.secondary-btn:hover { background: rgba(88,101,242,0.28); transform: translateY(-2px); box-shadow: 0 4px 14px rgba(88,101,242,0.35); }
.save-btn { transition: all 0.18s; }
.save-btn:hover { filter: brightness(1.15); transform: translateY(-2px); box-shadow: 0 4px 16px rgba(88,101,242,0.4); }
.message-action-btn { transition: all 0.18s; }
.message-action-btn:hover { background: #ff9d4d !important; color: white; transform: scale(1.2); box-shadow: 0 3px 12px rgba(255,157,77,0.4); }
.mobile-nav-item { transition: all 0.2s; }
.mobile-nav-item:hover, .mobile-nav-item.active { color: #ff9d4d; }
.settings-nav-item { transition: all 0.15s; }
.settings-nav-item:hover { background: linear-gradient(135deg, rgba(255,157,77,0.1), rgba(88,101,242,0.1)); color: #ff9d4d; transform: translateX(2px); }
.groups-search { width: 100%; padding: 10px 14px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-primary); font-size: 14px; margin-bottom: 12px; }
.groups-search:focus { outline: none; border-color: var(--primary-color); }
.group-card {
display: flex; align-items: center; gap: 14px;
padding: 14px 16px;
background: var(--bg-color);
border-radius: 10px;
margin-bottom: 10px;
border: 1px solid var(--border-color);
transition: border-color 0.2s, transform 0.2s, box-shadow 0.2s;
}
.group-card:hover { border-color: var(--primary-color); transform: translateY(-2px); box-shadow: 0 4px 16px rgba(0,0,0,0.3); }
.group-avatar { width: 48px; height: 48px; border-radius: 14px; background: linear-gradient(135deg, var(--primary-color), #4752c4); display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0; }
.emoji-glyph {
font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
font-size: 24px;
line-height: 1;
filter: none !important;
color: initial;
text-shadow: none;
}
.group-info { flex: 1; min-width: 0; }
.group-name { font-weight: 700; font-size: 15px; }
.group-desc { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.group-members-count { font-size: 11px; color: var(--text-secondary); margin-top: 4px; }
.create-group-btn { width: 100%; padding: 12px; background: linear-gradient(135deg, var(--primary-color), #4752c4); color: white; border: none; border-radius: 10px; cursor: pointer; font-size: 15px; font-weight: 700; margin-bottom: 14px; transition: all 0.2s; }
.create-group-btn:hover { filter: brightness(1.1); transform: translateY(-2px); }
.profile-close {
position: sticky;
top: 8px;
z-index: 100;
align-self: flex-end;
margin: 8px 10px -44px 0;
background: rgba(0,0,0,0.55);
border: none;
color: white;
font-size: 18px;
cursor: pointer;
width: 34px;
height: 34px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: background 0.2s;
}
.profile-header {
padding: 60px 24px 24px;
text-align: center;
border-bottom: 1px solid var(--border-color);
}
.profile-avatar {
width: 80px;
height: 80px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary-color), #4752c4);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 40px;
margin: 0 auto 12px;
}
.profile-name {
font-size: 20px;
font-weight: 600;
}
.profile-bio {
font-size: 14px;
color: var(--text-secondary);
margin-top: 8px;
}
.profile-content {
padding: 24px;
flex: 1;
min-height: 0;
overflow: visible;
padding-bottom: 34px;
}
.tab-buttons {
display: flex;
gap: 12px;
margin-bottom: 24px;
}
.tab-btn {
flex: 1;
padding: 8px;
background: var(--bg-color);
border: 1px solid var(--border-color);
color: var(--text-secondary);
cursor: pointer;
border-radius: 4px;
font-size: 12px;
transition: all 0.2s ease;
}
.tab-btn.active {
background: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.form-field {
margin-bottom: 16px;
}
.form-field label {
display: block;
font-size: 12px;
font-weight: 600;
margin-bottom: 8px;
}
.form-field input,
.form-field textarea {
width: 100%;
padding: 8px;
background: var(--bg-color);
border: 1px solid var(--border-color);
border-radius: 4px;
color: var(--text-primary);
font-size: 14px;
font-family: inherit;
}
.form-field textarea {
resize: vertical;
min-height: 80px;
}
.save-btn {
width: 100%;
padding: 10px;
background: var(--primary-color);
color: white;
border: none;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.save-btn:hover {
background: #4752c4;
}
.secondary-btn {
width: 100%;
padding: 10px;
background: var(--secondary-color);
color: white;
border: none;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.secondary-btn:hover {
opacity: 0.9;
}
.shop-item {
background: var(--bg-color);
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 12px;
margin-bottom: 12px;
display: flex;
justify-content: space-between;
align-items: center;
}
.shop-hero {
padding: 16px;
margin-bottom: 12px;
border-radius: 10px;
border: 1px solid rgba(255,255,255,0.12);
background: linear-gradient(135deg, rgba(88,101,242,0.28), rgba(67,181,129,0.15));
}
.shop-hero-title {
font-size: 18px;
font-weight: 800;
margin-bottom: 4px;
}
.shop-hero-subtitle {
font-size: 12px;
color: var(--text-secondary);
}
.shop-hero-discount {
margin-top: 10px;
display: inline-flex;
padding: 4px 10px;
border-radius: 999px;
font-size: 11px;
font-weight: 700;
color: #fff;
background: linear-gradient(135deg, #ff7b54, #ffb347);
}
.shop-item-name {
font-weight: 600;
font-size: 14px;
}
.shop-item-price {
color: var(--success);
font-weight: 600;
margin-right: 12px;
}
.buy-btn {
padding: 6px 12px;
background: var(--primary-color);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.buy-btn:disabled {
opacity: 0.55;
cursor: not-allowed;
}
.orb-card {
padding: 12px;
border: 1px solid var(--border-color);
border-radius: 10px;
background: var(--bg-color);
margin-bottom: 10px;
}
.saved-pill {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-radius: 999px;
border: 1px solid var(--border-color);
background: var(--bg-color);
margin: 0 8px 8px 0;
font-size: 12px;
}
.orb-none {
--orb-glow: transparent;
}
.orb-aurora {
--primary-color: #57c7ff;
--secondary-color: #3d6f9a;
--orb-glow: rgba(87, 199, 255, 0.35);
}
.orb-neon-pulse {
--primary-color: #42e695;
--secondary-color: #1f8c58;
--orb-glow: rgba(66, 230, 149, 0.35);
}
.orb-ocean-mist {
--primary-color: #5fa8ff;
--secondary-color: #2e5384;
--orb-glow: rgba(95, 168, 255, 0.3);
}
.orb-ember {
--primary-color: #ff8f5e;
--secondary-color: #8b3b1d;
--orb-glow: rgba(255, 143, 94, 0.35);
}
.orb-aurora .profile-avatar,
.orb-neon-pulse .profile-avatar,
.orb-ocean-mist .profile-avatar,
.orb-ember .profile-avatar {
box-shadow: 0 0 0 6px var(--orb-glow);
transition: box-shadow 0.3s ease;
}
.friend-item {
padding: 12px;
background: var(--bg-color);
border-radius: 4px;
margin-bottom: 12px;
display: flex;
justify-content: space-between;
align-items: center;
}
.friend-name {
font-weight: 600;
font-size: 14px;
}
.friend-status {
font-size: 12px;
color: var(--text-secondary);
}
.coins-display {
font-size: 14px;
color: var(--success);
font-weight: 600;
margin-bottom: 16px;
}
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 3000;
display: flex;
flex-direction: column;
gap: 10px;
}
.toast {
background: var(--chat-bg);
border-left: 4px solid var(--success);
padding: 16px 20px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
min-width: 300px;
display: flex;
align-items: center;
gap: 12px;
animation: slideInRight 0.3s ease, fadeOut 0.3s ease 2.7s;
cursor: pointer;
transition: transform 0.2s ease;
}
.toast:hover {
transform: translateX(-4px);
}
.toast.clickable {
cursor: pointer;
}
.toast.clickable:hover {
background: var(--bg-color);
transform: translateX(-8px) scale(1.02);
}
.toast.error {
border-left-color: var(--danger);
}
.toast.warning {
border-left-color: #faa61a;
}
.toast-icon {
font-size: 20px;
}
.toast-content {
flex: 1;
}
.toast-title {
font-weight: 600;
margin-bottom: 4px;
}
.toast-message {
font-size: 13px;
color: var(--text-secondary);
}
@keyframes slideInRight {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes fadeOut {
to { opacity: 0; transform: translateX(100%); }
}
.picker-panel {
--picker-scale: 1.45;
position: absolute;
bottom: 60px;
left: 50px;
width: calc(440px * var(--picker-scale));
height: calc(500px * var(--picker-scale));
max-width: min(96vw, 900px);
max-height: min(82vh, 760px);
background: var(--chat-bg);
border-radius: 8px 8px 0 0;
box-shadow: 0 -4px 24px rgba(0,0,0,0.3);
display: none;
z-index: 1002;
overflow: hidden;
}
.picker-panel.show {
display: flex;
flex-direction: column;
}
.profile-close:hover { background: rgba(255,255,255,0.25); }
#profileBackdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.45);
z-index: 999;
cursor: pointer;
}
.picker-tabs {
display: flex;
border-bottom: 1px solid var(--border-color);
}
.picker-size-controls {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 8px 10px;
border-bottom: 1px solid var(--border-color);
background: rgba(0, 0, 0, 0.08);
}
.picker-size-btn {
min-width: 34px;
height: 30px;
border-radius: 8px;
border: 1px solid var(--border-color);
background: var(--secondary-color);
color: var(--text-primary);
cursor: pointer;
font-weight: 700;
}
.picker-size-range {
width: 120px;
}
.picker-size-label {
min-width: 46px;
text-align: right;
font-size: 12px;
color: var(--text-secondary);
}
.picker-tab {
flex: 1;
padding: 12px;
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.2s;
font-size: 14px;
}
.picker-tab.active {
color: var(--primary-color);
border-bottom: 2px solid var(--primary-color);
}
.picker-content {
flex: 1;
overflow-y: auto;
padding: 14px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.picker-content.gifs-mode {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
padding: 18px;
}
.sticker-item, .gif-item {
font-size: 58px;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
text-align: center;
cursor: pointer;
padding: 10px;
border-radius: 10px;
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.08);
transition: all 0.2s;
}
.sticker-item:hover, .gif-item:hover {
background: var(--bg-color);
transform: scale(1.06);
}
.gif-item {
width: 100%;
height: 150px;
object-fit: cover;
border-radius: 12px;
}
.voice-recorder {
position: absolute;
bottom: 70px;
right: 20px;
background: var(--chat-bg);
border-radius: 8px;
padding: 20px;
box-shadow: 0 8px 24px rgba(0,0,0,0.4);
display: none;
flex-direction: column;
align-items: center;
gap: 12px;
z-index: 100;
min-width: 320px;
}
.voice-preview-container {
width: 100%;
margin-top: 8px;
padding: 12px;
background: rgba(88, 101, 242, 0.12);
border: 2px solid var(--primary-color);
border-radius: 8px;
}
.voice-preview-label {
font-size: 13px;
color: var(--primary-color);
margin-bottom: 8px;
font-weight: 700;
text-align: center;
}
.voice-recorder.show {
display: flex;
}
.record-button {
width: 60px;
height: 60px;
border-radius: 50%;
background: var(--danger);
border: none;
color: white;
font-size: 24px;
cursor: pointer;
transition: all 0.2s;
}
.record-button:hover {
transform: scale(1.1);
}
.record-button.recording {
animation: pulse 1s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.record-timer {
font-size: 18px;
font-weight: 600;
color: var(--danger);
}
.settings-panel {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.96);
width: min(920px, calc(100vw - 36px));
max-width: 920px;
height: min(82vh, 760px);
background: linear-gradient(180deg, rgba(35, 40, 74, 0.98) 0%, rgba(22, 25, 48, 0.98) 100%);
border: 1px solid rgba(111, 146, 255, 0.16);
border-radius: 22px;
box-shadow: 0 30px 90px rgba(0,0,0,0.48), 0 0 0 1px rgba(255,255,255,0.03) inset;
transition: opacity 0.28s ease, transform 0.28s ease;
z-index: 2500;
display: flex;
flex-direction: column;
opacity: 0;
pointer-events: none;
overflow: hidden;
backdrop-filter: blur(18px);
}
.settings-panel.show {
opacity: 1;
pointer-events: auto;
transform: translate(-50%, -50%) scale(1);
}
.settings-header {
padding: 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.settings-header h2 {
font-size: 20px;
color: var(--ui-text-color);
}
.settings-nav {
display: flex;
flex-direction: column;
border-right: 1px solid var(--border-color);
min-width: 140px;
}
.settings-nav-item {
padding: 12px 16px;
cursor: pointer;
transition: all 0.2s;
font-size: 14px;
border-left: 3px solid transparent;
color: var(--ui-text-color);
}
.settings-nav-item:hover {
background: var(--bg-color);
}
.settings-nav-item.active {
background: var(--bg-color);
border-left-color: var(--primary-color);
color: var(--primary-color);
}
.settings-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}
.settings-body {
display: flex;
flex: 1;
overflow: hidden;
}
.settings-section {
display: none;
}
.settings-section.active {
display: block;
}
.settings-section h3 {
color: var(--ui-text-color);
margin-bottom: 16px;
}
.settings-item {
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid var(--border-color);
}
.settings-item:last-child {
border-bottom: none;
}
.settings-label {
font-weight: 600;
margin-bottom: 8px;
font-size: 14px;
color: var(--ui-text-color);
}
.settings-description {
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 8px;
}
.toggle-switch {
position: relative;
display: inline-block;
width: 44px;
height: 24px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--secondary-color);
transition: 0.3s;
border-radius: 24px;
}
.toggle-slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
transition: 0.3s;
border-radius: 50%;
}
.toggle-switch input:checked + .toggle-slider {
background-color: var(--success);
}
.toggle-switch input:checked + .toggle-slider:before {
transform: translateX(20px);
}
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.6);
display: flex;
align-items: center;
justify-content: center;
z-index: 1500;
}
.modal.hidden {
display: none;
}
.modal-content {
background: var(--chat-bg);
padding: 32px;
border-radius: 8px;
max-width: 500px;
width: 90%;
box-shadow: 0 10px 40px rgba(0,0,0,0.5);
max-height: 90vh;
overflow-y: auto;
}
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--secondary-color);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #5a5d60;
}
.mobile-bottom-nav {
display: none;
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--sidebar-bg);
border-top: 2px solid var(--border-color);
z-index: 1000;
flex-direction: row;
justify-content: space-around;
padding: 8px 0;
box-shadow: 0 -4px 20px rgba(0,0,0,0.3);
}
.mobile-members-panel {
position: fixed;
right: -100%;
top: 0;
width: 80%;
max-width: 300px;
height: 100vh;
background: var(--sidebar-bg);
border-left: 1px solid var(--border-color);
z-index: 1500;
transition: right 0.3s ease;
display: flex;
flex-direction: column;
box-shadow: -4px 0 20px rgba(0,0,0,0.5);
}
.mobile-members-panel.show {
right: 0;
}
.mobile-members-header {
padding: 16px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.mobile-members-header h3 {
font-size: 16px;
font-weight: 600;
}
.mobile-members-list {
flex: 1;
overflow-y: auto;
padding: 8px;
}
.mobile-nav-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 8px;
border: none;
background: none;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.2s;
position: relative;
}
.mobile-nav-item.active {
color: var(--primary-color);
}
.mobile-nav-item i {
font-size: 22px;
}
.mobile-nav-item span {
font-size: 10px;
font-weight: 500;
}
.mobile-nav-badge {
position: absolute;
top: 4px;
right: 20%;
background: var(--danger);
color: white;
border-radius: 10px;
padding: 2px 6px;
font-size: 10px;
font-weight: bold;
min-width: 18px;
text-align: center;
}
@media (max-width: 1200px) {
.main-container {
grid-template-columns: 72px 240px 1fr;
}
.members-sidebar {
display: none;
}
.profile-panel {
width: 300px;
transform: translateX(300px);
}
.profile-panel.show {
transform: translateX(0);
}
}
@media (max-width: 768px) {
body {
overflow: hidden;
}
.main-container {
grid-template-columns: 45px 1fr;
height: 100vh;
height: 100dvh;
max-height: -webkit-fill-available;
}
.guild-sidebar {
padding: 2px 0;
width: 45px;
}
.guild-item {
width: 40px;
height: 40px;
font-size: 18px;
margin-bottom: 4px;
}
.guild-divider {
width: 24px;
margin: 4px 0;
}
/* Mobile Channel Sidebar */
.channel-sidebar {
display: none;
position: fixed;
left: 0;
top: 0;
width: 85%;
max-width: 320px;
height: 100%;
height: 100dvh;
z-index: 999;
box-shadow: 4px 0 20px rgba(0,0,0,0.5);
}
.channel-sidebar.show {
display: flex;
}
.channel-sidebar.show::before {
content: '';
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.5);
z-index: -1;
}
.chat-area {
height: 100vh;
height: 100dvh;
max-height: -webkit-fill-available;
}
.chat-header {
padding: 12px 16px;
flex-shrink: 0;
}
.chat-header-left {
flex: 1;
min-width: 0;
}
.chat-header-title {
font-size: 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.build-badge {
display: none;
}
.build-badge.mobile-essential {
display: inline-flex;
align-items: center;
}
.header-btn {
font-size: 16px;
padding: 8px;
}
.chat-header-actions {
gap: 4px;
flex-wrap: nowrap;
overflow-x: auto;
max-width: 56vw;
scrollbar-width: thin;
}
.chat-header-actions .header-btn {
padding: 6px;
min-width: 32px;
flex-shrink: 0;
}
#messages-container {
flex: 1;
min-height: 0;
max-height: none;
padding: 12px 16px;
padding-bottom: 16px;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
}
.message {
gap: 8px;
}
.message-avatar {
width: 36px;
height: 36px;
font-size: 16px;
}
.message-username {
font-size: 14px;
}
.message-text {
font-size: 14px;
}
.message-media {
max-width: 90%;
}
.input-area {
padding: 10px 8px;
gap: 6px;
flex-shrink: 0;
border-top: 2px solid var(--border-color);
display: grid;
grid-template-columns: auto auto auto auto minmax(0, 1fr) auto;
align-items: center;
}
.input-area input {
font-size: 16px;
padding: 9px 12px;
min-width: 0;
}
.input-btn {
width: 36px;
height: 36px;
font-size: 14px;
flex-shrink: 0;
}
.chat-scroll-rail {
right: 4px;
top: 64px;
bottom: 74px;
width: 12px;
}
.chat-scroll-thumb {
min-height: 40px;
}
.picker-panel {
width: 100%;
left: 0;
bottom: 0;
height: 68vh;
max-height: 68vh;
border-radius: 16px 16px 0 0;
}
.voice-recorder {
width: 90%;
left: 5%;
right: auto;
bottom: 80px;
}
.draft-preview {
margin: 8px 16px 0;
padding: 8px;
}
.settings-panel {
width: 100%;
max-width: none;
height: 100%;
top: 0;
left: 0;
border-radius: 0;
transform: translateY(18px);
}
.settings-panel.show {
transform: translateY(0);
}
.settings-body {
flex-direction: column;
}
.settings-nav {
flex-direction: row;
overflow-x: auto;
border-right: none;
border-bottom: 1px solid var(--border-color);
min-width: auto;
}
.settings-nav-item {
white-space: nowrap;
border-left: none;
border-bottom: 3px solid transparent;
font-size: 13px;
padding: 10px 14px;
}
.settings-nav-item.active {
border-left: none;
border-bottom-color: var(--primary-color);
}
.toast-container {
top: 10px;
right: 10px;
left: 10px;
}
.toast {
min-width: auto;
padding: 12px 16px;
}
.profile-panel {
width: 100%;
}
.members-sidebar {
display: none !important;
}
}
.custom-dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(8px);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
animation: fadeIn 0.2s ease;
}
.custom-dialog-content {
background: var(--chat-bg);
border-radius: 16px;
padding: 32px;
min-width: 400px;
max-width: 90%;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
animation: slideUp 0.3s ease;
border: 2px solid var(--primary-color);
}
.custom-dialog-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 20px;
}
.custom-dialog-icon {
font-size: 32px;
}
.custom-dialog-title {
font-size: 22px;
font-weight: 700;
color: var(--ui-text-color);
}
.custom-dialog-message {
font-size: 15px;
color: var(--text-primary);
margin-bottom: 24px;
line-height: 1.6;
}
.custom-dialog-input {
width: 100%;
padding: 12px;
background: var(--bg-color);
border: 2px solid var(--border-color);
border-radius: 8px;
color: var(--text-primary);
font-size: 14px;
margin-bottom: 20px;
transition: all 0.2s;
}
.custom-dialog-input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(88, 101, 242, 0.1);
}
.custom-dialog-buttons {
display: flex;
gap: 12px;
justify-content: flex-end;
}
.loader-logo {
position: relative;
width: 110px;
height: auto;
z-index: 10;
/* This creates a layered glow: one sharp blue, one soft cyan */
filter:
drop-shadow(0 0 10px rgba(95, 126, 255, 0.8))
drop-shadow(0 0 30px rgba(156, 196, 255, 0.4));
/* Applying three animations at once: float, flicker, and subtle rotate */
animation:
fireFloat 3s ease-in-out infinite,
fireFlicker 1.5s infinite alternate,
fireIgnite 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.custom-dialog-btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
min-width: 100px;
}
/* 1. Makes the flame float up and down gently */
@keyframes fireFloat {
0%, 100% { transform: translateY(0) rotate(-1deg); }
50% { transform: translateY(-12px) rotate(1deg); }
}
/* 2. Simulates the flickering intensity of fire */
@keyframes fireFlicker {
0%, 100% { opacity: 1; filter: brightness(1) drop-shadow(0 0 10px rgba(95, 126, 255, 0.8)); }
25% { opacity: 0.95; filter: brightness(1.2) drop-shadow(0 0 15px rgba(95, 126, 255, 1)); }
50% { opacity: 1; filter: brightness(0.9); }
75% { opacity: 0.98; filter: brightness(1.1) drop-shadow(0 0 12px rgba(156, 196, 255, 0.9)); }
}
/* 3. The "Pop Up" effect when the page first loads */
@keyframes fireIgnite {
0% { transform: scale(0) rotate(-20deg); opacity: 0; }
100% { transform: scale(1) rotate(0deg); opacity: 1; }
}
.custom-dialog-btn-primary {
background: var(--primary-color);
color: white;
}
.custom-dialog-btn-primary:hover {
background: #4752c4;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(88, 101, 242, 0.4);
}
.custom-dialog-btn-danger {
background: var(--danger);
color: white;
}
.custom-dialog-btn-danger:hover {
background: #d93636;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(240, 71, 71, 0.4);
}
.custom-dialog-btn-secondary {
background: var(--secondary-color);
color: var(--text-primary);
}
.custom-dialog-btn-secondary:hover {
opacity: 0.8;
transform: translateY(-2px);
}
.community-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(8px);
display: none;
align-items: center;
justify-content: center;
z-index: 2600;
}
.community-modal.show {
display: flex;
}
.community-modal-content {
background: var(--chat-bg);
border-radius: 14px;
width: min(92vw, 520px);
max-height: 88vh;
overflow: hidden;
border: 1px solid var(--border-color);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
}
.community-modal-header {
padding: 16px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
.community-modal-body {
padding: 12px 16px 16px;
overflow-y: auto;
max-height: calc(88vh - 68px);
}
.community-member-card {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
border-radius: 10px;
cursor: pointer;
}
.community-member-card:hover {
background: var(--bg-color);
}
.community-role-pill {
margin-left: auto;
font-size: 11px;
font-weight: 600;
padding: 2px 8px;
border-radius: 999px;
border: 1px solid var(--border-color);
color: var(--text-secondary);
}
.community-role-pill.leader {
color: #ffc107;
border-color: rgba(255, 193, 7, 0.45);
background: rgba(255, 193, 7, 0.1);
}
.friend-search-container {
padding: 12px 16px;
border-bottom: 1px solid var(--border-color);
}
.friend-search-input {
width: 100%;
padding: 10px 12px 10px 38px;
background: var(--bg-color);
border: 1px solid var(--border-color);
border-radius: 20px;
color: var(--text-primary);
font-size: 13px;
transition: all 0.2s;
}
.friend-search-input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(88, 101, 242, 0.15);
}
.friend-search-wrapper {
position: relative;
}
.friend-search-icon {
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
font-size: 14px;
}
.qr-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(10px);
display: none;
align-items: center;
justify-content: center;
z-index: 9998;
}
.qr-modal.show {
display: flex;
}
.qr-modal-content {
background: var(--chat-bg);
border-radius: 20px;
padding: 40px;
text-align: center;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.9);
border: 2px solid var(--primary-color);
max-width: 450px;
}
.qr-modal-title {
font-size: 24px;
font-weight: 700;
color: var(--ui-text-color);
margin-bottom: 16px;
}
.qr-modal-subtitle {
font-size: 14px;
color: var(--text-secondary);
margin-bottom: 24px;
}
.qr-code-container {
background: white;
padding: 20px;
border-radius: 12px;
display: inline-block;
margin-bottom: 20px;
}
#qrCodeCanvas {
display: block;
}
.qr-modal-close {
margin-top: 12px;
padding: 12px 32px;
background: var(--primary-color);
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: all 0.2s;
}
.qr-modal-close:hover {
background: #4752c4;
transform: translateY(-2px);
}
.media-preview-panel {
position: fixed;
bottom: -100%;
left: 0;
right: 0;
height: 60vh;
background: var(--chat-bg);
border-top: 3px solid var(--primary-color);
z-index: 1500;
transition: bottom 0.4s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
}
.media-preview-panel.show {
bottom: 0;
}
.media-preview-header {
padding: 20px 24px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
background: var(--bg-color);
}
.media-preview-title {
font-size: 18px;
font-weight: 600;
color: var(--ui-text-color);
}
.media-preview-close {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 24px;
padding: 8px;
transition: all 0.2s;
}
.media-preview-close:hover {
color: var(--danger);
transform: rotate(90deg);
}
.media-preview-content {
flex: 1;
overflow-y: auto;
padding: 24px;
display: flex;
flex-wrap: wrap;
gap: 16px;
align-content: flex-start;
}
.media-preview-item {
position: relative;
width: 200px;
height: 200px;
border-radius: 12px;
overflow: hidden;
border: 2px solid var(--border-color);
transition: all 0.2s;
}
.media-preview-item:hover {
transform: scale(1.05);
border-color: var(--primary-color);
box-shadow: 0 8px 24px rgba(88, 101, 242, 0.3);
}
.media-preview-item img,
.media-preview-item video {
width: 100%;
height: 100%;
object-fit: cover;
}
.danger-hover:hover {
color: var(--danger) !important;
transform: scale(1.08);
filter: drop-shadow(0 0 8px rgba(240, 71, 71, 0.6));
}
.save-btn.danger-hover:hover {
color: white !important;
transform: scale(1.02) !important;
}
.success-hover:hover {
color: var(--success) !important;
transform: scale(1.1);
filter: drop-shadow(0 0 8px rgba(67, 181, 129, 0.6));
}
.primary-hover:hover {
color: var(--primary-color) !important;
transform: scale(1.1);
filter: drop-shadow(0 0 8px rgba(88, 101, 242, 0.6));
}
@media (max-width: 768px) {
.chat-header-actions .header-btn {
animation: none !important;
}
.friend-item:hover,
.group-card:hover {
transform: none;
box-shadow: none;
}
.custom-dialog-content {
min-width: 90%;
padding: 24px;
}
.media-preview-panel {
height: 70vh;
}
.media-preview-item {
width: calc(50% - 8px);
height: 150px;
}
.qr-modal-content {
margin: 20px;
padding: 24px;
}
}
@media (max-width: 480px) {
.main-container {
grid-template-columns: 1fr;
height: calc(100vh - 68px);
height: calc(100dvh - 68px);
padding-bottom: 68px;
}
.mobile-bottom-nav {
display: flex;
}
.guild-sidebar {
display: none !important;
}
.members-sidebar {
display: none !important;
}
.profile-panel {
width: 100vw;
right: -100vw;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
}
.profile-panel.show {
right: 0;
}
.channel-sidebar {
position: fixed;
left: 0;
top: 0;
width: 85%;
max-width: 320px;
height: 100vh;
height: 100dvh;
z-index: 1500;
display: none;
flex-direction: column;
transform: translateX(-100%);
transition: transform 0.3s ease;
}
.channel-sidebar.show {
display: flex;
transform: translateX(0);
}
.channel-sidebar .sidebar-header > div button {
display: inline-flex;
align-items: center;
justify-content: center;
}
.channel-sidebar .sidebar-header {
gap: 8px;
flex-wrap: wrap;
}
.channel-sidebar .sidebar-header h3 {
font-size: 15px;
white-space: nowrap;
}
.sidebar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.6);
z-index: 1499;
}
.sidebar-overlay.show {
display: block;
}
.chat-area {
display: flex;
flex-direction: column;
height: calc(100vh - 68px);
height: calc(100dvh - 68px);
width: 100vw;
max-width: 100%;
}
.chat-header {
padding: 12px 16px;
flex-shrink: 0;
}
.chat-header-title {
font-size: 16px;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.chat-header-actions {
gap: 4px;
flex-shrink: 0;
overflow-x: auto;
max-width: 66vw;
padding-bottom: 2px;
}
.chat-header-actions button {
display: inline-flex;
flex-shrink: 0;
min-width: 30px;
min-height: 30px;
}
.chat-header-actions .mobile-essential {
display: inline-flex;
}
.build-badge.mobile-essential {
display: inline-flex !important;
flex-shrink: 0;
}
.build-badge {
display: none;
}
#messages-container {
flex: 1;
min-height: 0;
max-height: none;
overflow-y: auto;
overflow-x: hidden;
padding: 12px 16px;
padding-bottom: 16px;
gap: 8px;
}
.message {
gap: 8px;
}
.message-avatar {
width: 32px;
height: 32px;
min-width: 32px;
}
.message-input-area {
flex-shrink: 0;
padding: 12px 16px;
}
.message-input-section {
display: flex;
gap: 8px;
}
#messageInput {
flex: 1;
padding: 10px 12px;
font-size: 14px;
}
.message-input-btn {
padding: 8px 12px;
font-size: 14px;
}
.chat-scroll-rail {
right: 4px;
width: 8px;
}
.media-preview-item {
width: 100%;
height: 200px;
}
.custom-dialog-buttons {
flex-direction: column;
}
.custom-dialog-btn {
width: 100%;
}
.profile-panel {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100dvh;
z-index: 2601;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
}
.profile-content {
width: 100%;
max-width: none;
border-radius: 0;
padding-bottom: 120px;
}
.friends-modal {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
border-radius: 0;
max-width: none;
}
.modal-content {
border-radius: 0;
}
.qr-modal-content {
margin: 20px;
padding: 16px;
}
}
@media (min-width: 481px) and (max-width: 768px) {
.main-container {
grid-template-columns: 72px 1fr;
}
.members-sidebar {
display: none !important;
}
.channel-sidebar {
width: 200px;
}
}
</style>
</head>
<body>
<!-- ====== FIRE APP LOADER ====== -->
<div id="appLoader">
<div class="loader-scene">
<div class="loader-aura"></div>
<div class="loader-stage-ring"></div>
<img src="images/logo.png" alt="App Logo" class="loader-logo">
</div>
<div class="loader-app-name">FireTech</div>
<div class="loader-tagline">Secure your conversations. Trust the fire.</div>
<div class="loader-progress-wrap">
<div class="loader-progress-bar" id="loaderBar"></div>
</div>
<div class="loader-status" id="loaderStatus">Igniting...</div>
</div>
<div class="auth-container" id="authContainer">
<div class="auth-box">
<h2 id="authTitle">Login</h2>
<form id="authForm" onsubmit="handleAuth(event)">
<div id="registerFields" style="display: none;">
<div class="form-group">
<label>Username</label>
<input type="text" id="username" placeholder="Choose a username" required>
</div>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" id="email" placeholder="Enter your email" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" id="password" placeholder="Enter your password" required>
</div>
<div class="auth-inline-link" id="forgotPasswordWrap">
<button type="button" onclick="toggleForgotPasswordPanel()">Forgot password?</button>
</div>
<button type="submit" class="auth-button" id="authButton">Login</button>
</form>
<div class="reset-password-panel" id="resetPasswordPanel">
<div class="form-group" style="margin-bottom: 12px;">
<label>Reset Email</label>
<input type="email" id="resetEmail" placeholder="Enter your account email">
</div>
<div class="form-group" style="margin-bottom: 12px;">
<label>New Password</label>
<input type="password" id="resetNewPassword" placeholder="Enter new password (min 6 chars)">
</div>
<button type="button" class="auth-mini-button" onclick="resetForgottenPassword()">Reset Password</button>
</div>
<div id="authStatus" class="auth-status" aria-live="polite"></div>
<div class="auth-toggle">
<span>Don't have an account? <button type="button" onclick="toggleAuthMode()">Register</button></span>
</div>
</div>
</div>
<div class="main-container" id="mainApp">
<div class="guild-sidebar">
<div class="guild-item active" onclick="showSection('chat')" title="Chat">
<i class="fas fa-comment"></i>
</div>
<div class="guild-item" onclick="showSection('friends')" title="Friends">
<i class="fas fa-users"></i>
</div>
<div class="guild-item" onclick="showSection('shop')" title="Shop">
<i class="fas fa-store"></i>
</div>
<div class="guild-divider"></div>
<div class="guild-item" onclick="openFireTechBot()" title="FireTech Security Bot" style="background: linear-gradient(135deg, #ff9d4d, #5f7eff); font-size: 14px; font-weight: 700; display: flex; align-items: center; justify-content: center;">
⚑
</div>
<div class="guild-item" onclick="showArchivedMessages()" title="Archived Messages">
<i class="fas fa-archive"></i>
</div>
<div class="guild-item" onclick="openCommunitiesModal()" title="Communities">
<i class="fas fa-globe"></i>
</div>
<div class="guild-item" onclick="openGroupsModal()" title="Groups">
<i class="fas fa-user-group"></i>
</div>
</div>
<div class="channel-sidebar" id="channelSidebar">
<div class="sidebar-header">
<h3>FireTech</h3>
<div style="display: flex; gap: 6px; flex-wrap: wrap;">
<button onclick="createNewGroup()" title="Create Group" style="padding: 6px 10px; background: var(--primary-color); border: none; border-radius: 6px; color: white; cursor: pointer; font-size: 11px; font-weight: 600;">
<i class="fas fa-plus"></i> New
</button>
<button onclick="showQuickActionsMenu()" title="Quick Actions" style="padding: 6px 10px; background: var(--secondary-color); border: none; border-radius: 6px; color: white; cursor: pointer; font-size: 11px;">
<i class="fas fa-ellipsis-h"></i>
</button>
<button onclick="toggleChannelSidebar()" class="danger-hover" style="background: none; border: none; color: var(--text-secondary); cursor: pointer; font-size: 18px; padding: 4px 8px;"><i class="fas fa-times"></i></button>
</div>
</div>
<div class="friend-search-container">
<div class="friend-search-wrapper">
<i class="fas fa-search friend-search-icon"></i>
<input type="text" id="friendSearchInput" class="friend-search-input" placeholder="Search friends..." oninput="filterFriends(this.value)">
</div>
</div>
<div class="channels-list" id="channelsList">
</div>
</div>
<div class="chat-area">
<div class="chat-header">
<div class="chat-header-left">
<button class="header-btn" onclick="toggleChannelSidebar()">
<i class="fas fa-bars"></i>
</button>
<div class="chat-header-title" id="chatTitle">πŸ’¬ Select a friend to chat</div>
</div>
<div class="chat-header-actions">
<span class="build-badge mobile-essential" id="buildVersionBadge" title="Frontend build version">v3.2.8</span>
<button class="header-btn mobile-essential" onclick="toggleArchiveChat()" title="Archive chat">
<i class="fas fa-archive"></i>
</button>
<button class="header-btn mobile-essential" onclick="startVideoCall()" title="Video call">
<i class="fas fa-video"></i>
</button>
<button class="header-btn mobile-essential" onclick="togglePinCurrentChat()" title="Pin/Unpin chat" id="pinChatBtn">
<i class="fas fa-thumbtack"></i>
</button>
<button class="header-btn success mobile-essential" onclick="addCurrentChatToList()" title="Add chat to list">
<i class="fas fa-bookmark"></i>
</button>
<button class="header-btn danger-hover mobile-essential" onclick="clearAndCloseCurrentChat()" title="Clear and Close Chat" id="closeChatBtn" style="display: none;">
<i class="fas fa-times-circle"></i>
</button>
<button class="header-btn mobile-essential" onclick="toggleMobileMembers()" title="View members">
<i class="fas fa-users"></i>
</button>
<button class="header-btn mobile-essential" onclick="openSettings()" title="Settings">
<i class="fas fa-cog"></i>
</button>
<button class="header-btn mobile-essential notif-bell-btn" onclick="openNotifPanel()" title="Notifications">
<i class="fas fa-bell"></i>
<span class="notif-badge" id="notifBadge">0</span>
</button>
<button class="header-btn mobile-essential" onclick="openProfile()" title="Profile">
<i class="fas fa-user-circle"></i>
</button>
<button class="header-btn danger-hover mobile-essential" onclick="logout()" title="Logout">
<i class="fas fa-sign-out-alt"></i>
</button>
</div>
</div>
<div id="messages-container"></div>
<div id="chatScrollRail" class="chat-scroll-rail hidden">
<div id="chatScrollThumb" class="chat-scroll-thumb"></div>
</div>
<div id="mediaDraftPreview" class="draft-preview">
<div class="draft-preview-left">
<img id="draftPreviewThumb" class="draft-preview-thumb" alt="Selected media preview">
<div id="draftPreviewEmoji" class="draft-preview-emoji"></div>
<div id="draftPreviewMeta" class="draft-preview-meta">Media selected. Press Send when ready.</div>
</div>
<button class="draft-clear-btn" onclick="clearPendingMediaDraft()">Clear</button>
</div>
<div id="typingIndicator" style="display: none; padding: 10px; color: var(--text-secondary); font-size: 12px; font-style: italic;"></div>
<div class="input-area">
<button class="input-btn" onclick="document.getElementById('fileInput').click()" title="Upload Image">
<i class="fas fa-image"></i>
</button>
<button class="input-btn" onclick="document.getElementById('videoInput').click()" title="Upload Video / Reel">
<i class="fas fa-film"></i>
</button>
<button class="input-btn" onclick="togglePicker()" title="Stickers & GIFs">
<i class="fas fa-smile"></i>
</button>
<button class="input-btn" onclick="toggleVoiceRecorder()" title="Voice message">
<i class="fas fa-microphone"></i>
</button>
<input type="text" id="messageInput" placeholder="Message..." onkeypress="handleMessageKeypress(event)">
<button class="input-btn" onclick="sendMessage()" title="Send">
<i class="fas fa-paper-plane"></i>
</button>
<input type="file" id="fileInput" class="input-file" onchange="handleFileUpload(event)" accept="image/*" multiple>
<input type="file" id="videoInput" class="input-file" onchange="handleFileUpload(event)" accept="video/mp4,video/webm,video/ogg,video/*" multiple>
</div>
</div>
<div class="members-sidebar">
<div class="members-header">πŸ‘₯ Online Members</div>
<div class="members-list" id="membersList"></div>
</div>
</div>
<div id="profileBackdrop" onclick="closeProfile()"></div>
<div class="profile-panel" id="profilePanel">
<button class="profile-close" onclick="closeProfile()"><i class="fas fa-times"></i></button>
<div class="profile-banner-wrap" id="profileBannerWrap">
<img id="profileBannerImg" class="profile-banner-img" src="" alt="" style="display:none;">
<button class="profile-banner-edit-btn" onclick="openBannerPicker()">πŸ–Ό Edit Banner</button>
</div>
<div class="profile-header">
<div class="profile-avatar" id="profileAvatar">U</div>
<div class="profile-name" id="profileName">Username</div>
<div class="profile-bio" id="profileBio">No bio yet</div>
</div>
<div class="profile-content">
<div class="tab-buttons">
<button class="tab-btn active" onclick="switchProfileTab('profile', this)">Profile</button>
<button class="tab-btn" onclick="switchProfileTab('inventory', this)">Inventory</button>
<button class="tab-btn" onclick="switchProfileTab('orbs', this)">Orbs</button>
<button class="tab-btn" onclick="switchProfileTab('saved', this)">Saved</button>
</div>
<div class="tab-content active" id="profileTab">
<div class="form-field">
<label>Profile Picture</label>
<button class="save-btn" onclick="document.getElementById('profileImageInput').click()">Upload Profile Picture</button>
<input type="file" id="profileImageInput" class="input-file" onchange="uploadProfileImage(event)" accept="image/*" style="display: none;">
<p style="font-size: 12px; color: var(--text-secondary); margin-top: 5px;">Click to upload your profile picture</p>
</div>
<div class="form-field">
<label>Share Profile</label>
<button class="save-btn" onclick="shareProfileLink()" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">πŸ“‹ Copy Profile Link</button>
<p style="font-size: 12px; color: var(--text-secondary); margin-top: 5px;">Share this link with friends to connect</p>
</div>
<div class="form-field">
<label>Username</label>
<input type="text" id="editUsername" placeholder="Username">
</div>
<div class="form-field">
<label>Bio</label>
<textarea id="editBio" placeholder="Tell us about yourself"></textarea>
</div>
<div class="form-field">
<label>Phone Number</label>
<input type="tel" id="editPhoneNumber" placeholder="Add your phone number">
</div>
<button class="save-btn" onclick="saveProfile()">Save Profile</button>
</div>
<div class="tab-content" id="inventoryTab">
<div id="inventoryList"></div>
</div>
<div class="tab-content" id="orbsTab">
<div class="orb-card">
<label for="orbEffectSelect" style="display:block; font-size:12px; font-weight:700; margin-bottom:8px;">Orb Effect Theme</label>
<select id="orbEffectSelect" style="width:100%; padding:10px; border-radius:8px; border:1px solid var(--border-color); background:var(--chat-bg); color:var(--text-primary);" onchange="applyOrbEffect(this.value)">
<option value="none">None</option>
<option value="aurora">Aurora Glow</option>
<option value="neon_pulse">Neon Pulse</option>
<option value="ocean_mist">Ocean Mist</option>
<option value="ember">Ember Flame</option>
</select>
<p style="font-size:12px; color: var(--text-secondary); margin-top:8px;">Choose a profile orb effect. Changes apply instantly and are saved to your account locally.</p>
</div>
</div>
<div class="tab-content" id="savedTab">
<div style="margin-bottom:10px; color:var(--text-secondary); font-size:12px;">Your saved and archived content overview</div>
<div>
<span class="saved-pill">πŸ–Ό Saved Media: <strong id="savedMediaCount">0</strong></span>
<span class="saved-pill">πŸ“¦ Archived Messages: <strong id="savedArchivedCount">0</strong></span>
</div>
<button class="secondary-btn" onclick="openMediaPreview()" style="margin-top:8px;">Open Saved Media Vault</button>
<button class="secondary-btn" onclick="showArchivedMessages()" style="margin-top:8px;">Open Archive Center</button>
</div>
</div>
</div>
<div class="modal hidden" id="friendsModal">
<div class="modal-content">
<h2><i class="fas fa-users"></i> Friends & Friend Requests</h2>
<h3 style="margin-top: 20px; margin-bottom: 10px;">Pending Requests</h3>
<div id="friendRequests" style="max-height: 22vh; overflow-y: auto;"></div>
<h3 style="margin-top: 20px; margin-bottom: 10px;">Your Friends</h3>
<div id="friendsList" style="max-height: 36vh; overflow-y: auto;"></div>
<button class="save-btn" onclick="closeFriendsModal()" style="margin-top: 20px;">Close</button>
</div>
</div>
<div class="modal hidden" id="shopModal">
<div class="modal-content">
<h2><i class="fas fa-store"></i> Shop</h2>
<div class="coins-display" id="coinsDisplay">πŸ’° Coins: ...</div>
<div id="shopList"></div>
<button class="save-btn" onclick="closeShopModal()" style="margin-top: 20px;">Close</button>
</div>
</div>
<div class="modal hidden" id="archivedChatsModal">
<div class="archived-modal-content">
<h2 style="margin-bottom:6px;"><i class="fas fa-box-archive"></i> Archived Chats</h2>
<p style="color: var(--text-secondary); font-size: 13px; margin-bottom: 8px;">Open, unarchive, or delete chats in one place.</p>
<div id="archivedChatsList" class="archived-modal-list"></div>
<div style="display:flex; gap:10px; margin-top:10px;">
<button class="save-btn" style="background: var(--danger);" onclick="clearArchivedChats();">πŸ—‘ Clear All</button>
<button class="secondary-btn" onclick="closeArchivedChatsModal();">Close</button>
</div>
</div>
</div>
<div class="toast-container" id="toastContainer"></div>
<div class="picker-panel" id="pickerPanel">
<div class="picker-tabs">
<button class="picker-tab active" onclick="switchPickerTab('stickers', this)">πŸ˜€ Stickers</button>
<button class="picker-tab" onclick="switchPickerTab('gifs', this)">🎬 GIFs</button>
</div>
<div class="picker-size-controls">
<button class="picker-size-btn" onclick="adjustPickerSize(-0.1)" title="Smaller picker">A-</button>
<input id="pickerSizeRange" class="picker-size-range" type="range" min="1" max="2" step="0.05" value="1.45" oninput="setPickerScale(this.value)">
<button class="picker-size-btn" onclick="adjustPickerSize(0.1)" title="Larger picker">A+</button>
<span id="pickerSizeLabel" class="picker-size-label">145%</span>
</div>
<div class="picker-content" id="pickerContent">
</div>
</div>
<div class="voice-recorder" id="voiceRecorder">
<div class="record-timer" id="recordTimer">00:00</div>
<button class="record-button" id="recordButton" onclick="toggleRecording()">
<i class="fas fa-microphone"></i>
</button>
<div class="voice-preview-container" id="voicePreviewContainer" style="display: none;">
<div class="voice-preview-label">🎧 Preview your recording:</div>
<audio id="voicePreview" controls style="width: 100%; margin-bottom: 8px;"></audio>
</div>
<div style="display: flex; gap: 10px; width: 100%;">
<button class="save-btn" onclick="sendVoiceMessage()" style="padding: 8px 16px; flex: 1;" disabled>Send Voice Message</button>
<button class="save-btn" onclick="cancelRecording()" style="padding: 8px 16px; background: var(--danger); flex: 1;">Cancel</button>
</div>
</div>
<div class="settings-panel" id="settingsPanel">
<div class="settings-header">
<h2>βš™οΈ Settings</h2>
<button class="header-btn" onclick="closeSettings()"><i class="fas fa-times"></i></button>
</div>
<div class="settings-body">
<div class="settings-nav">
<div class="settings-nav-item active" onclick="switchSettingsTab('account', this)">πŸͺͺ Account</div>
<div class="settings-nav-item" onclick="switchSettingsTab('privacy', this)">πŸ›‘οΈ Privacy</div>
<div class="settings-nav-item" onclick="switchSettingsTab('chat', this)">πŸ—¨οΈ Chat</div>
<div class="settings-nav-item" onclick="switchSettingsTab('notifications', this)">πŸ“¬ Notifications</div>
<div class="settings-nav-item" onclick="switchSettingsTab('appearance', this)">πŸͺ„ Appearance</div>
<div class="settings-nav-item" onclick="switchSettingsTab('language', this)">🧭 Language</div>
<div class="settings-nav-item" onclick="switchSettingsTab('stats', this)">πŸ“ˆ Statistics</div>
</div>
<div class="settings-content">
<div class="settings-section active" id="accountSettings">
<h3>Account Settings</h3>
<div class="settings-item">
<div class="settings-label">Email</div>
<div class="settings-description">Your current email address</div>
<input type="email" id="settingsEmail" class="form-group input" readonly style="background: var(--bg-color); color: var(--text-secondary);">
</div>
<div class="settings-item">
<div class="settings-label">Change Username</div>
<div class="settings-description">Update your display name</div>
<input type="text" id="settingsUsername" placeholder="New username" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary); margin-bottom: 8px;">
<button class="save-btn" onclick="updateUsername()">Update Username</button>
</div>
<div class="settings-item">
<div class="settings-label">Delete Account</div>
<div class="settings-description">Permanently delete your account and all data</div>
<button class="save-btn danger-hover" onclick="showToast('Feature coming soon!', 'warning')" style="background: var(--danger);">Delete Account</button>
</div>
<div class="settings-item">
<div class="settings-label">Switch Account</div>
<div class="settings-description">Quickly switch between previously signed-in accounts</div>
<select id="accountSwitcher" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary); margin-bottom: 8px;"></select>
<button class="secondary-btn" onclick="switchAccount()">Switch Account</button>
</div>
</div>
<div class="settings-section" id="privacySettings">
<h3>Privacy & Safety</h3>
<div class="settings-item">
<div class="settings-label">Who can send you friend requests</div>
<label class="toggle-switch">
<input type="checkbox" checked id="allowFriendRequests">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Show online status</div>
<label class="toggle-switch">
<input type="checkbox" checked id="showOnlineStatus">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Read receipts</div>
<div class="settings-description">Let others know when you've read their messages</div>
<label class="toggle-switch">
<input type="checkbox" checked id="readReceipts">
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="settings-section" id="chatSettings">
<h3>Chat Settings</h3>
<div class="settings-item">
<div class="settings-label">Enter to send</div>
<div class="settings-description">Press Enter to send messages (Shift+Enter for new line)</div>
<label class="toggle-switch">
<input type="checkbox" checked id="enterToSend">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Show typing indicator</div>
<label class="toggle-switch">
<input type="checkbox" checked id="showTypingIndicator">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Auto-play GIFs</div>
<label class="toggle-switch">
<input type="checkbox" checked id="autoplayGifs">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">🎀 Microphone</div>
<div class="settings-description">Select audio input device for voice messages</div>
<select id="microphoneSelector" onchange="saveAudioSettings()" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary); margin-top: 8px;">
<option value="default">Default Microphone</option>
</select>
<button class="secondary-btn" onclick="refreshAudioDevices()" style="margin-top: 8px; padding: 6px 12px; font-size: 13px;">πŸ”„ Refresh Devices</button>
</div>
<div class="settings-item">
<div class="settings-label">πŸ”Š Speaker / Earphones</div>
<div class="settings-description">Select audio output device for playback</div>
<select id="speakerSelector" onchange="saveAudioSettings()" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary); margin-top: 8px;">
<option value="default">Default Speaker</option>
</select>
</div>
</div>
<div class="settings-section" id="notificationSettings">
<h3>Notifications</h3>
<div class="settings-item">
<div class="settings-label">Desktop notifications</div>
<label class="toggle-switch">
<input type="checkbox" id="desktopNotifications">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Message sound</div>
<label class="toggle-switch">
<input type="checkbox" checked id="messageSound">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Notification settings</div>
<div class="settings-description">All messages, Only mentions, Nothing</div>
<select id="notificationMode" onchange="saveNotificationSettings()" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary);">
<option value="all">All messages</option>
<option value="mentions">Only mentions</option>
<option value="none">Nothing</option>
</select>
</div>
<div class="settings-item">
<div class="settings-label">Notify on sent messages (this device)</div>
<label class="toggle-switch">
<input type="checkbox" id="notifyOnSent" onchange="saveNotificationSettings()">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Notify on received messages (this device)</div>
<label class="toggle-switch">
<input type="checkbox" id="notifyOnReceived" checked onchange="saveNotificationSettings()">
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="settings-section" id="appearanceSettings">
<h3>Appearance</h3>
<div class="settings-item">
<div class="settings-label">Theme</div>
<div class="settings-description">Choose your preferred theme</div>
<select id="themeSelector" onchange="changeTheme(this.value)" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary);">
<option value="dark">Dark</option>
<option value="light">Light</option>
<option value="custom">Custom Colors</option>
</select>
</div>
<div class="settings-item" id="customColorSection" style="display: none;">
<div class="settings-label">🎨 Customize Colors</div>
<div class="settings-description">Change background, text, and icon colors</div>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; margin-top: 10px;">
<div>
<label style="display: block; margin-bottom: 4px; font-size: 13px; color: var(--text-secondary);">Background</label>
<input type="color" id="bgColorPicker" value="#1e1f22" oninput="applySimpleCustomColors()" style="width: 100%; height: 40px; border: 1px solid var(--border-color); border-radius: 4px; cursor: pointer;">
</div>
<div>
<label style="display: block; margin-bottom: 4px; font-size: 13px; color: var(--text-secondary);">Text Color</label>
<input type="color" id="textColorPicker" value="#ffffff" oninput="applySimpleCustomColors()" style="width: 100%; height: 40px; border: 1px solid var(--border-color); border-radius: 4px; cursor: pointer;">
</div>
<div>
<label style="display: block; margin-bottom: 4px; font-size: 13px; color: var(--text-secondary);">Icons/Accents</label>
<input type="color" id="accentColorPicker" value="#5865F2" oninput="applySimpleCustomColors()" style="width: 100%; height: 40px; border: 1px solid var(--border-color); border-radius: 4px; cursor: pointer;">
</div>
</div>
<button class="secondary-btn" onclick="resetSimpleCustomColors()" style="margin-top: 10px; width: 100%; padding: 8px;">Reset to Default</button>
</div>
<div class="settings-item">
<div class="settings-label">Compact mode</div>
<div class="settings-description">Show more messages on screen</div>
<label class="toggle-switch">
<input type="checkbox" id="compactMode">
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-item">
<div class="settings-label">Message font size</div>
<select id="fontSizeSelector" onchange="saveAppearanceSettings()" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary);">
<option value="small">Small</option>
<option value="medium" selected>Medium</option>
<option value="large">Large</option>
</select>
</div>
<div class="settings-item">
<div class="settings-label">Disappearing messages</div>
<div class="settings-description">Auto-remove newly received/sent messages from your screen</div>
<select id="disappearTime" onchange="saveChatSettings()" style="width: 100%; padding: 10px; background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary);">
<option value="0">Off</option>
<option value="30">30 seconds</option>
<option value="60">1 minute</option>
<option value="300">5 minutes</option>
<option value="3600">1 hour</option>
</select>
</div>
</div>
<div class="settings-section" id="statsSettings">
<h3>πŸ“Š Your Statistics</h3>
<div class="settings-item" style="padding: 20px; background: var(--bg-color); border-radius: 8px;">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
<div style="background: var(--chat-bg); padding: 16px; border-radius: 6px; text-align: center; border: 1px solid var(--border-color);">
<div style="font-size: 32px; font-weight: bold; color: var(--primary-color);" id="statMessagesCount">0</div>
<div style="font-size: 13px; color: var(--text-secondary); margin-top: 8px;">Messages Sent</div>
</div>
<div style="background: var(--chat-bg); padding: 16px; border-radius: 6px; text-align: center; border: 1px solid var(--border-color);">
<div style="font-size: 32px; font-weight: bold; color: var(--primary-color);" id="statTotalChars">0</div>
<div style="font-size: 13px; color: var(--text-secondary); margin-top: 8px;">Characters Typed</div>
</div>
<div style="background: var(--chat-bg); padding: 16px; border-radius: 6px; text-align: center; border: 1px solid var(--border-color);">
<div style="font-size: 32px; font-weight: bold; color: var(--primary-color);" id="statReactionsGiven">0</div>
<div style="font-size: 13px; color: var(--text-secondary); margin-top: 8px;">Reactions Given</div>
</div>
<div style="background: var(--chat-bg); padding: 16px; border-radius: 6px; text-align: center; border: 1px solid var(--border-color);">
<div style="font-size: 32px; font-weight: bold; color: var(--primary-color);" id="statQuizCorrect">0</div>
<div style="font-size: 13px; color: var(--text-secondary); margin-top: 8px;">Quiz Correct</div>
</div>
</div>
</div>
<div class="settings-item">
<button class="save-btn" onclick="resetUserStats()" style="width: 100%;">Reset Statistics</button>
</div>
<div class="settings-item">
<button class="primary-btn" onclick="startQuiz()" style="width: 100%; padding: 12px; background: var(--primary-color); color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: bold;">🎯 Events & Challenges</button>
</div>
</div>
</div>
<!-- Language Settings -->
<div class="settings-section" id="languageSettings">
<h3>🌐 Language</h3>
<div class="settings-item">
<label class="settings-label">App Language</label>
<p style="font-size:13px; color:var(--text-secondary); margin:0 0 14px;">Choose your preferred language. UI text will update immediately.</p>
<div style="display:flex; align-items:center; gap:10px; margin-bottom:16px; padding:10px 14px; background:var(--bg-color); border-radius:10px; border:1px solid var(--border-color);">
<span style="font-size:20px;">🌐</span>
<span style="font-size:14px; font-weight:600;">Current:</span>
<span id="currentLangDisplay" style="font-size:14px; font-weight:700; color:var(--primary-color);">πŸ‡ΊπŸ‡Έ English</span>
</div>
<div class="lang-grid" id="langGrid"></div>
</div>
</div>
</div>
</div>
</div>
<div class="modal hidden" id="communitiesModal">
<div class="modal-content" style="max-width:min(96vw, 760px); width:min(96vw, 760px); max-height:86vh; overflow-y:auto;">
<h2><i class="fas fa-globe"></i> Communities</h2>
<p style="margin-top: 10px; color: var(--text-secondary);">Join public communities to discover people with shared interests.</p>
<input class="groups-search" placeholder="πŸ” Search communities..." oninput="filterCommunitiesList(this.value)">
<div id="communitiesList" style="margin-top: 6px;"></div>
<button class="save-btn" onclick="closeCommunitiesModal()" style="margin-top: 20px;">Close</button>
</div>
</div>
<div class="modal hidden" id="groupsModal">
<div class="modal-content" style="max-width:min(96vw, 760px); width:min(96vw, 760px); max-height:86vh; overflow-y:auto;">
<h2><i class="fas fa-user-group"></i> Groups</h2>
<p style="margin-top: 10px; color: var(--text-secondary);">Create and manage your own small group chats.</p>
<button class="create-group-btn" onclick="createNewGroup(); closeGroupsModal();" style="margin-top:14px;">βž• Create New Group</button>
<input class="groups-search" placeholder="πŸ” Search groups..." oninput="filterGroupsList(this.value)">
<div id="groupsList" style="margin-top: 4px;"></div>
<button class="save-btn" onclick="closeGroupsModal()" style="margin-top: 20px;">Close</button>
</div>
</div>
<div class="community-modal" id="communityDetailsModal">
<div class="community-modal-content">
<div class="community-modal-header">
<h3 id="communityDetailsTitle">Community</h3>
<button class="header-btn" onclick="closeCommunityDetails()"><i class="fas fa-times"></i></button>
</div>
<div class="community-modal-body" id="communityDetailsBody"></div>
</div>
</div>
<div class="qr-modal" id="qrModal">
<div class="qr-modal-content">
<h2 class="qr-modal-title">πŸ“± Friend Request QR Code</h2>
<p class="qr-modal-subtitle">Let your friends scan this code to send you a friend request!</p>
<div class="qr-code-container">
<canvas id="qrCodeCanvas" width="200" height="200"></canvas>
</div>
<p style="font-size: 13px; color: var(--text-secondary); margin-bottom: 16px;">Your ID: <strong id="qrUserId" style="color: var(--primary-color);"></strong></p>
<button class="qr-modal-close" onclick="closeQRCodeModal()">Close</button>
</div>
</div>
<div class="media-preview-panel" id="mediaPreviewPanel">
<div class="media-preview-header">
<h3 class="media-preview-title">πŸ“Έ Copied Media</h3>
<button class="media-preview-close" onclick="closeMediaPreview()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="media-preview-content" id="mediaPreviewContent">
</div>
</div>
<div class="mobile-bottom-nav" id="mobileBottomNav">
<button class="mobile-nav-item active" onclick="showMobileSection('chats')" data-section="chats">
<i class="fas fa-comment"></i>
<span>Chats</span>
</button>
<button class="mobile-nav-item" onclick="showMobileSection('communities')" data-section="communities">
<i class="fas fa-globe"></i>
<span>Communities</span>
</button>
<button class="mobile-nav-item" onclick="showMobileSection('groups')" data-section="groups">
<i class="fas fa-user-group"></i>
<span>Groups</span>
</button>
<button class="mobile-nav-item" onclick="showMobileSection('friends')" data-section="friends">
<i class="fas fa-users"></i>
<span>Friends</span>
</button>
<button class="mobile-nav-item" onclick="showMobileSection('settings')" data-section="settings">
<i class="fas fa-cog"></i>
<span>Settings</span>
</button>
</div>
<div class="sidebar-overlay" id="sidebarOverlay" onclick="closeMobileSidebar()"></div>
<div class="mobile-members-panel" id="mobileMembersPanel">
<div class="mobile-members-header">
<h3>πŸ‘₯ Online Members</h3>
<button class="header-btn" onclick="toggleMobileMembers()" style="font-size: 20px;">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mobile-members-list" id="mobileMembersList">
</div>
</div>
<div id="customDialog" style="display: none;"></div>
<div id="callOverlay">
<div class="call-overlay-stage">
<div id="hostedCallContainer"></div>
<video id="remoteCallVideo" autoplay playsinline style="position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0;"></video>
<video id="localCallVideo" autoplay muted playsinline style="position:absolute; bottom:110px; right:14px; width:110px; height:150px; border-radius:12px; border:2px solid rgba(255,255,255,0.6); object-fit:cover; z-index:2;"></video>
<div class="call-overlay-header">
<div>
<div id="callOverlayPeerName" style="color:#fff; font-size:18px; font-weight:700;"></div>
<div id="callTimerLabel" style="color:rgba(255,255,255,0.7); font-size:13px; margin-top:4px;">00:00:00</div>
<div id="callStatusLabel" style="color:#8fffc2; font-size:12px; margin-top:4px;">Preparing call...</div>
</div>
<button id="callDebugBtn" style="background:rgba(255,255,255,0.18); border:none; color:white; padding:7px 13px; border-radius:8px; cursor:pointer; font-size:12px; font-weight:600;">πŸ”§ Debug</button>
</div>
<div id="callDebugPanel"></div>
<div class="call-overlay-controls">
<button id="muteBtn" class="call-ctrl-btn" title="Mute/Unmute">🎀</button>
<button id="cameraBtn" class="call-ctrl-btn" title="Camera on/off">πŸ“·</button>
<button id="endCallBtn" class="call-end-btn" title="End Call">πŸ“΅</button>
</div>
</div>
</div>
<div id="notifPanel">
<div class="notif-panel-header">
<span style="font-weight:700; font-size:16px;">πŸ”” Notifications</span>
<div style="display:flex; gap:8px; align-items:center;">
<button onclick="clearAllNotifications()" style="background:none; border:none; color:var(--text-secondary); font-size:12px; cursor:pointer; padding:4px 8px; border-radius:4px; transition:all 0.15s;" onmouseover="this.style.background='var(--bg-color)'" onmouseout="this.style.background='none'">Clear all</button>
<button onclick="closeNotifPanel()" style="background:none; border:none; color:var(--text-secondary); font-size:20px; cursor:pointer; line-height:1;">Γ—</button>
</div>
</div>
<div id="notifList" style="flex:1;">
<div style="padding:30px; text-align:center; color:var(--text-secondary);">No notifications yet</div>
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="https://meet.jit.si/external_api.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/twemoji@14.0.2/dist/twemoji.min.js" crossorigin="anonymous"></script>
<script src="client.js?v=3.2.8"></script>
</body>
</html>