From 19fe6d30f43cb6c2978066177401b3ee0857e466 Mon Sep 17 00:00:00 2001 From: ssbg04 Date: Fri, 5 Jun 2026 18:47:00 +0800 Subject: [PATCH] secured privacy --- .env.example | 14 +- .gitignore | 1 + assets/css/style.css | 1818 ++++++++++++++++++++++++------------------ blog.php | 239 +++--- certifications.php | 262 +++--- config/db.php | 51 +- index.php | 370 +++++---- projects.php | 82 +- views/projects.php | 67 +- views/tprojects.php | 67 +- 10 files changed, 1666 insertions(+), 1305 deletions(-) diff --git a/.env.example b/.env.example index 8969c9e..1d1cfeb 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,15 @@ -# Email Configuration -CONTACT_EMAIL=your-email@gmail.com +# Database Configuration +DB_HOST=your-database-host +DB_USER=your-database-username +DB_PASS=your-database-password +DB_NAME=your-database-name # Google reCAPTCHA -RECAPTCHA_SITE_KEY=your-site-key-here -RECAPTCHA_SECRET_KEY=your-secret-key-here +RECAPTCHA_SITE_KEY=your-recaptcha-site-key-here +RECAPTCHA_SECRET_KEY=your-recaptcha-secret-key-here + +# Contact Email (used in FormSubmit action) +CONTACT_EMAIL=your-email@gmail.com # Rate Limiting (requests per hour) RATE_LIMIT=10 diff --git a/.gitignore b/.gitignore index 3f02504..b9e8365 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ if0_41132991_portfolio.sql googl* +.env diff --git a/assets/css/style.css b/assets/css/style.css index b8445d3..420b3b0 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1,755 +1,1063 @@ -/* --- Variables & Configuration --- */ -:root { - --bg: #0a0a0a; - --card-bg: #161616; - --text-main: #ededed; - --text-muted: #a1a1a1; - --accent: #3b82f6; - --border: #2a2a2a; - /* NEW: Dark Mode Transparent Background */ - --glass-bg: rgba(10, 10, 10, 0.8); -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} -html { - scroll-behavior: smooth; -} -/* 1. Set the width of the scrollbar */ -html::-webkit-scrollbar { - width: 8px; /* Thin and sleek */ -} - -/* 2. The background of the scrollbar (Track) */ -html::-webkit-scrollbar-track { - background: var(--bg); /* Matches your dark background */ -} - -/* 3. The moving part of the scrollbar (Thumb) */ -html::-webkit-scrollbar-thumb { - background-color: #333; /* Dark Grey */ - border-radius: 4px; /* Rounded edges */ -} - -/* 4. Hover effect */ -html::-webkit-scrollbar-thumb:hover { - background-color: var(--accent); /* Turns Blue when hovered */ -} - -.site-wrapper { - background-color: var(--bg); - color: var(--text-main); - min-height: 100vh; - width: 100%; - padding: 0 5%; - transition: - background-color 0.3s ease, - color 0.3s ease; - display: flex; - flex-direction: column; -} - -/* --- Dark/Light Logic --- */ -.toggle-checkbox { - display: none; -} - -.toggle-checkbox:not(:checked) ~ .site-wrapper { - --bg: #ffffff; - --card-bg: #f3f4f6; - --text-main: #111827; - --text-muted: #4b5563; - --accent: #2563eb; - --border: #e5e7eb; - /* NEW: Light Mode Transparent Background */ - --glass-bg: rgba(255, 255, 255, 0.8); -} - -.mode-btn { - cursor: pointer; - margin-left: 20px; - font-size: 1.2rem; - user-select: none; -} -.toggle-checkbox:checked ~ .site-wrapper .icon-sun { - display: none; -} -.toggle-checkbox:checked ~ .site-wrapper .icon-moon { - display: inline; -} -.toggle-checkbox:not(:checked) ~ .site-wrapper .icon-moon { - display: none; -} -.toggle-checkbox:not(:checked) ~ .site-wrapper .icon-sun { - display: inline; -} - -/* --- Global Styles --- */ -body { - font-family: "Inter", sans-serif; - line-height: 1.6; - margin: 0; -} - -/* --- UPDATED: Sticky Nav --- */ -nav { - display: flex; - justify-content: space-between; - align-items: center; - padding: 20px 0; /* Slightly reduced for a sleeker sticky bar */ - max-width: 1000px; - width: 100%; - margin: 0 auto; - - /* Sticky properties */ - position: sticky; - top: 0; - z-index: 1000; - - /* Theme-based Glass Background */ - background: var(--glass-bg); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-bottom: 1px solid var(--border); /* Adds a nice separation line when scrolling */ -} - -.logo { - font-weight: 800; - font-size: 1.5rem; - letter-spacing: -1px; -} - -/* Desktop: Show links normally */ -.nav-links { - display: flex; - align-items: center; - gap: 24px; -} - -.nav-links a { - color: var(--text-muted); - text-decoration: none; - font-size: 0.95rem; - transition: color 0.2s; -} -.nav-links a:hover { - color: var(--accent); -} - -/* Hamburger Icon (Hidden on Desktop) */ -.hamburger { - display: none; - cursor: pointer; -} - -.bar { - display: block; - width: 25px; - height: 3px; - margin: 5px auto; - transition: all 0.3s ease-in-out; - background-color: var(--text-main); /* Matches theme color */ -} - -/* --- Mobile Menu (Max-width 768px) --- */ -@media (max-width: 768px) { - /* Show Hamburger */ - .hamburger { - display: block; - } - - /* Animate Hamburger to X when active */ - .hamburger.active .bar:nth-child(2) { - opacity: 0; - } - .hamburger.active .bar:nth-child(1) { - transform: translateY(8px) rotate(45deg); - } - .hamburger.active .bar:nth-child(3) { - transform: translateY(-8px) rotate(-45deg); - } - - /* --- UPDATED: Mobile Dropdown --- */ - .nav-links { - position: absolute; /* Attaches exactly to the sticky nav */ - left: -100%; /* Hide off-screen */ - top: 100%; /* Sits exactly below the navbar */ - flex-direction: column; - width: 100%; - text-align: center; - transition: 0.3s ease-in-out; - box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05); - border-bottom: 1px solid var(--border); - padding: 20px 0; - gap: 20px; - - /* Theme-Based Transparent Background */ - background: var(--glass-bg); - backdrop-filter: blur(15px); - -webkit-backdrop-filter: blur(15px); - } - - /* Show Links when active */ - .nav-links.active { - left: 0; /* Slide in */ - } - - .nav-links a { - color: var(--text-main); /* Automatically matches dark/light mode */ - font-size: 1.2rem; - display: block; - padding: 10px; - } -} - -/* --- Hero --- */ -.hero { - display: flex; - align-items: center; - justify-content: space-between; - padding: 80px 0; - gap: 40px; - max-width: 1000px; - margin: 0 auto; -} - -.hero-text { - flex: 1; -} -.greeting { - color: var(--accent); - font-weight: 600; - display: block; - margin-bottom: 10px; -} -h1 { - font-size: clamp(2.5rem, 5vw, 3.5rem); - line-height: 1.1; - font-weight: 800; - margin-bottom: 20px; - letter-spacing: -1px; -} -.subtitle { - color: var(--text-muted); - font-size: 1.1rem; - margin-bottom: 30px; -} -.highlight { - color: var(--accent); -} - -.hero-btns { - display: flex; - gap: 15px; -} - -.btn { - text-decoration: none; - padding: 12px 24px; - border-radius: 6px; - font-weight: 600; - transition: transform 0.2s; -} -.btn.primary { - background: var(--accent); - color: white; - border: 1px solid var(--accent); -} -.btn.secondary { - background: transparent; - color: var(--text-main); - border: 1px solid var(--border); -} -.btn:hover { - transform: translateY(-2px); -} - -.hero-img-container { - position: relative; - width: 250px; - height: 250px; - flex-shrink: 0; -} - -.profile-pic { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - object-fit: cover; - border-radius: 20px; - border: 1px solid var(--border); - transition: opacity 0.4s ease-in-out; - opacity: 0; /* Hide all images by default */ -} -/* ----------------------------------- - DARK MODE (Default State) ------------------------------------ */ -.img-night-normal { - opacity: 1; - z-index: 2; - cursor: none; -} /* Show Night Normal */ - -/* On Hover: Fade in Night Hover, Fade out Night Normal */ -.hero-img-container:hover .img-night-hover { - opacity: 1; - z-index: 3; - cursor: none; -} -.hero-img-container:hover .img-night-normal { - opacity: 0; - cursor: none; -} - -/* ----------------------------------- - LIGHT MODE (When Checkbox is unchecked) ------------------------------------ */ -/* 1. Hide the Dark Mode images entirely */ -.toggle-checkbox:not(:checked) ~ .site-wrapper .img-night-normal, -.toggle-checkbox:not(:checked) ~ .site-wrapper .img-night-hover { - opacity: 0 !important; -} - -/* 2. Show Day Normal */ -.toggle-checkbox:not(:checked) ~ .site-wrapper .img-day-normal { - opacity: 1; - z-index: 2; - cursor: none; -} - -/* 3. On Hover: Fade in Day Hover, Fade out Day Normal */ -.toggle-checkbox:not(:checked) - ~ .site-wrapper - .hero-img-container:hover - .img-day-hover { - opacity: 1; - z-index: 3; - cursor: none; -} -.toggle-checkbox:not(:checked) - ~ .site-wrapper - .hero-img-container:hover - .img-day-normal { - opacity: 0; - cursor: none; -} - -.glow-effect { - position: absolute; - top: 20px; - left: 20px; - width: 100%; - height: 100%; - background: var(--accent); - border-radius: 20px; - opacity: 0.2; - z-index: 1; - filter: blur(20px); -} - -/* --- Common Section Styles --- */ -.section-pad { - padding: 80px 0; - max-width: 1000px; - margin: 0 auto; - width: 100%; -} -.section-title { - font-size: 2rem; - margin-bottom: 40px; -} - -.about-content { - display: grid; - grid-template-columns: 3fr 2fr; - gap: 50px; -} -.about-text p { - margin-bottom: 15px; - color: var(--text-muted); -} -.tags span { - background: var(--card-bg); - border: 1px solid var(--border); - padding: 6px 14px; - border-radius: 50px; - font-size: 0.85rem; - display: inline-block; - margin: 5px 0; -} - -/* --- Projects (Clickable) --- */ -.project-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - gap: 30px; -} - -/* Wrapper is now an anchor tag */ -a.project-card { - text-decoration: none; /* Remove underline */ - color: inherit; /* Keep text color */ - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 12px; - overflow: hidden; - display: block; - transition: - transform 0.3s, - border-color 0.3s; -} - -a.project-card:hover { - transform: translateY(-5px); - border-color: var(--accent); -} - -.card-img img { - width: 100%; - height: 200px; - object-fit: cover; -} -.card-content { - padding: 25px; -} - -/* Card Header for Arrow Icon */ -.card-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 10px; -} -.arrow-icon { - font-size: 1.2rem; - opacity: 0; - transform: translateX(-10px); - transition: 0.3s; - color: var(--accent); -} -a.project-card:hover .arrow-icon { - opacity: 1; - transform: translateX(0); -} - -.card-content p { - color: var(--text-muted); - font-size: 0.9rem; - margin-bottom: 15px; -} -.stack-icons { - font-size: 0.8rem; - color: var(--accent); - font-weight: 600; -} - -/* --- Certificates Section --- */ -.cert-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - gap: 20px; -} - -.cert-card { - background: var(--card-bg); - border: 1px solid var(--border); - border-radius: 12px; - padding: 25px; - display: flex; - align-items: center; - gap: 20px; - transition: 0.3s; -} - -.cert-card:hover { - border-color: var(--accent); -} - -.cert-icon { - font-size: 2rem; -} -.cert-info h3 { - font-size: 1rem; - margin-bottom: 5px; -} -.issuer { - color: var(--accent); - font-size: 0.85rem; - font-weight: 600; -} -.date { - display: block; - font-size: 0.75rem; - color: var(--text-muted); - margin-top: 5px; -} - -/* --- Blog Section --- */ -.blog-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - gap: 30px; -} - -.blog-card { - background: var(--card-bg); - border: 1px solid var(--border); - padding: 30px; - border-radius: 12px; - display: flex; - flex-direction: column; - transition: - transform 0.3s, - border-color 0.3s; - height: 100%; -} - -.blog-card:hover { - transform: translateY(-5px); - border-color: var(--accent); -} - -.blog-meta { - display: flex; - justify-content: space-between; - font-size: 0.8rem; - color: var(--text-muted); - margin-bottom: 15px; - text-transform: uppercase; - letter-spacing: 1px; -} - -.blog-tag { - color: var(--accent); - font-weight: 600; -} - -.blog-title { - font-size: 1.2rem; - margin-bottom: 10px; - line-height: 1.4; -} - -.blog-excerpt { - color: var(--text-muted); - font-size: 0.95rem; - margin-bottom: 20px; - flex-grow: 1; /* Pushes the link to the bottom */ -} - -.read-more { - text-decoration: none; - color: var(--accent); - font-weight: 600; - font-size: 0.9rem; - transition: opacity 0.2s; -} - -.read-more:hover { - opacity: 0.8; -} - -/* --- View All Button Wrapper --- */ -.view-all-container { - display: flex; - justify-content: center; - margin-top: 40px; -} - -/* --- Social Media Buttons --- */ -.social-links { - display: flex; - justify-content: center; - gap: 20px; - margin-bottom: 40px; -} - -.social-btn { - display: flex; - align-items: center; - justify-content: center; - width: 50px; - height: 50px; - border-radius: 50%; /* Makes them round */ - background: var(--card-bg); - border: 1px solid var(--border); - color: var(--text-muted); - transition: all 0.3s ease; -} - -.social-btn svg { - width: 22px; - height: 22px; -} - -/* Hover Effect: Glows with the accent color */ -.social-btn:hover { - border-color: var(--accent); - color: var(--accent); - transform: translateY(-3px); - box-shadow: 0 5px 15px var(--glow); -} - -/* --- Contact & Footer --- */ -.contact-container { - max-width: 600px; - margin: 0 auto; - text-align: center; -} -.contact-container p { - color: var(--text-muted); - margin-bottom: 30px; -} -.email-form { - display: flex; - flex-direction: column; - gap: 15px; -} -input, -textarea { - width: 100%; - padding: 15px; - background: var(--card-bg); - border: 1px solid var(--border); - color: var(--text-main); - border-radius: 8px; - font-family: inherit; -} -.full-width { - width: 100%; - cursor: pointer; -} - -footer { - padding: 50px 0; - text-align: center; - color: var(--text-muted); /* Maintained your font fix */ - font-size: 0.9rem; - border-top: 1px solid var(--border); - margin-top: auto; -} - -/* --- Back to Top Button --- */ -#back-to-top { - position: fixed; - bottom: 30px; - right: 30px; - width: 50px; - height: 50px; - background-color: var(--accent); - color: white; /* Arrow color */ - border-radius: 50%; - display: flex; - justify-content: center; - align-items: center; - text-decoration: none; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); - z-index: 1000; - - /* Hidden state */ - opacity: 0; - visibility: hidden; - transform: translateY(20px); - transition: all 0.3s ease; -} - -/* Visible state (added by JS) */ -#back-to-top.show { - opacity: 1; - visibility: visible; - transform: translateY(0); -} - -#back-to-top:hover { - background-color: var(--text-main); /* Inverts color on hover */ - color: var(--bg); - transform: translateY(-5px); /* Lift effect */ -} - -/* Mobile Adjustment */ -@media (max-width: 600px) { - #back-to-top { - bottom: 20px; - right: 20px; - width: 45px; - height: 45px; - } -} - -/* Mobile Content Layout */ -/* --- Mobile Menu (Max-width 768px) --- */ -@media (max-width: 768px) { - /* Show Hamburger */ - .hamburger { - display: block; - } - - /* Animate Hamburger to X when active */ - .hamburger.active .bar:nth-child(2) { - opacity: 0; - } - .hamburger.active .bar:nth-child(1) { - transform: translateY(8px) rotate(45deg); - } - .hamburger.active .bar:nth-child(3) { - transform: translateY(-8px) rotate(-45deg); - } - - /* --- FIXED: Mobile Dropdown --- */ - .nav-links { - position: absolute; - top: 100%; /* Sits exactly below the navbar */ - left: -120vw; /* Hide completely off-screen to the left */ - flex-direction: column; - - /* Force it to fill the ENTIRE screen width */ - width: 100vw; - - text-align: center; - transition: left 0.4s ease-in-out; /* Smooth sliding animation */ - box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05); - border-bottom: 1px solid var(--border); - padding: 30px 0; - gap: 20px; - - /* Theme-Based Transparent Background */ - background: var(--glass-bg); - backdrop-filter: blur(15px); - -webkit-backdrop-filter: blur(15px); - } - - /* Show Links when active */ - .nav-links.active { - /* This offsets the 5% padding of your site-wrapper - so the menu perfectly touches the left edge of the phone screen */ - left: -5vw; - } - - .nav-links a { - color: var(--text-main); - font-size: 1.2rem; - display: block; - padding: 10px; - } - - /* Mobile Content Layout */ - .hero { - flex-direction: column-reverse; - text-align: center; - } - .hero-btns { - justify-content: center; - } - .about-content { - grid-template-columns: 1fr; - } - .cert-card { - flex-direction: column; - text-align: center; - } -} +/* ===================================================== + DESIGN SYSTEM — Premium Portfolio v2 + ===================================================== */ + +/* --- Google Fonts --- */ +@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800;900&family=Inter:wght@300;400;500;600&display=swap'); + +/* Prevent horizontal scroll on all viewports */ +html, body { overflow-x: hidden; max-width: 100%; } + +/* --- CSS Variables (Dark Mode Default) --- */ +:root { + /* Backgrounds */ + --bg: #050814; + --bg-secondary: #0d1225; + --card-bg: rgba(255, 255, 255, 0.035); + --card-border: rgba(255, 255, 255, 0.08); + --glass-bg: rgba(5, 8, 20, 0.75); + + /* Text */ + --text-main: #f0f4ff; + --text-muted: #8892b0; + --text-subtle: #4a5578; + + /* Accents */ + --accent: #7c3aed; + --accent-2: #6366f1; + --accent-glow: rgba(124, 58, 237, 0.4); + --grad-1: #7c3aed; + --grad-2: #6366f1; + --grad-3: #06b6d4; + + /* Borders */ + --border: rgba(255, 255, 255, 0.08); + --border-hover: rgba(124, 58, 237, 0.5); + + /* Shadows */ + --shadow-card: 0 4px 32px rgba(0, 0, 0, 0.4); + --shadow-glow: 0 0 40px rgba(124, 58, 237, 0.25); + + /* Transitions */ + --ease: cubic-bezier(0.4, 0, 0.2, 1); +} + +/* --- Light Mode Overrides --- */ +.toggle-checkbox:not(:checked) ~ .site-wrapper { + --bg: #f8f7ff; + --bg-secondary: #ede9fe; + --card-bg: rgba(255, 255, 255, 0.7); + --card-border: rgba(124, 58, 237, 0.15); + --glass-bg: rgba(248, 247, 255, 0.85); + --text-main: #1e1b4b; + --text-muted: #5b5698; + --text-subtle: #9ca3af; + --accent: #7c3aed; + --accent-glow: rgba(124, 58, 237, 0.2); + --border: rgba(124, 58, 237, 0.12); + --border-hover: rgba(124, 58, 237, 0.45); + --shadow-card: 0 4px 24px rgba(124, 58, 237, 0.1); + --shadow-glow: 0 0 40px rgba(124, 58, 237, 0.15); +} + +/* ===================================================== + RESET & BASE + ===================================================== */ +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + scroll-behavior: smooth; + font-size: 16px; +} + +/* Custom Scrollbar */ +html::-webkit-scrollbar { width: 6px; } +html::-webkit-scrollbar-track { background: var(--bg); } +html::-webkit-scrollbar-thumb { + background: linear-gradient(to bottom, var(--grad-1), var(--grad-2)); + border-radius: 3px; +} +html::-webkit-scrollbar-thumb:hover { background: var(--grad-1); } + +body { + font-family: 'Inter', sans-serif; + line-height: 1.6; + background: var(--bg); + color: var(--text-main); + overflow-x: hidden; +} + +/* Hidden toggle */ +.toggle-checkbox { display: none; } + +/* ===================================================== + ANIMATED MESH BACKGROUND + ===================================================== */ +.mesh-bg { + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; + overflow: hidden; +} + +.orb { + position: absolute; + border-radius: 50%; + filter: blur(100px); + opacity: 0.15; + animation: float-orb 20s ease-in-out infinite; +} + +.orb-1 { + width: 600px; height: 600px; + background: radial-gradient(circle, #7c3aed, transparent 70%); + top: -200px; left: -200px; + animation-duration: 25s; + animation-delay: 0s; +} + +.orb-2 { + width: 500px; height: 500px; + background: radial-gradient(circle, #6366f1, transparent 70%); + top: 30%; right: -150px; + animation-duration: 20s; + animation-delay: -8s; + opacity: 0.12; +} + +.orb-3 { + width: 400px; height: 400px; + background: radial-gradient(circle, #06b6d4, transparent 70%); + bottom: 10%; left: 20%; + animation-duration: 30s; + animation-delay: -15s; + opacity: 0.08; +} + +@keyframes float-orb { + 0%, 100% { transform: translate(0, 0) scale(1); } + 33% { transform: translate(40px, -60px) scale(1.08); } + 66% { transform: translate(-30px, 40px) scale(0.95); } +} + +/* Light mode: softer orbs */ +.toggle-checkbox:not(:checked) ~ .mesh-bg .orb { opacity: 0.07; } + +/* ===================================================== + SITE WRAPPER + ===================================================== */ +.site-wrapper { + position: relative; + z-index: 1; + min-height: 100vh; + width: 100%; + display: flex; + flex-direction: column; + transition: background-color 0.4s var(--ease), color 0.4s var(--ease); +} + +/* ===================================================== + NAVIGATION + ===================================================== */ +nav { + position: sticky; + top: 0; + z-index: 1000; + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px 5%; + width: 100%; + background: var(--glass-bg); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-bottom: 1px solid var(--border); + transition: background 0.3s var(--ease), border-color 0.3s var(--ease); +} + +.logo { + font-family: 'Outfit', sans-serif; + font-weight: 900; + font-size: 1.6rem; + letter-spacing: -2px; + background: linear-gradient(135deg, var(--grad-1), var(--grad-2), var(--grad-3)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.nav-links { + display: flex; + align-items: center; + gap: 8px; +} + +.nav-links a { + color: var(--text-muted); + text-decoration: none; + font-size: 0.9rem; + font-weight: 500; + padding: 7px 14px; + border-radius: 8px; + transition: color 0.2s var(--ease), background 0.2s var(--ease); + letter-spacing: 0.02em; +} + +.nav-links a:hover { + color: var(--text-main); + background: var(--card-bg); +} + +.nav-links a.active-nav { + color: var(--accent); + background: rgba(124, 58, 237, 0.1); +} + +/* Theme Toggle */ +.mode-btn { + cursor: pointer; + margin-left: 8px; + width: 38px; + height: 38px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 10px; + background: var(--card-bg); + border: 1px solid var(--border); + font-size: 1.1rem; + transition: background 0.2s, border-color 0.2s, transform 0.2s; + user-select: none; +} +.mode-btn:hover { border-color: var(--border-hover); transform: scale(1.05); } + +.toggle-checkbox:checked ~ .site-wrapper .icon-sun { display: none; } +.toggle-checkbox:checked ~ .site-wrapper .icon-moon { display: flex; } +.toggle-checkbox:not(:checked) ~ .site-wrapper .icon-moon { display: none; } +.toggle-checkbox:not(:checked) ~ .site-wrapper .icon-sun { display: flex; } + +/* Hamburger */ +.hamburger { + display: none; + cursor: pointer; + flex-direction: column; + gap: 5px; + padding: 4px; +} +.bar { + display: block; + width: 24px; + height: 2px; + background: var(--text-main); + border-radius: 2px; + transition: all 0.3s var(--ease); +} +.hamburger.active .bar:nth-child(1) { transform: translateY(7px) rotate(45deg); } +.hamburger.active .bar:nth-child(2) { opacity: 0; transform: scaleX(0); } +.hamburger.active .bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } + +/* ===================================================== + SCROLL REVEAL + ===================================================== */ +.reveal { + opacity: 0; + transform: translateY(40px); + transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); +} +.reveal.active { + opacity: 1; + transform: translateY(0); +} +.reveal-delay-1 { transition-delay: 0.1s; } +.reveal-delay-2 { transition-delay: 0.2s; } +.reveal-delay-3 { transition-delay: 0.3s; } +.reveal-delay-4 { transition-delay: 0.4s; } + +/* ===================================================== + HERO SECTION + ===================================================== */ +.hero { + display: flex; + align-items: center; + justify-content: space-between; + gap: 60px; + padding: clamp(60px, 10vw, 120px) 5% clamp(50px, 8vw, 100px); + max-width: 1100px; + margin: 0 auto; + width: 100%; + box-sizing: border-box; +} + +.hero-text { flex: 1; } + +.hero-badge { + display: inline-flex; + align-items: center; + gap: 8px; + background: rgba(124, 58, 237, 0.1); + border: 1px solid rgba(124, 58, 237, 0.3); + border-radius: 50px; + padding: 6px 16px; + font-size: 0.8rem; + font-weight: 600; + color: var(--accent-2); + letter-spacing: 0.05em; + text-transform: uppercase; + margin-bottom: 20px; +} +.hero-badge .dot { + width: 7px; height: 7px; + background: #22c55e; + border-radius: 50%; + animation: pulse-dot 2s ease-in-out infinite; +} +@keyframes pulse-dot { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.6; transform: scale(0.8); } +} + +h1 { + font-family: 'Outfit', sans-serif; + font-size: clamp(2.8rem, 5.5vw, 4rem); + font-weight: 900; + line-height: 1.05; + letter-spacing: -2px; + margin-bottom: 20px; + color: var(--text-main); +} + +.highlight { + background: linear-gradient(135deg, var(--grad-1) 0%, var(--grad-2) 50%, var(--grad-3) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.subtitle { + color: var(--text-muted); + font-size: clamp(0.95rem, 2vw, 1.1rem); + margin-bottom: 30px; + max-width: 500px; + line-height: 1.7; +} + +.hero-btns { + display: flex; + gap: 14px; + flex-wrap: wrap; +} + +/* ===================================================== + BUTTONS + ===================================================== */ +.btn { + display: inline-flex; + align-items: center; + gap: 8px; + text-decoration: none; + padding: 13px 26px; + border-radius: 10px; + font-weight: 600; + font-size: 0.95rem; + transition: all 0.25s var(--ease); + border: none; + cursor: pointer; + font-family: inherit; + letter-spacing: 0.01em; +} + +.btn.primary { + background: linear-gradient(135deg, var(--grad-1), var(--grad-2)); + color: #fff; + box-shadow: 0 4px 20px rgba(124, 58, 237, 0.4); +} +.btn.primary:hover { + transform: translateY(-2px); + box-shadow: 0 8px 30px rgba(124, 58, 237, 0.5); +} + +.btn.secondary { + background: var(--card-bg); + color: var(--text-main); + border: 1px solid var(--border); + backdrop-filter: blur(10px); +} +.btn.secondary:hover { + transform: translateY(-2px); + border-color: var(--border-hover); + background: rgba(124, 58, 237, 0.08); +} + +.btn.full-width { width: 100%; justify-content: center; } + +/* ===================================================== + HERO PROFILE IMAGE + ===================================================== */ +.hero-img-container { + position: relative; + width: 280px; + height: 280px; + flex-shrink: 0; +} + +.img-ring { + position: absolute; + inset: -12px; + border-radius: 28px; + background: linear-gradient(135deg, var(--grad-1), var(--grad-2), var(--grad-3)); + z-index: 0; + opacity: 0.6; + animation: spin-ring 8s linear infinite; +} +@keyframes spin-ring { + 0% { filter: blur(4px) hue-rotate(0deg); } + 100% { filter: blur(4px) hue-rotate(360deg); } +} + +.profile-pic { + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + object-fit: cover; + border-radius: 20px; + border: 2px solid var(--border); + z-index: 2; + transition: opacity 0.4s var(--ease); + opacity: 0; +} + +/* Dark mode (default) image states */ +.img-night-normal { opacity: 1; z-index: 3; cursor: default; } +.hero-img-container:hover .img-night-hover { opacity: 1; z-index: 4; cursor: default; } +.hero-img-container:hover .img-night-normal { opacity: 0; } + +/* Light mode image states */ +.toggle-checkbox:not(:checked) ~ .site-wrapper .img-night-normal, +.toggle-checkbox:not(:checked) ~ .site-wrapper .img-night-hover { opacity: 0 !important; } +.toggle-checkbox:not(:checked) ~ .site-wrapper .img-day-normal { opacity: 1; z-index: 3; cursor: default; } +.toggle-checkbox:not(:checked) ~ .site-wrapper .hero-img-container:hover .img-day-hover { opacity: 1; z-index: 4; cursor: default; } +.toggle-checkbox:not(:checked) ~ .site-wrapper .hero-img-container:hover .img-day-normal { opacity: 0; } + +.glow-effect { + position: absolute; + inset: 0; + background: var(--accent); + border-radius: 20px; + opacity: 0.12; + z-index: 1; + filter: blur(30px); + transform: translate(10px, 10px); + transition: opacity 0.4s; +} +.hero-img-container:hover .glow-effect { opacity: 0.2; } + +/* ===================================================== + SECTION COMMONS + ===================================================== */ +.section-pad { + padding: clamp(60px, 8vw, 100px) 5%; + max-width: 1100px; + margin: 0 auto; + width: 100%; + box-sizing: border-box; +} + +.section-header { + margin-bottom: 60px; +} + +.section-label { + display: inline-block; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.15em; + color: var(--accent-2); + margin-bottom: 12px; +} + +.section-title { + font-family: 'Outfit', sans-serif; + font-size: clamp(1.8rem, 3vw, 2.5rem); + font-weight: 800; + letter-spacing: -1px; + background: linear-gradient(135deg, var(--text-main) 60%, var(--text-muted)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* ===================================================== + ABOUT SECTION + ===================================================== */ +.about-content { + display: grid; + grid-template-columns: 3fr 2fr; + gap: 60px; + align-items: start; +} + +.about-text p { + color: var(--text-muted); + margin-bottom: 18px; + font-size: 1.05rem; + line-height: 1.8; +} +.about-text p strong { color: var(--text-main); font-weight: 600; } + +.tech-stack h3 { + font-family: 'Outfit', sans-serif; + font-size: 1rem; + font-weight: 700; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.1em; + margin-bottom: 16px; +} + +.tags { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.tags span { + background: var(--card-bg); + border: 1px solid var(--border); + padding: 7px 16px; + border-radius: 50px; + font-size: 0.82rem; + font-weight: 600; + color: var(--text-muted); + letter-spacing: 0.02em; + transition: all 0.2s var(--ease); + backdrop-filter: blur(10px); +} +.tags span:hover { + border-color: var(--border-hover); + color: var(--accent-2); + background: rgba(124, 58, 237, 0.08); + transform: translateY(-1px); +} + +/* ===================================================== + STATS ROW + ===================================================== */ +.stats-row { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; + margin-top: 50px; + padding-top: 50px; + border-top: 1px solid var(--border); +} + +.stat-item { + text-align: center; +} +.stat-number { + font-family: 'Outfit', sans-serif; + font-size: 2.2rem; + font-weight: 900; + background: linear-gradient(135deg, var(--grad-1), var(--grad-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + line-height: 1; + margin-bottom: 6px; +} +.stat-label { + font-size: 0.8rem; + color: var(--text-muted); + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.08em; +} + +/* ===================================================== + PROJECT CARDS + ===================================================== */ +.project-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); + gap: 24px; +} + +a.project-card { + text-decoration: none; + color: inherit; + display: block; + background: var(--card-bg); + border: 1px solid var(--border); + border-radius: 16px; + overflow: hidden; + transition: transform 0.3s var(--ease), border-color 0.3s var(--ease), box-shadow 0.3s var(--ease); + backdrop-filter: blur(10px); +} +a.project-card:hover { + transform: translateY(-6px); + border-color: var(--border-hover); + box-shadow: var(--shadow-glow); +} + +.card-img { + position: relative; + height: 200px; + overflow: hidden; +} +.card-img img { + width: 100%; height: 100%; + object-fit: cover; + transition: transform 0.5s var(--ease); +} +a.project-card:hover .card-img img { transform: scale(1.05); } + +.card-img-overlay { + position: absolute; + inset: 0; + background: linear-gradient(to bottom, transparent 40%, rgba(5, 8, 20, 0.8)); + transition: opacity 0.3s; +} + +.card-content { padding: 24px; } + +.card-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 10px; + gap: 10px; +} +.card-header h3 { + font-family: 'Outfit', sans-serif; + font-size: 1.15rem; + font-weight: 700; + color: var(--text-main); + line-height: 1.3; +} +.arrow-icon { + font-size: 1.1rem; + opacity: 0; + transform: translate(-6px, 6px); + transition: all 0.3s var(--ease); + color: var(--accent-2); + flex-shrink: 0; +} +a.project-card:hover .arrow-icon { + opacity: 1; + transform: translate(0, 0); +} + +.card-content p { + color: var(--text-muted); + font-size: 0.88rem; + margin-bottom: 18px; + line-height: 1.7; +} + +.stack-badges { + display: flex; + flex-wrap: wrap; + gap: 6px; +} +.stack-badge { + padding: 4px 10px; + border-radius: 50px; + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.04em; + background: rgba(99, 102, 241, 0.1); + border: 1px solid rgba(99, 102, 241, 0.25); + color: var(--accent-2); +} + +/* ===================================================== + CERTIFICATIONS + ===================================================== */ +.cert-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); + gap: 20px; +} + +.cert-card { + background: var(--card-bg); + border: 1px solid var(--border); + border-radius: 16px; + padding: 28px; + display: flex; + align-items: center; + gap: 20px; + transition: all 0.3s var(--ease); + backdrop-filter: blur(10px); + cursor: default; +} +.cert-card:hover { + border-color: var(--border-hover); + transform: translateY(-3px); + box-shadow: var(--shadow-glow); +} + +.cert-icon { + font-size: 2rem; + width: 56px; + height: 56px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(124, 58, 237, 0.1); + border: 1px solid rgba(124, 58, 237, 0.2); + border-radius: 14px; + flex-shrink: 0; + transition: background 0.3s; +} +.cert-card:hover .cert-icon { background: rgba(124, 58, 237, 0.18); } + +.cert-info h3 { + font-family: 'Outfit', sans-serif; + font-size: 1rem; + font-weight: 700; + margin-bottom: 4px; + color: var(--text-main); +} +.issuer { + color: var(--accent-2); + font-size: 0.82rem; + font-weight: 600; +} +.date { + display: block; + font-size: 0.75rem; + color: var(--text-subtle); + margin-top: 4px; +} + +/* ===================================================== + BLOG CARDS + ===================================================== */ +.blog-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); + gap: 24px; +} + +.blog-card { + background: var(--card-bg); + border: 1px solid var(--border); + padding: 32px; + border-radius: 16px; + display: flex; + flex-direction: column; + transition: all 0.3s var(--ease); + backdrop-filter: blur(10px); +} +.blog-card:hover { + transform: translateY(-5px); + border-color: var(--border-hover); + box-shadow: var(--shadow-glow); +} + +.blog-meta { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 0.75rem; + color: var(--text-subtle); + margin-bottom: 16px; + text-transform: uppercase; + letter-spacing: 0.08em; + font-weight: 600; +} +.blog-tag { + color: var(--accent-2); + background: rgba(99, 102, 241, 0.1); + border: 1px solid rgba(99, 102, 241, 0.2); + padding: 3px 10px; + border-radius: 50px; +} + +.blog-title { + font-family: 'Outfit', sans-serif; + font-size: 1.15rem; + font-weight: 700; + margin-bottom: 12px; + line-height: 1.4; + color: var(--text-main); +} + +.blog-excerpt { + color: var(--text-muted); + font-size: 0.9rem; + margin-bottom: 24px; + flex-grow: 1; + line-height: 1.7; +} + +.read-more { + text-decoration: none; + color: var(--accent-2); + font-weight: 600; + font-size: 0.85rem; + display: inline-flex; + align-items: center; + gap: 6px; + transition: gap 0.2s var(--ease), opacity 0.2s; +} +.read-more:hover { gap: 10px; opacity: 0.8; } + +/* ===================================================== + VIEW ALL BUTTON + ===================================================== */ +.view-all-container { + display: flex; + justify-content: center; + margin-top: 50px; +} + +/* ===================================================== + CONTACT SECTION + ===================================================== */ +.contact-container { + max-width: 620px; + margin: 0 auto; + text-align: center; +} +.contact-container > p { + color: var(--text-muted); + margin-bottom: 40px; + font-size: 1.05rem; + line-height: 1.8; +} + +.social-links { + display: flex; + justify-content: center; + gap: 14px; + margin-bottom: 50px; +} + +.social-btn { + display: flex; + align-items: center; + justify-content: center; + width: 50px; + height: 50px; + border-radius: 13px; + background: var(--card-bg); + border: 1px solid var(--border); + color: var(--text-muted); + transition: all 0.25s var(--ease); + text-decoration: none; +} +.social-btn svg { width: 20px; height: 20px; } +.social-btn:hover { + border-color: var(--border-hover); + color: var(--accent-2); + transform: translateY(-3px); + background: rgba(124, 58, 237, 0.08); + box-shadow: 0 4px 20px rgba(124, 58, 237, 0.2); +} + +.email-form { + display: flex; + flex-direction: column; + gap: 14px; + text-align: left; +} + +input, textarea { + width: 100%; + padding: 14px 18px; + background: var(--card-bg); + border: 1px solid var(--border); + color: var(--text-main); + border-radius: 12px; + font-family: inherit; + font-size: 0.95rem; + transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), background 0.25s; + backdrop-filter: blur(10px); + outline: none; +} +input::placeholder, textarea::placeholder { color: var(--text-subtle); } +input:focus, textarea:focus { + border-color: var(--border-hover); + box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.15); + background: rgba(124, 58, 237, 0.03); +} + +/* reCAPTCHA centering */ +.g-recaptcha { display: flex; justify-content: center; } + +/* ===================================================== + FOOTER + ===================================================== */ +footer { + padding: 50px 5%; + text-align: center; + color: var(--text-subtle); + font-size: 0.85rem; + border-top: 1px solid var(--border); + margin-top: auto; +} + +/* ===================================================== + BACK TO TOP + ===================================================== */ +#back-to-top { + position: fixed; + bottom: 30px; + right: 30px; + width: 48px; + height: 48px; + background: linear-gradient(135deg, var(--grad-1), var(--grad-2)); + color: white; + border-radius: 13px; + display: flex; + justify-content: center; + align-items: center; + text-decoration: none; + box-shadow: 0 4px 20px rgba(124, 58, 237, 0.4); + z-index: 999; + opacity: 0; + visibility: hidden; + transform: translateY(20px); + transition: all 0.3s var(--ease); +} +#back-to-top.show { + opacity: 1; + visibility: visible; + transform: translateY(0); +} +#back-to-top:hover { + transform: translateY(-4px); + box-shadow: 0 8px 30px rgba(124, 58, 237, 0.5); +} + +/* ===================================================== + PAGE HERO (Sub-pages) + ===================================================== */ +.page-hero { + padding: clamp(50px, 8vw, 80px) 5% clamp(40px, 6vw, 60px); + max-width: 1100px; + margin: 0 auto; + width: 100%; + box-sizing: border-box; +} +.page-hero h1 { font-size: clamp(1.8rem, 5vw, 3rem); margin-bottom: 14px; } +.page-hero .subtitle { max-width: 500px; } + +/* ===================================================== + DIVIDER + ===================================================== */ +.section-divider { + height: 1px; + background: linear-gradient(to right, transparent, var(--border), transparent); + margin: 0 5%; +} + +/* ===================================================== + RESPONSIVE — TABLET (≤ 900px) + ===================================================== */ +@media (max-width: 900px) { + .hero { gap: 40px; } + .hero-img-container { width: 220px; height: 220px; } + .about-content { grid-template-columns: 1fr; gap: 40px; } + .stats-row { grid-template-columns: repeat(3, 1fr); } +} + +/* ===================================================== + RESPONSIVE — MOBILE (≤ 768px) + ===================================================== */ +@media (max-width: 768px) { + /* Hamburger visible */ + .hamburger { display: flex; } + + /* Nav desktop links hidden by default on mobile */ + .nav-links { + /* Nav is full viewport width (no container offset), so left: 0 = screen edge */ + position: fixed; + top: 0; + left: -100vw; /* hide completely off-screen */ + width: 100vw; + height: 100vh; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + padding: 40px 20px; + gap: 8px; + background: var(--glass-bg); + backdrop-filter: blur(24px); + -webkit-backdrop-filter: blur(24px); + border-right: 1px solid var(--border); + transition: left 0.35s var(--ease); + z-index: 999; + box-shadow: 4px 0 40px rgba(0, 0, 0, 0.3); + } + /* Slide in from left */ + .nav-links.active { left: 0; } + + .nav-links a { + font-size: 1.2rem; + font-weight: 600; + display: block; + padding: 14px 30px; + width: 100%; + border-radius: 12px; + } + + /* Close button (mode-btn) repositioned */ + .mode-btn { + margin-top: 20px; + margin-left: 0; + } + + /* Hero */ + .hero { + flex-direction: column-reverse; + text-align: center; + gap: 30px; + } + .hero-btns { justify-content: center; flex-wrap: wrap; } + .subtitle { margin: 0 auto 24px; } + .hero-badge { margin: 0 auto 16px; } + .hero-img-container { width: 180px; height: 180px; } + + /* Stats */ + .stats-row { grid-template-columns: repeat(3, 1fr); gap: 8px; } + .stat-number { font-size: 1.6rem; } + .stat-label { font-size: 0.7rem; } + + /* Certs */ + .cert-card { flex-direction: column; text-align: center; } + + /* Project grid single column on very narrow */ + .project-grid, + .blog-grid { + grid-template-columns: 1fr; + } + + /* Back to top smaller */ + #back-to-top { bottom: 16px; right: 16px; width: 42px; height: 42px; } + + /* Section divider */ + .section-divider { margin: 0 4%; } +} + +/* ===================================================== + RESPONSIVE — SMALL MOBILE (≤ 480px) + ===================================================== */ +@media (max-width: 480px) { + h1 { letter-spacing: -1px; } + .stats-row { grid-template-columns: repeat(3, 1fr); } + .cert-grid { grid-template-columns: 1fr; } + .btn { padding: 11px 18px; font-size: 0.9rem; } + .hero-img-container { width: 150px; height: 150px; } + .social-links { gap: 10px; } + .social-btn { width: 44px; height: 44px; } +} diff --git a/blog.php b/blog.php index 2bd7dbc..467313d 100755 --- a/blog.php +++ b/blog.php @@ -1,124 +1,117 @@ - - - - - - Blog | Cris Charles Garcia - - - - - - - - -
- - -
-
-

