diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..6247e42
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,118 @@
+
+/*
+ Custom Styles for Personal Portfolio
+*/
+
+:root {
+ --primary-color: #3B82F6;
+ --secondary-color: #10B981;
+ --background-color: #F9FAFB;
+ --surface-color: #FFFFFF;
+ --text-color: #1F2937;
+ --light-text-color: #6B7280;
+ --border-radius: 0.5rem;
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
+}
+
+body {
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ background-color: var(--background-color);
+ color: var(--text-color);
+}
+
+.navbar {
+ transition: background-color 0.3s ease-in-out;
+}
+
+.navbar-scrolled {
+ background-color: var(--surface-color);
+ box-shadow: var(--shadow-md);
+}
+
+.hero {
+ color: white;
+ padding: 8rem 0;
+ position: relative;
+ text-align: center;
+}
+
+.hero::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image: linear-gradient(to right, rgba(59, 130, 246, 0.8), rgba(16, 185, 129, 0.8)), url('../images/hero-kittens-45170.jpg');
+ background-size: cover;
+ background-position: center;
+ z-index: -1;
+}
+
+.hero h1 {
+ font-size: 3.5rem;
+ font-weight: 700;
+}
+
+.hero p {
+ font-size: 1.25rem;
+}
+
+.btn-primary {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ padding: 0.75rem 1.5rem;
+ border-radius: var(--border-radius);
+ font-weight: 600;
+}
+
+.btn-primary:hover {
+ opacity: 0.9;
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+}
+
+.section {
+ padding: 5rem 0;
+}
+
+.section-title {
+ text-align: center;
+ margin-bottom: 3rem;
+ font-size: 2.5rem;
+ font-weight: 700;
+}
+
+.portfolio-card {
+ border: none;
+ border-radius: var(--border-radius);
+ box-shadow: var(--shadow-md);
+ overflow: hidden;
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+}
+
+.portfolio-card:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+}
+
+.form-control:focus {
+ box-shadow: 0 0 0 0.25rem rgba(59, 130, 246, 0.25);
+ border-color: var(--primary-color);
+}
+
+footer {
+ background-color: var(--surface-color);
+ padding: 2rem 0;
+ border-top: 1px solid #e5e7eb;
+}
+
+#contact-alert {
+ position: fixed;
+ top: 1rem;
+ right: 1rem;
+ z-index: 1050;
+ display: none;
+ min-width: 250px;
+}
diff --git a/assets/images/hero-kittens-45170.jpg b/assets/images/hero-kittens-45170.jpg
new file mode 100644
index 0000000..ee824de
Binary files /dev/null and b/assets/images/hero-kittens-45170.jpg differ
diff --git a/assets/images/kitten-4450241.jpg b/assets/images/kitten-4450241.jpg
new file mode 100644
index 0000000..f76974d
Binary files /dev/null and b/assets/images/kitten-4450241.jpg differ
diff --git a/assets/images/kitten-7778872.jpg b/assets/images/kitten-7778872.jpg
new file mode 100644
index 0000000..0adc9d0
Binary files /dev/null and b/assets/images/kitten-7778872.jpg differ
diff --git a/assets/images/kitten-7778873.jpg b/assets/images/kitten-7778873.jpg
new file mode 100644
index 0000000..9184168
Binary files /dev/null and b/assets/images/kitten-7778873.jpg differ
diff --git a/assets/images/pexels/355952.jpg b/assets/images/pexels/355952.jpg
new file mode 100644
index 0000000..d6c9e22
Binary files /dev/null and b/assets/images/pexels/355952.jpg differ
diff --git a/assets/images/pexels/546819.jpg b/assets/images/pexels/546819.jpg
new file mode 100644
index 0000000..ea4f106
Binary files /dev/null and b/assets/images/pexels/546819.jpg differ
diff --git a/assets/images/pexels/577585.jpg b/assets/images/pexels/577585.jpg
new file mode 100644
index 0000000..43151ea
Binary files /dev/null and b/assets/images/pexels/577585.jpg differ
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..e6d5f79
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1,75 @@
+
+document.addEventListener('DOMContentLoaded', function () {
+
+ // Navbar scroll effect
+ const navbar = document.querySelector('.navbar');
+ if (navbar) {
+ window.addEventListener('scroll', () => {
+ if (window.scrollY > 50) {
+ navbar.classList.add('navbar-scrolled');
+ } else {
+ navbar.classList.remove('navbar-scrolled');
+ }
+ });
+ }
+
+ // Contact form submission
+ const contactForm = document.getElementById('contactForm');
+ if (contactForm) {
+ contactForm.addEventListener('submit', function (e) {
+ e.preventDefault();
+
+ const name = document.getElementById('name').value.trim();
+ const email = document.getElementById('email').value.trim();
+ const message = document.getElementById('message').value.trim();
+ const alertEl = document.getElementById('contact-alert');
+ const submitButton = contactForm.querySelector('button[type="submit"]');
+
+ if (!name || !email || !message) {
+ showAlert('Please fill in all fields.', 'danger');
+ return;
+ }
+
+ if (!/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(email)) {
+ showAlert('Please enter a valid email address.', 'danger');
+ return;
+ }
+
+ const formData = new FormData(this);
+ submitButton.disabled = true;
+ submitButton.innerHTML = ' Sending...';
+
+ fetch('contact.php', {
+ method: 'POST',
+ body: formData
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.success) {
+ showAlert('Message sent successfully! I will get back to you soon.', 'success');
+ contactForm.reset();
+ } else {
+ showAlert(data.error || 'An error occurred. Please try again.', 'danger');
+ }
+ })
+ .catch(() => {
+ showAlert('A network error occurred. Please try again.', 'danger');
+ })
+ .finally(() => {
+ submitButton.disabled = false;
+ submitButton.innerHTML = 'Send Message';
+ });
+ });
+ }
+
+ function showAlert(message, type) {
+ const alertEl = document.getElementById('contact-alert');
+ alertEl.innerHTML = message;
+ alertEl.className = `alert alert-${type}`;
+ alertEl.style.display = 'block';
+
+ setTimeout(() => {
+ alertEl.style.display = 'none';
+ }, 5000);
+ }
+});
diff --git a/contact.php b/contact.php
new file mode 100644
index 0000000..b774dcf
--- /dev/null
+++ b/contact.php
@@ -0,0 +1,43 @@
+ false, 'error' => 'An unknown error occurred.'];
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ $name = trim($_POST['name'] ?? '');
+ $email = trim($_POST['email'] ?? '');
+ $message = trim($_POST['message'] ?? '');
+
+ if (empty($name) || empty($email) || empty($message)) {
+ $response['error'] = 'Please fill out all fields.';
+ } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
+ $response['error'] = 'Please provide a valid email address.';
+ } else {
+ $subject = 'New Contact Form Submission from ' . htmlspecialchars($name);
+
+ // Using MailService to send the contact message.
+ // The user's email is automatically set as the Reply-To address.
+ // The recipient is determined by the MailService configuration (defaults to MAIL_TO in .env).
+ $result = MailService::sendContactMessage($name, $email, $message, null, $subject);
+
+ if (!empty($result['success'])) {
+ $response['success'] = true;
+ unset($response['error']);
+ } else {
+ // For security, we don't expose detailed mailer errors to the client.
+ // The error is logged on the server for debugging.
+ error_log('MailService Error: ' . ($result['error'] ?? 'Unknown error while sending email.'));
+ $response['error'] = 'Sorry, there was an issue sending your message. Please try again later.';
+ }
+ }
+} else {
+ http_response_code(405); // Method Not Allowed
+ $response['error'] = 'Invalid request method.';
+}
+
+echo json_encode($response);
diff --git a/includes/pexels.php b/includes/pexels.php
new file mode 100644
index 0000000..156d6fd
--- /dev/null
+++ b/includes/pexels.php
@@ -0,0 +1,55 @@
+ 0 ? $k : 'Vc99rnmOhHhJAbgGQoKLZtsaIVfkeownoQNbTj78VemUjKh08ZYRbf18';
+}
+
+function pexels_get($url) {
+ $ch = curl_init();
+ curl_setopt_array($ch, [
+ CURLOPT_URL => $url,
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_HTTPHEADER => [ 'Authorization: '. pexels_key() ],
+ CURLOPT_TIMEOUT => 15,
+ ]);
+ $resp = curl_exec($ch);
+ $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+ if ($code >= 200 && $code < 300 && $resp) {
+ return json_decode($resp, true);
+ }
+ return null;
+}
+
+function download_to($srcUrl, $destPath) {
+ if (!is_dir(dirname($destPath))) {
+ if (!mkdir(dirname($destPath), 0775, true)) {
+ return false;
+ }
+ }
+
+ $ch = curl_init($srcUrl);
+ $fp = fopen($destPath, 'wb');
+ if (!$fp) {
+ curl_close($ch);
+ return false;
+ }
+
+ curl_setopt($ch, CURLOPT_FILE, $fp);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 60);
+ $result = curl_exec($ch);
+ $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+ fclose($fp);
+
+ if ($result && $http_code >= 200 && $http_code < 300) {
+ return $destPath;
+ }
+
+ if (file_exists($destPath)) {
+ unlink($destPath);
+ }
+ return false;
+}
diff --git a/index.php b/index.php
index e13ae95..b51a6a1 100644
--- a/index.php
+++ b/index.php
@@ -1,131 +1,147 @@
-
-
+
-
-
- New Style
-
-
-
-
+
+
+ John Doe - Personal Portfolio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
Analyzing your requirements and generating your website…
-
- Loading…
-
-
Flatlogic AI is collecting your requirements and applying the first changes.
-
This page will update automatically as the plan is implemented.
-
Runtime: PHP = htmlspecialchars($phpVersion) ?> — UTC = htmlspecialchars($now) ?>
-
-
-
- Page updated: = htmlspecialchars($now) ?> (UTC)
-
+
+
+
+
+
+
+
+
+
+
+
About Me
+
+
+
I am a passionate web developer with a love for clean code and user-centric design. With a background in computer science and several years of experience, I specialize in creating dynamic and engaging websites. When I'm not coding, I enjoy hiking and photography.
+
+
+
+
+
+
+
+
Portfolio
+
+
+
+
+
+
Project One
+
A brief description of the project, its purpose, and the technologies used. This is a placeholder.
+
+
+
+
+
+
+
+
Project Two
+
A brief description of the project, its purpose, and the technologies used. This is a placeholder.
+
+
+
+
+
+
+
+
Project Three
+
A brief description of the project, its purpose, and the technologies used. This is a placeholder.
+
+
+
+
+
+
+
+
+
+
+
+
+
© John Doe. All Rights Reserved.
+
+
+
+
+
+
+
+
-
+