diff --git a/projects/challenge 11/portifolio(work_in_progress)/.test/.sql/portfolio.sql b/projects/challenge 11/portifolio(work_in_progress)/.test/.sql/portfolio.sql
new file mode 100644
index 0000000..b085e70
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/.test/.sql/portfolio.sql
@@ -0,0 +1,24 @@
+-- Create database
+CREATE DATABASE IF NOT EXISTS portfolio;
+USE portfolio;
+
+-- Create projects table
+CREATE TABLE IF NOT EXISTS projects (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ title VARCHAR(255) NOT NULL,
+ description TEXT,
+ image_url VARCHAR(255),
+ project_url VARCHAR(255),
+ tags VARCHAR(255),
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- Insert a sample project
+INSERT INTO projects (title, description, image_url, project_url, tags)
+VALUES (
+ 'Sample Project',
+ 'This is a sample project description.',
+ 'assets/sample.jpg',
+ 'https://example.com',
+ 'html,css,school'
+);
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/.test/.sql/update_projects.sql b/projects/challenge 11/portifolio(work_in_progress)/.test/.sql/update_projects.sql
new file mode 100644
index 0000000..8d2252b
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/.test/.sql/update_projects.sql
@@ -0,0 +1,5 @@
+-- Add long_description column to projects table
+ALTER TABLE projects ADD COLUMN long_description TEXT AFTER description;
+
+-- Update existing projects with long descriptions (optional)
+UPDATE projects SET long_description = description WHERE long_description IS NULL;
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/.test/test-dark-mode.html b/projects/challenge 11/portifolio(work_in_progress)/.test/test-dark-mode.html
new file mode 100644
index 0000000..bb30a7b
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/.test/test-dark-mode.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+ Dark Mode Test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Dark Mode Test Page
+
+
+
Test Content
+
+ This is a test page to verify that the dark mode toggle button appears and works correctly.
+
+
+ You should see a dark mode toggle button in the bottom-left corner of the screen.
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/favicon.svg b/projects/challenge 11/portifolio(work_in_progress)/assets/favicon.svg
new file mode 100644
index 0000000..885b49a
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/assets/favicon.svg
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_68532b2c9db398.90652024.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68532b2c9db398.90652024.webp
new file mode 100644
index 0000000..2359e98
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68532b2c9db398.90652024.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_68532c22650974.25780946.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68532c22650974.25780946.webp
new file mode 100644
index 0000000..c6526e9
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68532c22650974.25780946.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_685332e2c19726.68679915.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_685332e2c19726.68679915.webp
new file mode 100644
index 0000000..271a26f
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_685332e2c19726.68679915.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533428d7dbf7.04812047.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533428d7dbf7.04812047.webp
new file mode 100644
index 0000000..75b94d9
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533428d7dbf7.04812047.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533897b6e606.91354272.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533897b6e606.91354272.webp
new file mode 100644
index 0000000..1d6b018
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533897b6e606.91354272.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533a4fae17a2.61602173.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533a4fae17a2.61602173.webp
new file mode 100644
index 0000000..b4aab28
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533a4fae17a2.61602173.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533d573a8017.49535201.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533d573a8017.49535201.webp
new file mode 100644
index 0000000..db436b8
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_68533d573a8017.49535201.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_6853423c94f733.00653812.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_6853423c94f733.00653812.webp
new file mode 100644
index 0000000..dfed976
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_6853423c94f733.00653812.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/img_685343f1288b20.49230464.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/img_685343f1288b20.49230464.webp
new file mode 100644
index 0000000..b145588
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/img_685343f1288b20.49230464.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/assets/pano_left.webp b/projects/challenge 11/portifolio(work_in_progress)/assets/pano_left.webp
new file mode 100644
index 0000000..ad382c9
Binary files /dev/null and b/projects/challenge 11/portifolio(work_in_progress)/assets/pano_left.webp differ
diff --git a/projects/challenge 11/portifolio(work_in_progress)/css/animations.css b/projects/challenge 11/portifolio(work_in_progress)/css/animations.css
new file mode 100644
index 0000000..a15ea61
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/css/animations.css
@@ -0,0 +1,240 @@
+/* Custom animations and keyframes */
+
+/* Fade in animation */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+/* Slide up animation */
+@keyframes slideUp {
+ from {
+ opacity: 0;
+ transform: translateY(30px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+/* Bounce in animation */
+@keyframes bounceIn {
+ 0% {
+ opacity: 0;
+ transform: scale(0.3);
+ }
+ 50% {
+ opacity: 1;
+ transform: scale(1.05);
+ }
+ 70% {
+ transform: scale(0.9);
+ }
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+/* Pulse animation */
+@keyframes pulse {
+ 0%, 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.5;
+ }
+}
+
+/* Shimmer effect for loading states */
+@keyframes shimmer {
+ 0% {
+ background-position: -200px 0;
+ }
+ 100% {
+ background-position: calc(200px + 100%) 0;
+ }
+}
+
+/* Floating animation */
+@keyframes float {
+ 0%, 100% {
+ transform: translateY(0px);
+ }
+ 50% {
+ transform: translateY(-10px);
+ }
+}
+
+/* Gradient animation */
+@keyframes gradientShift {
+ 0% {
+ background-position: 0% 50%;
+ }
+ 50% {
+ background-position: 100% 50%;
+ }
+ 100% {
+ background-position: 0% 50%;
+ }
+}
+
+/* Typing animation */
+@keyframes typing {
+ from {
+ width: 0;
+ }
+ to {
+ width: 100%;
+ }
+}
+
+/* Blink animation for cursor */
+@keyframes blink {
+ 0%, 50% {
+ opacity: 1;
+ }
+ 51%, 100% {
+ opacity: 0;
+ }
+}
+
+/* Utility classes for animations */
+.animate-fade-in {
+ animation: fadeIn 0.6s ease-out;
+}
+
+.animate-slide-up {
+ animation: slideUp 0.8s ease-out;
+}
+
+.animate-bounce-in {
+ animation: bounceIn 1s ease-out;
+}
+
+.animate-pulse {
+ animation: pulse 2s infinite;
+}
+
+.animate-float {
+ animation: float 3s ease-in-out infinite;
+}
+
+.animate-gradient {
+ background-size: 200% 200%;
+ animation: gradientShift 3s ease infinite;
+}
+
+.animate-shimmer {
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
+ background-size: 200px 100%;
+ animation: shimmer 1.5s infinite;
+}
+
+/* Staggered animations for lists */
+.stagger-animation > * {
+ opacity: 0;
+ animation: slideUp 0.6s ease-out forwards;
+}
+
+.stagger-animation > *:nth-child(1) { animation-delay: 0.1s; }
+.stagger-animation > *:nth-child(2) { animation-delay: 0.2s; }
+.stagger-animation > *:nth-child(3) { animation-delay: 0.3s; }
+.stagger-animation > *:nth-child(4) { animation-delay: 0.4s; }
+.stagger-animation > *:nth-child(5) { animation-delay: 0.5s; }
+.stagger-animation > *:nth-child(6) { animation-delay: 0.6s; }
+
+/* Hover animations */
+.hover-lift {
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+}
+
+.hover-lift:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 10px 25px rgba(0,0,0,0.15);
+}
+
+.hover-scale {
+ transition: transform 0.3s ease;
+}
+
+.hover-scale:hover {
+ transform: scale(1.05);
+}
+
+.hover-glow {
+ transition: box-shadow 0.3s ease;
+}
+
+.hover-glow:hover {
+ box-shadow: 0 0 20px rgba(79, 172, 254, 0.4);
+}
+
+/* Loading spinner */
+.spinner {
+ width: 40px;
+ height: 40px;
+ border: 4px solid rgba(0, 0, 0, 0.1);
+ border-left-color: #4facfe;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+/* Text reveal animation */
+.text-reveal {
+ overflow: hidden;
+ position: relative;
+}
+
+.text-reveal::after {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: var(--bg-primary);
+ animation: textReveal 1.5s ease-out forwards;
+}
+
+@keyframes textReveal {
+ 0% {
+ transform: translateX(0);
+ }
+ 100% {
+ transform: translateX(100%);
+ }
+}
+
+/* Parallax effect */
+.parallax {
+ transform: translateZ(0);
+ will-change: transform;
+}
+
+/* Smooth scrolling */
+html {
+ scroll-behavior: smooth;
+}
+
+/* Reduced motion for accessibility */
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ }
+}
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/css/styles.css b/projects/challenge 11/portifolio(work_in_progress)/css/styles.css
new file mode 100644
index 0000000..8ad41d9
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/css/styles.css
@@ -0,0 +1,306 @@
+/* Custom CSS for enhanced styling with dark/light theme support */
+
+/* Custom properties for theme colors */
+:root {
+ --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ --secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+ --accent-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+ --success-gradient: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
+
+ /* Light theme colors */
+ --bg-primary: #ffffff;
+ --bg-secondary: #f8fafc;
+ --bg-card: #ffffff;
+ --text-primary: #1e293b;
+ --text-secondary: #64748b;
+ --border-color: #e2e8f0;
+ --shadow-color: rgba(0, 0, 0, 0.1);
+ --shadow-hover: rgba(0, 0, 0, 0.15);
+
+ /* Animation variables */
+ --transition-fast: 0.2s ease;
+ --transition-normal: 0.3s ease;
+ --transition-slow: 0.5s ease;
+}
+
+/* Dark theme colors */
+.dark {
+ --bg-primary: #0f172a;
+ --bg-secondary: #1e293b;
+ --bg-card: #334155;
+ --text-primary: #f1f5f9;
+ --text-secondary: #94a3b8;
+ --border-color: #475569;
+ --shadow-color: rgba(0, 0, 0, 0.3);
+ --shadow-hover: rgba(0, 0, 0, 0.4);
+}
+
+/* Global styles */
+* {
+ box-sizing: border-box;
+}
+
+body {
+ background: var(--bg-primary);
+ color: var(--text-primary);
+ transition: background-color var(--transition-normal), color var(--transition-normal);
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ line-height: 1.6;
+}
+
+/* Enhanced header with gradient and animation */
+header {
+ background: var(--primary-gradient) !important;
+ position: relative;
+ overflow: hidden;
+}
+
+header::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.1'%3E%3Ccircle cx='30' cy='30' r='2'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
+ animation: float 20s ease-in-out infinite;
+}
+
+@keyframes float {
+ 0%, 100% { transform: translateY(0px) rotate(0deg); }
+ 50% { transform: translateY(-20px) rotate(180deg); }
+}
+
+/* Enhanced project cards */
+.project-card {
+ background: var(--bg-card);
+ border: 1px solid var(--border-color);
+ border-radius: 16px;
+ box-shadow: 0 4px 6px var(--shadow-color);
+ transition: all var(--transition-normal);
+ position: relative;
+ overflow: hidden;
+}
+
+.project-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: var(--accent-gradient);
+ transform: scaleX(0);
+ transition: transform var(--transition-normal);
+}
+
+.project-card:hover::before {
+ transform: scaleX(1);
+}
+
+.project-card:hover {
+ transform: translateY(-8px) scale(1.02);
+ box-shadow: 0 20px 25px var(--shadow-hover);
+ border-color: transparent;
+}
+
+/* Enhanced images */
+.project-image {
+ border-radius: 12px;
+ transition: transform var(--transition-normal);
+ position: relative;
+ overflow: hidden;
+}
+
+.project-card:hover .project-image {
+ transform: scale(1.05);
+}
+
+.project-image::after {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.1) 50%, transparent 70%);
+ transform: translateX(-100%);
+ transition: transform var(--transition-slow);
+}
+
+.project-card:hover .project-image::after {
+ transform: translateX(100%);
+}
+
+/* Enhanced tags */
+.tag {
+ background: var(--accent-gradient);
+ color: white;
+ font-weight: 500;
+ border-radius: 20px;
+ padding: 4px 12px;
+ font-size: 0.75rem;
+ transition: all var(--transition-fast);
+ position: relative;
+ overflow: hidden;
+}
+
+.tag::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: -100%;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
+ transition: left var(--transition-slow);
+}
+
+.tag:hover::before {
+ left: 100%;
+}
+
+.tag:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
+}
+
+/* Enhanced buttons */
+.btn-primary {
+ background: var(--primary-gradient);
+ color: white;
+ border: none;
+ border-radius: 12px;
+ padding: 12px 24px;
+ font-weight: 600;
+ transition: all var(--transition-normal);
+ position: relative;
+ overflow: hidden;
+}
+
+.btn-primary::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: -100%;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
+ transition: left var(--transition-slow);
+}
+
+.btn-primary:hover::before {
+ left: 100%;
+}
+
+.btn-primary:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 8px 16px rgba(0,0,0,0.2);
+}
+
+/* Enhanced modal */
+.modal-overlay {
+ backdrop-filter: blur(8px);
+ background: rgba(0, 0, 0, 0.6);
+}
+
+.modal-content {
+ background: var(--bg-card);
+ border-radius: 20px;
+ border: 1px solid var(--border-color);
+ box-shadow: 0 25px 50px var(--shadow-hover);
+}
+
+/* Enhanced theme toggle */
+.theme-toggle {
+ background: var(--bg-card);
+ border: 2px solid var(--border-color);
+ border-radius: 50%;
+ box-shadow: 0 4px 12px var(--shadow-color);
+ transition: all var(--transition-normal);
+}
+
+.theme-toggle:hover {
+ transform: scale(1.1) rotate(180deg);
+ box-shadow: 0 8px 20px var(--shadow-hover);
+}
+
+/* Loading animation */
+.loading {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ border: 3px solid var(--border-color);
+ border-radius: 50%;
+ border-top-color: var(--primary-gradient);
+ animation: spin 1s ease-in-out infinite;
+}
+
+@keyframes spin {
+ to { transform: rotate(360deg); }
+}
+
+/* Enhanced typography */
+h1, h2, h3 {
+ background: var(--primary-gradient);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+header h1 {
+ color: #f0f6ff;
+ background: none;
+ -webkit-background-clip: initial;
+ -webkit-text-fill-color: initial;
+}
+
+/* Scrollbar styling */
+::-webkit-scrollbar {
+ width: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--bg-secondary);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--accent-gradient);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--secondary-gradient);
+}
+
+/* Responsive enhancements */
+@media (max-width: 768px) {
+ .project-card:hover {
+ transform: translateY(-4px) scale(1.01);
+ }
+
+ .theme-toggle:hover {
+ transform: scale(1.05) rotate(90deg);
+ }
+}
+
+/* Focus states for accessibility */
+button:focus,
+a:focus {
+ outline: 2px solid var(--accent-gradient);
+ outline-offset: 2px;
+}
+
+/* Print styles */
+@media print {
+ .theme-toggle,
+ .modal-overlay {
+ display: none !important;
+ }
+
+ .project-card {
+ break-inside: avoid;
+ box-shadow: none;
+ border: 1px solid #ccc;
+ }
+}
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/db/add_project.php b/projects/challenge 11/portifolio(work_in_progress)/db/add_project.php
new file mode 100644
index 0000000..4a427b6
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/db/add_project.php
@@ -0,0 +1,159 @@
+Image upload failed.';
+ }
+ } else if (!empty($_POST['image_url'])) {
+ $image_url = $_POST['image_url'];
+ }
+ if (!$message) {
+ try {
+ $pdo = get_pdo();
+ $stmt = $pdo->prepare('INSERT INTO projects (title, description, long_description, image_url, project_url, tags) VALUES (?, ?, ?, ?, ?, ?)');
+ $stmt->execute([$title, $description, $long_description, $image_url, $project_url, $tags]);
+ $message = 'Project added successfully!
';
+ } catch (Exception $e) {
+ $message = 'Error: ' . htmlspecialchars($e->getMessage()) . '
';
+ }
+ }
+}
+?>
+
+
+
+
+
+ Add Project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Back to Home
+
+
+
+
+
+ = $message ?>
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/db/index.php b/projects/challenge 11/portifolio(work_in_progress)/db/index.php
new file mode 100644
index 0000000..a716fd6
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/db/index.php
@@ -0,0 +1,255 @@
+prepare('DELETE FROM projects WHERE id = ?')->execute([$id]);
+ $message = 'Project deleted.
';
+ } catch (Exception $e) {
+ $message = 'Error: ' . htmlspecialchars($e->getMessage()) . '
';
+ }
+}
+
+// Handle update
+if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['edit_id'])) {
+ $id = intval($_POST['edit_id']);
+ $title = $_POST['title'] ?? '';
+ $description = $_POST['description'] ?? '';
+ $long_description = $_POST['long_description'] ?? '';
+ $project_url = $_POST['project_url'] ?? '';
+ $tags = $_POST['tags'] ?? '';
+ $image_url = $_POST['image_url'] ?? '';
+ // Handle image upload
+ if (isset($_FILES['image_file']) && $_FILES['image_file']['error'] === UPLOAD_ERR_OK) {
+ $ext = pathinfo($_FILES['image_file']['name'], PATHINFO_EXTENSION);
+ $filename = uniqid('img_', true) . '.' . strtolower($ext);
+ $target = '/var/www/alvnx.xyz/public_html/assets/' . $filename;
+ if (move_uploaded_file($_FILES['image_file']['tmp_name'], $target)) {
+ $image_url = 'assets/' . $filename;
+ } else {
+ $message = 'Image upload failed.
';
+ }
+ }
+ if (!$message) {
+ try {
+ $pdo = get_pdo();
+ $stmt = $pdo->prepare('UPDATE projects SET title=?, description=?, long_description=?, image_url=?, project_url=?, tags=? WHERE id=?');
+ $stmt->execute([$title, $description, $long_description, $image_url, $project_url, $tags, $id]);
+ $message = 'Project updated.
';
+ } catch (Exception $e) {
+ $message = 'Error: ' . htmlspecialchars($e->getMessage()) . '
';
+ }
+ }
+}
+
+// Fetch all projects
+try {
+ $pdo = get_pdo();
+ $projects = $pdo->query('SELECT * FROM projects ORDER BY created_at DESC')->fetchAll();
+} catch (Exception $e) {
+ $projects = [];
+ $message = 'Error: ' . htmlspecialchars($e->getMessage()) . '
';
+}
+
+// If editing, fetch project
+$edit_project = null;
+if (isset($_GET['edit'])) {
+ $id = intval($_GET['edit']);
+ foreach ($projects as $p) {
+ if ($p['id'] == $id) {
+ $edit_project = $p;
+ break;
+ }
+ }
+}
+?>
+
+
+
+
+
+ Manage Projects
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Back to Home
+
+
+
+
+
+
+
Manage Projects
+
Add, edit, and manage your portfolio projects
+
+
+
+
+
+ = $message ?? '' ?>
+
+
+
+
+
+
+
+
+ Edit Project
+
+
+
+
+
+ Short Description
+ = htmlspecialchars($edit_project['description']) ?>
+
+
+ Long Description
+ = htmlspecialchars($edit_project['long_description'] ?? '') ?>
+
+
+
+
Current Image
+
+
+
+
+ No image
+
+
+
+
+ Upload New Image
+
+
+
+
+ Or Image URL
+
+
+
+
Tags
+
+
Separate tags with commas
+
+
+
+
+
+
+ Save Changes
+
+
Cancel
+
+
+
+
+
+
+
+
+
+
+
+
+
= htmlspecialchars($project['title']) ?>
+
= htmlspecialchars($project['description']) ?>
+
+
+
+ = htmlspecialchars(trim($tag)) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/db/login.php b/projects/challenge 11/portifolio(work_in_progress)/db/login.php
new file mode 100644
index 0000000..c700b5a
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/db/login.php
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ Login - Manage Projects
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Back to Home
+
+
+
+
+
+
Sign In
+
Access your project management dashboard
+
+
+
+
+
+
+
+
+
= htmlspecialchars($error) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sign In
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/index.php b/projects/challenge 11/portifolio(work_in_progress)/index.php
new file mode 100644
index 0000000..9128d0c
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/index.php
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+ My School Projects Portfolio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A showcase of all my school projects, loaded from a database.
+
+
+
+
+
+
+
Dynamic content
+
+
+
+
+
+
Responsive design
+
+
+
+
+
+
+
+
+ Manage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
© 2025 School Projects Portfolio. Built with modern web technologies.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/js/dark-mode.js b/projects/challenge 11/portifolio(work_in_progress)/js/dark-mode.js
new file mode 100644
index 0000000..50975b9
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/js/dark-mode.js
@@ -0,0 +1,143 @@
+// Dark mode functionality with enhanced animations
+function initDarkMode() {
+
+ // Check for saved theme preference or use system preference
+ const savedTheme = localStorage.getItem('theme');
+ const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
+
+ if (savedTheme === 'dark' || (!savedTheme && systemPrefersDark)) {
+ document.documentElement.classList.add('dark');
+ } else {
+
+ }
+
+ // Remove existing toggle button if it exists
+ const existingButton = document.getElementById('theme-toggle');
+ if (existingButton) {
+ existingButton.remove();
+ }
+
+ // Create and add the theme toggle button with fallback styling
+ const toggleButton = document.createElement('button');
+ toggleButton.id = 'theme-toggle';
+ toggleButton.setAttribute('aria-label', 'Toggle dark mode');
+
+ // Use inline styles as fallback
+ const isDark = document.documentElement.classList.contains('dark');
+ toggleButton.style.cssText = `
+ position: fixed;
+ bottom: 1rem;
+ left: 1rem;
+ z-index: 9999;
+ background: ${isDark ? '#334155' : '#ffffff'};
+ border: 2px solid ${isDark ? '#475569' : '#e2e8f0'};
+ border-radius: 50%;
+ padding: 0.75rem;
+ box-shadow: 0 4px 12px ${isDark ? 'rgba(0,0,0,0.3)' : 'rgba(0,0,0,0.1)'};
+ transition: all 0.3s ease;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 3rem;
+ height: 3rem;
+ `;
+
+ toggleButton.innerHTML = `
+
+
+
+
+ `;
+
+ document.body.appendChild(toggleButton);
+
+ // Add click handler with enhanced animation
+ toggleButton.addEventListener('click', () => {
+
+ // Add click animation
+ toggleButton.style.transform = 'scale(0.9)';
+ setTimeout(() => {
+ toggleButton.style.transform = '';
+ }, 150);
+
+ // Toggle theme
+ const newIsDark = document.documentElement.classList.toggle('dark');
+ localStorage.setItem('theme', newIsDark ? 'dark' : 'light');
+
+ // Update button styles
+ toggleButton.style.background = newIsDark ? '#334155' : '#ffffff';
+ toggleButton.style.borderColor = newIsDark ? '#475569' : '#e2e8f0';
+ toggleButton.style.boxShadow = newIsDark ? '0 4px 12px rgba(0,0,0,0.3)' : '0 4px 12px rgba(0,0,0,0.1)';
+
+ const svg = toggleButton.querySelector('svg');
+ svg.style.color = newIsDark ? '#f1f5f9' : '#1e293b';
+
+ const sunIcon = toggleButton.querySelector('.sun-icon');
+ const moonIcon = toggleButton.querySelector('.moon-icon');
+
+ if (newIsDark) {
+ sunIcon.style.display = 'none';
+ moonIcon.style.display = 'block';
+ } else {
+ sunIcon.style.display = 'block';
+ moonIcon.style.display = 'none';
+ }
+
+ // Add theme transition effect
+ addThemeTransitionEffect();
+ });
+
+ // Listen for system theme changes
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
+ if (!localStorage.getItem('theme')) {
+ if (e.matches) {
+ document.documentElement.classList.add('dark');
+ } else {
+ document.documentElement.classList.remove('dark');
+ }
+ }
+ });
+}
+
+function addThemeTransitionEffect() {
+ // Create a temporary overlay for smooth transition
+ const overlay = document.createElement('div');
+ overlay.style.cssText = `
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: ${document.documentElement.classList.contains('dark') ? '#0f172a' : '#ffffff'};
+ z-index: 9998;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease;
+ `;
+ document.body.appendChild(overlay);
+
+ // Fade in and out
+ requestAnimationFrame(() => {
+ overlay.style.opacity = '0.1';
+ setTimeout(() => {
+ overlay.style.opacity = '0';
+ setTimeout(() => {
+ if (document.body.contains(overlay)) {
+ document.body.removeChild(overlay);
+ }
+ }, 300);
+ }, 150);
+ });
+}
+
+// Initialize dark mode when the DOM is loaded
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initDarkMode);
+} else {
+ // DOM is already loaded
+ initDarkMode();
+}
+
+// Also try to initialize after a short delay to ensure everything is ready
+setTimeout(initDarkMode, 100);
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/js/main.js b/projects/challenge 11/portifolio(work_in_progress)/js/main.js
new file mode 100644
index 0000000..de691d2
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/js/main.js
@@ -0,0 +1,188 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const container = document.getElementById('projects');
+
+ // Add loading state with enhanced spinner
+ container.innerHTML = '';
+
+ // Create modal element with enhanced styling
+ const modal = document.createElement('div');
+ modal.className = 'modal-overlay fixed inset-0 hidden items-center justify-center z-50 transition-opacity duration-300';
+ modal.innerHTML = `
+
+ `;
+ document.body.appendChild(modal);
+
+ // Add modal functions to window
+ window.openModal = (project) => {
+ const modalTitle = modal.querySelector('h2');
+ const modalImage = modal.querySelector('.modal-image');
+ const modalDescription = modal.querySelector('.modal-description');
+ const modalTags = modal.querySelector('.modal-tags');
+ const modalLinks = modal.querySelector('.modal-links');
+ const modalContent = modal.querySelector('.modal-content');
+
+ modalTitle.textContent = project.title;
+
+ if (project.image_url) {
+ modalImage.innerHTML = ` `;
+ } else {
+ modalImage.innerHTML = '';
+ }
+
+ modalDescription.innerHTML = `
+ ${project.description || ''}
+ ${project.long_description ? `${project.long_description}
` : ''}
+ `;
+
+ if (project.tags) {
+ modalTags.innerHTML = `
+
+ ${project.tags.split(',').map(tag =>
+ `${tag.trim()} `
+ ).join('')}
+
+ `;
+ } else {
+ modalTags.innerHTML = '';
+ }
+
+ modalLinks.innerHTML = project.project_url ?
+ `View Project → ` : '';
+
+ // Show modal with animation
+ modal.classList.remove('hidden');
+ modal.classList.add('flex');
+ document.body.style.overflow = 'hidden';
+
+ // Trigger animation
+ requestAnimationFrame(() => {
+ modalContent.classList.remove('scale-95', 'opacity-0');
+ modalContent.classList.add('scale-100', 'opacity-100');
+ });
+ };
+
+ window.closeModal = () => {
+ const modalContent = modal.querySelector('.modal-content');
+
+ // Start closing animation
+ modalContent.classList.remove('scale-100', 'opacity-100');
+ modalContent.classList.add('scale-95', 'opacity-0');
+
+ // Wait for animation to finish before hiding
+ setTimeout(() => {
+ modal.classList.add('hidden');
+ modal.classList.remove('flex');
+ document.body.style.overflow = '';
+ }, 300);
+ };
+
+ // Close modal when clicking outside
+ modal.addEventListener('click', (e) => {
+ if (e.target === modal) {
+ closeModal();
+ }
+ });
+
+ // Close modal with Escape key
+ document.addEventListener('keydown', (e) => {
+ if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
+ closeModal();
+ }
+ });
+
+ // Enhanced project fetching with error handling
+ fetch('php/get_projects.php')
+ .then(res => {
+ if (!res.ok) {
+ throw new Error(`HTTP error! status: ${res.status}`);
+ }
+ return res.json();
+ })
+ .then(projects => {
+ if (!Array.isArray(projects) || projects.length === 0) {
+ container.innerHTML = `
+
+
+
No projects found.
+
Projects will appear here once added.
+
`;
+ return;
+ }
+
+ container.innerHTML = '';
+
+ // Add projects with CSS animations
+ projects.forEach((project) => {
+ const card = document.createElement('div');
+ card.className = 'project-card p-5 flex flex-col cursor-pointer hover-lift';
+
+ card.onclick = () => openModal(project);
+
+ if (project.image_url) {
+ card.innerHTML += ` `;
+ } else {
+ card.innerHTML += ``;
+ }
+
+ card.innerHTML += `
+ ${project.title}
+ ${project.description || ''}
+ ${project.tags ? `${project.tags.split(',').map(tag => `${tag.trim()} `).join('')}
` : ''}
+ ${project.project_url ? `View Project → ` : ''}
+ `;
+
+ container.appendChild(card);
+ });
+ })
+ .catch(err => {
+ console.error('Error fetching projects:', err);
+ container.innerHTML = `
+
+
+
Failed to load projects.
+
Error: ${err.message}
+
Try Again
+
`;
+ });
+});
+
+// Add fadeInUp animation
+const style = document.createElement('style');
+style.textContent = `
+ @keyframes fadeInUp {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+`;
+document.head.appendChild(style);
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/php/config.php b/projects/challenge 11/portifolio(work_in_progress)/php/config.php
new file mode 100644
index 0000000..fa2ba77
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/php/config.php
@@ -0,0 +1,18 @@
+ PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+];
+function get_pdo() {
+ global $dsn, $user, $pass, $options;
+ return new PDO($dsn, $user, $pass, $options);
+}
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/php/get_projects.php b/projects/challenge 11/portifolio(work_in_progress)/php/get_projects.php
new file mode 100644
index 0000000..93a1797
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/php/get_projects.php
@@ -0,0 +1,21 @@
+query('SELECT id, title, description, long_description, image_url, project_url, tags, created_at FROM projects ORDER BY created_at DESC');
+ $projects = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ echo json_encode($projects);
+} catch (Exception $e) {
+ http_response_code(500);
+ echo json_encode(['error' => $e->getMessage()]);
+}
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/php/phpinfo.php b/projects/challenge 11/portifolio(work_in_progress)/php/phpinfo.php
new file mode 100644
index 0000000..e974c40
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/php/phpinfo.php
@@ -0,0 +1 @@
+";
+
+ // Test query
+ $stmt = $pdo->query('SELECT COUNT(*) as count FROM projects');
+ $result = $stmt->fetch();
+ echo "Number of projects in database: " . $result['count'];
+} catch (Exception $e) {
+ echo "Error: " . $e->getMessage();
+}
\ No newline at end of file
diff --git a/projects/challenge 11/portifolio(work_in_progress)/robots.txt b/projects/challenge 11/portifolio(work_in_progress)/robots.txt
new file mode 100644
index 0000000..a0c656f
--- /dev/null
+++ b/projects/challenge 11/portifolio(work_in_progress)/robots.txt
@@ -0,0 +1,160 @@
+# Allow all well-behaved bots
+User-agent: *
+Disallow:
+
+# Block specific bots
+User-agent: AI2Bot
+Disallow: /db
+
+User-agent: Ai2Bot-Dolma
+Disallow: /db
+
+User-agent: aiHitBot
+Disallow: /db
+
+User-agent: Amazonbot
+Disallow: /db
+
+User-agent: anthropic-ai
+Disallow: /db
+
+User-agent: Applebot
+Disallow: /db
+
+User-agent: Applebot-Extended
+Disallow: /db
+
+User-agent: Brightbot 1.0
+Disallow: /db
+
+User-agent: Bytespider
+Disallow: /db
+
+User-agent: CCBot
+Disallow: /db
+
+User-agent: ChatGPT-User
+Disallow: /db
+
+User-agent: Claude-Web
+Disallow: /db
+
+User-agent: ClaudeBot
+Disallow: /db
+
+User-agent: cohere-ai
+Disallow: /db
+
+User-agent: cohere-training-data-crawler
+Disallow: /db
+
+User-agent: Cotoyogi
+Disallow: /db
+
+User-agent: Crawlspace
+Disallow: /db
+
+User-agent: Diffbot
+Disallow: /db
+
+User-agent: DuckAssistBot
+Disallow: /db
+
+User-agent: FacebookBot
+Disallow: /db
+
+User-agent: Factset_spyderbot
+Disallow: /db
+
+User-agent: FirecrawlAgent
+Disallow: /db
+
+User-agent: FriendlyCrawler
+Disallow: /db
+
+User-agent: GPTBot
+Disallow: /db
+
+User-agent: iaskspider/2.0
+Disallow: /db
+
+User-agent: ICC-Crawler
+Disallow: /db
+
+User-agent: ImagesiftBot
+Disallow: /db
+
+User-agent: img2dataset
+Disallow: /db
+
+User-agent: imgproxy
+Disallow: /db
+
+User-agent: ISSCyberRiskCrawler
+Disallow: /db
+
+User-agent: Kangaroo Bot
+Disallow: /db
+
+User-agent: Meta-ExternalAgent
+Disallow: /db
+
+User-agent: Meta-ExternalFetcher
+Disallow: /db
+
+User-agent: NovaAct
+Disallow: /db
+
+User-agent: OAI-SearchBot
+Disallow: /db
+
+User-agent: omgili
+Disallow: /db
+
+User-agent: omgilibot
+Disallow: /db
+
+User-agent: Operator
+Disallow: /db
+
+User-agent: PanguBot
+Disallow: /db
+
+User-agent: Perplexity-User
+Disallow: /db
+
+User-agent: PerplexityBot
+Disallow: /db
+
+User-agent: PetalBot
+Disallow: /db
+
+User-agent: Scrapy
+Disallow: /db
+
+User-agent: SemrushBot-OCOB
+Disallow: /db
+
+User-agent: SemrushBot-SWA
+Disallow: /db
+
+User-agent: Sidetrade indexer bot
+Disallow: /db
+
+User-agent: TikTokSpider
+Disallow: /db
+
+User-agent: Timpibot
+Disallow: /db
+
+User-agent: VelenPublicWebCrawler
+Disallow: /db
+
+User-agent: Webzio-Extended
+Disallow: /db
+
+User-agent: YouBot
+Disallow: /db
+
+# Sitemap location
+Sitemap: https://alvnx.xyz/sitemap.xml