Skip to content

Commit 7f193af

Browse files
committed
screens
1 parent b4f80f7 commit 7f193af

6 files changed

Lines changed: 511 additions & 322 deletions

File tree

-205 KB
Binary file not shown.

src/app/globals.css

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,34 +40,34 @@
4040

4141
html.dark {
4242
/* ── Core palette (dark) ────────────────────── */
43-
--background: #0a0a0a;
44-
--section-bg: #0a0a0a;
45-
--foreground: #ededed;
46-
--dark-text: rgba(237, 237, 237, 0.58);
47-
--muted: rgba(237, 237, 237, 0.55);
43+
--background: #1a1a1e;
44+
--section-bg: #1a1a1e;
45+
--foreground: #f0f0f0;
46+
--dark-text: rgba(240, 240, 240, 0.78);
47+
--muted: rgba(240, 240, 240, 0.72);
4848

49-
--card: rgba(255, 255, 255, 0.03);
50-
--card-border: rgba(255, 255, 255, 0.08);
49+
--card: rgba(255, 255, 255, 0.06);
50+
--card-border: rgba(255, 255, 255, 0.14);
5151

52-
--primary: #ededed;
53-
--primary-light: #ededed;
54-
--primary-glow: rgba(255, 255, 255, 0.06);
55-
--accent: #ededed;
52+
--primary: #f0f0f0;
53+
--primary-light: #f0f0f0;
54+
--primary-glow: rgba(255, 255, 255, 0.08);
55+
--accent: #f0f0f0;
5656

5757
/* ── Hover / interactive ────────────────────── */
58-
--hover-accent-bg: rgba(190, 0, 181, 0.07);
59-
--chat-bubble-bg: rgba(255, 255, 255, 0.07);
60-
--counter-color: rgba(237, 237, 237, 0.22);
58+
--hover-accent-bg: rgba(190, 0, 181, 0.09);
59+
--chat-bubble-bg: rgba(255, 255, 255, 0.1);
60+
--counter-color: rgba(240, 240, 240, 0.35);
6161

6262
/* ── Navbar ─────────────────────────────────── */
63-
--nav-bg-scrolled: rgba(10, 10, 10, 0.92);
64-
--nav-border-color: rgba(255, 255, 255, 0.08);
65-
--nav-mobile-bg: rgba(10, 10, 10, 0.98);
66-
--nav-link-color: #ededed;
67-
--nav-mobile-border: rgba(255, 255, 255, 0.08);
68-
69-
--input-bg: rgba(255, 255, 255, 0.07);
70-
--arrow-color: #ededed;
63+
--nav-bg-scrolled: rgba(26, 26, 30, 0.94);
64+
--nav-border-color: rgba(255, 255, 255, 0.14);
65+
--nav-mobile-bg: rgba(26, 26, 30, 0.98);
66+
--nav-link-color: #f0f0f0;
67+
--nav-mobile-border: rgba(255, 255, 255, 0.14);
68+
69+
--input-bg: rgba(255, 255, 255, 0.09);
70+
--arrow-color: #f0f0f0;
7171
}
7272

7373
@keyframes moonblink {

src/app/page.js

Lines changed: 99 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useState, useEffect, useCallback, useRef } from 'react';
44
import Link from 'next/link';
55
import { motion, AnimatePresence } from 'framer-motion';
66
import { FiArrowRight, FiMoon, FiSun, FiCheck, FiGithub, FiLinkedin, FiDownload } from 'react-icons/fi';
7+
import Footer from '@/components/Footer';
78

89
const ACCENT = '#BE00B5';
910
const SECTION_LABELS = ['Intro', 'AI & Chatbots', 'Accessibility', 'Connect'];
@@ -20,16 +21,6 @@ function useC() {
2021
};
2122
}
2223

23-
// ─── Section tag ─────────────────────────────────────────────────────────────
24-
function Tag({ n, label, c }) {
25-
return (
26-
<p style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: '0.68rem', letterSpacing: '0.14em', color: c.muted, margin: '0 0 2.5rem', display: 'flex', gap: '0.5rem', transition: 'color 0.5s ease' }}>
27-
<span style={{ color: ACCENT }}>//</span>
28-
<span>{n}{label}</span>
29-
</p>
30-
);
31-
}
32-
3324
// ─── Side nav ─────────────────────────────────────────────────────────────────
3425
function SideNav({ current, total, onGo }) {
3526
const c = useC();
@@ -53,6 +44,38 @@ function SideNav({ current, total, onGo }) {
5344
);
5445
}
5546

