Skip to content

Commit 0a4a711

Browse files
committed
v0.67
feat: Enhance UI components and audio controls - Updated MuteButton to persist mute state using localStorage and improved audio handling. - Refactored ScrollDownButton to scroll to different sections based on scroll position. - Enhanced ScrollToTop button with new styling and functionality. - Improved ThemeToggle button with updated styles and visibility handling. - Refined TopNav for better visibility control and added memoization for performance. - Updated Typewriter component with new phrases and styling adjustments. - Added About page with information on Nucleus AI. - Introduced Footer component with contact links and social media icons. - Created audio utility functions for fading in and out background music. - Added HuggingFace SVG logo and background music file.
1 parent d693975 commit 0a4a711

20 files changed

Lines changed: 761 additions & 168 deletions

public/huggingface.svg

Lines changed: 1 addition & 0 deletions
Loading

public/music.mp3

-13.7 MB
Binary file not shown.

public/music.wav

9 MB
Binary file not shown.

src/app/about/page.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
export default function About() {
2+
return (
3+
<main className="w-full">
4+
<section className="min-h-screen flex flex-col justify-center items-center px-6 sm:px-12 max-w-4xl mx-auto py-24 text-center z-10 relative">
5+
<h1 className="text-4xl sm:text-6xl lg:text-7xl leading-[1.2] sm:leading-[1.3] font-medium text-gray-900 dark:text-gray-100 tracking-tight mb-8">
6+
About Nucleus AI
7+
</h1>
8+
9+
<div className="space-y-6 text-lg sm:text-xl text-gray-700 dark:text-gray-300 leading-relaxed">
10+
<p>
11+
Nucleus AI is dedicated to advancing the field of artificial intelligence through innovative research
12+
and development. We focus on building the next generation of general intelligence systems that can
13+
understand, learn, and adapt to complex real-world challenges.
14+
</p>
15+
16+
<p>
17+
Our team combines expertise in machine learning, software engineering, and systems architecture
18+
to create robust, scalable AI solutions. We believe in open collaboration and sharing knowledge
19+
to accelerate progress in the AI community.
20+
</p>
21+
22+
<p>
23+
Through our work, we aim to push the boundaries of what's possible with artificial intelligence,
24+
developing technologies that are not only powerful but also responsible, ethical, and beneficial
25+
to humanity.
26+
</p>
27+
</div>
28+
29+
<div className="mt-12 grid grid-cols-1 md:grid-cols-3 gap-8 text-center">
30+
<div>
31+
<h3 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-2">Research</h3>
32+
<p className="text-gray-600 dark:text-gray-400">
33+
Cutting-edge AI research focused on general intelligence and autonomous systems.
34+
</p>
35+
</div>
36+
37+
<div>
38+
<h3 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-2">Development</h3>
39+
<p className="text-gray-600 dark:text-gray-400">
40+
Building scalable, production-ready AI systems and applications.
41+
</p>
42+
</div>
43+
44+
<div>
45+
<h3 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-2">Collaboration</h3>
46+
<p className="text-gray-600 dark:text-gray-400">
47+
Working with the global AI community to advance the field together.
48+
</p>
49+
</div>
50+
</div>
51+
</section>
52+
</main>
53+
);
54+
}

