Put the NGU dove at the centre of the brand hero's rings

DoveMark carries the dove path from the original home page as its
own component. The hero draws it at the rings' centre, upright while
they turn, with a soft glow and a gentle bob that stops under reduced
motion. The rings' opacity moves from the SVG to their own group so
the dove isn't dimmed with them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Zaldimmar 2026-09-25 05:49:52 -05:00
parent 6a69084de2
commit 641ab167b0
3 changed files with 75 additions and 11 deletions

View file

@ -4,7 +4,8 @@
The top of the front page, in whichever mode the admin set:
brand drifting colour and slow concentric rings — many
circles, one centre — behind the words
circles, one centre — behind the words, with the
dove at that centre
photos the hero photos, crossfading with a slow zoom, a
progress bar per photo and a pause button (anything
that moves on its own for more than five seconds
@ -24,6 +25,7 @@
import { useEffect, useState, type CSSProperties } from 'react'
import HomeLink from './HomeLink.tsx'
import DoveMark from '../../../components/DoveMark.tsx'
import { livestreamEmbedUrl } from '../../../lib/embeds.ts'
import { heroPhoto } from '../../../lib/media.ts'
import type { Hero, HeroSlide } from '../../../lib/useFrontPage.ts'
@ -157,19 +159,38 @@ function BrandBackdrop() {
<div className="hp-aurora hp-aurora--c" style={blob('#d8b64a', '30vw', '70%', '-5%')} />
<svg
className="absolute -right-[20vw] top-1/2 h-[120vw] w-[120vw] -translate-y-1/2 opacity-[0.16] md:-right-[10vw] md:h-[80vw] md:w-[80vw]"
className="absolute -right-[20vw] top-1/2 h-[120vw] w-[120vw] -translate-y-1/2 md:-right-[10vw] md:h-[80vw] md:w-[80vw]"
viewBox="0 0 400 400"
>
<g className="hp-rings" fill="none" stroke="#ffffff">
{[40, 70, 100, 130, 160, 190].map((r, i) => (
<circle key={r} cx="200" cy="200" r={r} strokeWidth={i % 2 ? 0.6 : 1.2} strokeDasharray={i % 2 ? '2 6' : undefined} />
))}
<circle cx="390" cy="200" r="4" fill="#9fe7d0" stroke="none" />
<circle cx="200" cy="40" r="3" fill="#5ce7ff" stroke="none" />
<defs>
<radialGradient id="hp-dove-glow">
<stop offset="0%" stopColor="#9fe7d0" stopOpacity="0.35" />
<stop offset="100%" stopColor="#9fe7d0" stopOpacity="0" />
</radialGradient>
</defs>
{/* The rings are faint; the dove at their centre is not, so
the opacity sits on the rings rather than the whole SVG. */}
<g opacity="0.16">
<g className="hp-rings" fill="none" stroke="#ffffff">
{[40, 70, 100, 130, 160, 190].map((r, i) => (
<circle key={r} cx="200" cy="200" r={r} strokeWidth={i % 2 ? 0.6 : 1.2} strokeDasharray={i % 2 ? '2 6' : undefined} />
))}
<circle cx="390" cy="200" r="4" fill="#9fe7d0" stroke="none" />
<circle cx="200" cy="40" r="3" fill="#5ce7ff" stroke="none" />
</g>
<g className="hp-rings hp-rings--reverse" fill="none" stroke="#9fe7d0">
<circle cx="200" cy="200" r="115" strokeWidth="0.8" strokeDasharray="1 10" />
<circle cx="85" cy="200" r="3.5" fill="#ffffff" stroke="none" />
</g>
</g>
<g className="hp-rings hp-rings--reverse" fill="none" stroke="#9fe7d0">
<circle cx="200" cy="200" r="115" strokeWidth="0.8" strokeDasharray="1 10" />
<circle cx="85" cy="200" r="3.5" fill="#ffffff" stroke="none" />
{/* Outside the rotating groups, so it stays upright while the
rings turn around it. 64 × 42.7 at the centre fits inside
the innermost ring (r 40) with room to float. */}
<circle cx="200" cy="200" r="46" fill="url(#hp-dove-glow)" />
<g className="hp-dove" style={{ color: '#ffffff' }} opacity="0.9">
<DoveMark x="168" y="178.65" width="64" height="42.7" />
</g>
</svg>

View file

@ -44,6 +44,18 @@
to { transform: rotate(360deg); }
}
/* The dove at the rings' centre bobs gently rather than turning. */
.hp-dove {
animation: hp-bob 6s ease-in-out infinite;
transform-box: fill-box;
transform-origin: center;
}
@keyframes hp-bob {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
/* ── Hero: headline words rise in ────────────────────────────── */
.hp-rise {
@ -137,6 +149,7 @@
@media (prefers-reduced-motion: reduce) {
.hp-aurora,
.hp-rings,
.hp-dove,
.hp-slide--on img,
.hp-live-dot {
animation: none;