openvibers/openvibe.live Commits

Brand mark → OV monogram: O ring with a comet arc, V drawn inside with a light sweep, orbiting dot, hero sparks; shared by navbar and hero

OP OpenVibers committed 16 Sept 2026 · c15590d4ab · 2 files, +60 −63

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

Changes

ddiff --git a/public/css/style.css b/public/css/style.css
iindex 270fefed..fa1c6e1f 100644
---- a/public/css/style.css
++++ b/public/css/style.css
@@@ -14770,43 +14770,37 @@ a .arena-thread:hover { color: var(--text-primary); background: color-mix(in srg
.arena-me-left > .arena-portrait { flex: 0 0 64px !important; width: 64px !important; height: 64px !important; display: block; }
.arena-me-left > .arena-portrait-initial { display: flex; }
--/* ── Animated brand mark (navbar) — three nodes, live edges, packets doing laps ── */
++/* ── OV brand mark (navbar + hero): the O is a ring with a comet running around it, the V is
++ drawn inside with a light sweep, a dot orbits the ring. Transform/opacity/stroke motion only. ── */
.brand-mark { display: inline-grid; place-items: center; width: 32px; height: 32px; color: var(--accent); flex: none; }
--.brand-mark svg { overflow: visible; transform-origin: 50% 55%; animation: bmFloat 4.5s ease-in-out infinite; }
--.bm-glow { fill: currentColor; opacity: 0.12; transform-box: fill-box; transform-origin: center; animation: bmGlow 3s ease-in-out infinite; }
--.bm-edges { fill: none; stroke: url(#bm-grad); stroke-width: 2.2; stroke-linejoin: round; stroke-dasharray: 6 4; animation: bmDash 1.6s linear infinite; opacity: 0.9; }
--.bm-node { fill: currentColor; stroke: var(--bg-primary, #0f1117); stroke-width: 1.6; transform-box: fill-box; transform-origin: center; animation: bmPulse 2.6s ease-in-out infinite; }
--.bm-node--2 { animation-delay: 0.87s; } .bm-node--3 { animation-delay: 1.73s; }
--.bm-core { fill: #fff; opacity: 0.85; transform-box: fill-box; transform-origin: center; animation: bmCore 2.6s ease-in-out infinite; }
--.bm-pk { fill: #fff; filter: drop-shadow(0 0 3px currentColor); }
--.bm-pk--2 { opacity: 0.7; }
--.nav-brand:hover .brand-mark svg { animation: bmSpin 0.9s cubic-bezier(.2,1.5,.3,1) 1; }
--.nav-brand:hover .bm-glow { opacity: 0.3; }
--.nav-brand:hover .bm-edges { stroke-dasharray: none; animation: none; }
--@keyframes bmFloat { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-1px) rotate(3deg); } }
--@keyframes bmGlow { 0%, 100% { opacity: 0.1; transform: scale(0.9); } 50% { opacity: 0.22; transform: scale(1.08); } }
--@keyframes bmDash { to { stroke-dashoffset: -20; } }
--@keyframes bmPulse { 0%, 70%, 100% { transform: scale(1); } 15% { transform: scale(1.45); } 30% { transform: scale(1); } }
--@keyframes bmCore { 0%, 100% { transform: scale(1); opacity: 0.85; } 50% { transform: scale(1.4); opacity: 1; } }
--@keyframes bmSpin { from { transform: rotate(0deg) scale(1); } 40% { transform: rotate(200deg) scale(1.2); } to { transform: rotate(360deg) scale(1); } }
--@media (prefers-reduced-motion: reduce) { .brand-mark svg, .bm-glow, .bm-edges, .bm-node, .bm-core { animation: none !important; } .bm-pk { display: none; } }
--/* Lite mode keeps the cheap transform/opacity motion; only the drop-shadow filter goes. */
--.rs-lite .bm-pk, .rs-lite .bmh-spark { filter: none; }
--
--/* Hero version: same mark, bigger, with an orbit ring, comet trail and sparks */
++.brand-mark svg { overflow: visible; transform-origin: 50% 50%; animation: ovFloat 5s ease-in-out infinite; }
++.ov-glow { fill: currentColor; opacity: 0.1; transform-box: fill-box; transform-origin: center; animation: ovGlow 3.4s ease-in-out infinite; }
++.ov-ring { fill: none; stroke: currentColor; stroke-width: 4; opacity: 0.28; }
++.ov-comet { fill: none; stroke-width: 4; stroke-linecap: round; stroke-dasharray: 34 79; transform-box: fill-box; transform-origin: center; animation: ovComet 3.6s linear infinite; }
++.ov-v { fill: none; stroke-width: 4.6; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 46; stroke-dashoffset: 0; animation: ovDraw 1.1s cubic-bezier(.2,.8,.2,1) both; }
++.ov-dot { fill: #fff; transform-box: fill-box; transform-origin: center; animation: ovDot 2.4s ease-in-out infinite; }
++.ov-orbit { fill: #fff; filter: drop-shadow(0 0 3px currentColor); }
++.ov-orbit--tail { opacity: 0.5; }
++.nav-brand:hover .brand-mark svg, .hero h1:hover .brand-mark--hero svg { animation: ovSpin 0.9s cubic-bezier(.2,1.5,.3,1) 1; }
++.nav-brand:hover .ov-comet, .hero h1:hover .ov-comet { animation-duration: 0.9s; }
++.nav-brand:hover .ov-glow, .hero h1:hover .ov-glow { opacity: 0.28; }
++.nav-brand:hover .ov-v, .hero h1:hover .ov-v { animation: ovDraw 0.7s cubic-bezier(.2,.8,.2,1) both; }
++@keyframes ovFloat { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-1px) rotate(2deg); } }
++@keyframes ovGlow { 0%, 100% { opacity: 0.08; transform: scale(0.92); } 50% { opacity: 0.2; transform: scale(1.06); } }
++@keyframes ovComet { to { transform: rotate(360deg); } }
++@keyframes ovDraw { from { stroke-dashoffset: 46; } to { stroke-dashoffset: 0; } }
++@keyframes ovDot { 0%, 100% { transform: scale(1); opacity: 0.85; } 50% { transform: scale(1.5); opacity: 1; } }
++@keyframes ovSpin { from { transform: rotate(0deg) scale(1); } 40% { transform: rotate(200deg) scale(1.18); } to { transform: rotate(360deg) scale(1); } }
++/* Hero: bigger, plus sparks off the V */
.brand-mark--hero { width: 1.05em; height: 1.05em; vertical-align: -0.16em; color: var(--accent); margin-right: 0.08em; }
--.brand-mark--hero svg { width: 100%; height: 100%; animation: bmFloat 5s ease-in-out infinite; }
--.brand-mark--hero .bm-edges { stroke: url(#bmh-grad); stroke-width: 2.4; }
--.brand-mark--hero .bm-node { stroke-width: 1.4; }
--.bmh-orbit { fill: none; stroke: currentColor; stroke-width: 0.9; stroke-dasharray: 3 5; opacity: 0.55; transform-box: fill-box; transform-origin: center; animation: bmhOrbit 9s linear infinite; }
--.bmh-trail { opacity: 0.55; } .bmh-trail2 { opacity: 0.3; }
--.bmh-spark { fill: #fff; opacity: 0; transform-box: fill-box; transform-origin: center; animation: bmhSpark 3.4s ease-out infinite; }
--.bmh-spark--2 { animation-delay: 1.1s; animation-name: bmhSpark2; } .bmh-spark--3 { animation-delay: 2.3s; animation-name: bmhSpark3; }
--.hero h1:hover .brand-mark--hero svg { animation: bmSpin 1s cubic-bezier(.2,1.5,.3,1) 1; }
--.hero h1:hover .bmh-orbit { animation-duration: 2s; opacity: 0.9; }
--@keyframes bmhOrbit { to { transform: rotate(360deg); } }
--@keyframes bmhSpark { 0% { opacity: 0; transform: translate(0,0) scale(0.6); } 10% { opacity: 1; } 60% { opacity: 0; transform: translate(11px,-14px) scale(1.4); } 100% { opacity: 0; } }
--@keyframes bmhSpark2 { 0% { opacity: 0; transform: translate(0,0) scale(0.6); } 10% { opacity: 1; } 60% { opacity: 0; transform: translate(-13px,-9px) scale(1.3); } 100% { opacity: 0; } }
--@keyframes bmhSpark3 { 0% { opacity: 0; transform: translate(0,0) scale(0.6); } 10% { opacity: 1; } 60% { opacity: 0; transform: translate(4px,15px) scale(1.2); } 100% { opacity: 0; } }
--@media (prefers-reduced-motion: reduce) { .bmh-orbit, .bmh-spark, .brand-mark--hero svg { animation: none !important; } .bmh-spark { display: none; } }
++.brand-mark--hero svg { width: 100%; height: 100%; }
++.brand-mark--hero .ov-ring { stroke-width: 3.6; } .brand-mark--hero .ov-comet { stroke-width: 3.6; } .brand-mark--hero .ov-v { stroke-width: 4.2; }
++.ov-spark { fill: #fff; opacity: 0; transform-box: fill-box; transform-origin: center; animation: ovSpark 3.4s ease-out infinite; }
++.ov-spark--2 { animation-delay: 1.1s; animation-name: ovSpark2; } .ov-spark--3 { animation-delay: 2.3s; animation-name: ovSpark3; }
++@keyframes ovSpark { 0% { opacity: 0; transform: translate(0,10px) scale(0.6); } 10% { opacity: 1; } 60% { opacity: 0; transform: translate(12px,-12px) scale(1.4); } 100% { opacity: 0; } }
++@keyframes ovSpark2 { 0% { opacity: 0; transform: translate(0,10px) scale(0.6); } 10% { opacity: 1; } 60% { opacity: 0; transform: translate(-13px,-8px) scale(1.3); } 100% { opacity: 0; } }
++@keyframes ovSpark3 { 0% { opacity: 0; transform: translate(0,10px) scale(0.6); } 10% { opacity: 1; } 60% { opacity: 0; transform: translate(3px,16px) scale(1.2); } 100% { opacity: 0; } }
++@media (max-width: 600px) { .brand-mark { width: 26px; height: 26px; } .brand-mark svg { width: 25px; height: 25px; } .brand-mark--hero svg { width: 100%; height: 100%; } }
++.rs-lite .ov-orbit, .rs-lite .ov-spark { filter: none; }
++@media (prefers-reduced-motion: reduce) { .brand-mark svg, .ov-glow, .ov-comet, .ov-v, .ov-dot, .ov-spark { animation: none !important; } .ov-orbit, .ov-spark { display: none; } .ov-comet { stroke-dasharray: none; opacity: 0.9; } }
@media (max-width: 600px) { .brand-mark { width: 26px; height: 26px; } .brand-mark svg { width: 25px; height: 25px; } }
ddiff --git a/public/index.html b/public/index.html
iindex 835219d2..67f82add 100644
---- a/public/index.html
++++ b/public/index.html
@@@ -62,7 +62,7 @@
</script>
<!-- Stylesheets -->
-- <link rel="stylesheet" href="/css/style.css?v=162">
++ <link rel="stylesheet" href="/css/style.css?v=163">
<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">
@@@ -116,16 +116,19 @@
<!-- ═══════════════════════════════════════════════════════════ -->
<nav class="navbar">
<a class="nav-brand" href="/" onclick="return handleLinkClick(event, '/')" data-brand-tooltip="This platform is in early alpha — features may be incomplete, buggy, or change without notice. Data will likely be reset multiple times during the alpha phase. Thanks for testing!">
-- <span class="brand-mark" aria-hidden="true"><svg viewBox="0 0 40 40" width="30" height="30">
-- <defs><linearGradient id="bm-grad" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="currentColor"/><stop offset="1" stop-color="currentColor" stop-opacity="0.55"/></linearGradient></defs>
-- <circle class="bm-glow" cx="20" cy="22" r="17"/>
-- <path id="bm-path" class="bm-edges" d="M20,7 L34,31 L6,31 Z"/>
-- <circle class="bm-node bm-node--1" cx="20" cy="7" r="4.2"/>
-- <circle class="bm-node bm-node--2" cx="34" cy="31" r="4.2"/>
-- <circle class="bm-node bm-node--3" cx="6" cy="31" r="4.2"/>
-- <circle class="bm-core" cx="20" cy="23" r="2.6"/>
-- <circle class="bm-pk" r="1.9"><animateMotion dur="2.6s" repeatCount="indefinite" rotate="auto"><mpath href="#bm-path"/></animateMotion></circle>
-- <circle class="bm-pk bm-pk--2" r="1.4"><animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite"><mpath href="#bm-path"/></animateMotion></circle>
++ <span class="brand-mark" aria-hidden="true"><svg viewBox="0 0 48 48" width="30" height="30">
++ <defs>
++ <linearGradient id="ovn-g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="currentColor"/><stop offset="1" stop-color="currentColor" stop-opacity="0.45"/></linearGradient>
++ <linearGradient id="ovn-v" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fff"/><stop offset="0.5" stop-color="currentColor"/><stop offset="1" stop-color="#fff" stop-opacity="0.9"/><animateTransform attributeName="gradientTransform" type="translate" from="-1 0" to="1 0" dur="3.2s" repeatCount="indefinite"/></linearGradient>
++ <path id="ovn-ring" d="M24,6 A18,18 0 1,1 23.99,6 Z"/>
++ </defs>
++ <circle class="ov-glow" cx="24" cy="24" r="21"/>
++ <circle class="ov-ring" cx="24" cy="24" r="18"/>
++ <circle class="ov-comet" cx="24" cy="24" r="18" stroke="url(#ovn-g)"/>
++ <path class="ov-v" d="M14.5,17 L24,34 L33.5,17" stroke="url(#ovn-v)"/>
++ <circle class="ov-dot" cx="24" cy="34" r="2.6"/>
++ <circle class="ov-orbit" r="2"><animateMotion dur="3.6s" repeatCount="indefinite" rotate="auto"><mpath href="#ovn-ring"/></animateMotion></circle>
++ <circle class="ov-orbit ov-orbit--tail" r="1.4"><animateMotion dur="3.6s" begin="0.14s" repeatCount="indefinite"><mpath href="#ovn-ring"/></animateMotion></circle>
</svg></span>
<span class="brand-text-wrap">
<span class="alpha-badge">ALPHA</span>
@@@ -224,21 +227,21 @@
<div class="hero-collage" id="hero-collage" aria-hidden="true"></div>
<div class="hero-scrim" aria-hidden="true"></div>
<div class="hero-content">
-- <h1><span class="brand-mark brand-mark--hero" aria-hidden="true"><svg viewBox="0 0 40 40">
-- <defs><linearGradient id="bmh-grad" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="currentColor"/><stop offset="1" stop-color="currentColor" stop-opacity="0.5"/></linearGradient></defs>
-- <circle class="bm-glow" cx="20" cy="22" r="18"/>
-- <circle class="bmh-orbit" cx="20" cy="22" r="17.5"/>
-- <path id="bmh-path" class="bm-edges" d="M20,7 L34,31 L6,31 Z"/>
-- <circle class="bm-node bm-node--1" cx="20" cy="7" r="4.2"/>
-- <circle class="bm-node bm-node--2" cx="34" cy="31" r="4.2"/>
-- <circle class="bm-node bm-node--3" cx="6" cy="31" r="4.2"/>
-- <circle class="bm-core" cx="20" cy="23" r="2.8"/>
-- <circle class="bm-pk" r="2.1"><animateMotion dur="2.6s" repeatCount="indefinite"><mpath href="#bmh-path"/></animateMotion></circle>
-- <circle class="bm-pk bmh-trail" r="1.6"><animateMotion dur="2.6s" begin="0.12s" repeatCount="indefinite"><mpath href="#bmh-path"/></animateMotion></circle>
-- <circle class="bm-pk bmh-trail2" r="1.1"><animateMotion dur="2.6s" begin="0.24s" repeatCount="indefinite"><mpath href="#bmh-path"/></animateMotion></circle>
-- <circle class="bm-pk bm-pk--2" r="1.6"><animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite"><mpath href="#bmh-path"/></animateMotion></circle>
-- <circle class="bmh-spark" cx="20" cy="22" r="1.2"/><circle class="bmh-spark bmh-spark--2" cx="20" cy="22" r="1"/><circle class="bmh-spark bmh-spark--3" cx="20" cy="22" r="0.9"/>
-- </svg></span> OpenVibe.Live</h1>
++ <h1><span class="brand-mark brand-mark--hero" aria-hidden="true"><svg viewBox="0 0 48 48">
++ <defs>
++ <linearGradient id="ovh-g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="currentColor"/><stop offset="1" stop-color="currentColor" stop-opacity="0.45"/></linearGradient>
++ <linearGradient id="ovh-v" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fff"/><stop offset="0.5" stop-color="currentColor"/><stop offset="1" stop-color="#fff" stop-opacity="0.9"/><animateTransform attributeName="gradientTransform" type="translate" from="-1 0" to="1 0" dur="3.2s" repeatCount="indefinite"/></linearGradient>
++ <path id="ovh-ring" d="M24,6 A18,18 0 1,1 23.99,6 Z"/>
++ </defs>
++ <circle class="ov-glow" cx="24" cy="24" r="21"/>
++ <circle class="ov-ring" cx="24" cy="24" r="18"/>
++ <circle class="ov-comet" cx="24" cy="24" r="18" stroke="url(#ovh-g)"/>
++ <path class="ov-v" d="M14.5,17 L24,34 L33.5,17" stroke="url(#ovh-v)"/>
++ <circle class="ov-dot" cx="24" cy="34" r="2.6"/>
++ <circle class="ov-orbit" r="2"><animateMotion dur="3.6s" repeatCount="indefinite" rotate="auto"><mpath href="#ovh-ring"/></animateMotion></circle>
++ <circle class="ov-orbit ov-orbit--tail" r="1.4"><animateMotion dur="3.6s" begin="0.14s" repeatCount="indefinite"><mpath href="#ovh-ring"/></animateMotion></circle>
++ <circle class="ov-spark" cx="24" cy="24" r="1.3"/><circle class="ov-spark ov-spark--2" cx="24" cy="24" r="1"/><circle class="ov-spark ov-spark--3" cx="24" cy="24" r="1.1"/>
++ </svg></span> OpenVibe.Live</h1>
<p class="hero-tagline">Live streaming for <span class="hero-rotate-wrap"><span class="hero-rotate" id="hero-rotate"></span></span></p>
<p class="hero-quip" id="hero-quip" aria-live="polite"></p>
<div class="hero-slogan-timer" id="hero-slogan-timer" hidden></div>