Writing & Thoughts

-

Tutorials, tech reviews, and updates from my developer journey.

-
-
- -
-
- -
-
- Feb 10, 2026 - React -
-

Understanding Custom Hooks in React

-

Why you should stop copying code and start abstracting logic into reusable hooks.

- Read Article → -
- -
-
- Jan 22, 2026 - DevOps -
-

Why I Switched from XAMPP to Docker

-

Setting up a consistent development environment for PHP and Node.js without the headache.

- Read Article → -
- -
-
- Dec 05, 2025 - Career -
-

My Journey as a BSIT Student

-

Balancing capstone projects, freelance work, and learning new tech stacks in 2026.

- Read Article → -
- -
-
- Nov 15, 2025 - CSS -
-

Dark Mode in 5 Minutes

-

How to implement a pure CSS dark mode toggle without flashing content.

- Read Article → -
- -
-
- -
-

© 2026 Cris Charles Garcia. Crafted in Laguna.

-
-
- - - - - - - + + + + + + + Blog | Cris Charles Garcia + + + + + + + + + +
+ + + +
+ +

Writing & Thoughts

+

Tutorials, tech reviews, and updates from my developer journey.

+
+ +
+ +
+
+ +
+
+ Feb 10, 2026 + React +
+

Understanding Custom Hooks in React

