diff --git a/public/JUST-GREY.png b/public/JUST-GREY.png new file mode 100644 index 0000000..f295043 Binary files /dev/null and b/public/JUST-GREY.png differ diff --git a/public/JUST-YELLOW.png b/public/JUST-YELLOW.png new file mode 100644 index 0000000..281c907 Binary files /dev/null and b/public/JUST-YELLOW.png differ diff --git a/public/duck.png b/public/duck.png new file mode 100644 index 0000000..e72ef29 Binary files /dev/null and b/public/duck.png differ diff --git a/public/fish.png b/public/fish.png new file mode 100644 index 0000000..32724b1 Binary files /dev/null and b/public/fish.png differ diff --git a/public/illusion-lab.html b/public/illusion-lab.html new file mode 100644 index 0000000..a53ee6c --- /dev/null +++ b/public/illusion-lab.html @@ -0,0 +1,1503 @@ + + + + + + + Bird Illusion Lab — Static Motion Prototyping + + + + + + +
+
+ ILLUSION + LAB + +
+ + +
Bird A — Yellow
+
+ +
No image loaded.
+
+ + +
Bird B — Grey
+
+ +
No image loaded.
+
+ + +
Pair Alignment
+
+ Adjust alignment offsets (pre-tuned) +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
No composite yet.
+ + +
Tessellation
+
+ Grid parameters +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
Peripheral Drift
+
+ +
+
+ + +
+
Bird A (yellow) → rightward | Bird B (grey) → leftward
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
Enable processing and load both birds.
+ + +
Counter-Motion Boost
+
+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 8419512..91a42c0 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -6,6 +6,8 @@ body { font-family: var(--font-base), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + overflow-x: hidden; + width: 100%; } code, @@ -47,9 +49,11 @@ samp { } #typing { - font-size: 1.8rem; - font-weight: 500; - /* Removed modern styles like letter-spacing, min-height, etc. */ + font-size: 2.5rem; + font-weight: 600; + position: relative; + z-index: 20; + color: white; } #email { @@ -58,14 +62,15 @@ samp { font-size: 1.3rem; font-weight: 100; opacity: 0; - color: black; /* Legacy assumed black text on white, ensuring visibility */ } #caption { font-size: 2.5rem; font-weight: 500; opacity: 0; - color: black; + position: relative; + z-index: 20; + color: white; } .fadeInAnimation { @@ -93,13 +98,13 @@ samp { } .cursor { - border-right: 3px solid black; + border-right: 3px solid white; animation: blink 1s step-end infinite; } @keyframes blink { from, to { border-color: transparent; } - 50% { border-color: black; } + 50% { border-color: white; } } /* Media queries for responsive adjustments - EXACTLY matching legacy */ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e595fd5..5eb227c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,10 +1,8 @@ import type { Metadata, Viewport } from "next"; -import Link from "next/link"; import "./globals.css"; -import Image from "next/image"; import { IBM_Plex_Mono, Inconsolata } from "next/font/google"; import ScrollToTop from "@/components/ScrollToTop"; -import EscherBackground from "@/components/EscherBackground"; +import NavBar from "@/components/NavBar"; const plexMono = IBM_Plex_Mono({ subsets: ["latin"], @@ -50,27 +48,10 @@ export default function RootLayout({ }>) { return ( - - -
-
- - Nucleus AI Logo - Nucleus AI - {(process.env.NODE_ENV === "development" || process.env.NEXT_PUBLIC_ENV === "dev") && ( - - DEV - - )} - -
- -
-
{children}
-
contact@withnucleus.ai
+ + +
{children}
+
contact@withnucleus.ai
diff --git a/src/app/page.tsx b/src/app/page.tsx index 508705d..5e14792 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,6 +3,8 @@ import ScrollDownButton from "@/components/ScrollDownButton"; import BlogSection from "@/components/BlogSection"; import { getPosts } from "@/lib/posts"; +import EscherBirdsBackground from "@/components/EscherBirdsBackground"; + export default async function Home() { const posts = await getPosts(); const recentPosts = posts.slice(0, 3); @@ -10,6 +12,7 @@ export default async function Home() { return (
+
diff --git a/src/components/EscherBirdsBackground.tsx b/src/components/EscherBirdsBackground.tsx new file mode 100644 index 0000000..781ff1b --- /dev/null +++ b/src/components/EscherBirdsBackground.tsx @@ -0,0 +1,51 @@ +"use client"; +import { useEffect, useState } from "react"; + +export default function EscherBirdsBackground() { + const [opacity, setOpacity] = useState(1); + + useEffect(() => { + let rafId: number; + + const handleScroll = () => { + // Fade out over the first 80% of the viewport + const fadePoint = window.innerHeight * 0.8; + // Use a slightly eased curve for smoother visual disappearance + const scrollY = window.scrollY; + const rawOpacity = 1 - (scrollY / fadePoint); + const newOpacity = Math.max(0, Math.min(1, rawOpacity)); + + setOpacity(newOpacity); + }; + + const onScroll = () => { + cancelAnimationFrame(rafId); + rafId = requestAnimationFrame(handleScroll); + }; + + // Initial check + handleScroll(); + + window.addEventListener('scroll', onScroll, { passive: true }); + return () => { + window.removeEventListener('scroll', onScroll); + cancelAnimationFrame(rafId); + }; + }, []); + + return ( +
0.05 ? 'auto' : 'none' + }} + > +