/**

GlowingBlob.tsx — Apple-style organic blob controlled via external slider */ import React, { useEffect } from 'react'; import { View, StyleSheet } from 'react-native'; import { Canvas, Path, Group, vec, RadialGradient, BlurMask, Image, Skia } from '@shopify/react-native-skia'; import Animated, { useSharedValue, withTiming, withRepeat, useDerivedValue } from 'react-native-reanimated'; import { Spacing, getClarityGradient } from '@/constants/Colors'; import { CognitionLevel } from '@/types'; // ---------- constants ---------- const SPEED: Record<CognitionLevel, number> = { 1: 8000, 2: 7000, 3: 6000, 4: 5000, 5: 4500, };

// ---------- alpha helper ---------- const addAlpha = (hex: string, alpha: number) => { const a = Math.round(alpha * 255) .toString(16) .padStart(2, '0') .toUpperCase(); return #
a
a{hex.replace('#', '')}; };

// ---------- noise bitmap (cached once) ---------- const createNoiseBitmap = () => { const surface = Skia.Surface.MakeOffscreen(512, 512); if (!surface) { console.warn('Skia offscreen surface failed; using transparent fallback'); return null; } const canvas = surface.getCanvas(); const paint = Skia.Paint(); paint.setAntiAlias(true); for (let x = 0; x < 512; x += 4) { for (let y = 0; y < 512; y += 4) { paint.setColor(Skia.Color(rgba(255,255,255,${Math.random() * 0.3 + 0.1}))); canvas.drawRect(Skia.XYWHRect(x, y, 4, 4), paint); } } return surface.makeImageSnapshot(); }; const noiseImage = createNoiseBitmap();

// ---------- organic blob path ---------- const makeBlobPath = (R: number, t: number, clarity: CognitionLevel) => { 'worklet'; const pts = 48; const ampl = Math.min(0.08, Math.max(0.05, 0.18 - clarity * 0.02)); const p: [number, number][] = []; for (let i = 0; i < pts; ++i) { const a = (i / pts) * Math.PI * 2; const n = Math.sin(a * 3 + t * 2) * 0.6 + Math.sin(a * 7 + t) * 0.4; const r = R * (1 + ampl * n); p.push([Math.cos(a) * r, Math.sin(a) * r]); } const path = Skia.Path.Make(); for (let i = 0; i < pts; ++i) { const p0 = p[(i - 1 + pts) % pts], p1 = p[i], p2 = p[(i + 1) % pts], p3 = p[(i + 2) % pts]; if (i === 0) path.moveTo(...p1); path.cubicTo( p1[0] + (p2[0] - p0[0]) / 6, p1[1] + (p2[1] - p0[1]) / 6, p2[0] - (p3[0] - p1[0]) / 6, p2[1] - (p3[1] - p1[1]) / 6, ...p2 ); } path.close(); return path; };

// ---------- component ---------- export default function GlowingBlob({ clarity = 3, size = 300, }: { clarity?: CognitionLevel; size?: number; }) { const level = clarity;

const prog = useSharedValue(0); useEffect(() => { prog.value = withRepeat(withTiming(1, { duration: SPEED[level] }), -1, false); }, [level, prog]);

// geometry const σ = 50; const pad = σ * 3; const canvasDim = size + pad * 2; const R = size * 0.35;

// transforms const baseScale = 0.9 + level * 0.03; const transform = useDerivedValue(() => { const breath = 0.04 * Math.sin(prog.value * 2 * Math.PI); return [ { translateX: canvasDim / 2 }, { translateY: canvasDim / 2 }, { scale: baseScale + breath }, ]; });

// dynamic colors const [light, mid, deep = mid] = getClarityGradient(level); const rimTint = addAlpha(light, 0); const bloomTint = addAlpha(mid, 0.8);

// blob path const blobPath = useDerivedValue( () => makeBlobPath(R, prog.value * 2 * Math.PI, level), [prog, level] );

return ( <View style={[ styles.container, { width: size, height: size, overflow: 'hidden' }, ]} > <Canvas style={{ width: canvasDim, height: canvasDim, margin: -pad }}> {/* bloom /} <Group origin={vec(canvasDim / 2, canvasDim / 2)} transform={transform}> <Group blendMode="screen"> <Path path={blobPath}> <RadialGradient c={vec(0, 0)} r={R} colors={[bloomTint, rimTint]} /> <BlurMask blur={σ} style="outer" /> </Path> </Group> {/ core /} <Path path={blobPath}> <RadialGradient c={vec(0, 0)} r={R} colors={[deep, mid, light]} positions={[0, 0.6, 1]} /> </Path> {/ rim highlight /} <Path path={blobPath} style="stroke" strokeWidth={1.2} color="rgba(255,255,255,0.18)" > <BlurMask blur={6} style="solid" /> </Path> </Group> {/ noise overlay */} {noiseImage && ( <Image image={noiseImage} x={0} y={0} width={canvasDim} height={canvasDim} blendMode="softLight" opacity={0.05} /> )} </Canvas> </View> ); }

const styles = StyleSheet.create({ container: { alignItems: 'center', justifyContent: 'center', marginVertical: Spacing.lg, backgroundColor: 'white', // clip all overflow, so no grey background bleeds in // (added in line above) },

}); you removed grey but you have introduced another problem of clipping where now i see a gray square. i dont want anything gray , do you understand? the issue is very simple its because you are trying to render shadows, i think problem is from shadow, somehow shadow introduce this