Projek3
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profil Pribadi — Modern & Elegan</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
/* ============================================
1. RESET & VARIABEL GLOBAL
============================================ */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--grad-1: #667eea;
--grad-2: #764ba2;
--grad-3: #f093fb;
--grad-4: #f5576c;
--accent: #ffd93d;
--dark: #1a1a2e;
--darker: #0f0f1e;
--light: #ffffff;
--text: #eaeaea;
--text-dim: #a0a0b8;
--glass: rgba(255, 255, 255, 0.08);
--glass-border: rgba(255, 255, 255, 0.15);
--shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
--transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
--radius: 24px;
}
html { scroll-behavior: smooth; }
body {
font-family: 'Poppins', sans-serif;
background: var(--darker);
color: var(--text);
line-height: 1.7;
min-height: 100vh;
overflow-x: hidden;
display: flex;
flex-direction: column;
position: relative;
}
/* Animated background blobs */
body::before,
body::after {
content: '';
position: fixed;
border-radius: 50%;
filter: blur(120px);
opacity: 0.4;
z-index: -1;
pointer-events: none;
}
body::before {
width: 500px;
height: 500px;
background: var(--grad-1);
top: -150px;
left: -150px;
animation: float1 15s ease-in-out infinite;
}
body::after {
width: 450px;
height: 450px;
background: var(--grad-4);
bottom: -150px;
right: -150px;
animation: float2 18s ease-in-out infinite;
}
@keyframes float1 {
0%, 100% { transform: translate(0, 0) scale(1); }
50% { transform: translate(80px, 60px) scale(1.15); }
}
@keyframes float2 {
0%, 100% { transform: translate(0, 0) scale(1); }
50% { transform: translate(-80px, -60px) scale(1.2); }
}
a { text-decoration: none; color: inherit; }
/* ============================================
2. HEADER & NAVIGASI
============================================ */
header {
position: sticky;
top: 0;
z-index: 100;
padding: 1rem 2rem;
background: rgba(15, 15, 30, 0.7);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border-bottom: 1px solid var(--glass-border);
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 1rem;
}
.logo {
font-size: 1.6rem;
font-weight: 800;
background: linear-gradient(135deg, var(--grad-1), var(--grad-3), var(--accent));
background-size: 200% 200%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: gradientMove 4s ease infinite;
letter-spacing: 0.5px;
}
@keyframes gradientMove {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
nav {
display: flex;
gap: 0.4rem;
flex-wrap: wrap;
}
nav a {
color: var(--text-dim);
padding: 0.6rem 1.3rem;
border-radius: 50px;
font-weight: 500;
font-size: 0.95rem;
transition: var(--transition);
display: inline-flex;
align-items: center;
gap: 0.5rem;
position: relative;
overflow: hidden;
}
nav a::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, var(--grad-1), var(--grad-2));
opacity: 0;
transition: opacity 0.4s ease;
border-radius: inherit;
z-index: -1;
}
nav a:hover {
color: var(--light);
transform: translateY(-2px);
}
nav a:hover::before { opacity: 0.6; }
nav a.active {
color: var(--light);
background: linear-gradient(135deg, var(--grad-1), var(--grad-2));
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.5);
}
/* ============================================
3. MAIN & PAGE CONTAINER
============================================ */
main {
flex: 1;
max-width: 1200px;
width: 100%;
margin: 2.5rem auto;
padding: 0 1.5rem;
}
.page {
display: none;
animation: pageEnter 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.page.active { display: block; }
@keyframes pageEnter {
from { opacity: 0; transform: translateY(30px) scale(0.98); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
/* Glass card */
.glass-card {
background: var(--glass);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border: 1px solid var(--glass-border);
border-radius: var(--radius);
padding: 2.8rem;
box-shadow: var(--shadow);
position: relative;
overflow: hidden;
}
.glass-card::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, var(--accent), transparent);
animation: shine 4s ease-in-out infinite;
}
@keyframes shine {
0% { left: -100%; }
50%, 100% { left: 100%; }
}
.section-title {
font-size: 2.2rem;
font-weight: 700;
margin-bottom: 0.4rem;
display: flex;
align-items: center;
gap: 0.8rem;
background: linear-gradient(135deg, var(--light), var(--text-dim));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.section-title i {
background: linear-gradient(135deg, var(--grad-3), var(--accent));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 1.8rem;
}
.subtitle {
color: var(--text-dim);
margin-bottom: 2rem;
font-size: 1rem;
font-weight: 300;
}
/* ============================================
4. HOME / HERO
============================================ */
.hero {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 3rem;
min-height: 60vh;
}
.hero-text {
flex: 1 1 320px;
}
.hero-badge {
display: inline-block;
padding: 0.4rem 1rem;
background: rgba(102, 126, 234, 0.15);
border: 1px solid rgba(102, 126, 234, 0.4);
border-radius: 50px;
font-size: 0.85rem;
color: #b8c5f0;
margin-bottom: 1.2rem;
font-weight: 500;
}
.hero-badge::before {
content: '●';
color: #4ade80;
margin-right: 0.4rem;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
.hero-text h1 {
font-size: 3.2rem;
font-weight: 800;
line-height: 1.15;
margin-bottom: 0.8rem;
letter-spacing: -1px;
}
.hero-text h1 .gradient-text {
background: linear-gradient(135deg, var(--grad-1), var(--grad-3), var(--accent));
background-size: 200% 200%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: gradientMove 4s ease infinite;
}
.hero-text .tagline {
font-size: 1.15rem;
color: var(--text-dim);
margin-bottom: 1.5rem;
font-weight: 300;
}
.hero-text p.intro {
color: var(--text-dim);
margin-bottom: 2rem;
max-width: 520px;
}
/* Buttons */
.btn-group {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
gap: 0.6rem;
padding: 0.85rem 2rem;
border-radius: 50px;
font-weight: 600;
font-size: 0.95rem;
cursor: pointer;
border: none;
transition: var(--transition);
position: relative;
overflow: hidden;
}
.btn-primary {
background: linear-gradient(135deg, var(--grad-1), var(--grad-2));
color: white;
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
}
.btn-primary:hover {
transform: translateY(-4px);
box-shadow: 0 15px 40px rgba(102, 126, 234, 0.6);
}
.btn-outline {
background: transparent;
color: var(--text);
border: 1.5px solid var(--glass-border);
}
.btn-outline:hover {
background: var(--glass);
border-color: var(--accent);
transform: translateY(-4px);
}
/* Avatar */
.hero-avatar {
flex: 0 0 260px;
text-align: center;
position: relative;
}
.avatar-ring {
position: relative;
display: inline-block;
}
.avatar-ring::before {
content: '';
position: absolute;
inset: -12px;
border-radius: 50%;
background: conic-gradient(from 0deg, var(--grad-1), var(--grad-3), var(--accent), var(--grad-1));
animation: rotateRing 6s linear infinite;
z-index: 0;
}
@keyframes rotateRing {
to { transform: rotate(360deg); }
}
.avatar-ring::after {
content: '';
position: absolute;
inset: -6px;
border-radius: 50%;
background: var(--darker);
z-index: 1;
}
.avatar-ring img {
position: relative;
z-index: 2;
width: 240px;
height: 240px;
border-radius: 50%;
object-fit: cover;
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
animation: floatAvatar 4s ease-in-out infinite;
}
@keyframes floatAvatar {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
/* ============================================
5. ABOUT
============================================ */
.about-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1.2rem;
margin: 1.5rem 0 2rem;
}
.about-item {
background: rgba(255, 255, 255, 0.04);
border: 1px solid var(--glass-border);
border-radius: 18px;
padding: 1.3rem 1.5rem;
transition: var(--transition);
position: relative;
overflow: hidden;
}
.about-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background: linear-gradient(180deg, var(--grad-1), var(--grad-3));
border-radius: 4px;
}
.about-item:hover {
background: rgba(255, 255, 255, 0.08);
transform: translateY(-6px);
border-color: rgba(102, 126, 234, 0.5);
box-shadow: 0 12px 30px rgba(102, 126, 234, 0.2);
}
.about-item .label {
font-size: 0.8rem;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 0.3rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.about-item .label i { color: var(--accent); }
.about-item .value {
font-size: 1.05rem;
font-weight: 600;
color: var(--light);
}
.about-desc {
padding: 1.5rem 1.8rem;
background: rgba(102, 126, 234, 0.08);
border: 1px solid rgba(102, 126, 234, 0.2);
border-radius: 18px;
color: var(--text-dim);
line-height: 1.8;
}
.about-desc strong { color: var(--accent); }
/* ============================================
6. GALLERY
============================================ */
.gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 1.3rem;
}
.gallery-item {
border-radius: 20px;
overflow: hidden;
background: rgba(255, 255, 255, 0.04);
border: 1px solid var(--glass-border);
transition: var(--transition);
cursor: pointer;
position: relative;
}
.gallery-item:hover {
transform: translateY(-8px) scale(1.02);
border-color: rgba(240, 147, 251, 0.6);
box-shadow: 0 20px 45px rgba(240, 147, 251, 0.25);
}
.gallery-thumb {
height: 160px;
display: flex;
align-items: center;
justify-content: center;
font-size: 3.8rem;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.4), rgba(118, 75, 162, 0.4));
position: relative;
overflow: hidden;
}
.gallery-thumb::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at center, transparent 30%, rgba(0, 0, 0, 0.4));
transition: opacity 0.3s;
}
.gallery-item:hover .gallery-thumb::after { opacity: 0.3; }
.gallery-info {
padding: 1rem 1.3rem 1.3rem;
}
.gallery-info h4 {
font-size: 1rem;
font-weight: 600;
color: var(--light);
margin-bottom: 0.2rem;
}
.gallery-info p {
font-size: 0.85rem;
color: var(--text-dim);
}
/* ============================================
7. CONTACT
============================================ */
.contact-wrap {
display: grid;
grid-template-columns: 1fr 1.4fr;
gap: 2.5rem;
}
.contact-info .info-item {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
border-radius: 16px;
margin-bottom: 0.8rem;
background: rgba(255, 255, 255, 0.03);
border: 1px solid transparent;
transition: var(--transition);
}
.contact-info .info-item:hover {
background: rgba(255, 255, 255, 0.07);
border-color: var(--glass-border);
transform: translateX(6px);
}
.info-icon {
width: 48px;
height: 48px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
background: linear-gradient(135deg, var(--grad-1), var(--grad-2));
color: white;
flex-shrink: 0;
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.35);
}
.info-detail .top {
font-weight: 600;
color: var(--light);
font-size: 0.95rem;
}
.info-detail .bottom {
font-size: 0.8rem;
color: var(--text-dim);
}
/* Form */
.contact-form .form-group {
margin-bottom: 1.2rem;
position: relative;
}
.contact-form label {
display: block;
font-size: 0.85rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--text-dim);
letter-spacing: 0.3px;
}
.contact-form input,
.contact-form textarea {
width: 100%;
padding: 0.9rem 1.2rem;
border-radius: 14px;
border: 1.5px solid var(--glass-border);
background: rgba(255, 255, 255, 0.04);
color: var(--text);
font-family: inherit;
font-size: 0.95rem;
transition: var(--transition);
}
.contact-form input::placeholder,
.contact-form textarea::placeholder {
color: rgba(160, 160, 184, 0.6);
}
.contact-form input:focus,
.contact-form textarea:focus {
outline: none;
border-color: var(--grad-1);
background: rgba(255, 255, 255, 0.07);
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.15);
}
.contact-form textarea {
resize: vertical;
min-height: 120px;
}
.btn-submit {
width: 100%;
padding: 1rem;
border-radius: 14px;
border: none;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
background: linear-gradient(135deg, var(--grad-1), var(--grad-2), var(--grad-3));
background-size: 200% 200%;
color: white;
transition: var(--transition);
animation: gradientMove 4s ease infinite;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.6rem;
}
.btn-submit:hover {
transform: translateY(-3px);
box-shadow: 0 15px 35px rgba(118, 75, 162, 0.5);
}
.btn-submit:active { transform: translateY(-1px); }
/* ============================================
8. FOOTER
============================================ */
footer {
text-align: center;
padding: 2rem;
color: var(--text-dim);
font-size: 0.85rem;
border-top: 1px solid var(--glass-border);
margin-top: 2rem;
}
footer .heart {
color: var(--grad-4);
animation: heartbeat 1.5s ease infinite;
display: inline-block;
}
@keyframes heartbeat {
0%, 100% { transform: scale(1); }
25% { transform: scale(1.25); }
50% { transform: scale(1); }
}
/* ============================================
9. RESPONSIF
============================================ */
@media (max-width: 900px) {
.contact-wrap {
grid-template-columns: 1fr;
gap: 2rem;
}
}
@media (max-width: 768px) {
header { padding: 0.8rem 1rem; }
.nav-container {
flex-direction: column;
gap: 0.6rem;
}
nav { justify-content: center; }
nav a {
padding: 0.5rem 1rem;
font-size: 0.85rem;
}
.glass-card { padding: 1.8rem 1.4rem; }
.hero {
flex-direction: column-reverse;
text-align: center;
gap: 2rem;
min-height: auto;
}
.hero-text h1 { font-size: 2.2rem; }
.hero-text p.intro { margin-left: auto; margin-right: auto; }
.btn-group { justify-content: center; }
.avatar-ring img {
width: 180px;
height: 180px;
}
.section-title { font-size: 1.7rem; }
.gallery-grid {
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}
}
@media (max-width: 480px) {
nav a {
padding: 0.4rem 0.8rem;
font-size: 0.78rem;
}
.logo { font-size: 1.3rem; }
.hero-text h1 { font-size: 1.9rem; }
.avatar-ring img {
width: 150px;
height: 150px;
}
.btn { padding: 0.7rem 1.5rem; font-size: 0.85rem; }
}
</style>
</head>
<body>
<!-- ============ HEADER ============ -->
<header>
<div class="nav-container">
<div class="logo">✦ Andi.Dev</div>
<nav id="navMenu">
<a href="#" class="active" data-page="home"><i class="fas fa-house"></i> Home</a>
<a href="#" data-page="about"><i class="fas fa-user"></i> About Me</a>
<a href="#" data-page="gallery"><i class="fas fa-images"></i> Gallery</a>
<a href="#" data-page="contact"><i class="fas fa-envelope"></i> Contact</a>
</nav>
</div>
</header>
<!-- ============ MAIN ============ -->
<main>
<!-- HOME -->
<section id="page-home" class="page active">
<div class="glass-card">
<div class="hero">
<div class="hero-text">
<div class="hero-badge">Tersedia untuk freelance</div>
<h1>Halo, saya <span class="gradient-text">Andi Pratama</span> 👋</h1>
<div class="tagline">Web Developer & Creative Thinker</div>
<p class="intro">
Saya membangun pengalaman digital yang indah, cepat, dan
bermakna. Fokus pada front-end development dan desain antarmuka
yang memukau.
</p>
<div class="btn-group">
<a href="#" class="btn btn-primary" data-page="contact">
<i class="fas fa-paper-plane"></i> Hubungi Saya
</a>
<a href="#" class="btn btn-outline" data-page="gallery">
<i class="fas fa-images"></i> Lihat Karya
</a>
</div>
</div>
<div class="hero-avatar">
<div class="avatar-ring">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 200 200'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23667eea'/%3E%3Cstop offset='1' stop-color='%23f093fb'/%3E%3C/linearGradient%3E%3C/defs%3E%3Ccircle cx='100' cy='100' r='100' fill='url(%23g)'/%3E%3Ccircle cx='100' cy='80' r='45' fill='%23ffffff' opacity='0.9'/%3E%3Ccircle cx='75' cy='60' r='10' fill='%231a1a2e'/%3E%3Ccircle cx='125' cy='60' r='10' fill='%231a1a2e'/%3E%3Cpath d='M70 125 Q100 150 130 125' stroke='%231a1a2e' stroke-width='8' fill='none' stroke-linecap='round'/%3E%3C/svg%3E" alt="Avatar Andi">
</div>
</div>
</div>
</div>
</section>
<!-- ABOUT -->
<section id="page-about" class="page">
<div class="glass-card">
<h2 class="section-title"><i class="fas fa-user-astronaut"></i> Tentang Saya</h2>
<p class="subtitle">Kenalan lebih dekat — siapa saya dan apa yang saya kerjakan</p>
<div class="about-grid">
<div class="about-item">
<div class="label"><i class="fas fa-signature"></i> Nama</div>
<div class="value">Andi Pratama</div>
</div>
<div class="about-item">
<div class="label"><i class="fas fa-cake-candles"></i> Usia</div>
<div class="value">25 Tahun</div>
</div>
<div class="about-item">
<div class="label"><i class="fas fa-briefcase"></i> Pekerjaan</div>
<div class="value">Front-End Developer</div>
</div>
<div class="about-item">
<div class="label"><i class="fas fa-location-dot"></i> Lokasi</div>
<div class="value">Jakarta, Indonesia</div>
</div>
<div class="about-item">
<div class="label"><i class="fas fa-graduation-cap"></i> Pendidikan</div>
<div class="value">S1 Teknik Informatika</div>
</div>
<div class="about-item">
<div class="label"><i class="fas fa-heart"></i> Hobi</div>
<div class="value">Fotografi & Musik</div>
</div>
</div>
<div class="about-desc">
<p>
<strong>💬 Cerita saya:</strong> Ketertarikan saya pada dunia
teknologi dimulai sejak SMA, dan kini saya terus belajar hal baru
setiap hari. Saya percaya bahwa teknologi harus humanis, cepat,
dan menyenangkan digunakan. Di waktu luang, saya menikmati
fotografi, mendengarkan musik, dan mencoba resep kopi baru.
</p>
</div>
</div>
</section>
<!-- GALLERY -->
<section id="page-gallery" class="page">
<div class="glass-card">
<h2 class="section-title"><i class="fas fa-camera-retro"></i> Gallery</h2>
<p class="subtitle">Momen & karya yang saya banggakan</p>
<div class="gallery-grid">
<div class="gallery-item">
<div class="gallery-thumb">🌄</div>
<div class="gallery-info"><h4>Sunset di Bali</h4><p>Pantai Uluwatu, 2025</p></div>
</div>
<div class="gallery-item">
<div class="gallery-thumb">💻</div>
<div class="gallery-info"><h4>Workspace</h4><p>Setup minimalis</p></div>
</div>
<div class="gallery-item">
<div class="gallery-thumb">☕</div>
<div class="gallery-info"><h4>Kopi Pagi</h4><p>Single origin Toraja</p></div>
</div>
<div class="gallery-item">
<div class="gallery-thumb">🏙️</div>
<div class="gallery-info"><h4>Kota Malam</h4><p>Jakarta dari ketinggian</p></div>
</div>
<div class="gallery-item">
<div class="gallery-thumb">🎸</div>
<div class="gallery-info"><h4>Jamming Session</h4><p>Bersama teman-teman</p></div>
</div>
<div class="gallery-item">
<div class="gallery-thumb">🌿</div>
<div class="gallery-info"><h4>Taman Baca</h4><p>Sudut kota favorit</p></div>
</div>
</div>
</div>
</section>
<!-- CONTACT -->
<section id="page-contact" class="page">
<div class="glass-card">
<h2 class="section-title"><i class="fas fa-paper-plane"></i> Hubungi Saya</h2>
<p class="subtitle">Punya proyek atau sekadar ingin menyapa? Kirim pesan!</p>
<div class="contact-wrap">
<div class="contact-info">
<div class="info-item">
<div class="info-icon"><i class="fas fa-envelope"></i></div>
<div class="info-detail">
<div class="top">andi.pratama@email.com</div>
<div class="bottom">Email pribadi</div>
</div>
</div>
<div class="info-item">
<div class="info-icon"><i class="fas fa-phone"></i></div>
<div class="info-detail">
<div class="top">+62 812 3456 7890</div>
<div class="bottom">WhatsApp / Telepon</div>
</div>
</div>
<div class="info-item">
<div class="info-icon"><i class="fab fa-instagram"></i></div>
<div class="info-detail">
<div class="top">@andipratama.dev</div>
<div class="bottom">Instagram</div>
</div>
</div>
<div class="info-item">
<div class="info-icon"><i class="fab fa-linkedin-in"></i></div>
<div class="info-detail">
<div class="top">linkedin.com/in/andipratama</div>
<div class="bottom">LinkedIn</div>
</div>
</div>
</div>
<form class="contact-form" id="contactForm">
<div class="form-group">
<label for="name">Nama Lengkap</label>
<input type="text" id="name" placeholder="Masukkan nama Anda" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" placeholder="email@anda.com" required>
</div>
<div class="form-group">
<label for="message">Pesan</label>
<textarea id="message" placeholder="Tulis pesan Anda..." required></textarea>
</div>
<button type="submit" class="btn-submit">
<i class="fas fa-paper-plane"></i> Kirim Pesan
</button>
</form>
</div>
</div>
</section>
</main>
<!-- ============ FOOTER ============ -->
<footer>
© 2026 <strong>Andi Pratama</strong> — Dibuat dengan
<span class="heart">❤</span> dan secangkir kopi.
</footer>
<!-- ============ JAVASCRIPT ============ -->
<script>
(function () {
'use strict';
const navLinks = document.querySelectorAll('#navMenu a');
const pages = {
home: document.getElementById('page-home'),
about: document.getElementById('page-about'),
gallery: document.getElementById('page-gallery'),
contact: document.getElementById('page-contact')
};
const contactForm = document.getElementById('contactForm');
/* Navigasi antar halaman */
function navigateTo(pageId) {
if (!pages[pageId]) return;
Object.values(pages).forEach(p => p.classList.remove('active'));
navLinks.forEach(l => l.classList.remove('active'));
pages[pageId].classList.add('active');
navLinks.forEach(l => {
if (l.dataset.page === pageId) l.classList.add('active');
});
window.scrollTo({ top: 0, behavior: 'smooth' });
}
/* Klik link navigasi */
navLinks.forEach(link => {
link.addEventListener('click', function (e) {
e.preventDefault();
if (this.dataset.page) navigateTo(this.dataset.page);
});
});
/* Tombol lain dengan data-page */
document.querySelectorAll('[data-page]:not(#navMenu a)').forEach(btn => {
btn.addEventListener('click', function (e) {
e.preventDefault();
if (this.dataset.page) navigateTo(this.dataset.page);
});
});
/* Form kontak */
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();
if (!name || !email || !message) {
alert('⚠️ Semua kolom wajib diisi!');
return;
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
alert('⚠️ Format email tidak valid.');
return;
}
alert('✅ Pesan berhasil terkirim!\nTerima kasih, ' + name + '. Saya akan segera membalas.');
this.reset();
});
}
console.log('✨ Website profil modern siap digunakan!');
})();
</script>
</body>
</html>
Komentar
Posting Komentar