@@ -43,11 +43,9 @@ const ORB_BEAT = 450
4343/** Closing hold on the wordmark before the loop wraps back to the opening hold. */
4444const HOLD_LOGO_END = 1700
4545const TAIL = 200
46- /** Goo blur while liquid (through the cycle) and while crisp ( the wordmark) . */
46+ /** Blur range for the filtered portion of the morph . */
4747const GOO_HI = 5
4848const GOO_LO = 0.55
49- /** Post-threshold blur, about half a device pixel at the mark's largest size. */
50- const EDGE_SMOOTHING = 0.16
5149/**
5250 * Shapes that restart from compact when they appear and play exactly one pulse
5351 * of this many ms (just under a loop, so the dots reach the edge without
@@ -356,13 +354,19 @@ interface StageNode {
356354 key : StageKey
357355}
358356
357+ interface GooFilterNodes {
358+ blur : SVGFEGaussianBlurElement
359+ group : SVGGElement
360+ url : string
361+ }
362+
359363/**
360364 * Paints one frame of the choreography at `t` ms into the cycle by writing
361365 * SVG attributes directly - no React render per frame.
362366 */
363367function paintFrame (
364368 t : number ,
365- blur : SVGFEGaussianBlurElement ,
369+ goo : GooFilterNodes ,
366370 stages : StageNode [ ] ,
367371 anims : AnimatedNode [ ]
368372) : void {
@@ -412,7 +416,12 @@ function paintFrame(
412416 1 - smooth ( T_OUTRO_START , T_OUTRO_END , t )
413417 )
414418 const deviation = round ( GOO_LO + ( GOO_HI - GOO_LO ) * liquid )
415- if ( blur . getAttribute ( 'stdDeviation' ) !== deviation ) blur . setAttribute ( 'stdDeviation' , deviation )
419+ if ( goo . blur . getAttribute ( 'stdDeviation' ) !== deviation ) {
420+ goo . blur . setAttribute ( 'stdDeviation' , deviation )
421+ }
422+ /** Resting vectors retain native antialiasing; only the liquid morph needs raster filtering. */
423+ const filter = liquid > 0 ? goo . url : 'none'
424+ if ( goo . group . getAttribute ( 'filter' ) !== filter ) goo . group . setAttribute ( 'filter' , filter )
416425}
417426
418427interface FooterWordmarkLoopProps {
@@ -454,7 +463,9 @@ export function FooterWordmarkLoop({ className }: FooterWordmarkLoopProps) {
454463 const svg = svgRef . current
455464 if ( ! svg ) return
456465 const blur = svg . querySelector < SVGFEGaussianBlurElement > ( '[data-goo]' )
457- if ( ! blur ) return
466+ const group = svg . querySelector < SVGGElement > ( '[data-goo-group]' )
467+ if ( ! blur || ! group ) return
468+ const goo : GooFilterNodes = { blur, group, url : `url(#${ gooId } )` }
458469
459470 const stages : StageNode [ ] = Array . from (
460471 svg . querySelectorAll < SVGGElement > ( '[data-stage]' ) ,
@@ -475,7 +486,7 @@ export function FooterWordmarkLoop({ className }: FooterWordmarkLoopProps) {
475486 const tick = ( now : number ) => {
476487 if ( previous !== null ) elapsed += Math . min ( now - previous , MAX_FRAME_STEP )
477488 previous = now
478- paintFrame ( elapsed % CYCLE_MS , blur , stages , anims )
489+ paintFrame ( elapsed % CYCLE_MS , goo , stages , anims )
479490 frame = requestAnimationFrame ( tick )
480491 }
481492 const play = ( ) => {
@@ -492,7 +503,7 @@ export function FooterWordmarkLoop({ className }: FooterWordmarkLoopProps) {
492503 if ( reducedMotion ?. matches ) {
493504 pause ( )
494505 elapsed = 0
495- paintFrame ( 0 , blur , stages , anims )
506+ paintFrame ( 0 , goo , stages , anims )
496507 } else {
497508 play ( )
498509 }
@@ -517,7 +528,7 @@ export function FooterWordmarkLoop({ className }: FooterWordmarkLoopProps) {
517528 observer ?. disconnect ( )
518529 reducedMotion ?. removeEventListener ( 'change' , onMotionPreference )
519530 }
520- } , [ ] )
531+ } , [ gooId ] )
521532
522533 return (
523534 < div className = { cn ( 'relative mx-auto aspect-[5/3] w-[clamp(180px,17vw,320px)]' , className ) } >
@@ -545,11 +556,6 @@ export function FooterWordmarkLoop({ className }: FooterWordmarkLoopProps) {
545556 values = '1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 40 -19'
546557 result = 'goo'
547558 />
548- { /* The threshold discards the rasterizer's edge coverage, so at the
549- resting blur the wordmark's edge fell inside a device pixel and
550- stair-stepped at the largest size. A sub-pixel blur after it
551- restores ordinary anti-aliasing without touching the melt. */ }
552- < feGaussianBlur in = 'goo' stdDeviation = { EDGE_SMOOTHING } />
553559 </ filter >
554560 < radialGradient id = { inkId } cx = '0.5' cy = '0.5' r = '0.5' >
555561 < stop style = { INK_STOP_INNER } />
@@ -575,7 +581,8 @@ export function FooterWordmarkLoop({ className }: FooterWordmarkLoopProps) {
575581 </ defs >
576582
577583 < g
578- filter = { `url(#${ gooId } )` }
584+ data-goo-group = ''
585+ filter = 'none'
579586 fill = { `url(#${ inkId } )` }
580587 stroke = { `url(#${ inkId } )` }
581588 strokeWidth = { 0 }
0 commit comments