diff --git a/neode-ui/public/assets/img/app-icons/alby-hub.svg b/neode-ui/public/assets/img/app-icons/alby-hub.svg index a5ac1825..1dbec155 100644 --- a/neode-ui/public/assets/img/app-icons/alby-hub.svg +++ b/neode-ui/public/assets/img/app-icons/alby-hub.svg @@ -1,4 +1,4 @@ - + diff --git a/neode-ui/public/assets/img/app-icons/phoenixd.svg b/neode-ui/public/assets/img/app-icons/phoenixd.svg index 5122fcb8..1c196615 100644 --- a/neode-ui/public/assets/img/app-icons/phoenixd.svg +++ b/neode-ui/public/assets/img/app-icons/phoenixd.svg @@ -1,4 +1,4 @@ - + diff --git a/neode-ui/src/components/ScreensaverLogo.vue b/neode-ui/src/components/ScreensaverLogo.vue index b42b0889..02f91c76 100644 --- a/neode-ui/src/components/ScreensaverLogo.vue +++ b/neode-ui/src/components/ScreensaverLogo.vue @@ -1,5 +1,5 @@
+
diff --git a/neode-ui/src/components/federation/NetworkMap3D.vue b/neode-ui/src/components/federation/NetworkMap3D.vue index ccc5f39c..2e23fe1f 100644 --- a/neode-ui/src/components/federation/NetworkMap3D.vue +++ b/neode-ui/src/components/federation/NetworkMap3D.vue @@ -878,7 +878,9 @@ function tick(_time: number, deltaMS: number) { } function attachTicker() { - if (tickerAttached || staticMode) return + // Kiosks run staticMode for PLACEMENT (instant, intro-free) but still get + // the calm orbit — half-rate via the kioskLowPower frame-skip in tick(). + if (tickerAttached || (staticMode && !kioskLowPower)) return gsap.ticker.add(tick) tickerAttached = true } @@ -1179,17 +1181,19 @@ function measure() { } // Resize: snap to the current mode's fit (no tween — tracks the drag) applyMode(viewMode.value, false) + // No ticker (reduced-motion) means nobody repaints after this resize — + // without an explicit render the map keeps its stale (possibly zero-size) + // projection: the "loads blank / wrong scale until refresh" bug. + if (built && !tickerAttached) render() } function initialBuild() { - // Kiosk TVs get the fully static map: no entrance animation, no ticker. - // The GSAP intro needs healthy rAF delivery to ever reach opacity 1 — on - // a paint-starved kiosk it stalls and the screen reads as BLANK until a - // lucky refresh (framework-pt, 2026-08-14). Half-rate ticking (below) - // helped but any continuous SVG animation is still the single biggest - // load on the kiosk's compositor, and at TV distance the still map loses - // nothing. Everything lands in place immediately, graph updates apply - // instantly, and the 2D/3D toggle still works. + // Kiosk TVs take the static PLACEMENT path (the GSAP entrance intro needs + // healthy rAF delivery to reach opacity 1 — on a paint-starved kiosk it + // stalls and the screen reads as BLANK until a lucky refresh, + // framework-pt 2026-08-14) but keep the calm orbital motion: the ticker + // re-attaches below at half rate. Fully-static-everything was tried and + // rejected — it also killed the animation on screens that could carry it. staticMode = prefersReducedMotion() || kioskLowPower built = true applyGraph() @@ -1208,6 +1212,8 @@ function initialBuild() { if (staticMode) { introPlayed = true playIntro() // static branch: everything lands in place + attachTicker() // no-op for reduced-motion; kiosks resume the calm orbit + render() // paint the landed state now — nothing else repaints until a tick return } attachTicker() diff --git a/neode-ui/src/style.css b/neode-ui/src/style.css index fe70e684..aa1535ea 100644 --- a/neode-ui/src/style.css +++ b/neode-ui/src/style.css @@ -1135,13 +1135,15 @@ html.controller-nav [data-controller-container]:focus { lower reflection arc, bottom depth vignette, paint-black base; inset rim lights; and a curved liquid "window streak" on ::before (under the badge's z-1 content, above the paint). Revert: delete this block. */ - .logo-gradient-border { + .logo-gradient-border.logo-gloss, + .tap-to-start-logo .logo-gradient-border { background: none; box-shadow: none; padding: 0; overflow: hidden; } - .logo-gradient-border::after { + .logo-gradient-border.logo-gloss::after, + .tap-to-start-logo .logo-gradient-border::after { inset: 0; /* Dense intermediate stops + a fine turbulence grain (top layer, overlay-blended) dither the near-black falloffs — without them the @@ -1160,7 +1162,8 @@ html.controller-nav [data-controller-container]:focus { inset 0 0 0 1px rgba(255,242,212,0.08), 0 12px 34px rgba(0,0,0,0.65); } - .logo-gradient-border::before { + .logo-gradient-border.logo-gloss::before, + .tap-to-start-logo .logo-gradient-border::before { content: ''; position: absolute; left: 8%; diff --git a/neode-ui/src/views/Login.vue b/neode-ui/src/views/Login.vue index 3395cdf1..37d35141 100644 --- a/neode-ui/src/views/Login.vue +++ b/neode-ui/src/views/Login.vue @@ -8,7 +8,7 @@ >
-
+
diff --git a/neode-ui/src/views/OnboardingIntro.vue b/neode-ui/src/views/OnboardingIntro.vue index 9028fea2..8c605db6 100644 --- a/neode-ui/src/views/OnboardingIntro.vue +++ b/neode-ui/src/views/OnboardingIntro.vue @@ -4,7 +4,7 @@