+

Why you should stop copying code and start abstracting logic into reusable hooks. A deep dive into the why and how.

+ Read Article → +
+ +
+
+ Jan 22, 2026 + DevOps +
+

Why I Switched from XAMPP to Docker

+

Setting up a consistent development environment for PHP and Node.js without the headache. Containers changed everything.

+ Read Article → +
+ +
+
+ Dec 05, 2025 + Career +
+

My Journey as a BSIT Student

+

Balancing capstone projects, freelance work, and learning new tech stacks in 2026.

+ Read Article → +
+ +
+
+ Nov 15, 2025 + CSS +
+

Dark Mode in 5 Minutes

+

How to implement a pure CSS dark mode toggle without flashing content. The trick most tutorials miss.

+ Read Article → +
+ +
+
+ +
+

© Cris Charles Garcia. Crafted in Laguna 🇵🇭

+
+
+ + + + + + + \ No newline at end of file diff --git a/certifications.php b/certifications.php index 6015d95..b9c82be 100755 --- a/certifications.php +++ b/certifications.php @@ -1,132 +1,132 @@ - - - - - - Certifications | Cris Charles Garcia - - - - - - - - -
- - -
-
-

Certifications

-

Qualifications and courses I have completed.

-
-
- -
-
-
-
🏆
-
-

