feat(home): Liquid Glass + Jua 폰트로 헤더·푸터·홈·뮤직 페이지 전환

- layout.tsx: Bagel/Inter/Manrope/SpaceGrotesk → Jua 단일화 + GlassFilter 마운트
- globals.css: 글래스 효과·Jua 폰트 변수
- TopNav: 알약형 글래스 헤더 (스크롤 시 max-w-3xl 축소)
- PublicShell: 푸터 정돈
- 홈 page.tsx: hero 영상 배경 + GlassButton CTA + 트윗 마퀴
- 뮤직 page.tsx: SparklesOverlay + 3D card effect

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-28 02:12:29 +09:00
parent 7ee75f1511
commit 32dce9ea1e
6 changed files with 493 additions and 457 deletions

View File

@@ -3,6 +3,8 @@
import { useState } from 'react';
import Link from 'next/link';
import PurchaseAgreementModal from '../../components/PurchaseAgreementModal';
import { SparklesOverlay } from '@/components/ui/sparkles-text';
import { CardBody, CardContainer, CardItem } from '@/components/ui/3d-card-effect';
type Tier = 'starter' | 'pro' | 'master';
@@ -47,42 +49,10 @@ const TIERS: Record<Tier, { name: string; price: string; priceNum: string; desc:
};
const PROCESS = [
{
num: '01',
title: '크리에이티브 디렉팅',
subtitle: 'Concept & Lyrics',
customer: '원하는 키워드 3개 또는 사연 제공',
value: 'ChatGPT·Claude로 Suno가 이해하는 가사·스타일 태그로 변환',
result: 'AI 최적화 가사 · 메타데이터 시트',
color: 'from-violet-500 to-fuchsia-500',
},
{
num: '02',
title: '오디오 엔지니어링',
subtitle: 'Music Generation',
customer: '결과물 확인 · 방향 피드백',
value: 'Suno Custom Mode로 가사 배치·파트·보컬·악기 세밀 조정. 가장 높은 퀄리티가 나올 때까지 프롬프트 깎기',
result: '고품질 완곡 (Full Track, 스템 분리본)',
color: 'from-fuchsia-500 to-pink-500',
},
{
num: '03',
title: '비주얼 마스터링',
subtitle: 'AI MV Generation',
customer: '-',
value: 'Midjourney · Runway · Luma로 음악 분위기에 맞는 이미지·영상 생성. 비트와 가사에 맞춘 싱크 설계',
result: '쇼츠(9:16) 또는 유튜브(16:9) 고화질 영상',
color: 'from-sky-500 to-cyan-500',
},
{
num: '04',
title: '퍼블리싱 가이드',
subtitle: 'Viral Optimization',
customer: '유튜브 업로드',
value: '제목·해시태그·설명란(SEO) AI 최적화 템플릿 제공',
result: '즉시 업로드 가능한 유튜브 배포 패키지',
color: 'from-cyan-500 to-emerald-500',
},
{ num: '01', subtitle: 'Concept & Lyrics', title: '크리에이티브 디렉팅', result: 'AI 최적화 가사 · 메타데이터 시트' },
{ num: '02', subtitle: 'Music Generation', title: '오디오 엔지니어링', result: '고품질 완곡 (Full Track, 스템 분리본)' },
{ num: '03', subtitle: 'AI MV Generation', title: '비주얼 마스터링', result: '쇼츠(9:16) 또는 유튜브(16:9) 고화질 영상' },
{ num: '04', subtitle: 'Viral Optimization', title: '퍼블리싱 가이드', result: '즉시 업로드 가능한 유튜브 배포 패키지' },
];
const FAQS = [
@@ -113,87 +83,17 @@ export default function MusicServicePage() {
const [openFaq, setOpenFaq] = useState<number | null>(0);
return (
<div className="min-h-full bg-slate-950 text-white">
{/* HERO — 결과 중심 2-column */}
<section className="px-6 pt-16 pb-14 lg:px-14 bg-slate-950 border-b border-white/5">
<div className="max-w-6xl mx-auto grid lg:grid-cols-2 gap-10 lg:gap-14 items-center">
{/* 좌: 카피 + CTA */}
<div>
<div className="flex items-center gap-2 mb-5">
<span className="inline-flex h-2 w-2 rounded-full bg-violet-400 animate-pulse" />
<span className="font-mono text-[11px] tracking-widest uppercase text-violet-300/80">
AI MUSIC PACK · v1
</span>
</div>
<h1
className="kx-display text-[2.25rem] md:text-[3.25rem] font-extrabold leading-[1.1] mb-5"
style={{ wordBreak: 'keep-all', letterSpacing: '-0.02em' }}
>
,
<br />
<span className="bg-gradient-to-r from-violet-300 to-cyan-300 bg-clip-text text-transparent">
.
</span>
</h1>
<p className="text-slate-300 text-base md:text-lg leading-relaxed mb-8 max-w-lg">
Suno , , .
<br className="hidden sm:block" />
.
</p>
<div className="flex flex-col sm:flex-row gap-3">
<a
href="#pricing"
className="inline-flex items-center justify-center gap-2 bg-violet-500 hover:bg-violet-400 text-white px-7 py-4 rounded-xl font-extrabold text-sm transition-colors shadow-[0_12px_40px_-12px_rgba(139,92,246,0.6)]"
>
39,000
</a>
<Link
href="/services/music/samples"
className="inline-flex items-center justify-center gap-2 border border-white/15 hover:border-white/30 hover:bg-white/5 text-white px-7 py-4 rounded-xl font-semibold text-sm transition-colors"
>
</Link>
</div>
</div>
{/* 우: 결과 프리뷰 */}
<div className="relative">
<div className="absolute -inset-6 bg-gradient-to-br from-violet-500/20 to-cyan-500/10 blur-3xl rounded-full pointer-events-none" />
<div
className="relative aspect-[9/16] max-w-[320px] mx-auto rounded-2xl overflow-hidden border border-white/10 shadow-2xl shadow-violet-900/40"
style={{ background: 'linear-gradient(135deg,#1e1b4b 0%,#0f172a 60%,#0b0530 100%)' }}
>
<div className="absolute inset-0 flex flex-col items-center justify-center p-6 text-center">
<div className="text-5xl mb-3">🎬</div>
<p className="font-mono text-[10px] tracking-widest text-violet-300/80 uppercase mb-1">
FEATURED SHORT
</p>
<p className="text-sm text-white font-semibold">TOP </p>
<p className="text-[11px] text-slate-400 mt-1">9:16 · 58</p>
</div>
<div className="absolute bottom-3 left-3 right-3 flex gap-1.5">
<span className="text-[10px] px-2 py-0.5 rounded-full bg-black/60 text-white border border-white/10">
Suno V4
</span>
<span className="text-[10px] px-2 py-0.5 rounded-full bg-black/60 text-white border border-white/10">
1
</span>
</div>
</div>
</div>
</div>
</section>
{/* PRICING — 상세 최상단 */}
<section id="pricing" className="px-6 py-14 lg:px-14 bg-slate-950">
<div className="min-h-full bg-black text-white">
{/* PRICING */}
<section id="pricing" className="px-6 py-14 lg:px-14 bg-black">
<div className="max-w-6xl mx-auto">
<div className="flex items-end justify-between flex-wrap gap-3 mb-8">
<div>
<p className="font-mono text-xs text-violet-300/70 tracking-widest uppercase mb-1">Pricing · 1 </p>
<p className="font-mono text-xs text-white/50 tracking-widest uppercase mb-1">Pricing · 1 </p>
<h2 className="text-2xl md:text-3xl font-extrabold">3 , </h2>
</div>
<Link href="/services/music/samples" className="text-sm text-violet-300 hover:text-violet-200 underline underline-offset-4">
<Link href="/services/music/samples" className="text-sm text-white/80 hover:text-white underline underline-offset-4">
</Link>
</div>
@@ -201,52 +101,68 @@ export default function MusicServicePage() {
{(Object.keys(TIERS) as Tier[]).map((key) => {
const t = TIERS[key];
return (
<div
key={key}
className={`relative rounded-2xl p-8 flex flex-col border transition-all ${
t.highlight
? 'border-violet-400 bg-gradient-to-br from-violet-900/40 to-slate-900 shadow-[0_0_60px_rgba(139,92,246,0.35)] md:scale-[1.03] md:-translate-y-2'
: 'border-white/10 bg-white/[0.02] hover:border-white/30'
}`}
>
{t.highlight && (
<div className="absolute -top-3 left-1/2 -translate-x-1/2">
<span className="inline-flex items-center gap-1 bg-gradient-to-r from-violet-500 to-pink-500 text-white text-[10px] font-extrabold px-3 py-1.5 rounded-full uppercase tracking-wider">
🔥
</span>
</div>
)}
<h3 className="font-extrabold text-2xl mb-1">{t.name}</h3>
<p className="text-sm text-slate-400 mb-6">{t.desc}</p>
<div className="mb-6">
<span className="text-4xl font-extrabold font-mono">{t.price}</span>
<span className="text-xs text-slate-500 ml-2">1 </span>
</div>
<ul className="space-y-3 text-sm text-slate-200 mb-8 flex-1">
{t.features.map((f) => (
<li key={f} className="flex gap-2.5">
<svg className="w-4 h-4 text-emerald-400 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg>
<span className="leading-relaxed">{f}</span>
</li>
))}
</ul>
<button
onClick={() => setSelectedTier(key)}
className={`w-full py-4 rounded-xl font-extrabold text-sm transition-colors ${
<CardContainer key={key} containerClassName="w-full py-0" className="w-full h-full">
<CardBody
className={`relative w-full h-full rounded-2xl p-8 flex flex-col border transition-all ${
t.highlight
? 'bg-violet-500 hover:bg-violet-400 text-white'
: 'bg-white/10 hover:bg-white/20 text-white'
? 'border-white bg-white text-black md:scale-[1.03] md:-translate-y-2'
: 'border-white/15 bg-white/[0.02] hover:border-white/40 text-white'
}`}
>
{t.name}
</button>
</div>
{t.highlight && (
<SparklesOverlay
sparklesCount={20}
colors={{ first: '#9E7AFF', second: '#FE8BBB' }}
className="rounded-2xl"
/>
)}
{t.highlight && (
<CardItem translateZ={60} className="absolute -top-3 left-1/2 -translate-x-1/2 z-20">
<span className="inline-flex items-center bg-black text-white text-[10px] font-extrabold px-3 py-1.5 rounded-full uppercase tracking-wider border border-white">
</span>
</CardItem>
)}
<CardItem translateZ={40} as="h3" className="font-extrabold text-2xl mb-1 relative z-10">
{t.name}
</CardItem>
<CardItem translateZ={20} as="p" className={`text-sm mb-6 ${t.highlight ? 'text-black/60' : 'text-white/60'}`}>
{t.desc}
</CardItem>
<CardItem translateZ={50} className="mb-6">
<span className="text-4xl font-extrabold font-mono">{t.price}</span>
<span className={`text-xs ml-2 ${t.highlight ? 'text-black/50' : 'text-white/50'}`}>1 </span>
</CardItem>
<CardItem
translateZ={20}
as="ul"
className={`space-y-3 text-sm mb-8 flex-1 ${t.highlight ? 'text-black/80' : 'text-white/80'}`}
>
{t.features.map((f) => (
<li key={f} className="flex gap-2.5">
<span className="flex-shrink-0 mt-0.5">·</span>
<span className="leading-relaxed">{f}</span>
</li>
))}
</CardItem>
<CardItem
translateZ={40}
as="button"
onClick={() => setSelectedTier(key)}
className={`w-full py-4 rounded-xl font-extrabold text-sm transition-colors ${
t.highlight
? 'bg-black hover:bg-black/85 text-white'
: 'bg-white/10 hover:bg-white/20 text-white border border-white/20'
}`}
>
{t.name}
</CardItem>
</CardBody>
</CardContainer>
);
})}
</div>
<p className="text-xs text-slate-500 text-center mt-8">
<p className="text-xs text-white/50 text-center mt-8">
<Link href="/legal/refund" className="underline hover:text-white"> </Link> .
.
</p>
@@ -254,38 +170,33 @@ export default function MusicServicePage() {
</section>
{/* 팩 구성품 */}
<section className="px-6 py-16 lg:px-14 bg-slate-950 border-t border-white/5">
<section className="px-6 py-16 lg:px-14 bg-black border-t border-white/10">
<div className="max-w-6xl mx-auto">
<p className="font-mono text-xs text-violet-300/70 tracking-widest uppercase mb-2">What's Included</p>
<p className="font-mono text-xs text-white/50 tracking-widest uppercase mb-2">What&apos;s Included</p>
<h2 className="text-2xl md:text-3xl font-extrabold mb-8"> </h2>
<div className="grid md:grid-cols-2 gap-4">
{[
{ icon: '📄', title: 'Suno ', desc: '·· 20+. PDF.' },
{ icon: '🎬', title: 'MV ', desc: 'Midjourney·Runway·Luma로 .' },
{ icon: '', title: ' & ', desc: 'Suno·Runway + .' },
{ icon: '📦', title: ' ', desc: ' ·· . .' },
{ title: 'Suno 프롬프트 북', desc: '장르·무드·보컬 톤 조합법 20+종. 복붙해서 바로 사용하는 PDF.' },
{ title: 'MV 워크플로우', desc: 'Midjourney·Runway·Luma로 비트 싱크 영상 만드는 단계별 가이드.' },
{ title: '저작권 & 상업 이용', desc: 'Suno·Runway 약관 요약 + 수익화 전 안전 체크리스트.' },
{ title: '샘플 프로젝트 파일', desc: '완성된 가사·프롬프트·영상 세트. 그대로 수정해 재사용 가능.' },
].map((item) => (
<div
key={item.title}
className="flex gap-4 p-6 rounded-2xl border border-white/10 bg-white/[0.02]"
className="p-6 rounded-2xl border border-white/15 bg-white/[0.02]"
>
<div className="text-2xl flex-shrink-0">{item.icon}</div>
<div>
<h3 className="font-bold text-white mb-1">{item.title}</h3>
<p className="text-sm text-slate-400 leading-relaxed">{item.desc}</p>
</div>
<h3 className="font-bold text-white mb-1">{item.title}</h3>
<p className="text-sm text-white/60 leading-relaxed">{item.desc}</p>
</div>
))}
</div>
</div>
</section>
{/* PROCESS — 4 STEPS (컴팩트) */}
<section className="px-6 py-16 lg:px-14 bg-gradient-to-b from-slate-950 to-[#0b0530]">
{/* PROCESS */}
<section className="px-6 py-16 lg:px-14 bg-black border-t border-white/10">
<div className="max-w-6xl mx-auto">
<p className="font-mono text-xs text-violet-300/70 tracking-widest uppercase mb-2">
Process
</p>
<p className="font-mono text-xs text-white/50 tracking-widest uppercase mb-2">Process</p>
<h2 className="text-2xl md:text-3xl font-extrabold mb-10" style={{ wordBreak: 'keep-all' }}>
</h2>
@@ -294,18 +205,14 @@ export default function MusicServicePage() {
{PROCESS.map((step) => (
<div
key={step.num}
className="rounded-2xl p-6 border border-white/10 bg-white/[0.02] hover:border-violet-400/40 transition-colors"
className="rounded-2xl p-6 border border-white/15 bg-white/[0.02] hover:border-white/40 transition-colors"
>
<div
className={`inline-flex items-center justify-center w-10 h-10 rounded-lg bg-gradient-to-br ${step.color} font-extrabold text-sm text-white mb-4`}
>
{step.num}
</div>
<p className="font-mono text-[10px] text-violet-300/60 uppercase tracking-widest mb-1">
<p className="font-mono text-xs text-white/50 mb-3">{step.num}</p>
<p className="font-mono text-[10px] text-white/50 uppercase tracking-widest mb-1">
{step.subtitle}
</p>
<h3 className="text-lg font-extrabold text-white mb-2">{step.title}</h3>
<p className="text-sm text-slate-400 leading-relaxed" style={{ wordBreak: 'keep-all' }}>
<p className="text-sm text-white/60 leading-relaxed" style={{ wordBreak: 'keep-all' }}>
{step.result}
</p>
</div>
@@ -314,42 +221,42 @@ export default function MusicServicePage() {
</div>
</section>
{/* SAMPLES — 컴팩트 링크 */}
<section id="samples" className="px-6 py-12 lg:px-14 bg-[#0b0530] border-t border-white/5">
{/* SAMPLES */}
<section id="samples" className="px-6 py-12 lg:px-14 bg-black border-t border-white/10">
<div className="max-w-6xl mx-auto flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
<div>
<p className="font-mono text-xs text-violet-300/70 tracking-widest uppercase mb-1">Samples</p>
<p className="font-mono text-xs text-white/50 tracking-widest uppercase mb-1">Samples</p>
<h2 className="text-xl md:text-2xl font-extrabold"> </h2>
</div>
<Link
href="/services/music/samples"
className="inline-flex items-center gap-2 px-6 py-3 rounded-xl border border-violet-400/40 bg-violet-500/10 hover:bg-violet-500/20 text-sm font-semibold text-violet-200 transition whitespace-nowrap"
className="inline-flex items-center px-6 py-3 rounded-xl border border-white/30 hover:bg-white hover:text-black text-sm font-semibold text-white transition whitespace-nowrap"
>
전체 샘플 갤러리 →
</Link>
</div>
</section>
{/* FAQ */}
<section className="px-6 py-20 lg:px-14 bg-slate-950">
<section className="px-6 py-20 lg:px-14 bg-black border-t border-white/10">
<div className="max-w-3xl mx-auto">
<h2 className="text-2xl md:text-3xl font-extrabold text-center mb-10">
</h2>
<div className="space-y-3">
{FAQS.map((f, i) => (
<div key={i} className="border border-white/10 rounded-2xl overflow-hidden bg-white/[0.02]">
<div key={i} className="border border-white/15 rounded-2xl overflow-hidden bg-white/[0.02]">
<button
onClick={() => setOpenFaq(openFaq === i ? null : i)}
className="w-full flex items-center justify-between px-5 py-4 text-left hover:bg-white/5 transition-colors"
>
<span className="font-bold text-white text-sm">{f.q}</span>
<span className={`text-violet-400 text-xl transition-transform ${openFaq === i ? 'rotate-45' : ''}`}>
<span className={`text-white text-xl transition-transform ${openFaq === i ? 'rotate-45' : ''}`}>
+
</span>
</button>
{openFaq === i && (
<div className="px-5 pb-5 text-sm text-slate-300 leading-relaxed" style={{ wordBreak: 'keep-all' }}>
<div className="px-5 pb-5 text-sm text-white/70 leading-relaxed" style={{ wordBreak: 'keep-all' }}>
{f.a}
</div>
)}
@@ -359,23 +266,23 @@ export default function MusicServicePage() {
</div>
</section>
{/* Sticky 바텀 CTA */}
{/* Sticky CTA */}
<div
className="fixed bottom-0 inset-x-0 z-40 border-t border-white/10 backdrop-blur-md"
style={{ background: 'rgba(6,14,32,0.85)' }}
className="fixed bottom-0 inset-x-0 z-40 border-t border-white/15 backdrop-blur-md"
style={{ background: 'rgba(0,0,0,0.85)' }}
>
<div className="max-w-6xl mx-auto px-5 py-3 flex items-center justify-between gap-4">
<div className="min-w-0">
<p className="text-[11px] font-mono text-violet-300/70 tracking-widest uppercase">From</p>
<p className="text-[11px] font-mono text-white/50 tracking-widest uppercase">From</p>
<p className="text-white font-extrabold text-lg leading-tight">
39,000 <span className="text-xs text-slate-400 font-medium">· 1 </span>
39,000 <span className="text-xs text-white/50 font-medium">· 1 </span>
</p>
</div>
<a
href="#pricing"
className="inline-flex items-center gap-2 bg-violet-500 hover:bg-violet-400 text-white px-6 py-3 rounded-xl font-extrabold text-sm transition-colors shadow-[0_8px_30px_-8px_rgba(139,92,246,0.6)] whitespace-nowrap"
className="inline-flex items-center bg-white hover:bg-white/90 text-black px-6 py-3 rounded-xl font-extrabold text-sm transition-colors whitespace-nowrap"
>
</a>
</div>
</div>