From e3e5cefd03d5fcf01209b38cbaaddc75ac001b94 Mon Sep 17 00:00:00 2001 From: artheru Date: Wed, 10 Jun 2026 08:37:52 +0800 Subject: [PATCH] liveliness + consistency: activity reveal, gatehouse count-up (0.62.0) - Reveal now accepts a tag prop so it can wrap semantic elements - 'Live in the tavern' activity items stagger-fade-up as they scroll into view (as
  • , valid list semantics), matching the feature cards - gatehouse stats now count up from 0, consistent with the home hero - both respect prefers-reduced-motion - verified live: 8 items reveal (opacity 1, not stuck), gatehouse Count renders, 0 exceptions --- index.html | 2 +- package.json | 2 +- src/Scene2D.jsx | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/index.html b/index.html index fcb9ea2..c8f87e2 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + diff --git a/package.json b/package.json index dd2036d..0321ce8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amerc-site", - "version": "0.61.0-syntax", + "version": "0.62.0-liveness", "private": true, "type": "module", "scripts": { diff --git a/src/Scene2D.jsx b/src/Scene2D.jsx index b077bd7..d9a3d38 100644 --- a/src/Scene2D.jsx +++ b/src/Scene2D.jsx @@ -7,7 +7,7 @@ import Account from './Account.jsx'; import TavernGame from './TavernGame.jsx'; import { api } from './api.js'; -const RELEASE = '0.61.0-syntax'; +const RELEASE = '0.62.0-liveness'; const NAV = [ { id: 'home', label: 'Tavern' }, @@ -86,7 +86,7 @@ function Count({ n }) { } // Fade-up as the element scrolls into view; always-visible fallback if no IO / reduced motion. -function Reveal({ children, className = '', delay = 0 }) { +function Reveal({ children, className = '', delay = 0, tag: Tag = 'div' }) { const ref = useRef(null); const [armed] = useState(() => typeof window !== 'undefined' && 'IntersectionObserver' in window && !prefersReducedMotion()); const [shown, setShown] = useState(false); @@ -95,7 +95,7 @@ function Reveal({ children, className = '', delay = 0 }) { const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }); }, { threshold: 0.12, rootMargin: '0px 0px -6% 0px' }); io.observe(ref.current); return () => io.disconnect(); }, [armed]); - return
    {children}
    ; + return {children}; } function Home({ setRoute }) { @@ -149,7 +149,7 @@ function ActivityFeed() {

    Live in the tavern

    @@ -309,9 +309,9 @@ function Gatehouse({ auth, setRoute }) {
    🔓 One sign-in works across tavern, docs, PM and git.
    {stats && (
    - {stats.classes} classes - {stats.online} online - {stats.sessions} sessions + classes + online + sessions
    )}