47+
// ─── Cycling role title ────────────────────────────────────────────────────────
48+
const ROLES = ['Full-Stack Developer', 'AI Builder', 'React Engineer', 'Product Builder'];
49+
50+
function CyclingRole() {
51+
const [text, setText] = useState('');
52+
const [roleIdx, setRoleIdx] = useState(0);
53+
const [deleting, setDeleting] = useState(false);
54+
55+
useEffect(() => {
56+
const target = ROLES[roleIdx];
57+
let timeout;
58+
if (!deleting && text === target) {
59+
timeout = setTimeout(() => setDeleting(true), 1800);
60+
} else if (deleting && text === '') {
61+
setDeleting(false);
62+
setRoleIdx(i => (i + 1) % ROLES.length);
63+
} else if (deleting) {
64+
timeout = setTimeout(() => setText(t => t.slice(0, -1)), 45);
65+
} else {
66+
timeout = setTimeout(() => setText(target.slice(0, text.length + 1)), 85);
67+
}
68+
return () => clearTimeout(timeout);
69+
}, [text, deleting, roleIdx]);
70+
71+
return (
72+
<span>
73+
{text}
74+
<span style={{ display: 'inline-block', width: '2px', height: '0.85em', background: ACCENT, marginLeft: '2px', verticalAlign: 'middle', animation: 'blink 1s step-end infinite' }} />
75+
</span>
76+
);
77+
}
78+
5679
// ─── Marquee ──────────────────────────────────────────────────────────────────
5780
const TICKER = ['React', 'Next.js', 'Node.js', 'TypeScript', 'AI Chatbots', 'Accessibility', 'UX Design', 'Supabase', 'REST APIs', 'React Native', 'Python', 'Full-Stack Dev'];
5881

@@ -80,7 +103,7 @@ function IntroSection() {
80103
const c = useC();
81104

82105
return (
83-
<section style={{ minHeight: '100vh', width: '100%', background: c.bg, color: c.fg, display: 'flex', flexDirection: 'column', transition: 'background 0.5s ease, color 0.5s ease' }}>
106+
<section style={{ height: '100%', width: '100%', background: c.bg, color: c.fg, display: 'flex', flexDirection: 'column', transition: 'background 0.5s ease, color 0.5s ease' }}>
84107
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: '7rem max(2rem, 7vw) 2.5rem', maxWidth: '1200px', margin: '0 auto', width: '100%' }}>
85108

86109
<motion.p
@@ -89,7 +112,7 @@ function IntroSection() {
89112
transition={{ delay: 0.08, duration: 0.55 }}
90113
style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: '0.95rem', color: ACCENT, margin: '0 0 1.25rem', cursor: 'default', letterSpacing: '0.04em' }}
91114
>
92-
// Full-Stack Developer
115+
// <CyclingRole />
93116
</motion.p>
94117