Responsive Web Design

-

FreeCodeCamp

- Issued Dec 2024 -
-
-
-
📜
-
-

JavaScript Algorithms

-

HackerRank

- Issued Nov 2024 -
-
-
-
☁️
-
-

Cloud Fundamentals

-

AWS

- Issued Oct 2024 -
-
-
-
🐍
-
-

Python for Data Science

-

Coursera

- Issued Sept 2024 -
-
-
-
🔒
-
-

Cybersecurity Essentials

-

Cisco

- Issued Aug 2024 -
-
-
-
⚛️
-
-

React Advanced Patterns

-

Udemy

- Issued July 2024 -
-
-
-
- -
-

© 2026 Cris Charles Garcia. Crafted in Laguna.

-
-
- - - - - - - + + + + + + + Certifications | Cris Charles Garcia + + + + + + + + + +
+ + + +
+ +

Certifications

+

Qualifications and courses I have completed.

+
+ +
+ +
+
+ +
+
🏆
+
+

Responsive Web Design

+

FreeCodeCamp

+ Issued Dec 2024 +
+
+ +
+
📜
+
+

JavaScript Algorithms

+

HackerRank

+ Issued Nov 2024 +
+
+ +
+
☁️
+
+

Cloud Fundamentals

+

AWS

+ Issued Oct 2024 +
+
+ +
+
🐍
+
+

