@@ -190,269 +190,3 @@ <h3>Message</h3>
190190 < script src ="script.js "> </ script >
191191</ body >
192192</ html >
193- <!DOCTYPE html>
194- < html lang ="en ">
195- < head >
196- < meta charset ="utf-8 " />
197- < meta name ="viewport " content ="width=device-width, initial-scale=1 " />
198- < title > SCode — Developer Portfolio</ title >
199- < link rel ="stylesheet " href ="style.css " />
200- < meta name ="description " content ="SCode — Web developer. Creative developer passionate about design, code, and user experience. " />
201-
202- <!-- Favicon -->
203- < link rel ="icon " href ="https://raw.githubusercontent.com/SCodeGit/scode.git.io/main/images/scode.jpg " type ="image/jpeg ">
204- < link rel ="apple-touch-icon " href ="https://raw.githubusercontent.com/SCodeGit/scode.git.io/main/images/scode.jpg ">
205-
206- <!-- Theme preference -->
207- < meta name ="color-scheme " content ="light dark ">
208- </ head >
209- < body class ="dark-theme ">
210-
211- <!-- Background overlay for particles/matrix -->
212- < canvas id ="bgCanvas " style ="position:fixed;left:0;top:0;width:100%;height:100%;z-index:0;pointer-events:none;opacity:0.06 "> </ canvas >
213-
214- <!-- Theme toggle -->
215- < button class ="theme-toggle " id ="themeToggle " title ="Toggle light/dark " aria-label ="Toggle theme "> 🌙</ button >
216-
217- <!-- Header / Hero -->
218- < header class ="hero-outer ">
219- < div class ="container hero-inner ">
220- < div class ="logo-wrap ">
221- < a href ="index.html ">
222- < img src ="https://raw.githubusercontent.com/SCodeGit/scode.git.io/main/images/scode.jpg " alt ="SCode logo " class ="hero-logo neon-glow ">
223- </ a >
224- < script >
225- // Typewriter function
226- function typeWriter ( element , text , speed = 40 , callback = null ) {
227- let i = 0 ;
228- element . textContent = '' ;
229- function type ( ) {
230- if ( i < text . length ) {
231- element . textContent += text . charAt ( i ) ;
232- i ++ ;
233- setTimeout ( type , speed ) ;
234- } else if ( callback ) {
235- callback ( ) ;
236- }
237- }
238- type ( ) ;
239- }
240-
241- // Hero section elements
242- const titleEl = document . querySelector ( '.name' ) ;
243- const titleSmall = titleEl . querySelector ( 'small' ) ;
244- const taglineEl = document . getElementById ( 'typed' ) ;
245- const btnEl = document . getElementById ( 'whatsappBtn' ) ;
246-
247- // Hero text content
248- const titleText = 'SCode' ;
249- const titleSuffix = ' — Developer' ;
250- const taglineText = 'Crafting sleek, responsive web experiences with precision and creativity.' ;
251- const btnText = 'Hire Me (WhatsApp)' ;
252-
253- // About/intro paragraph
254- const introEl = document . querySelector ( '#about p' ) ;
255- const introText = 'Hi, I’m SCode. I specialize in building modern, responsive websites for startups, NGOs, and businesses, blending design, code, and user experience with precision and creativity.' ;
256-
257- // Animate hero section sequentially
258- typeWriter ( titleEl , titleText , 50 , ( ) => {
259- titleSmall . textContent = titleSuffix ;
260- typeWriter ( taglineEl , taglineText , 30 , ( ) => {
261- typeWriter ( btnEl , btnText , 40 , ( ) => {
262- // After hero finishes, animate intro
263- typeWriter ( introEl , introText , 25 ) ;
264- } ) ;
265- } ) ;
266- } ) ;
267- </ script >
268-
269-
270- </ section >
271-
272- <!-- Projects -->
273- < section class ="section projects " id ="projects ">
274- < div class ="container ">
275- < h2 class ="glitch "> Selected Projects</ h2 >
276- < div class ="projects-grid ">
277-
278- <!-- Project 1 -->
279- < a class ="project-card neon-glow " href ="https://scodegit.github.io/pacesettersfoundation.github.io/ " target ="_blank " rel ="noopener ">
280- < img src ="https://raw.githubusercontent.com/SCodeGit/scode.git.io/main/images/scode.jpg " alt ="Pacesetters Foundation ">
281- < div class ="project-body ">
282- < h3 > Pacesetters Foundation</ h3 >
283- < p > Multi-page NGO site with donation and community sections.</ p >
284- </ div >
285- </ a >
286-
287- <!-- Project 2 -->
288- < a class ="project-card neon-glow " href ="https://scodegit.github.io/Bowiri-Traditional-Council/index.html " target ="_blank " rel ="noopener ">
289- < img src ="https://raw.githubusercontent.com/SCodeGit/Bowiri-Traditional-Council/28857d96cf2048e159e3a22335a78a7f13cf84a6/king%20logo.png " alt ="Bowiri Traditional Council ">
290- < div class ="project-body ">
291- < h3 > Bowiri Traditional Council</ h3 >
292- < p > Elegant traditional council website highlighting culture, leadership, and heritage.</ p >
293- </ div >
294- </ a >
295-
296- <!-- Project 3 placeholder -->
297- < div class ="project-card placeholder neon-glow ">
298- < div class ="project-body ">
299- < h3 > Project Three</ h3 >
300- < p > Coming soon — demo and case study will be added here.</ p >
301- </ div >
302- </ div >
303-
304- </ div >
305- </ div >
306- </ section >
307-
308- <!-- Contact -->
309- < section class ="section contact " id ="contact ">
310- < div class ="container ">
311- < h2 class ="glitch "> Contact</ h2 >
312- < div class ="contact-grid ">
313-
314- < div class ="contact-card neon-glow ">
315- < h3 > Get in touch</ h3 >
316- < p > Email:
< a href ="
mailto:[email protected] "
> [email protected] </ a > </ p > 317- < p > WhatsApp: < a href ="https://wa.me/233555578864 " target ="_blank " rel ="noopener "> +233 55 557 8864</ a > </ p >
318- < p > Facebook: < a href ="https://www.facebook.com/people/Atubra-Abraham/100072576882412/ " target ="_blank " rel ="noopener "> Atubra Abraham</ a > </ p >
319- </ div >
320-
321- < div class ="contact-card neon-glow ">
322- < h3 > Message</ h3 >
323- < form id ="contactForm " autocomplete ="on " novalidate >
324- < input type ="text " name ="name " placeholder ="Your name " required >
325- < input type ="email " name ="email " placeholder ="Your email " required >
326- < textarea name ="message " rows ="4 " placeholder ="Your message " required > </ textarea >
327- < button class ="btn primary neon-btn " type ="submit "> Send</ button >
328- < p id ="formStatus " role ="status " aria-live ="polite " style ="margin-top:10px; "> </ p >
329- </ form >
330- </ div >
331-
332- </ div >
333- </ div >
334- </ section >
335-
336- <!-- Footer -->
337- < footer class ="footer neon-glow ">
338- < div class ="container footer-inner ">
339- < div class ="left ">
340- < strong > SCode</ strong > < br >
341- < small > © 2025 All Rights Reserved — built by
342- < a class ="dev-link " href ="index.html "> SCode</ a >
343- </ small >
344- </ div >
345- < div class ="right social-links ">
346- < a href ="https://www.facebook.com/people/Atubra-Abraham/100072576882412/ " target ="_blank " rel ="noopener "> Facebook</ a >
347- < a href ="https://wa.me/233555578864 " target ="_blank " rel ="noopener "> WhatsApp</ a >
348- </ div >
349- </ div >
350- </ footer >
351-
352- < button id ="topBtn " title ="Back to top " class ="neon-btn "> ↑</ button >
353-
354- <!-- Scripts -->
355- < script >
356- // ================================
357- // Contact Form Submission (Formspree)
358- // ================================
359- const form = document . getElementById ( 'contactForm' ) ;
360- const status = document . getElementById ( 'formStatus' ) ;
361-
362- form . addEventListener ( 'submit' , function ( event ) {
363- event . preventDefault ( ) ; // prevent page reload
364- const formData = new FormData ( form ) ;
365-
366- fetch ( 'https://formspree.io/f/xwpwvqaz' , {
367- method : 'POST' ,
368- body : formData ,
369- headers : { 'Accept' : 'application/json' }
370- } ) . then ( response => {
371- if ( response . ok ) {
372- status . style . color = 'lime' ;
373- status . textContent = '✅ Message sent successfully! Thank you.' ;
374- form . reset ( ) ;
375- } else {
376- response . json ( ) . then ( data => {
377- if ( data . errors ) {
378- status . style . color = 'red' ;
379- status . textContent = '❌ Error sending message: ' + data . errors . map ( e => e . message ) . join ( ', ' ) ;
380- } else {
381- status . style . color = 'red' ;
382- status . textContent = '❌ Something went wrong. Please try again later.' ;
383- }
384- } ) ;
385- }
386- } ) . catch ( error => {
387- status . style . color = 'red' ;
388- status . textContent = '❌ Network error. Please try again later.' ;
389- } ) ;
390- } ) ;
391-
392- // ================================
393- // Theme Toggle
394- // ================================
395- const themeBtn = document . getElementById ( 'themeToggle' ) ;
396- const body = document . body ;
397- const savedTheme = localStorage . getItem ( 'scode_theme' ) ;
398- if ( savedTheme === 'light' ) body . classList . remove ( 'dark-theme' ) ;
399-
400- themeBtn . addEventListener ( 'click' , ( ) => {
401- body . classList . toggle ( 'dark-theme' ) ;
402- const isLight = ! body . classList . contains ( 'dark-theme' ) ;
403- localStorage . setItem ( 'scode_theme' , isLight ? 'light' : 'dark' ) ;
404- themeBtn . textContent = isLight ? '☀️' : '🌙' ;
405- } ) ;
406-
407- // ================================
408- // Back to top button
409- // ================================
410- const topBtn = document . getElementById ( 'topBtn' ) ;
411- topBtn . addEventListener ( 'click' , ( ) => window . scrollTo ( { top :0 , behavior :'smooth' } ) ) ;
412-
413- // ================================
414- // Typed text effect
415- // ================================
416- const typedEl = document . getElementById ( 'typed' ) ;
417- const text = "Creative developer — design, code & UX" ;
418- let i = 0 ;
419- function typeWriter ( ) {
420- if ( i <= text . length ) {
421- typedEl . innerHTML = text . slice ( 0 , i ) + ( i % 2 === 0 ? "|" : "" ) ;
422- i ++ ;
423- setTimeout ( typeWriter , 100 ) ;
424- }
425- }
426- typeWriter ( ) ;
427-
428- // ================================
429- // Background Matrix/Particles
430- // ================================
431- const canvas = document . getElementById ( 'bgCanvas' ) ;
432- const ctx = canvas . getContext ( '2d' ) ;
433- let w = canvas . width = innerWidth ;
434- let h = canvas . height = innerHeight ;
435- const cols = Math . floor ( w / 20 ) ;
436- const ypos = Array ( cols ) . fill ( 0 ) ;
437-
438- function run ( ) {
439- ctx . fillStyle = 'rgba(3,7,10,0.06)' ;
440- ctx . fillRect ( 0 , 0 , w , h ) ;
441- ctx . fillStyle = 'rgba(0,255,159,0.04)' ;
442- ctx . font = '12px monospace' ;
443- for ( let i = 0 ; i < ypos . length ; i ++ ) {
444- const text = String . fromCharCode ( 65 + Math . random ( ) * 33 ) ;
445- ctx . fillText ( text , i * 20 , ypos [ i ] ) ;
446- ypos [ i ] = ( ypos [ i ] > 100 + Math . random ( ) * 10000 ) ? 0 : ypos [ i ] + 14 ;
447- }
448- }
449- let anim = setInterval ( run , 85 ) ;
450- window . addEventListener ( 'resize' , ( ) => {
451- clearInterval ( anim ) ;
452- w = canvas . width = innerWidth ;
453- h = canvas . height = innerHeight ;
454- anim = setInterval ( run , 85 ) ;
455- } ) ;
456- </ script >
457- </ body >
458- </ html >
0 commit comments