feat(outsourcing): Deep Field 재스킨 + 쇼케이스 풀 그리드 + 운영 실증 카피
- 라이트 → 다크 캔버스 전환 (메인과 동일 비주얼 언어: 다크 루트 div + -mt-16 hero + border-t 섹션 리듬 + 모노 라벨 헤더) - Hero 축약 ~60vh + HeroField 배경 - #showcase 섹션 ShowcaseGrid variant="full"(8슬롯), #portfolio 하위호환 앵커 유지 - 구 SAMPLES(/work/website/samples) 노출 링크 제거 — 쇼케이스가 대체 - 운영 실사례/제공분야/프로세스/FAQ 다크 카드 + ScrollReveal 스태거 - OutsourcingRequestForm 다크 스킨(스타일 값만, 로직 diff 0) + placeholder dark-soft - "7년차"·"대기업" 잔존 카피 전부 운영 실증 톤으로 교체 (metadata 포함) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -16,9 +16,9 @@ const KOR_TIGHT = { letterSpacing: '-0.02em' } as const;
|
|||||||
const KOR_BODY = { letterSpacing: '-0.01em' } as const;
|
const KOR_BODY = { letterSpacing: '-0.01em' } as const;
|
||||||
|
|
||||||
const INPUT_STYLE = {
|
const INPUT_STYLE = {
|
||||||
background: 'var(--jsm-surface)',
|
background: 'var(--jsm-dark-surface)',
|
||||||
border: '1px solid var(--jsm-line)',
|
border: '1px solid var(--jsm-dark-line)',
|
||||||
color: 'var(--jsm-ink)',
|
color: 'var(--jsm-dark-ink)',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const PROJECT_TYPES = [
|
const PROJECT_TYPES = [
|
||||||
@@ -195,13 +195,13 @@ export default function OutsourcingRequestForm() {
|
|||||||
ref={setHeadingRef}
|
ref={setHeadingRef}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className="text-xl font-bold break-keep outline-none"
|
className="text-xl font-bold break-keep outline-none"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
>
|
>
|
||||||
의뢰가 접수되었습니다
|
의뢰가 접수되었습니다
|
||||||
</h3>
|
</h3>
|
||||||
<p
|
<p
|
||||||
className="mt-3 text-sm leading-relaxed break-keep"
|
className="mt-3 text-sm leading-relaxed break-keep"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
영업일 2일 내 회신드립니다.
|
영업일 2일 내 회신드립니다.
|
||||||
</p>
|
</p>
|
||||||
@@ -218,7 +218,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
</Link>
|
</Link>
|
||||||
<p
|
<p
|
||||||
className="mt-3 text-xs leading-relaxed break-keep"
|
className="mt-3 text-xs leading-relaxed break-keep"
|
||||||
style={{ color: 'var(--jsm-ink-faint)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
추적 링크를 이메일로도 보내드렸습니다.
|
추적 링크를 이메일로도 보내드렸습니다.
|
||||||
</p>
|
</p>
|
||||||
@@ -232,7 +232,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
const canAdvance = stepValid(step);
|
const canAdvance = stepValid(step);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="jsm-dark-form">
|
||||||
{/* 진행 표시기 */}
|
{/* 진행 표시기 */}
|
||||||
<ol className="flex items-center gap-2 mb-7" aria-label="진행 단계">
|
<ol className="flex items-center gap-2 mb-7" aria-label="진행 단계">
|
||||||
{STEPS.map((s, i) => {
|
{STEPS.map((s, i) => {
|
||||||
@@ -244,7 +244,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-bold shrink-0 transition-colors"
|
className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-bold shrink-0 transition-colors"
|
||||||
style={
|
style={
|
||||||
state === 'upcoming'
|
state === 'upcoming'
|
||||||
? { background: 'var(--jsm-surface-alt)', color: 'var(--jsm-ink-faint)' }
|
? { background: 'var(--jsm-dark-surface)', color: 'var(--jsm-dark-soft)', boxShadow: 'inset 0 0 0 1px var(--jsm-dark-line)' }
|
||||||
: { background: 'var(--jsm-accent)', color: '#ffffff' }
|
: { background: 'var(--jsm-accent)', color: '#ffffff' }
|
||||||
}
|
}
|
||||||
aria-current={state === 'current' ? 'step' : undefined}
|
aria-current={state === 'current' ? 'step' : undefined}
|
||||||
@@ -255,7 +255,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
className="text-xs font-semibold truncate hidden sm:inline"
|
className="text-xs font-semibold truncate hidden sm:inline"
|
||||||
style={{
|
style={{
|
||||||
color:
|
color:
|
||||||
state === 'upcoming' ? 'var(--jsm-ink-faint)' : 'var(--jsm-ink)',
|
state === 'upcoming' ? 'var(--jsm-dark-soft)' : 'var(--jsm-dark-ink)',
|
||||||
...KOR_BODY,
|
...KOR_BODY,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -264,7 +264,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
{i < STEPS.length - 1 && (
|
{i < STEPS.length - 1 && (
|
||||||
<span
|
<span
|
||||||
className="w-4 sm:w-6 h-px shrink-0"
|
className="w-4 sm:w-6 h-px shrink-0"
|
||||||
style={{ background: 'var(--jsm-line)' }}
|
style={{ background: 'var(--jsm-dark-line)' }}
|
||||||
aria-hidden
|
aria-hidden
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -281,13 +281,13 @@ export default function OutsourcingRequestForm() {
|
|||||||
ref={setHeadingRef}
|
ref={setHeadingRef}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className="text-lg font-bold break-keep outline-none mb-1"
|
className="text-lg font-bold break-keep outline-none mb-1"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
>
|
>
|
||||||
어떤 프로젝트인가요?
|
어떤 프로젝트인가요?
|
||||||
</legend>
|
</legend>
|
||||||
<p
|
<p
|
||||||
className="text-sm leading-relaxed break-keep mb-5"
|
className="text-sm leading-relaxed break-keep mb-5"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
가장 가까운 유형을 하나 선택해주세요.
|
가장 가까운 유형을 하나 선택해주세요.
|
||||||
</p>
|
</p>
|
||||||
@@ -303,12 +303,12 @@ export default function OutsourcingRequestForm() {
|
|||||||
className="px-4 py-3.5 rounded-lg text-sm font-semibold text-center break-keep transition-colors outline-none focus-visible:ring-2 focus-visible:ring-[var(--jsm-accent)]"
|
className="px-4 py-3.5 rounded-lg text-sm font-semibold text-center break-keep transition-colors outline-none focus-visible:ring-2 focus-visible:ring-[var(--jsm-accent)]"
|
||||||
style={{
|
style={{
|
||||||
border: selected
|
border: selected
|
||||||
? '1px solid var(--jsm-accent)'
|
? '1px solid var(--jsm-accent-bright)'
|
||||||
: '1px solid var(--jsm-line)',
|
: '1px solid var(--jsm-dark-line)',
|
||||||
background: selected
|
background: selected
|
||||||
? 'var(--jsm-accent-soft)'
|
? 'rgba(96,165,250,0.12)'
|
||||||
: 'var(--jsm-surface)',
|
: 'var(--jsm-dark-surface)',
|
||||||
color: selected ? 'var(--jsm-accent)' : 'var(--jsm-ink)',
|
color: selected ? 'var(--jsm-accent-bright)' : 'var(--jsm-dark-ink)',
|
||||||
...KOR_BODY,
|
...KOR_BODY,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -327,13 +327,13 @@ export default function OutsourcingRequestForm() {
|
|||||||
ref={setHeadingRef}
|
ref={setHeadingRef}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className="text-lg font-bold break-keep outline-none mb-1"
|
className="text-lg font-bold break-keep outline-none mb-1"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
>
|
>
|
||||||
예산과 일정을 알려주세요
|
예산과 일정을 알려주세요
|
||||||
</h3>
|
</h3>
|
||||||
<p
|
<p
|
||||||
className="text-sm leading-relaxed break-keep mb-5"
|
className="text-sm leading-relaxed break-keep mb-5"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
대략적인 범위면 충분합니다. 정해지지 않았다면 미정을 선택하세요.
|
대략적인 범위면 충분합니다. 정해지지 않았다면 미정을 선택하세요.
|
||||||
</p>
|
</p>
|
||||||
@@ -341,7 +341,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
<fieldset className="mb-6">
|
<fieldset className="mb-6">
|
||||||
<legend
|
<legend
|
||||||
className="text-sm font-semibold mb-2.5"
|
className="text-sm font-semibold mb-2.5"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
예산
|
예산
|
||||||
</legend>
|
</legend>
|
||||||
@@ -360,7 +360,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend
|
<legend
|
||||||
className="text-sm font-semibold mb-2.5"
|
className="text-sm font-semibold mb-2.5"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
희망 일정
|
희망 일정
|
||||||
</legend>
|
</legend>
|
||||||
@@ -385,13 +385,13 @@ export default function OutsourcingRequestForm() {
|
|||||||
ref={setHeadingRef}
|
ref={setHeadingRef}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className="text-lg font-bold break-keep outline-none mb-1"
|
className="text-lg font-bold break-keep outline-none mb-1"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
>
|
>
|
||||||
자세히 들려주세요
|
자세히 들려주세요
|
||||||
</h3>
|
</h3>
|
||||||
<p
|
<p
|
||||||
className="text-sm leading-relaxed break-keep mb-5"
|
className="text-sm leading-relaxed break-keep mb-5"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
구체적일수록 정확한 견적이 가능합니다. 최소 10자 이상 작성해주세요.
|
구체적일수록 정확한 견적이 가능합니다. 최소 10자 이상 작성해주세요.
|
||||||
</p>
|
</p>
|
||||||
@@ -413,7 +413,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
/>
|
/>
|
||||||
<p
|
<p
|
||||||
className="mt-1.5 text-xs"
|
className="mt-1.5 text-xs"
|
||||||
style={{ color: 'var(--jsm-ink-faint)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
{trimmedMessage.length}/10자 이상
|
{trimmedMessage.length}/10자 이상
|
||||||
</p>
|
</p>
|
||||||
@@ -427,13 +427,13 @@ export default function OutsourcingRequestForm() {
|
|||||||
ref={setHeadingRef}
|
ref={setHeadingRef}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className="text-lg font-bold break-keep outline-none mb-1"
|
className="text-lg font-bold break-keep outline-none mb-1"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
>
|
>
|
||||||
어디로 회신드릴까요?
|
어디로 회신드릴까요?
|
||||||
</h3>
|
</h3>
|
||||||
<p
|
<p
|
||||||
className="text-sm leading-relaxed break-keep mb-5"
|
className="text-sm leading-relaxed break-keep mb-5"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
영업일 2일 내에 회신드립니다.
|
영업일 2일 내에 회신드립니다.
|
||||||
</p>
|
</p>
|
||||||
@@ -443,7 +443,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
<label
|
<label
|
||||||
htmlFor="req-name"
|
htmlFor="req-name"
|
||||||
className="block text-sm font-medium mb-1.5"
|
className="block text-sm font-medium mb-1.5"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
이름 <span style={{ color: 'var(--jsm-accent)' }}>*</span>
|
이름 <span style={{ color: 'var(--jsm-accent)' }}>*</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -465,7 +465,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
<label
|
<label
|
||||||
htmlFor="req-email"
|
htmlFor="req-email"
|
||||||
className="block text-sm font-medium mb-1.5"
|
className="block text-sm font-medium mb-1.5"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
이메일 <span style={{ color: 'var(--jsm-accent)' }}>*</span>
|
이메일 <span style={{ color: 'var(--jsm-accent)' }}>*</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -487,7 +487,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
<label
|
<label
|
||||||
htmlFor="req-phone"
|
htmlFor="req-phone"
|
||||||
className="block text-sm font-medium mb-1.5"
|
className="block text-sm font-medium mb-1.5"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
연락처
|
연락처
|
||||||
</label>
|
</label>
|
||||||
@@ -530,10 +530,10 @@ export default function OutsourcingRequestForm() {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={goPrev}
|
onClick={goPrev}
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
className="px-5 py-3 rounded-lg text-sm font-semibold border transition-colors hover:bg-[var(--jsm-surface-alt)] disabled:opacity-50 disabled:cursor-not-allowed"
|
className="px-5 py-3 rounded-lg text-sm font-semibold border transition-colors hover:bg-[var(--jsm-dark-surface)] disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
style={{
|
style={{
|
||||||
...INPUT_STYLE,
|
...INPUT_STYLE,
|
||||||
borderColor: 'var(--jsm-line)',
|
borderColor: 'var(--jsm-dark-line)',
|
||||||
...KOR_BODY,
|
...KOR_BODY,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -548,7 +548,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
className="flex-1 py-3 rounded-lg text-sm font-semibold text-white transition-colors"
|
className="flex-1 py-3 rounded-lg text-sm font-semibold text-white transition-colors"
|
||||||
style={{
|
style={{
|
||||||
background: !canAdvance || submitting
|
background: !canAdvance || submitting
|
||||||
? 'var(--jsm-ink-faint)'
|
? 'var(--jsm-dark-line)'
|
||||||
: 'var(--jsm-accent)',
|
: 'var(--jsm-accent)',
|
||||||
cursor: !canAdvance || submitting ? 'not-allowed' : 'pointer',
|
cursor: !canAdvance || submitting ? 'not-allowed' : 'pointer',
|
||||||
...KOR_BODY,
|
...KOR_BODY,
|
||||||
@@ -563,7 +563,7 @@ export default function OutsourcingRequestForm() {
|
|||||||
disabled={!canAdvance}
|
disabled={!canAdvance}
|
||||||
className="flex-1 inline-flex items-center justify-center gap-2 py-3 rounded-lg text-sm font-semibold text-white transition-colors"
|
className="flex-1 inline-flex items-center justify-center gap-2 py-3 rounded-lg text-sm font-semibold text-white transition-colors"
|
||||||
style={{
|
style={{
|
||||||
background: canAdvance ? 'var(--jsm-accent)' : 'var(--jsm-ink-faint)',
|
background: canAdvance ? 'var(--jsm-accent)' : 'var(--jsm-dark-line)',
|
||||||
cursor: canAdvance ? 'pointer' : 'not-allowed',
|
cursor: canAdvance ? 'pointer' : 'not-allowed',
|
||||||
...KOR_BODY,
|
...KOR_BODY,
|
||||||
}}
|
}}
|
||||||
@@ -595,9 +595,9 @@ function Chip({
|
|||||||
aria-pressed={selected}
|
aria-pressed={selected}
|
||||||
className="px-4 py-2.5 rounded-lg text-sm font-semibold break-keep transition-colors outline-none focus-visible:ring-2 focus-visible:ring-[var(--jsm-accent)]"
|
className="px-4 py-2.5 rounded-lg text-sm font-semibold break-keep transition-colors outline-none focus-visible:ring-2 focus-visible:ring-[var(--jsm-accent)]"
|
||||||
style={{
|
style={{
|
||||||
border: selected ? '1px solid var(--jsm-accent)' : '1px solid var(--jsm-line)',
|
border: selected ? '1px solid var(--jsm-accent-bright)' : '1px solid var(--jsm-dark-line)',
|
||||||
background: selected ? 'var(--jsm-accent-soft)' : 'var(--jsm-surface)',
|
background: selected ? 'rgba(96,165,250,0.12)' : 'var(--jsm-dark-surface)',
|
||||||
color: selected ? 'var(--jsm-accent)' : 'var(--jsm-ink)',
|
color: selected ? 'var(--jsm-accent-bright)' : 'var(--jsm-dark-ink)',
|
||||||
...KOR_BODY,
|
...KOR_BODY,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -198,6 +198,13 @@ body {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 외주 의뢰 폼 — 다크 스킨 placeholder (Deep Field 재스킨) */
|
||||||
|
.jsm-dark-form input::placeholder,
|
||||||
|
.jsm-dark-form textarea::placeholder {
|
||||||
|
color: var(--jsm-dark-soft);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Service card hover */
|
/* Service card hover */
|
||||||
.service-card {
|
.service-card {
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
|||||||
@@ -2,14 +2,20 @@ import Link from 'next/link';
|
|||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import OutsourcingRequestForm from '@/app/components/OutsourcingRequestForm';
|
import OutsourcingRequestForm from '@/app/components/OutsourcingRequestForm';
|
||||||
|
|
||||||
// 외주 개발 의뢰 페이지 (서버 컴포넌트)
|
import HeroField from '@/app/components/deepfield/HeroField';
|
||||||
// PublicShell이 TopNav(h-16)·푸터·main 배경을 제공하므로 여기서는 콘텐츠 섹션만 렌더한다.
|
import ShowcaseGrid from '@/app/components/deepfield/ShowcaseGrid';
|
||||||
// 메인(/)의 토큰·타이포 패턴(KOR_TIGHT/KOR_BODY)·섹션 리듬과 일관되게 구성한다.
|
import ScrollReveal from '@/app/components/deepfield/ScrollReveal';
|
||||||
|
import { SHOWCASE_SLOTS } from '@/lib/showcase';
|
||||||
|
|
||||||
|
// 외주 개발 의뢰 페이지 (서버 컴포넌트) — Deep Field 다크 캔버스.
|
||||||
|
// PublicShell이 TopNav(h-16, /outsourcing 다크 인지)·푸터·main 배경(라이트)을 제공한다.
|
||||||
|
// 이 페이지는 자기 풀-블리드 다크 배경을 소유해 main의 라이트 배경을 덮고,
|
||||||
|
// 메인(/)과 동일한 비주얼 언어(다크 루트 div + -mt-16 hero + 섹션 border-t 리듬 + 모노 라벨 헤더)를 따른다.
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: '외주 개발',
|
title: '외주 개발',
|
||||||
description:
|
description:
|
||||||
'7년차 대기업 백엔드 개발자가 직접 진행하는 맞춤 소프트웨어 외주 개발. 웹 서비스, 업무 자동화, API·백엔드, 봇, AI 연동까지 기획부터 납품·하자보수까지 단독으로 책임집니다.',
|
'24시간 돌아가는 실서비스를 직접 설계·운영하는 손으로, 맞춤 소프트웨어를 만들어 드립니다. 웹 서비스·업무 자동화·API·백엔드·봇·AI 연동까지 기획부터 납품·하자보수까지 단독으로 책임집니다.',
|
||||||
};
|
};
|
||||||
|
|
||||||
const KOR_TIGHT = { letterSpacing: '-0.02em' } as const;
|
const KOR_TIGHT = { letterSpacing: '-0.02em' } as const;
|
||||||
@@ -51,7 +57,7 @@ const PROCESS = [
|
|||||||
{ n: '06', t: '무상 하자보수 30일', d: '납품 후 30일간 결함·수정을 무상으로 대응해 안정화까지 책임집니다.' },
|
{ n: '06', t: '무상 하자보수 30일', d: '납품 후 30일간 결함·수정을 무상으로 대응해 안정화까지 책임집니다.' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// 기존 work/freelance(lib/freelance-portfolio) 실사례를 새 토큰 기준으로 재구성.
|
// 기존 work/freelance(lib/freelance-portfolio) 실사례를 다크 토큰 기준으로 재구성.
|
||||||
const CASES = [
|
const CASES = [
|
||||||
{
|
{
|
||||||
t: '주식 자동매매 시스템',
|
t: '주식 자동매매 시스템',
|
||||||
@@ -97,14 +103,6 @@ const CASES = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// /work/website/samples/* 중 대표 샘플 — 이 라우트는 숨김이 아니라 포트폴리오용으로 잔존.
|
|
||||||
const SAMPLES = [
|
|
||||||
{ slug: 'corporate', t: '기업 홈페이지', sub: '테크솔루션㈜', tag: 'B2B · 신뢰' },
|
|
||||||
{ slug: 'shopping', t: '개인 쇼핑몰', sub: 'MELLOW STUDIO', tag: '쇼핑몰 · 브랜드' },
|
|
||||||
{ slug: 'dashboard', t: '관리자 대시보드', sub: 'DataFlow SaaS', tag: 'SaaS · 자동화' },
|
|
||||||
{ slug: 'portfolio', t: '개인 포트폴리오', sub: 'Kim Jisu', tag: '크리에이터 · 수주' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const FAQ = [
|
const FAQ = [
|
||||||
{
|
{
|
||||||
q: '견적은 어떻게 산정되나요?',
|
q: '견적은 어떻게 산정되나요?',
|
||||||
@@ -145,395 +143,430 @@ function ArrowRight() {
|
|||||||
|
|
||||||
export default function OutsourcingPage() {
|
export default function OutsourcingPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
// 풀-블리드 다크 캔버스 — main의 라이트 배경을 덮는다.
|
||||||
{/* ─── 1. Hero ─── */}
|
<div style={{ background: 'var(--jsm-dark-bg)', color: 'var(--jsm-dark-ink)' }}>
|
||||||
<section className="border-b" style={{ borderColor: 'var(--jsm-line)' }}>
|
{/* ─────────────────── 1. HERO (축약 ~60vh) ─────────────────── */}
|
||||||
<div className="max-w-6xl mx-auto px-6 lg:px-8 py-24 lg:py-32">
|
{/* -mt-16 pt-16: 고정 헤더 아래로 끌어올려 상단 라이트 띠 제거 */}
|
||||||
|
<section className="relative -mt-16 flex min-h-[60vh] items-center overflow-hidden pt-16">
|
||||||
|
<HeroField className="absolute inset-0" />
|
||||||
|
{/* 콘텐츠 가독성용 스크림 (radial 광원 위 텍스트 대비) */}
|
||||||
|
<div
|
||||||
|
aria-hidden
|
||||||
|
className="pointer-events-none absolute inset-0"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
'linear-gradient(to bottom, rgba(7,13,26,0.55) 0%, transparent 30%, transparent 62%, rgba(7,13,26,0.78) 100%)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="relative z-10 mx-auto w-full max-w-6xl px-6 py-20 lg:px-8 lg:py-24">
|
||||||
<div className="max-w-3xl">
|
<div className="max-w-3xl">
|
||||||
<span
|
<span
|
||||||
className="inline-block text-xs font-semibold mb-6 px-2.5 py-1 rounded"
|
className="mb-7 inline-flex items-center gap-2 font-mono text-[11px] uppercase tracking-[0.22em]"
|
||||||
style={{ color: 'var(--jsm-accent)', background: 'var(--jsm-accent-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
>
|
>
|
||||||
외주 개발
|
<span
|
||||||
|
className="inline-block h-1 w-1 rounded-full"
|
||||||
|
style={{ background: 'var(--jsm-accent-bright)' }}
|
||||||
|
/>
|
||||||
|
outsourcing
|
||||||
</span>
|
</span>
|
||||||
<h1
|
<h1
|
||||||
className="text-4xl sm:text-5xl lg:text-[3.5rem] font-bold leading-[1.2] break-keep"
|
className="font-bold break-keep"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{
|
||||||
|
color: 'var(--jsm-dark-ink)',
|
||||||
|
fontSize: 'clamp(2.4rem, 7vw, 5rem)',
|
||||||
|
lineHeight: 1.06,
|
||||||
|
letterSpacing: '-0.04em',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
맞춤 소프트웨어{' '}
|
맞춤 소프트웨어
|
||||||
<span style={{ color: 'var(--jsm-accent)' }}>외주 개발</span>
|
<br />
|
||||||
|
외주 개발
|
||||||
|
<span style={{ color: 'var(--jsm-accent-bright)' }}>.</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p
|
<p
|
||||||
className="mt-7 text-lg lg:text-xl leading-relaxed break-keep max-w-2xl"
|
className="mt-7 max-w-2xl break-keep text-lg leading-relaxed lg:text-xl"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
기획 정리가 안 됐어도 괜찮습니다. 상담에서 함께 정리합니다. 7년차 대기업 백엔드
|
기획 정리가 안 됐어도 괜찮습니다. 상담에서 함께 정리합니다.
|
||||||
개발자가 기획부터 배포·하자보수까지 단독으로 책임집니다.
|
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-10 flex flex-col sm:flex-row gap-3">
|
<div className="mt-10 flex flex-col gap-3 sm:flex-row">
|
||||||
<Link
|
<Link
|
||||||
href="#contact"
|
href="#contact"
|
||||||
className="inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg font-semibold text-white transition-colors duration-150 hover:bg-[var(--jsm-accent-hover)]"
|
className="inline-flex items-center justify-center gap-2 rounded-lg px-6 py-3.5 font-semibold text-white transition-transform duration-200 hover:translate-y-[-1px]"
|
||||||
style={{ background: 'var(--jsm-accent)', ...KOR_BODY }}
|
style={{ background: 'var(--jsm-accent)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
의뢰 내용 보내기
|
의뢰 내용 보내기
|
||||||
<ArrowRight />
|
<ArrowRight />
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href="#portfolio"
|
href="#showcase"
|
||||||
className="inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg font-semibold border transition-colors duration-150 hover:bg-[var(--jsm-surface-alt)]"
|
className="inline-flex items-center justify-center gap-2 rounded-lg border px-6 py-3.5 font-semibold transition-colors duration-200 hover:bg-[var(--jsm-dark-surface)]"
|
||||||
style={{
|
style={{
|
||||||
color: 'var(--jsm-ink)',
|
color: 'var(--jsm-dark-ink)',
|
||||||
borderColor: 'var(--jsm-line)',
|
borderColor: 'var(--jsm-dark-line)',
|
||||||
background: 'var(--jsm-surface)',
|
|
||||||
...KOR_BODY,
|
...KOR_BODY,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
포트폴리오 보기
|
작업 화면 보기
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ─── 2. 제공 분야 ─── */}
|
{/* ─────────────────── 2. SHOWCASE (풀 그리드) ─────────────────── */}
|
||||||
<section style={{ background: 'var(--jsm-surface-alt)' }}>
|
<section id="showcase" className="scroll-mt-20 border-t" style={{ borderColor: 'var(--jsm-dark-line)' }}>
|
||||||
<div className="max-w-6xl mx-auto px-6 lg:px-8 py-20 lg:py-28">
|
{/* 하위 호환: 기존 /outsourcing#portfolio 링크(메인 footer 등)용 앵커 유지 */}
|
||||||
<div className="max-w-2xl">
|
<div id="portfolio" className="scroll-mt-20" />
|
||||||
|
<div className="mx-auto max-w-6xl px-6 py-24 lg:px-8 lg:py-32">
|
||||||
|
<ScrollReveal>
|
||||||
<p
|
<p
|
||||||
className="text-xs font-semibold uppercase tracking-wider mb-3"
|
className="mb-3 font-mono text-[11px] uppercase tracking-[0.22em]"
|
||||||
style={{ color: 'var(--jsm-accent)' }}
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
>
|
>
|
||||||
Scope
|
showcase
|
||||||
</p>
|
</p>
|
||||||
<h2
|
<h2
|
||||||
className="text-3xl lg:text-4xl font-bold break-keep"
|
className="max-w-2xl break-keep text-3xl font-bold lg:text-[2.75rem] lg:leading-[1.12]"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', letterSpacing: '-0.03em' }}
|
||||||
>
|
>
|
||||||
이런 것들을 만들어 드립니다
|
우리가 만드는 화면들
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</ScrollReveal>
|
||||||
<div className="mt-12 grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
||||||
{FIELDS.map((f) => (
|
<div className="mt-14">
|
||||||
<div
|
<ShowcaseGrid slots={SHOWCASE_SLOTS} variant="full" />
|
||||||
key={f.t}
|
|
||||||
className="rounded-2xl p-7 border"
|
|
||||||
style={{ background: 'var(--jsm-surface)', borderColor: 'var(--jsm-line)' }}
|
|
||||||
>
|
|
||||||
<h3
|
|
||||||
className="text-lg font-bold break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
|
||||||
>
|
|
||||||
{f.t}
|
|
||||||
</h3>
|
|
||||||
<p
|
|
||||||
className="mt-2.5 text-sm leading-relaxed break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
|
||||||
>
|
|
||||||
{f.d}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ─── 3. 진행 프로세스 ─── */}
|
{/* ─────────────────── 3. 운영 실사례 ─────────────────── */}
|
||||||
<section id="process" className="scroll-mt-20" style={{ background: 'var(--jsm-bg)' }}>
|
<section className="border-t" style={{ borderColor: 'var(--jsm-dark-line)' }}>
|
||||||
<div className="max-w-6xl mx-auto px-6 lg:px-8 py-20 lg:py-28">
|
<div className="mx-auto max-w-6xl px-6 py-24 lg:px-8 lg:py-32">
|
||||||
<div className="max-w-2xl">
|
<ScrollReveal>
|
||||||
<p
|
<p
|
||||||
className="text-xs font-semibold uppercase tracking-wider mb-3"
|
className="mb-3 font-mono text-[11px] uppercase tracking-[0.22em]"
|
||||||
style={{ color: 'var(--jsm-accent)' }}
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
>
|
>
|
||||||
Process
|
in production
|
||||||
</p>
|
</p>
|
||||||
<h2
|
<h2
|
||||||
className="text-3xl lg:text-4xl font-bold break-keep"
|
className="max-w-2xl break-keep text-3xl font-bold lg:text-[2.75rem] lg:leading-[1.12]"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', letterSpacing: '-0.03em' }}
|
||||||
>
|
|
||||||
상담부터 하자보수까지, 흐름이 분명합니다
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="mt-12 grid sm:grid-cols-2 lg:grid-cols-3 gap-px rounded-2xl overflow-hidden border"
|
|
||||||
style={{ borderColor: 'var(--jsm-line)', background: 'var(--jsm-line)' }}
|
|
||||||
>
|
|
||||||
{PROCESS.map((s) => (
|
|
||||||
<div key={s.n} className="p-7 lg:p-8" style={{ background: 'var(--jsm-surface)' }}>
|
|
||||||
<span
|
|
||||||
className="text-sm font-bold"
|
|
||||||
style={{ color: 'var(--jsm-accent)', fontFamily: 'monospace' }}
|
|
||||||
>
|
|
||||||
{s.n}
|
|
||||||
</span>
|
|
||||||
<h3
|
|
||||||
className="mt-4 text-lg font-bold break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
|
||||||
>
|
|
||||||
{s.t}
|
|
||||||
</h3>
|
|
||||||
<p
|
|
||||||
className="mt-2 text-sm leading-relaxed break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
|
||||||
>
|
|
||||||
{s.d}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* ─── 4. 포트폴리오 ─── */}
|
|
||||||
<section id="portfolio" className="scroll-mt-20" style={{ background: 'var(--jsm-surface-alt)' }}>
|
|
||||||
<div className="max-w-6xl mx-auto px-6 lg:px-8 py-20 lg:py-28">
|
|
||||||
<div className="max-w-2xl">
|
|
||||||
<p
|
|
||||||
className="text-xs font-semibold uppercase tracking-wider mb-3"
|
|
||||||
style={{ color: 'var(--jsm-accent)' }}
|
|
||||||
>
|
|
||||||
Portfolio
|
|
||||||
</p>
|
|
||||||
<h2
|
|
||||||
className="text-3xl lg:text-4xl font-bold break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
|
||||||
>
|
>
|
||||||
직접 개발하고, 실제로 굴러가는 결과물
|
직접 개발하고, 실제로 굴러가는 결과물
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p
|
||||||
className="mt-4 leading-relaxed break-keep"
|
className="mt-4 max-w-xl break-keep leading-relaxed"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
운영 중인 서비스와 납품 완료 프로젝트입니다. 의뢰하신 프로젝트도 같은 깊이로 만듭니다.
|
운영 중인 서비스와 납품 완료 프로젝트입니다. 의뢰하신 프로젝트도 같은 깊이로 만듭니다.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</ScrollReveal>
|
||||||
|
|
||||||
{/* 실사례 카드 */}
|
<div className="mt-14 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
<div className="mt-12 grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
{CASES.map((c, i) => (
|
||||||
{CASES.map((c) => (
|
<ScrollReveal key={c.t} delay={i * 80}>
|
||||||
<div
|
<div
|
||||||
key={c.t}
|
className="flex h-full flex-col rounded-2xl border p-7"
|
||||||
className="flex flex-col rounded-2xl p-7 border"
|
style={{
|
||||||
style={{ background: 'var(--jsm-surface)', borderColor: 'var(--jsm-line)' }}
|
background: 'var(--jsm-dark-surface)',
|
||||||
>
|
borderColor: 'var(--jsm-dark-line)',
|
||||||
<span
|
}}
|
||||||
className="self-start inline-flex items-center gap-1.5 text-[11px] font-semibold px-2.5 py-1 rounded-full mb-5"
|
|
||||||
style={
|
|
||||||
c.live
|
|
||||||
? { color: 'var(--jsm-accent)', background: 'var(--jsm-accent-soft)' }
|
|
||||||
: { color: 'var(--jsm-ink-soft)', background: 'var(--jsm-surface-alt)' }
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{c.live && (
|
|
||||||
<span
|
|
||||||
className="w-1.5 h-1.5 rounded-full"
|
|
||||||
style={{ background: 'var(--jsm-accent)' }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{c.cat}
|
|
||||||
</span>
|
|
||||||
<h3
|
|
||||||
className="text-lg font-bold break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
|
||||||
>
|
|
||||||
{c.t}
|
|
||||||
</h3>
|
|
||||||
<p
|
|
||||||
className="mt-2.5 text-sm leading-relaxed break-keep flex-1"
|
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
|
||||||
>
|
|
||||||
{c.d}
|
|
||||||
</p>
|
|
||||||
<div className="mt-5 flex flex-wrap gap-1.5">
|
|
||||||
{c.tags.map((tag) => (
|
|
||||||
<span
|
|
||||||
key={tag}
|
|
||||||
className="text-xs px-2.5 py-1 rounded"
|
|
||||||
style={{
|
|
||||||
color: 'var(--jsm-ink-soft)',
|
|
||||||
background: 'var(--jsm-surface-alt)',
|
|
||||||
...KOR_BODY,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 웹사이트 샘플 링크 */}
|
|
||||||
<div className="mt-14">
|
|
||||||
<h3
|
|
||||||
className="text-lg font-bold break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
|
||||||
>
|
|
||||||
웹사이트 제작 샘플
|
|
||||||
</h3>
|
|
||||||
<p
|
|
||||||
className="mt-2 text-sm leading-relaxed break-keep"
|
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
|
||||||
>
|
|
||||||
직접 둘러볼 수 있는 데모 사이트입니다. 카드를 눌러 화면을 확인하세요.
|
|
||||||
</p>
|
|
||||||
<div className="mt-6 grid sm:grid-cols-2 lg:grid-cols-4 gap-5">
|
|
||||||
{SAMPLES.map((s) => (
|
|
||||||
<Link
|
|
||||||
key={s.slug}
|
|
||||||
href={`/work/website/samples/${s.slug}`}
|
|
||||||
className="group flex flex-col rounded-2xl p-6 border transition-colors duration-200 hover:border-[var(--jsm-accent)]"
|
|
||||||
style={{ background: 'var(--jsm-surface)', borderColor: 'var(--jsm-line)' }}
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="text-[11px] font-semibold uppercase tracking-wider"
|
className="mb-5 inline-flex items-center gap-1.5 self-start rounded-full px-2.5 py-1 text-[11px] font-semibold"
|
||||||
style={{ color: 'var(--jsm-accent)' }}
|
style={
|
||||||
|
c.live
|
||||||
|
? { color: 'var(--jsm-accent-bright)', background: 'rgba(96,165,250,0.12)' }
|
||||||
|
: { color: 'var(--jsm-dark-soft)', background: 'rgba(148,163,184,0.08)' }
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{s.tag}
|
{c.live && (
|
||||||
|
<span
|
||||||
|
className="h-1.5 w-1.5 rounded-full"
|
||||||
|
style={{ background: 'var(--jsm-accent-bright)' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{c.cat}
|
||||||
</span>
|
</span>
|
||||||
<h4
|
<h3
|
||||||
className="mt-3 text-base font-bold break-keep"
|
className="break-keep text-lg font-bold"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
>
|
>
|
||||||
{s.t}
|
{c.t}
|
||||||
</h4>
|
</h3>
|
||||||
<p
|
<p
|
||||||
className="mt-1 text-sm break-keep"
|
className="mt-2.5 flex-1 break-keep text-sm leading-relaxed"
|
||||||
style={{ color: 'var(--jsm-ink-faint)', ...KOR_BODY }}
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
>
|
>
|
||||||
{s.sub}
|
{c.d}
|
||||||
</p>
|
</p>
|
||||||
<span
|
<div className="mt-5 flex flex-wrap gap-1.5">
|
||||||
className="mt-5 inline-flex items-center gap-1.5 text-sm font-semibold transition-colors duration-150 group-hover:text-[var(--jsm-accent-hover)]"
|
{c.tags.map((tag) => (
|
||||||
style={{ color: 'var(--jsm-accent)', ...KOR_BODY }}
|
<span
|
||||||
>
|
key={tag}
|
||||||
데모 보기
|
className="rounded px-2.5 py-1 text-xs"
|
||||||
<ArrowRight />
|
style={{
|
||||||
</span>
|
color: 'var(--jsm-dark-soft)',
|
||||||
</Link>
|
background: 'rgba(148,163,184,0.08)',
|
||||||
))}
|
...KOR_BODY,
|
||||||
</div>
|
}}
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ─── 5. FAQ ─── */}
|
{/* ─────────────────── 4a. 제공 분야 ─────────────────── */}
|
||||||
<section style={{ background: 'var(--jsm-bg)' }}>
|
<section className="border-t" style={{ borderColor: 'var(--jsm-dark-line)' }}>
|
||||||
<div className="max-w-3xl mx-auto px-6 lg:px-8 py-20 lg:py-28">
|
<div className="mx-auto max-w-6xl px-6 py-24 lg:px-8 lg:py-32">
|
||||||
<div className="mb-12">
|
<ScrollReveal>
|
||||||
<p
|
<p
|
||||||
className="text-xs font-semibold uppercase tracking-wider mb-3"
|
className="mb-3 font-mono text-[11px] uppercase tracking-[0.22em]"
|
||||||
style={{ color: 'var(--jsm-accent)' }}
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
>
|
>
|
||||||
FAQ
|
scope
|
||||||
</p>
|
</p>
|
||||||
<h2
|
<h2
|
||||||
className="text-3xl lg:text-4xl font-bold break-keep"
|
className="max-w-2xl break-keep text-3xl font-bold lg:text-[2.75rem] lg:leading-[1.12]"
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
style={{ color: 'var(--jsm-dark-ink)', letterSpacing: '-0.03em' }}
|
||||||
|
>
|
||||||
|
이런 것들을 만들어 드립니다
|
||||||
|
</h2>
|
||||||
|
</ScrollReveal>
|
||||||
|
|
||||||
|
<div className="mt-14 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{FIELDS.map((f, i) => (
|
||||||
|
<ScrollReveal key={f.t} delay={i * 80}>
|
||||||
|
<div
|
||||||
|
className="h-full rounded-2xl border p-7"
|
||||||
|
style={{
|
||||||
|
background: 'var(--jsm-dark-surface)',
|
||||||
|
borderColor: 'var(--jsm-dark-line)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
className="break-keep text-lg font-bold"
|
||||||
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
|
>
|
||||||
|
{f.t}
|
||||||
|
</h3>
|
||||||
|
<p
|
||||||
|
className="mt-2.5 break-keep text-sm leading-relaxed"
|
||||||
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
|
>
|
||||||
|
{f.d}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ─────────────────── 4b. 진행 프로세스 ─────────────────── */}
|
||||||
|
<section id="process" className="scroll-mt-20 border-t" style={{ borderColor: 'var(--jsm-dark-line)' }}>
|
||||||
|
<div className="mx-auto max-w-6xl px-6 py-24 lg:px-8 lg:py-32">
|
||||||
|
<ScrollReveal>
|
||||||
|
<p
|
||||||
|
className="mb-3 font-mono text-[11px] uppercase tracking-[0.22em]"
|
||||||
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
|
>
|
||||||
|
process
|
||||||
|
</p>
|
||||||
|
<h2
|
||||||
|
className="max-w-2xl break-keep text-3xl font-bold lg:text-[2.75rem] lg:leading-[1.12]"
|
||||||
|
style={{ color: 'var(--jsm-dark-ink)', letterSpacing: '-0.03em' }}
|
||||||
|
>
|
||||||
|
상담부터 하자보수까지, 흐름이 분명합니다
|
||||||
|
</h2>
|
||||||
|
</ScrollReveal>
|
||||||
|
|
||||||
|
<div className="mt-14 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{PROCESS.map((s, i) => (
|
||||||
|
<ScrollReveal key={s.n} delay={i * 80}>
|
||||||
|
<div
|
||||||
|
className="relative h-full rounded-2xl border p-7 lg:p-8"
|
||||||
|
style={{
|
||||||
|
background: 'var(--jsm-dark-surface)',
|
||||||
|
borderColor: 'var(--jsm-dark-line)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="relative z-10 inline-flex h-12 w-12 items-center justify-center rounded-full font-mono text-sm font-bold"
|
||||||
|
style={{
|
||||||
|
color: 'var(--jsm-accent-bright)',
|
||||||
|
background: 'var(--jsm-dark-bg)',
|
||||||
|
boxShadow: 'inset 0 0 0 1px var(--jsm-dark-line)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{s.n}
|
||||||
|
</span>
|
||||||
|
<h3
|
||||||
|
className="mt-5 break-keep text-lg font-bold"
|
||||||
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
|
>
|
||||||
|
{s.t}
|
||||||
|
</h3>
|
||||||
|
<p
|
||||||
|
className="mt-2 break-keep text-sm leading-relaxed"
|
||||||
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
|
>
|
||||||
|
{s.d}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ─────────────────── 5. FAQ ─────────────────── */}
|
||||||
|
<section className="border-t" style={{ borderColor: 'var(--jsm-dark-line)' }}>
|
||||||
|
<div className="mx-auto max-w-3xl px-6 py-24 lg:px-8 lg:py-32">
|
||||||
|
<ScrollReveal>
|
||||||
|
<p
|
||||||
|
className="mb-3 font-mono text-[11px] uppercase tracking-[0.22em]"
|
||||||
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
|
>
|
||||||
|
faq
|
||||||
|
</p>
|
||||||
|
<h2
|
||||||
|
className="break-keep text-3xl font-bold lg:text-[2.75rem] lg:leading-[1.12]"
|
||||||
|
style={{ color: 'var(--jsm-dark-ink)', letterSpacing: '-0.03em' }}
|
||||||
>
|
>
|
||||||
자주 묻는 질문
|
자주 묻는 질문
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</ScrollReveal>
|
||||||
<div className="space-y-3">
|
|
||||||
{FAQ.map((item) => (
|
<div className="mt-14 space-y-3">
|
||||||
<details
|
{FAQ.map((item, i) => (
|
||||||
key={item.q}
|
<ScrollReveal key={item.q} delay={i * 80}>
|
||||||
className="group rounded-2xl border overflow-hidden"
|
<details
|
||||||
style={{ background: 'var(--jsm-surface)', borderColor: 'var(--jsm-line)' }}
|
className="group overflow-hidden rounded-2xl border"
|
||||||
>
|
style={{
|
||||||
<summary
|
background: 'var(--jsm-dark-surface)',
|
||||||
className="flex items-center justify-between gap-4 cursor-pointer list-none px-6 py-5 font-semibold break-keep"
|
borderColor: 'var(--jsm-dark-line)',
|
||||||
style={{ color: 'var(--jsm-ink)', ...KOR_TIGHT }}
|
}}
|
||||||
>
|
>
|
||||||
{item.q}
|
<summary
|
||||||
<svg
|
className="flex cursor-pointer list-none items-center justify-between gap-4 break-keep px-6 py-5 font-semibold"
|
||||||
className="shrink-0 transition-transform duration-200 group-open:rotate-45"
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
width="18"
|
|
||||||
height="18"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
aria-hidden
|
|
||||||
style={{ color: 'var(--jsm-ink-faint)' }}
|
|
||||||
>
|
>
|
||||||
<path d="M12 5v14M5 12h14" />
|
{item.q}
|
||||||
</svg>
|
<svg
|
||||||
</summary>
|
className="shrink-0 transition-transform duration-200 group-open:rotate-45"
|
||||||
<p
|
width="18"
|
||||||
className="px-6 pb-5 text-sm leading-relaxed break-keep"
|
height="18"
|
||||||
style={{ color: 'var(--jsm-ink-soft)', ...KOR_BODY }}
|
viewBox="0 0 24 24"
|
||||||
>
|
fill="none"
|
||||||
{item.a}
|
stroke="currentColor"
|
||||||
</p>
|
strokeWidth="2"
|
||||||
</details>
|
strokeLinecap="round"
|
||||||
|
aria-hidden
|
||||||
|
style={{ color: 'var(--jsm-dark-soft)' }}
|
||||||
|
>
|
||||||
|
<path d="M12 5v14M5 12h14" />
|
||||||
|
</svg>
|
||||||
|
</summary>
|
||||||
|
<p
|
||||||
|
className="break-keep px-6 pb-5 text-sm leading-relaxed"
|
||||||
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
|
>
|
||||||
|
{item.a}
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ─── 6. 의뢰 폼 ─── */}
|
{/* ─────────────────── 6. 의뢰 폼 ─────────────────── */}
|
||||||
<section id="contact" className="scroll-mt-20" style={{ background: 'var(--jsm-navy)' }}>
|
<section id="contact" className="scroll-mt-20 border-t" style={{ borderColor: 'var(--jsm-dark-line)' }}>
|
||||||
<div className="max-w-6xl mx-auto px-6 lg:px-8 py-20 lg:py-28">
|
<div className="mx-auto max-w-6xl px-6 py-24 lg:px-8 lg:py-32">
|
||||||
<div className="grid lg:grid-cols-5 gap-10 lg:gap-12">
|
<div className="grid gap-10 lg:grid-cols-5 lg:gap-12">
|
||||||
{/* 안내 */}
|
{/* 안내 */}
|
||||||
<div className="lg:col-span-2">
|
<div className="lg:col-span-2">
|
||||||
<p
|
<ScrollReveal>
|
||||||
className="text-xs font-semibold uppercase tracking-wider mb-3"
|
<p
|
||||||
style={{ color: '#7aa7ff' }}
|
className="mb-3 font-mono text-[11px] uppercase tracking-[0.22em]"
|
||||||
>
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
Contact
|
|
||||||
</p>
|
|
||||||
<h2
|
|
||||||
className="text-3xl lg:text-[2.5rem] font-bold leading-tight text-white break-keep"
|
|
||||||
style={KOR_TIGHT}
|
|
||||||
>
|
|
||||||
프로젝트 문의
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
className="mt-5 text-lg leading-relaxed text-white/70 break-keep"
|
|
||||||
style={KOR_BODY}
|
|
||||||
>
|
|
||||||
영업일 2일 내에 회신드립니다. 아이디어 단계여도 괜찮습니다 — 상담에서 방향을
|
|
||||||
함께 잡아드립니다.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
className="mt-8 pt-8 border-t space-y-3"
|
|
||||||
style={{ borderColor: 'rgba(255,255,255,0.12)' }}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="mailto:bgg8988@gmail.com"
|
|
||||||
className="flex items-center gap-3 text-sm text-white/80 hover:text-white transition-colors"
|
|
||||||
style={KOR_BODY}
|
|
||||||
>
|
>
|
||||||
<span className="text-white/40 text-xs uppercase tracking-wider w-12">Mail</span>
|
contact
|
||||||
bgg8988@gmail.com
|
</p>
|
||||||
</a>
|
<h2
|
||||||
<a
|
className="break-keep text-3xl font-bold leading-tight lg:text-[2.5rem]"
|
||||||
href="tel:010-3907-1392"
|
style={{ color: 'var(--jsm-dark-ink)', ...KOR_TIGHT }}
|
||||||
className="flex items-center gap-3 text-sm text-white/80 hover:text-white transition-colors"
|
|
||||||
style={KOR_BODY}
|
|
||||||
>
|
>
|
||||||
<span className="text-white/40 text-xs uppercase tracking-wider w-12">Tel</span>
|
프로젝트 문의
|
||||||
010-3907-1392
|
</h2>
|
||||||
</a>
|
<p
|
||||||
</div>
|
className="mt-5 break-keep text-lg leading-relaxed"
|
||||||
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
|
>
|
||||||
|
영업일 2일 내에 회신드립니다. 아이디어 단계여도 괜찮습니다 — 상담에서 방향을
|
||||||
|
함께 잡아드립니다.
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
className="mt-8 space-y-3 border-t pt-8"
|
||||||
|
style={{ borderColor: 'var(--jsm-dark-line)' }}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="mailto:bgg8988@gmail.com"
|
||||||
|
className="flex items-center gap-3 text-sm transition-colors hover:text-[var(--jsm-dark-ink)]"
|
||||||
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="w-12 font-mono text-xs uppercase tracking-wider"
|
||||||
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
|
>
|
||||||
|
Mail
|
||||||
|
</span>
|
||||||
|
bgg8988@gmail.com
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="tel:010-3907-1392"
|
||||||
|
className="flex items-center gap-3 text-sm transition-colors hover:text-[var(--jsm-dark-ink)]"
|
||||||
|
style={{ color: 'var(--jsm-dark-soft)', ...KOR_BODY }}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="w-12 font-mono text-xs uppercase tracking-wider"
|
||||||
|
style={{ color: 'var(--jsm-accent-bright)' }}
|
||||||
|
>
|
||||||
|
Tel
|
||||||
|
</span>
|
||||||
|
010-3907-1392
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 폼 */}
|
{/* 폼 */}
|
||||||
<div className="lg:col-span-3">
|
<div className="lg:col-span-3">
|
||||||
<div
|
<ScrollReveal delay={100}>
|
||||||
className="rounded-2xl p-6 lg:p-8"
|
<div
|
||||||
style={{ background: 'var(--jsm-surface)' }}
|
className="rounded-2xl border p-6 lg:p-8"
|
||||||
>
|
style={{
|
||||||
<OutsourcingRequestForm />
|
background: 'var(--jsm-dark-surface)',
|
||||||
</div>
|
borderColor: 'var(--jsm-dark-line)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<OutsourcingRequestForm />
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user