feat: glitter sparkles on heart, metallic gold text across all headings

- Add animated gold sparkle dots on heart surface with glow filter
- Brighten heart metal fill for better visibility against dark bg
- Update headline gradient to dark metallic gold (no white tones)
- Apply gradient-text to all section headings for consistency
- Warm gold subtitle color in hero

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 12:55:31 +03:00
parent 04963fb0de
commit c28c9a05a8
4 changed files with 74 additions and 11 deletions

View File

@@ -25,6 +25,25 @@ const ANIM_CONFIG = [
const FULL_PATH = PATHS.join(" ");
// Glitter sparkle positions (x, y) placed within the heart shape
const SPARKLES = [
{ x: 150, y: 30, delay: 0, dur: 2.4 },
{ x: 185, y: 55, delay: 1.1, dur: 2.0 },
{ x: 200, y: 85, delay: 0.5, dur: 2.8 },
{ x: 170, y: 110, delay: 2.0, dur: 2.2 },
{ x: 145, y: 75, delay: 1.6, dur: 2.6 },
{ x: 130, y: 50, delay: 0.3, dur: 2.1 },
{ x: 160, y: 140, delay: 2.5, dur: 2.4 },
{ x: 125, y: 160, delay: 1.8, dur: 2.0 },
{ x: 105, y: 100, delay: 0.8, dur: 2.5 },
{ x: 90, y: 70, delay: 1.3, dur: 2.3 },
{ x: 75, y: 45, delay: 2.2, dur: 2.1 },
{ x: 60, y: 80, delay: 0.6, dur: 2.7 },
{ x: 50, y: 55, delay: 1.9, dur: 2.0 },
{ x: 40, y: 95, delay: 0.2, dur: 2.4 },
{ x: 115, y: 130, delay: 1.4, dur: 2.6 },
];
export function HeroLogo({ className = "", size = 220 }: HeroLogoProps) {
const h = Math.round(size * (192 / 234));
@@ -41,9 +60,9 @@ export function HeroLogo({ className = "", size = 220 }: HeroLogoProps) {
<defs>
{/* Dark metal gradient for fill */}
<radialGradient id="metal-fill" cx="50%" cy="35%" r="65%" fx="50%" fy="30%">
<stop offset="0%" stopColor="#222" />
<stop offset="50%" stopColor="#111" />
<stop offset="100%" stopColor="#0a0a0a" />
<stop offset="0%" stopColor="#333" />
<stop offset="50%" stopColor="#1a1a1a" />
<stop offset="100%" stopColor="#111" />
</radialGradient>
{/* Gold glow filter for the stroke */}
@@ -54,6 +73,20 @@ export function HeroLogo({ className = "", size = 220 }: HeroLogoProps) {
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
{/* Sparkle glow filter */}
<filter id="sparkle-glow" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
{/* Clip to heart shape so sparkles stay inside */}
<clipPath id="heart-clip">
<path d={FULL_PATH} fillRule="evenodd" />
</clipPath>
</defs>
{/* Base heart: dark metal */}
@@ -63,6 +96,28 @@ export function HeroLogo({ className = "", size = 220 }: HeroLogoProps) {
d={FULL_PATH}
/>
{/* Glitter sparkles on heart surface */}
<g clipPath="url(#heart-clip)" filter="url(#sparkle-glow)">
{SPARKLES.map((s, i) => (
<circle key={`sparkle-${i}`} cx={s.x} cy={s.y} r="1.8" fill="#d4b87a">
<animate
attributeName="opacity"
values="0;0;0.9;1;0.9;0;0"
dur={`${s.dur}s`}
begin={`${s.delay}s`}
repeatCount="indefinite"
/>
<animate
attributeName="r"
values="0.8;1.8;0.8"
dur={`${s.dur}s`}
begin={`${s.delay}s`}
repeatCount="indefinite"
/>
</circle>
))}
</g>
{/* Animated gold glint — one per sub-path, staggered */}
{PATHS.map((d, i) => {
const len = PATH_LENGTHS[i];
@@ -92,13 +147,13 @@ export function HeroLogo({ className = "", size = 220 }: HeroLogoProps) {
);
})}
{/* Subtle constant gold edge highlight */}
{/* Constant gold edge highlight */}
<path
d={FULL_PATH}
fill="none"
stroke="#c9a96e"
strokeWidth="0.5"
strokeOpacity="0.15"
strokeWidth="0.75"
strokeOpacity="0.3"
fillRule="evenodd"
/>
</svg>

View File

@@ -8,7 +8,7 @@ export function SectionHeading({ children, className = "", centered = false }: S
return (
<div className={centered ? "text-center" : ""}>
<h2
className={`font-display text-4xl font-bold uppercase tracking-wide sm:text-5xl lg:text-6xl heading-text ${className}`}
className={`font-display text-4xl font-bold uppercase tracking-wide sm:text-5xl lg:text-6xl gradient-text ${className}`}
>
{children}
</h2>