feat(site): pro hero with animated ring and floating stat chips

- hero-ring: continuously shifting gradient hairline around the hero
  frame (mask-drawn, reduced-motion safe).
- glass-chip: frosted floating pills under the CTAs that bob on a
  staggered loop, live online counter keeps ticking for the Online chip.
- Taller hero for more presence on desktop.
This commit is contained in:
openhands committed 2026-09-12 18:08:09 +02:00
1 parent 8a1b83b965
commit fd7b29a5f8
2 files changed
+135 -1

No files matched your search

+62 -1
View File
@@ -248,8 +248,9 @@ export default async function Home() {
}}
/>
<AmbientOrbs />
<div className="hero-ring" aria-hidden="true" style={{ zIndex: 3 }} />
<div
className="relative flex flex-col items-center gap-5 px-4 py-10 text-center sm:gap-8 sm:px-6 sm:py-12 md:px-12 md:py-20"
className="relative flex flex-col items-center gap-5 px-4 py-12 text-center sm:gap-8 sm:px-6 sm:py-14 md:px-12 md:py-24"
style={{ zIndex: 2 }}
>
<div
@@ -331,6 +332,66 @@ export default async function Home() {
{th("login")}
</Link>
</div>
<div className="flex flex-wrap items-center justify-center gap-2 sm:gap-2.5">
{[
{
value: users,
label: tp("statsCitizens"),
icon: ICON_FRIENDS,
live: false,
},
{
value: rooms,
label: tp("statsRooms"),
icon: ICON_CATALOG,
live: false,
},
{
value: online,
label: tp("statsOnline"),
icon: ICON_NAV_ME,
live: true,
},
].map((s) => (
<div key={s.label} className="glass-chip">
<Image
src={s.icon}
alt=""
width={12}
height={12}
unoptimized
className="opacity-70"
/>
<span
className="glass-chip-dot"
style={{
background: s.live
? "var(--color-primary)"
: "color-mix(in srgb, var(--color-text-muted) 55%, transparent)",
boxShadow: s.live
? "0 0 10px color-mix(in srgb, var(--color-primary) 70%, transparent)"
: "none",
}}
/>
<span
className="glass-chip-value"
style={{
color: "var(--color-text-readable)",
fontSize: "13px",
}}
>
{s.value === null ? (
<span className="text-xs">{te("unavailable")}</span>
) : s.live ? (
<LiveOnlineCounter initial={s.value} />
) : (
<AnimatedCounter value={s.value} />
)}
</span>
<span className="glass-chip-label">{s.label}</span>
</div>
))}
</div>
</div>
</div>
</Reveal>
+73
View File
@@ -2262,4 +2262,77 @@ html {
.brand-halo {
animation: none;
}
.hero-ring,
.glass-chip {
animation: none;
}
}
/* ── Hero pro touches ──────────────────────────────────────────────── */
/* Continuously shifting gradient hairline drawn on the hero border. */
.hero-ring {
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
background: linear-gradient(
120deg,
color-mix(in srgb, var(--color-primary) 70%, transparent) 0%,
color-mix(in srgb, var(--color-accent) 60%, transparent) 35%,
var(--color-surface) 50%,
color-mix(in srgb, var(--color-accent) 60%, transparent) 65%,
color-mix(in srgb, var(--color-primary) 70%, transparent) 100%
);
background-size: 260% 260%;
animation: gradient-shift 14s ease-in-out infinite;
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask-composite: exclude;
pointer-events: none;
}
/* Frosted floating stat chips that bob gently on the hero. */
.glass-chip {
display: inline-flex;
align-items: center;
gap: 0.45rem;
padding: 0.45rem 0.85rem;
border-radius: 999px;
background: color-mix(in srgb, var(--color-surface) 38%, transparent);
border: 1px solid color-mix(in srgb, var(--color-text-muted) 14%, transparent);
box-shadow:
0 10px 26px -10px color-mix(in srgb, #000 30%, transparent),
inset 0 1px 0 0 color-mix(in srgb, #fff 12%, transparent);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
animation: float 5s ease-in-out infinite;
}
.glass-chip:nth-child(2) {
animation-delay: -1.7s;
}
.glass-chip:nth-child(3) {
animation-delay: -3.4s;
}
.glass-chip-dot {
width: 0.45rem;
height: 0.45rem;
border-radius: 999px;
flex-shrink: 0;
}
.glass-chip-value {
font-weight: 900;
font-variant-numeric: tabular-nums;
line-height: 1;
}
.glass-chip-label {
font-size: 9px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--color-text-muted);
}