diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..e9f468a Binary files /dev/null and b/public/logo.png differ diff --git a/src/components/AnimatedBackground.tsx b/src/components/AnimatedBackground.tsx new file mode 100644 index 0000000..cb534a4 --- /dev/null +++ b/src/components/AnimatedBackground.tsx @@ -0,0 +1,145 @@ +'use client'; + +import { Box } from '@mui/material'; +import { useTheme } from '@mui/material/styles'; + +interface AnimatedBackgroundProps { + /** Intensity multiplier (0.5 = subtle, 1 = default, 1.5 = bold) */ + intensity?: number; +} + +export default function AnimatedBackground({ intensity = 1 }: AnimatedBackgroundProps) { + const theme = useTheme(); + const isDark = theme.palette.mode === 'dark'; + const base = isDark ? 0.25 : 0.4; + + return ( + + + + + + + {/* Subtle grid pattern */} + + + {/* Vignette so foreground content reads clearly */} + + + ); +} + +interface OrbProps { + color: string; + size: number; + opacity: number; + delay: number; + duration: number; + x: string[]; + y: string[]; + scale: number[]; +} + +function Orb({ color, size, opacity, delay, duration, x, y, scale }: OrbProps) { + // Build keyframes inline as a CSS custom animation + const animName = `pp-orb-${Math.abs( + delay * 31 + duration * 7 + size + )}`; + + const keyframes = ` + @keyframes ${animName} { + 0% { transform: translate3d(${x[0]}, ${y[0]}, 0) scale(${scale[0]}); } + 50% { transform: translate3d(${x[1]}, ${y[1]}, 0) scale(${scale[1]}); } + 100% { transform: translate3d(${x[2]}, ${y[2]}, 0) scale(${scale[2]}); } + } + `; + + return ( + <> + + + + ); +} diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx new file mode 100644 index 0000000..0113328 --- /dev/null +++ b/src/components/Logo.tsx @@ -0,0 +1,88 @@ +'use client'; + +import Image from 'next/image'; +import { Box } from '@mui/material'; + +interface LogoProps { + /** Total box size in pixels. */ + size?: number; + /** Show the rounded white container backplate (for use over coloured surfaces). */ + withBackplate?: boolean; + /** Padding inside the backplate (if any). */ + padding?: number; + /** Optional border-radius override (defaults to 2 = 8px). */ + rounded?: number; + /** className for parent positioning. */ + className?: string; + /** Click handler. */ + onClick?: () => void; +} + +export default function Logo({ + size = 36, + withBackplate = false, + padding, + rounded, + className, + onClick, +}: LogoProps) { + const inner = ( + PatchPilot Logo + ); + + if (!withBackplate) { + return ( + + {inner} + + ); + } + + return ( + + {inner} + + ); +}