@@ -80,9 +80,9 @@ const useBlurredBg = (imageSrc) => {
8080 canvas . width = 64
8181 canvas . height = 64
8282 const ctx = canvas . getContext ( "2d" )
83- ctx . filter = "blur(4px ) saturate(1.3 ) brightness(0.65 )"
84- ctx . drawImage ( img , - 4 , - 4 , 72 , 72 )
85- const dataUrl = canvas . toDataURL ( "image/jpeg" , 0.7 )
83+ ctx . filter = "blur(6px ) saturate(1.4 ) brightness(0.6 )"
84+ ctx . drawImage ( img , - 6 , - 6 , 76 , 76 )
85+ const dataUrl = canvas . toDataURL ( "image/jpeg" , 0.6 )
8686 setBgUrls ( ( prev ) => ( { current : dataUrl , previous : prev . current , transitioning : true } ) )
8787 if ( timeoutRef . current ) clearTimeout ( timeoutRef . current )
8888 timeoutRef . current = setTimeout ( ( ) => {
@@ -178,7 +178,7 @@ const NowPlayingTab = memo(({ currentSong }) => {
178178 const songImage = useMemo ( ( ) => currentSong ?. image ?. [ 2 ] ?. link , [ currentSong ] )
179179 const colors = useImageColors ( songImage )
180180 const images = useCrossfadeImage ( songImage )
181- const mobileBg = useBlurredBg ( songImage )
181+ const blurredBg = useBlurredBg ( songImage )
182182 const nextSong = useNextSong ( currentSong )
183183 const hasAnimated = useRef ( false )
184184 const [ showEntrance , setShowEntrance ] = useState ( false )
@@ -214,67 +214,66 @@ const NowPlayingTab = memo(({ currentSong }) => {
214214 const imgShadowDesktop = `0 30px 80px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.05), 0 0 80px -20px rgba(${ c1 [ 0 ] } ,${ c1 [ 1 ] } ,${ c1 [ 2 ] } ,0.25)`
215215 const imgShadowMobile = `0 24px 60px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.05), 0 0 60px -15px rgba(${ c1 [ 0 ] } ,${ c1 [ 1 ] } ,${ c1 [ 2 ] } ,0.25)`
216216
217- const orbColor = ( c , a ) => ( {
218- background : `rgba(${ c [ 0 ] } ,${ c [ 1 ] } ,${ c [ 2 ] } ,${ a } )` ,
219- transition : "background 2s ease-out" ,
220- } )
217+ const orbStyle = useMemo ( ( ) => ( {
218+ o1 : { background : `rgba(${ c1 [ 0 ] } ,${ c1 [ 1 ] } ,${ c1 [ 2 ] } ,0.18)` , transition : "background 2s ease-out" } ,
219+ o2 : { background : `rgba(${ c2 [ 0 ] } ,${ c2 [ 1 ] } ,${ c2 [ 2 ] } ,0.14)` , transition : "background 2s ease-out" } ,
220+ } ) , [ c1 , c2 ] )
221+
222+ const overlayStyle = useMemo ( ( ) => ( {
223+ background : [
224+ "radial-gradient(ellipse 70% 50% at 25% 20%, rgba(255,255,255,0.08) 0%, transparent 50%)" ,
225+ "radial-gradient(ellipse 50% 35% at 75% 75%, rgba(255,255,255,0.04) 0%, transparent 40%)" ,
226+ "radial-gradient(ellipse 120% 80% at 50% 40%, rgba(255,255,255,0.03) 0%, transparent 50%)" ,
227+ "radial-gradient(ellipse at 50% 45%, transparent 30%, rgba(5,5,8,0.3) 60%, rgba(5,5,8,0.85) 100%)" ,
228+ ] . join ( ", " ) ,
229+ } ) , [ ] )
230+
231+ const mobileVignette = useMemo ( ( ) => ( {
232+ background : "radial-gradient(ellipse at 50% 45%, transparent 30%, rgba(5,5,8,0.3) 60%, rgba(5,5,8,0.85) 100%)" ,
233+ } ) , [ ] )
221234
222235 return (
223236 < div className = "w-full h-full relative overflow-hidden bg-[#050508]" >
224237
225- { /* === MOBILE BG: Pre-blurred canvas, no CSS filter === */ }
226- { mobileBg . previous && (
238+ { /* === MOBILE BG: Pre-blurred canvas, zero CSS filter cost === */ }
239+ { blurredBg . previous && (
227240 < div
228241 className = "lg:hidden absolute inset-0 bg-cover bg-center np-bg-fade-out"
229- style = { { backgroundImage : `url(${ mobileBg . previous } )` } }
242+ style = { { backgroundImage : `url(${ blurredBg . previous } )` } }
230243 />
231244 ) }
232- { mobileBg . current && (
245+ { blurredBg . current && (
233246 < div
234- className = { `lg:hidden absolute inset-0 bg-cover bg-center ${ mobileBg . transitioning ? "np-bg-fade-in" : "" } ` }
235- style = { { backgroundImage : `url(${ mobileBg . current } )` } }
247+ className = { `lg:hidden absolute inset-0 bg-cover bg-center ${ blurredBg . transitioning ? "np-bg-fade-in" : "" } ` }
248+ style = { { backgroundImage : `url(${ blurredBg . current } )` } }
236249 />
237250 ) }
238251
239- { /* === DESKTOP BG: Full liquid glass with CSS blur === */ }
252+ { /* === DESKTOP BG: CSS blur for high quality === */ }
240253 { images . previous && (
241254 < div
242255 className = "hidden lg:block absolute inset-0 bg-cover bg-center np-bg-fade-out"
243- style = { { backgroundImage : `url(${ images . previous } )` , filter : "blur(160px) saturate(1.4) brightness(0.65)" , transform : "scale(2)" } }
256+ style = { { backgroundImage : `url(${ images . previous } )` , filter : "blur(160px) saturate(1.4) brightness(0.65)" , transform : "scale(2) translateZ(0)" , willChange : "transform " } }
244257 />
245258 ) }
246259 < div
247260 className = { `hidden lg:block absolute inset-0 bg-cover bg-center ${ images . transitioning ? "np-bg-fade-in" : "" } ` }
248- style = { { backgroundImage : `url(${ images . current } )` , filter : "blur(160px) saturate(1.4) brightness(0.65)" , transform : "scale(2)" , transition : "background-image 0.6s ease " } }
261+ style = { { backgroundImage : `url(${ images . current } )` , filter : "blur(160px) saturate(1.4) brightness(0.65)" , transform : "scale(2) translateZ(0) " , willChange : "transform " } }
249262 />
250263
251- { /* Desktop-only : glass noise */ }
264+ { /* Desktop: glass effects */ }
252265 < div className = "hidden lg:block absolute inset-0 np-glass-noise" />
253-
254- { /* Desktop-only: specular highlights */ }
255- < div className = "hidden lg:block absolute inset-0" style = { {
256- background : "radial-gradient(ellipse 70% 50% at 25% 20%, rgba(255,255,255,0.08) 0%, transparent 50%)"
257- } } />
258- < div className = "hidden lg:block absolute inset-0" style = { {
259- background : "radial-gradient(ellipse 50% 35% at 75% 75%, rgba(255,255,255,0.04) 0%, transparent 40%)"
260- } } />
261-
262- { /* Desktop-only: animated liquid shimmer */ }
263266 < div className = "hidden lg:block absolute inset-0 np-orb-layer" >
264- < div className = "np-orb np-o1" style = { orbColor ( c1 , 0.18 ) } />
265- < div className = "np-orb np-o2" style = { orbColor ( c2 , 0.14 ) } />
267+ < div className = "np-orb np-o1" style = { orbStyle . o1 } />
268+ < div className = "np-orb np-o2" style = { orbStyle . o2 } />
266269 < div className = "np-shimmer" />
267270 </ div >
268271
269- { /* Desktop-only: luminous depth */ }
270- < div className = "hidden lg:block absolute inset-0" style = { {
271- background : "radial-gradient(ellipse 120% 80% at 50% 40%, rgba(255,255,255,0.03) 0%, transparent 50%)"
272- } } />
272+ { /* Desktop: specular + luminous + vignette merged into one div */ }
273+ < div className = "hidden lg:block absolute inset-0" style = { overlayStyle } />
273274
274- { /* Shared: vignette (single gradient, very light on GPU) */ }
275- < div className = "absolute inset-0" style = { {
276- background : "radial-gradient(ellipse at 50% 45%, transparent 30%, rgba(5,5,8,0.3) 60%, rgba(5,5,8,0.85) 100%)"
277- } } />
275+ { /* Mobile: vignette only */ }
276+ < div className = "lg:hidden absolute inset-0" style = { mobileVignette } />
278277
279278 { /* Desktop layout */ }
280279 < div className = "hidden lg:flex relative z-10 h-full w-full max-w-[1100px] mx-auto items-center gap-14 xl:gap-20 px-10 xl:px-16" >
@@ -393,53 +392,53 @@ const NowPlayingTab = memo(({ currentSong }) => {
393392 mix-blend-mode: overlay;
394393 }
395394 .np-orb-layer {
396- filter: blur(100px );
397- transform: scale(1.4 );
395+ filter: blur(80px );
396+ transform: scale(1.3 );
398397 mix-blend-mode: soft-light;
399- opacity: 0.7 ;
398+ opacity: 0.6 ;
400399 }
401400 .np-orb {
402401 position: absolute;
403402 border-radius: 50%;
404403 }
405404 .np-o1 {
406- width: 55 %;
407- height: 60 %;
408- top: -10 %;
409- left: -10 %;
405+ width: 50 %;
406+ height: 55 %;
407+ top: -8 %;
408+ left: -8 %;
410409 animation: npo1 26s ease-in-out infinite;
411410 }
412411 .np-o2 {
413- width: 50 %;
414- height: 50 %;
415- bottom: -10 %;
416- right: -10 %;
412+ width: 45 %;
413+ height: 45 %;
414+ bottom: -8 %;
415+ right: -8 %;
417416 animation: npo2 32s ease-in-out infinite;
418417 }
419418 .np-shimmer {
420419 position: absolute;
421- width: 40 %;
422- height: 30 %;
420+ width: 35 %;
421+ height: 25 %;
423422 top: 15%;
424423 left: 20%;
425424 border-radius: 50%;
426- background: radial-gradient(ellipse, rgba(255,255,255,0.06 ) 0%, transparent 70%);
427- animation: npShimmer 18s ease-in-out infinite;
425+ background: radial-gradient(ellipse, rgba(255,255,255,0.05 ) 0%, transparent 70%);
426+ animation: npShimmer 20s ease-in-out infinite;
428427 }
429428 @keyframes npo1 {
430429 0%, 100% { transform: translate(0, 0) scale(1); border-radius: 50%; }
431- 33% { transform: translate(10 %, 15 %) scale(1.05 ); border-radius: 44% 56% 52% 48%; }
432- 66% { transform: translate(5 %, 8 %) scale(0.97); border-radius: 48% 52% 46% 54%; }
430+ 33% { transform: translate(8 %, 12 %) scale(1.04 ); border-radius: 44% 56% 52% 48%; }
431+ 66% { transform: translate(4 %, 6 %) scale(0.97); border-radius: 48% 52% 46% 54%; }
433432 }
434433 @keyframes npo2 {
435434 0%, 100% { transform: translate(0, 0) scale(1); border-radius: 50%; }
436- 33% { transform: translate(-8 %, -12 %) scale(1.04 ); border-radius: 54% 46% 48% 52%; }
437- 66% { transform: translate(-14 %, -5 %) scale(0.96 ); border-radius: 47% 53% 52% 48%; }
435+ 33% { transform: translate(-6 %, -10 %) scale(1.03 ); border-radius: 54% 46% 48% 52%; }
436+ 66% { transform: translate(-12 %, -4 %) scale(0.97 ); border-radius: 47% 53% 52% 48%; }
438437 }
439438 @keyframes npShimmer {
440- 0%, 100% { transform: translate(0, 0); opacity: 0.6 ; }
441- 33% { transform: translate(30 %, 10 %); opacity: 1 ; }
442- 66% { transform: translate(-10 %, 20 %); opacity: 0.4 ; }
439+ 0%, 100% { transform: translate(0, 0); opacity: 0.5 ; }
440+ 33% { transform: translate(25 %, 8 %); opacity: 0.8 ; }
441+ 66% { transform: translate(-8 %, 15 %); opacity: 0.3 ; }
443442 }
444443 .np-bg-fade-in {
445444 animation: npBgIn 0.8s ease-out both;
0 commit comments