feat: 쇼핑몰 샘플 추가, 홈페이지 서비스 페이지 재디자인, 공통 UI 개선
- 모든 샘플 페이지 우측 하단 맨 위로 스크롤 버튼 추가 (인테리어, 독서) - 독서 기록 노트 상단 '홈페이지 제작 서비스로 돌아가기' 배너 추가 - 개인 쇼핑몰 샘플 (MELLOW STUDIO) 신규 생성 - 베이지/크림 라이트 톤, Cormorant Garamond + Pretendard - 히어로 스플릿 레이아웃, 상품 그리드(카테고리 필터), 브랜드 스토리, 리뷰, CTA, 푸터 - 장바구니 뱃지, 상품 찜하기, 퀵 장바구니 인터랙션 - 홈페이지 서비스 소개 페이지 재디자인 - CookieRun → Pretendard 교체로 한글 폰트 렌더링 개선 - word-break: keep-all 적용으로 이상한 개행 제거 - IntersectionObserver 스크롤 reveal 애니메이션 추가 - Trust badge 섹션, Marquee 추가 - 쇼핑몰 샘플 카드 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
|
||||
const samples = [
|
||||
{
|
||||
@@ -74,6 +74,16 @@ const samples = [
|
||||
tags: ['라이프', '독서', '기록'],
|
||||
icon: '◻',
|
||||
},
|
||||
{
|
||||
type: 'shopping',
|
||||
title: '개인 쇼핑몰',
|
||||
subtitle: 'MELLOW STUDIO',
|
||||
desc: '감각적인 브랜드 스토리텔링과 미니멀 레이아웃으로 완성한 패션·라이프스타일 쇼핑몰',
|
||||
gradient: 'linear-gradient(135deg, #2A2018 0%, #4A3C2C 50%, #7A6A52 100%)',
|
||||
accent: '#C4A882',
|
||||
tags: ['쇼핑몰', '패션', '라이프'],
|
||||
icon: '◇',
|
||||
},
|
||||
];
|
||||
|
||||
const processSteps = [
|
||||
@@ -127,193 +137,349 @@ const faqs = [
|
||||
},
|
||||
];
|
||||
|
||||
function useReveal() {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
const el = ref.current;
|
||||
if (!el) return;
|
||||
const scroller = (document.querySelector('.main-content') as HTMLElement | null) ?? document.documentElement;
|
||||
const obs = new IntersectionObserver(
|
||||
([entry]) => { if (entry.isIntersecting) { el.classList.add('ws-visible'); obs.disconnect(); } },
|
||||
{ threshold: 0.1, root: scroller === document.documentElement ? null : scroller }
|
||||
);
|
||||
obs.observe(el);
|
||||
return () => obs.disconnect();
|
||||
}, []);
|
||||
return ref;
|
||||
}
|
||||
|
||||
export default function WebsiteServicePage() {
|
||||
const [openFaq, setOpenFaq] = useState<number | null>(null);
|
||||
const [showTop, setShowTop] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const scroller = (document.querySelector('.main-content') as HTMLElement | null) ?? document.documentElement;
|
||||
const onScroll = () => setShowTop(scroller.scrollTop > 400);
|
||||
scroller.addEventListener('scroll', onScroll, { passive: true });
|
||||
return () => scroller.removeEventListener('scroll', onScroll);
|
||||
}, []);
|
||||
|
||||
const samplesRef = useReveal();
|
||||
const processRef = useReveal();
|
||||
const pricingRef = useReveal();
|
||||
const faqRef = useReveal();
|
||||
const ctaRef = useReveal();
|
||||
|
||||
return (
|
||||
<div style={{ background: '#020817', minHeight: '100vh', color: 'white' }}>
|
||||
<style>{`
|
||||
@keyframes fadeUp { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: translateY(0); } }
|
||||
@keyframes gridScroll { from { background-position: 0 0; } to { background-position: 48px 48px; } }
|
||||
.ws-card:hover { transform: translateY(-5px); box-shadow: 0 20px 60px rgba(0,0,0,0.5); }
|
||||
.ws-card { transition: transform 0.3s ease, box-shadow 0.3s ease; }
|
||||
.ws-plan:hover { transform: translateY(-3px); }
|
||||
.ws-plan { transition: transform 0.3s ease; }
|
||||
`}</style>
|
||||
<div style={{ background: '#030712', minHeight: '100vh', color: 'white', fontFamily: "'Pretendard', 'Apple SD Gothic Neo', system-ui, sans-serif" }}>
|
||||
<style dangerouslySetInnerHTML={{ __html: `
|
||||
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.min.css');
|
||||
|
||||
{/* Hero */}
|
||||
<section style={{ padding: '72px 24px 56px', textAlign: 'center', position: 'relative', overflow: 'hidden' }}>
|
||||
* { box-sizing: border-box; }
|
||||
word-break { word-break: keep-all; }
|
||||
|
||||
/* scroll reveal */
|
||||
.ws-reveal {
|
||||
opacity: 0;
|
||||
transform: translateY(32px);
|
||||
filter: blur(3px);
|
||||
transition: opacity 0.7s cubic-bezier(0.16,1,0.3,1),
|
||||
transform 0.7s cubic-bezier(0.16,1,0.3,1),
|
||||
filter 0.7s cubic-bezier(0.16,1,0.3,1);
|
||||
}
|
||||
.ws-reveal.ws-visible { opacity: 1; transform: translateY(0); filter: blur(0); }
|
||||
.ws-reveal > *:nth-child(1) { transition-delay: 0ms; }
|
||||
.ws-reveal > *:nth-child(2) { transition-delay: 80ms; }
|
||||
.ws-reveal > *:nth-child(3) { transition-delay: 160ms; }
|
||||
.ws-reveal > *:nth-child(4) { transition-delay: 240ms; }
|
||||
.ws-reveal > *:nth-child(5) { transition-delay: 320ms; }
|
||||
|
||||
@keyframes ws-fadeUp {
|
||||
from { opacity: 0; transform: translateY(28px); filter: blur(4px); }
|
||||
to { opacity: 1; transform: translateY(0); filter: blur(0); }
|
||||
}
|
||||
@keyframes ws-gridScroll {
|
||||
from { background-position: 0 0; }
|
||||
to { background-position: 48px 48px; }
|
||||
}
|
||||
@keyframes ws-marquee {
|
||||
from { transform: translateX(0); }
|
||||
to { transform: translateX(-50%); }
|
||||
}
|
||||
@keyframes ws-glow {
|
||||
0%,100% { opacity: 0.5; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.ws-sample-card {
|
||||
border-radius: 20px; overflow: hidden;
|
||||
border: 1px solid rgba(255,255,255,0.07);
|
||||
background: #0a0f1e; cursor: pointer;
|
||||
transition: transform 0.45s cubic-bezier(0.16,1,0.3,1),
|
||||
box-shadow 0.45s cubic-bezier(0.16,1,0.3,1),
|
||||
border-color 0.3s;
|
||||
}
|
||||
.ws-sample-card:hover {
|
||||
transform: translateY(-6px);
|
||||
box-shadow: 0 24px 64px rgba(0,0,0,0.5);
|
||||
border-color: rgba(255,255,255,0.14);
|
||||
}
|
||||
|
||||
.ws-plan-card {
|
||||
transition: transform 0.4s cubic-bezier(0.16,1,0.3,1), box-shadow 0.4s;
|
||||
}
|
||||
.ws-plan-card:hover { transform: translateY(-4px); }
|
||||
|
||||
.ws-faq-item {
|
||||
border-radius: 14px; overflow: hidden;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
|
||||
.ws-step-card {
|
||||
transition: transform 0.4s cubic-bezier(0.16,1,0.3,1), box-shadow 0.4s;
|
||||
}
|
||||
.ws-step-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 16px 48px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.ws-marquee-track { animation: ws-marquee 30s linear infinite; display: flex; }
|
||||
|
||||
/* scrollbar */
|
||||
::-webkit-scrollbar { width: 4px; }
|
||||
::-webkit-scrollbar-track { background: #030712; }
|
||||
::-webkit-scrollbar-thumb { background: rgba(99,102,241,0.3); border-radius: 2px; }
|
||||
`}} />
|
||||
|
||||
{/* ── Hero ── */}
|
||||
<section style={{ padding: '80px 24px 60px', textAlign: 'center', position: 'relative', overflow: 'hidden' }}>
|
||||
{/* Animated grid */}
|
||||
<div style={{
|
||||
position: 'absolute', inset: 0,
|
||||
backgroundImage: 'linear-gradient(rgba(99,102,241,0.06) 1px, transparent 1px), linear-gradient(90deg, rgba(99,102,241,0.06) 1px, transparent 1px)',
|
||||
position: 'absolute', inset: 0, pointerEvents: 'none',
|
||||
backgroundImage: 'linear-gradient(rgba(99,102,241,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(99,102,241,0.05) 1px, transparent 1px)',
|
||||
backgroundSize: '48px 48px',
|
||||
animation: 'gridScroll 8s linear infinite',
|
||||
animation: 'ws-gridScroll 10s linear infinite',
|
||||
}} />
|
||||
{/* Radial glow */}
|
||||
<div style={{
|
||||
position: 'absolute', inset: 0, pointerEvents: 'none',
|
||||
background: 'radial-gradient(ellipse 75% 55% at 50% 0%, rgba(99,102,241,0.15) 0%, transparent 70%)',
|
||||
}} />
|
||||
{/* Ambient dot */}
|
||||
<div style={{
|
||||
position: 'absolute', top: '60%', left: '15%', width: 300, height: 300,
|
||||
background: 'radial-gradient(circle, rgba(129,140,248,0.06) 0%, transparent 70%)',
|
||||
borderRadius: '50%', pointerEvents: 'none', animation: 'ws-glow 5s ease-in-out infinite',
|
||||
}} />
|
||||
<div style={{
|
||||
position: 'absolute', inset: 0,
|
||||
background: 'radial-gradient(ellipse 70% 60% at 50% 0%, rgba(99,102,241,0.18) 0%, transparent 70%)',
|
||||
position: 'absolute', top: '30%', right: '10%', width: 200, height: 200,
|
||||
background: 'radial-gradient(circle, rgba(244,114,182,0.05) 0%, transparent 70%)',
|
||||
borderRadius: '50%', pointerEvents: 'none', animation: 'ws-glow 7s ease-in-out infinite 2s',
|
||||
}} />
|
||||
<div style={{ maxWidth: 820, margin: '0 auto', position: 'relative', animation: 'fadeUp 0.8s ease forwards' }}>
|
||||
|
||||
<div style={{ maxWidth: 820, margin: '0 auto', position: 'relative', animation: 'ws-fadeUp 0.9s cubic-bezier(0.16,1,0.3,1) both' }}>
|
||||
<span style={{
|
||||
display: 'inline-block', fontSize: 11, fontWeight: 700, letterSpacing: '0.2em',
|
||||
color: '#818cf8', textTransform: 'uppercase',
|
||||
border: '1px solid rgba(129,140,248,0.35)', padding: '5px 16px', borderRadius: 100,
|
||||
marginBottom: 28, fontFamily: "'CookieRun', sans-serif",
|
||||
border: '1px solid rgba(129,140,248,0.3)', padding: '5px 16px', borderRadius: 100,
|
||||
marginBottom: 32,
|
||||
}}>
|
||||
Homepage Development Service
|
||||
</span>
|
||||
<h1 style={{
|
||||
fontFamily: "'CookieRun', sans-serif", fontSize: 'clamp(30px, 5vw, 58px)', fontWeight: 800,
|
||||
lineHeight: 1.15, marginBottom: 20,
|
||||
fontSize: 'clamp(28px, 4.5vw, 54px)', fontWeight: 800,
|
||||
lineHeight: 1.2, marginBottom: 20,
|
||||
letterSpacing: '-0.02em',
|
||||
background: 'linear-gradient(135deg, #ffffff 0%, #c7d2fe 50%, #818cf8 100%)',
|
||||
WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
|
||||
wordBreak: 'keep-all',
|
||||
}}>
|
||||
홈페이지 맡겼다가 연락 끊긴 경험,<br />여기선 없습니다
|
||||
홈페이지 맡겼다가<br/>연락 끊긴 경험, 여기선 없습니다
|
||||
</h1>
|
||||
<p style={{
|
||||
fontSize: 16, color: '#94a3b8', lineHeight: 1.8, marginBottom: 36,
|
||||
fontFamily: "'CookieRun', sans-serif",
|
||||
fontSize: 16, color: '#64748b', lineHeight: 1.85, marginBottom: 36,
|
||||
wordBreak: 'keep-all',
|
||||
}}>
|
||||
계약서 작성 → 중간 보고 → 소스코드 인도까지 단계마다 증거를 남깁니다.<br />
|
||||
계약서 작성 → 중간 보고 → 소스코드 인도까지 단계마다 증거를 남깁니다.<br/>
|
||||
납기 지연 시 하루당 10만원 감면 — 그래서 안 늦습니다.
|
||||
</p>
|
||||
<div style={{ display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap' }}>
|
||||
<Link href="/freelance?service=website" style={{
|
||||
display: 'inline-block', padding: '14px 32px',
|
||||
display: 'inline-flex', alignItems: 'center', gap: 8,
|
||||
padding: '14px 28px',
|
||||
background: 'linear-gradient(135deg, #6366f1, #818cf8)',
|
||||
borderRadius: 12, color: 'white', fontWeight: 700, fontSize: 15,
|
||||
textDecoration: 'none', fontFamily: "'CookieRun', sans-serif",
|
||||
textDecoration: 'none',
|
||||
boxShadow: '0 8px 32px rgba(99,102,241,0.4)',
|
||||
}}>
|
||||
transition: 'transform 0.3s, box-shadow 0.3s',
|
||||
}}
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.transform = 'translateY(-2px)'; (e.currentTarget as HTMLElement).style.boxShadow = '0 16px 48px rgba(99,102,241,0.5)'; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.transform = ''; (e.currentTarget as HTMLElement).style.boxShadow = '0 8px 32px rgba(99,102,241,0.4)'; }}>
|
||||
무료 상담 신청 →
|
||||
</Link>
|
||||
<a href="#samples" style={{
|
||||
display: 'inline-block', padding: '14px 32px',
|
||||
border: '1px solid rgba(255,255,255,0.12)', borderRadius: 12,
|
||||
color: '#cbd5e1', fontWeight: 600, fontSize: 15,
|
||||
textDecoration: 'none', fontFamily: "'CookieRun', sans-serif",
|
||||
}}>
|
||||
display: 'inline-flex', alignItems: 'center', gap: 8,
|
||||
padding: '14px 28px',
|
||||
border: '1px solid rgba(255,255,255,0.1)', borderRadius: 12,
|
||||
color: '#94a3b8', fontWeight: 600, fontSize: 15,
|
||||
textDecoration: 'none',
|
||||
transition: 'border-color 0.3s, color 0.3s',
|
||||
}}
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.borderColor = 'rgba(255,255,255,0.25)'; (e.currentTarget as HTMLElement).style.color = '#e2e8f0'; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.borderColor = 'rgba(255,255,255,0.1)'; (e.currentTarget as HTMLElement).style.color = '#94a3b8'; }}>
|
||||
샘플 보기
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
<div style={{ display: 'flex', gap: 32, justifyContent: 'center', marginTop: 48, flexWrap: 'wrap' }}>
|
||||
<div style={{ display: 'flex', gap: 0, justifyContent: 'center', marginTop: 56, flexWrap: 'wrap' }}>
|
||||
{[
|
||||
{ num: '3~5일', label: '최단 납품 (스타터)' },
|
||||
{ num: '20만원~', label: '시작 가격' },
|
||||
{ num: '전액환불', label: '납품 전 환불 보장' },
|
||||
].map((s) => (
|
||||
<div key={s.label} style={{ textAlign: 'center' }}>
|
||||
<div style={{ fontSize: 24, fontWeight: 800, color: 'white', fontFamily: "'CookieRun', sans-serif" }}>{s.num}</div>
|
||||
<div style={{ fontSize: 12, color: '#475569', fontFamily: "'CookieRun', sans-serif", marginTop: 2 }}>{s.label}</div>
|
||||
].map((s, i) => (
|
||||
<div key={s.label} style={{
|
||||
textAlign: 'center', padding: '0 40px',
|
||||
borderRight: i < 2 ? '1px solid rgba(255,255,255,0.08)' : 'none',
|
||||
}}>
|
||||
<div style={{ fontSize: 22, fontWeight: 800, color: 'white', letterSpacing: '-0.02em' }}>{s.num}</div>
|
||||
<div style={{ fontSize: 12, color: '#475569', marginTop: 4, letterSpacing: '0.02em' }}>{s.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Sample Portfolio */}
|
||||
<section id="samples" style={{ padding: '56px 24px', maxWidth: 1100, margin: '0 auto' }}>
|
||||
<div style={{ textAlign: 'center', marginBottom: 40 }}>
|
||||
<h2 style={{
|
||||
fontFamily: "'CookieRun', sans-serif", fontSize: 28, fontWeight: 800,
|
||||
color: 'white', marginBottom: 10,
|
||||
}}>
|
||||
포트폴리오 샘플
|
||||
</h2>
|
||||
<p style={{ color: '#64748b', fontFamily: "'CookieRun', sans-serif", fontSize: 15 }}>
|
||||
카드를 클릭하면 실제 완성 화면을 미리 확인할 수 있습니다
|
||||
</p>
|
||||
{/* ── Marquee ── */}
|
||||
<div style={{ borderTop: '1px solid rgba(255,255,255,0.04)', borderBottom: '1px solid rgba(255,255,255,0.04)', overflow: 'hidden', padding: '12px 0' }}>
|
||||
<div className="ws-marquee-track" style={{ gap: 0 }}>
|
||||
{[...Array(2)].map((_, i) => (
|
||||
<div key={i} style={{ display: 'flex', gap: 0, whiteSpace: 'nowrap', flexShrink: 0 }}>
|
||||
{['반응형 디자인', 'SEO 최적화', '빠른 납품', '계약서 작성', '소스코드 제공', '1년 AS 보장', '도메인 배포'].map((t, j) => (
|
||||
<span key={j} style={{ padding: '0 2rem', fontSize: '0.75rem', color: '#1e293b', letterSpacing: '0.12em', textTransform: 'uppercase' }}>
|
||||
{t} <span style={{ color: 'rgba(99,102,241,0.3)', margin: '0 0.5rem' }}>·</span>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 20 }}>
|
||||
{samples.map((s) => (
|
||||
<Link key={s.type} href={`/services/website/samples/${s.type}`} style={{ textDecoration: 'none' }}>
|
||||
<div className="ws-card" style={{
|
||||
borderRadius: 20, overflow: 'hidden',
|
||||
border: '1px solid rgba(255,255,255,0.07)',
|
||||
background: '#0a1020', cursor: 'pointer',
|
||||
}}>
|
||||
<div style={{
|
||||
height: 170, background: s.gradient, position: 'relative',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
<span style={{ fontSize: 52, filter: 'drop-shadow(0 4px 16px rgba(0,0,0,0.6))' }}>{s.icon}</span>
|
||||
<div style={{
|
||||
position: 'absolute', top: 12, left: 12,
|
||||
display: 'flex', gap: 5,
|
||||
}}>
|
||||
{s.tags.map((tag) => (
|
||||
<span key={tag} style={{
|
||||
fontSize: 10, fontWeight: 600, color: '#e2e8f0',
|
||||
background: 'rgba(0,0,0,0.55)', backdropFilter: 'blur(8px)',
|
||||
border: '1px solid rgba(255,255,255,0.12)',
|
||||
padding: '2px 8px', borderRadius: 100,
|
||||
}}>{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
<div style={{
|
||||
position: 'absolute', bottom: 12, right: 12,
|
||||
background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(8px)',
|
||||
border: `1px solid ${s.accent}50`,
|
||||
borderRadius: 8, padding: '5px 12px',
|
||||
fontSize: 11, color: s.accent, fontFamily: "'CookieRun', sans-serif", fontWeight: 700,
|
||||
}}>
|
||||
미리보기 →
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ padding: '18px 22px 22px' }}>
|
||||
<div style={{ fontSize: 11, color: '#475569', fontFamily: "'CookieRun', sans-serif", marginBottom: 5, letterSpacing: '0.05em' }}>
|
||||
{s.subtitle}
|
||||
</div>
|
||||
<div style={{ fontSize: 17, fontWeight: 700, color: 'white', fontFamily: "'CookieRun', sans-serif", marginBottom: 8 }}>
|
||||
{s.title}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: '#64748b', lineHeight: 1.65, fontFamily: "'CookieRun', sans-serif" }}>
|
||||
{s.desc}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── Trust badges ── */}
|
||||
<section style={{ padding: '48px 24px', maxWidth: 1000, margin: '0 auto' }}>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 16 }}>
|
||||
{[
|
||||
{ icon: '📋', title: '계약서 필수 작성', desc: '모든 프로젝트 계약서 체결 후 진행' },
|
||||
{ icon: '📊', title: '주간 진행 보고', desc: '매주 작업 현황 공유, 연락 두절 없음' },
|
||||
{ icon: '💾', title: '소스코드 전액 제공', desc: '완성 후 전체 소스코드 인도' },
|
||||
{ icon: '🔒', title: '납기 지연 패널티', desc: '지연 1일당 10만원 자동 감면' },
|
||||
].map((b) => (
|
||||
<div key={b.title} style={{
|
||||
padding: '20px 22px', borderRadius: 14,
|
||||
background: 'rgba(255,255,255,0.02)',
|
||||
border: '1px solid rgba(255,255,255,0.05)',
|
||||
display: 'flex', gap: 14, alignItems: 'flex-start',
|
||||
}}>
|
||||
<span style={{ fontSize: 24, flexShrink: 0 }}>{b.icon}</span>
|
||||
<div>
|
||||
<div style={{ fontSize: 13, fontWeight: 700, color: '#e2e8f0', marginBottom: 4, wordBreak: 'keep-all' }}>{b.title}</div>
|
||||
<div style={{ fontSize: 12, color: '#475569', lineHeight: 1.6, wordBreak: 'keep-all' }}>{b.desc}</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Process */}
|
||||
<section style={{ padding: '56px 24px', background: 'rgba(255,255,255,0.02)', borderTop: '1px solid rgba(255,255,255,0.05)', borderBottom: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<div style={{ maxWidth: 1000, margin: '0 auto' }}>
|
||||
<div style={{ textAlign: 'center', marginBottom: 40 }}>
|
||||
<h2 style={{ fontFamily: "'CookieRun', sans-serif", fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 10 }}>
|
||||
{/* ── Sample Portfolio ── */}
|
||||
<section id="samples" style={{ padding: '56px 24px', maxWidth: 1160, margin: '0 auto' }}>
|
||||
<div ref={samplesRef} className="ws-reveal">
|
||||
<div style={{ textAlign: 'center', marginBottom: 44 }}>
|
||||
<p style={{ fontSize: 11, color: '#6366f1', letterSpacing: '0.2em', textTransform: 'uppercase', marginBottom: 12, fontWeight: 700 }}>Portfolio Samples</p>
|
||||
<h2 style={{ fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 10, letterSpacing: '-0.02em' }}>
|
||||
포트폴리오 샘플
|
||||
</h2>
|
||||
<p style={{ color: '#475569', fontSize: 14 }}>
|
||||
카드를 클릭하면 실제 완성 화면을 미리 확인할 수 있습니다
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 18 }}>
|
||||
{samples.map((s) => (
|
||||
<Link key={s.type} href={`/services/website/samples/${s.type}`} style={{ textDecoration: 'none' }}>
|
||||
<div className="ws-sample-card">
|
||||
<div style={{
|
||||
height: 175, background: s.gradient, position: 'relative',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
<span style={{ fontSize: 52, filter: 'drop-shadow(0 4px 20px rgba(0,0,0,0.6))' }}>{s.icon}</span>
|
||||
<div style={{ position: 'absolute', top: 12, left: 12, display: 'flex', gap: 5 }}>
|
||||
{s.tags.map((tag) => (
|
||||
<span key={tag} style={{
|
||||
fontSize: 10, fontWeight: 600, color: '#e2e8f0',
|
||||
background: 'rgba(0,0,0,0.5)', backdropFilter: 'blur(8px)',
|
||||
border: '1px solid rgba(255,255,255,0.1)',
|
||||
padding: '2px 8px', borderRadius: 100,
|
||||
}}>{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
<div style={{
|
||||
position: 'absolute', bottom: 12, right: 12,
|
||||
background: 'rgba(0,0,0,0.55)', backdropFilter: 'blur(8px)',
|
||||
border: `1px solid ${s.accent}45`,
|
||||
borderRadius: 8, padding: '5px 12px',
|
||||
fontSize: 11, color: s.accent, fontWeight: 700,
|
||||
}}>
|
||||
미리보기 →
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ padding: '18px 22px 22px' }}>
|
||||
<div style={{ fontSize: 11, color: '#334155', marginBottom: 5, letterSpacing: '0.05em' }}>
|
||||
{s.subtitle}
|
||||
</div>
|
||||
<div style={{ fontSize: 16, fontWeight: 700, color: 'white', marginBottom: 8, letterSpacing: '-0.01em' }}>
|
||||
{s.title}
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: '#475569', lineHeight: 1.65, wordBreak: 'keep-all' }}>
|
||||
{s.desc}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Process ── */}
|
||||
<section style={{ padding: '56px 24px', background: 'rgba(255,255,255,0.015)', borderTop: '1px solid rgba(255,255,255,0.04)', borderBottom: '1px solid rgba(255,255,255,0.04)' }}>
|
||||
<div ref={processRef} className="ws-reveal" style={{ maxWidth: 1060, margin: '0 auto' }}>
|
||||
<div style={{ textAlign: 'center', marginBottom: 44 }}>
|
||||
<p style={{ fontSize: 11, color: '#6366f1', letterSpacing: '0.2em', textTransform: 'uppercase', marginBottom: 12, fontWeight: 700 }}>Process</p>
|
||||
<h2 style={{ fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 10, letterSpacing: '-0.02em' }}>
|
||||
제작 프로세스
|
||||
</h2>
|
||||
<p style={{ color: '#64748b', fontFamily: "'CookieRun', sans-serif", fontSize: 15 }}>
|
||||
투명하고 체계적인 5단계로 진행됩니다
|
||||
</p>
|
||||
<p style={{ color: '#475569', fontSize: 14 }}>투명하고 체계적인 5단계로 진행됩니다</p>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'stretch', flexWrap: 'wrap', justifyContent: 'center', gap: 0 }}>
|
||||
{processSteps.map((p, i) => (
|
||||
<div key={i} style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<div style={{
|
||||
textAlign: 'center', padding: '24px 20px', minWidth: 130,
|
||||
background: '#0f172a', borderRadius: 16,
|
||||
border: '1px solid rgba(255,255,255,0.06)',
|
||||
<div className="ws-step-card" style={{
|
||||
textAlign: 'center', padding: '28px 22px', minWidth: 138,
|
||||
background: '#080d1a', borderRadius: 16,
|
||||
border: '1px solid rgba(255,255,255,0.05)',
|
||||
}}>
|
||||
<div style={{ fontSize: 30, marginBottom: 10 }}>{p.icon}</div>
|
||||
<div style={{
|
||||
fontSize: 10, color: '#6366f1', fontFamily: "'CookieRun', sans-serif",
|
||||
fontWeight: 700, letterSpacing: '0.1em', marginBottom: 6,
|
||||
}}>
|
||||
<div style={{ fontSize: 28, marginBottom: 12 }}>{p.icon}</div>
|
||||
<div style={{ fontSize: 10, color: '#6366f1', fontWeight: 700, letterSpacing: '0.12em', marginBottom: 7 }}>
|
||||
STEP {p.step}
|
||||
</div>
|
||||
<div style={{ fontSize: 14, fontWeight: 700, color: 'white', fontFamily: "'CookieRun', sans-serif", marginBottom: 5 }}>
|
||||
<div style={{ fontSize: 14, fontWeight: 700, color: 'white', marginBottom: 6, wordBreak: 'keep-all' }}>
|
||||
{p.title}
|
||||
</div>
|
||||
<div style={{ fontSize: 11, color: '#475569', fontFamily: "'CookieRun', sans-serif", lineHeight: 1.5 }}>
|
||||
<div style={{ fontSize: 11, color: '#334155', lineHeight: 1.55, wordBreak: 'keep-all' }}>
|
||||
{p.desc}
|
||||
</div>
|
||||
</div>
|
||||
{i < processSteps.length - 1 && (
|
||||
<div style={{ color: '#1e293b', fontSize: 22, padding: '0 6px', flexShrink: 0 }}>›</div>
|
||||
<div style={{ color: '#1e293b', fontSize: 20, padding: '0 4px', flexShrink: 0 }}>›</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
@@ -321,142 +487,165 @@ export default function WebsiteServicePage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Pricing */}
|
||||
<section style={{ padding: '56px 24px', maxWidth: 1000, margin: '0 auto' }}>
|
||||
<div style={{ textAlign: 'center', marginBottom: 40 }}>
|
||||
<h2 style={{ fontFamily: "'CookieRun', sans-serif", fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 10 }}>
|
||||
가격 플랜
|
||||
</h2>
|
||||
<p style={{ color: '#64748b', fontFamily: "'CookieRun', sans-serif", fontSize: 15 }}>
|
||||
프로젝트 규모에 맞는 플랜을 선택하세요
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 20 }}>
|
||||
{plans.map((plan) => (
|
||||
<div key={plan.name} className="ws-plan" style={{
|
||||
padding: 30, borderRadius: 20,
|
||||
background: plan.featured ? 'linear-gradient(135deg, #1e1b4b, #312e81)' : '#0f172a',
|
||||
border: `1px solid ${plan.featured ? plan.color + '55' : 'rgba(255,255,255,0.06)'}`,
|
||||
position: 'relative', overflow: 'hidden',
|
||||
boxShadow: plan.featured ? `0 24px 64px ${plan.color}18` : 'none',
|
||||
}}>
|
||||
{plan.featured && (
|
||||
<div style={{
|
||||
position: 'absolute', top: 18, right: 18,
|
||||
background: plan.color, color: '#1e1b4b',
|
||||
fontSize: 10, fontWeight: 800, padding: '3px 10px', borderRadius: 100,
|
||||
fontFamily: "'CookieRun', sans-serif",
|
||||
}}>BEST</div>
|
||||
)}
|
||||
<div style={{ fontSize: 13, color: plan.color, fontFamily: "'CookieRun', sans-serif", fontWeight: 700, marginBottom: 10 }}>
|
||||
{plan.name}
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginBottom: 4 }}>
|
||||
<span style={{ fontSize: 42, fontWeight: 800, color: 'white', fontFamily: "'CookieRun', sans-serif" }}>
|
||||
{plan.price}
|
||||
</span>
|
||||
<span style={{ fontSize: 16, color: '#94a3b8', fontFamily: "'CookieRun', sans-serif" }}>
|
||||
{plan.unit}
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 12, color: '#475569', fontFamily: "'CookieRun', sans-serif", marginBottom: 22 }}>
|
||||
{plan.note}
|
||||
</div>
|
||||
<div style={{ borderTop: '1px solid rgba(255,255,255,0.07)', paddingTop: 20, marginBottom: 24 }}>
|
||||
{plan.features.map((f) => (
|
||||
<div key={f} style={{ display: 'flex', alignItems: 'center', gap: 9, marginBottom: 11 }}>
|
||||
<span style={{ color: plan.color, fontSize: 14, flexShrink: 0, fontWeight: 700 }}>✓</span>
|
||||
<span style={{ fontSize: 13, color: '#94a3b8', fontFamily: "'CookieRun', sans-serif" }}>{f}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Link href="/freelance?service=website" style={{
|
||||
display: 'block', textAlign: 'center', padding: '12px',
|
||||
background: plan.featured ? plan.color : 'rgba(255,255,255,0.05)',
|
||||
borderRadius: 10, color: plan.featured ? '#1e1b4b' : '#cbd5e1',
|
||||
fontWeight: 700, fontSize: 14, textDecoration: 'none',
|
||||
fontFamily: "'CookieRun', sans-serif",
|
||||
border: plan.featured ? 'none' : '1px solid rgba(255,255,255,0.08)',
|
||||
{/* ── Pricing ── */}
|
||||
<section style={{ padding: '64px 24px', maxWidth: 1040, margin: '0 auto' }}>
|
||||
<div ref={pricingRef} className="ws-reveal">
|
||||
<div style={{ textAlign: 'center', marginBottom: 44 }}>
|
||||
<p style={{ fontSize: 11, color: '#6366f1', letterSpacing: '0.2em', textTransform: 'uppercase', marginBottom: 12, fontWeight: 700 }}>Pricing</p>
|
||||
<h2 style={{ fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 10, letterSpacing: '-0.02em' }}>
|
||||
가격 플랜
|
||||
</h2>
|
||||
<p style={{ color: '#475569', fontSize: 14 }}>프로젝트 규모에 맞는 플랜을 선택하세요</p>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(270px, 1fr))', gap: 20 }}>
|
||||
{plans.map((plan) => (
|
||||
<div key={plan.name} className="ws-plan-card" style={{
|
||||
padding: 32, borderRadius: 20,
|
||||
background: plan.featured ? 'linear-gradient(135deg, #1e1b4b, #312e81)' : '#080d1a',
|
||||
border: `1px solid ${plan.featured ? plan.color + '40' : 'rgba(255,255,255,0.05)'}`,
|
||||
position: 'relative', overflow: 'hidden',
|
||||
boxShadow: plan.featured ? `0 24px 64px ${plan.color}12` : 'none',
|
||||
}}>
|
||||
상담 신청
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ */}
|
||||
<section style={{ padding: '0 24px 56px', maxWidth: 720, margin: '0 auto' }}>
|
||||
<div style={{ textAlign: 'center', marginBottom: 32 }}>
|
||||
<h2 style={{ fontFamily: "'CookieRun', sans-serif", fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 10 }}>
|
||||
자주 묻는 질문
|
||||
</h2>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
|
||||
{faqs.map((faq, i) => (
|
||||
<div key={i} style={{
|
||||
background: '#0f172a', borderRadius: 14,
|
||||
border: `1px solid ${openFaq === i ? 'rgba(99,102,241,0.45)' : 'rgba(255,255,255,0.06)'}`,
|
||||
overflow: 'hidden', transition: 'border-color 0.25s',
|
||||
}}>
|
||||
<button onClick={() => setOpenFaq(openFaq === i ? null : i)} style={{
|
||||
width: '100%', textAlign: 'left', padding: '18px 22px',
|
||||
background: 'none', border: 'none', cursor: 'pointer',
|
||||
display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12,
|
||||
}}>
|
||||
<span style={{ fontSize: 14, fontWeight: 600, color: 'white', fontFamily: "'CookieRun', sans-serif" }}>
|
||||
{faq.q}
|
||||
</span>
|
||||
<span style={{
|
||||
color: '#6366f1', fontSize: 22, flexShrink: 0,
|
||||
transition: 'transform 0.2s',
|
||||
transform: openFaq === i ? 'rotate(45deg)' : 'none',
|
||||
display: 'inline-block',
|
||||
}}>+</span>
|
||||
</button>
|
||||
{openFaq === i && (
|
||||
<div style={{
|
||||
padding: '0 22px 18px', fontSize: 14, color: '#64748b',
|
||||
lineHeight: 1.75, fontFamily: "'CookieRun', sans-serif",
|
||||
}}>
|
||||
{faq.a}
|
||||
{plan.featured && (
|
||||
<div style={{
|
||||
position: 'absolute', top: 20, right: 20,
|
||||
background: plan.color, color: '#1e1b4b',
|
||||
fontSize: 10, fontWeight: 800, padding: '3px 10px', borderRadius: 100,
|
||||
}}>BEST</div>
|
||||
)}
|
||||
<div style={{ fontSize: 12, color: plan.color, fontWeight: 700, marginBottom: 12, letterSpacing: '0.05em' }}>
|
||||
{plan.name}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginBottom: 4 }}>
|
||||
<span style={{ fontSize: 40, fontWeight: 800, color: 'white', letterSpacing: '-0.03em' }}>{plan.price}</span>
|
||||
<span style={{ fontSize: 15, color: '#64748b' }}>{plan.unit}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 12, color: '#334155', marginBottom: 24, wordBreak: 'keep-all' }}>{plan.note}</div>
|
||||
<div style={{ borderTop: '1px solid rgba(255,255,255,0.06)', paddingTop: 20, marginBottom: 24 }}>
|
||||
{plan.features.map((f) => (
|
||||
<div key={f} style={{ display: 'flex', alignItems: 'center', gap: 9, marginBottom: 12 }}>
|
||||
<span style={{ color: plan.color, fontSize: 13, flexShrink: 0, fontWeight: 700 }}>✓</span>
|
||||
<span style={{ fontSize: 13, color: '#94a3b8', wordBreak: 'keep-all' }}>{f}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Link href="/freelance?service=website" style={{
|
||||
display: 'block', textAlign: 'center', padding: '13px',
|
||||
background: plan.featured ? plan.color : 'rgba(255,255,255,0.04)',
|
||||
borderRadius: 10, color: plan.featured ? '#1e1b4b' : '#94a3b8',
|
||||
fontWeight: 700, fontSize: 14, textDecoration: 'none',
|
||||
border: plan.featured ? 'none' : '1px solid rgba(255,255,255,0.07)',
|
||||
transition: 'opacity 0.2s',
|
||||
}}>
|
||||
상담 신청
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section style={{ padding: '0 24px 80px', textAlign: 'center' }}>
|
||||
<div style={{
|
||||
maxWidth: 620, margin: '0 auto',
|
||||
padding: '52px 40px', borderRadius: 24,
|
||||
background: 'linear-gradient(135deg, #1e1b4b, #312e81)',
|
||||
border: '1px solid rgba(129,140,248,0.3)',
|
||||
boxShadow: '0 24px 80px rgba(99,102,241,0.2)',
|
||||
}}>
|
||||
<h2 style={{ fontFamily: "'CookieRun', sans-serif", fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 14 }}>
|
||||
지금 바로 시작하세요
|
||||
</h2>
|
||||
<p style={{
|
||||
color: '#a5b4fc', fontSize: 15, lineHeight: 1.7, marginBottom: 30,
|
||||
fontFamily: "'CookieRun', sans-serif",
|
||||
}}>
|
||||
무료 상담은 24시간 이내 답변드립니다.<br />
|
||||
어떤 규모의 프로젝트든 환영합니다.
|
||||
</p>
|
||||
<Link href="/freelance?service=website" style={{
|
||||
display: 'inline-block', padding: '15px 40px',
|
||||
background: 'linear-gradient(135deg, #818cf8, #6366f1)',
|
||||
borderRadius: 12, color: 'white', fontWeight: 700, fontSize: 16,
|
||||
textDecoration: 'none', fontFamily: "'CookieRun', sans-serif",
|
||||
boxShadow: '0 8px 32px rgba(99,102,241,0.5)',
|
||||
}}>
|
||||
무료 상담 신청하기 →
|
||||
</Link>
|
||||
{/* ── FAQ ── */}
|
||||
<section style={{ padding: '0 24px 64px', maxWidth: 720, margin: '0 auto' }}>
|
||||
<div ref={faqRef} className="ws-reveal">
|
||||
<div style={{ textAlign: 'center', marginBottom: 36 }}>
|
||||
<p style={{ fontSize: 11, color: '#6366f1', letterSpacing: '0.2em', textTransform: 'uppercase', marginBottom: 12, fontWeight: 700 }}>FAQ</p>
|
||||
<h2 style={{ fontSize: 28, fontWeight: 800, color: 'white', letterSpacing: '-0.02em' }}>
|
||||
자주 묻는 질문
|
||||
</h2>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
|
||||
{faqs.map((faq, i) => (
|
||||
<div key={i} className="ws-faq-item" style={{
|
||||
background: '#080d1a',
|
||||
border: `1px solid ${openFaq === i ? 'rgba(99,102,241,0.4)' : 'rgba(255,255,255,0.05)'}`,
|
||||
}}>
|
||||
<button onClick={() => setOpenFaq(openFaq === i ? null : i)} style={{
|
||||
width: '100%', textAlign: 'left', padding: '18px 22px',
|
||||
background: 'none', border: 'none', cursor: 'pointer',
|
||||
display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12,
|
||||
}}>
|
||||
<span style={{ fontSize: 14, fontWeight: 600, color: 'white', wordBreak: 'keep-all' }}>
|
||||
{faq.q}
|
||||
</span>
|
||||
<span style={{
|
||||
color: '#6366f1', fontSize: 22, flexShrink: 0,
|
||||
transition: 'transform 0.25s',
|
||||
transform: openFaq === i ? 'rotate(45deg)' : 'none',
|
||||
display: 'inline-block',
|
||||
}}>+</span>
|
||||
</button>
|
||||
{openFaq === i && (
|
||||
<div style={{ padding: '0 22px 18px', fontSize: 14, color: '#475569', lineHeight: 1.8, wordBreak: 'keep-all' }}>
|
||||
{faq.a}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CTA ── */}
|
||||
<section style={{ padding: '0 24px 80px', textAlign: 'center' }}>
|
||||
<div ref={ctaRef} className="ws-reveal">
|
||||
<div style={{
|
||||
maxWidth: 640, margin: '0 auto',
|
||||
padding: '56px 44px', borderRadius: 24,
|
||||
background: 'linear-gradient(135deg, #1e1b4b, #312e81)',
|
||||
border: '1px solid rgba(129,140,248,0.25)',
|
||||
boxShadow: '0 24px 80px rgba(99,102,241,0.18)',
|
||||
position: 'relative', overflow: 'hidden',
|
||||
}}>
|
||||
<div style={{ position: 'absolute', top: -60, right: -60, width: 200, height: 200, background: 'radial-gradient(circle, rgba(129,140,248,0.15) 0%, transparent 70%)', borderRadius: '50%', pointerEvents: 'none' }} />
|
||||
<h2 style={{ fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 14, letterSpacing: '-0.02em', wordBreak: 'keep-all', position: 'relative' }}>
|
||||
지금 바로 시작하세요
|
||||
</h2>
|
||||
<p style={{ color: '#a5b4fc', fontSize: 15, lineHeight: 1.75, marginBottom: 32, wordBreak: 'keep-all', position: 'relative' }}>
|
||||
무료 상담은 24시간 이내 답변드립니다.<br/>
|
||||
어떤 규모의 프로젝트든 환영합니다.
|
||||
</p>
|
||||
<Link href="/freelance?service=website" style={{
|
||||
display: 'inline-block', padding: '15px 40px',
|
||||
background: 'linear-gradient(135deg, #818cf8, #6366f1)',
|
||||
borderRadius: 12, color: 'white', fontWeight: 700, fontSize: 15,
|
||||
textDecoration: 'none',
|
||||
boxShadow: '0 8px 32px rgba(99,102,241,0.5)',
|
||||
position: 'relative',
|
||||
transition: 'transform 0.3s, box-shadow 0.3s',
|
||||
}}
|
||||
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.transform = 'translateY(-2px)'; (e.currentTarget as HTMLElement).style.boxShadow = '0 16px 48px rgba(99,102,241,0.6)'; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.transform = ''; (e.currentTarget as HTMLElement).style.boxShadow = '0 8px 32px rgba(99,102,241,0.5)'; }}>
|
||||
무료 상담 신청하기 →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Scroll to Top ── */}
|
||||
<button
|
||||
onClick={() => {
|
||||
const scroller = (document.querySelector('.main-content') as HTMLElement | null) ?? document.documentElement;
|
||||
scroller.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}}
|
||||
style={{
|
||||
position: 'fixed', bottom: '2rem', right: '2rem', zIndex: 200,
|
||||
width: 48, height: 48, borderRadius: '50%',
|
||||
background: 'linear-gradient(135deg, #6366f1, #818cf8)',
|
||||
border: 'none', cursor: 'pointer',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
boxShadow: '0 8px 32px rgba(99,102,241,0.4)',
|
||||
opacity: showTop ? 1 : 0,
|
||||
transform: showTop ? 'translateY(0) scale(1)' : 'translateY(12px) scale(0.9)',
|
||||
transition: 'opacity 0.35s cubic-bezier(0.16,1,0.3,1), transform 0.35s cubic-bezier(0.16,1,0.3,1)',
|
||||
pointerEvents: showTop ? 'auto' : 'none',
|
||||
}}
|
||||
aria-label="맨 위로"
|
||||
>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="18 15 12 9 6 15"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user