openvibers/openvibe.live Commits

Hero: stop the background flashing black while the stat board expands

OP OpenVibers committed 16 Sept 2026 · e2aa9db1ec · 2 files, +23 −1

The board sits over the hero's photographic background with backdrop-filter: blur(10px), and the
expand animates its height. A backdrop filter re-rasterises everything behind the element on
every frame of that animation, so on a phone the hero image, the title and the philosophy row all
vanished for the length of the animation and snapped back at the end.

No blur while the height is animating, and none at all below 900px — the same trade the navbar
already makes on small screens. The board keeps a slightly more opaque background of its own so
the text never ends up sitting on bare backdrop.

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

Changes

ddiff --git a/public/css/style.css b/public/css/style.css
iindex ea04dd37..c9d82cdd 100644
---- a/public/css/style.css
++++ b/public/css/style.css
@@@ -15149,3 +15149,25 @@ a .arena-thread:hover { color: var(--text-primary); background: color-mix(in srg
.nav-coins, .nav-balance { max-width: 88px; overflow: hidden; }
.nav-avatar-wrap .nav-username { display: none; }
}
++
++/* ── The stat board's backdrop blur ──────────────────────────────────────────
++ .hero-stats sits over the hero's photographic background with backdrop-filter: blur(10px), and
++ the expand/collapse animates its height. A backdrop filter has to re-rasterise everything
++ behind the element on every frame of that animation — on a phone that means the hero image,
++ the title and the philosophy row all go missing for the duration and snap back at the end,
++ which is exactly what it looked like.
++
++ So: no blur while the height is animating, and none at all on a phone. The board already has
++ its own translucent background, so it stays legible either way. This is the same trade the
++ navbar already makes on small screens for scroll performance. */
++.hero-stats.is-swapping { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
++/* An opaque-enough panel while animating, so the text never sits on bare background. */
++.hero-stats.is-swapping { background: color-mix(in srgb, var(--bg-primary) 88%, transparent); }
++@media (max-width: 900px) {
++ .hero-stats {
++ backdrop-filter: none; -webkit-backdrop-filter: none;
++ background: color-mix(in srgb, var(--bg-primary) 86%, transparent);
++ }
++}
++/* Nothing inside the hero should be re-rasterised by the board changing size. */
++#page-home .hero-content > h1, #page-home .hero-tagline, #page-home .hero-philosophy-links { will-change: auto; }
ddiff --git a/public/index.html b/public/index.html
iindex de04b25d..f09cddb6 100644
---- a/public/index.html
++++ b/public/index.html
@@@ -88,7 +88,7 @@
overlay) and is fetched without blocking the first paint: media="print" makes the browser
treat it as non-critical, and the onload flips it back to all once it has arrived. -->
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
-- <link rel="stylesheet" href="/css/style.css?v=189">
++ <link rel="stylesheet" href="/css/style.css?v=190">
<link rel="stylesheet" href="/css/home-fx.css?v=12">
<link rel="stylesheet" href="/css/home-tour.css?v=7">
<link rel="stylesheet" href="/css/i18n-star.css?v=5">