File manager - Edit - /home/webapp69.cm.in.th/u69319090045/portfolio/index.html
Back
<!DOCTYPE html> <html lang="th" id="html-root"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Khaowfang.dev | Portfolio - พรภวิษย์ ดอนศรีมอญ</title> <meta name="description" content="พอร์ตโฟลิโอของ นายพรภวิษย์ ดอนศรีมอญ (ข้าวฟ่าง) - นักศึกษา ปวส.1 วิทยาลัยเทคนิคเชียงใหม่"> <!-- Google Fonts: Prompt (Thai/EN) + Inter --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Prompt:wght@200;300;400;500;600;700&display=swap" rel="stylesheet"> <style> /* ===================================================== DESIGN TOKENS — Dark Mode (Default) ===================================================== */ :root { --bg-primary: #080c14; --bg-secondary: #0d1527; --bg-card: rgba(22, 32, 54, 0.72); --bg-card-hover: rgba(30, 45, 75, 0.88); --border-color: rgba(255,255,255,0.08); --border-hover: rgba(6,182,212,0.4); --text-primary: #f8fafc; --text-secondary: #94a3b8; --text-muted: #64748b; --color-cyan: #06b6d4; --color-purple: #8b5cf6; --gradient-primary: linear-gradient(135deg,#06b6d4 0%,#8b5cf6 100%); --gradient-text: linear-gradient(135deg,#22d3ee 0%,#a78bfa 100%); --font-main: 'Prompt', sans-serif; --transition: all 0.38s cubic-bezier(0.16,1,0.3,1); --shadow: 0 10px 30px -10px rgba(2,6,12,0.7); --glow: 0 0 28px rgba(6,182,212,0.28); /* background overlay — overridden by custom bg */ --body-bg-overlay: radial-gradient(circle at 10% 20%,rgba(6,182,212,0.06) 0%,transparent 40%), radial-gradient(circle at 90% 80%,rgba(139,92,246,0.06) 0%,transparent 45%); } /* ===================================================== Light Mode Tokens ===================================================== */ html.light { --bg-primary: #f0f4ff; --bg-secondary: #e2e8f4; --bg-card: rgba(255,255,255,0.82); --bg-card-hover: rgba(255,255,255,0.96); --border-color: rgba(0,0,0,0.08); --border-hover: rgba(6,182,212,0.55); --text-primary: #0f172a; --text-secondary: #475569; --text-muted: #94a3b8; --shadow: 0 10px 30px -10px rgba(0,0,0,0.12); --glow: 0 0 28px rgba(6,182,212,0.18); --body-bg-overlay: radial-gradient(circle at 10% 20%,rgba(6,182,212,0.08) 0%,transparent 40%), radial-gradient(circle at 90% 80%,rgba(139,92,246,0.08) 0%,transparent 45%); } /* ===================================================== RESET & BASE ===================================================== */ *, *::before, *::after { margin:0; padding:0; box-sizing:border-box; } html { scroll-behavior: smooth; } body { font-family: var(--font-main); background-color: var(--bg-primary); background-image: var(--body-bg-overlay); background-attachment: fixed; background-size: cover; background-position: center; color: var(--text-primary); line-height: 1.65; overflow-x: hidden; transition: background-color 0.45s ease, color 0.45s ease; } /* When custom background image is active */ body.has-custom-bg { background-size: cover; background-position: center; background-attachment: fixed; } /* Scrollbar */ ::-webkit-scrollbar { width: 7px; } ::-webkit-scrollbar-track { background: var(--bg-primary); } ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 10px; } ::-webkit-scrollbar-thumb:hover { background: var(--color-cyan); } /* ===================================================== UTILITY ===================================================== */ .container { width: 100%; max-width: 1100px; margin: 0 auto; padding: 0 1.5rem; position: relative; z-index: 2; } .gradient-text { background: var(--gradient-text); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 0.75rem 1.75rem; border-radius: 50px; font-family: var(--font-main); font-size: 1rem; font-weight: 500; cursor: pointer; text-decoration: none; border: 1px solid transparent; transition: var(--transition); } .btn-primary { background: var(--gradient-primary); color: #fff; box-shadow: 0 4px 16px rgba(6,182,212,0.22); } .btn-primary:hover { transform: translateY(-3px); box-shadow: 0 8px 28px rgba(6,182,212,0.42), var(--glow); } .btn-secondary { background: transparent; color: var(--text-primary); border-color: var(--border-color); } .btn-secondary:hover { border-color: var(--color-cyan); background: rgba(6,182,212,0.06); transform: translateY(-3px); } /* ===================================================== FLOATING GLOW BLOBS (decorative) ===================================================== */ .blob { position: fixed; border-radius: 50%; background: var(--gradient-primary); filter: blur(130px); opacity: 0.1; pointer-events: none; z-index: 0; } .blob-1 { width:400px; height:400px; top:10%; left:0; } .blob-2 { width:350px; height:350px; bottom:10%; right:0; } html.light .blob { opacity: 0.06; } /* ===================================================== HEADER / NAV ===================================================== */ header { position: fixed; inset: 0 0 auto 0; height: 76px; display: flex; align-items: center; z-index: 100; transition: var(--transition); } header.scrolled { background: rgba(8,12,20,0.82); backdrop-filter: blur(18px); border-bottom: 1px solid var(--border-color); box-shadow: var(--shadow); } html.light header.scrolled { background: rgba(240,244,255,0.82); } .navbar { display: flex; justify-content: space-between; align-items: center; width: 100%; } .logo { font-size: 1.45rem; font-weight: 700; text-decoration: none; color: var(--text-primary); } /* Nav right side: links + controls */ .nav-right { display: flex; align-items: center; gap: 2rem; } .nav-links { list-style: none; display: flex; gap: 2.2rem; } .nav-link { text-decoration: none; color: var(--text-secondary); font-size: 0.97rem; font-weight: 400; transition: var(--transition); position: relative; padding: 4px 0; } .nav-link::after { content:''; position: absolute; bottom: 0; left: 0; width: 0; height: 2px; background: var(--gradient-primary); transition: var(--transition); } .nav-link:hover, .nav-link.active { color: var(--text-primary); } .nav-link:hover::after, .nav-link.active::after { width: 100%; } /* --- Controls cluster --- */ .controls-cluster { display: flex; align-items: center; gap: 10px; } /* Dark/Light toggle button */ .theme-btn { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--border-color); background: var(--bg-card); color: var(--text-primary); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: var(--transition); font-size: 1.15rem; } .theme-btn:hover { border-color: var(--color-cyan); background: rgba(6,182,212,0.1); } /* Background picker button */ .bg-btn { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--border-color); background: var(--bg-card); color: var(--text-primary); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: var(--transition); font-size: 1.15rem; } .bg-btn:hover { border-color: var(--color-purple); background: rgba(139,92,246,0.1); } /* Mobile hamburger */ .hamburger { display: none; flex-direction: column; gap: 5px; background: none; border: none; cursor: pointer; } .hamburger span { width: 24px; height: 2px; background: var(--text-primary); border-radius: 2px; transition: var(--transition); } .hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); } .hamburger.open span:nth-child(2) { opacity: 0; } .hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } @media(max-width:768px) { .hamburger { display: flex; } .nav-links { position: fixed; top: 0; right: -100%; width: 72%; max-width: 280px; height: 100vh; background: var(--bg-secondary); flex-direction: column; justify-content: center; align-items: center; gap: 2.5rem; border-left: 1px solid var(--border-color); transition: right 0.4s cubic-bezier(0.16,1,0.3,1); z-index: 99; } .nav-links.open { right: 0; } } /* ===================================================== BACKGROUND PICKER PANEL ===================================================== */ .bg-panel { position: fixed; top: 90px; right: -340px; width: 320px; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 22px; padding: 1.5rem; z-index: 99; transition: right 0.4s cubic-bezier(0.16,1,0.3,1); box-shadow: var(--shadow); } .bg-panel.open { right: 20px; } .bg-panel h4 { font-size: 1rem; margin-bottom: 1rem; color: var(--text-primary); display: flex; align-items: center; gap: 8px; } /* Preset swatches */ .bg-presets { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 1rem; } .bg-swatch { width: 100%; aspect-ratio: 1; border-radius: 12px; cursor: pointer; border: 2px solid transparent; transition: var(--transition); } .bg-swatch:hover { transform: scale(1.08); border-color: var(--color-cyan); } .bg-swatch.active { border-color: var(--color-cyan); box-shadow: 0 0 10px rgba(6,182,212,0.5); } /* Upload area */ .upload-area { border: 2px dashed var(--border-color); border-radius: 16px; padding: 1.2rem; text-align: center; cursor: pointer; transition: var(--transition); color: var(--text-secondary); font-size: 0.9rem; } .upload-area:hover { border-color: var(--color-purple); background: rgba(139,92,246,0.05); } .upload-area .upload-icon { font-size: 2rem; margin-bottom: 6px; } .upload-area p { margin: 0; } #bgFileInput { display: none; } .bg-reset-btn { width: 100%; margin-top: 0.75rem; padding: 0.6rem; border-radius: 12px; background: rgba(255,255,255,0.05); border: 1px solid var(--border-color); color: var(--text-secondary); font-family: var(--font-main); font-size: 0.9rem; cursor: pointer; transition: var(--transition); } .bg-reset-btn:hover { border-color: var(--color-cyan); color: var(--text-primary); } /* ===================================================== HERO SECTION ===================================================== */ .hero { min-height: 100vh; display: flex; align-items: center; padding-top: 96px; position: relative; overflow: hidden; } .hero-grid { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 3rem; align-items: center; } /* Text side */ .hero-eyebrow { display: flex; align-items: center; gap: 10px; color: var(--color-cyan); font-size: 1rem; font-weight: 500; margin-bottom: 1rem; } .hero-eyebrow::before { content: ''; width: 28px; height: 2px; background: var(--color-cyan); } .hero-title { font-size: 3.2rem; line-height: 1.18; margin-bottom: 1.25rem; } .hero-typing-wrap { font-size: 1.6rem; color: var(--text-secondary); display: flex; align-items: center; min-height: 40px; margin-bottom: 1.75rem; } .cursor { width: 3px; height: 26px; background: var(--color-cyan); margin-left: 4px; animation: blink 0.85s infinite; } @keyframes blink { 50% { opacity:0; } } .hero-bio { color: var(--text-secondary); font-size: 1.05rem; max-width: 540px; margin-bottom: 2.25rem; } .hero-btns { display: flex; gap: 1.2rem; flex-wrap: wrap; } /* Profile card side */ .hero-visual { display: flex; justify-content: center; align-items: center; position: relative; } /* ------ Profile: Square Frame (กรอบสี่เหลี่ยม) ------ */ .profile-wrap { position: relative; display: inline-block; } /* Outer glow ring (decorative) */ .profile-wrap::before { content: ''; position: absolute; inset: -4px; border-radius: 16px; background: var(--gradient-primary); z-index: 0; opacity: 0.65; transition: var(--transition); } .profile-wrap:hover::before { opacity: 1; filter: blur(4px); } .profile-frame { position: relative; width: 310px; height: 310px; border-radius: 12px; /* กรอบสี่เหลี่ยมมุมโค้งเล็กน้อย */ overflow: hidden; border: 3px solid transparent; background-clip: padding-box; box-shadow: 0 8px 32px rgba(0,0,0,0.45), var(--glow); transition: var(--transition); z-index: 1; } .profile-frame:hover { transform: translateY(-6px) scale(1.025); box-shadow: 0 16px 48px rgba(0,0,0,0.5), 0 0 40px rgba(6,182,212,0.45); } .profile-frame img { width: 100%; height: 100%; object-fit: cover; object-position: center top; /* ตัดรูปให้เห็นใบหน้า */ display: block; transition: var(--transition); } .profile-frame:hover img { transform: scale(1.04); } /* Name badge — sits below the frame */ .profile-badge { margin-top: 14px; position: relative; padding: 0.75rem 1.2rem; background: var(--bg-card); backdrop-filter: blur(12px); border: 1px solid var(--border-color); border-radius: 14px; text-align: center; z-index: 1; transition: var(--transition); } html.light .profile-badge { background: rgba(255,255,255,0.88); } .profile-badge h4 { font-size: 0.97rem; font-weight: 600; color: var(--text-primary); } .profile-badge p { font-size: 0.78rem; color: var(--color-cyan); margin-top: 3px; } /* Floating decoration */ .deco { position: absolute; border-radius: 50%; background: var(--gradient-primary); filter: blur(28px); opacity: 0.18; animation: float 7s ease-in-out infinite; } .deco-1 { width:110px; height:110px; top:-15px; right:-15px; } .deco-2 { width:140px; height:140px; bottom:-20px; left:-20px; animation-delay:-3.5s; } @keyframes float { 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-14px); } } @media(max-width:940px) { .hero-grid { grid-template-columns: 1fr; text-align: center; gap: 3.5rem; } .hero-eyebrow { justify-content: center; } .hero-eyebrow::before { display: none; } .hero-bio { margin: 0 auto 2rem; } .hero-btns { justify-content: center; } .hero-typing-wrap { justify-content: center; } } @media(max-width:480px) { .hero-title { font-size: 2.2rem; } .profile-frame { width: 250px; height: 250px; } /* keep square on mobile */ } /* Camera overlay — hover to change profile photo */ .profile-change-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.48); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; opacity: 0; transition: opacity 0.3s ease; cursor: pointer; z-index: 5; border-radius: 12px; } .profile-frame:hover .profile-change-overlay { opacity: 1; } .profile-change-overlay span { font-size: 2rem; } .profile-change-overlay p { font-size: 0.75rem; color: #fff; font-weight: 500; margin: 0; } #profileFileInput { display: none; } /* ===================================================== ABOUT SECTION ===================================================== */ .about-section { padding: 8rem 0; position: relative; } .section-title { text-align: center; margin-bottom: 3.5rem; } .section-title h2 { font-size: 2.1rem; display: inline-block; position: relative; margin-bottom: 0.75rem; } .section-title h2::after { content:''; position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%); width: 56px; height: 3px; background: var(--gradient-primary); border-radius: 2px; } .section-title p { color: var(--text-secondary); font-size: 1.05rem; max-width: 580px; margin: 0 auto; } /* Info cards grid */ .info-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1.5rem; margin-bottom: 2.5rem; } .info-card { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 20px; padding: 1.5rem; display: flex; gap: 1rem; align-items: flex-start; transition: var(--transition); backdrop-filter: blur(10px); } .info-card:hover { transform: translateY(-5px); border-color: var(--border-hover); background: var(--bg-card-hover); } .info-card-icon { width: 44px; height: 44px; border-radius: 12px; background: rgba(6,182,212,0.1); color: var(--color-cyan); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .info-card-text h4 { font-size: 0.82rem; color: var(--text-muted); font-weight: 500; margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.05em; } .info-card-text p { font-size: 1.05rem; font-weight: 600; color: var(--text-primary); } /* Bio text */ .bio-box { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 24px; padding: 2rem 2.5rem; backdrop-filter: blur(10px); transition: var(--transition); } .bio-box p { color: var(--text-secondary); font-size: 1.08rem; line-height: 1.8; } .bio-box p strong { color: var(--text-primary); } /* ===================================================== CONTACT SECTION ===================================================== */ .contact-section { padding: 8rem 0; background: var(--bg-secondary); position: relative; } html.light .contact-section { background: var(--bg-secondary); } .contact-grid { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: 3.5rem; align-items: start; } /* Contact info panel */ .contact-info-panel { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 28px; padding: 2.25rem; display: flex; flex-direction: column; gap: 1.75rem; backdrop-filter: blur(10px); } .contact-info-panel h3 { font-size: 1.45rem; } .contact-item { display: flex; align-items: center; gap: 1.1rem; text-decoration: none; color: var(--text-secondary); transition: var(--transition); } a.contact-item:hover { color: var(--color-cyan); transform: translateX(5px); } a.contact-item:hover .c-icon { background: var(--gradient-primary); color:#fff; box-shadow: 0 0 14px rgba(6,182,212,0.35); } .c-icon { width: 48px; height: 48px; border-radius: 14px; background: rgba(6,182,212,0.08); border: 1px solid rgba(6,182,212,0.15); color: var(--color-cyan); display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: var(--transition); } .c-text h4 { font-size: 0.76rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 500; } .c-text p { font-size: 1rem; font-weight: 500; color: var(--text-primary); } /* Form panel */ .contact-form-panel { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 28px; padding: 2.25rem; backdrop-filter: blur(10px); } .contact-form-panel h3 { font-size: 1.45rem; margin-bottom: 1.75rem; } .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin-bottom: 1.25rem; } .form-group { position: relative; margin-bottom: 1.25rem; } .form-input, .form-textarea { width: 100%; background: rgba(8,12,20,0.5); border: 1px solid var(--border-color); border-radius: 12px; padding: 1rem 1.2rem; font-family: var(--font-main); color: var(--text-primary); font-size: 0.97rem; transition: var(--transition); outline: none; } html.light .form-input, html.light .form-textarea { background: rgba(255,255,255,0.65); } .form-textarea { resize: none; min-height: 140px; } .form-group label { position: absolute; left: 1.2rem; top: 1rem; color: var(--text-muted); pointer-events: none; transition: var(--transition); font-size: 0.97rem; background: transparent; } .form-input:focus ~ label, .form-input:not(:placeholder-shown) ~ label, .form-textarea:focus ~ label, .form-textarea:not(:placeholder-shown) ~ label { top: -0.55rem; left: 0.75rem; font-size: 0.75rem; padding: 0 0.4rem; background: var(--bg-secondary); border-radius: 4px; color: var(--color-cyan); } .form-input:focus, .form-textarea:focus { border-color: var(--color-cyan); box-shadow: 0 0 10px rgba(6,182,212,0.14); } @media(max-width:940px) { .contact-grid { grid-template-columns:1fr; gap:2.5rem; } } @media(max-width:520px) { .form-row { grid-template-columns:1fr; } .contact-info-panel, .contact-form-panel { padding:1.5rem; } } /* ===================================================== FOOTER ===================================================== */ footer { border-top: 1px solid var(--border-color); background: var(--bg-primary); padding: 2.5rem 0; } .footer-inner { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.2rem; } .footer-copy { color: var(--text-muted); font-size: 0.9rem; } .scroll-top { width: 42px; height: 42px; border-radius: 50%; background: var(--bg-card); border: 1px solid var(--border-color); color: var(--text-primary); display: flex; align-items: center; justify-content: center; text-decoration: none; transition: var(--transition); } .scroll-top:hover { background: var(--color-cyan); color:#fff; transform:translateY(-5px); box-shadow: var(--glow); } @media(max-width:480px) { .footer-inner { flex-direction:column-reverse; text-align:center; } } /* ===================================================== TOAST NOTIFICATION ===================================================== */ .toast { position: fixed; bottom: -90px; right: 28px; background: var(--gradient-primary); color: #fff; padding: 0.9rem 1.75rem; border-radius: 16px; box-shadow: var(--shadow); display: flex; align-items: center; gap: 10px; z-index: 500; font-weight: 500; transition: transform 0.5s cubic-bezier(0.175,0.885,0.32,1.275); } .toast.show { transform: translateY(-115px); } </style> </head> <body> <!-- Decorative blobs --> <div class="blob blob-1"></div> <div class="blob blob-2"></div> <!-- ================================================= HEADER ================================================= --> <header id="site-header"> <div class="container navbar"> <a href="#home" class="logo"> Khaowfang<span class="gradient-text">.dev</span> </a> <div class="nav-right"> <!-- Nav links --> <ul class="nav-links" id="nav-links"> <li><a href="#home" class="nav-link active" onclick="closeMenu()">หน้าแรก</a></li> <li><a href="#about" class="nav-link" onclick="closeMenu()">เกี่ยวกับฉัน</a></li> <li><a href="#contact" class="nav-link" onclick="closeMenu()">ติดต่อ</a></li> </ul> <!-- Controls: theme + bg-picker --> <div class="controls-cluster"> <!-- Dark/Light toggle --> <button class="theme-btn" id="theme-btn" aria-label="สลับโหมดมืด/สว่าง" title="สลับโหมดมืด/สว่าง"> 🌙 </button> <!-- Background picker --> <button class="bg-btn" id="bg-btn" aria-label="เปลี่ยนพื้นหลัง" title="เปลี่ยนพื้นหลัง"> 🖼️ </button> </div> <!-- Hamburger --> <button class="hamburger" id="hamburger" aria-label="เมนู"> <span></span><span></span><span></span> </button> </div> </div> </header> <!-- ================================================= BACKGROUND PICKER PANEL ================================================= --> <div class="bg-panel" id="bg-panel"> <h4>🎨 เปลี่ยนพื้นหลัง</h4> <!-- Preset colour / gradient swatches --> <div class="bg-presets" id="bg-presets"> <!-- Swatch: Default dark --> <div class="bg-swatch active" style="background: linear-gradient(135deg,#080c14,#0d1527);" data-bg="default" onclick="applyPresetBg(this, 'default')" title="Dark Default"></div> <!-- Swatch: Ocean blue --> <div class="bg-swatch" style="background: linear-gradient(135deg,#001f3f,#0077b6);" data-bg="linear-gradient(135deg,#001f3f,#0077b6)" onclick="applyPresetBg(this, this.dataset.bg)" title="Ocean"></div> <!-- Swatch: Forest green --> <div class="bg-swatch" style="background: linear-gradient(135deg,#0a1a0a,#145214);" data-bg="linear-gradient(135deg,#0a1a0a,#145214)" onclick="applyPresetBg(this, this.dataset.bg)" title="Forest"></div> <!-- Swatch: Sunset purple --> <div class="bg-swatch" style="background: linear-gradient(135deg,#1a0033,#6a0dad);" data-bg="linear-gradient(135deg,#1a0033,#6a0dad)" onclick="applyPresetBg(this, this.dataset.bg)" title="Twilight"></div> <!-- Swatch: Lanna red gold --> <div class="bg-swatch" style="background: linear-gradient(135deg,#3d0000,#b8860b);" data-bg="linear-gradient(135deg,#3d0000,#b8860b)" onclick="applyPresetBg(this, this.dataset.bg)" title="Lanna Gold"></div> <!-- Swatch: Cyan-teal --> <div class="bg-swatch" style="background: linear-gradient(135deg,#003333,#006d6d);" data-bg="linear-gradient(135deg,#003333,#006d6d)" onclick="applyPresetBg(this, this.dataset.bg)" title="Teal"></div> <!-- Swatch: Light minimal --> <div class="bg-swatch" style="background: linear-gradient(135deg,#f0f4ff,#e2e8f4);" data-bg="linear-gradient(135deg,#f0f4ff,#e2e8f4)" onclick="applyPresetBg(this, this.dataset.bg)" title="Light Minimal"></div> <!-- Swatch: Neon night --> <div class="bg-swatch" style="background: linear-gradient(135deg,#0a0015,#1a003a);" data-bg="linear-gradient(135deg,#0a0015,#1a003a)" onclick="applyPresetBg(this, this.dataset.bg)" title="Neon Night"></div> </div> <!-- Upload custom image --> <div class="upload-area" onclick="document.getElementById('bgFileInput').click()"> <div class="upload-icon">📁</div> <p>คลิกเพื่ออัปโหลดรูปพื้นหลัง<br><small style="color:var(--text-muted)">รองรับ JPG, PNG, WEBP, GIF</small></p> </div> <input type="file" id="bgFileInput" accept="image/*" onchange="handleBgUpload(event)"> <!-- Reset --> <button class="bg-reset-btn" onclick="resetBackground()">↺ รีเซ็ตพื้นหลัง</button> </div> <!-- ================================================= HERO SECTION ================================================= --> <section id="home" class="hero"> <div class="container hero-grid"> <!-- Left: Text --> <div class="hero-content"> <div class="hero-eyebrow">ยินดีต้อนรับสู่พอร์ตโฟลิโอของผม</div> <h1 class="hero-title"> สวัสดีครับ, ผม<br> <span class="gradient-text">พรภวิษย์ ดอนศรีมอญ</span> </h1> <!-- Typewriter --> <div class="hero-typing-wrap"> <span id="typewriter"></span> <span class="cursor"></span> </div> <p class="hero-bio"> นักศึกษา ปวส.1 สาขาเทคโนโลยีคอมพิวเตอร์ วิทยาลัยเทคนิคเชียงใหม่ ผู้ที่หลงใหลในการพัฒนา Front-end และงานออกแบบ UX/UI มุ่งมั่นสร้างประสบการณ์ดิจิทัลที่สวยงามและลื่นไหล </p> <div class="hero-btns"> <a href="#about" class="btn btn-primary">เกี่ยวกับฉัน <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg></a> <a href="#contact" class="btn btn-secondary">ติดต่อผม</a> </div> </div> <!-- Right: Profile photo (กรอบสี่เหลี่ยม) --> <div class="hero-visual"> <div class="profile-wrap"> <!-- กรอบสี่เหลี่ยมรูปโปรไฟล์ --> <div class="profile-frame"> <!-- ================================================ 📌 วิธีใส่รูปจริง: บันทึกรูปภาพลงในโฟลเดอร์: c:\xampp\htdocs\69319090045\images\profile.jpg หรือ hover ที่รูปแล้วกด 📷 เพื่ออัปโหลดจากเครื่อง ================================================ --> <img id="profile-img" src="images/profile.jpg" onerror="this.onerror=null; this.src='https://images.unsplash.com/photo-1519085360753-af0119f7cbe7?auto=format&fit=crop&w=600&q=80'" alt="นายพรภวิษย์ ดอนศรีมอญ (ข้าวฟ่าง)" > <!-- Hover overlay to change photo --> <div class="profile-change-overlay" onclick="document.getElementById('profileFileInput').click()"> <span>📷</span> <p>เปลี่ยนรูปโปรไฟล์</p> </div> </div> <input type="file" id="profileFileInput" accept="image/*" onchange="changeProfilePhoto(event)"> <!-- ป้ายชื่อ อยู่ด้านล่างกรอบ --> <div class="profile-badge"> <h4>พรภวิษย์ ดอนศรีมอญ (ข้าวฟ่าง)</h4> <p>ปวส.1 วิทยาลัยเทคนิคเชียงใหม่</p> </div> </div> <div class="deco deco-1"></div> <div class="deco deco-2"></div> </div> </div> </section> <!-- ================================================= ABOUT SECTION ================================================= --> <section id="about" class="about-section"> <div class="container"> <div class="section-title"> <h2>เกี่ยวกับตัวผม</h2> <p>ประวัติส่วนตัวและข้อมูลการศึกษาของ นายพรภวิษย์ ดอนศรีมอญ</p> </div> <!-- Info cards --> <div class="info-cards"> <!-- ชื่อ-นามสกุล --> <div class="info-card"> <div class="info-card-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> </div> <div class="info-card-text"> <h4>ชื่อ-นามสกุล</h4> <p>นายพรภวิษย์ ดอนศรีมอญ</p> </div> </div> <!-- ชื่อเล่น --> <div class="info-card"> <div class="info-card-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 10c-.83 0-1.5-.67-1.5-1.5v-5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5v5c0 .83-.67 1.5-1.5 1.5z"/><path d="M20.5 10H19V8.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/><path d="M9.5 14c.83 0 1.5.67 1.5 1.5v5c0 .83-.67 1.5-1.5 1.5S8 21.33 8 20.5v-5c0-.83.67-1.5 1.5-1.5z"/><path d="M3.5 14H5v1.5c0 .83-.67 1.5-1.5 1.5S2 16.33 2 15.5 2.67 14 3.5 14z"/><path d="M14 14.5c0-.83.67-1.5 1.5-1.5h5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-5c-.83 0-1.5-.67-1.5-1.5z"/><path d="M15.5 19H14v1.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"/><path d="M10 9.5C10 8.67 9.33 8 8.5 8h-5C2.67 8 2 8.67 2 9.5S2.67 11 3.5 11h5c.83 0 1.5-.67 1.5-1.5z"/><path d="M8.5 5H10V3.5C10 2.67 9.33 2 8.5 2S7 2.67 7 3.5 7.67 5 8.5 5z"/></svg> </div> <div class="info-card-text"> <h4>ชื่อเล่น</h4> <p>ข้าวฟ่าง</p> </div> </div> <!-- อายุ --> <div class="info-card"> <div class="info-card-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg> </div> <div class="info-card-text"> <h4>อายุ / วันเกิด</h4> <p>21 ปี (30 มิ.ย. 2548)</p> </div> </div> <!-- การศึกษา --> <div class="info-card"> <div class="info-card-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c0 2 2 3 6 3s6-1 6-3v-5"/></svg> </div> <div class="info-card-text"> <h4>การศึกษา</h4> <p>ปวส.1 วิทยาลัยเทคนิคเชียงใหม่</p> </div> </div> <!-- สถานที่ --> <div class="info-card"> <div class="info-card-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg> </div> <div class="info-card-text"> <h4>สถานที่เรียน</h4> <p>เชียงใหม่, ประเทศไทย</p> </div> </div> <!-- สายงาน --> <div class="info-card"> <div class="info-card-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg> </div> <div class="info-card-text"> <h4>สายงานที่สนใจ</h4> <p>Front-end / UX/UI Design</p> </div> </div> </div> <!-- Bio --> <div class="bio-box"> <p> กระผม <strong>นายพรภวิษย์ ดอนศรีมอญ (ข้าวฟ่าง)</strong> อายุ 21 ปี เกิดวันที่ 30 มิถุนายน พ.ศ. 2548 ปัจจุบันกำลังศึกษาอยู่ในระดับ <strong>ปวส.1 วิทยาลัยเทคนิคเชียงใหม่</strong> สาขาเทคโนโลยีคอมพิวเตอร์ มีความสนใจและชื่นชอบงานด้านการพัฒนาเว็บไซต์ (Front-end Development) รวมถึงงานออกแบบ UI/UX ที่ใส่ใจประสบการณ์ผู้ใช้งาน มุ่งมั่นพัฒนาตัวเองและนำความรู้ที่เรียนมาใช้ให้เกิดประโยชน์สูงสุด </p> </div> </div> </section> <!-- ================================================= CONTACT SECTION ================================================= --> <section id="contact" class="contact-section"> <div class="container"> <div class="section-title"> <h2>ติดต่อผม</h2> <p>มีคำถามหรืออยากพูดคุย? ส่งข้อความมาหาผมได้เลยครับ!</p> </div> <div class="contact-grid"> <!-- Left: Contact details --> <div class="contact-info-panel"> <h3>ช่องทางติดต่อ</h3> <a href="mailto:phonphawit.dev@gmail.com" class="contact-item"> <div class="c-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg> </div> <div class="c-text"> <h4>อีเมล</h4> <p>phonphawit.dev@gmail.com</p> </div> </a> <a href="https://github.com/Khaowfang-PD" target="_blank" rel="noopener noreferrer" class="contact-item"> <div class="c-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg> </div> <div class="c-text"> <h4>GitHub</h4> <p>github.com/Khaowfang-PD</p> </div> </a> <a href="https://linkedin.com/in/phonphawit-donsrimon" target="_blank" rel="noopener noreferrer" class="contact-item"> <div class="c-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></svg> </div> <div class="c-text"> <h4>LinkedIn</h4> <p>linkedin.com/in/phonphawit</p> </div> </a> <!-- เบอร์โทรศัพท์ --> <a href="tel:0946037755" class="contact-item"> <div class="c-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 12a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.6 1.17h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.91 8.73a16 16 0 0 0 6.29 6.29l1.13-1.12a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z"/></svg> </div> <div class="c-text"> <h4>เบอร์โทรศัพท์</h4> <p>094-603-7755</p> </div> </a> <!-- ที่อยู่บ้าน --> <div class="contact-item"> <div class="c-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg> </div> <div class="c-text"> <h4>ที่อยู่บ้าน</h4> <p>159 ม.11 ต.หนองหาร อ.สันทราย จ.เชียงใหม่ 50290</p> </div> </div> <!-- ที่อยู่สถานที่เรียน --> <div class="contact-item"> <div class="c-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg> </div> <div class="c-text"> <h4>สถานที่เรียน</h4> <p>วิทยาลัยเทคนิคเชียงใหม่ ถ.เวียงแก้ว ต.ศรีภูมิ อ.เมือง จ.เชียงใหม่</p> </div> </div> </div> <!-- Right: Contact form (mock) --> <div class="contact-form-panel"> <h3>ส่งข้อความหาผม</h3> <form id="contactForm" onsubmit="handleForm(event)"> <div class="form-row"> <div class="form-group"> <input type="text" id="cName" class="form-input" placeholder=" " required> <label for="cName">ชื่อผู้ติดต่อ</label> </div> <div class="form-group"> <input type="email" id="cEmail" class="form-input" placeholder=" " required> <label for="cEmail">อีเมล</label> </div> </div> <div class="form-group"> <input type="text" id="cSubject" class="form-input" placeholder=" " required> <label for="cSubject">หัวเรื่อง</label> </div> <div class="form-group"> <textarea id="cMessage" class="form-textarea" placeholder=" " required></textarea> <label for="cMessage">ข้อความของคุณ</label> </div> <button type="submit" class="btn btn-primary" style="width:100%"> ส่งข้อความ <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg> </button> </form> </div> </div> </div> </section> <!-- ================================================= FOOTER ================================================= --> <footer> <div class="container footer-inner"> <p class="footer-copy">© 2026 Khaowfang.dev · พัฒนาโดย นายพรภวิษย์ ดอนศรีมอญ</p> <a href="#home" class="scroll-top" aria-label="กลับขึ้นบน"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg> </a> </div> </footer> <!-- Toast --> <div class="toast" id="toast"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg> <span>ส่งข้อความจำลองสำเร็จ! ขอบคุณครับ 🙏</span> </div> <!-- ================================================= JAVASCRIPT ================================================= --> <script> /* ------------------------------------------------------- 1. Header scroll effect ------------------------------------------------------- */ const header = document.getElementById('site-header'); window.addEventListener('scroll', () => { header.classList.toggle('scrolled', window.scrollY > 50); }); /* ------------------------------------------------------- 2. Mobile hamburger menu ------------------------------------------------------- */ const hamburger = document.getElementById('hamburger'); const navLinks = document.getElementById('nav-links'); hamburger.addEventListener('click', () => { hamburger.classList.toggle('open'); navLinks.classList.toggle('open'); }); function closeMenu() { hamburger.classList.remove('open'); navLinks.classList.remove('open'); } /* ------------------------------------------------------- 3. ScrollSpy — highlight active nav link ------------------------------------------------------- */ const sections = document.querySelectorAll('section[id]'); const links = document.querySelectorAll('.nav-link'); window.addEventListener('scroll', () => { let current = ''; sections.forEach(s => { if (window.scrollY >= s.offsetTop - 220) current = s.id; }); links.forEach(l => { l.classList.toggle('active', l.getAttribute('href') === `#${current}`); }); }); /* ------------------------------------------------------- 4. Typewriter Effect (Hero) ------------------------------------------------------- */ const phrases = [ 'นักพัฒนา Front-end รุ่นใหม่ 💻', 'นักออกแบบ UX/UI ที่ใฝ่ฝัน 🎨', 'นักศึกษา ปวส.1 เทคนิคเชียงใหม่ 🎓' ]; let pi = 0, ci = 0, deleting = false, speed = 110; function typeLoop() { const phrase = phrases[pi]; const tw = document.getElementById('typewriter'); if (!deleting) { tw.textContent = phrase.substring(0, ci + 1); ci++; speed = 115; if (ci === phrase.length) { deleting = true; speed = 2600; } } else { tw.textContent = phrase.substring(0, ci - 1); ci--; speed = 52; if (ci === 0) { deleting = false; pi = (pi + 1) % phrases.length; speed = 480; } } setTimeout(typeLoop, speed); } typeLoop(); /* ------------------------------------------------------- 5. Dark / Light Mode Toggle ------------------------------------------------------- */ const htmlRoot = document.getElementById('html-root'); const themeBtn = document.getElementById('theme-btn'); // Restore saved preference if (localStorage.getItem('theme') === 'light') { htmlRoot.classList.add('light'); themeBtn.textContent = '☀️'; } themeBtn.addEventListener('click', () => { const isLight = htmlRoot.classList.toggle('light'); themeBtn.textContent = isLight ? '☀️' : '🌙'; localStorage.setItem('theme', isLight ? 'light' : 'dark'); }); /* ------------------------------------------------------- 6. Background Picker Panel toggle ------------------------------------------------------- */ const bgBtn = document.getElementById('bg-btn'); const bgPanel = document.getElementById('bg-panel'); bgBtn.addEventListener('click', (e) => { e.stopPropagation(); bgPanel.classList.toggle('open'); }); // Close panel when clicking outside document.addEventListener('click', (e) => { if (!bgPanel.contains(e.target) && e.target !== bgBtn) { bgPanel.classList.remove('open'); } }); /* ------------------------------------------------------- 7. Preset Background Swatches ------------------------------------------------------- */ function applyPresetBg(el, value) { // Remove active from all swatches document.querySelectorAll('.bg-swatch').forEach(s => s.classList.remove('active')); el.classList.add('active'); const body = document.body; if (value === 'default') { body.style.backgroundImage = ''; body.style.backgroundSize = ''; body.classList.remove('has-custom-bg'); // Restore CSS variable gradient body.style.removeProperty('background-image'); } else { body.style.backgroundImage = value; body.style.backgroundSize = 'cover'; body.classList.add('has-custom-bg'); } localStorage.setItem('customBg', value); } /* ------------------------------------------------------- 8. Upload Custom Background Image ------------------------------------------------------- */ function handleBgUpload(event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const dataUrl = e.target.result; const body = document.body; body.style.backgroundImage = `url('${dataUrl}')`; body.style.backgroundSize = 'cover'; body.style.backgroundPosition = 'center'; body.style.backgroundAttachment = 'fixed'; body.classList.add('has-custom-bg'); // Clear swatch active state document.querySelectorAll('.bg-swatch').forEach(s => s.classList.remove('active')); // Save to localStorage (caution: large files may exceed storage quota) try { localStorage.setItem('customBg', `url('${dataUrl}')`); } catch(e) { console.warn('LocalStorage quota exceeded for large image — bg will not persist on reload.'); } }; reader.readAsDataURL(file); } /* ------------------------------------------------------- 9. Reset Background ------------------------------------------------------- */ function resetBackground() { const body = document.body; body.style.backgroundImage = ''; body.style.backgroundSize = ''; body.style.backgroundPosition = ''; body.classList.remove('has-custom-bg'); localStorage.removeItem('customBg'); document.querySelectorAll('.bg-swatch').forEach(s => s.classList.remove('active')); document.querySelector('.bg-swatch[data-bg="default"]').classList.add('active'); } /* ------------------------------------------------------- 10. Restore saved background on page load ------------------------------------------------------- */ (function restoreBg() { const saved = localStorage.getItem('customBg'); if (!saved || saved === 'default') return; const body = document.body; body.style.backgroundImage = saved; body.style.backgroundSize = 'cover'; body.style.backgroundPosition = 'center'; body.style.backgroundAttachment = 'fixed'; body.classList.add('has-custom-bg'); // Mark matching swatch if gradient preset document.querySelectorAll('.bg-swatch').forEach(s => { if (s.dataset.bg === saved) s.classList.add('active'); }); })(); /* ------------------------------------------------------- 11. Contact Form (mock submit) ------------------------------------------------------- */ function handleForm(e) { e.preventDefault(); document.getElementById('contactForm').reset(); const toast = document.getElementById('toast'); toast.classList.add('show'); setTimeout(() => toast.classList.remove('show'), 4500); } /* ------------------------------------------------------- 12. Change Profile Photo (hover + file upload) ------------------------------------------------------- */ function changeProfilePhoto(event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const dataUrl = e.target.result; // Update displayed image immediately document.getElementById('profile-img').src = dataUrl; // Persist to localStorage so it survives page refresh try { localStorage.setItem('profilePhoto', dataUrl); } catch (err) { console.warn('LocalStorage quota exceeded — large profile image won\'t persist on reload.'); } }; reader.readAsDataURL(file); // Reset input so same file can be re-selected event.target.value = ''; } // Restore saved profile photo on page load (function restoreProfilePhoto() { const saved = localStorage.getItem('profilePhoto'); if (saved) { const img = document.getElementById('profile-img'); if (img) img.src = saved; } })(); </script> </body> </html>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.36 |
proxy
|
phpinfo
|
Settings