Python for Data Science

+

Coursera

+ Issued Sept 2024 +
+
+ +
+
🔒
+
+

Cybersecurity Essentials

+

Cisco

+ Issued Aug 2024 +
+
+ +
+
⚛️
+
+

React Advanced Patterns

+

Udemy

+ Issued July 2024 +
+
+ +
+
+ +
+

© Cris Charles Garcia. Crafted in Laguna 🇵🇭

+
+
+ + + + + + + \ No newline at end of file diff --git a/config/db.php b/config/db.php index b18d3ec..57b5090 100644 --- a/config/db.php +++ b/config/db.php @@ -1,17 +1,46 @@ DB config missing. Please create a .env file from .env.example

'); +} + $mysqli = new mysqli($host, $ngalan, $sikreto, $deytabeys); if ($mysqli->connect_error) { - die("Connection failed: " . $mysqli->connect_error); + die('

Connection failed: ' . htmlspecialchars($mysqli->connect_error) . '

'); } -echo ""; ?> \ No newline at end of file diff --git a/index.php b/index.php index 0a45abb..df7d4cb 100755 --- a/index.php +++ b/index.php @@ -1,116 +1,155 @@ + + Cris Charles Garcia | Software Developer - - - - - + + + + +
-
- - - + + + - + // 5. HAMBURGER MENU + const hamburger = document.getElementById("hamburger"); + const navLinks = document.getElementById("nav-links"); + const navItems = document.querySelectorAll(".nav-item"); + + function closeMenu() { + hamburger.classList.remove("active"); + navLinks.classList.remove("active"); + hamburger.setAttribute("aria-expanded", "false"); + } + + hamburger.addEventListener("click", (e) => { + e.stopPropagation(); + const isOpen = hamburger.classList.toggle("active"); + navLinks.classList.toggle("active"); + hamburger.setAttribute("aria-expanded", isOpen); + }); + + // Close on nav link click + navItems.forEach(item => item.addEventListener("click", closeMenu)); + + // Close when clicking outside the menu + document.addEventListener("click", (e) => { + if (navLinks.classList.contains("active") && !navLinks.contains(e.target) && !hamburger.contains(e.target)) { + closeMenu(); + } + }); + + // Close on scroll + window.addEventListener('scroll', () => { + if (navLinks.classList.contains('active')) { + closeMenu(); + } + }); + }); + + // Prevent right-click & drag on images + document.addEventListener("contextmenu", e => { if (e.target.tagName === 'IMG') e.preventDefault(); }); + document.addEventListener("dragstart", e => { if (e.target.tagName === 'IMG') e.preventDefault(); }); + \ No newline at end of file diff --git a/projects.php b/projects.php index cbe7b11..c2d36b8 100755 --- a/projects.php +++ b/projects.php @@ -3,84 +3,76 @@ + All Projects | Cris Charles Garcia - - + + +
+ -
-
-