95118
<div style={{ overflow: 'hidden' }}>
@@ -133,7 +156,7 @@ function IntroSection() {
133156
</p>
134157
</div>
135158

136-
{/* Primary CTAs */}
159+
{/* Primary CTA */}
137160
<div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', alignItems: 'center' }}>
138161
<Link
139162
href="/case-studies/elika-beauty"
@@ -143,45 +166,47 @@ function IntroSection() {
143166
>
144167
View Elika Beauty <FiArrowRight size={13} />
145168
</Link>
146-
<Link
147-
href="/resume"
148-
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.45rem', padding: '0.7rem 1.5rem', background: 'transparent', color: c.fg, border: `2px solid ${c.border}`, borderRadius: '4px', fontFamily: "'JetBrains Mono', monospace", fontSize: '0.85rem', textDecoration: 'none', transition: 'border-color 0.2s, color 0.5s ease' }}
149-
onMouseEnter={e => { e.currentTarget.style.borderColor = c.fg; }}
150-
onMouseLeave={e => { e.currentTarget.style.borderColor = c.border; }}
151-
>
152-
<FiDownload size={13} /> Download Resume
153-
</Link>
154169
</div>
155170

156-
{/* Social links */}
157-
<div style={{ display: 'flex', gap: '0.65rem', flexWrap: 'wrap' }}>
158-
<a
159-
href="https://github.com/curleycoder"
160-
target="_blank"
161-
rel="noopener noreferrer"
162-
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem', padding: '0.45rem 0.9rem', border: `1.5px solid ${c.border}`, borderRadius: '4px', color: c.sub, fontFamily: "'JetBrains Mono', monospace", fontSize: '0.76rem', textDecoration: 'none', letterSpacing: '0.06em', transition: 'border-color 0.2s, color 0.2s' }}
163-
onMouseEnter={e => { e.currentTarget.style.borderColor = ACCENT; e.currentTarget.style.color = ACCENT; }}
164-
onMouseLeave={e => { e.currentTarget.style.borderColor = c.border; e.currentTarget.style.color = c.sub; }}
165-
>
166-
<FiGithub size={13} /> GitHub
167-
</a>
168-
<a
169-
href="https://linkedin.com/in/shabnam-beiraghian"
170-
target="_blank"
171-
rel="noopener noreferrer"
172-
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem', padding: '0.45rem 0.9rem', border: `1.5px solid ${c.border}`, borderRadius: '4px', color: c.sub, fontFamily: "'JetBrains Mono', monospace", fontSize: '0.76rem', textDecoration: 'none', letterSpacing: '0.06em', transition: 'border-color 0.2s, color 0.2s' }}
173-
onMouseEnter={e => { e.currentTarget.style.borderColor = ACCENT; e.currentTarget.style.color = ACCENT; }}
174-
onMouseLeave={e => { e.currentTarget.style.borderColor = c.border; e.currentTarget.style.color = c.sub; }}
175-
>
176-
<FiLinkedin size={13} /> LinkedIn
177-
</a>
171+
{/* Social links + Download Resume */}
172+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '0.65rem', flexWrap: 'wrap' }}>
173+
<div style={{ display: 'flex', gap: '0.65rem', flexWrap: 'wrap' }}>
174+
<a
175+
href="https://github.com/curleycoder"
176+
target="_blank"
177+
rel="noopener noreferrer"
178+
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem', padding: '0.45rem 0.9rem', border: `1.5px solid ${c.border}`, borderRadius: '4px', color: c.sub, fontFamily: "'JetBrains Mono', monospace", fontSize: '0.76rem', textDecoration: 'none', letterSpacing: '0.06em', transition: 'border-color 0.2s, color 0.2s' }}
179+
onMouseEnter={e => { e.currentTarget.style.borderColor = ACCENT; e.currentTarget.style.color = ACCENT; }}
180+
onMouseLeave={e => { e.currentTarget.style.borderColor = c.border; e.currentTarget.style.color = c.sub; }}
181+
>
182+
<FiGithub size={13} /> GitHub
183+
</a>
184+
<a
185+
href="https://linkedin.com/in/shabnam-beiraghian"
186+
target="_blank"
187+
rel="noopener noreferrer"
188+
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem', padding: '0.45rem 0.9rem', border: `1.5px solid ${c.border}`, borderRadius: '4px', color: c.sub, fontFamily: "'JetBrains Mono', monospace", fontSize: '0.76rem', textDecoration: 'none', letterSpacing: '0.06em', transition: 'border-color 0.2s, color 0.2s' }}
189+
onMouseEnter={e => { e.currentTarget.style.borderColor = ACCENT; e.currentTarget.style.color = ACCENT; }}
190+
onMouseLeave={e => { e.currentTarget.style.borderColor = c.border; e.currentTarget.style.color = c.sub; }}
191+
>
192+
<FiLinkedin size={13} /> LinkedIn
193+
</a>
194+
<Link
195+
href="/projects"
196+
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem', padding: '0.45rem 0.9rem', border: `1.5px solid ${c.border}`, borderRadius: '4px', color: c.sub, fontFamily: "'JetBrains Mono', monospace", fontSize: '0.76rem', textDecoration: 'none', letterSpacing: '0.06em', transition: 'border-color 0.2s, color 0.2s' }}
197+
onMouseEnter={e => { e.currentTarget.style.borderColor = ACCENT; e.currentTarget.style.color = ACCENT; }}
198+
onMouseLeave={e => { e.currentTarget.style.borderColor = c.border; e.currentTarget.style.color = c.sub; }}
199+
>
200+
All projects <FiArrowRight size={12} />
201+
</Link>
202+
</div>
178203
<Link
179-
href="/projects"
180-
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem', padding: '0.45rem 0.9rem', border: `1.5px solid ${c.border}`, borderRadius: '4px', color: c.sub, fontFamily: "'JetBrains Mono', monospace", fontSize: '0.76rem', textDecoration: 'none', letterSpacing: '0.06em', transition: 'border-color 0.2s, color 0.2s' }}
204+
href="/resume"
205+
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.45rem', padding: '0.45rem 0.9rem', background: 'transparent', color: c.sub, border: `1.5px solid ${c.border}`, borderRadius: '4px', fontFamily: "'JetBrains Mono', monospace", fontSize: '0.76rem', textDecoration: 'none', letterSpacing: '0.06em', transition: 'border-color 0.2s, color 0.2s' }}
181206
onMouseEnter={e => { e.currentTarget.style.borderColor = ACCENT; e.currentTarget.style.color = ACCENT; }}
182207
onMouseLeave={e => { e.currentTarget.style.borderColor = c.border; e.currentTarget.style.color = c.sub; }}
183208
>
184-
All projects <FiArrowRight size={12} />
209+
<FiDownload size={13} /> Download Resume
185210
</Link>
186211
</div>
187212
</motion.div>
@@ -190,6 +215,7 @@ function IntroSection() {
190215
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.85, duration: 0.6 }}>
191216
<Marquee />
192217
</motion.div>
218+
<Footer />
193219
</section>
194220
);
195221
}
@@ -228,7 +254,6 @@ function ChatSection() {
228254
<div className="chat-grid" style={{ maxWidth: '1100px', width: '100%', margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '6rem', alignItems: 'center' }}>
229255

230256
<div>
231-
<Tag n="02" label="AI & CHATBOTS" c={c} />
232257
<h2 style={{ fontFamily: "'JetBrains Mono', monospace", fontWeight: 800, fontSize: 'clamp(2rem, 5vw, 4rem)', lineHeight: 1.05, color: c.fg, textTransform: 'uppercase', letterSpacing: '-0.02em', margin: '0 0 1.75rem', transition: 'color 0.5s ease' }}>
233258
Embedded<br /><span style={{ color: ACCENT }}>AI</span>
234259
</h2>
@@ -300,8 +325,6 @@ function A11ySection({ isDark, toggleDark }) {
300325
return (
301326
<section style={{ minHeight: '100vh', width: '100%', background: c.bg, color: c.fg, display: 'flex', alignItems: 'center', padding: '5rem max(2rem, 7vw)', transition: 'background 0.5s ease, color 0.5s ease' }}>
302327
<div style={{ maxWidth: '1100px', width: '100%', margin: '0 auto' }}>
303-
<Tag n="03" label="ACCESSIBILITY" c={c} />
304-
305328
<div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: '3rem', flexWrap: 'wrap', gap: '2rem' }}>
306329
<h2 style={{ fontFamily: "'JetBrains Mono', monospace", fontWeight: 800, fontSize: 'clamp(2rem, 5.5vw, 4.5rem)', lineHeight: 1.05, color: c.fg, textTransform: 'uppercase', letterSpacing: '-0.02em', margin: 0, transition: 'color 0.5s ease' }}>
307330
Built for<br /><span style={{ color: ACCENT }}>everyone.</span>
@@ -359,8 +382,6 @@ function ConnectSection() {
359382
return (
360383
<section style={{ minHeight: '100vh', width: '100%', background: c.bg, color: c.fg, display: 'flex', alignItems: 'center', padding: '5rem max(2rem, 7vw)', transition: 'background 0.5s ease, color 0.5s ease' }}>
361384
<div style={{ maxWidth: '1100px', width: '100%', margin: '0 auto' }}>
362-
<Tag n="04" label="CONNECT" c={c} />
363-
364385
<h2 style={{ fontFamily: "'JetBrains Mono', monospace", fontWeight: 800, fontSize: 'clamp(2.5rem, 6vw, 5rem)', lineHeight: 1.05, color: c.fg, textTransform: 'uppercase', letterSpacing: '-0.02em', margin: '0 0 2rem', transition: 'color 0.5s ease' }}>
365386
Open for<br /><span style={{ color: ACCENT }}>new roles.</span>
366387
</h2>
@@ -480,7 +501,28 @@ export default function HomePage() {
480501

481502
useEffect(() => {
482503
document.body.style.overflow = 'hidden';
483-
return () => { document.body.style.overflow = ''; };
504+
document.documentElement.style.overflow = 'hidden';
505+
const globalFooter = document.querySelector('body > main + footer');
506+
if (globalFooter) globalFooter.style.display = 'none';
507+
return () => {
508+
document.body.style.overflow = '';
509+
document.documentElement.style.overflow = '';
510+
if (globalFooter) globalFooter.style.display = '';
511+
};
512+
}, []);
513+
514+
// Auto-advance sections
515+
useEffect(() => {
516+
const timer = setInterval(() => {
517+
if (animating.current) return;
518+
setCurrent(c => {
519+
const next = (c + 1) % SECTIONS.length;
520+
animating.current = true;
521+
setTimeout(() => { animating.current = false; }, 700);
522+
return next;
523+
});
524+
}, 12000);
525+
return () => clearInterval(timer);
484526
}, []);
485527

486528
const Cur = SECTIONS[current];
@@ -506,25 +548,15 @@ export default function HomePage() {
506548
<SideNav current={current} total={SECTIONS.length} onGo={goTo} />
507549
</div>
508550

509-
{/* Bottom-center label */}
510-
<div style={{ position: 'fixed', bottom: '3.5rem', left: '50%', transform: 'translateX(-50%)', zIndex: 20, pointerEvents: 'none', userSelect: 'none' }}>
511-
<AnimatePresence mode="wait">
512-
<motion.span
513-
key={current}
514-
initial={{ opacity: 0, y: 4 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -4 }}
515-
transition={{ duration: 0.2 }}
516-
style={{ display: 'block', fontFamily: "'JetBrains Mono', monospace", fontSize: '0.6rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--counter-color)', transition: 'color 0.5s ease', whiteSpace: 'nowrap' }}
517-
>
518-
{String(current + 1).padStart(2, '0')}{SECTION_LABELS[current]}
519-
</motion.span>
520-
</AnimatePresence>
521-
</div>
522-
523-
<style jsx global>{`
551+
<style jsx global>{`
524552
@keyframes tickerMove {
525553
from { transform: translateX(0); }
526554
to { transform: translateX(-50%); }
527555
}
556+
@keyframes blink {
557+
0%, 100% { opacity: 1; }
558+
50% { opacity: 0; }
559+
}
528560
@media (max-width: 760px) {
529561
.chat-grid { grid-template-columns: 1fr !important; gap: 2.5rem !important; }
530562
.fs-grid { grid-template-columns: 1fr !important; gap: 2.5rem !important; }

src/components/Navbar.jsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useState, useEffect } from 'react';
44
import Link from 'next/link';
55
import { usePathname } from 'next/navigation';
6+
import { FiSun, FiMoon } from 'react-icons/fi';
67

78
const navLinks = [
89
{ href: '/', label: 'HOME' },
@@ -13,12 +14,28 @@ const navLinks = [
1314

1415
export default function Navbar() {
1516
const [mobileOpen, setMobileOpen] = useState(false);
17+
const [isDark, setIsDark] = useState(false);
1618
const pathname = usePathname();
1719

1820
useEffect(() => {
1921
setMobileOpen(false);
2022
}, [pathname]);
2123

24+
useEffect(() => {
25+
setIsDark(document.documentElement.classList.contains('dark'));
26+
const observer = new MutationObserver(() => {
27+
setIsDark(document.documentElement.classList.contains('dark'));
28+
});
29+
observer.observe(document.documentElement, { attributeFilter: ['class'] });
30+
return () => observer.disconnect();
31+
}, []);
32+
33+
const toggleDark = () => {
34+
const next = !isDark;
35+
document.documentElement.classList.toggle('dark', next);
36+
setIsDark(next);
37+
};
38+
2239
return (
2340
<nav
2441
style={{
@@ -93,6 +110,7 @@ export default function Navbar() {
93110
style={{ display: 'flex', alignItems: 'center', gap: '1.75rem' }}
94111
>
95112
{navLinks.map((link) => {
113+
96114
const isActive =
97115
link.href === '/'
98116
? pathname === '/'
@@ -125,6 +143,22 @@ export default function Navbar() {
125143
</Link>
126144
);
127145
})}
146+
147+
<button
148+
onClick={toggleDark}
149+
aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'}
150+
style={{
151+
display: 'flex', alignItems: 'center', justifyContent: 'center',
152+
width: '32px', height: '32px', borderRadius: '6px',
153+
border: '1.5px solid var(--nav-border-color)',
154+
background: 'transparent', color: 'var(--nav-link-color)',
155+
cursor: 'pointer', transition: 'border-color 0.2s, color 0.2s',
156+
}}
157+
onMouseEnter={e => { e.currentTarget.style.borderColor = '#BE00B5'; e.currentTarget.style.color = '#BE00B5'; }}
158+
onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--nav-border-color)'; e.currentTarget.style.color = 'var(--nav-link-color)'; }}
159+
>
160+
{isDark ? <FiSun size={14} /> : <FiMoon size={14} />}
161+
</button>
128162
</div>
129163

130164
{/* Mobile button */}

0 commit comments

Comments
 (0)