openvibers/openvibe.live Commits

Arena: phone layout for expanded ladder rows — single column, bubbles for taunts, inline quips, full names

OP OpenVibers committed 30 Aug 2026 · 3949c0109b · 3 files, +28 −4

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017AyeSFu7qdLdR64Zv99QNm

Changes

ddiff --git a/public/css/style.css b/public/css/style.css
iindex 652aedad..5856ff7e 100644
---- a/public/css/style.css
++++ b/public/css/style.css
@@@ -14650,3 +14650,27 @@ a .arena-thread:hover { color: var(--text-primary); background: color-mix(in srg
.arena-numbers-compact { grid-template-columns: repeat(3, 1fr); }
.arena-profile-custom { grid-template-columns: 1fr; }
}
++
++/* ── Arena: phone layout for expanded ladder rows + quips (specificity matches the open rule) ── */
++.arena-quip-val { display: inline-block; min-width: 2.1em; text-align: right; color: var(--accent-light); font-variant-numeric: tabular-nums; margin-right: 4px; }
++.arena-row-bubbles { margin: 0 0 10px; }
++.arena-row-bubbles .arena-bubble { padding: 8px 10px; }
++.arena-row-bubbles .arena-bubble-text { font-size: 0.88rem; }
++@media (max-width: 700px) {
++ .arena-row.is-open .arena-row-expand { grid-template-columns: 1fr; gap: 12px; padding: 12px 0 4px; }
++ .arena-row-expand > div:first-child { display: flex; flex-direction: column; align-items: center; }
++ .arena-row-expand .arena-radar { max-width: 230px; width: 100%; margin: 0 auto; }
++ .arena-row-expand .arena-mini-record { text-align: center; }
++ .arena-row-lore.is-clamp { -webkit-line-clamp: 4; font-size: 0.9rem; }
++ .arena-row-expand .arena-quips, .arena-row-expand .arena-quips-custom { display: flex; flex-direction: column; gap: 6px; }
++ .arena-row-expand .arena-quip { display: grid; grid-template-columns: auto 1fr; gap: 8px; align-items: baseline; font-size: 0.86rem; }
++ .arena-row-expand .arena-quip b { white-space: nowrap; }
++ .arena-row-expand .arena-quip span { color: var(--text-secondary); }
++ .arena-row-expand-actions { flex-direction: row; flex-wrap: wrap; }
++ .arena-row-expand-actions .btn { flex: 1 1 auto; justify-content: center; }
++ .arena-row-taunt { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
++ .arena-row-main strong { white-space: normal; }
++ .arena-profile-custom .arena-quips-custom { display: flex; flex-direction: column; gap: 6px; }
++ .arena-profile-custom .arena-quip { display: grid; grid-template-columns: auto 1fr; gap: 8px; align-items: baseline; }
++ .arena-profile-custom .arena-quip b { white-space: nowrap; }
++}
ddiff --git a/public/index.html b/public/index.html
iindex 55e18147..1858cfca 100644
---- a/public/index.html
++++ b/public/index.html
@@@ -62,7 +62,7 @@
</script>
<!-- Stylesheets -->
-- <link rel="stylesheet" href="/css/style.css?v=153">
++ <link rel="stylesheet" href="/css/style.css?v=154">
<link rel="stylesheet" href="/css/chat-shared.css?v=1">
<link rel="stylesheet" href="/css/broadcast.css?v=11">
<link rel="stylesheet" href="/css/cosmetics.css?v=2">
@@@ -5107,7 +5107,7 @@ curl -s https://openvibe.media/live/@Goosely/chat-insight.json | jq ".chat_insig
<script src="/js/staff-console.js?v=1" defer></script>
<script src="/js/dashboard-moderation.js?v=5" defer></script>
<script src="/js/ai-viewers.js?v=2" defer></script>
--<script src="/js/arena.js?v=15" defer></script>
++<script src="/js/arena.js?v=16" defer></script>
<script src="/js/powerchat.js?v=10" defer></script>
<script src="/js/pastes.js?v=15" defer></script>
<script src="/js/draggable-fab.js?v=2" defer></script>
ddiff --git a/public/js/arena.js b/public/js/arena.js
iindex a96c7abb..a9ed19cf 100644
---- a/public/js/arena.js
++++ b/public/js/arena.js
@@@ -142,7 +142,7 @@ function _aCustomRadar(f, color, size = 240) {
function _aCustomQuips(f) {
const cs = (f.persona && Array.isArray(f.persona.custom_stats) ? f.persona.custom_stats : []);
if (!cs.length) return '';
-- return `<div class="arena-quips arena-quips-custom">${cs.map(x => `<div class="arena-quip"><b>${_aEsc(x.name)} ${Number(x.value)}</b><span>${_aEsc(x.quip || '')}</span></div>`).join('')}</div>`;
++ return `<div class="arena-quips arena-quips-custom">${cs.map(x => `<div class="arena-quip"><b><span class="arena-quip-val">${Number(x.value)}</span> ${_aEsc(x.name)}</b><span>${_aEsc(x.quip || '')}</span></div>`).join('')}</div>`;
}
/** Sparkline of a per-stream series. */
@@@ -603,7 +603,7 @@ function _aRenderList(fighters) {
<div>${_aCustomRadar(f, f.user.profile_color || '#8b5cf6', 220)}<div class="arena-mini-record">${(f.persona.custom_stats || []).length ? 'AI characteristics · ' : ''}${f.category ? _aEsc(f.category) + ' · ' : ''}last live ${_aEsc(f.last_live_at ? _aDate(f.last_live_at) : '—')}</div></div>
<div>
<p class="arena-row-lore is-clamp">${_aEsc(f.persona.lore)}</p>
-- ${(f.persona.taunts || []).length ? `<div class="arena-row-taunts">${f.persona.taunts.slice(0, 2).map(t => `<em>“${_aEsc(t)}” ${_aSpeakBtn(t, '', f.user.username)}</em>`).join('')}${f.persona.typing_style ? `<small><i class="fa-solid fa-keyboard"></i> ${_aEsc(f.persona.typing_style)}</small>` : ''}</div>` : ''}
++ ${(f.persona.taunts || []).length ? `<div class="arena-bubbles arena-row-bubbles">${f.persona.taunts.slice(0, 2).map(t => `<div class="arena-bubble"><span class="arena-bubble-who">${_aEsc(f.user.display_name || f.user.username)}</span><span class="arena-bubble-text">${_aEsc(t)}</span>${_aSpeakBtn(t, 'arena-bubble-speak', f.user.username)}</div>`).join('')}${f.persona.typing_style ? `<small class="arena-note"><i class="fa-solid fa-keyboard"></i> ${_aEsc(f.persona.typing_style)}</small>` : ''}</div>` : ''}
${(f.persona.custom_stats || []).length ? _aCustomQuips(f) : `<div class="arena-quips">${ARENA_STATS.map(k => `<div class="arena-quip"><b>${_aEsc(ARENA_STAT_LABEL[k])} ${f.ratings[k]}</b><span>${_aEsc((f.persona.stat_quips || {})[k] || '')}</span></div>`).join('')}</div>`}
${f.persona.signature_move ? `<div class="arena-mini-record"><b>Signature:</b> ${_aEsc(f.persona.signature_move.name)} — ${_aEsc(f.persona.signature_move.description)}</div>` : ''}
</div>