Avatar-Speech / frontend /src /index.css
agkavin
Initial commit: speech_to_video project with models via LFS
249e06d
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');
/* ══════════════════════════════════════════════
DESIGN TOKENS β€” Cyan / Blue / Deep Black
══════════════════════════════════════════════ */
:root {
--bg-base: #000000;
--bg-primary: #050810;
--bg-secondary: #080d18;
--bg-card: #0c1220;
--bg-elevated: #111827;
--cyan: #00e5ff;
--cyan-dim: #00b8cc;
--cyan-glow: rgba(0, 229, 255, 0.22);
--cyan-glow-lg: rgba(0, 229, 255, 0.1);
--blue: #2563eb;
--blue-bright: #3b82f6;
--blue-glow: rgba(37, 99, 235, 0.3);
--accent-gradient: linear-gradient(135deg, #00e5ff 0%, #2563eb 60%, #7c3aed 100%);
--text-primary: #f0f6ff;
--text-secondary: #8aa0c0;
--text-muted: #3d5070;
--border-subtle: rgba(255,255,255,0.05);
--border-mid: rgba(0,229,255,0.14);
--border-accent: rgba(0,229,255,0.32);
--success: #00e5ff;
--warning: #f59e0b;
--error: #f43f5e;
--font-primary: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 28px;
--radius-full: 9999px;
--shadow-card: 0 8px 32px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);
--shadow-glow: 0 0 40px var(--cyan-glow), 0 0 80px var(--cyan-glow-lg);
--transition: 180ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* ══════════════════════════════════════════════
RESET
══════════════════════════════════════════════ */
*, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }
html { font-size:16px; -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility; }
body {
font-family: var(--font-primary);
background: var(--bg-base);
color: var(--text-primary);
height: 100vh; overflow: hidden;
}
/* ══════════════════════════════════════════════
AMBIENT BACKGROUND
══════════════════════════════════════════════ */
.bg-particles {
position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden;
}
.bg-particles::before {
content: '';
position: absolute; inset: -50%;
background:
radial-gradient(ellipse 60% 40% at 15% 55%, rgba(0,229,255,0.07) 0%, transparent 60%),
radial-gradient(ellipse 50% 50% at 85% 20%, rgba(37,99,235,0.08) 0%, transparent 60%),
radial-gradient(ellipse 40% 60% at 50% 90%, rgba(124,58,237,0.05) 0%, transparent 60%);
animation: bgDrift 25s ease-in-out infinite alternate;
}
.bg-particles::after {
content: '';
position: absolute; inset: 0;
background:
repeating-linear-gradient(0deg, transparent, transparent 80px, rgba(0,229,255,0.013) 80px, rgba(0,229,255,0.013) 81px),
repeating-linear-gradient(90deg, transparent, transparent 80px, rgba(0,229,255,0.013) 80px, rgba(0,229,255,0.013) 81px);
}
@keyframes bgDrift {
0% { transform: translate(0,0) scale(1); }
100% { transform: translate(-3%,4%) scale(1.04); }
}
/* ══════════════════════════════════════════════
LAYOUT
══════════════════════════════════════════════ */
.app-container {
position: relative; z-index: 1;
display: flex; flex-direction: column;
height: 100vh;
}
/* ══════════════════════════════════════════════
HEADER
══════════════════════════════════════════════ */
.app-header {
display: flex; align-items: center; justify-content: space-between;
padding: 0 28px; height: 56px; flex-shrink: 0;
border-bottom: 1px solid var(--border-subtle);
background: rgba(5,8,16,0.94);
backdrop-filter: blur(24px); z-index: 10;
}
.header-left { display:flex; align-items:center; gap:14px; }
.logo-icon {
display:flex; align-items:center; justify-content:center;
width:36px; height:36px; border-radius:10px; flex-shrink:0;
background: var(--accent-gradient); color:#fff;
box-shadow: 0 0 18px var(--cyan-glow), 0 4px 12px rgba(0,0,0,0.4);
}
.header-text h1 {
font-size:1.12rem; font-weight:800; letter-spacing:-0.03em;
background: var(--accent-gradient);
-webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text;
}
.subtitle {
font-size:0.67rem; color:var(--text-muted);
letter-spacing:0.07em; text-transform:uppercase; font-weight:500;
}
.header-right { display:flex; align-items:center; gap:10px; }
.status-badge {
display:flex; align-items:center; gap:7px;
padding:5px 13px; border-radius:var(--radius-full);
font-size:0.73rem; font-weight:600; letter-spacing:0.03em;
background: rgba(255,255,255,0.03); border:1px solid var(--border-subtle);
color: var(--text-secondary);
}
.status-badge.status-connected { background:rgba(0,229,255,0.08); border-color:rgba(0,229,255,0.25); color:var(--cyan); }
.status-badge.status-connecting { background:rgba(245,158,11,0.08); border-color:rgba(245,158,11,0.25); color:var(--warning); }
.status-badge.status-error { background:rgba(244,63,94,0.08); border-color:rgba(244,63,94,0.25); color:var(--error); }
.status-dot {
width:7px; height:7px; border-radius:50%; flex-shrink:0;
background:var(--cyan); box-shadow:0 0 8px var(--cyan);
animation:statusPulse 2s ease-in-out infinite;
}
.status-badge.status-connecting .status-dot { background:var(--warning); box-shadow:0 0 8px var(--warning); }
.status-badge.status-error .status-dot { background:var(--error); box-shadow:0 0 8px var(--error); animation:none; }
.status-badge.status-disconnected .status-dot { background:var(--text-muted); box-shadow:none; animation:none; }
@keyframes statusPulse {
0%,100% { opacity:1; transform:scale(1); }
50% { opacity:0.35; transform:scale(0.7); }
}
.btn-icon {
display:flex; align-items:center; justify-content:center;
width:34px; height:34px; border-radius:var(--radius-sm);
border:1px solid var(--border-subtle); background:transparent;
color:var(--text-muted); cursor:pointer; transition:var(--transition);
}
.btn-icon:hover { background:rgba(0,229,255,0.07); color:var(--cyan); border-color:var(--border-mid); }
/* ══════════════════════════════════════════════
MAIN SPLIT
══════════════════════════════════════════════ */
.main-content { display:flex; flex:1; overflow:hidden; }
/* ══════════════════════════════════════════════
LEFT β€” Full-height avatar panel
══════════════════════════════════════════════ */
.avatar-panel {
flex: 1 1 0; min-width: 0;
display:flex; flex-direction:column;
background: var(--bg-secondary);
border-right: 1px solid var(--border-subtle);
position: relative;
padding-left: 16px;
}
/* The phone frame is now the full stretchable area */
.phone-frame {
flex: 1;
position: relative;
overflow: hidden;
min-height: 0;
background: #000;
}
/* Top cosmetic gradient bar */
.phone-notch {
position: absolute; top:0; left:0; right:0; z-index:10;
height: 52px;
background: linear-gradient(to bottom, rgba(5,8,16,0.95) 0%, transparent 100%);
display:flex; align-items:center; justify-content:center; pointer-events:none;
}
.phone-notch::after {
content: '';
width:44px; height:5px; border-radius:3px;
background: rgba(0,229,255,0.25);
box-shadow: 0 0 10px var(--cyan-glow);
}
.phone-screen { position:absolute; inset:0; overflow:hidden; }
.avatar-media {
position:absolute; inset:0;
width:100%; height:100%;
object-fit:cover;
object-position: center top;
opacity:0; transition:opacity 0.4s ease;
}
.avatar-media.active { opacity:1; }
/* Bottom overlay: name + speaking waves */
.phone-name-chip {
position:absolute; bottom:0; left:0; right:0; z-index:5;
padding: 60px 20px 16px;
background: linear-gradient(to top, rgba(5,8,16,0.88) 0%, rgba(5,8,16,0.4) 50%, transparent 100%);
display:flex; align-items:center; gap:10px;
}
.phone-name-chip::before {
content:''; width:9px; height:9px; border-radius:50%; flex-shrink:0;
background:var(--cyan); box-shadow:0 0 12px var(--cyan);
animation:statusPulse 2s ease-in-out infinite;
}
.phone-name-chip span {
font-size:1rem; font-weight:700; color:#fff; letter-spacing:0.02em;
text-shadow:0 2px 10px rgba(0,0,0,0.9);
}
.speaking-indicator {
position:absolute; bottom:60px; left:50%; transform:translateX(-50%); z-index:6;
display:flex; align-items:flex-end; gap:4px; height:30px;
}
.wave-bar {
width:4px; border-radius:2px;
background:var(--cyan); box-shadow:0 0 8px var(--cyan-glow);
animation:wave 0.75s ease-in-out infinite alternate;
}
.wave-bar:nth-child(1) { height:8px; animation-delay:0s; }
.wave-bar:nth-child(2) { height:16px; animation-delay:0.1s; }
.wave-bar:nth-child(3) { height:30px; animation-delay:0.2s; }
.wave-bar:nth-child(4) { height:16px; animation-delay:0.3s; }
.wave-bar:nth-child(5) { height:8px; animation-delay:0.4s; }
@keyframes wave {
from { transform:scaleY(0.3); opacity:0.45; }
to { transform:scaleY(1); opacity:1; }
}
.processing-overlay {
position:absolute; inset:0; z-index:7;
display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px;
background:rgba(5,8,16,0.7); backdrop-filter:blur(8px);
color:var(--text-primary); font-size:0.87rem; font-weight:500; letter-spacing:0.03em;
}
.processing-overlay span { color:var(--cyan); }
.spinner {
width:38px; height:38px;
border:2.5px solid rgba(0,229,255,0.15); border-top-color:var(--cyan);
border-radius:50%; animation:spin 0.85s linear infinite;
box-shadow:0 0 20px var(--cyan-glow);
}
@keyframes spin { to { transform:rotate(360deg); } }
/* ── Controls bar ── */
.phone-controls {
display:flex; gap:8px; padding:12px 14px;
background:var(--bg-secondary); border-top:1px solid var(--border-subtle);
flex-shrink:0;
}
.ctrl-btn {
flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px;
padding:11px 6px; border:none; border-radius:var(--radius-md);
cursor:pointer; transition:var(--transition);
font-size:0.6rem; font-weight:700; letter-spacing:0.08em; text-transform:uppercase;
}
.ctrl-btn:disabled { opacity:0.25; cursor:not-allowed; pointer-events:none; }
.ctrl-active { background:var(--bg-elevated); color:var(--text-secondary); border:1px solid var(--border-subtle); }
.ctrl-active:hover { background:var(--bg-card); color:var(--text-primary); border-color:var(--border-mid); }
.ctrl-muted { background:rgba(244,63,94,0.12); color:var(--error); border:1px solid rgba(244,63,94,0.28); }
.ctrl-muted:hover { background:rgba(244,63,94,0.22); }
.ctrl-connect {
background:linear-gradient(135deg, rgba(0,229,255,0.12) 0%, rgba(37,99,235,0.12) 100%);
color:var(--cyan); border:1px solid rgba(0,229,255,0.26);
}
.ctrl-connect:not(:disabled):hover {
background:linear-gradient(135deg, rgba(0,229,255,0.22) 0%, rgba(37,99,235,0.22) 100%);
box-shadow:0 0 18px var(--cyan-glow);
}
.ctrl-disconnect { background:rgba(244,63,94,0.08); color:var(--error); border:1px solid rgba(244,63,94,0.2); }
.ctrl-disconnect:not(:disabled):hover { background:rgba(244,63,94,0.18); }
.spinner-sm {
width:16px; height:16px; border-radius:50%;
border:2px solid rgba(0,229,255,0.2); border-top-color:var(--cyan);
animation:spin 0.7s linear infinite; display:inline-block;
}
/* ══════════════════════════════════════════════
RIGHT β€” Chat panel
══════════════════════════════════════════════ */
.chat-panel {
flex:2 1 0; min-width:0; display:flex; flex-direction:column; overflow:hidden;
background:var(--bg-primary);
}
.chat-messages {
flex:1; overflow-y:auto; padding:24px 28px;
display:flex; flex-direction:column; gap:18px;
scrollbar-width:thin; scrollbar-color:rgba(0,229,255,0.1) transparent;
}
.chat-messages::-webkit-scrollbar { width:4px; }
.chat-messages::-webkit-scrollbar-thumb { background:rgba(0,229,255,0.15); border-radius:2px; }
.chat-messages::-webkit-scrollbar-thumb:hover { background:rgba(0,229,255,0.28); }
/* Bubbles */
.message { display:flex; gap:14px; animation:fadeUp 0.2s ease-out both; }
@keyframes fadeUp {
from { opacity:0; transform:translateY(8px); }
to { opacity:1; transform:translateY(0); }
}
.user-message { flex-direction:row-reverse; }
.system-message { justify-content:center; }
.assistant-message { flex-direction:row; }
.message-avatar {
width:38px; height:38px; border-radius:50%;
display:flex; align-items:center; justify-content:center;
flex-shrink:0; margin-top:2px;
}
.assistant-message .message-avatar {
background:linear-gradient(135deg, var(--cyan) 0%, var(--blue) 100%);
color:#000; box-shadow:0 0 16px var(--cyan-glow), 0 4px 10px rgba(0,0,0,0.4);
}
.user-message .message-avatar {
background:var(--bg-elevated); color:var(--text-secondary);
border:1px solid var(--border-subtle);
}
.message-content { max-width:72%; display:flex; flex-direction:column; gap:5px; }
.user-message .message-content { align-items:flex-end; }
.message-header { display:flex; align-items:baseline; gap:8px; }
.message-name { font-size:0.84rem; font-weight:700; color:var(--text-secondary); }
.assistant-message .message-name { color:var(--cyan); }
.message-time { font-size:0.7rem; color:var(--text-muted); }
.message-text {
padding:13px 17px; border-radius:var(--radius-lg);
font-size:1.05rem; line-height:1.65; letter-spacing:0.01em;
}
.assistant-message .message-text {
background:var(--bg-card); border:1px solid var(--border-mid);
border-bottom-left-radius:4px; color:var(--text-primary);
box-shadow:0 4px 20px rgba(0,0,0,0.35), 0 0 0 1px rgba(0,229,255,0.04);
}
.user-message .message-text {
background:linear-gradient(135deg, #1d4ed8 0%, var(--blue) 100%);
color:#fff; border-bottom-right-radius:4px;
box-shadow:0 4px 20px rgba(37,99,235,0.35), 0 2px 8px rgba(0,0,0,0.3);
}
.message-text code {
background:rgba(0,229,255,0.1); color:var(--cyan);
padding:2px 6px; border-radius:4px;
font-family:var(--font-mono); font-size:0.85em;
}
.system-message .message-content {
background:rgba(0,229,255,0.04); border:1px solid rgba(0,229,255,0.1);
border-radius:var(--radius-full); padding:5px 16px; max-width:none;
}
.system-message .message-text { font-size:0.8rem; color:var(--text-muted); background:none; border:none; padding:0; }
/* ══════════════════════════════════════════════
INPUT
══════════════════════════════════════════════ */
.input-area {
padding:16px 28px 20px;
background:rgba(8,13,24,0.97);
border-top:1px solid var(--border-subtle);
backdrop-filter:blur(16px);
}
.input-wrapper { display:flex; gap:10px; align-items:flex-end; }
.text-input {
flex:1; padding:13px 18px;
border-radius:var(--radius-lg);
border:1px solid var(--border-mid);
background:var(--bg-card);
color:var(--text-primary);
font-family:var(--font-primary);
font-size:0.97rem; line-height:1.45;
resize:none; min-height:48px; max-height:120px;
outline:none; transition:var(--transition);
box-shadow:inset 0 2px 8px rgba(0,0,0,0.25);
}
.text-input:focus {
border-color:rgba(0,229,255,0.42);
box-shadow:0 0 0 3px rgba(0,229,255,0.1), inset 0 2px 8px rgba(0,0,0,0.25);
}
.text-input::placeholder { color:var(--text-muted); }
.text-input:disabled { opacity:0.35; cursor:not-allowed; }
.btn-send {
width:48px; height:48px; flex-shrink:0;
display:flex; align-items:center; justify-content:center;
border:none; border-radius:var(--radius-lg);
background:linear-gradient(135deg, var(--cyan) 0%, var(--blue) 100%);
color:#000; cursor:pointer; transition:var(--transition);
box-shadow:0 0 20px var(--cyan-glow), 0 4px 12px rgba(0,0,0,0.3);
}
.btn-send:hover:not(:disabled) {
transform:translateY(-2px);
box-shadow:0 0 32px var(--cyan-glow), 0 6px 20px rgba(0,0,0,0.4);
}
.btn-send:disabled { background:var(--bg-elevated); color:var(--text-muted); box-shadow:none; cursor:not-allowed; }
.input-footer {
display:flex; align-items:center; gap:8px;
margin-top:9px; font-size:0.78rem; color:var(--text-muted);
}
.mic-pulse {
display:inline-block; width:8px; height:8px; border-radius:50%; flex-shrink:0;
background:var(--cyan); box-shadow:0 0 10px var(--cyan);
animation:statusPulse 1.4s ease-in-out infinite;
}