@@ -11,6 +11,7 @@ const nav = [
1111]
1212
1313const stack = [' Java' , ' C#' , ' Python' , ' Node.js' , ' Flutter' , ' Dart' , ' Rust' , ' SQL' , ' Azure' , ' Firebase' , ' REST APIs' , ' Git' ]
14+ const roles = [' web apps' , ' REST APIs' , ' mobile apps' , ' developer tools' ]
1415
1516const skills = [
1617 { k: ' Languages' , v: [' Java' , ' C#' , ' Python' , ' JavaScript' , ' SQL' , ' Dart' , ' Rust' ] },
@@ -51,18 +52,29 @@ const certs = [
5152<Base >
5253 <a id =" top" ></a >
5354
55+ <!-- Load intro -->
56+ <div id =" ed-loader" aria-hidden =" true" >
57+ <span class =" ed-loader__tag ed-mono" >Ronan Roberts / Portfolio</span >
58+ <span class =" ed-loader__count ed-mono" id =" ed-count" >000</span >
59+ <span class =" ed-loader__bar" ></span >
60+ </div >
61+
62+ <!-- Custom cursor -->
63+ <div id =" ed-cursor" aria-hidden =" true" ></div >
64+ <div id =" ed-cursor-ring" aria-hidden =" true" ><span id =" ed-cursor-label" ></span ></div >
65+
5466 <header id =" site-header" class =" fixed top-0 inset-x-0 z-50" >
5567 <div class =" container-wide" >
5668 <div id =" nav-inner" class =" flex items-center justify-between h-[72px] transition-all duration-300" >
57- <a href =" #top" class =" ed-mono font-bold tracking-tight text-sm" >RR / ROBERTS</a >
69+ <a href =" #top" class =" ed-mono font-bold tracking-tight text-sm" data-cursor >RR / ROBERTS</a >
5870 <nav class =" hidden md:flex items-center gap-7" >
5971 { nav .map (item => (
60- <a href = { item .href } class = " ed-mono text-xs uppercase tracking-widest nav-link" >{ item .label } </a >
72+ <a href = { item .href } class = " ed-mono text-xs uppercase tracking-widest nav-link" data-cursor >{ item .label } </a >
6173 ))}
6274 </nav >
6375 <div class =" flex items-center gap-4" >
6476 <span class =" ed-avail hidden sm:inline-flex" ><i ></i >Available for work</span >
65- <button class =" ed-menu-btn ed-mono text-xs uppercase tracking-widest" id =" ed-menu-open" aria-label =" Open menu" >Menu</button >
77+ <button class =" ed-menu-btn ed-mono text-xs uppercase tracking-widest" id =" ed-menu-open" aria-label =" Open menu" data-cursor >Menu</button >
6678 </div >
6779 </div >
6880 </div >
@@ -76,32 +88,43 @@ const certs = [
7688 <main class =" container-wide pt-[72px]" >
7789
7890 <!-- Masthead -->
79- <section class =" min-h-[calc(100dvh-72px)] flex flex-col justify-center pt-10 pb-16" >
80- <div class =" ed-kicker mb-6" data-reveal >Full-stack Developer, Germiston ZA</div >
81- <hr class =" ed-rule-accent mb-8" data-reveal />
91+ <section class =" ed-hero min-h-[calc(100dvh-72px)] flex flex-col justify-center pt-10 pb-16" >
92+ <div class =" ed-hero-top" data-reveal >
93+ <span class =" ed-kicker" >Full-stack Developer</span >
94+ <span class =" ed-kicker ed-clock" id =" ed-clock" >Germiston ZA</span >
95+ </div >
96+ <hr class =" ed-rule-accent mb-8 mt-6" data-reveal />
8297
83- <h1 class =" ed-huge" style = " font-size: clamp(3.4rem, 15vw, 13rem) " data-ed-title >
98+ <h1 class =" ed-huge ed-name " data-ed-title >
8499 <span class =" ed-line" ><span >Ronan</span ></span >
85100 <span class =" ed-line" ><span class =" ed-outline" >Roberts</span ></span >
86101 </h1 >
87102
88103 <hr class =" ed-rule mt-10 mb-8" data-reveal />
89104 <div class =" grid grid-cols-1 md:grid-cols-[1.7fr_1fr] gap-8 md:gap-16 items-end" >
90- <p class =" text-lg md:text-xl leading-relaxed" style =" max-width: 58ch" data-reveal >
91- I build across the stack, web front-ends and back-ends in Java, C#,
92- Python and Node.js, and cross-platform mobile apps in Flutter and Dart.
93- Currently a Junior Software Engineer at Coast IT.
94- </p >
105+ <div >
106+ <div class =" ed-rotate ed-mono mb-5" aria-hidden =" true" >
107+ <span >I build</span >
108+ <span class =" ed-rotate__mask" ><span class =" ed-rotate__list" data-rotate >
109+ { roles .map (r => <span >{ r } </span >)}
110+ <span >{ roles [0 ]} </span >
111+ </span ></span >
112+ </div >
113+ <p class =" text-lg md:text-xl leading-relaxed" style =" max-width: 58ch" data-reveal >
114+ Web front-ends and back-ends in Java, C#, Python and Node.js, and cross-platform
115+ mobile apps in Flutter and Dart. Currently a Junior Software Engineer at Coast IT.
116+ </p >
117+ </div >
95118 <div class =" flex flex-wrap gap-3 md:justify-end" data-reveal >
96- <a href =" #work" class =" btn-primary magnetic" data-magnetic >View work</a >
97- <a href =" #contact" class =" btn-ghost magnetic" data-magnetic >Get in touch</a >
119+ <a href =" #work" class =" btn-primary magnetic" data-magnetic data-cursor >View work</a >
120+ <a href =" #contact" class =" btn-ghost magnetic" data-magnetic data-cursor >Get in touch</a >
98121 </div >
99122 </div >
100123 </section >
101124 </main >
102125
103- <!-- Tech marquee -->
104- <section class =" py-6 border-y" style =" border-color: var(--border)" aria-hidden =" true" >
126+ <!-- Velocity marquee -->
127+ <section class =" py-6 border-y ed-marquee-wrap " style =" border-color: var(--border)" aria-hidden =" true" >
105128 <div class =" marquee" >
106129 <div class =" marquee__track" >
107130 { stack .map (s => <span class = " marquee__item" >{ s } </span >)}
@@ -115,9 +138,15 @@ const certs = [
115138 <main class =" container-wide" >
116139
117140 <!-- Profile / skills -->
118- <section id =" profile" class =" py-20 lg:py-28" >
119- <h2 class =" ed-huge mb-12" style =" font-size: clamp(2rem, 6vw, 4rem)" data-reveal >Profile</h2 >
120- <div class =" grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-10 gap-y-10" >
141+ <section id =" profile" class =" py-24 lg:py-36" >
142+ <h2 class =" ed-huge ed-h2 mb-12" data-reveal >Profile</h2 >
143+
144+ <p class =" ed-fill" data-fill >
145+ I care about software that ships, holds up in production, and still reads clearly six
146+ months later. I work across the whole stack and own a feature from schema to screen.
147+ </p >
148+
149+ <div class =" grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-10 gap-y-10 mt-20" >
121150 { skills .map (group => (
122151 <div data-reveal >
123152 <div class = " ed-kicker mb-3 pb-2" style = " border-bottom: 1px solid var(--border)" >{ group .k } </div >
@@ -128,38 +157,46 @@ const certs = [
128157 ))}
129158 </div >
130159 </section >
160+ </main >
131161
132- <!-- Work index -->
133- <section id =" work" class =" py-20 lg:py-28" >
134- <div class =" flex items-end justify-between mb-10 gap-4" >
135- <h2 class =" ed-huge" style =" font-size: clamp(2rem, 6vw, 4rem)" data-reveal >Selected Work</h2 >
136- <span class =" ed-mono text-xs hidden sm:block" style =" color: var(--muted)" data-reveal >2024 to 2026</span >
137- </div >
138- <div >
162+ <!-- Work: horizontal-pinned act (falls back to vertical stack) -->
163+ <section id =" work" class =" ed-work" >
164+ <div class =" container-wide ed-work-head" >
165+ <h2 class =" ed-huge ed-h2" data-reveal >Selected<br />Work</h2 >
166+ <span class =" ed-mono text-xs" style =" color: var(--muted)" data-reveal >05 projects, 2024 to 2026</span >
167+ </div >
168+ <div class =" ed-work-viewport" >
169+ <div class =" ed-work-track" >
139170 { work .map (item => (
140- <a href = { item .href } target = " _blank" rel = " noopener noreferrer" class = " work-row group " data-reveal >
141- <span class = " ed-num " >{ item .n } </span >
142- <span >
143- <span class = " work-title block " >{ item .title } </span >
144- <span class = " ed-mono text-xs " style = " color: var(--muted)" >{ item .meta } </span >
171+ <a href = { item .href } target = " _blank" rel = " noopener noreferrer" class = " ed-panel " data-hr data-cursor data-cursor-label = " Open " >
172+ <span class = " ed-panel__num ed-outline " >{ item .n } </span >
173+ <span class = " ed-panel__body " >
174+ <span class = " ed-panel__title " >{ item .title } </span >
175+ <span class = " ed-mono text-sm " style = " color: var(--muted)" >{ item .meta } </span >
145176 </span >
146- <span class = " flex items-center gap-4 " >
147- <span class = " hidden md: flex flex-wrap gap-1.5 justify-end " style = " max-width: 220px " >
177+ <span class = " ed-panel__foot " >
178+ <span class = " flex flex-wrap gap-1.5" >
148179 { item .tags .map (t => <span class = " ed-tag" >{ t } </span >)}
149180 </span >
150- <span class = " ed-mono text-xs hidden sm:inline" style = " color: var(--muted)" >{ item .year } </span >
151- <span class = " work-row__arrow" aria-hidden = " true" >
152- <svg width = " 15" height = " 15" viewBox = " 0 0 24 24" fill = " none" stroke = " currentColor" stroke-width = " 2.2" stroke-linecap = " round" stroke-linejoin = " round" ><path d = " M5 12h14M13 6l6 6-6 6" /></svg >
181+ <span class = " ed-panel__year ed-mono" >{ item .year }
182+ <svg width = " 16" height = " 16" viewBox = " 0 0 24 24" fill = " none" stroke = " currentColor" stroke-width = " 2.2" stroke-linecap = " round" stroke-linejoin = " round" ><path d = " M7 17L17 7M17 7H8M17 7V16" /></svg >
153183 </span >
154184 </span >
155185 </a >
156186 ))}
187+ <a href =" https://github.com/Ronan-R-R" target =" _blank" rel =" noopener noreferrer" class =" ed-panel ed-panel--end" data-hr data-cursor data-cursor-label =" GitHub" >
188+ <span class =" ed-panel__title" >More<br />on GitHub</span >
189+ <span class =" ed-mono text-sm" style =" color: var(--muted)" >github.com/Ronan-R-R</span >
190+ </a >
157191 </div >
158- </section >
192+ </div >
193+ </section >
194+
195+ <main class =" container-wide" >
159196
160197 <!-- Record -->
161- <section id =" record" class =" py-20 lg:py-28 " >
162- <h2 class =" ed-huge mb-12 " style = " font-size: clamp(2rem, 6vw, 4rem) " data-reveal >Record</h2 >
198+ <section id =" record" class =" py-24 lg:py-36 " >
199+ <h2 class =" ed-huge ed-h2 mb-12 " data-reveal >Record</h2 >
163200 <div class =" grid grid-cols-1 lg:grid-cols-2 gap-x-16 gap-y-12" >
164201 <div data-reveal >
165202 <div class =" ed-kicker mb-4" >Experience & Education</div >
@@ -189,32 +226,37 @@ const certs = [
189226 </section >
190227
191228 <!-- Contact -->
192- <section id =" contact" class =" py-20 lg:py-28" >
193- <h2 class =" ed-huge mb-8" style =" font-size: clamp(2rem, 6vw, 4rem)" data-reveal >Get in touch</h2 >
194- <hr class =" ed-rule-accent mb-12" data-reveal />
229+ <section id =" contact" class =" py-24 lg:py-36" >
230+ <h2 class =" ed-huge ed-contact-title" data-ed-title >
231+ <span class =" ed-line" ><span >Let's</span ></span >
232+ <span class =" ed-line" ><span class =" ed-outline" >Talk</span ></span >
233+ </h2 >
234+ <hr class =" ed-rule-accent my-12" data-reveal />
195235 <div class =" grid grid-cols-1 lg:grid-cols-[1fr_1fr] gap-12 lg:gap-20" >
196236 <div data-reveal >
197237 <p class =" text-2xl md:text-4xl font-display font-bold leading-tight mb-10" style =" max-width: 16ch" >
198238 Open to freelance projects and job opportunities.
199239 </p >
200240 <div class =" ed-mono text-sm flex flex-col gap-3" >
201- <a href =" mailto:ronanr2003@gmail.com" class =" ed-link w-fit" >ronanr2003@gmail.com</a >
202- <a href =" https://www.linkedin.com/in/rr-roberts/" target =" _blank" rel =" noopener noreferrer" class =" ed-link w-fit" >linkedin.com/in/rr-roberts</a >
203- <a href =" https://github.com/Ronan-R-R" target =" _blank" rel =" noopener noreferrer" class =" ed-link w-fit" >github.com/Ronan-R-R</a >
241+ <a href =" mailto:ronanr2003@gmail.com" class =" ed-link w-fit" data-cursor >ronanr2003@gmail.com</a >
242+ <a href =" https://www.linkedin.com/in/rr-roberts/" target =" _blank" rel =" noopener noreferrer" class =" ed-link w-fit" data-cursor >linkedin.com/in/rr-roberts</a >
243+ <a href =" https://github.com/Ronan-R-R" target =" _blank" rel =" noopener noreferrer" class =" ed-link w-fit" data-cursor >github.com/Ronan-R-R</a >
204244 </div >
205245 </div >
206246 <div data-reveal >
207247 <ContactForm client:visible />
208248 </div >
209249 </div >
210250 </section >
211-
212- <footer class =" py-10 ed-mono text-xs flex flex-col sm:flex-row justify-between gap-3" style =" border-top: 1px solid var(--border); color: var(--muted)" >
213- <span >© <span id =" footer-year" ></span > Ronan Roberts</span >
214- <span >Designed and built by Ronan Roberts</span >
215- </footer >
216251 </main >
217252
253+ <div class =" ed-footmark" aria-hidden =" true" ><span >ROBERTS</span ></div >
254+
255+ <footer class =" container-wide py-10 ed-mono text-xs flex flex-col sm:flex-row justify-between gap-3" style =" border-top: 1px solid var(--border); color: var(--muted)" >
256+ <span >© <span id =" footer-year" ></span > Ronan Roberts</span >
257+ <span >Designed and built by Ronan Roberts</span >
258+ </footer >
259+
218260 <script >
219261 const el = document.getElementById('footer-year')
220262 if (el) el.textContent = String(new Date().getFullYear())
0 commit comments