chore(phase0): redirect에 가린 죽은 페이지 4종 + 전이 고아(ContactForm·freelance-portfolio) 제거

- /work → /outsourcing 리다이렉트에 가려진 app/work/page.tsx 제거
- /work/freelance → /outsourcing 리다이렉트에 가려진 freelance/ 디렉토리 제거
- /work/website → /portfolio 리다이렉트에 가려진 app/work/website/page.tsx 제거
- /music/packs → /products 리다이렉트에 가려진 app/music/packs/ 디렉토리 제거
- 유일 소비처(freelance/)가 삭제된 ContactForm.tsx 제거
- 유일 소비처(/work, /work/freelance)가 삭제된 freelance-portfolio.ts 제거

samples/** 8종과 layout.tsx는 유지됨.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 14:15:30 +09:00
parent 1e926fcb19
commit 592b3fcf4e
8 changed files with 0 additions and 2361 deletions

View File

@@ -1,27 +0,0 @@
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: '외주 개발 의뢰',
description:
'계약서 먼저, 납기 지키고, 소스코드 100% 인도. 47건 납품 완료. 현직 실무 엔지니어에게 외주 개발을 맡겨보세요. 납기 지연 시 하루 10만 원 패널티.',
keywords: [
'외주 개발',
'프리랜서 개발자',
'웹 개발 외주',
'앱 개발 외주',
'RPA 개발',
'업무 자동화 외주',
'소프트웨어 개발',
],
openGraph: {
title: '외주 개발 의뢰 | 쟁승메이드',
description:
'47건 납품 완료. 계약서 먼저, 납기 패널티, 소스코드 100% 인도. 연락 두절 없는 개발자.',
url: 'https://jaengseung-made.com/work/freelance',
},
robots: { index: false, follow: false },
};
export default function FreelanceLayout({ children }: { children: React.ReactNode }) {
return children;
}

View File

@@ -1,644 +0,0 @@
'use client';
import { useState, useEffect, useRef } from 'react';
import ContactForm from '@/app/components/ContactForm';
import { PORTFOLIO as portfolio } from '@/lib/freelance-portfolio';
/* ─── Data ─── */
const testimonials = [
{
name: '이서준',
role: '온라인 쇼핑몰 운영자',
project: '경쟁사 가격 모니터링 봇',
content: '경쟁사 10곳 가격을 매일 수동으로 확인했는데 이제 텔레그램으로 자동 알림 받습니다. 납기도 정확히 지켜주셨고, 완료 후에도 작은 수정 요청에 빠르게 응답해주셔서 믿음이 갔습니다.',
result: '가격 모니터링 시간 → 0분/일',
accentColor: 'bg-emerald-500',
borderColor: 'border-emerald-200',
tagColor: 'text-emerald-700 bg-emerald-50 border-emerald-200',
},
{
name: '박하은',
role: '스타트업 운영팀장',
project: 'Excel 보고서 자동화 시스템',
content: '매주 월요일 아침 2시간씩 쓰던 Excel 집계 작업을 자동화했습니다. 처음엔 반신반의했는데 계약서부터 작성해주셔서 진짜 전문가구나 싶었고, 결과물도 기대 이상이었습니다.',
result: '주간 보고 작업 2시간 → 5분',
accentColor: 'bg-blue-500',
borderColor: 'border-blue-200',
tagColor: 'text-blue-700 bg-blue-50 border-blue-200',
},
{
name: '김도윤',
role: '프리랜서 디자이너',
project: '포트폴리오 웹사이트 제작',
content: '이전에 다른 개발자한테 맡겼다가 중간에 연락이 끊겼던 경험이 있어서 많이 걱정했는데, 주 1회 진행 보고를 꼬박꼬박 해주시고 최종 소스코드까지 전달해주셔서 정말 만족했습니다.',
result: '2주 납품 약속 정확히 이행',
accentColor: 'bg-violet-500',
borderColor: 'border-violet-200',
tagColor: 'text-violet-700 bg-violet-50 border-violet-200',
},
];
const process = [
{
num: '01',
title: '무료 상담',
desc: '전화 또는 이메일로 요구사항 파악 (30분 이내)',
sub: '비용 없음 · 부담 없음',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
),
},
{
num: '02',
title: '견적 제안',
desc: '개발 범위, 일정, 비용 상세 견적서 제공',
sub: '1~3일 이내 발송',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
),
},
{
num: '03',
title: '계약 체결',
desc: '계약서 작성 및 계약금(30%) 입금 후 개발 시작',
sub: '계약서 포함 · 안전 거래',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
),
},
{
num: '04',
title: '개발 진행',
desc: '주 1회 이상 진행 상황 공유 및 중간 검수',
sub: '투명한 진행 보고',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
),
highlight: true,
},
{
num: '05',
title: '최종 납품',
desc: '완성본 인도 + 사용 교육 + 소스코드 전달',
sub: '소스코드 전체 제공',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M5 13l4 4L19 7" />
</svg>
),
},
{
num: '06',
title: 'AS 지원',
desc: '1개월 무상 기술 지원 및 평생 유지보수 가능',
sub: '1개월 무상 + 평생 AS',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
</svg>
),
},
];
const guarantees = [
{
label: '계약서 필수',
detail: '구두 약속 없음 — 착수 전 계약서 발송',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
),
accentText: 'text-sky-400',
accentBorder: 'border-sky-400/20',
},
{
label: '납기 지연 패널티',
detail: '하루 지연 = 10만원 감면 — 그래서 안 늦습니다',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
),
accentText: 'text-amber-400',
accentBorder: 'border-amber-400/20',
},
{
label: '소스코드 100% 인도',
detail: '납품 후 전체 소스코드 + 배포 가이드 제공',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
),
accentText: 'text-emerald-400',
accentBorder: 'border-emerald-400/20',
},
{
label: '1개월 무상 AS',
detail: '납품 후 한 달 — 버그·수정 무상 대응',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
),
accentText: 'text-violet-400',
accentBorder: 'border-violet-400/20',
},
{
label: '실시간 진행 현황',
detail: '마이페이지에서 7단계 진행 상황 직접 확인',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
),
accentText: 'text-cyan-400',
accentBorder: 'border-cyan-400/20',
},
];
/* ─── Scroll Reveal ─── */
function useScrollReveal() {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.1, rootMargin: '0px 0px -40px 0px' }
);
el.querySelectorAll('.reveal').forEach((child) => observer.observe(child));
return () => observer.disconnect();
}, []);
return ref;
}
/* ─── Main Page ─── */
export default function FreelancePage() {
const [_contactPreset] = useState('');
const containerRef = useScrollReveal();
return (
<div ref={containerRef} className="min-h-full bg-[#f0f5ff]">
<style>{`
.reveal {
opacity: 0;
transform: translateY(1.5rem);
transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}
.reveal.is-visible {
opacity: 1;
transform: translateY(0);
}
.reveal-d1 { transition-delay: 80ms; }
.reveal-d2 { transition-delay: 160ms; }
.reveal-d3 { transition-delay: 240ms; }
.reveal-d4 { transition-delay: 320ms; }
`}</style>
{/* ─── Hero ─── */}
<div
className="relative overflow-hidden bg-[#04102b] px-6 py-14 lg:px-12"
style={{ backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.012) 0px, rgba(255,255,255,0.012) 1px, transparent 1px, transparent 40px), repeating-linear-gradient(45deg, rgba(255,255,255,0.012) 0px, rgba(255,255,255,0.012) 1px, transparent 1px, transparent 40px)' }}
>
<div className="relative max-w-5xl mx-auto">
<div className="mb-10">
<div className="inline-flex items-center gap-2 bg-emerald-400/10 border border-emerald-400/20 text-emerald-300 text-xs font-semibold px-4 py-2 rounded-full mb-5">
<span className="w-2 h-2 rounded-full bg-emerald-400 animate-pulse" />
</div>
<h1 className="text-4xl md:text-5xl font-extrabold text-white tracking-tight leading-tight mb-4">
? .<br />
<span className="text-[#5ba4ff]"> , </span>
</h1>
<p className="text-blue-200/60 text-base md:text-lg max-w-xl leading-relaxed mb-2">
?<br />
, , .
</p>
</div>
{/* Developer tag */}
<div className="flex items-center gap-4 bg-white/5 border border-white/10 rounded-2xl px-6 py-3 mb-8 w-fit">
<div className="w-10 h-10 rounded-full bg-[#1a56db] flex items-center justify-center text-white font-extrabold text-sm flex-shrink-0">
</div>
<div>
<div className="text-white font-bold text-sm"> ()</div>
<div className="text-blue-300/50 text-xs"> · Python / Java / Next.js</div>
</div>
<div className="flex flex-wrap gap-2">
{['Python', 'Java', 'Next.js', 'Docker'].map(t => (
<span key={t} className="bg-[#1a56db]/20 border border-[#1a56db]/30 text-[#5ba4ff] text-xs px-2 py-0.5 rounded-md font-mono">{t}</span>
))}
</div>
</div>
{/* 보증 카드 4개 */}
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3">
{guarantees.map((g) => (
<div key={g.label} className={`bg-[#04102b]/60 border ${g.accentBorder} rounded-xl p-4`}>
<div className={`${g.accentText} mb-2`}>{g.icon}</div>
<div className="text-white font-bold text-sm mb-1">{g.label}</div>
<div className="text-blue-300/40 text-xs leading-relaxed">{g.detail}</div>
</div>
))}
</div>
</div>
</div>
{/* ─── 포트폴리오 ─── */}
<div id="automation" className="px-6 py-12 lg:px-12 scroll-mt-20">
<div className="max-w-5xl mx-auto">
<div className="reveal text-center mb-8">
<p className="text-[#1a56db] text-xs font-bold uppercase tracking-widest mb-2">PORTFOLIO</p>
<h2 className="text-2xl md:text-3xl font-extrabold text-[#04102b]"> </h2>
<p className="text-slate-500 text-sm mt-2"> </p>
</div>
<div className="reveal grid sm:grid-cols-2 lg:grid-cols-3 gap-5">
{portfolio.map((item) => (
<div
key={item.title}
className="bg-white rounded-2xl border border-[#dbe8ff] overflow-hidden hover:shadow-xl hover:shadow-blue-100 hover:-translate-y-1 transition-all duration-200 group"
>
{/* card header */}
<div className={`px-5 pt-5 pb-8 ${item.accentBg}`}>
<div className="flex items-start justify-between">
<div>
<div className={`text-xs font-bold mb-2 uppercase tracking-wider ${item.accentColor}`}>{item.category}</div>
<h3 className="text-white font-extrabold text-sm leading-snug">{item.title}</h3>
</div>
{item.statusType === 'live' ? (
<div className="flex items-center gap-1.5 bg-emerald-400/20 border border-emerald-400/30 text-emerald-300 text-xs font-bold px-2.5 py-1 rounded-full flex-shrink-0 ml-2">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse" />
</div>
) : (
<div className="flex items-center gap-1.5 bg-blue-400/20 border border-blue-400/30 text-blue-300 text-xs font-bold px-2.5 py-1 rounded-full flex-shrink-0 ml-2">
<svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
</div>
)}
</div>
</div>
{/* card body */}
<div className="px-5 py-4 -mt-3 relative">
<p className="text-slate-600 text-xs leading-relaxed mb-3">{item.desc}</p>
{item.result && (
<div className="flex items-start gap-1.5 bg-emerald-50 border border-emerald-200 rounded-lg px-3 py-2 mb-3">
<svg className="w-3.5 h-3.5 text-emerald-600 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
<span className="text-emerald-700 text-xs font-semibold leading-snug">{item.result}</span>
</div>
)}
<div className="flex flex-wrap gap-1.5">
{item.tags.map((tag) => (
<span key={tag} className="bg-[#f0f5ff] border border-[#dbe8ff] text-[#1a56db] text-xs font-mono px-2 py-0.5 rounded-md">
{tag}
</span>
))}
</div>
<div className="flex items-center justify-between mt-3 pt-3 border-t border-slate-100">
<span className="text-xs text-blue-600 font-semibold bg-blue-50 px-2 py-0.5 rounded-full">{item.priceRange}</span>
<a href="#contact-form" className="inline-flex items-center gap-1 text-sm text-blue-600 hover:text-blue-800 font-medium transition">
</a>
</div>
</div>
</div>
))}
</div>
{/* 추가 문구 */}
<div className="reveal mt-6 text-center">
<p className="text-slate-400 text-sm">
·{' '}
<a href="mailto:bgg8988@gmail.com" className="text-[#1a56db] hover:underline font-medium"> </a>
</p>
</div>
</div>
</div>
{/* ─── 고객 후기 ─── */}
<div className="px-6 pb-12 lg:px-12">
<div className="max-w-5xl mx-auto">
<div className="reveal text-center mb-8">
<p className="text-[#1a56db] text-xs font-bold uppercase tracking-widest mb-2">REVIEWS</p>
<h2 className="text-2xl md:text-3xl font-extrabold text-[#04102b]"> </h2>
<p className="text-slate-500 text-sm mt-2" style={{ wordBreak: 'keep-all' }}> </p>
</div>
<div className="reveal grid sm:grid-cols-2 md:grid-cols-3 gap-5">
{testimonials.map((t) => (
<div
key={t.name}
className={`bg-white rounded-2xl border-2 ${t.borderColor} p-6 flex flex-col hover:shadow-lg hover:-translate-y-0.5`}
style={{ transition: 'all 0.4s cubic-bezier(0.16, 1, 0.3, 1)' }}
>
{/* 별점 */}
<div className="flex items-center gap-0.5 mb-4">
{[1,2,3,4,5].map((n) => (
<svg key={n} className="w-4 h-4 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
</svg>
))}
</div>
{/* 후기 내용 */}
<p className="text-slate-600 text-sm leading-relaxed flex-1 mb-5" style={{ wordBreak: 'keep-all' }}>
&ldquo;{t.content}&rdquo;
</p>
{/* 결과 뱃지 */}
<div className={`text-xs font-bold px-3 py-1.5 rounded-lg border mb-4 ${t.tagColor}`} style={{ wordBreak: 'keep-all' }}>
{t.result}
</div>
{/* 의뢰인 */}
<div className="flex items-center gap-3 pt-4 border-t border-slate-100">
<div className={`w-9 h-9 rounded-full ${t.accentColor} flex items-center justify-center text-white font-extrabold text-sm flex-shrink-0`}>
{t.name[0]}
</div>
<div>
<div className="font-bold text-[#04102b] text-sm">{t.name}</div>
<div className="text-slate-400 text-xs">{t.role} · {t.project}</div>
</div>
</div>
</div>
))}
</div>
<p className="text-center text-slate-400 text-xs mt-5">
* . .
</p>
<div className="reveal text-center py-6">
<a href="#contact-form" className="inline-flex items-center gap-2 px-6 py-3 bg-[#1a56db] text-white font-semibold rounded-xl hover:bg-blue-700 transition shadow-sm">
</a>
<p className="text-sm text-slate-400 mt-2">24 · </p>
</div>
</div>
</div>
{/* ─── 진행 프로세스 ─── */}
<div className="px-6 pb-12 lg:px-12">
<div className="max-w-3xl mx-auto">
<div className="reveal text-center mb-10">
<p className="text-[#1a56db] text-xs font-bold uppercase tracking-widest mb-2">PROCESS</p>
<h2 className="text-2xl md:text-3xl font-extrabold text-[#04102b]"> </h2>
<p className="text-slate-500 text-sm mt-2"> 6 </p>
</div>
{/* Vertical timeline */}
<div className="reveal relative">
{/* connecting line */}
<div className="absolute left-6 top-6 bottom-6 w-px bg-[#dbe8ff]" />
<div className="space-y-4">
{process.map((p) => (
<div key={p.num} className="relative flex gap-5">
{/* step circle */}
<div className={`relative z-10 w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0 shadow-lg ${
p.highlight
? 'bg-[#1a56db] shadow-blue-500/30 border border-[#1a56db]/50'
: 'bg-white border-2 border-[#dbe8ff]'
}`}>
<span className={p.highlight ? 'text-white' : 'text-[#1a56db]'}>{p.icon}</span>
</div>
{/* content */}
<div
className={`flex-1 rounded-2xl border p-5 mb-0 ${
p.highlight
? 'border-[#1a56db]/40'
: 'bg-white border-[#dbe8ff]'
}`}
style={p.highlight ? {
background: '#04102b',
backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.015) 0px, rgba(255,255,255,0.015) 1px, transparent 1px, transparent 30px)',
} : {}}
>
<div className="flex items-start justify-between gap-3">
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<span className={`text-xs font-bold font-mono ${p.highlight ? 'text-[#5ba4ff]' : 'text-slate-400'}`}>STEP {p.num}</span>
{p.highlight && (
<span className="bg-[#1a56db]/30 border border-[#1a56db]/40 text-[#5ba4ff] text-xs font-bold px-2 py-0.5 rounded-md"> </span>
)}
</div>
<h3 className={`font-extrabold text-sm mb-1 ${p.highlight ? 'text-white' : 'text-[#04102b]'}`}>{p.title}</h3>
<p className={`text-xs leading-relaxed ${p.highlight ? 'text-blue-200/60' : 'text-slate-500'}`}>{p.desc}</p>
</div>
<div className={`text-xs font-semibold px-2.5 py-1 rounded-full whitespace-nowrap flex-shrink-0 ${
p.highlight
? 'bg-[#1a56db]/30 text-[#5ba4ff]'
: 'bg-[#f0f5ff] text-[#1a56db] border border-[#dbe8ff]'
}`}>
{p.sub}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
{/* ─── 기술 스택 & 신뢰 ─── */}
<div className="px-6 pb-12 lg:px-12">
<div className="max-w-5xl mx-auto grid md:grid-cols-2 gap-5">
{/* Tech Stack */}
<div className="reveal reveal-d1 bg-white rounded-2xl border border-[#dbe8ff] p-6">
<div className="flex items-center gap-2 mb-4">
<div className="w-1 h-5 bg-[#1a56db] rounded-full" />
<h3 className="font-bold text-[#04102b] text-sm"> </h3>
</div>
<div className="space-y-3">
{[
{ label: 'Backend', techs: ['Python', 'Java', 'Spring Boot', 'FastAPI', 'Node.js'] },
{ label: 'Frontend', techs: ['Next.js', 'React', 'TypeScript', 'Tailwind CSS'] },
{ label: 'Database', techs: ['PostgreSQL', 'MySQL', 'Redis', 'SQLite'] },
{ label: 'Infra / API', techs: ['Docker', 'AWS', 'Telegram API', '공공 API'] },
].map((group) => (
<div key={group.label}>
<div className="text-xs font-bold text-slate-400 mb-1.5 uppercase tracking-wider">{group.label}</div>
<div className="flex flex-wrap gap-1.5">
{group.techs.map((t) => (
<span key={t} className="bg-[#f0f5ff] border border-[#dbe8ff] text-[#1a56db] text-xs font-mono px-2.5 py-1 rounded-lg">
{t}
</span>
))}
</div>
</div>
))}
</div>
</div>
{/* 신뢰 포인트 */}
<div
className="reveal reveal-d2 rounded-2xl border border-[#1a3a7a] p-6"
style={{
background: '#04102b',
backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.015) 0px, rgba(255,255,255,0.015) 1px, transparent 1px, transparent 30px)',
}}
>
<div className="flex items-center gap-2 mb-4">
<div className="w-1 h-5 bg-[#5ba4ff] rounded-full" />
<h3 className="font-bold text-white text-sm"> </h3>
</div>
<ul className="space-y-3.5">
{[
{
title: '지금 URL로 직접 확인',
desc: 'jaengseung-made.com — 로또 분석, 주식 자동매매 지금도 운영 중',
icon: (
<svg className="w-4 h-4 text-[#5ba4ff] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
</svg>
),
},
{
title: '계약서 먼저, 개발 나중',
desc: '구두 약속 없음 — 견적서·계약서 발송 후 착수',
icon: (
<svg className="w-4 h-4 text-[#5ba4ff] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
),
},
{
title: '납품 전 전액 환불 보장',
desc: '마음에 안 드시면 이유 불문 전액 환불',
icon: (
<svg className="w-4 h-4 text-[#5ba4ff] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
),
},
{
title: '소스코드 100% 인도',
desc: '완성 후 전체 소스코드 + 배포 가이드 제공',
icon: (
<svg className="w-4 h-4 text-[#5ba4ff] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
),
},
{
title: '납기 지연 시 패널티',
desc: '하루 늦을 때마다 10만원 감면 — 그래서 안 늦습니다',
icon: (
<svg className="w-4 h-4 text-[#5ba4ff] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
),
},
].map((item) => (
<li key={item.title} className="flex items-start gap-3">
{item.icon}
<div>
<div className="text-white text-sm font-bold">{item.title}</div>
<div className="text-blue-300/50 text-xs">{item.desc}</div>
</div>
</li>
))}
</ul>
</div>
</div>
</div>
{/* ─── 문의 폼 ─── */}
<div id="contact-form" className="px-6 pb-14 lg:px-12">
<div className="max-w-5xl mx-auto">
<div className="reveal text-center mb-8">
<p className="text-[#1a56db] text-xs font-bold uppercase tracking-widest mb-2">CONTACT</p>
<h2 className="text-2xl md:text-3xl font-extrabold text-[#04102b]"> </h2>
<p className="text-slate-500 text-sm mt-2"> ? .</p>
</div>
<div className="reveal grid md:grid-cols-5 gap-6">
{/* 왼쪽: 간단 안내 */}
<div className="md:col-span-2 space-y-4">
<div className="bg-white rounded-2xl border border-[#dbe8ff] p-5">
<h3 className="font-bold text-[#04102b] text-sm mb-4"> </h3>
<ul className="space-y-2.5">
{[
'어떤 업무를 자동화/개발하고 싶은지',
'현재 사용 중인 시스템 (엑셀, ERP 등)',
'희망하는 완성 일정',
'예산 범위 (대략적으로도 OK)',
].map((item, i) => (
<li key={item} className="flex items-start gap-2.5 text-xs text-slate-600">
<span className="w-5 h-5 rounded-full bg-[#f0f5ff] border border-[#dbe8ff] text-[#1a56db] font-bold text-xs flex items-center justify-center flex-shrink-0">{i + 1}</span>
{item}
</li>
))}
</ul>
</div>
<div className="bg-white rounded-2xl border border-[#dbe8ff] p-5">
<h3 className="font-bold text-[#04102b] text-sm mb-3"> </h3>
<div className="space-y-2.5">
<a href="mailto:bgg8988@gmail.com" className="flex items-center gap-2.5 text-sm text-slate-600 hover:text-[#1a56db] transition group">
<div className="w-8 h-8 rounded-lg bg-[#f0f5ff] border border-[#dbe8ff] flex items-center justify-center group-hover:bg-[#1a56db] group-hover:border-[#1a56db] transition">
<svg className="w-4 h-4 text-[#1a56db] group-hover:text-white transition" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
bgg8988@gmail.com
</a>
<a href="tel:010-3907-1392" className="flex items-center gap-2.5 text-sm text-slate-600 hover:text-[#1a56db] transition group">
<div className="w-8 h-8 rounded-lg bg-[#f0f5ff] border border-[#dbe8ff] flex items-center justify-center group-hover:bg-[#1a56db] group-hover:border-[#1a56db] transition">
<svg className="w-4 h-4 text-[#1a56db] group-hover:text-white transition" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
</svg>
</div>
010-3907-1392
</a>
</div>
</div>
<div
className="rounded-2xl border border-[#1a3a7a] p-5 text-center"
style={{ background: '#04102b' }}
>
<div className="text-2xl font-extrabold text-white mb-0.5">24h</div>
<div className="text-[#5ba4ff] text-xs font-bold mb-1"> </div>
<div className="text-blue-300/40 text-xs"> · </div>
</div>
</div>
{/* 오른쪽: 폼 */}
<div className="md:col-span-3 bg-white rounded-2xl border border-[#dbe8ff] p-6">
<ContactForm />
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -1,134 +0,0 @@
'use client';
import { useState } from 'react';
import Link from 'next/link';
import ContactModal from '@/app/components/ContactModal';
import { PORTFOLIO } from '@/lib/freelance-portfolio';
import { trackCTAClick } from '@/lib/gtag';
const CARDS = [
{
href: '/work/freelance',
label: '외주 개발',
desc: '맞춤 솔루션 외주 · RPA·API 연동·자동화 포함',
key: 'freelance',
},
{
href: '/work/website',
label: '웹사이트 제작',
desc: '기업·브랜드 사이트 · Next.js + SEO + 배포',
key: 'website',
},
{
href: '/work/saju',
label: 'AI 사주',
desc: 'AI 사주팔자 + 12개 항목 해석 (무료)',
key: 'saju',
},
];
export default function WorkHub() {
const [modalOpen, setModalOpen] = useState(false);
const [modalService, setModalService] = useState('외주 개발 문의');
const openContact = (service: string) => {
setModalService(service);
setModalOpen(true);
};
return (
<div className="min-h-screen bg-black text-white">
<ContactModal
isOpen={modalOpen}
onClose={() => {
setModalOpen(false);
setModalService('외주 개발 문의');
}}
service={modalService}
checklist={['연락처/이메일', '원하는 작업 범위', '희망 일정']}
/>
<section className="relative w-full min-h-[60vh] flex items-center justify-center px-6 border-b border-white/10">
<div className="absolute inset-0 bg-gradient-to-b from-[#060e20] to-black pointer-events-none" />
<div className="relative z-10 max-w-3xl mx-auto text-center">
<p className="font-mono text-[11px] tracking-widest uppercase text-white/50 mb-4">
Custom Work
</p>
<h1
className="kx-display text-4xl md:text-6xl font-bold mb-5"
style={{ wordBreak: 'keep-all', letterSpacing: '-0.02em' }}
>
</h1>
<p className="text-base md:text-lg text-white/70 max-w-2xl mx-auto leading-relaxed">
7 ··. , , AI .
</p>
</div>
</section>
<section className="py-20 px-6">
<div className="max-w-6xl mx-auto grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{CARDS.map((c) => (
<Link
key={c.key}
href={c.href}
onClick={() => trackCTAClick(`work_hub_card_${c.key}`)}
className="group rounded-2xl border border-white/15 bg-white/[0.02] p-5 hover:border-white/40 hover:bg-white/[0.05] transition flex flex-col"
style={{ textDecoration: 'none' }}
>
<p className="font-bold text-white text-sm mb-1.5">{c.label}</p>
<p className="text-xs text-white/60 leading-relaxed flex-1">{c.desc}</p>
<span aria-hidden="true" className="mt-3 text-white/40 text-xs"></span>
</Link>
))}
</div>
</section>
<section className="py-20 px-6 bg-white/[0.02] border-t border-white/10">
<div className="max-w-6xl mx-auto">
<p className="font-mono text-[11px] tracking-widest uppercase text-white/50 mb-4 text-center">
Recent Deliveries
</p>
<h2 className="kx-display text-2xl md:text-3xl font-bold text-center mb-10">
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3">
{PORTFOLIO.map((p) => (
<div
key={p.title}
className={`p-5 rounded-2xl border ${p.borderAccent} ${p.accentBg} flex flex-col`}
>
<p className={`font-mono text-[10px] uppercase tracking-widest ${p.accentColor} mb-2`}>
{p.category}
</p>
<h3 className="font-bold text-white text-sm leading-tight mb-2">{p.title}</h3>
<p className="text-xs text-white/60 line-clamp-3 flex-1">{p.result}</p>
<p className="text-xs text-white/40 mt-3">{p.priceRange}</p>
</div>
))}
</div>
</div>
</section>
<section className="py-20 px-6 border-t border-white/10">
<div className="max-w-3xl mx-auto text-center">
<h2 className="kx-display text-2xl md:text-4xl font-bold mb-5">
?
</h2>
<p className="text-base text-white/70 mb-8">
+ + 24 .
</p>
<button
onClick={() => {
trackCTAClick('work_hub_cta');
openContact('외주 개발 문의');
}}
className="kx-btn-primary inline-flex items-center px-7 py-3 rounded-full text-sm"
>
</button>
</div>
</section>
</div>
);
}