Project Archive

-

A complete list of apps, websites, and experiments I've built.

-
-
+
+ +

Project Archive

+

A complete list of apps, websites, and experiments I've built.

+
+ +
- - +
-

© 2026 Cris Charles Garcia. Crafted in Laguna.

+

© Cris Charles Garcia. Crafted in Laguna 🇵🇭

- - - + + + \ No newline at end of file diff --git a/views/projects.php b/views/projects.php index 92317b3..5576b6a 100644 --- a/views/projects.php +++ b/views/projects.php @@ -1,35 +1,34 @@ - - - - - -
- <?php echo htmlspecialchars($project['title']); ?> -
-
-
-

- ↗ -
-

- -
- -
-
-
- - -

No projects found in the database.

+ + + + + +
+ <?php echo htmlspecialchars($project['title']); ?> +
+
+
+
+

+ ↗ +
+

+
+ + + +
+
+
+ + +

No projects found in the database.

\ No newline at end of file diff --git a/views/tprojects.php b/views/tprojects.php index 6557b1d..b0dd474 100644 --- a/views/tprojects.php +++ b/views/tprojects.php @@ -1,35 +1,34 @@ - - - - - -
- <?php echo htmlspecialchars($project['title']); ?> -
-
-
-

- ↗ -
-

- -
- -
-
-
- - -

No projects found in the database.

+ + + + + +
+ <?php echo htmlspecialchars($project['title']); ?> +
+
+
+
+

+ ↗ +
+

+
+ + + +
+
+
+ + +

No projects found in the database.

\ No newline at end of file