gemma-multi-avatar / src /style.css
bep40's picture
Upload src/style.css
f4acc79 verified
Raw
History Blame
22.2 kB
:root {
--bg: #0a0b10;
--bg-elev: #13151c;
--bg-elev-2: #1b1e29;
--border: rgba(255, 255, 255, 0.08);
--border-strong: rgba(255, 255, 255, 0.16);
--text: #f5f6fa;
--text-dim: rgba(245, 246, 250, 0.65);
--text-faint: rgba(245, 246, 250, 0.42);
--error: #ff6a75;
--live: #22d3ee;
--font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
--radius-sm: 8px;
--radius-md: 14px;
}
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body { background: var(--bg); color: var(--text); font-family: Inter, system-ui, -apple-system, sans-serif; overflow: hidden; }
#app { position: relative; height: 100dvh; }
#stage { position: absolute; inset: 0; }
#stage canvas { display: block; }
[hidden] { display: none !important; }
#loading { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--font-mono); font-size: 12px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); background: var(--bg); transition: opacity 0.6s ease; pointer-events: none; }
#loading.done { opacity: 0; }
#topbar { position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: flex-start; justify-content: space-between; padding: 18px 20px; pointer-events: none; }
#topbar > * { pointer-events: auto; }
#identity h1 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: 0.01em; }
#identity p { margin: 4px 0 0; max-width: 340px; font-size: 12px; line-height: 1.45; color: var(--text-faint); }
#identity strong { color: var(--text-dim); font-weight: 500; }
.icon-btn { display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-elev); color: var(--text-dim); cursor: pointer; touch-action: manipulation; transition: color 0.15s ease, border-color 0.15s ease; }
.icon-btn:hover { color: var(--text); border-color: var(--border-strong); }
.icon-btn.active { color: var(--live); border-color: var(--border-strong); }
.icon-btn.small { width: 28px; height: 28px; }
#main-btn { min-width: 190px; height: 46px; padding: 0 26px; border: none; border-radius: 23px; background: var(--text); color: var(--bg); font-family: Inter, system-ui, sans-serif; font-size: 14px; font-weight: 600; cursor: pointer; touch-action: manipulation; transition: transform 0.12s ease, opacity 0.15s ease; }
#main-btn:hover:not(:disabled) { transform: translateY(-1px); }
#main-btn:disabled { opacity: 0.45; cursor: default; }
#main-btn.live { background: var(--bg-elev); color: var(--text); border: 1px solid var(--border-strong); }
#controls { position: absolute; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 0 20px calc(22px + env(safe-area-inset-bottom)); z-index: 100; }
#buttons { display: flex; align-items: center; gap: 10px; }
#caption { font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-faint); transition: color 0.2s ease; }
#caption.live { color: var(--live); }
#caption.error { color: var(--error); }
#subtitles { position: absolute; left: 50%; bottom: 118px; transform: translateX(-50%); max-width: min(640px, calc(100vw - 48px)); padding: 10px 16px; border-radius: var(--radius-md); background: rgba(10, 11, 16, 0.72); backdrop-filter: blur(6px); border: 1px solid var(--border); font-size: 15px; line-height: 1.5; text-align: center; text-wrap: balance; color: var(--text); opacity: 0; transition: opacity 0.25s ease; pointer-events: none; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
#subtitles.visible { opacity: 1; }
#settings { width: min(440px, calc(100vw - 40px)); padding: 22px; border: 1px solid var(--border-strong); border-radius: var(--radius-md); background: var(--bg-elev); color: var(--text); box-shadow: 0 4px 18px rgba(0, 0, 0, 0.32); }
#settings::backdrop { background: rgba(5, 6, 9, 0.6); backdrop-filter: blur(2px); }
#settings h2 { margin: 0 0 16px; font-size: 15px; font-weight: 600; }
#settings label { display: block; margin-bottom: 14px; font-size: 12px; color: var(--text-dim); }
#settings select, #settings textarea, #settings input { display: block; width: 100%; margin-top: 6px; padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-elev-2); color: var(--text); font-family: inherit; font-size: 13px; }
#settings select:focus-visible, #settings textarea:focus-visible, #settings input:focus-visible { outline: 1px solid var(--text-dim); outline-offset: 1px; }
#settings textarea { resize: vertical; }
#settings .check-row { display: flex; align-items: center; gap: 9px; }
#settings .check-row input { display: inline-block; width: auto; margin: 0; accent-color: var(--text); }
.dialog-actions { display: flex; justify-content: flex-end; margin-top: 6px; }
.dialog-actions .primary { padding: 9px 20px; border: none; border-radius: var(--radius-sm); background: var(--text); color: var(--bg); font-weight: 600; font-size: 13px; cursor: pointer; }
/* ── Draggable / Resizable Chat ───────────────────────────────────────────── */
#text-chat {
position: fixed;
z-index: 9999;
top: 100px;
left: 20px;
width: min(380px, calc(100vw - 40px));
height: 50vh;
display: flex;
flex-direction: column;
background: rgba(10, 11, 16, 0.92);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid var(--border-strong);
border-radius: var(--radius-md);
overflow: hidden;
min-height: 2.5rem;
max-height: 80vh;
cursor: default;
resize: none;
box-shadow: 0 8px 32px rgba(0,0,0,0.5);
touch-action: none;
}
#text-chat.dragging { cursor: grabbing !important; user-select: none !important; }
#text-chat.resizing { user-select: none !important; }
/* Chat header bar β€” drag handle */
#chat-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 12px;
border-bottom: 1px solid var(--border);
background: var(--bg-elev);
cursor: grab;
flex-shrink: 0;
touch-action: none;
}
#text-chat.dragging #chat-header { cursor: grabbing !important; }
#chat-title { font-size: 12px; font-weight: 600; color: var(--text-dim); letter-spacing: 0.04em; }
#chat-header-actions { display: flex; align-items: center; gap: 6px; pointer-events: auto; }
#chat-avatar-select { font-size: 11px; padding: 2px 6px; border: 1px solid var(--border); border-radius: 4px; background: var(--bg-elev-2); color: var(--text); cursor: pointer; max-width: 100px; pointer-events: auto; }
#chat-messages { flex: 1; padding: 12px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
#chat-messages::-webkit-scrollbar { width: 6px; }
#chat-messages::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.chat-message { max-width: 85%; padding: 8px 12px; border-radius: var(--radius-sm); font-size: 13px; line-height: 1.5; word-wrap: break-word; cursor: pointer; }
.chat-message.user { align-self: flex-end; background: var(--live); color: var(--bg); }
.chat-message.assistant { align-self: flex-start; background: var(--bg-elev-2); color: var(--text); border: 1px solid var(--border); }
.chat-message.selected { outline: 2px solid var(--live); outline-offset: 1px; }
.chat-message a { color: var(--live); }
#chat-input-container { display: flex; gap: 8px; padding: 10px; border-top: 1px solid var(--border); background: var(--bg-elev); flex-shrink: 0; }
#chat-input { flex: 1; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); color: var(--text); font-family: inherit; font-size: 13px; }
#chat-input:focus { outline: 1px solid var(--text-dim); outline-offset: 1px; }
/* Resize handle at bottom-right corner β€” bigger, better contrast */
#chat-resize-handle {
position: absolute;
bottom: 0;
right: 0;
width: 24px;
height: 24px;
cursor: nwse-resize;
background: transparent;
z-index: 1;
touch-action: none;
}
#chat-resize-handle::after {
content: '';
position: absolute;
bottom: 3px;
right: 3px;
width: 14px;
height: 14px;
border-right: 2px solid var(--text-dim);
border-bottom: 2px solid var(--text-dim);
opacity: 0.4;
transition: opacity 0.15s;
}
#chat-resize-handle:hover::after { opacity: 1; }
#text-chat.resizing #chat-resize-handle::after { opacity: 1; }
/* ── News Box (draggable + resizable, with thumbnails) ─────────────────── */
#news-panel {
position: fixed;
z-index: 9998;
bottom: 80px;
right: 20px;
width: min(380px, calc(100vw - 40px));
height: min(520px, 70vh);
display: flex;
flex-direction: column;
background: rgba(10, 11, 16, 0.95);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--border-strong);
border-radius: var(--radius-md);
overflow: hidden;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
resize: none;
touch-action: none;
min-width: 300px;
min-height: 180px;
}
#news-panel.dragging { cursor: grabbing !important; user-select: none !important; }
#news-panel.resizing { user-select: none !important; }
#news-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 14px;
border-bottom: 1px solid var(--border);
background: var(--bg-elev);
flex-shrink: 0;
cursor: grab;
touch-action: none;
}
#news-panel.dragging #news-header { cursor: grabbing !important; }
#news-title {
font-size: 13px;
font-weight: 600;
color: var(--text);
letter-spacing: 0.02em;
pointer-events: none;
}
#news-list {
flex: 1;
padding: 10px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 8px;
}
#news-list::-webkit-scrollbar { width: 6px; }
#news-list::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.news-item {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: 10px;
padding: 8px;
border-radius: var(--radius-sm);
background: var(--bg-elev-2);
border: 1px solid var(--border);
cursor: pointer;
transition: border-color 0.15s ease, background 0.15s ease, transform 0.1s ease;
}
.news-item:hover {
border-color: var(--border-strong);
background: var(--bg-elev);
}
.news-item:active { transform: scale(0.99); }
.news-thumb {
flex-shrink: 0;
width: 56px;
height: 56px;
border-radius: 6px;
overflow: hidden;
background: var(--bg);
border: 1px solid var(--border);
display: grid;
place-items: center;
}
.news-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.news-thumb--fallback {
font-size: 16px;
font-weight: 600;
color: var(--text);
background: linear-gradient(135deg, #1f6feb55, #22d3ee44);
letter-spacing: 0.02em;
}
.news-body {
flex: 1 1 auto;
min-width: 0;
display: flex;
flex-direction: column;
gap: 4px;
overflow: hidden;
}
.news-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.news-source {
font-size: 11px;
color: var(--live);
font-weight: 600;
white-space: nowrap;
}
.news-index {
font-size: 10px;
color: var(--text-faint);
font-family: var(--font-mono);
}
.news-title {
font-size: 12.5px;
line-height: 1.4;
color: var(--text);
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.news-empty {
padding: 20px;
text-align: center;
color: var(--text-dim);
font-size: 13px;
}
/* Load more */
#news-loadmore {
flex-shrink: 0;
padding: 8px 10px 10px;
border-top: 1px solid var(--border);
background: var(--bg-elev);
position: relative;
}
.news-loadmore-btn {
width: 100%;
padding: 9px 12px;
border: 1px solid var(--border-strong);
border-radius: var(--radius-sm);
background: var(--bg-elev-2);
color: var(--text-dim);
font-family: inherit;
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: color 0.15s ease, border-color 0.15s ease;
}
.news-loadmore-btn:hover:not(:disabled) {
color: var(--text);
border-color: var(--live);
}
.news-loadmore-btn:disabled { opacity: 0.6; cursor: default; }
.news-loadmore-btn.loading::after {
content: "";
display: inline-block;
width: 11px;
height: 11px;
margin-left: 8px;
vertical-align: -1px;
border: 2px solid var(--text-faint);
border-top-color: var(--live);
border-radius: 50%;
animation: news-spin 0.7s linear infinite;
}
@keyframes news-spin { to { transform: rotate(360deg); } }
#news-sentinel { position: absolute; bottom: 0; left: 0; right: 0; height: 1px; pointer-events: none; }
/* News resize handle (bottom-right) */
#news-resize-handle {
position: absolute;
bottom: 0;
right: 0;
width: 24px;
height: 24px;
cursor: nwse-resize;
background: transparent;
z-index: 2;
touch-action: none;
}
#news-resize-handle::after {
content: '';
position: absolute;
bottom: 3px;
right: 3px;
width: 14px;
height: 14px;
border-right: 2px solid var(--text-dim);
border-bottom: 2px solid var(--text-dim);
opacity: 0.4;
transition: opacity 0.15s;
}
#news-resize-handle:hover::after { opacity: 1; }
#news-panel.resizing #news-resize-handle::after { opacity: 1; }
/* ── News image card inside chat ──────────────────────────────────────── */
.news-card {
margin-top: 8px;
display: flex;
gap: 10px;
align-items: center;
padding: 8px;
border-radius: var(--radius-sm);
background: var(--bg);
border: 1px solid var(--border);
cursor: pointer;
transition: border-color 0.15s ease;
max-width: 100%;
}
.news-card:hover { border-color: var(--border-strong); }
.news-card-img {
flex-shrink: 0;
width: 64px;
height: 64px;
border-radius: 6px;
object-fit: cover;
display: block;
background: var(--bg-elev);
border: 1px solid var(--border);
}
.news-card-img--fallback {
display: grid;
place-items: center;
font-size: 18px;
font-weight: 600;
color: var(--text);
background: linear-gradient(135deg, #1f6feb55, #22d3ee44);
}
.news-card-meta {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 3px;
}
.news-card-source {
font-size: 10.5px;
font-weight: 600;
color: var(--live);
white-space: nowrap;
}
.news-card-title {
font-size: 12px;
line-height: 1.4;
color: var(--text);
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ── VNEWS control panel ─────────────────────────────────────────────── */
#vnews-panel {
position: fixed;
z-index: 9997;
top: 80px;
right: 20px;
width: 280px;
display: flex;
flex-direction: column;
gap: 10px;
padding: 14px;
background: rgba(10, 11, 16, 0.95);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--border-strong);
border-radius: var(--radius-md);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
touch-action: none;
}
#vnews-panel.dragging { user-select: none !important; }
#vnews-header {
display: flex;
align-items: center;
justify-content: space-between;
cursor: grab;
touch-action: none;
}
#vnews-title {
font-size: 14px;
font-weight: 700;
letter-spacing: 0.03em;
color: var(--live);
}
.vnews-btn {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--border-strong);
border-radius: var(--radius-sm);
background: var(--bg-elev-2);
color: var(--text);
font-family: inherit;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: border-color 0.15s ease, background 0.15s ease;
}
.vnews-btn:hover:not(:disabled) {
border-color: var(--live);
background: var(--bg-elev);
}
.vnews-btn:disabled { opacity: 0.5; cursor: default; }
#vnews-status {
font-size: 11.5px;
color: var(--text-dim);
line-height: 1.4;
}
#vnews-toggle-btn { margin-left: 8px; }
@media (max-width: 600px) {
#identity p { display: none; }
#subtitles { bottom: 128px; font-size: 14px; }
#text-chat { top: 60px; left: 10px; width: calc(100vw - 20px); height: 40vh; }
#news-panel {
bottom: 70px;
right: 10px;
left: 10px;
width: calc(100vw - 20px);
height: 60vh;
min-width: 0;
}
#vnews-panel {
top: 60px;
right: 10px;
left: 10px;
width: calc(100vw - 20px);
}
}
/* ── News card action buttons (Nguα»“n / Hỏi) ───────────────────────────── */
.news-actions {
display: flex;
gap: 6px;
margin-top: 6px;
flex: 1 1 100%;
width: 100%;
}
.news-act-btn {
flex: 1 1 0;
min-width: 0;
padding: 5px 6px;
border: 1px solid var(--border-strong);
border-radius: var(--radius-sm);
background: var(--bg-elev-2);
color: var(--text-dim);
font-family: inherit;
font-size: 11px;
font-weight: 600;
cursor: pointer;
transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.news-act-btn:hover {
color: var(--text);
border-color: var(--live);
background: var(--bg-elev);
}
.news-act-btn--ask {
color: var(--live);
}
.news-act-btn--ask:hover {
background: var(--bg-elev);
}
/* News item description (mΓ΄ tαΊ£ ngαΊ―n dΖ°α»›i tiΓͺu đề) */
.news-desc {
font-size: 11.5px;
line-height: 1.4;
color: var(--text-dim);
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ── Snap (capture PNG) ──────────────────────────────── */
#snap-preview { max-width: 100%; border-radius: 8px; display: block; margin: 0 auto; }
#snap-dialog img { background: #0b0e14; }
#snap-dialog .dialog-actions { flex-wrap: wrap; }
.avatar-thumb-preview {
width: 28px; height: 28px; border-radius: 50%;
object-fit: cover; vertical-align: middle; margin-left: 6px;
border: 1px solid rgba(255,255,255,.3);
}
/* ── Onboarding picker (choose character + voice BEFORE loading) ── */
#loading { display: none; }
#loading.active { display: grid; }
.picker { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; background: rgba(8,11,18,.82); backdrop-filter: blur(6px); padding: 20px; overflow: auto; }
.picker[hidden] { display: none; }
.picker-card { width: min(720px, 96vw); max-height: 92vh; overflow: auto; background: #11151f; border: 1px solid rgba(255,255,255,.08); border-radius: 16px; padding: 22px 24px; color: #e8edf5; box-shadow: 0 20px 60px rgba(0,0,0,.5); }
.picker-card h1 { font-size: 20px; margin: 0 0 4px; }
.picker-sub { color: #9aa6b8; margin: 0 0 14px; font-size: 13px; }
.picker-card h2 { font-size: 14px; margin: 18px 0 10px; color: #cdd6e4; }
.picker-avatars { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 12px; }
.avatar-card { display: flex; flex-direction: column; align-items: center; gap: 8px; background: #0c0f17; border: 2px solid transparent; border-radius: 12px; padding: 10px 8px; cursor: pointer; color: #e8edf5; text-align: center; transition: border-color .15s, transform .1s; }
.avatar-card:hover { transform: translateY(-2px); }
.avatar-card.selected { border-color: #22d3ee; }
.avatar-card-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
.avatar-card-thumb { width: 84px; height: 84px; border-radius: 50%; overflow: hidden; background: linear-gradient(135deg, #1b2230, #2a3550); display: flex; align-items: center; justify-content: center; font-size: 28px; font-weight: 600; color: #cfe9ff; border: 1px solid rgba(255,255,255,.12); }
.avatar-card-name { font-size: 12px; line-height: 1.2; }
.picker-voices { display: flex; flex-wrap: wrap; gap: 8px; }
.voice-chip { border: 1px solid rgba(255,255,255,.15); background: #0c0f17; color: #e8edf5; border-radius: 999px; padding: 7px 14px; cursor: pointer; font-size: 13px; }
.voice-chip.selected { background: #22d3ee; color: #04222a; border-color: #22d3ee; font-weight: 600; }
.picker-start { margin-top: 20px; width: 100%; font-size: 15px; padding: 12px; }
/* ── Topic tags (chα»§ đề HOT, clickable) ── */
.topic-tags { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 10px; border-top: 1px solid rgba(255,255,255,.06); }
.topic-chip { border: 1px solid rgba(34,211,238,.4); background: rgba(34,211,238,.08); color: #a5f3fc; border-radius: 999px; padding: 5px 12px; cursor: pointer; font-size: 12.5px; transition: background .15s, transform .1s; }
.topic-chip:hover { background: rgba(34,211,238,.2); transform: translateY(-1px); }
.topic-chip.active { background: #22d3ee; color: #04222a; font-weight: 600; }
/* ── Start progress bar ── */
.start-progress {
position: absolute;
bottom: 120px;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 12px 24px;
border-radius: 12px;
background: rgba(10, 11, 16, 0.85);
backdrop-filter: blur(6px);
border: 1px solid rgba(255, 255, 255, 0.12);
z-index: 200;
min-width: 280px;
text-align: center;
}
.start-progress__msg {
font-size: 14px;
font-weight: 500;
color: #a5f3fc;
line-height: 1.4;
}
.start-progress__bar {
width: 100%;
height: 6px;
border-radius: 3px;
background: rgba(255, 255, 255, 0.1);
overflow: hidden;
}
.start-progress__fill {
height: 100%;
border-radius: 3px;
background: linear-gradient(90deg, #22d3ee, #06b6d4);
transition: width 0.3s ease;
}
/* ── Avatar thumb fallback (khi chΖ°a cΓ³ server thumbnail) ── */
.thumb-fallback {
width: 28px; height: 28px; border-radius: 50%;
display: inline-flex; align-items: center; justify-content: center;
font-size: 14px; font-weight: 700;
color: #cfe9ff; background: linear-gradient(135deg, #1b2230, #2a3550);
border: 1px solid rgba(255,255,255,.12);
vertical-align: middle;
margin-left: 6px;
flex-shrink: 0;
}