View File

@@ -1,962 +0,0 @@
'use client';
import Link from 'next/link';
import { useState, useEffect, useRef } from 'react';
import ContactModal from '@/app/components/ContactModal';
import { trackCTAClick } from '@/lib/gtag';
const samples = [
{
type: 'corporate',
title: '기업 홈페이지',
subtitle: '테크솔루션㈜',
desc: '"홈페이지가 없어서 B2B 영업 때마다 명함만 건넸다"는 고민을 해결한 기업 브랜드 사이트',
gradient: 'linear-gradient(135deg, #0a192f 0%, #112240 50%, #1a3a6c 100%)',
accent: '#4fc3f7',
tags: ['기업', 'B2B', '신뢰'],
icon: '🏢',
},
{
type: 'bakery',
title: '베이커리 홈페이지',
subtitle: '르 쁘띠 포르',
desc: '"인스타 팔로워는 많은데 실제 방문 예약이 없다"는 F&B 매장의 전환율 문제를 해결한 사이트',
gradient: 'linear-gradient(135deg, #78350f 0%, #92400e 50%, #d97706 100%)',
accent: '#fbbf24',
tags: ['F&B', '로컬', '예약'],
icon: '🥐',
},
{
type: 'portfolio',
title: '개인 포트폴리오',
subtitle: 'Kim Jisu',
desc: '"링크드인에 PDF 올리면 아무도 안 보더라"는 문제를 해결한 채용·수주 전환형 포트폴리오',
gradient: 'linear-gradient(135deg, #000000 0%, #0d0d0d 50%, #001a00 100%)',
accent: '#00ff88',
tags: ['크리에이터', '디자이너', '수주'],
icon: '✦',
},
{
type: 'dashboard',
title: '관리자 대시보드',
subtitle: 'DataFlow SaaS',
desc: '"엑셀로 수기 집계하다가 오류가 나서 야근"을 없애는 실시간 데이터 대시보드',
gradient: 'linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f2a3a 100%)',
accent: '#38bdf8',
tags: ['SaaS', '자동화', '관리'],
icon: '📊',
},
{
type: 'game',
title: '게임 매칭 시스템',
subtitle: 'NEXUS ARENA',
desc: '"디스코드에서 수동으로 팀 짜다가 싸움 났다"는 커뮤니티의 매칭·랭킹 자동화 플랫폼',
gradient: 'linear-gradient(135deg, #000000 0%, #0a0a1a 50%, #0d0029 100%)',
accent: '#a855f7',
tags: ['게임', '커뮤니티', '자동화'],
icon: '⚡',
},
{
type: 'interior',
title: '인테리어 업체 소개',
subtitle: 'AURUM Interior',
desc: '"포트폴리오 사진을 카톡으로만 보내다가 고급 고객을 놓쳤다"는 문제를 해결한 브랜드 사이트',
gradient: 'linear-gradient(135deg, #2C1810 0%, #4A3728 50%, #6B4E37 100%)',
accent: '#D4A853',
tags: ['인테리어', '포트폴리오', '고급'],
icon: '◈',
},
{
type: 'reading',
title: '독서 기록 노트',
subtitle: '나의 독서 기록',
desc: '읽은 책과 감상을 아름답게 기록하는 나만의 독서 저널 — 이런 것도 만들 수 있습니다',
gradient: 'linear-gradient(135deg, #0C0B09 0%, #1A1710 50%, #2A2218 100%)',
accent: '#D4A853',
tags: ['라이프', '독서', '기록'],
icon: '◻',
},
{
type: 'shopping',
title: '개인 쇼핑몰',
subtitle: 'MELLOW STUDIO',
desc: '"카페24 기본 테마가 너무 흔해서 브랜드가 안 살아난다"는 고민을 해결한 커스텀 쇼핑몰',
gradient: 'linear-gradient(135deg, #2A2018 0%, #4A3C2C 50%, #7A6A52 100%)',
accent: '#C4A882',
tags: ['쇼핑몰', '패션', '라이프'],
icon: '◇',
},
];
const processSteps = [
{ step: '01', title: '무료 상담', desc: '요구사항 파악 및 방향성 논의', icon: '💬' },
{ step: '02', title: '기획', desc: '사이트맵 & 와이어프레임', icon: '📋' },
{ step: '03', title: '디자인', desc: 'UI/UX 시안 제작', icon: '🎨' },
{ step: '04', title: '개발', desc: '반응형 퍼블리싱 & 기능 구현', icon: '⚙️' },
{ step: '05', title: '납품', desc: '검수 완료 후 도메인 배포', icon: '🚀' },
];
const plans = [
{
name: '스타터',
price: '20',
unit: '만원~',
color: '#38bdf8',
features: ['5페이지 이내', '반응형 디자인', '기본 SEO 설정', '1개월 유지보수', '3~5영업일 납품'],
note: '개인 블로그, 소규모 소개 사이트',
productId: 'website_starter',
},
{
name: '비즈니스',
price: '100',
unit: '만원~',
color: '#818cf8',
featured: true,
features: ['10페이지 이내', '반응형 디자인', '관리자 페이지', 'SEO 최적화', '3개월 유지보수', '1~2주 납품'],
note: '기업 사이트, 브랜드 페이지',
productId: 'website_business',
},
{
name: '프리미엄',
price: '200',
unit: '만원~',
color: '#f472b6',
features: ['페이지 수 무제한', '맞춤 디자인', '결제/회원 시스템', 'DB 연동', '6개월 유지보수', '일정 협의'],
note: '쇼핑몰, SaaS, 복합 시스템',
productId: 'website_premium',
},
];
const faqs = [
{
q: '제작 기간은 얼마나 걸리나요?',
a: '규모에 따라 다르지만, 스타터는 3~5영업일, 비즈니스는 1~2주, 프리미엄은 협의 후 결정합니다. 빠른 납품이 필요한 경우 별도 상담해 주세요.',
},
{
q: '수정은 몇 번까지 가능한가요?',
a: '기획 확정 후 디자인 시안 수정은 2회, 개발 완료 후 기능 수정은 유지보수 기간 내 자유롭게 가능합니다. 추가 기능 개발은 별도 견적으로 진행합니다.',
},
{
q: '도메인과 호스팅도 도와주시나요?',
a: '네, 도메인 구매부터 서버 세팅, 배포까지 전 과정을 도와드립니다. Vercel, AWS, 카페24 등 원하시는 플랫폼에 맞춰 배포해 드립니다.',
},
{
q: '앱(모바일 앱)이나 쇼핑몰도 개발 가능한가요?',
a: '네. iOS/Android 앱(React Native), 모바일 웹앱, 결제 연동 쇼핑몰, 회원/관리자 시스템 등 모두 개발 가능합니다. 프리미엄 플랜 이상이거나 규모에 따라 별도 견적으로 진행됩니다. 먼저 어떤 기능이 필요한지 상담해 주세요.',
},
{
q: '계약금은 어떻게 되나요? 중간에 취소하면 어떻게 되나요?',
a: '계약서 체결 후 착수금 30%를 먼저 입금받고 개발을 시작합니다. 납품 전 취소 시 완성 비율에 따라 정산하며, 착수 전 전액 환불됩니다. 모든 조건은 계약서에 명시됩니다.',
},
];
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;
}
function SampleMiniPreview({ type }: { type: string }) {
const W = 700, H = 350;
const inner = (content: React.ReactNode, bg: string) => (
<div style={{ height: 175, overflow: 'hidden', position: 'relative', background: bg, borderRadius: '20px 20px 0 0' }}>
<div style={{ width: W, height: H, transform: 'scale(0.5)', transformOrigin: 'top left', position: 'absolute', top: 0, left: 0, pointerEvents: 'none' }}>
{content}
</div>
</div>
);
switch (type) {
case 'corporate':
return inner(
<div style={{ background: '#fff', width: '100%', height: '100%', fontFamily: 'system-ui' }}>
<div style={{ height: 50, background: '#0a192f', display: 'flex', alignItems: 'center', padding: '0 28px', justifyContent: 'space-between' }}>
<div style={{ fontSize: 15, fontWeight: 900, color: '#4fc3f7', letterSpacing: '0.1em' }}>TECHSOLUTION</div>
<div style={{ display: 'flex', gap: 22 }}>
{['서비스','솔루션','고객사','연락처'].map(t => <span key={t} style={{ fontSize: 11, color: '#475569' }}>{t}</span>)}
</div>
<div style={{ fontSize: 11, background: '#1d4ed8', color: '#fff', padding: '7px 18px', borderRadius: 4, fontWeight: 700 }}> </div>
</div>
<div style={{ padding: '36px 32px', backgroundImage: 'linear-gradient(rgba(29,78,216,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(29,78,216,0.04) 1px, transparent 1px)', backgroundSize: '24px 24px' }}>
<div style={{ fontSize: 10, color: '#1d4ed8', letterSpacing: '0.18em', marginBottom: 12, fontWeight: 700 }}>ENTERPRISE IT SOLUTIONS</div>
<div style={{ fontSize: 36, fontWeight: 900, color: '#0a192f', lineHeight: 1.1, marginBottom: 14 }}> IT ,<br/> </div>
<div style={{ fontSize: 12, color: '#64748b', marginBottom: 22, lineHeight: 1.6 }}>15 IT .<br/>··DX .</div>
<div style={{ display: 'flex', gap: 10, marginBottom: 28 }}>
<div style={{ background: '#1d4ed8', color: '#fff', fontSize: 12, padding: '10px 22px', borderRadius: 6, fontWeight: 700 }}> </div>
<div style={{ border: '1px solid #cbd5e1', color: '#475569', fontSize: 12, padding: '10px 22px', borderRadius: 6 }}> </div>
</div>
<div style={{ display: 'flex', gap: 36 }}>
{[['15+','년 업력'],['340+','완료 프로젝트'],['180+','기업 고객'],['99.9%','가동률']].map(([n,l]) => (
<div key={l}><div style={{ fontSize: 22, fontWeight: 800, color: '#0a192f', letterSpacing: '-0.02em' }}>{n}</div><div style={{ fontSize: 9, color: '#94a3b8', marginTop: 3 }}>{l}</div></div>
))}
</div>
</div>
</div>, '#fff'
);
case 'bakery':
return inner(
<div style={{ background: '#fffbf5', width: '100%', height: '100%', fontFamily: 'Georgia, serif' }}>
<div style={{ height: 52, background: 'rgba(255,251,245,0.96)', borderBottom: '1px solid #fde8c8', display: 'flex', alignItems: 'center', padding: '0 28px', justifyContent: 'space-between' }}>
<div><div style={{ fontSize: 18, fontStyle: 'italic', color: '#78350f', fontWeight: 700 }}>Le Petit Fort</div><div style={{ fontSize: 8, color: '#b45309', letterSpacing: '0.2em' }}>ARTISAN BOULANGERIE</div></div>
<div style={{ display: 'flex', gap: 20 }}>
{['메뉴','스토리','예약'].map(t => <span key={t} style={{ fontSize: 11, color: '#92400e', fontFamily: 'system-ui' }}>{t}</span>)}
</div>
<div style={{ fontSize: 11, background: '#b45309', color: '#fff', padding: '7px 18px', borderRadius: 100, fontFamily: 'system-ui', fontWeight: 700 }}> </div>
</div>
<div style={{ padding: '28px 32px 0', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 28, alignItems: 'center' }}>
<div>
<div style={{ fontSize: 10, color: '#b45309', letterSpacing: '0.2em', marginBottom: 12, fontFamily: 'system-ui', fontWeight: 600 }}>Since 2018 · Paris Recipe</div>
<div style={{ fontSize: 38, fontWeight: 700, color: '#1c1008', lineHeight: 1.05, marginBottom: 14 }}> <br/><em></em><br/> </div>
<div style={{ fontSize: 11, color: '#92400e', marginBottom: 18, lineHeight: 1.7, fontFamily: 'system-ui' }}> <br/> .</div>
<div style={{ display: 'flex', gap: 10 }}>
<div style={{ background: '#b45309', color: '#fff', fontSize: 11, padding: '9px 20px', borderRadius: 100, fontFamily: 'system-ui', fontWeight: 700 }}> </div>
<div style={{ border: '1px solid #d97706', color: '#92400e', fontSize: 11, padding: '9px 20px', borderRadius: 100, fontFamily: 'system-ui' }}> </div>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
{[{n:'버터 크루아상',p:'3,200',c:'#d97706'},{n:'소금빵',p:'2,800',c:'#b45309'},{n:'딸기 케이크',p:'7,500',c:'#be185d'},{n:'캄파뉴',p:'8,900',c:'#065f46'}].map(item => (
<div key={item.n} style={{ background: '#fff8f0', borderRadius: 10, padding: 10, border: '1px solid #fde8c8' }}>
<div style={{ height: 38, background: 'linear-gradient(135deg, #fde68a, #fbbf24)', borderRadius: 6, marginBottom: 6 }} />
<div style={{ fontSize: 9, color: '#1c1008', fontFamily: 'system-ui', fontWeight: 600 }}>{item.n}</div>
<div style={{ fontSize: 10, color: item.c, fontFamily: 'system-ui', fontWeight: 700 }}>{item.p}</div>
</div>
))}
</div>
</div>
</div>, '#fffbf5'
);
case 'portfolio':
return inner(
<div style={{ background: '#000', width: '100%', height: '100%' }}>
<div style={{ position: 'absolute', top: -40, left: '25%', width: 320, height: 320, background: 'radial-gradient(circle, rgba(0,255,136,0.06) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ height: 50, background: 'rgba(0,0,0,0.95)', borderBottom: '1px solid rgba(0,255,136,0.1)', display: 'flex', alignItems: 'center', padding: '0 32px', justifyContent: 'space-between', position: 'relative', zIndex: 2 }}>
<div style={{ fontFamily: 'monospace', fontSize: 16, fontWeight: 700, color: '#00ff88' }}>KJ<span style={{ color: 'rgba(0,255,136,0.3)' }}>_</span></div>
<div style={{ display: 'flex', gap: 24 }}>
{['About','Work','Skills','Contact'].map(t => <span key={t} style={{ fontFamily: 'system-ui', fontSize: 10, color: '#374151', letterSpacing: '0.08em', textTransform: 'uppercase' }}>{t}</span>)}
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div style={{ width: 6, height: 6, borderRadius: '50%', background: '#00ff88' }} />
<span style={{ fontFamily: 'monospace', fontSize: 9, color: '#00ff88' }}>Available</span>
<div style={{ marginLeft: 8, border: '1px solid #00ff88', color: '#00ff88', fontSize: 9, padding: '5px 12px', borderRadius: 3, fontFamily: 'monospace', fontWeight: 700 }}>HIRE ME</div>
</div>
</div>
<div style={{ position: 'absolute', inset: 0, top: 50, backgroundImage: 'linear-gradient(rgba(0,255,136,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(0,255,136,0.04) 1px, transparent 1px)', backgroundSize: '32px 32px', pointerEvents: 'none' }} />
<div style={{ padding: '38px 32px', position: 'relative', zIndex: 2, display: 'grid', gridTemplateColumns: '1fr auto', gap: 32, alignItems: 'center' }}>
<div>
<div style={{ fontFamily: 'monospace', fontSize: 10, color: '#00ff88', letterSpacing: '0.15em', marginBottom: 16, border: '1px solid rgba(0,255,136,0.2)', display: 'inline-block', padding: '3px 10px' }}>FULL-STACK DEVELOPER</div>
<div style={{ fontSize: 56, fontWeight: 900, color: '#fff', lineHeight: 0.9, letterSpacing: '-0.03em', marginBottom: 18, fontFamily: 'system-ui' }}>Kim<br/><span style={{ color: '#00ff88' }}>Jisu</span></div>
<div style={{ fontSize: 11, color: '#4b5563', lineHeight: 1.7, marginBottom: 22, fontFamily: 'system-ui' }}>React · Next.js · TypeScript · Node.js<br/> .</div>
<div style={{ display: 'flex', gap: 10 }}>
<div style={{ background: '#00ff88', color: '#000', fontSize: 11, padding: '9px 22px', borderRadius: 4, fontWeight: 800, fontFamily: 'monospace' }}>VIEW WORK</div>
<div style={{ border: '1px solid rgba(0,255,136,0.3)', color: '#00ff88', fontSize: 11, padding: '9px 22px', borderRadius: 4, fontFamily: 'monospace' }}>CONTACT</div>
</div>
</div>
<div style={{ width: 130, height: 160, background: 'linear-gradient(135deg, #001a0d, #003322)', border: '1px solid rgba(0,255,136,0.2)', borderRadius: 12, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<div style={{ width: 80, height: 80, borderRadius: '50%', border: '2px solid rgba(0,255,136,0.3)', background: 'rgba(0,255,136,0.05)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ fontSize: 26, color: '#00ff88', fontFamily: 'monospace', fontWeight: 700 }}>KJ</span>
</div>
</div>
</div>
</div>, '#000'
);
case 'dashboard':
return inner(
<div style={{ background: '#0f172a', width: '100%', height: '100%', display: 'flex', fontFamily: 'system-ui' }}>
<div style={{ width: 140, background: '#020617', borderRight: '1px solid rgba(255,255,255,0.05)', padding: '20px 14px' }}>
<div style={{ fontSize: 14, fontWeight: 800, color: '#38bdf8', marginBottom: 24, letterSpacing: '-0.02em' }}>DataFlow</div>
{['대시보드','분석','리포트','사용자','설정'].map((item, i) => (
<div key={item} style={{ fontSize: 10, color: i === 0 ? '#38bdf8' : '#475569', padding: '8px 10px', borderRadius: 6, marginBottom: 4, background: i === 0 ? 'rgba(56,189,248,0.1)' : 'transparent' }}>{item}</div>
))}
</div>
<div style={{ flex: 1, padding: '20px 22px' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
<div style={{ fontSize: 14, fontWeight: 700, color: '#e2e8f0' }}> </div>
<div style={{ fontSize: 10, color: '#475569', background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.06)', padding: '4px 12px', borderRadius: 6 }}> </div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 10, marginBottom: 14 }}>
{[{l:'총 매출',v:'₩48.2M',c:'#38bdf8',u:true},{l:'신규 사용자',v:'1,247',c:'#34d399',u:true},{l:'전환율',v:'12.4%',c:'#a78bfa',u:false}].map(s => (
<div key={s.l} style={{ background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 8, padding: '12px 14px' }}>
<div style={{ fontSize: 8, color: '#475569', marginBottom: 6 }}>{s.l}</div>
<div style={{ fontSize: 20, fontWeight: 800, color: s.c, letterSpacing: '-0.02em' }}>{s.v}</div>
<div style={{ fontSize: 8, color: s.u ? '#34d399' : '#f87171', marginTop: 4 }}>{s.u ? '↑ +8.3%' : '↓ -1.2%'}</div>
</div>
))}
</div>
<div style={{ background: 'rgba(255,255,255,0.02)', border: '1px solid rgba(255,255,255,0.05)', borderRadius: 8, padding: 14, height: 110 }}>
<div style={{ fontSize: 9, color: '#475569', marginBottom: 10 }}> </div>
<div style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height: 72 }}>
{[40,55,35,65,80,60,90,75,85,95,70,100].map((h, i) => (
<div key={i} style={{ flex: 1, height: `${h}%`, background: i === 11 ? '#38bdf8' : 'rgba(56,189,248,0.22)', borderRadius: '2px 2px 0 0' }} />
))}
</div>
</div>
</div>
</div>, '#0f172a'
);
case 'game':
return inner(
<div style={{ background: '#000', width: '100%', height: '100%' }}>
<div style={{ position: 'absolute', top: -60, left: '30%', width: 340, height: 340, background: 'radial-gradient(circle, rgba(168,85,247,0.14) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', top: -20, right: '10%', width: 200, height: 200, background: 'radial-gradient(circle, rgba(6,182,212,0.1) 0%, transparent 70%)', pointerEvents: 'none' }} />
<div style={{ height: 50, background: 'rgba(0,0,0,0.9)', borderBottom: '1px solid rgba(6,182,212,0.2)', display: 'flex', alignItems: 'center', padding: '0 28px', justifyContent: 'space-between', position: 'relative', zIndex: 2 }}>
<div style={{ fontFamily: 'monospace', fontSize: 15, fontWeight: 900, color: '#06b6d4', letterSpacing: '0.15em' }}>NEXUS<span style={{ color: '#a855f7' }}>ARENA</span></div>
<div style={{ display: 'flex', gap: 20 }}>
{['랭킹','매칭','챔피언','스토어'].map(t => <span key={t} style={{ fontFamily: 'system-ui', fontSize: 10, color: '#374151', letterSpacing: '0.08em' }}>{t}</span>)}
</div>
<div style={{ background: 'linear-gradient(90deg, #06b6d4, #a855f7)', color: '#000', fontSize: 10, padding: '7px 18px', borderRadius: 3, fontWeight: 800, fontFamily: 'monospace' }}>PLAY NOW</div>
</div>
<div style={{ padding: '32px 32px', position: 'relative', zIndex: 2, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24, alignItems: 'center' }}>
<div>
<div style={{ fontFamily: 'monospace', fontSize: 9, color: '#06b6d4', letterSpacing: '0.2em', marginBottom: 14 }}>SEASON 7 · COMPETITIVE</div>
<div style={{ fontSize: 50, fontWeight: 900, color: '#fff', lineHeight: 0.88, letterSpacing: '-0.03em', marginBottom: 18, fontFamily: 'system-ui' }}>NEXUS<br/><span style={{ background: 'linear-gradient(90deg, #06b6d4, #a855f7)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}>ARENA</span></div>
<div style={{ fontSize: 10, color: '#4b5563', lineHeight: 1.65, marginBottom: 22, fontFamily: 'system-ui' }}> · · <br/> .</div>
<div style={{ display: 'flex', gap: 10 }}>
<div style={{ background: 'linear-gradient(90deg, #06b6d4, #a855f7)', color: '#fff', fontSize: 11, padding: '10px 22px', borderRadius: 4, fontWeight: 800, fontFamily: 'monospace' }}>PLAY NOW</div>
<div style={{ border: '1px solid rgba(6,182,212,0.4)', color: '#06b6d4', fontSize: 11, padding: '10px 22px', borderRadius: 4, fontFamily: 'monospace' }}> </div>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
{[{name:'VIPER',role:'Assassin',c:'#06b6d4'},{name:'NOVA',role:'Mage',c:'#a855f7'},{name:'IRON',role:'Tank',c:'#94a3b8'},{name:'KIRA',role:'Support',c:'#ec4899'}].map(ch => (
<div key={ch.name} style={{ background: 'rgba(255,255,255,0.03)', border: `1px solid ${ch.c}30`, borderRadius: 8, padding: 10 }}>
<div style={{ height: 34, background: `linear-gradient(135deg, ${ch.c}20, ${ch.c}05)`, borderRadius: 4, marginBottom: 6, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ width: 24, height: 24, borderRadius: '50%', background: `${ch.c}30`, border: `1px solid ${ch.c}60` }} />
</div>
<div style={{ fontFamily: 'monospace', fontSize: 9, color: ch.c, fontWeight: 700 }}>{ch.name}</div>
<div style={{ fontSize: 8, color: '#374151', fontFamily: 'system-ui' }}>{ch.role}</div>
</div>
))}
</div>
</div>
</div>, '#000'
);
case 'interior':
return inner(
<div style={{ background: '#faf8f4', width: '100%', height: '100%' }}>
<div style={{ height: 50, background: '#2C1810', display: 'flex', alignItems: 'center', padding: '0 28px', justifyContent: 'space-between' }}>
<div><div style={{ fontFamily: 'Georgia, serif', fontSize: 14, color: '#D4A853', fontWeight: 700, letterSpacing: '0.12em' }}>AURUM</div><div style={{ fontSize: 7, color: '#6B4E37', letterSpacing: '0.25em' }}>INTERIOR DESIGN</div></div>
<div style={{ display: 'flex', gap: 18 }}>
{['포트폴리오','서비스','견적 문의'].map(t => <span key={t} style={{ fontSize: 9, color: '#9a8070', fontFamily: 'system-ui' }}>{t}</span>)}
</div>
<div style={{ border: '1px solid #D4A853', color: '#D4A853', fontSize: 9, padding: '6px 14px', fontFamily: 'system-ui', letterSpacing: '0.08em' }}>CONTACT</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', height: 300 }}>
<div style={{ padding: '32px 28px', display: 'flex', flexDirection: 'column', justifyContent: 'center', background: '#2C1810' }}>
<div style={{ fontSize: 9, color: '#D4A853', letterSpacing: '0.25em', marginBottom: 14, fontFamily: 'system-ui', textTransform: 'uppercase' }}>Premium Interior Design</div>
<div style={{ fontFamily: 'Georgia, serif', fontSize: 34, color: '#faf8f4', lineHeight: 1.1, marginBottom: 18 }}><br/><em></em><br/> </div>
<div style={{ fontSize: 10, color: '#9a8070', lineHeight: 1.7, fontFamily: 'system-ui', marginBottom: 22 }}>20 <br/> .</div>
<div style={{ display: 'inline-flex' }}><div style={{ background: '#D4A853', color: '#2C1810', fontSize: 10, padding: '10px 22px', fontFamily: 'system-ui', fontWeight: 700 }}> </div></div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gridTemplateRows: '1fr 1fr', gap: 3 }}>
{['linear-gradient(135deg, #c9b99a, #a8927a)','linear-gradient(135deg, #8B7355, #6B5A47)','linear-gradient(135deg, #D4C5A9, #B8A88A)','linear-gradient(135deg, #7C6555, #5C4A3A)'].map((bg, i) => (
<div key={i} style={{ background: bg }}><div style={{ width: '100%', height: '100%', background: 'rgba(44,24,16,0.08)' }} /></div>
))}
</div>
</div>
</div>, '#faf8f4'
);
case 'reading':
return inner(
<div style={{ background: '#0C0B09', width: '100%', height: '100%' }}>
<div style={{ height: 46, background: '#0C0B09', borderBottom: '1px solid rgba(212,168,83,0.1)', display: 'flex', alignItems: 'center', padding: '0 28px', justifyContent: 'space-between' }}>
<div style={{ fontFamily: 'Georgia, serif', fontSize: 14, fontStyle: 'italic', color: '#D4A853', fontWeight: 600 }}> </div>
<div style={{ display: 'flex', gap: 18 }}>
{['서재','월별 기록','통계'].map(t => <span key={t} style={{ fontSize: 9, color: '#5c5040', fontFamily: 'system-ui' }}>{t}</span>)}
</div>
</div>
<div style={{ padding: '32px 32px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 28, alignItems: 'center' }}>
<div>
<div style={{ fontSize: 10, color: '#D4A853', letterSpacing: '0.2em', marginBottom: 14, fontFamily: 'system-ui', textTransform: 'uppercase' }}>My Reading Journal</div>
<div style={{ fontFamily: 'Georgia, serif', fontSize: 40, color: '#faf8f4', lineHeight: 1.05, marginBottom: 16 }}> <br/><em style={{ color: '#D4A853' }}></em><br/> </div>
<div style={{ fontSize: 10, color: '#5c5040', lineHeight: 1.7, fontFamily: 'system-ui', marginBottom: 22 }}> .<br/> .</div>
<div style={{ display: 'inline-flex', background: '#D4A853', color: '#0C0B09', fontSize: 10, padding: '9px 22px', fontFamily: 'system-ui', fontWeight: 700 }}> </div>
<div style={{ display: 'flex', gap: 24, marginTop: 22 }}>
{[['47','완독'],['1,240','페이지'],['12','이번 달']].map(([n,l]) => (
<div key={l}><div style={{ fontSize: 20, fontWeight: 800, color: '#D4A853', fontFamily: 'Georgia, serif' }}>{n}</div><div style={{ fontSize: 8, color: '#5c5040', fontFamily: 'system-ui', marginTop: 2 }}>{l}</div></div>
))}
</div>
</div>
<div style={{ display: 'flex', gap: 8, alignItems: 'flex-end', justifyContent: 'center' }}>
{[{h:130,bg:'linear-gradient(180deg,#1e3a5f,#0a1628)',sp:'#2563eb'},{h:152,bg:'linear-gradient(180deg,#2C1810,#1a0e0a)',sp:'#D4A853'},{h:118,bg:'linear-gradient(180deg,#1a1a1a,#0d0d0d)',sp:'#6b7280'},{h:142,bg:'linear-gradient(180deg,#1e1b4b,#0f0d2e)',sp:'#7c3aed'},{h:120,bg:'linear-gradient(180deg,#064e3b,#022c22)',sp:'#10b981'}].map((b, i) => (
<div key={i} style={{ width: 38, height: b.h, background: b.bg, borderRadius: '3px 3px 0 0', borderLeft: `3px solid ${b.sp}40`, boxShadow: '2px 0 8px rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ width: 1, height: '80%', background: `${b.sp}30` }} />
</div>
))}
</div>
</div>
</div>, '#0C0B09'
);
case 'shopping':
return inner(
<div style={{ background: '#F4F2EF', width: '100%', height: '100%' }}>
<div style={{ height: 52, background: '#F4F2EF', borderBottom: '1px solid #E0DDD8', display: 'flex', alignItems: 'center', padding: '0 28px', justifyContent: 'space-between' }}>
<div style={{ fontSize: 16, fontWeight: 900, color: '#0C0B09', letterSpacing: '0.2em', textTransform: 'uppercase', fontFamily: 'system-ui' }}>MELLOW<span style={{ fontWeight: 300 }}> STUDIO</span></div>
<div style={{ display: 'flex', gap: 20 }}>
{['NEW','OUTER','TOP','BOTTOM'].map(t => <span key={t} style={{ fontSize: 9, color: '#7C7870', fontFamily: 'system-ui', letterSpacing: '0.1em' }}>{t}</span>)}
</div>
<div style={{ display: 'flex', gap: 14, fontSize: 12, color: '#0C0B09', fontFamily: 'system-ui' }}><span>🔍</span><span>🛍 2</span></div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', height: 298 }}>
<div style={{ background: 'linear-gradient(135deg, #2A2018, #4A3C2C)', display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', overflow: 'hidden' }}>
<div style={{ width: 120, height: 200, background: 'linear-gradient(180deg, #c8b89a, #9a8a72)', borderRadius: 4, boxShadow: '16px 16px 40px rgba(0,0,0,0.35)' }} />
<div style={{ position: 'absolute', bottom: 16, left: 16 }}>
<div style={{ fontSize: 9, color: 'rgba(244,242,239,0.5)', letterSpacing: '0.2em', fontFamily: 'system-ui' }}>NEW ARRIVAL</div>
<div style={{ fontSize: 17, fontWeight: 900, color: '#F4F2EF', fontFamily: 'system-ui', letterSpacing: '-0.01em' }}>SS 2025</div>
</div>
</div>
<div style={{ padding: 20, display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
<div>
<div style={{ fontSize: 9, color: '#7C7870', letterSpacing: '0.2em', marginBottom: 10, fontFamily: 'system-ui' }}>COLLECTION</div>
<div style={{ fontSize: 30, fontWeight: 900, color: '#0C0B09', lineHeight: 1.05, fontFamily: 'system-ui', letterSpacing: '-0.02em', marginBottom: 12 }}>Quiet<br/>Luxury</div>
<div style={{ fontSize: 10, color: '#7C7870', lineHeight: 1.65, fontFamily: 'system-ui', marginBottom: 18 }}> .<br/> .</div>
<div style={{ display: 'inline-flex', background: '#0C0B09', color: '#F4F2EF', fontSize: 9, padding: '9px 20px', letterSpacing: '0.15em', fontFamily: 'system-ui', fontWeight: 700 }}>SHOP NOW</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8 }}>
{[['#c8b89a','₩328K'],['#8a7860','₩498K'],['#d4c5a9','₩218K']].map(([bg, p], i) => (
<div key={i} style={{ borderRadius: 3, overflow: 'hidden' }}>
<div style={{ height: 52, background: `linear-gradient(160deg, ${bg}, rgba(0,0,0,0.08))` }} />
<div style={{ fontSize: 8, color: '#7C7870', fontFamily: 'system-ui', paddingTop: 4 }}>{p}</div>
</div>
))}
</div>
</div>
</div>
</div>, '#F4F2EF'
);
default:
return <div style={{ height: 175, background: '#0a0f1e', borderRadius: '20px 20px 0 0' }} />;
}
}
export default function WebsiteServicePage() {
const [openFaq, setOpenFaq] = useState<number | null>(null);
const [showTop, setShowTop] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
const [modalService, setModalService] = useState('홈페이지 제작');
const openModal = (service: string) => {
trackCTAClick(service, '/work/website');
setModalService(service);
setModalOpen(true);
};
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: '#030712', minHeight: '100vh', color: 'white', fontFamily: "'Pretendard', 'Apple SD Gothic Neo', system-ui, sans-serif" }}>
<ContactModal
isOpen={modalOpen}
onClose={() => setModalOpen(false)}
service={modalService}
checklist={[
'원하시는 홈페이지 종류 (소개/쇼핑몰/SaaS 등)',
'참고하고 싶은 사이트 URL (있으면)',
'필요한 주요 페이지 및 기능',
'희망 납품 일정 및 예산 범위',
'디자인 선호 스타일 (모던/감성/심플 등)',
]}
accentColor="text-indigo-400"
headerFrom="#0a0a1a"
headerTo="#1e1b4b"
/>
<style dangerouslySetInnerHTML={{ __html: `
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.min.css');
* { 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-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);
}
/* 모바일 반응형 */
@media (max-width: 640px) {
.ws-portfolio-grid { grid-template-columns: 1fr !important; }
.ws-process-steps { flex-direction: column !important; align-items: stretch !important; }
.ws-process-divider { display: none !important; }
.ws-pricing-grid { grid-template-columns: 1fr !important; }
.ws-hero-stats { gap: 0 !important; flex-wrap: nowrap !important; }
.ws-hero-stats > div { padding: 0 16px !important; }
.ws-cta-box { padding: 36px 24px !important; }
}
@media (max-width: 480px) {
.ws-hero-buttons { flex-direction: column !important; align-items: stretch !important; }
.ws-hero-buttons a, .ws-hero-buttons button { text-align: center !important; justify-content: center !important; }
}
/* 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', position: 'relative', overflow: 'hidden' }}>
{/* Diagonal pattern */}
<div style={{
position: 'absolute', inset: 0, pointerEvents: 'none',
backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.015) 0px, rgba(255,255,255,0.015) 1px, transparent 1px, transparent 40px)',
}} />
<div style={{ maxWidth: 820, margin: '0 auto', position: 'relative', animation: 'ws-fadeUp 0.9s cubic-bezier(0.16,1,0.3,1) both' }}>
<p style={{
fontSize: 11, fontWeight: 700, letterSpacing: '0.18em',
color: '#6366f1', textTransform: 'uppercase',
fontFamily: 'monospace',
marginBottom: 24,
}}>
</p>
<h1 style={{
fontSize: 'clamp(28px, 4.5vw, 54px)', fontWeight: 800,
lineHeight: 1.2, marginBottom: 20,
letterSpacing: '-0.02em',
color: '#ffffff',
wordBreak: 'keep-all',
}}>
·· ,<br/>
</h1>
<p style={{
fontSize: 16, color: '#64748b', lineHeight: 1.85, marginBottom: 36,
wordBreak: 'keep-all',
}}>
SaaS·· <br/>
. 10 .
</p>
<div className="ws-hero-buttons" style={{ display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap' }}>
<Link href="/work/freelance?service=website" style={{
display: 'inline-flex', alignItems: 'center', gap: 8,
padding: '14px 28px',
background: '#6366f1',
borderRadius: 12, color: 'white', fontWeight: 700, fontSize: 15,
textDecoration: 'none',
transition: 'background 0.2s',
}}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = '#4f46e5'; }}
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#6366f1'; }}>
</Link>
<a href="#samples" style={{
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 className="ws-hero-stats" style={{ display: 'flex', gap: 0, justifyContent: 'center', marginTop: 56, flexWrap: 'wrap' }}>
{[
{ num: '3~5일', label: '최단 납품 (스타터)' },
{ num: '20만원~', label: '시작 가격' },
{ num: '전액환불', label: '납품 전 환불 보장' },
].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>
{/* ── Feature tags ── */}
<div style={{ borderTop: '1px solid rgba(255,255,255,0.05)', borderBottom: '1px solid rgba(255,255,255,0.05)', padding: '14px 24px' }}>
<div style={{ maxWidth: 1000, margin: '0 auto', display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'center' }}>
{['반응형 디자인', 'SEO 최적화', '웹앱·모바일웹', '계약서 작성', '소스코드 제공', '납기 패널티 보장', '도메인 배포'].map((t) => (
<span key={t} style={{ padding: '4px 12px', fontSize: '11px', color: '#475569', letterSpacing: '0.06em', border: '1px solid rgba(255,255,255,0.07)', borderRadius: 4, fontFamily: 'monospace' }}>
{t}
</span>
))}
</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: 1, border: '1px solid rgba(255,255,255,0.06)', borderRadius: 12, overflow: 'hidden' }}>
{[
{
title: '계약서 필수 작성', desc: '모든 프로젝트 계약서 체결 후 진행',
icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} style={{ width: 20, height: 20 }}><path strokeLinecap="round" strokeLinejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25zM6.75 12h.008v.008H6.75V12zm0 3h.008v.008H6.75V15zm0 3h.008v.008H6.75V18z" /></svg>,
},
{
title: '주간 진행 보고', desc: '매주 작업 현황 공유, 연락 두절 없음',
icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} style={{ width: 20, height: 20 }}><path strokeLinecap="round" strokeLinejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z" /></svg>,
},
{
title: '소스코드 전액 제공', desc: '완성 후 전체 소스코드 인도',
icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} style={{ width: 20, height: 20 }}><path strokeLinecap="round" strokeLinejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5" /></svg>,
},
{
title: '납기 지연 패널티', desc: '지연 1일당 10만원 자동 감면',
icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} style={{ width: 20, height: 20 }}><path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z" /></svg>,
},
{
title: '실시간 진행 현황', desc: '마이페이지에서 7단계 진행 상황 직접 확인',
icon: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} style={{ width: 20, height: 20 }}><path strokeLinecap="round" strokeLinejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg>,
},
].map((b) => (
<div key={b.title} style={{
padding: '20px 22px',
background: 'rgba(255,255,255,0.02)',
display: 'flex', gap: 14, alignItems: 'flex-start',
}}>
<span style={{ color: '#6366f1', flexShrink: 0, marginTop: 2 }}>{b.icon}</span>
<div>
<div style={{ fontSize: 13, fontWeight: 600, 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>
</div>
))}
</div>
</section>
{/* ── 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 className="ws-portfolio-grid" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 18 }}>
{samples.map((s) => (
<Link key={s.type} href={`/work/website/samples/${s.type}`} style={{ textDecoration: 'none' }}>
<div className="ws-sample-card">
<div style={{ position: 'relative' }}>
<SampleMiniPreview type={s.type} />
<div style={{ position: 'absolute', top: 12, left: 12, display: 'flex', gap: 5, zIndex: 10 }}>
{s.tags.map((tag) => (
<span key={tag} style={{
fontSize: 10, fontWeight: 600, color: '#e2e8f0',
background: 'rgba(0,0,0,0.52)', backdropFilter: 'blur(8px)',
border: '1px solid rgba(255,255,255,0.13)',
padding: '2px 8px', borderRadius: 100,
}}>{tag}</span>
))}
</div>
<div style={{
position: 'absolute', bottom: 12, right: 12, zIndex: 10,
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: '#475569', fontSize: 14 }}> 5 </p>
</div>
<div className="ws-process-steps" style={{ display: 'flex', alignItems: 'stretch', flexWrap: 'wrap', justifyContent: 'center', gap: 0 }}>
{processSteps.map((p, i) => (
<div key={i} style={{ display: 'flex', alignItems: 'center' }}>
<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: 22, fontWeight: 800, color: '#6366f1', fontFamily: 'monospace', marginBottom: 12, letterSpacing: '-0.02em' }}>
{p.step}
</div>
<div style={{ fontSize: 14, fontWeight: 700, color: 'white', marginBottom: 6, wordBreak: 'keep-all' }}>
{p.title}
</div>
<div style={{ fontSize: 11, color: '#334155', lineHeight: 1.55, wordBreak: 'keep-all' }}>
{p.desc}
</div>
</div>
{i < processSteps.length - 1 && (
<div className="ws-process-divider" style={{ color: '#1e293b', fontSize: 20, padding: '0 4px', flexShrink: 0 }}></div>
)}
</div>
))}
</div>
</div>
</section>
{/* ── 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 className="ws-pricing-grid" 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 ? '#0d1240' : '#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',
}}>
{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 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>
<button
onClick={() => openModal(`홈페이지 제작 - ${plan.name}`)}
style={{
display: 'block', width: '100%', 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, border: plan.featured ? 'none' : '1px solid rgba(255,255,255,0.07)',
transition: 'opacity 0.2s', cursor: 'pointer',
}}
>
</button>
</div>
))}
</div>
</div>
</section>
{/* ── 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 className="ws-cta-box" style={{
maxWidth: 640, margin: '0 auto',
padding: '56px 44px', borderRadius: 24,
background: '#04102b',
backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.012) 0px, rgba(255,255,255,0.012) 1px, transparent 1px, transparent 40px)',
border: '1px solid rgba(99,102,241,0.3)',
boxShadow: '0 24px 80px rgba(0,0,0,0.3)',
}}>
<h2 style={{ fontSize: 28, fontWeight: 800, color: 'white', marginBottom: 14, letterSpacing: '-0.02em', wordBreak: 'keep-all' }}>
?
</h2>
<p style={{ color: '#94a3b8', fontSize: 15, lineHeight: 1.75, marginBottom: 32, wordBreak: 'keep-all' }}>
24 .<br/>
···, .
</p>
<Link href="/work/freelance?service=website" style={{
display: 'inline-block', padding: '15px 40px',
background: '#6366f1',
borderRadius: 12, color: 'white', fontWeight: 700, fontSize: 15,
textDecoration: 'none',
boxShadow: '0 8px 24px 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 40px rgba(99,102,241,0.5)'; }}
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.transform = ''; (e.currentTarget as HTMLElement).style.boxShadow = '0 8px 24px rgba(99,102,241,0.4)'; }}>
</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: '5.5rem', right: '2rem', zIndex: 200,
width: 48, height: 48, borderRadius: '50%',
background: '#6366f1',
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>
);
}