src/app/blog/[slug]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export default async function BlogPost({ params }: { params: Promise<{ slug: str
6363
}
6464

6565
return (
66-
<div className="max-w-[1200px] mx-auto py-10 px-4 sm:py-16 sm:px-8 text-left w-full box-border">
66+
<div className="max-w-[1200px] mx-auto py-10 px-4 sm:py-16 sm:px-8 text-left w-full box-border select-text">
6767
<Link href="/blog" className="inline-flex items-center mb-6 sm:mb-8 no-underline text-[#666] dark:text-gray-400 text-[0.8rem] sm:text-[0.85rem] font-medium transition-colors duration-200 hover:text-black dark:hover:text-white">
6868
← Back to Blogs
6969
</Link>

src/app/blog/page.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ export default async function BlogPage() {
99
const posts = await getPosts();
1010

1111
return (
12-
<div className="max-w-5xl mx-auto py-10 px-4 sm:py-16 sm:px-6 text-left w-full box-border text-gray-900 dark:text-gray-100">
12+
<div className="max-w-5xl mx-auto py-10 px-4 sm:py-16 sm:px-6 text-left w-full box-border text-gray-900 dark:text-gray-100 select-text">
1313
<h1 className="text-3xl sm:text-5xl mb-8 sm:mb-12 pb-4 sm:pb-6 border-b border-[#eee] dark:border-gray-800 tracking-tight">Blogs</h1>
1414
<div className="posts-list">
1515
{posts.map((post) => (
1616
<div key={post.slug} className="mb-10 sm:mb-12 pb-10 sm:pb-12 border-b border-[#f0f0f0] dark:border-gray-800">
17-
<Link href={`/blog/${post.slug}`} className="no-underline text-inherit block mb-2 group">
18-
<h2 className="text-[1.4rem] sm:text-[1.8rem] font-semibold tracking-tight m-0 transition-colors duration-200 group-hover:text-[#444] dark:group-hover:text-gray-300">{post.title}</h2>
19-
</Link>
20-
<p className="text-[#888] dark:text-gray-500 text-xs sm:text-sm mb-4 block">{post.date}</p>
21-
<p className="leading-relaxed text-[#444] dark:text-gray-400 mb-6 text-[0.98rem] sm:text-[1.05rem]">{post.excerpt}</p>
22-
<Link href={`/blog/${post.slug}`} className="no-underline font-semibold text-black dark:text-white border-b border-black dark:border-white pb-0.5 transition-opacity duration-200 hover:opacity-70">
23-
Read more →
17+
<Link href={`/blog/${post.slug}`} className="group no-underline text-inherit block hover:no-underline">
18+
<h2 className="text-[1.4rem] sm:text-[1.8rem] font-semibold tracking-tight m-0 mb-2 transition-colors duration-200 text-gray-900 dark:text-gray-100 group-hover:text-blue-600 dark:group-hover:text-blue-400">{post.title}</h2>
19+
<p className="text-[#888] dark:text-gray-500 text-xs sm:text-sm mb-4 block">{post.date}</p>
20+
<p className="leading-relaxed text-[#444] dark:text-gray-400 mb-6 text-[0.98rem] sm:text-[1.05rem]">{post.excerpt}</p>
21+
<span className="inline-block font-semibold text-black dark:text-white border-b border-black dark:border-white pb-0.5 transition-colors duration-200 group-hover:text-blue-600 dark:group-hover:text-blue-400 group-hover:border-blue-600 dark:group-hover:border-blue-400">
22+
Read more →
23+
</span>
2424
</Link>
2525
</div>
2626
))}

src/app/globals.css

Lines changed: 209 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
body {
99
font-family: var(--font-base), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
10+
/* Disable text selection */
11+
-webkit-user-select: none;
12+
-moz-user-select: none;
13+
-ms-user-select: none;
14+
user-select: none;
1015
}
1116

1217
code,
@@ -16,6 +21,203 @@ samp {
1621
font-family: var(--font-code), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
1722
}
1823

24+
25+
26+
.btn {
27+
position: relative;
28+
display: inline-block;
29+
overflow: hidden;
30+
cursor: pointer;
31+
background: rgba(255, 255, 255, 0.9);
32+
backdrop-filter: blur(20px);
33+
border: 2px solid rgba(255, 255, 255, 0.5);
34+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
35+
transition: all 0.2s ease;
36+
/* Disable text selection */
37+
-webkit-user-select: none;
38+
user-select: none;
39+
}
40+
41+
.dark .btn {
42+
background: rgba(0, 0, 0, 0.9);
43+
border: 2px solid rgba(255, 255, 255, 0.3);
44+
box-shadow: 0 4px 20px rgba(255, 255, 255, 0.05);
45+
}
46+
47+
.btn:hover {
48+
transform: scale(1.05);
49+
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
50+
}
51+
52+
.dark .btn:hover {
53+
box-shadow: 0 8px 30px rgba(255, 255, 255, 0.1);
54+
}
55+
56+
/* Text/Icon Label inside the button */
57+
.btn__content {
58+
position: relative;
59+
z-index: 3;
60+
width: 100%;
61+
height: 100%;
62+
display: flex;
63+
align-items: center;
64+
justify-content: center;
65+
color: #111; /* Dark initially for light mode */
66+
transition: color 0.3s ease-in-out;
67+
/* font-weight: bold; */
68+
letter-spacing: 0.05em;
69+
}
70+
71+
.dark .btn__content {
72+
color: #fff; /* White for dark mode */
73+
}
74+
75+
/* The Hover Interaction - Changes Text Color */
76+
.btn:hover .btn__content {
77+
color: #fff; /* White on hover for light mode */
78+
}
79+
80+
.dark .btn:hover .btn__content {
81+
color: #000; /* Black on hover for dark mode */
82+
}
83+
84+
/* * THE FILL CIRCLE (The background that scales up)
85+
*/
86+
.btn__fill-layer {
87+
position: absolute;
88+
top: 0;
89+
left: 0;
90+
width: 100%;
91+
height: 100%;
92+
pointer-events: none;
93+
}
94+
95+
.btn__fill-circle {
96+
transform-origin: 50% 50%;
97+
transform: scale(0); /* Start hidden/tiny */
98+
transition: transform 0.3s ease-in-out;
99+
fill: #111; /* Dark fill for light mode */
100+
}
101+
102+
.dark .btn__fill-circle {
103+
fill: #fff; /* White fill for dark mode */
104+
}
105+
106+
/* Scale up on hover */
107+
.btn:hover .btn__fill-circle {
108+
transform: scale(1); /* Scale to fit within container */
109+
}
110+
111+
/* * THE BORDER SVG (The lines that draw themselves)
112+
*/
113+
.btn__border-layer {
114+
position: absolute;
115+
top: 0;
116+
left: 0;
117+
width: 100%;
118+
height: 100%;
119+
pointer-events: none;
120+
}
121+
122+
.btn__border-path {
123+
fill: none;
124+
stroke: #111; /* Dark stroke for light mode */
125+
stroke-width: 1; /* Slight thickness */
126+
stroke-linecap: round;
127+
transition: stroke-dashoffset 0.3s ease-in-out;
128+
}
129+
130+
.dark .btn__border-path {
131+
stroke: #fff; /* White stroke for dark mode */
132+
}
133+
134+
/* -----------------------------------------------------------
135+
SPECIFIC: CIRCULAR BUTTON
136+
----------------------------------------------------------- */
137+
.btn--circle {
138+
width: 2.5rem;
139+
height: 2.5rem;
140+
border-radius: 50%;
141+
}
142+
143+
@media (min-width: 768px) {
144+
.btn--circle {
145+
width: 3rem;
146+
height: 3rem;
147+
}
148+
}
149+
150+
/* Circumference Calculation for radius 29 (60px viewbox - 1px stroke padding):
151+
C = 2 * pi * 29 ≈ 182.2
152+
Half Circle ≈ 91.1
153+
*/
154+
.btn--circle .btn__border-path {
155+
stroke-dasharray: 91.1 91.1;
156+
}
157+
158+
/* Initial State: Lines pushed away */
159+
.btn--circle .btn__border-path--left {
160+
stroke-dashoffset: -91.1;
161+
}
162+
.btn--circle .btn__border-path--right {
163+
stroke-dashoffset: 91.1;
164+
}
165+
166+
/* Hover State: Draw lines to 0 (center) */
167+
.btn--circle:hover .btn__border-path--left,
168+
.btn--circle:hover .btn__border-path--right {
169+
stroke-dashoffset: 0;
170+
}
171+
/* -----------------------------------------------------------
172+
SPECIFIC: ORIGINAL PILL BUTTON (For Comparison)
173+
----------------------------------------------------------- */
174+
.btn--pill {
175+
width: 10vw;
176+
height: 5vw;
177+
border-radius: 1.5vw;
178+
}
179+
180+
.btn--pill .btn__border-path {
181+
stroke-dasharray: 62 62; /* From original code */
182+
}
183+
184+
.btn--pill .btn__border-path--left {
185+
stroke-dashoffset: -62;
186+
}
187+
.btn--pill .btn__border-path--right {
188+
stroke-dashoffset: 62;
189+
}
190+
191+
.btn--pill:hover .btn__border-path--left,
192+
.btn--pill:hover .btn__border-path--right {
193+
stroke-dashoffset: 0;
194+
}
195+
/* -----------------------------------------------------------
196+
SPECIFIC: PLAYGROUND BUTTON (190px x 50px)
197+
----------------------------------------------------------- */
198+
.btn--playground {
199+
width: 190px;
200+
height: 50px;
201+
border-radius: 25px;
202+
}
203+
204+
.btn--playground .btn__border-path {
205+
stroke-dasharray: 216 216;
206+
}
207+
208+
.btn--playground .btn__border-path--left {
209+
stroke-dashoffset: -216;
210+
}
211+
212+
.btn--playground .btn__border-path--right {
213+
stroke-dashoffset: 216;
214+
}
215+
216+
.btn--playground:hover .btn__border-path--left,
217+
.btn--playground:hover .btn__border-path--right {
218+
stroke-dashoffset: 0;
219+
}
220+
19221
/* KaTeX responsive equations */
20222
.katex-display {
21223
max-width: 100%;
@@ -233,19 +435,22 @@ html::-webkit-scrollbar, body::-webkit-scrollbar {
233435
/* Text overlay - slides in from right, covering over the dashes, vertically centered */
234436
.toc-text-overlay {
235437
position: absolute;
236-
top: 50%;
438+
top: 0;
237439
right: 0;
238440
width: 280px;
239-
z-index: 30;
441+
height: 100%;
442+
z-index: 60;
240443
pointer-events: none;
241444
opacity: 0;
242-
transform: translate(100%, -50%);
445+
transform: translateX(100%);
243446
transition: all 0.5s cubic-bezier(0.22, 1, 0.36, 1);
447+
display: flex;
448+
align-items: center;
244449
}
245450

246451
.toc-text-overlay.visible {
247452
opacity: 1;
248-
transform: translate(0, -50%);
453+
transform: translateX(0);
249454
pointer-events: auto;
250455
}
251456

src/app/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ThemeProvider } from "@/components/ThemeProvider";
66
import ThemeToggle from "@/components/ThemeToggle";
77
import MuteButton from "@/components/MuteButton";
88
import TopNav from "@/components/TopNav";
9+
import Footer from "@/components/Footer";
910

1011
const plexMono = IBM_Plex_Mono({
1112
subsets: ["latin"],
@@ -64,10 +65,10 @@ export default function RootLayout({
6465
enableSystem
6566
disableTransitionOnChange
6667
>
67-
<audio id="bg-music" loop src="/music.mp3" />
68+
<audio id="bg-music" loop preload="none" src="/music.wav" />
6869
<TopNav />
6970
<main className="flex-1 flex flex-col w-full sm:pt-28">{children}</main>
70-
<div id="email" className="fixed bottom-7.5 text-base text-[#666] dark:text-gray-400 font-normal opacity-0 tracking-widest pointer-events-none">contact@withnucleus.ai</div>
71+
<Footer />
7172
<ScrollToTop />
7273
<ThemeToggle />
7374
<MuteButton />

src/app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ export default async function Home() {
2020
<ScrollDownButton />
2121
</section>
2222

23-
<section className="min-h-[60vh] flex flex-col justify-center items-center px-6 sm:px-12 max-w-5xl mx-auto py-24 text-center z-10 relative">
23+
<section id="intro-section" className="h-svh flex flex-col justify-center items-center px-6 sm:px-12 max-w-5xl mx-auto py-24 text-center z-10 relative">
2424
<h2 className="text-3xl sm:text-5xl lg:text-6xl leading-[1.3] sm:leading-[1.4] font-medium text-gray-900 dark:text-gray-100 tracking-tight">
25-
We design systems that shape tomorrow. Exploring the frontiers of software, artificial intelligence, and resilient architectures to build the foundations of modern engineering.
25+
We design systems that shape tomorrow. Exploring the frontiers of software, artificial intelligence, and <span className="whitespace-nowrap">resilient architectures</span> to build the foundations of modern engineering.
2626
</h2>
2727
</section>
2828

src/components/BlogSection.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import MiniBlogCard from "@/components/MiniBlogCard";
55
import { Post } from "@/lib/posts";
66
import Link from "next/link";
77
import { ArrowRight } from "lucide-react";
8+
import { fadeOutAudio } from "@/lib/audio";
89

910
interface BlogSectionProps {
1011
posts: Post[];
@@ -31,7 +32,7 @@ export default function BlogSection({ posts }: BlogSectionProps) {
3132
{/* Ultra-Minimalist Blog Grid */}
3233
{/* Vertical Blog Gallery */}
3334
<div className="flex flex-col gap-8 sm:gap-16 max-w-5xl mx-auto">
34-
{posts.map((post, index) => {
35+
{posts.map((post) => {
3536
return (
3637
<div key={post.slug} className="w-full border-b border-gray-100 dark:border-gray-800 pb-8 sm:pb-16 last:border-0 last:pb-0">
3738
<MiniBlogCard
@@ -48,6 +49,7 @@ export default function BlogSection({ posts }: BlogSectionProps) {
4849
<div className="mt-8 flex justify-end">
4950
<Link
5051
href="/blog"
52+
onClick={fadeOutAudio}
5153
className="group inline-flex items-center gap-2 text-sm font-medium text-gray-600 dark:text-gray-400 hover:text-black dark:hover:text-white transition-colors"
5254
>
5355
View All Blogs

0 commit comments

Comments
 (0)